<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import {
    Divider,
    Button,
    TextField,
    SimpleSwitch,
    SimpleSelect,
    InputLabel,
    FormHelperText,
    FormControl,
    SimpleTab,
    SimpleTabPanel,
    SimpleTabs,
    InputAdornment,
    Input,
    ExpandLessIconButton,
    ExpandMoreIconButton,
    TranslateIconButton
} from 'ui/admin'
import FileDrop from './FileDrop'
import TypePicker from './TypePicker'
import config from 'gen/config-client'
import TinyEditor from './TinyEditor'
import {withStyles} from 'ui/admin'
import {checkFieldType} from 'util/typesAdmin'
import Hook from '../../util/hook'
import classNames from 'classnames'
import Expandable from 'client/components/Expandable'
import {_t} from '../../util/i18n'
import Util from '../util'
import DomUtil from '../util/dom'
import {matchExpr, propertyByPath} from '../util/json'
import JsonEditor from '../../extensions/cms/components/JsonEditor'
import {Query} from '../middleware/graphql'
import {getTypeQueries} from 'util/types'
import Async from './Async'

const CodeEditor = (props) => <Async {...props} load={import(/* webpackChunkName: "codeeditor" */ './CodeEditor')}/>



const styles = theme => {
    return {
        editor: {
            border: '1px solid ' + theme.palette.grey['200'],
            margin: theme.spacing(3) + 'px 0'
        },
        formField: {
            margin: theme.spacing(1) + 'px',
            width: 'calc(100% - ' + theme.spacing(2) + 'px)',
            [theme.breakpoints.up('md')]: {
                width: 'calc(50% - ' + theme.spacing(2) + 'px)'
            }
        },
        formFieldThird: {
            margin: theme.spacing(1) + 'px',
            width: 'calc(100% - ' + theme.spacing(2) + 'px)',
            [theme.breakpoints.up('md')]: {
                width: 'calc(33.33% - ' + theme.spacing(2) + 'px)'
            }
        },
        formFieldFull: {
            width: 'calc(100% - ' + theme.spacing(2) + 'px)',
            margin: theme.spacing(1) + 'px',
        },
        tabContainer: {
            backgroundColor: theme.palette.background.paper
        },
        translationAbsolute: {
            right: '3.55rem',
            marginTop: '-0.5rem',
            position: 'absolute',
            zIndex: 2
        }
    }
}

const autoIncrement = (key, cb) => {
    fetch('/lunucapi/autoIncrement?key=' + key).then(response => response.json().then(cb))
}

function matchObjectValueFromList(value, field, list) {
    if (value && value.constructor === Object) {
        // find key for value
        const strValue = JSON.stringify(value)
        for (let i = 0; i < list.length; i++) {
            if (JSON.stringify(list[i].value) == strValue) {
                return list[i].name
            }
        }
        return ''
    }
    return value
}

class GenericForm extends React.Component {
    constructor(props) {
        super(props)
        this.state = GenericForm.getInitalState(props, {})
    }

    static getInitalState = (props, prevState) => {
        const initalState = {
            fieldsOri: props.fields,
            fields: {},
            valuesOri: props.values,
            showTranslations: {},
            tabValue: prevState.tabValue ? prevState.tabValue : 0
        }
        Object.keys(props.fields).map(fieldKey => {
            const field = props.fields[fieldKey]
            if (!field) {
                return
            }
            let fieldValue
            if (field.localized) {
                if (props.values && props.values[fieldKey]) {
                    if (props.values[fieldKey].constructor === String) {
                        if (!fieldValue) {
                            fieldValue = {}
                        }
                        config.LANGUAGES.forEach(lang => {
                            fieldValue[lang] = props.values[fieldKey]
                        })
                    } else {
                        fieldValue = Object.assign({}, props.values[fieldKey])
                    }
                } else {
                    fieldValue = null
                }
            } else {
                if (props.values) {
                    fieldValue = props.values[fieldKey]
                } else {
                    // value must be null instead of undefined
                    fieldValue = field.value === undefined ? null : field.value
                }
            }
            initalState.fields[fieldKey] = fieldValue
        })
        const formValidation = GenericForm.staticValidate(initalState, props)
        initalState.isValid = formValidation.isValid
        initalState.fieldErrors = formValidation.fieldErrors
        return initalState
    }


    static getDerivedStateFromProps(nextProps, prevState) {
        if (nextProps.fields !== prevState.fieldsOri ||
            (nextProps.updateOnValueChange && Util.shallowCompare(nextProps.values, prevState.valuesOri))) {
            console.log('GenericForm fields changed')
            return GenericForm.getInitalState(nextProps, prevState)
        }
        return null
    }

