More SmartForms

This commit is contained in:
Stan Wohlwend 2024-05-18 11:26:54 +02:00
parent baa8d70a14
commit 04cc355087
4 changed files with 39 additions and 47 deletions

View File

@ -5,7 +5,7 @@ import { useAdminApp } from "../use-admin-app";
import { Button } from "@/components/ui/button";
import { PermissionListField } from "@/components/permission-field";
import { PageLayout } from "../page-layout";
import { FormDialog } from "@/components/form-dialog";
import { FormDialog, SmartFormDialog } from "@/components/form-dialog";
import { InputField } from "@/components/form-fields";
import { TeamPermissionTable } from "@/components/data-table/team-permission-table";
@ -43,28 +43,21 @@ function CreateDialog(props: {
const permissions = stackAdminApp.usePermissionDefinitions();
const formSchema = yup.object({
id: yup.string().required().notOneOf(permissions.map((p) => p.id), "ID already exists"),
description: yup.string(),
containPermissionIds: yup.array().of(yup.string().required()).required(),
id: yup.string().required().notOneOf(permissions.map((p) => p.id), "ID already exists").label("ID"),
description: yup.string().label("Description"),
containPermissionIds: yup.array().of(yup.string().required()).required().default([]).meta({
stackFormFieldRender: (props) => (
<PermissionListField {...props} permissions={permissions} type="new" />
),
}),
});
const defaultValues = {
containPermissionIds: [],
};
return <FormDialog
return <SmartFormDialog
open={props.open}
onOpenChange={props.onOpenChange}
title="Create Permission"
formSchema={formSchema}
defaultValues={defaultValues}
okButton={{ label: "Save" }}
render={(form) => (
<>
<InputField control={form.control} label="ID" name="id" />
<InputField control={form.control} label="Description" name="description" />
<PermissionListField control={form.control} name="containPermissionIds" permissions={permissions} type="new" />
</>
)}
onSubmit={async (values) => {
await stackAdminApp.createPermissionDefinition({
id: values.id,
@ -75,4 +68,4 @@ function CreateDialog(props: {
}}
cancelButton
/>;
}
}

View File

@ -6,7 +6,7 @@ import { DataTableColumnHeader } from "./elements/column-header";
import { DataTable } from "./elements/data-table";
import { ActionCell, BadgeCell, TextCell } from "./elements/cells";
import { SearchToolbarItem } from "./elements/toolbar-items";
import { FormDialog } from "../form-dialog";
import { FormDialog, SmartFormDialog } from "../form-dialog";
import { InputField } from "../form-fields";
import { ActionDialog } from "../action-dialog";
import { useAdminApp } from "@/app/(main)/(protected)/projects/[projectId]/use-admin-app";
@ -34,31 +34,29 @@ function EditDialog(props: {
}
const formSchema = yup.object({
id: yup.string().required().notOneOf(permissions.map((p) => p.id).filter(p => p !== props.selectedPermissionId), "ID already exists"),
description: yup.string(),
containPermissionIds: yup.array().of(yup.string().required()).required(),
});
return <FormDialog
open={props.open}
onOpenChange={props.onOpenChange}
title="Edit Permission"
formSchema={formSchema}
defaultValues={currentPermission}
okButton={{ label: "Save" }}
render={(form) => (
<>
<InputField control={form.control} label="ID" name="id" />
<InputField control={form.control} label="Description" name="description" />
id: yup.string()
.required()
.notOneOf(permissions.map((p) => p.id).filter(p => p !== props.selectedPermissionId), "ID already exists")
.label("ID"),
description: yup.string().label("Description"),
containPermissionIds: yup.array().of(yup.string().required()).required().meta({
stackFormFieldRender: (innerProps) => (
<PermissionListField
control={form.control}
name="containPermissionIds"
{...innerProps}
permissions={permissions}
type="edit"
selectedPermissionId={props.selectedPermissionId}
/>
</>
)}
),
}),
}).default(currentPermission);
return <SmartFormDialog
open={props.open}
onOpenChange={props.onOpenChange}
title="Edit Permission"
formSchema={formSchema}
okButton={{ label: "Save" }}
onSubmit={async (values) => {
await stackAdminApp.updatePermissionDefinition(props.selectedPermissionId, values);
}}

View File

@ -182,11 +182,7 @@ export function PermissionListField<F extends FieldValues>(props: {
);
const inheritedFrom = contain && ancestors.length > 0 && `(from ${ancestors.join(', ')})`;
return (
<label className="flex flex-row items-center justify-between -my-3 py-3" key={permission.id}>
<FieldLabel>
{permission.id}
{inheritedFrom && <span className="text-gray-500"> {inheritedFrom}</span>}
</FieldLabel>
<label className="flex flex-row justify-start gap-2 -my-3 py-3" key={permission.id}>
<FormControl>
<Checkbox
checked={selected}
@ -207,6 +203,10 @@ export function PermissionListField<F extends FieldValues>(props: {
}}
/>
</FormControl>
<FieldLabel>
{permission.id}
{inheritedFrom && <span className="text-gray-500"> {inheritedFrom}</span>}
</FieldLabel>
<FormMessage />
</label>
);

View File

@ -45,12 +45,13 @@ export function SmartForm<S extends yup.ObjectSchema<any, any, any, any>>(props:
}, [props, form]);
const details = props.formSchema.describe();
const defaults = props.formSchema.getDefault();
return (
<Form {...form}>
<form onSubmit={(e) => runAsynchronously(handleSubmit(e))} id={props.formId} className="space-y-4">
{Object.entries(details.fields).map(([fieldId, field]) => (
<SmartFormField key={fieldId} id={fieldId} description={field} form={form} disabled={isSubmitting} />
<SmartFormField key={fieldId} id={fieldId} description={field} form={form} disabled={isSubmitting} defaultValue={defaults[fieldId]} />
))}
</form>
</Form>
@ -63,6 +64,7 @@ function SmartFormField(props: {
description: yup.SchemaFieldDescription,
form: ReturnType<typeof useForm>,
disabled: boolean,
defaultValue: unknown,
}) {
const usualProps = {
control: props.form.control,
@ -71,10 +73,9 @@ function SmartFormField(props: {
disabled: props.disabled,
required: !("optional" in props.description && props.description.optional),
placeholder: "meta" in props.description && props.description.meta?.stackFormFieldPlaceholder !== undefined ? props.description.meta?.stackFormFieldPlaceholder :
"default" in props.description ? (typeof props.description.default === "string" ? `Eg.: ${props.description.default}` : undefined) : undefined,
defaultValue: "default" in props.description ? props.description.default : undefined,
typeof props.defaultValue === "string" ? `Eg.: ${props.defaultValue}` : undefined,
defaultValue: props.defaultValue,
};
console.log(usualProps, props);
if ("meta" in props.description) {
const meta = props.description.meta;