diff --git a/app/src/ui/components/code/JsonEditor.tsx b/app/src/ui/components/code/JsonEditor.tsx index c65e59a..93bb8d1 100644 --- a/app/src/ui/components/code/JsonEditor.tsx +++ b/app/src/ui/components/code/JsonEditor.tsx @@ -1,6 +1,7 @@ import { Suspense, lazy, useState } from "react"; import { twMerge } from "tailwind-merge"; import type { CodeEditorProps } from "./CodeEditor"; +import { useDebouncedCallback } from "@mantine/hooks"; const CodeEditor = lazy(() => import("./CodeEditor")); export type JsonEditorProps = Omit & { @@ -21,13 +22,13 @@ export function JsonEditor({ const [editorValue, setEditorValue] = useState( JSON.stringify(value, null, 2), ); - const handleChange = (given: string) => { + const handleChange = useDebouncedCallback((given: string) => { const value = given === "" ? (emptyAs === "null" ? null : undefined) : given; try { setEditorValue(value); onChange?.(value ? JSON.parse(value) : value); } catch (e) {} - }; + }, 500); const handleBlur = (e) => { setEditorValue(JSON.stringify(value, null, 2)); onBlur?.(e); diff --git a/app/src/ui/routes/auth/auth.roles.edit.$role.tsx b/app/src/ui/routes/auth/auth.roles.edit.$role.tsx index e1be5dd..51d909d 100644 --- a/app/src/ui/routes/auth/auth.roles.edit.$role.tsx +++ b/app/src/ui/routes/auth/auth.roles.edit.$role.tsx @@ -233,15 +233,19 @@ const Permission = ({ permission, index }: { permission: TPermission; index?: nu const { value } = useDerivedFieldContext("permissions", (ctx) => { const v = ctx.value; if (!Array.isArray(v)) return undefined; - return v.find((v) => v && v.permission === permission.name); + const v2 = v.find((v) => v && v.permission === permission.name); + return { + set: !!v2, + policies: (v2?.policies?.length ?? 0) as number, + }; }); const { setValue } = useFormContext(); const [open, setOpen] = useState(false); - const data = value as PermissionData | undefined; - const policiesCount = data?.policies?.length ?? 0; + const policiesCount = value?.policies ?? 0; + const isSet = value?.set ?? false; async function handleSwitch() { - if (data) { + if (isSet) { setValue(path, undefined); setOpen(false); } else { @@ -253,6 +257,10 @@ const Permission = ({ permission, index }: { permission: TPermission; index?: nu } } + function toggleOpen() { + setOpen((o) => !o); + } + return ( <>
setOpen((o) => !o)} + onClick={toggleOpen} />
- + {open && ( @@ -299,13 +307,22 @@ const Permission = ({ permission, index }: { permission: TPermission; index?: nu }; const Policies = ({ path, permission }: { path: string; permission: TPermission }) => { - const { value: _value } = useFormValue(path); - const { setValue, schema: policySchema, lib, deleteValue } = useDerivedFieldContext(path); - const value = _value ?? []; + const { + setValue, + schema: policySchema, + lib, + deleteValue, + value, + } = useDerivedFieldContext(path, ({ value }) => { + return { + policies: (value?.length ?? 0) as number, + }; + }); + const policiesCount = value?.policies ?? 0; function handleAdd() { setValue( - `${path}.${value.length}`, + `${path}.${policiesCount}`, lib.getTemplate(undefined, policySchema!.items, { addOptionalProps: true, }), @@ -317,19 +334,20 @@ const Policies = ({ path, permission }: { path: string; permission: TPermission } return ( -
0 && "gap-8")}> +
0 && "gap-8")}>
- {value.map((policy, i) => ( - - {i > 0 &&
} -
-
- + {policiesCount > 0 && + Array.from({ length: policiesCount }).map((_, i) => ( + + {i > 0 &&
} +
+
+ +
+ handleDelete(i)} size="sm" />
- handleDelete(i)} size="sm" /> -
-
- ))} + + ))}
@@ -366,7 +384,9 @@ const Policy = ({ }: { permission: TPermission; }) => { - const { value } = useFormValue(""); + const { value } = useDerivedFieldContext("", ({ value }) => ({ + effect: (value?.effect ?? "allow") as "allow" | "deny" | "filter", + })); const $bknd = useBknd(); const $permissions = useApiQuery((api) => api.system.permissions(), { use: [mountOnce],