| 1 | import { Form, FormProps } from '@hfs/mui-grid-form' |
| 2 | import { apiCall, useApiEx } from './api' |
| 3 | import { createElement as h, useEffect, useState, Dispatch } from 'react' |
| 4 | import _ from 'lodash' |
| 5 | import { IconBtn, propsForModifiedValues } from './mui' |
| 6 | import { RestartAlt } from '@mui/icons-material' |
| 7 | import { Callback, onlyTruthy } from './misc' |
| 8 | |
| 9 | type FormRest<T> = Omit<FormProps<T>, 'values' | 'set' | 'save'> & Partial<Pick<FormProps<T>, 'save'>> |
| 10 | export function ConfigForm<T=any>({ keys, form, saveOnChange, onSave, ...rest }: Partial<FormRest<T>> & { |
| 11 | keys?: (keyof T)[], |
| 12 | form: FormRest<T> | ((values: T, optional: { setValues: Dispatch<T> }) => FormRest<T>), |
| 13 | onSave?: Callback, |
| 14 | saveOnChange?: boolean |
| 15 | }) { |
| 16 | const [keys_, setKeys_] = useState(keys) |
| 17 | const config = useApiEx(keys_ && 'get_config', { only: keys_ }) |
| 18 | const [values, setValues] = useState<any>(config.data) |
| 19 | useEffect(() => setValues((v: any) => config.data || v), [config.data]) |
| 20 | const modified = values && !_.isEqual(values, config.data) |
| 21 | useEffect(() => { |
| 22 | if (modified && saveOnChange) save() |
| 23 | }, [modified]) |
| 24 | const formProps = _.isFunction(form) ? form(values, { setValues }) : form |
| 25 | useEffect(() => { |
| 26 | if (!keys) // autodetect keys |
| 27 | setKeys_(onlyTruthy(formProps.fields.map(x => (x as any)?.k))) |
| 28 | }, [keys]) |
| 29 | if (!values) |
| 30 | return config.element |
| 31 | return h(Form, { |
| 32 | values, |
| 33 | set(v, k) { |
| 34 | setValues((was: any) => ({ ...was, [k]: v })) |
| 35 | }, |
| 36 | save: saveOnChange ? false : { |
| 37 | onClick: save, |
| 38 | ...propsForModifiedValues(modified), |
| 39 | }, |
| 40 | ...formProps, |
| 41 | ...rest, |
| 42 | barSx: { gap: 1, ...rest.barSx }, |
| 43 | addToBar: [ |
| 44 | h(IconBtn, { |
| 45 | icon: RestartAlt, |
| 46 | disabled: !modified, |
| 47 | title: "Reset", |
| 48 | onClick(){ setValues(config.data) } |
| 49 | }), |
| 50 | ...rest.addToBar||[], |
| 51 | ], |
| 52 | }) |
| 53 | |
| 54 | function save() { |
| 55 | return apiCall('set_config', { values }).then(onSave).then(config.reload) |
| 56 | } |
| 57 | } |