mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-03-10 18:43:09 +03:00
add custom validation and use it for ffmpeg input roles
This commit is contained in:
parent
718757fc60
commit
09ceff9bd8
@ -16,5 +16,6 @@
|
||||
"format": "Invalid format",
|
||||
"additionalProperties": "Unknown property is not allowed",
|
||||
"oneOf": "Must match exactly one of the allowed schemas",
|
||||
"anyOf": "Must match at least one of the allowed schemas"
|
||||
"anyOf": "Must match at least one of the allowed schemas",
|
||||
"ffmpeg.inputs.rolesUnique": "Each role can only be assigned to one input stream."
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// ConfigForm - Main RJSF form wrapper component
|
||||
import Form from "@rjsf/shadcn";
|
||||
import validator from "@rjsf/validator-ajv8";
|
||||
import type { RJSFSchema, UiSchema } from "@rjsf/utils";
|
||||
import type { FormValidation, RJSFSchema, UiSchema } from "@rjsf/utils";
|
||||
import type { IChangeEvent } from "@rjsf/core";
|
||||
import { frigateTheme } from "./theme";
|
||||
import { transformSchema } from "@/lib/config-schema";
|
||||
@ -182,6 +182,11 @@ export interface ConfigFormProps {
|
||||
formContext?: ConfigFormContext;
|
||||
/** i18n namespace for field labels */
|
||||
i18nNamespace?: string;
|
||||
/** Optional custom validation */
|
||||
customValidate?: (
|
||||
formData: unknown,
|
||||
errors: FormValidation,
|
||||
) => FormValidation;
|
||||
}
|
||||
|
||||
export function ConfigForm({
|
||||
@ -202,6 +207,7 @@ export function ConfigForm({
|
||||
liveValidate = true,
|
||||
formContext,
|
||||
i18nNamespace,
|
||||
customValidate,
|
||||
}: ConfigFormProps) {
|
||||
const { t, i18n } = useTranslation([
|
||||
i18nNamespace || "common",
|
||||
@ -319,6 +325,7 @@ export function ConfigForm({
|
||||
liveValidate={liveValidate}
|
||||
formContext={extendedFormContext}
|
||||
transformErrors={errorTransformer}
|
||||
customValidate={customValidate}
|
||||
{...frigateTheme}
|
||||
/>
|
||||
</div>
|
||||
|
||||
47
web/src/components/config-form/section-validations/ffmpeg.ts
Normal file
47
web/src/components/config-form/section-validations/ffmpeg.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import type { FormValidation } from "@rjsf/utils";
|
||||
import type { TFunction } from "i18next";
|
||||
import { isJsonObject } from "@/lib/utils";
|
||||
import type { JsonObject } from "@/types/configForm";
|
||||
|
||||
export function validateFfmpegInputRoles(
|
||||
formData: unknown,
|
||||
errors: FormValidation,
|
||||
t: TFunction,
|
||||
): FormValidation {
|
||||
if (!isJsonObject(formData as JsonObject)) {
|
||||
return errors;
|
||||
}
|
||||
|
||||
const inputs = (formData as JsonObject).inputs;
|
||||
if (!Array.isArray(inputs)) {
|
||||
return errors;
|
||||
}
|
||||
|
||||
const roleCounts = new Map<string, number>();
|
||||
inputs.forEach((input) => {
|
||||
if (!isJsonObject(input) || !Array.isArray(input.roles)) {
|
||||
return;
|
||||
}
|
||||
input.roles.forEach((role) => {
|
||||
if (typeof role !== "string") {
|
||||
return;
|
||||
}
|
||||
roleCounts.set(role, (roleCounts.get(role) || 0) + 1);
|
||||
});
|
||||
});
|
||||
|
||||
const hasDuplicates = Array.from(roleCounts.values()).some(
|
||||
(count) => count > 1,
|
||||
);
|
||||
|
||||
if (hasDuplicates) {
|
||||
const inputsErrors = errors.inputs as {
|
||||
addError?: (message: string) => void;
|
||||
};
|
||||
inputsErrors?.addError?.(
|
||||
t("ffmpeg.inputs.rolesUnique", { ns: "config/validation" }),
|
||||
);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
26
web/src/components/config-form/section-validations/index.ts
Normal file
26
web/src/components/config-form/section-validations/index.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import type { FormValidation } from "@rjsf/utils";
|
||||
import type { TFunction } from "i18next";
|
||||
import { validateFfmpegInputRoles } from "./ffmpeg";
|
||||
|
||||
export type SectionValidation = (
|
||||
formData: unknown,
|
||||
errors: FormValidation,
|
||||
) => FormValidation;
|
||||
|
||||
type SectionValidationOptions = {
|
||||
sectionPath: string;
|
||||
level: "global" | "camera";
|
||||
t: TFunction;
|
||||
};
|
||||
|
||||
export function getSectionValidation({
|
||||
sectionPath,
|
||||
level,
|
||||
t,
|
||||
}: SectionValidationOptions): SectionValidation | undefined {
|
||||
if (sectionPath === "ffmpeg" && level === "camera") {
|
||||
return (formData, errors) => validateFfmpegInputRoles(formData, errors, t);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user