mirror of
https://github.com/rowyio/rowy.git
synced 2025-12-29 00:16:39 +01:00
table settings: show form errors in step labels
This commit is contained in:
@@ -7,6 +7,8 @@ import {
|
||||
StepProps,
|
||||
StepButton,
|
||||
StepButtonProps,
|
||||
StepLabel,
|
||||
StepLabelProps,
|
||||
Typography,
|
||||
StepContent,
|
||||
StepContentProps,
|
||||
@@ -17,11 +19,14 @@ export interface ISteppedAccordionProps extends Partial<StepperProps> {
|
||||
steps: {
|
||||
id: string;
|
||||
title: React.ReactNode;
|
||||
subtitle?: React.ReactNode;
|
||||
optional?: boolean;
|
||||
content: React.ReactNode;
|
||||
error?: boolean;
|
||||
|
||||
stepProps?: Partial<StepProps>;
|
||||
titleProps?: Partial<StepButtonProps>;
|
||||
labelButtonProps?: Partial<StepButtonProps>;
|
||||
labelProps?: Partial<StepLabelProps>;
|
||||
contentProps?: Partial<StepContentProps>;
|
||||
}[];
|
||||
disableUnmount?: boolean;
|
||||
@@ -67,22 +72,30 @@ export default function SteppedAccordion({
|
||||
({
|
||||
id,
|
||||
title,
|
||||
subtitle,
|
||||
optional,
|
||||
content,
|
||||
error,
|
||||
stepProps,
|
||||
titleProps,
|
||||
labelButtonProps,
|
||||
labelProps,
|
||||
contentProps,
|
||||
}) => (
|
||||
<Step key={id} {...stepProps}>
|
||||
<StepButton
|
||||
onClick={() => setActiveStep((s) => (s === id ? "" : id))}
|
||||
optional={
|
||||
optional && <Typography variant="caption">Optional</Typography>
|
||||
subtitle ||
|
||||
(optional && (
|
||||
<Typography variant="caption">Optional</Typography>
|
||||
))
|
||||
}
|
||||
{...titleProps}
|
||||
{...labelButtonProps}
|
||||
>
|
||||
{title}
|
||||
<ExpandIcon />
|
||||
<StepLabel error={error} {...labelProps}>
|
||||
{title}
|
||||
<ExpandIcon />
|
||||
</StepLabel>
|
||||
</StepButton>
|
||||
|
||||
<StepContent
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import useSWR from "swr";
|
||||
import _find from "lodash/find";
|
||||
import _sortBy from "lodash/sortBy";
|
||||
import _get from "lodash/get";
|
||||
import { useSnackbar } from "notistack";
|
||||
|
||||
import { DialogContentText, Stack, Typography } from "@mui/material";
|
||||
@@ -191,124 +192,173 @@ export default function TableSettings({
|
||||
: "Table settings"
|
||||
}
|
||||
fields={fields}
|
||||
customBody={(formFieldsProps) => (
|
||||
<>
|
||||
<Stack
|
||||
direction="row"
|
||||
spacing={1}
|
||||
sx={{
|
||||
display: "flex",
|
||||
height: "var(--dialog-title-height)",
|
||||
alignItems: "center",
|
||||
customBody={(formFieldsProps) => {
|
||||
const { errors } = formFieldsProps.useFormMethods.formState;
|
||||
const groupedErrors: Record<string, string> = Object.entries(
|
||||
errors
|
||||
).reduce((acc, [name, err]) => {
|
||||
const match = _find(fields, ["name", name])?.step;
|
||||
if (!match) return acc;
|
||||
acc[match] = err.message;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
right: 40 + 12 + 8,
|
||||
}}
|
||||
>
|
||||
{mode === TableSettingsDialogModes.update && (
|
||||
<DeleteMenu clearDialog={clearDialog} data={data} />
|
||||
)}
|
||||
</Stack>
|
||||
return (
|
||||
<>
|
||||
<Stack
|
||||
direction="row"
|
||||
spacing={1}
|
||||
sx={{
|
||||
display: "flex",
|
||||
height: "var(--dialog-title-height)",
|
||||
alignItems: "center",
|
||||
|
||||
<SteppedAccordion
|
||||
disableUnmount
|
||||
steps={
|
||||
[
|
||||
{
|
||||
id: "collection",
|
||||
title: "Collection",
|
||||
content: (
|
||||
<>
|
||||
<DialogContentText paragraph>
|
||||
Connect this table to a new or existing Firestore
|
||||
collection
|
||||
</DialogContentText>
|
||||
<FormFields
|
||||
{...formFieldsProps}
|
||||
fields={fields.filter((f) => f.step === "collection")}
|
||||
/>
|
||||
</>
|
||||
),
|
||||
optional: false,
|
||||
},
|
||||
{
|
||||
id: "display",
|
||||
title: "Display",
|
||||
content: (
|
||||
<>
|
||||
<DialogContentText paragraph>
|
||||
Set how this table is displayed to users
|
||||
</DialogContentText>
|
||||
<FormFields
|
||||
{...formFieldsProps}
|
||||
fields={fields.filter((f) => f.step === "display")}
|
||||
customComponents={customComponents}
|
||||
/>
|
||||
</>
|
||||
),
|
||||
optional: false,
|
||||
},
|
||||
{
|
||||
id: "accessControls",
|
||||
title: "Access controls",
|
||||
content: (
|
||||
<>
|
||||
<DialogContentText paragraph>
|
||||
Set who can view and edit this table. Only ADMIN users
|
||||
can edit table settings or add, edit, and delete
|
||||
columns.
|
||||
</DialogContentText>
|
||||
<FormFields
|
||||
{...formFieldsProps}
|
||||
fields={fields.filter(
|
||||
(f) => f.step === "accessControls"
|
||||
)}
|
||||
customComponents={customComponents}
|
||||
/>
|
||||
</>
|
||||
),
|
||||
optional: false,
|
||||
},
|
||||
{
|
||||
id: "auditing",
|
||||
title: "Auditing",
|
||||
content: (
|
||||
<>
|
||||
<DialogContentText paragraph>
|
||||
Track when users create or update rows
|
||||
</DialogContentText>
|
||||
<FormFields
|
||||
{...formFieldsProps}
|
||||
fields={fields.filter((f) => f.step === "auditing")}
|
||||
/>
|
||||
</>
|
||||
),
|
||||
optional: true,
|
||||
},
|
||||
mode === TableSettingsDialogModes.create
|
||||
? {
|
||||
id: "columns",
|
||||
title: "Columns",
|
||||
content: (
|
||||
<>
|
||||
<DialogContentText paragraph>
|
||||
Initialize table with columns
|
||||
</DialogContentText>
|
||||
<FormFields
|
||||
{...formFieldsProps}
|
||||
fields={fields.filter((f) => f.step === "columns")}
|
||||
/>
|
||||
</>
|
||||
),
|
||||
optional: true,
|
||||
}
|
||||
: null,
|
||||
].filter(Boolean) as any
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
right: 40 + 12 + 8,
|
||||
}}
|
||||
>
|
||||
<ActionsMenu
|
||||
mode={mode}
|
||||
control={formFieldsProps.control}
|
||||
useFormMethods={formFieldsProps.useFormMethods}
|
||||
/>
|
||||
{mode === TableSettingsDialogModes.update && (
|
||||
<DeleteMenu clearDialog={clearDialog} data={data} />
|
||||
)}
|
||||
</Stack>
|
||||
|
||||
<SteppedAccordion
|
||||
disableUnmount
|
||||
steps={
|
||||
[
|
||||
{
|
||||
id: "collection",
|
||||
title: "Collection",
|
||||
content: (
|
||||
<>
|
||||
<DialogContentText paragraph>
|
||||
Connect this table to a new or existing Firestore
|
||||
collection
|
||||
</DialogContentText>
|
||||
<FormFields
|
||||
{...formFieldsProps}
|
||||
fields={fields.filter((f) => f.step === "collection")}
|
||||
/>
|
||||
</>
|
||||
),
|
||||
optional: false,
|
||||
error: groupedErrors.collection,
|
||||
subtitle: groupedErrors.collection && (
|
||||
<Typography variant="caption" color="error">
|
||||
{groupedErrors.collection}
|
||||
</Typography>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "display",
|
||||
title: "Display",
|
||||
content: (
|
||||
<>
|
||||
<DialogContentText paragraph>
|
||||
Set how this table is displayed to users
|
||||
</DialogContentText>
|
||||
<FormFields
|
||||
{...formFieldsProps}
|
||||
fields={fields.filter((f) => f.step === "display")}
|
||||
customComponents={customComponents}
|
||||
/>
|
||||
</>
|
||||
),
|
||||
optional: false,
|
||||
error: groupedErrors.display,
|
||||
subtitle: groupedErrors.display && (
|
||||
<Typography variant="caption" color="error">
|
||||
{groupedErrors.display}
|
||||
</Typography>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "accessControls",
|
||||
title: "Access controls",
|
||||
content: (
|
||||
<>
|
||||
<DialogContentText paragraph>
|
||||
Set who can view and edit this table. Only ADMIN users
|
||||
can edit table settings or add, edit, and delete
|
||||
columns.
|
||||
</DialogContentText>
|
||||
<FormFields
|
||||
{...formFieldsProps}
|
||||
fields={fields.filter(
|
||||
(f) => f.step === "accessControls"
|
||||
)}
|
||||
customComponents={customComponents}
|
||||
/>
|
||||
</>
|
||||
),
|
||||
optional: false,
|
||||
error: groupedErrors.accessControls,
|
||||
subtitle: groupedErrors.accessControls && (
|
||||
<Typography variant="caption" color="error">
|
||||
{groupedErrors.accessControls}
|
||||
</Typography>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "auditing",
|
||||
title: "Auditing",
|
||||
content: (
|
||||
<>
|
||||
<DialogContentText paragraph>
|
||||
Track when users create or update rows
|
||||
</DialogContentText>
|
||||
<FormFields
|
||||
{...formFieldsProps}
|
||||
fields={fields.filter((f) => f.step === "auditing")}
|
||||
/>
|
||||
</>
|
||||
),
|
||||
optional: true,
|
||||
error: groupedErrors.auditing,
|
||||
subtitle: groupedErrors.auditing && (
|
||||
<Typography variant="caption" color="error">
|
||||
{groupedErrors.auditing}
|
||||
</Typography>
|
||||
),
|
||||
},
|
||||
mode === TableSettingsDialogModes.create
|
||||
? {
|
||||
id: "columns",
|
||||
title: "Columns",
|
||||
content: (
|
||||
<>
|
||||
<DialogContentText paragraph>
|
||||
Initialize table with columns
|
||||
</DialogContentText>
|
||||
<FormFields
|
||||
{...formFieldsProps}
|
||||
fields={fields.filter(
|
||||
(f) => f.step === "columns"
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
),
|
||||
optional: true,
|
||||
error: groupedErrors.columns,
|
||||
subtitle: groupedErrors.columns && (
|
||||
<Typography variant="caption" color="error">
|
||||
{groupedErrors.columns}
|
||||
</Typography>
|
||||
),
|
||||
}
|
||||
: null,
|
||||
].filter(Boolean) as any
|
||||
}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
customComponents={customComponents}
|
||||
values={{ ...data }}
|
||||
onSubmit={handleSubmit}
|
||||
|
||||
Reference in New Issue
Block a user