<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import {
    withStyles,
    List,
    ListItem,
    ListItemText,
    Collapse,
    ExpandLessIcon,
    ExpandMoreIcon,
    TextField,
    AddIconButton,
    ClearIconButton
} from 'ui/admin'
import Util from 'client/util'

const styles = theme => ({
    type: {
        fontWeight: 'bold'
    }
})
import JsonDom from '../JsonDom'

class JsonEditor extends React.Component {

    json = null

    constructor(props) {
        super(props)
        try {
            this.json = JSON.parse(props.children)
        } catch (e) {
            console.log(e)
        }
//console.log(JsonDom.components)
        this.state = {
            open: {}
        }
    }

    renderJsonRec(json, key, level) {
        const {classes} = this.props
        if (!json) return null
        if (!key) key = '0'
        if (!level) level = 0

        if (json.constructor === Array) {
            const acc = []
            json.forEach((item, idx) => {
                acc.push(this.renderJsonRec(item, key + '.' + idx, level + 1))
            })
            return <List component="nav">{acc}</List>
        } else if (json.constructor === Object) {
            const t = (json.t || 'div')
            const props = []
            Object.keys(json).forEach(k => {
                if (k !== 't' && k !== 'c') {
                    props.push(<ListItem style={{paddingLeft: 10 * level + 10}}
                                         key={key + '.' + k}><ListItemText>{k + ' = ' + JSON.stringify(json[k])}</ListItemText></ListItem>)
                }
            })

            let newkey = key, newlevel = level
            if (json.c && json.c.constructor === Object) {
                newkey += '.0'
                newlevel++
            }


            return [<ListItem onMouseOver={() => {
                console.log('TODO: implement highlighting')
            }} key={key} style={{paddingLeft: 10 * level}} button
                              onClick={this.handleClick.bind(this, key)}>
                <ListItemText classes={{primary: classes.type}}>
                    <span
                        onClick={e => {
                            e.stopPropagation()
                            return false
                        }}
                        onKeyUp={e => {
                            this.setChildComponent(key, e.target.innerText.trim(), 't')
                        }
                        }
                        onBlur={e => {
                        }}
                        suppressContentEditableWarning={true}
                        contentEditable>{t}</span>
                </ListItemText>
                <AddIconButton onClick={e => {
                    e.stopPropagation()
                    this.addComponent(key)
                    return false
                }}></AddIconButton>
                <ClearIconButton onClick={e => {
                    e.stopPropagation()
                    this.addComponent(key)
                    return false
                }}></ClearIconButton>
                { json.c && (!!this.state.open[key] ? <ExpandLessIcon /> : <ExpandMoreIcon />)}
            </ListItem>,
                <Collapse key={key + '.colapse'} in={!!this.state.open[key]} timeout="auto" unmountOnExit>
                    {props}
                    {this.renderJsonRec(json.c, newkey, newlevel)}

                </Collapse>]
        } else {
            return <ListItem style={{paddingLeft: 10 * level + 10}} key={key + '.c'}><ListItemText>
                <TextField fullWidth value={json} onChange={e => {
                    this.setChildComponent(key, e.target.value)
                }
                } onBlur={e => {
                    this.props.onBlur(JSON.stringify(this.json, null, 4))
                }}/>
            </ListItemText></ListItem>
        }
    }

    setChildComponent(key, value, prop) {
        const o = Util.getComponentByKey(key, this.json)
        if (o) {
            o[prop || 'c'] = value
            this.props.onChange(JSON.stringify(this.json, null, 4))
            this.forceUpdate()
        }
    }


    addComponent(key) {
        const o = Util.getComponentByKey(key, this.json)
        if (o) {
            let c = o['c']
            if (!c) {
                c = []
            } else if (c.constructor !== Array) {
                c = [c]
            }
            c.push({'c': 'new component'})
            o.c = c
            this.props.onBlur(JSON.stringify(this.json, null, 4))
            this.setState({open: Object.assign({}, this.state.open, {[key]: true})});

        }
    }

    handleClick(key) {
        this.setState({open: Object.assign({}, this.state.open, {[key]: !this.state.open[key]})});
    }

    render() {
        return this.renderJsonRec(this.json)
    }

    shouldComponentUpdate(nextProps, nextState) {
        return nextState.open !== this.state.open || nextProps.children != this.props.children
    }

}

JsonEditor.propTypes = {
    style: PropTypes.object,
    onChange: PropTypes.func,
    onBlur: PropTypes.func,
    classes: PropTypes.object.isRequired,
}

export default withStyles(styles)(JsonEditor)<commit_msg>Small improvments<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import {
    withStyles,
    List,
    ListItem,
    ListItemText,
    Collapse,
    ExpandLessIcon,
    ExpandMoreIcon,
    TextField,
    AddIconButton,
    ClearIconButton
} from 'ui/admin'
import Util from 'client/util'

const styles = theme => ({
    type: {
        fontWeight: 'bold'
    }
})
import JsonDom from '../JsonDom'

class JsonEditor extends React.Component {

