mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-03-10 10:33:11 +03:00
154 lines
4.1 KiB
TypeScript
154 lines
4.1 KiB
TypeScript
// ConfigForm - Main RJSF form wrapper component
|
|
import Form from "@rjsf/core";
|
|
import validator from "@rjsf/validator-ajv8";
|
|
import type { RJSFSchema, UiSchema } from "@rjsf/utils";
|
|
import type { IChangeEvent } from "@rjsf/core";
|
|
import { frigateTheme } from "./theme";
|
|
import { transformSchema } from "@/lib/config-schema";
|
|
import { createErrorTransformer } from "@/lib/config-schema/errorMessages";
|
|
import { useMemo, useCallback } from "react";
|
|
import { useTranslation } from "react-i18next";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
export interface ConfigFormProps {
|
|
/** JSON Schema for the form */
|
|
schema: RJSFSchema;
|
|
/** Current form data */
|
|
formData?: unknown;
|
|
/** Called when form data changes */
|
|
onChange?: (data: unknown) => void;
|
|
/** Called when form is submitted */
|
|
onSubmit?: (data: unknown) => void;
|
|
/** Called when form has errors on submit */
|
|
onError?: (errors: unknown[]) => void;
|
|
/** Additional uiSchema overrides */
|
|
uiSchema?: UiSchema;
|
|
/** Field ordering */
|
|
fieldOrder?: string[];
|
|
/** Field groups for layout */
|
|
fieldGroups?: Record<string, string[]>;
|
|
/** Fields to hide */
|
|
hiddenFields?: string[];
|
|
/** Fields marked as advanced (collapsed by default) */
|
|
advancedFields?: string[];
|
|
/** Whether form is disabled */
|
|
disabled?: boolean;
|
|
/** Whether form is read-only */
|
|
readonly?: boolean;
|
|
/** Whether to show submit button */
|
|
showSubmit?: boolean;
|
|
/** Custom class name */
|
|
className?: string;
|
|
/** Live validation mode */
|
|
liveValidate?: boolean;
|
|
/** Form context passed to all widgets */
|
|
formContext?: Record<string, unknown>;
|
|
/** i18n namespace for field labels */
|
|
i18nNamespace?: string;
|
|
}
|
|
|
|
export function ConfigForm({
|
|
schema,
|
|
formData,
|
|
onChange,
|
|
onSubmit,
|
|
onError,
|
|
uiSchema: customUiSchema,
|
|
fieldOrder,
|
|
fieldGroups,
|
|
hiddenFields,
|
|
advancedFields,
|
|
disabled = false,
|
|
readonly = false,
|
|
showSubmit = false,
|
|
className,
|
|
liveValidate = true,
|
|
formContext,
|
|
i18nNamespace,
|
|
}: ConfigFormProps) {
|
|
const { t, i18n } = useTranslation([
|
|
i18nNamespace || "common",
|
|
"views/settings",
|
|
"config/validation",
|
|
]);
|
|
|
|
// Determine which fields to hide based on advanced toggle
|
|
const effectiveHiddenFields = useMemo(() => {
|
|
return hiddenFields;
|
|
}, [hiddenFields]);
|
|
|
|
// Transform schema and generate uiSchema
|
|
const { schema: transformedSchema, uiSchema: generatedUiSchema } = useMemo(
|
|
() =>
|
|
transformSchema(schema, {
|
|
fieldOrder,
|
|
hiddenFields: effectiveHiddenFields,
|
|
advancedFields: advancedFields,
|
|
i18nNamespace,
|
|
}),
|
|
[schema, fieldOrder, effectiveHiddenFields, advancedFields, i18nNamespace],
|
|
);
|
|
|
|
// Merge generated uiSchema with custom overrides
|
|
const finalUiSchema = useMemo(
|
|
() => ({
|
|
...generatedUiSchema,
|
|
"ui:groups": fieldGroups,
|
|
...customUiSchema,
|
|
"ui:submitButtonOptions": showSubmit
|
|
? { norender: false }
|
|
: { norender: true },
|
|
}),
|
|
[generatedUiSchema, customUiSchema, showSubmit, fieldGroups],
|
|
);
|
|
|
|
// Create error transformer for user-friendly error messages
|
|
const errorTransformer = useMemo(() => createErrorTransformer(i18n), [i18n]);
|
|
|
|
const handleChange = useCallback(
|
|
(e: IChangeEvent) => {
|
|
onChange?.(e.formData);
|
|
},
|
|
[onChange],
|
|
);
|
|
|
|
const handleSubmit = useCallback(
|
|
(e: IChangeEvent) => {
|
|
onSubmit?.(e.formData);
|
|
},
|
|
[onSubmit],
|
|
);
|
|
|
|
// Extended form context with i18n info
|
|
const extendedFormContext = useMemo(
|
|
() => ({
|
|
...formContext,
|
|
i18nNamespace,
|
|
t,
|
|
}),
|
|
[formContext, i18nNamespace, t],
|
|
);
|
|
|
|
return (
|
|
<div className={cn("config-form", className)}>
|
|
<Form
|
|
schema={transformedSchema}
|
|
uiSchema={finalUiSchema}
|
|
formData={formData}
|
|
validator={validator}
|
|
onChange={handleChange}
|
|
onSubmit={handleSubmit}
|
|
onError={onError}
|
|
disabled={disabled}
|
|
readonly={readonly}
|
|
liveValidate={liveValidate}
|
|
formContext={extendedFormContext}
|
|
transformErrors={errorTransformer}
|
|
{...frigateTheme}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default ConfigForm;
|