frigate/web/src/components/config-form/section-configs/objects.ts
Josh Hawkins 4ff7ab96dc
Some checks are pending
CI / AMD64 Build (push) Waiting to run
CI / ARM Build (push) Waiting to run
CI / Jetson Jetpack 6 (push) Waiting to run
CI / AMD64 Extra Build (push) Blocked by required conditions
CI / ARM Extra Build (push) Blocked by required conditions
CI / Synaptics Build (push) Blocked by required conditions
CI / Assemble and push default build (push) Blocked by required conditions
Fixes (#23130)
* respect section hiddenFields when detecting config overrides

* change audio events to audio detection to match docs

* add field messages for object and review genai

* add more config messages

* more messages

* add guard to prevent race when adding camera dynamically

* fix duplicate websocket messages from zombie connection under react strict mode

detach ws event handlers before close() in WsProvider cleanup so a CONNECTING socket's deferred onclose can't schedule a reconnect after the next mount resets the unmounted guard, which was spawning a second live ws and duplicating every message

* fix double event publishes for stationary objects with attributes
2026-05-07 12:23:02 -06:00

169 lines
4.4 KiB
TypeScript

import type { FrigateConfig } from "@/types/frigateConfig";
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}`);
const objects: SectionConfigOverrides = {
base: {
sectionDocs: "/configuration/object_filters",
messages: [
{
key: "detect-disabled",
messageKey: "configMessages.detect.disabled",
severity: "info",
condition: (ctx) =>
ctx.level === "camera" &&
ctx.fullCameraConfig?.detect?.enabled === false,
},
],
fieldMessages: [
{
key: "genai-no-descriptions-provider",
field: "genai.enabled",
messageKey: "configMessages.objects.genaiNoDescriptionsProvider",
severity: "warning",
position: "before",
condition: (ctx) => {
const providers = ctx.fullConfig.genai;
if (!providers || Object.keys(providers).length === 0) return true;
return !Object.values(providers).some((agent) =>
agent.roles?.includes("descriptions"),
);
},
},
],
fieldDocs: {
"filters.min_area": "/configuration/object_filters#object-area",
"filters.max_area": "/configuration/object_filters#object-area",
"filters.min_score": "/configuration/object_filters#minimum-score",
"filters.threshold": "/configuration/object_filters#threshold",
"filters.min_ratio": "/configuration/object_filters/#object-proportions",
"filters.max_ratio": "/configuration/object_filters/#object-proportions",
},
restartRequired: [],
fieldOrder: ["track", "alert", "detect", "filters"],
fieldGroups: {
tracking: ["track", "alert", "detect"],
filtering: ["filters"],
},
hiddenFields: [
"enabled_in_config",
"mask",
"raw_mask",
"genai.enabled_in_config",
"filters.*.mask",
"filters.*.raw_mask",
"filters.mask",
"filters.raw_mask",
hideAttributeFilters,
],
advancedFields: ["genai"],
uiSchema: {
filters: {
"ui:options": {
expandable: false,
},
},
"filters.*.min_area": {
"ui:options": {
suppressMultiSchema: true,
},
},
"filters.*": {
"ui:options": {
additionalPropertyKeyReadonly: true,
},
},
"filters.*.max_area": {
"ui:options": {
suppressMultiSchema: true,
},
},
track: {
"ui:widget": "objectLabels",
"ui:options": {
suppressMultiSchema: true,
},
},
genai: {
objects: {
"ui:widget": "objectLabels",
"ui:options": {
suppressMultiSchema: true,
},
},
prompt: {
"ui:widget": "textarea",
"ui:options": {
size: "full",
},
},
object_prompts: {
additionalProperties: {
"ui:options": {
size: "full",
},
},
},
required_zones: {
"ui:widget": "zoneNames",
"ui:options": {
suppressMultiSchema: true,
},
},
enabled_in_config: {
"ui:widget": "hidden",
},
},
},
},
global: {
restartRequired: [],
hiddenFields: [
"enabled_in_config",
"mask",
"raw_mask",
"genai.enabled_in_config",
"filters.*.mask",
"filters.*.raw_mask",
"filters.mask",
"filters.raw_mask",
"genai.required_zones",
hideAttributeFilters,
],
},
camera: {
restartRequired: [],
},
replay: {
restartRequired: [],
fieldOrder: ["track", "filters"],
fieldGroups: {
tracking: ["track"],
filtering: ["filters"],
},
hiddenFields: [
"enabled_in_config",
"alert",
"detect",
"mask",
"raw_mask",
"genai",
"genai.enabled_in_config",
"filters.*.mask",
"filters.*.raw_mask",
"filters.mask",
"filters.raw_mask",
hideAttributeFilters,
],
advancedFields: [],
},
};
export default objects;