public commit

This commit is contained in:
dswbx
2024-11-16 12:01:47 +01:00
commit 90f80c4280
582 changed files with 49291 additions and 0 deletions

View File

@@ -0,0 +1,170 @@
import { useDisclosure, useFocusTrap } from "@mantine/hooks";
import type { TObject } from "core/utils";
import { omit } from "lodash-es";
import { useRef, useState } from "react";
import { TbCirclePlus, TbVariable } from "react-icons/tb";
import { useLocation } from "wouter";
import { useBknd } from "../../../client/BkndProvider";
import { Button } from "../../../components/buttons/Button";
import * as Formy from "../../../components/form/Formy";
import {
JsonSchemaForm,
type JsonSchemaFormRef
} from "../../../components/form/json-schema/JsonSchemaForm";
import { Dropdown } from "../../../components/overlay/Dropdown";
import { Modal } from "../../../components/overlay/Modal";
export type SettingsNewModalProps = {
schema: TObject;
uiSchema?: object;
anyOfValues?: Record<string, { label: string; icon?: any }>;
path: string[];
prefixPath: string;
generateKey?: string | ((formData: any) => string);
};
export const SettingNewModal = ({
schema,
uiSchema = {},
anyOfValues,
path,
prefixPath,
generateKey
}: SettingsNewModalProps) => {
const [location, navigate] = useLocation();
const [formSchema, setFormSchema] = useState(schema);
const [submitting, setSubmitting] = useState(false);
const { actions } = useBknd();
const [opened, { open, close }] = useDisclosure(false);
const isGeneratedKey = generateKey !== undefined;
const isStaticGeneratedKey = typeof generateKey === "string";
const [newKey, setNewKey] = useState(isStaticGeneratedKey ? generateKey : "");
const focusTrap = useFocusTrap(!isGeneratedKey);
const formRef = useRef<JsonSchemaFormRef>(null);
const isAnyOf = "anyOf" in schema;
function handleFormChange(data) {
if (generateKey && typeof generateKey === "function") {
handleKeyNameChange({
target: {
value: generateKey(data)
}
});
}
console.log("form change", data);
}
function handleKeyNameChange(e) {
const v = String(e.target.value);
if (v.length > 0 && !/^[a-zA-Z_][a-zA-Z0-9_ ]*$/.test(v)) {
console.log("no match", v);
return;
}
setNewKey(v.toLowerCase().replace(/ /g, "_").replace(/__+/g, "_"));
}
async function handleSave() {
if (formRef.current?.validateForm()) {
setSubmitting(true);
const data = formRef.current?.formData();
const [module, ...restOfPath] = path;
const addPath = [...restOfPath, newKey].join(".");
if (await actions.add(module as any, addPath, data)) {
navigate(prefixPath + newKey, {
replace: true
});
} else {
setSubmitting(false);
}
}
console.log("valid?", formRef.current?.validateForm());
console.log("data", newKey, formRef.current?.formData());
}
const anyOfItems = isAnyOf
? (schema.anyOf as any[])!.map((item) => {
const key = item.title;
const label = anyOfValues?.[key]?.label || key;
const icon = anyOfValues?.[key]?.icon;
return {
label,
icon,
onClick: () => {
setFormSchema(item);
open();
}
};
})
: [];
return (
<>
<div className="flex flex-row">
{isAnyOf ? (
<Dropdown position="top-start" items={anyOfItems} itemsClassName="gap-3">
<Button>Add new</Button>
</Dropdown>
) : (
<Button onClick={open}>Add new</Button>
)}
</div>
<Modal
open={opened}
allowBackdropClose={false}
onClose={close}
className="min-w-96 w-6/12 mt-[30px] mb-[20px]"
stickToTop
>
<div
className="border border-muted rounded-lg flex flex-col overflow-y-scroll font-normal"
style={{ maxHeight: "calc(100dvh - 100px)" }}
>
<div className="bg-muted py-2 px-4 text-primary/70 font-mono flex flex-row gap-2 items-center">
{[...path, newKey].join(".")}
</div>
<div className="flex flex-row gap-10 sticky top-0 bg-background z-10 p-4 border-b border-muted">
<div className="flex flex-row flex-grow items-center relative">
<Formy.Input
ref={focusTrap}
className="w-full"
placeholder="New unique key..."
onChange={handleKeyNameChange}
value={newKey}
disabled={isGeneratedKey}
/>
{isGeneratedKey && (
<div className="absolute h-full flex items-center z-10 right-3.5 top-0 bottom-0 font-mono font-sm opacity-50">
generated
</div>
)}
</div>
<div className="flex flex-row gap-2">
<Button onClick={close} disabled={submitting}>
Cancel
</Button>
<Button
variant="primary"
onClick={handleSave}
disabled={submitting || newKey.length === 0}
>
Create
</Button>
</div>
</div>
<div className="flex flex-col p-4">
<JsonSchemaForm
ref={formRef}
/* readonly={!editing} */
schema={omit(formSchema, ["title"])}
uiSchema={uiSchema}
onChange={handleFormChange}
className="legacy hide-required-mark fieldset-alternative mute-root"
/>
</div>
</div>
</Modal>
</>
);
};