new formDialog signature
Massimo Melina committed
Mar 22, 2023 at 19:00 UTC
36fc9e20ff06022205dec6d8e21b235c68fe1b6a
3 files changed
+37
-31
admin/src/ArrayField.ts
+2
-2
@@ -33,7 +33,7 @@ export function ArrayField<T extends object>({ label, helperText, fields, value,
33
icon: Add,
34
title: "Add",
35
onClick: (event:any) =>
36
- formDialog({ fields }).then(o => // @ts-ignore
36
+ formDialog({ form: { fields } }).then(o => // @ts-ignore
37
o && onChange([...value||[], o], { was: value, event }))
38
})
39
},
@@ -44,7 +44,7 @@ export function ArrayField<T extends object>({ label, helperText, fields, value,
44
icon: Edit,
45
title: "Modify",
46
onClick: (event:any) =>
47
- formDialog({ fields, values: row }).then(newRec => {
47
+ formDialog<T>({ values: row, form: { fields } }).then(newRec => {
48
if (!newRec) return
49
const newValue = value!.map((oldRec, i) => i === $idx ? newRec : oldRec)
50
onChange(newValue, { was: value, event })
admin/src/OptionsPage.ts
+12
-8
@@ -287,14 +287,18 @@ export async function makeCertAndSave() {
287
return alertDialog("Retry this procedure on localhost", 'warning')
288
const res = await formDialog<{ commonName: string }>({
289
title: "We'll generate a basic certificate for you",
290
- fields: [
291
- h(Box, { display: 'flex', gap: 1, alignItems: 'center' }, h(Warning), "This certificate is just one click away, but will issue a warning on the browser"),
292
- { k: 'commonName', label: "Enter a domain, or leave empty" }
293
- ],
294
- save: { children: "Continue" },
295
- barSx: { gap: 1 },
296
- addToBar: [ h(Link, { target: 'cert', href: 'https://letsencrypt.org/' }, h(Button, {}, "Get better certificate")) ],
297
-
290
+ form: {
291
+ fields: [
292
+ h(Box, { display: 'flex', gap: 1, alignItems: 'center' },
293
+ h(Warning), "This certificate is just one click away, but will issue a warning on the browser"),
294
+ { k: 'commonName', label: "Enter a domain, or leave empty" }
295
+ ],
296
+ save: { children: "Continue" },
297
+ barSx: { gap: 1 },
298
+ addToBar: [
299
+ h(Link, { target: 'cert', href: 'https://letsencrypt.org/' }, h(Button, {}, "Get better certificate"))
300
+ ],
301
+ }
302
})
303
if (!res) return
304
const close = waitDialog()
admin/src/dialog.ts
+23
-21
@@ -6,14 +6,13 @@ import {
6
CircularProgress,
7
Dialog as MuiDialog,
8
DialogContent,
9
- DialogProps,
9
DialogTitle,
10
IconButton
11
} from '@mui/material'
12
import {
14
- createElement as h, Fragment,
13
+ createElement as h, Dispatch, Fragment,
14
isValidElement,
16
- ReactElement,
15
+ ReactElement, SetStateAction,
16
useEffect,
17
useRef,
18
useState
@@ -141,39 +140,43 @@ export async function confirmDialog(msg: string | ReactElement, { href }: Confir
140
}
141
}
142
144
-type FormDialog<T> = Pick<DialogProps, 'fullScreen' | 'title'>
145
- & Pick<DialogOptions, 'dialogProps'>
146
- & Omit<FormProps<T>, 'values' | 'save' | 'set'>
147
- & Partial<Pick<FormProps<T>, 'values' | 'save'>>
143
+type FormDialog<T> = Omit<FormProps<T>, 'values' | 'save' | 'set'>
144
+ & Partial<Pick<FormProps<T>, 'save'>>
145
& {
149
- onChange?: (values:Partial<T>, extra: { setValues: React.Dispatch<React.SetStateAction<Partial<T>>> }) => void,
150
- before?: any
151
-}
152
-export async function formDialog<T>({ fullScreen, title, onChange, before, ...props }: FormDialog<T>) : Promise<T> {
146
+ onChange?: (values:Partial<T>, extra: { setValues: Dispatch<SetStateAction<Partial<T>>> }) => void,
147
+ before?: any
148
+ }
149
+export async function formDialog<T>(
150
+ { form, values, ...options }: Omit<DialogOptions, 'Content'> & {
151
+ values?: Partial<T>,
152
+ form: FormDialog<T> | ((values: Partial<T>) => FormDialog<T>),
153
+ },
154
+) : Promise<T> {
155
return new Promise(resolve => newDialog({
156
className: 'dialog-confirm',
157
icon: '?',
158
onClose: resolve,
157
- title,
159
+ ...options,
160
Content
161
}) )
162
163
function Content() {
162
- const [values, setValues] = useState<Partial<T>>(props.values||{})
164
+ const [curValues, setCurValues] = useState<Partial<T>>(values||{})
165
+ const { onChange, before, ...props } = typeof form === 'function' ? form(curValues) : form
166
return h(Fragment, {},
167
before,
168
h(Form, {
169
...props,
167
- values,
170
+ values: curValues,
171
set(v, k) {
169
- const newV = { ...values, [k]: v }
170
- setValues(newV)
171
- onChange?.(newV, { setValues })
172
+ const newV = { ...curValues, [k]: v }
173
+ setCurValues(newV)
174
+ onChange?.(newV, { setValues: setCurValues })
175
},
176
save: {
177
...props.save,
178
onClick() {
176
- closeDialog(values)
179
+ closeDialog(curValues)
180
}
181
}
182
})
@@ -182,8 +185,7 @@ export async function formDialog<T>({ fullScreen, title, onChange, before, ...pr
185
}
186
187
export async function promptDialog(msg: string, props:any={}) : Promise<string | undefined> {
185
- return formDialog<{ text: string }>({
186
- ...props,
188
+ return formDialog<{ text: string }>({ ...props, form: {
189
fields: [
190
{ k: 'text', label: null, autoFocus: true,
191
before: h(Box, { mb: 2 }, msg),
@@ -201,7 +203,7 @@ export async function promptDialog(msg: string, props:any={}) : Promise<string |
203
h(Button, { onClick: closeDialog }, "Cancel"),
204
...props.addToBar||[],
205
]
204
- }).then(values => values?.text)
206
+ } }).then(values => values?.text)
207
}
208
209
export function waitDialog() {