<commit_before>import React from 'react'
import request from 'superagent'
import Radium from 'radium'
import { Tooltip } from 'reactstrap'

import Styles from './Styles'
import Strings from './Strings'
import ResultList from './ResultList'
import DropButton from './DropButton'
import Card from './Card'
import DropDown from './DropDown'

@Radium
export default class ClassifierDetail extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            tooltipOpen: false,
            error: this.props.failError
        }
    }

    classify = (req, uploadedImage, onProgress, onFinished) => {
        var self = this
        if (uploadedImage) {
            req.attach('file', uploadedImage)
        }

        req.query({api_key: localStorage.getItem('api_key')})

        req.on('progress', function(e) {
            if (e.direction == 'upload') {
                onProgress(e.percent / 2)
            } else if (e.direction == 'download') {
                if (e.percent < 100) {
                    onProgress(50 + e.percent / 2)
                }
            }
        })

        req.end(function(err, res) {
            onProgress(100)
            console.log(res)
            var results
            if (res.body != null && res.body.images != null) {
                if (res.body.images[0].classifiers != null && res.body.images[0].classifiers.length > 0 ) {
                    results = res.body.images[0].classifiers[0].classes
                    results.sort(function(a, b) {
                        return b.score - a.score
                    })
                } else if (res.body.images[0].faces != null && res.body.images[0].faces.length > 0) {
                    results = res.body.images[0].faces
                } else if (res.body.images[0].faces != null) {
                    self.setState({ error: Strings.faces_error }, self.stateChanged)
                } else if (res.body.images[0].error != null) {
                    console.error(res.body.images[0].error.description)
                    if (res.body.images[0].error.description == 'Image size limit exceeded (2935034 bytes > 2097152 bytes [2 MiB]).') {
                        self.setState({ error: Strings.mb2_error }, self.stateChanged)
                    } else {
                        self.setState({ error: res.body.images[0].error.description }, self.stateChanged)
                    }
                }
            } else if (res.body.error != null) {
                var error = res.body.error
                self.setState({ error: error }, self.stateChanged)
            } else {
                var error = Strings.unknown_error
                self.setState({ error: error }, self.stateChanged)
            }
            self.setState({ file: uploadedImage, results: results, link: null }, self.stateChanged)
            onFinished()
        })
    }

    toggle = () => {
        this.setState({
            tooltipOpen: !this.state.tooltipOpen
        })
    }

    stateChanged = () => {
        this.setState({
            tooltipOpen: false
        })
        this.props.reDraw()
    }

    deleteClassifier = (e) => {
        e.preventDefault()
        if (confirm('Delete ' + this.props.name + '?') == true) {
            var req = request.del('/api/classifiers/' + this.props.classifierID)
            amplitude.getInstance().logEvent('Delete-classifier')
            var self = this
            req.query({api_key: localStorage.getItem('api_key')})
            req.end(function(err, res) {
                console.log('deleted')
                if (res.body.error != null) {
                    alert(res.body.error)
                }
                self.props.reData()
            })
        }
    }

    getName = () => {
      if (this.props.name == 'default') {
        return Strings.classifier_general
      } else if (this.props.name == 'food') {
        return Strings.classifier_food
      } else {
        return this.props.name
      }
    }

    resizeImage = (image, uploadedImage) => {
        var c = window.document.createElement('canvas')
        var ctx = c.getContext('2d')
        var ratio = image.width / image.height
        var maxSize = 1000

        if (image.width < maxSize && image.height < maxSize) {
           c.width = image.width
           c.height = image.height
        } else {
           c.width = (ratio > 1 ? maxSize : maxSize * ratio)
           c.height = (ratio > 1 ? maxSize / ratio : maxSize)
        }

        ctx.drawImage(image, 0, 0, c.width, c.height)
        return c.toDataURL('image/jpeg')
    }

    convertDataURLtoFile = (imageDataURL, fileName) => {
        var imageType = imageDataURL.substring(imageDataURL.indexOf(':') + 1, imageDataURL.indexOf(';'))
        var imageDataBase64 = imageDataURL.substring(imageDataURL.indexOf(',') + 1, imageDataURL.length)
        var byteCharacters = atob(imageDataBase64)
        var byteNumbers = new Array(byteCharacters.length)
        for (var i = 0; i < byteCharacters.length; i++) {
            byteNumbers[i] = byteCharacters.charCodeAt(i)
        }
        var byteArray = new Uint8Array(byteNumbers)
        var blob = new Blob([byteArray], {type: imageType})

        return new File([blob], fileName, {type: imageType, lastModified: Date.now()})
    }

    onDrop = (files, rejects, onFinished, onProgress) => {
        var self = this
        var req

        self.clearClassifier()
        self.setState({ error: null }, self.stateChanged)

        if (files == null || files.length <= 0) {
            self.setState({ error: Strings.invalid_image_error }, self.stateChanged)
            return
        }

        if (this.props.classifierID == null && this.props.name == Strings.classifier_face) {
            req = request.post('/api/faces')
        } else {
            req = request.post('/api/classify')
            req.query({classifier_ids: [this.props.classifierID || this.props.name.toLowerCase()]})
            req.query({threshold: 0.0})
        }

        if (this.props.classifierID == null) {
            amplitude.getInstance().logEvent('Classify-' + this.props.name.toLowerCase())
        } else {
            amplitude.getInstance().logEvent('Classify-custom')
        }

        var uploadedImage = files[0]

        // resize uploaded image if greater than 2MB
        if (files[0].size > 2000000) {
            var name = files[0].name
            var reader = new FileReader()
            reader.onload = () => {
                var image = new Image()
                image.src = reader.result
                image.onload = () => {
                    uploadedImage = this.convertDataURLtoFile(this.resizeImage(image), name)
                    this.classify(req, uploadedImage, onProgress, onFinished)
                }
            }
            reader.readAsDataURL(files[0])

        } else {
            this.classify(req, uploadedImage, onProgress, onFinished)
        }
    }

    onLink = (link, onFinished, onProgress) => {
        var self = this
        var req

        self.setState({ error: null }, self.stateChanged)
<commit_msg>need to re-add preview for resized images<commit_after>import React from 'react'
import request from 'superagent'
import Radium from 'radium'
import { Tooltip } from 'reactstrap'

import Styles from './Styles'
import Strings from './Strings'
import ResultList from './ResultList'
import DropButton from './DropButton'
import Card from './Card'
import DropDown from './DropDown'

@Radium
export default class ClassifierDetail extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            tooltipOpen: false,
            error: this.props.failError
        }
    }

    classify = (req, uploadedImage, onProgress, onFinished) => {
        var self = this
        if (uploadedImage) {
            req.attach('file', uploadedImage)
        }

        req.query({api_key: localStorage.getItem('api_key')})

        req.on('progress', function(e) {
            if (e.direction == 'upload') {
                onProgress(e.percent / 2)
            } else if (e.direction == 'download') {
                if (e.percent < 100) {
                    onProgress(50 + e.percent / 2)
                }
            }
        })

        req.end(function(err, res) {
            onProgress(100)
            console.log(res)
            var results
            if (res.body != null && res.body.images != null) {
                if (res.body.images[0].classifiers != null && res.body.images[0].classifiers.length > 0 ) {
                    results = res.body.images[0].classifiers[0].classes
                    results.sort(function(a, b) {
                        return b.score - a.score
                    })
                } else if (res.body.images[0].faces != null && res.body.images[0].faces.length > 0) {
                    results = res.body.images[0].faces
                } else if (res.body.images[0].faces != null) {
                    self.setState({ error: Strings.faces_error }, self.stateChanged)
                } else if (res.body.images[0].error != null) {
                    console.error(res.body.images[0].error.description)
                    if (res.body.images[0].error.description == 'Image size limit exceeded (2935034 bytes > 2097152 bytes [2 MiB]).') {
                        self.setState({ error: Strings.mb2_error }, self.stateChanged)
                    } else {
                        self.setState({ error: res.body.images[0].error.description }, self.stateChanged)
                    }
                }
            } else if (res.body.error != null) {
                var error = res.body.error
                self.setState({ error: error }, self.stateChanged)
            } else {
                var error = Strings.unknown_error
                self.setState({ error: error }, self.stateChanged)
            }
            self.setState({ file: uploadedImage, results: results, link: null }, self.stateChanged)
            onFinished()
        })
    }

    toggle = () => {
        this.setState({
            tooltipOpen: !this.state.tooltipOpen
        })
    }

    stateChanged = () => {
        this.setState({
            tooltipOpen: false
        })
        this.props.reDraw()
    }

    deleteClassifier = (e) => {
        e.preventDefault()
        if (confirm('Delete ' + this.props.name + '?') == true) {
            var req = request.del('/api/classifiers/' + this.props.classifierID)
            amplitude.getInstance().logEvent('Delete-classifier')
            var self = this
            req.query({api_key: localStorage.getItem('api_key')})
            req.end(function(err, res) {
                console.log('deleted')
                if (res.body.error != null) {
                    alert(res.body.error)
                }
                self.props.reData()
            })
        }
    }

    getName = () => {
      if (this.props.name == 'default') {
        return Strings.classifier_general
      } else if (this.props.name == 'food') {
        return Strings.classifier_food
      } else {
        return this.props.name
      }
    }

    resizeImage = (image, uploadedImage) => {
        var c = window.document.createElement('canvas')
        var ctx = c.getContext('2d')
        var ratio = image.width / image.height
        var maxSize = 1000

        if (image.width < maxSize && image.height < maxSize) {
           c.width = image.width
           c.height = image.height
        } else {
           c.width = (ratio > 1 ? maxSize : maxSize * ratio)
           c.height = (ratio > 1 ? maxSize / ratio : maxSize)
        }

        ctx.drawImage(image, 0, 0, c.width, c.height)
        return c.toDataURL('image/jpeg')
    }

    convertDataURLtoFile = (imageDataURL, fileName, preview) => {
        var imageType = imageDataURL.substring(imageDataURL.indexOf(':') + 1, imageDataURL.indexOf(';'))
        var imageDataBase64 = imageDataURL.substring(imageDataURL.indexOf(',') + 1, imageDataURL.length)
        var byteCharacters = atob(imageDataBase64)
        var byteNumbers = new Array(byteCharacters.length)
        for (var i = 0; i < byteCharacters.length; i++) {
            byteNumbers[i] = byteCharacters.charCodeAt(i)
        }
        var byteArray = new Uint8Array(byteNumbers)
        var blob = new Blob([byteArray], {type: imageType})

        var file = new File([blob], fileName, {type: imageType, lastModified: Date.now()})
        file.preview = preview

        return file
    }

    onDrop = (files, rejects, onFinished, onProgress) => {
        var self = this
        var req

        self.clearClassifier()
        self.setState({ error: null }, self.stateChanged)

        if (files == null || files.length <= 0) {
            self.setState({ error: Strings.invalid_image_error }, self.stateChanged)
            return
        }

        if (this.props.classifierID == null && this.props.name == Strings.classifier_face) {
            req = request.post('/api/faces')
        } else {
            req = request.post('/api/classify')
            req.query({classifier_ids: [this.props.classifierID || this.props.name.toLowerCase()]})
            req.query({threshold: 0.0})
        }

        if (this.props.classifierID == null) {
            amplitude.getInstance().logEvent('Classify-' + this.props.name.toLowerCase())
        } else {
            amplitude.getInstance().logEvent('Classify-custom')
        }

        var uploadedImage = files[0]

        // resize uploaded image if greater than 2MB
        if (files[0].size > 2000000) {
            var name = files[0].name
            var preview = files[0].preview
            var reader = new FileReader()
            reader.onload = () => {
                var image = new Image()
                image.src = reader.result
                image.onload = () => {
                    uploadedImage = this.convertDataURLtoFile(this.resizeImage(image), name, preview)
                    this.classify(req, uploadedImage, onProgress, onFinished)
                }
            }
            reader.readAsDataURL(files[0])

        } else {
            this.classify(req, uploadedImage, onProgress, onFinished)
        }
    }

    onLink = (link, onFinished, onProgress) => {
        var self = this
        var req

        self.setState({ error: null }, self.stateChanged)

{'fraction_non_alphanumeric': 0.12427966395889745, 'fraction_numerical': 0.010067347080469347, 'mean_word_length': 1.730098559514784, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '657998', 'n_tokens_mistral': 4154, 'n_tokens_neox': 3964, 'n_words': 856}