admin: prompt dialogs will submit on enter and have better layout

Massimo Melina committed Jun 9, 2022 at 00:53 UTC 01a0ae985f2fcd6ef26e5f4d04802f1203a625d1
4 files changed +33 -7
admin/src/ConfigPage.ts
+1 -1
@@ -143,7 +143,7 @@ export default function ConfigPage() {
143 return window.location.href = loc.protocol + '//' + loc.hostname + ':' + newPort + loc.pathname
144 }
145 setTimeout(reloadStatus, 'port' in changes || 'https_port' in changes ? 1000 : 0) // give some time to consider new ports
146 - Object.assign(loaded, changes) // since changes are recalculated subscribing state.config, but it depends on 'loaded' to (which cannot be subscribed), be sure to update loaded first
146 + Object.assign(loaded!, changes) // since changes are recalculated subscribing state.config, but it depends on 'loaded' to (which cannot be subscribed), be sure to update loaded first
147 recalculateChanges()
148 toast("Changes applied", 'success')
149 }
admin/src/dialog.ts
+5 -2
@@ -148,14 +148,17 @@ export async function promptDialog(msg: string, props:any={}) : Promise<string |
148 return formDialog<{ text: string }>({
149 ...props,
150 fields: [
151 - h(Box, {}, msg),
152 - { k: 'text', label: null, autoFocus: true, ...props.field },
151 + { k: 'text', label: null, autoFocus: true,
152 + before: h(Box, { mb: 2 }, msg),
153 + ...props.field
154 + },
155 ],
156 save: {
157 children: "Continue",
158 startIcon: h(Forward),
159 ...props.save,
160 },
161 + saveOnEnter: true,
162 barSx: { gap: 2 },
163 addToBar: [
164 h(Button, { onClick: closeDialog }, "Cancel"),
mui-grid-form/src/Form.ts
+26 -4
@@ -17,6 +17,7 @@ import { Save } from '@mui/icons-material'
17 import { LoadingButton } from '@mui/lab'
18 import _ from 'lodash'
19 import { StringField } from './StringField'
20 +import { GridProps } from '@mui/material/Grid/Grid'
21 export * from './SelectField'
22 export * from './misc-fields'
23 export * from './StringStringField'
@@ -30,6 +31,8 @@ export interface FieldDescriptor<T=any> {
31 getError?: (v: any, extra?: any) => Promisable<ValidationError>
32 toField?: (v: T) => any
33 fromField?: (v: any) => T
34 + before?: ReactNode
35 + after?: ReactNode
36 [extraProp: string]: any
37 }
38
@@ -62,9 +65,25 @@ export interface FormProps<Values> extends Partial<BoxProps> {
65 onError?: (err: any) => any
66 formRef?: MutableRefObject<HTMLFormElement | undefined>
67 saveOnEnter?: boolean
68 + gridProps?: Partial<GridProps>
69 }
70 enum Phase { Idle, WaitValues, Validating }
67 -export function Form<Values extends Dict>({ fields, values, set, defaults, save, stickyBar, addToBar=[], barSx, formRef, onError, saveOnEnter, ...rest }: FormProps<Values>) {
71 +
72 +export function Form<Values extends Dict>({
73 + fields,
74 + values,
75 + set,
76 + defaults,
77 + save,
78 + stickyBar,
79 + addToBar = [],
80 + barSx,
81 + formRef,
82 + onError,
83 + saveOnEnter,
84 + gridProps,
85 + ...rest
86 +}: FormProps<Values>) {
87 const mounted = useRef(false)
88 useEffect(() => {
89 mounted.current = true
@@ -98,7 +117,7 @@ export function Form<Values extends Dict>({ fields, values, set, defaults, save,
117 gap: 3,
118 ...rest
119 },
101 - h(Grid, { container:true, rowSpacing:3, columnSpacing:1 },
120 + h(Grid, { container:true, rowSpacing:3, columnSpacing:1, ...gridProps },
121 fields.map((row, idx) => {
122 if (!row)
123 return null
@@ -143,11 +162,14 @@ export function Form<Values extends Dict>({ fields, values, set, defaults, save,
162 _.defaults(field, defaults?.(whole))
163 }
164 {
146 - const { xs=12, sm, md, lg, xl, comp=StringField,
165 + const { xs=12, sm, md, lg, xl, comp=StringField, before, after,
166 fromField, toField, // don't propagate
167 ...rest } = field
168 return h(Grid, { key: k, item: true, xs, sm, md, lg, xl },
150 - isValidElement(comp) ? comp : h(comp, rest) )
169 + before,
170 + isValidElement(comp) ? comp : h(comp, rest),
171 + after
172 + )
173 }
174 })
175 ),
mui-grid-form/src/StringField.ts
+1
@@ -20,6 +20,7 @@ export function StringField({ value, onChange, min, max, required, getApi, typin
20 fullWidth: true,
21 InputLabelProps: state || props.placeholder ? { shrink: true } : undefined,
22 ...props,
23 + sx: props.label ? props.sx : Object.assign({ '& .MuiInputBase-input': { pt: 1.5 } }, props.sx),
24 value: state,
25 onChange(ev) {
26 const val = ev.target.value