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;
};