    json = null

    constructor(props) {
        super(props)
        try {
            this.json = JSON.parse(props.children)
        } catch (e) {
            console.log(e)
        }
//console.log(JsonDom.components)
        this.state = {
            open: {}
        }
    }

    renderJsonRec(json, key, level) {
        const {classes} = this.props
        if (!json) return null
        if (!key) key = '0'
        if (!level) level = 0

        if (json.constructor === Array) {
            const acc = []
            json.forEach((item, idx) => {
                acc.push(this.renderJsonRec(item, key + '.' + idx, level + 1))
            })
            return <List component="nav">{acc}</List>
        } else if (json.constructor === Object) {
            const t = (json.t || 'div')
            const props = []
            Object.keys(json).forEach(k => {
                if (k !== 't' && k !== 'c') {
                    props.push(<ListItem style={{paddingLeft: 10 * level + 10}}
                                         key={key + '.' + k}><ListItemText>{k + ' = ' + JSON.stringify(json[k])}</ListItemText></ListItem>)
                }
            })

            let newkey = key, newlevel = level
            if (json.c && json.c.constructor === Object) {
                newkey += '.0'
                newlevel++
            }


            return [<ListItem onMouseOver={() => {
                console.log('TODO: implement highlighting')
            }} key={key} style={{paddingLeft: 10 * level}} button
                              onClick={this.handleClick.bind(this, key)}>
                <ListItemText classes={{primary: classes.type}}>
                    <span
                        onClick={e => {
                            e.stopPropagation()
                            return false
                        }}
                        onKeyUp={e => {
                            this.setChildComponent(key, e.target.innerText.trim(), 't')
                        }
                        }
                        onBlur={e => {
                        }}
                        suppressContentEditableWarning={true}
                        contentEditable>{t}</span>
                </ListItemText>
                <AddIconButton onClick={e => {
                    e.stopPropagation()
                    this.addComponent(key)
                    return false
                }}></AddIconButton>
                <ClearIconButton onClick={e => {
                    e.stopPropagation()
                    this.removeComponent(key)
                    return false
                }}></ClearIconButton>
                { json.c && (!!this.state.open[key] ? <ExpandLessIcon /> : <ExpandMoreIcon />)}
            </ListItem>,
                <Collapse key={key + '.colapse'} in={!!this.state.open[key]} timeout="auto" unmountOnExit>
                    {props}
                    {this.renderJsonRec(json.c, newkey, newlevel)}

                </Collapse>]
        } else {
            return <ListItem style={{paddingLeft: 10 * level + 10}} key={key + '.c'}><ListItemText>
                <TextField fullWidth value={json} onChange={e => {
                    this.setChildComponent(key, e.target.value)
                }
                } onBlur={e => {
                    this.props.onBlur(JSON.stringify(this.json, null, 4))
                }}/>
            </ListItemText></ListItem>
        }
    }

    setChildComponent(key, value, prop) {
        const o = Util.getComponentByKey(key, this.json)
        if (o) {
            o[prop || 'c'] = value
            this.props.onChange(JSON.stringify(this.json, null, 4))
            this.forceUpdate()
        }
    }


    addComponent(key) {
        const o = Util.getComponentByKey(key, this.json)
        if (o) {
            let c = o['c']
            if (!c) {
                c = []
            } else if (c.constructor !== Array) {
                c = [c]
            }
            c.push({'c': 'new component'})
            o.c = c
            this.props.onBlur(JSON.stringify(this.json, null, 4))
            this.setState({open: Object.assign({}, this.state.open, {[key]: true})});

        }
    }


    removeComponent(key) {
        const parentKey = key.substring(0,key.lastIndexOf('.'))
        const parent = Util.getComponentByKey(parentKey, this.json), child = Util.getComponentByKey(key, this.json)
        if (parent && child) {
            let c = parent['c']
            if (!c) {
                return
            } else if (c.constructor !== Array) {
                c = ''
            }else{
                c.splice( c.indexOf(child), 1 );
            }
            parent.c = c
            this.props.onBlur(JSON.stringify(this.json, null, 4))
            this.setState({open: Object.assign({}, this.state.open, {[key]: true})});

        }
    }

    handleClick(key) {
        this.setState({open: Object.assign({}, this.state.open, {[key]: !this.state.open[key]})});
    }

    render() {
        return this.renderJsonRec(this.json)
    }

    shouldComponentUpdate(nextProps, nextState) {
        return nextState.open !== this.state.open || nextProps.children != this.props.children
    }

}

JsonEditor.propTypes = {
    style: PropTypes.object,
    onChange: PropTypes.func,
    onBlur: PropTypes.func,
    classes: PropTypes.object.isRequired,
}

export default withStyles(styles)(JsonEditor)
{'fraction_non_alphanumeric': 0.1354682018530179, 'fraction_numerical': 0.0033282360349015023, 'mean_word_length': 1.4080571799870045, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 75, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1773355', 'n_tokens_mistral': 3156, 'n_tokens_neox': 3031, 'n_words': 591}