    static staticValidate(state, props, options = {changeTab: false}) {
        const {fields, onValidate} = props
        const fieldErrors = {}, tabs = []
        Object.keys(fields).forEach(fieldKey => {
            const field = fields[fieldKey]

            if (!field) {
                return
            }

            if (field.tab && options.changeTab) {
                if (tabs.indexOf(field.tab) < 0) {
                    tabs.push(field.tab)
                }
            }

            if (field.required) {

                if (field.reference) {<commit_msg>Validate only if visible in GenericForm<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import {
    Divider,
    Button,
    TextField,
    SimpleSwitch,
    SimpleSelect,
    InputLabel,
    FormHelperText,
    FormControl,
    SimpleTab,
    SimpleTabPanel,
    SimpleTabs,
    InputAdornment,
    Input,
    ExpandLessIconButton,
    ExpandMoreIconButton,
    TranslateIconButton
} from 'ui/admin'
import FileDrop from './FileDrop'
import TypePicker from './TypePicker'
import config from 'gen/config-client'
import TinyEditor from './TinyEditor'
import {withStyles} from 'ui/admin'
import {checkFieldType} from 'util/typesAdmin'
import Hook from '../../util/hook'
import classNames from 'classnames'
import Expandable from 'client/components/Expandable'
import {_t} from '../../util/i18n'
import Util from '../util'
import DomUtil from '../util/dom'
import {matchExpr, propertyByPath} from '../util/json'
import JsonEditor from '../../extensions/cms/components/JsonEditor'
import {Query} from '../middleware/graphql'
import {getTypeQueries} from 'util/types'
import Async from './Async'

const CodeEditor = (props) => <Async {...props} load={import(/* webpackChunkName: "codeeditor" */ './CodeEditor')}/>



const styles = theme => {
    return {
        editor: {
            border: '1px solid ' + theme.palette.grey['200'],
            margin: theme.spacing(3) + 'px 0'
        },
        formField: {
            margin: theme.spacing(1) + 'px',
            width: 'calc(100% - ' + theme.spacing(2) + 'px)',
            [theme.breakpoints.up('md')]: {
                width: 'calc(50% - ' + theme.spacing(2) + 'px)'
            }
        },
        formFieldThird: {
            margin: theme.spacing(1) + 'px',
            width: 'calc(100% - ' + theme.spacing(2) + 'px)',
            [theme.breakpoints.up('md')]: {
                width: 'calc(33.33% - ' + theme.spacing(2) + 'px)'
            }
        },
        formFieldFull: {
            width: 'calc(100% - ' + theme.spacing(2) + 'px)',
            margin: theme.spacing(1) + 'px',
        },
        tabContainer: {
            backgroundColor: theme.palette.background.paper
        },
        translationAbsolute: {
            right: '3.55rem',
            marginTop: '-0.5rem',
            position: 'absolute',
            zIndex: 2
        }
    }
}

const autoIncrement = (key, cb) => {
    fetch('/lunucapi/autoIncrement?key=' + key).then(response => response.json().then(cb))
}

function matchObjectValueFromList(value, field, list) {
    if (value && value.constructor === Object) {
        // find key for value
        const strValue = JSON.stringify(value)
        for (let i = 0; i < list.length; i++) {
            if (JSON.stringify(list[i].value) == strValue) {
                return list[i].name
            }
        }
        return ''
    }
    return value
}

class GenericForm extends React.Component {
    constructor(props) {
        super(props)
        this.state = GenericForm.getInitalState(props, {})
    }

    static getInitalState = (props, prevState) => {
        const initalState = {
            fieldsOri: props.fields,
            fields: {},
            valuesOri: props.values,
            showTranslations: {},
            tabValue: prevState.tabValue ? prevState.tabValue : 0
        }
        Object.keys(props.fields).map(fieldKey => {
            const field = props.fields[fieldKey]
            if (!field) {
                return
            }
            let fieldValue
            if (field.localized) {
                if (props.values && props.values[fieldKey]) {
                    if (props.values[fieldKey].constructor === String) {
                        if (!fieldValue) {
                            fieldValue = {}
                        }
                        config.LANGUAGES.forEach(lang => {
                            fieldValue[lang] = props.values[fieldKey]
                        })
                    } else {
                        fieldValue = Object.assign({}, props.values[fieldKey])
                    }
                } else {
                    fieldValue = null
                }
            } else {
                if (props.values) {
                    fieldValue = props.values[fieldKey]
                } else {
                    // value must be null instead of undefined
                    fieldValue = field.value === undefined ? null : field.value
                }
            }
            initalState.fields[fieldKey] = fieldValue
        })
        const formValidation = GenericForm.staticValidate(initalState, props)
        initalState.isValid = formValidation.isValid
        initalState.fieldErrors = formValidation.fieldErrors
        return initalState
    }


    static getDerivedStateFromProps(nextProps, prevState) {
        if (nextProps.fields !== prevState.fieldsOri ||
            (nextProps.updateOnValueChange && Util.shallowCompare(nextProps.values, prevState.valuesOri))) {
            console.log('GenericForm fields changed')
            return GenericForm.getInitalState(nextProps, prevState)
        }
        return null
    }

    static staticValidate(state, props, options = {changeTab: false}) {
        const {fields, onValidate} = props
        const fieldErrors = {}, tabs = []
        Object.keys(fields).forEach(fieldKey => {
            const field = fields[fieldKey]

            if (!field) {
                return
            }

            if (field.tab && options.changeTab) {
                if (tabs.indexOf(field.tab) < 0) {
                    tabs.push(field.tab)
                }
            }
            if (field.required && (!field.uistate || !field.uistate.visible || !matchExpr(field.uistate.visible, state.fields))) {

                if(field.uitype==='select'){
                    const value = state.fields[fieldKey]
                    if(!value || value.length===0){
                        fieldErrors[fieldKey] = _t('GenericForm.fieldIsRequired')
                    }
                }else if (field.reference) {
{'fraction_non_alphanumeric': 0.12192013593882753, 'fraction_numerical': 0.006881903143585387, 'mean_word_length': 1.7216184971098265, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2468338', 'n_tokens_mistral': 3298, 'n_tokens_neox': 3166, 'n_words': 684}