import Query from 'query'; import dotProp from 'dot-prop'; import React, { useState, useEffect, useCallback } from 'react'; import { Icon, Hbs, View, Box, Tooltip, useTheme, ToggleButtonGroup, ToggleButton, Stack, CircularProgress } from '../'; // let context let DashupUIContext = null; // create dashup grid body const DashupUIFormField = (props = {}) => { // state const [hovered, setHovered] = useState(false); // theme const theme = useTheme(); // get field struct const struct = props.getFieldStruct(props.field.type); // clean data const cleanQuery = useCallback((obj = {}) => { // keys Object.keys(obj).map((key) => { // val const val = obj[key]; // check key if (key.includes('.') && Array.isArray(dotProp.get(props.clean || {}, key.split('.')[0]))) { // make elemmatch return obj = { [key.split('.')[0]] : { $elemMatch : { [key.split('.')[1]] : val, } } }; } // check key if (key === '$inc') { obj = { $likeI : val, }; } if (key === '$eq') return obj = val; // check key if (val && typeof val === 'string' && val.includes('{{')) { try { // compile template const tmpl = Hbs.Handlebars.compile(val); // return actual value obj[key] = tmpl(props.clean || {}); } catch (e) { // check value obj[key] = ''; } } // check obj if (val && val instanceof Object) { obj[key] = cleanQuery(val); } }); // return obj return obj; }, [JSON.stringify(props.clean)]); // use state const [defaultValue, setDefaultValue] = useState(struct?.data?.actions?.includes('sanitise') ? null : cleanQuery({ val : props.field?.default }).val); const [loading, setLoading] = useState(!defaultValue && !props.value && !!props.field?.default && struct?.data?.actions?.includes('sanitise')); const [actualDefaultValue, setActualDefaultValue] = useState(struct?.data?.actions?.includes('sanitise') ? null : props.field?.default); // on break const onBreak = (e) => { // set field props.setField(props.field, 'break', !props.field.break); }; // on compress const onCompress = (e) => { // set field props.setField(props.field, 'col', !props.field.col); }; // is visible const isViewOnly = useCallback((clean) => { // check value if ((props.field.viewOnly || '[]').length <= 2) return false; // try/catch try { // match return !Query.query([clean], { $and : cleanQuery(JSON.parse(props.field.viewOnly)), }, Query.undot).length; } catch (e) {} // return true return true; }, [props.field.viewOnly, JSON.stringify(props.clean)]); // is visible const isReadOnly = useCallback((clean) => { // check value if ((props.field.readOnly || '[]').length <= 2) return false; // try/catch try { // match return !Query.query([clean], { $and : cleanQuery(JSON.parse(props.field.readOnly)), }, Query.undot).length; } catch (e) {} // return true return true; }, [props.field.readOnly, JSON.stringify(props.clean)]); // check default value useEffect(() => { // check struct actions if (props.value) return; if (!actualDefaultValue) return; if (typeof props.field?.default === 'undefined') return; // new default value const newDefaultValue = cleanQuery({ val : actualDefaultValue }).val; // check value if (JSON.stringify(defaultValue) === JSON.stringify(newDefaultValue)) return; // set value setLoading(true); setDefaultValue(newDefaultValue); // timeout setTimeout(() => setLoading(false), 100); }, [JSON.stringify(props.clean)]); // check default value useEffect(() => { // check struct actions if (defaultValue) return setLoading(false); if (typeof props.field?.default === 'undefined') return setLoading(false); if (!struct?.data?.actions?.includes('sanitise')) return setLoading(false); // loading default setLoading(true); // load value props.dashup.action({ type : 'field', page : props.page.get('_id'), struct : struct?.type, }, 'sanitise', props.field, props.field?.default).then((data) => { // check data if (!data || !data.sanitised) return setLoading(false); // set value setDefaultValue(cleanQuery({ val : data.sanitised }).val); setActualDefaultValue(data.sanitised); // loading default setLoading(false); }); }, [props.field?.uuid]); // button sx const buttonSx = { paddingLeft : 1, paddingRight : 1, }; // return jsx return !struct ? null : ( .updating' : { display : 'flex', } } } data-field={ props.field.uuid } data-type={ props.field.type } id={ `field-${props.field.uuid}${props.iKey ? `-${props.iKey}` : '' }` } onMouseEnter={ () => props.updating && setHovered(true) } onMouseLeave={ () => props.updating && setHovered(false) } > { props.updating && hovered && ( <> { struct.title } Field onCompress(e) } sx={ buttonSx }> { props.field.col ? ( ) : ( ) } onBreak(e) } sx={ buttonSx }> props.onConfig(props.field) } sx={ buttonSx }> props.onRemove(props.field) } selected color="error" sx={ buttonSx }> ) } { loading ? ( ) : ( ) } ); }; // consumer wrapper const DashupUIFormFieldWrap = (props = {}) => { // return JSX return ( { (data) => ( ) } ); }; // export default page menu export default (ctx) => { // use context DashupUIContext = ctx; // return actual component return DashupUIFormFieldWrap; };