extend schema modification

This commit is contained in:
Josh Hawkins 2026-05-19 08:12:02 -05:00
parent 702cc7133d
commit 1b3fb08306
2 changed files with 69 additions and 10 deletions

View File

@ -1,12 +1,36 @@
import type { FrigateConfig } from "@/types/frigateConfig";
import type { HiddenFieldContext } from "@/types/configForm";
import type { SectionConfigOverrides } from "./types";
// Attribute labels (face, license_plate, Frigate+ couriers like DHL/Amazon,
// etc.) are populated into objects.filters by the backend even when the
// model can't actually detect them. They aren't user-settable, so hide any
// `filters.<attr>` patterns from forms and override comparisons.
const hideAttributeFilters = (config: FrigateConfig): string[] =>
(config.model?.all_attributes ?? []).map((attr) => `filters.${attr}`);
// etc.) are populated into objects.filters by the backend for every
// attribute the model knows about. Hide the filter collapsible for an
// attribute unless it's in the effective objects.track list at this scope.
// When an attribute IS tracked, only a subset of fields are exposed — see the
// schema-modification path in modifySchemaForSection (objects branch) which
// promotes tracked attribute keys to explicit `properties` with a
// restricted FilterConfig shape so RJSF renders just that one field.
const hideAttributeFilters = ({
fullConfig,
fullCameraConfig,
level,
formData,
}: HiddenFieldContext): string[] => {
const trackFromForm = Array.isArray(
(formData as { track?: unknown } | undefined)?.track,
)
? (formData as { track: string[] }).track
: undefined;
const track =
trackFromForm ??
(level !== "global" ? fullCameraConfig?.objects?.track : undefined) ??
fullConfig.objects?.track ??
[];
return (fullConfig.model?.all_attributes ?? [])
.filter((attr) => !track.includes(attr))
.map((attr) => `filters.${attr}`);
};
const objects: SectionConfigOverrides = {
base: {

View File

@ -308,11 +308,30 @@ export function ConfigSection({
// Get section schema using cached hook
const sectionSchema = useSectionSchema(sectionPath, effectiveLevel);
// Apply special case handling for sections with problematic schema defaults
// Apply special case handling for sections with problematic schema defaults.
// The HiddenFieldContext is built from `config` (saved state) only — not the
// in-flight raw section value — because the schema is computed before
// rawFormData is derived. The objects-branch fallback in
// modifySchemaForSection reads `track` from fullCameraConfig / fullConfig.
const modifiedSchema = useMemo(
() =>
modifySchemaForSection(sectionPath, level, sectionSchema ?? undefined),
[sectionPath, level, sectionSchema],
modifySchemaForSection(
sectionPath,
level,
sectionSchema ?? undefined,
config
? {
fullConfig: config,
fullCameraConfig:
effectiveLevel === "camera" && cameraName
? config.cameras?.[cameraName]
: undefined,
level,
cameraName,
}
: undefined,
),
[sectionPath, level, sectionSchema, config, effectiveLevel, cameraName],
);
// Get override status (camera vs global)
@ -384,7 +403,19 @@ export function ConfigSection({
// When editing a profile, hide fields that require a restart since they
// cannot take effect via profile switching alone.
const effectiveHiddenFields = useMemo(() => {
const base = resolveHiddenFieldEntries(sectionConfig.hiddenFields, config);
const ctx = config
? {
fullConfig: config,
fullCameraConfig:
effectiveLevel === "camera" && cameraName
? config.cameras?.[cameraName]
: undefined,
level,
cameraName,
formData: rawFormData,
}
: undefined;
const base = resolveHiddenFieldEntries(sectionConfig.hiddenFields, ctx);
if (!profileName || !sectionConfig.restartRequired?.length) {
return base;
}
@ -394,6 +425,10 @@ export function ConfigSection({
sectionConfig.hiddenFields,
sectionConfig.restartRequired,
config,
effectiveLevel,
cameraName,
level,
rawFormData,
]);
const sanitizeSectionData = useCallback(