main
ts 57 lines 2.06 KB
Raw
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 }