diff --git a/web/src/components/config-form/ConfigForm.tsx b/web/src/components/config-form/ConfigForm.tsx index 5c13a30b0..9907c1009 100644 --- a/web/src/components/config-form/ConfigForm.tsx +++ b/web/src/components/config-form/ConfigForm.tsx @@ -60,7 +60,7 @@ export function ConfigForm({ advancedFields, disabled = false, readonly = false, - showSubmit = true, + showSubmit = false, className, liveValidate = true, formContext, diff --git a/web/src/components/config-form/sections/AudioSection.tsx b/web/src/components/config-form/sections/AudioSection.tsx index 7d9a94455..347f5f94b 100644 --- a/web/src/components/config-form/sections/AudioSection.tsx +++ b/web/src/components/config-form/sections/AudioSection.tsx @@ -21,6 +21,11 @@ export const AudioSection = createConfigSection({ }, hiddenFields: ["enabled_in_config"], advancedFields: ["min_volume", "max_not_heard", "num_threads"], + uiSchema: { + listen: { + "ui:widget": "audioLabels", + }, + }, }, }); diff --git a/web/src/components/config-form/sections/ObjectsSection.tsx b/web/src/components/config-form/sections/ObjectsSection.tsx index 870660f17..e4953958d 100644 --- a/web/src/components/config-form/sections/ObjectsSection.tsx +++ b/web/src/components/config-form/sections/ObjectsSection.tsx @@ -12,7 +12,12 @@ export const ObjectsSection = createConfigSection({ tracking: ["track", "alert", "detect"], filtering: ["filters"], }, - hiddenFields: ["enabled_in_config", "mask", "raw_mask"], + hiddenFields: [ + "enabled_in_config", + "mask", + "raw_mask", + "genai.enabled_in_config", + ], advancedFields: ["filters"], uiSchema: { track: { @@ -34,6 +39,9 @@ export const ObjectsSection = createConfigSection({ suppressMultiSchema: true, }, }, + enabled_in_config: { + "ui:widget": "hidden", + }, }, }, }, diff --git a/web/src/components/config-form/sections/RecordSection.tsx b/web/src/components/config-form/sections/RecordSection.tsx index 3263f0464..2e2256842 100644 --- a/web/src/components/config-form/sections/RecordSection.tsx +++ b/web/src/components/config-form/sections/RecordSection.tsx @@ -21,7 +21,7 @@ export const RecordSection = createConfigSection({ retention: ["continuous", "motion"], events: ["alerts", "detections"], }, - hiddenFields: ["enabled_in_config"], + hiddenFields: ["enabled_in_config", "sync_recordings"], advancedFields: ["expire_interval", "preview", "export"], }, }); diff --git a/web/src/components/config-form/theme/frigateTheme.ts b/web/src/components/config-form/theme/frigateTheme.ts index cd5d8cde0..ddf74f45a 100644 --- a/web/src/components/config-form/theme/frigateTheme.ts +++ b/web/src/components/config-form/theme/frigateTheme.ts @@ -20,6 +20,7 @@ import { ColorWidget } from "./widgets/ColorWidget"; import { TextareaWidget } from "./widgets/TextareaWidget"; import { SwitchesWidget } from "./widgets/SwitchesWidget"; import { ObjectLabelSwitchesWidget } from "./widgets/ObjectLabelSwitchesWidget"; +import { AudioLabelSwitchesWidget } from "./widgets/AudioLabelSwitchesWidget"; import { ZoneSwitchesWidget } from "./widgets/ZoneSwitchesWidget"; import { FieldTemplate } from "./templates/FieldTemplate"; @@ -29,7 +30,6 @@ import { BaseInputTemplate } from "./templates/BaseInputTemplate"; import { DescriptionFieldTemplate } from "./templates/DescriptionFieldTemplate"; import { TitleFieldTemplate } from "./templates/TitleFieldTemplate"; import { ErrorListTemplate } from "./templates/ErrorListTemplate"; -import { SubmitButton } from "./templates/SubmitButton"; import { MultiSchemaFieldTemplate } from "./templates/MultiSchemaFieldTemplate"; export interface FrigateTheme { @@ -58,6 +58,7 @@ export const frigateTheme: FrigateTheme = { textarea: TextareaWidget, switches: SwitchesWidget, objectLabels: ObjectLabelSwitchesWidget, + audioLabels: AudioLabelSwitchesWidget, zoneNames: ZoneSwitchesWidget, }, templates: { @@ -72,7 +73,6 @@ export const frigateTheme: FrigateTheme = { MultiSchemaFieldTemplate: MultiSchemaFieldTemplate, ButtonTemplates: { ...defaultRegistry.templates.ButtonTemplates, - SubmitButton: SubmitButton, }, }, fields: { diff --git a/web/src/components/config-form/theme/templates/SubmitButton.tsx b/web/src/components/config-form/theme/templates/SubmitButton.tsx deleted file mode 100644 index cc098e098..000000000 --- a/web/src/components/config-form/theme/templates/SubmitButton.tsx +++ /dev/null @@ -1,27 +0,0 @@ -// Submit Button Template -import type { SubmitButtonProps } from "@rjsf/utils"; -import { Button } from "@/components/ui/button"; -import { useTranslation } from "react-i18next"; -import { LuSave } from "react-icons/lu"; - -export function SubmitButton(props: SubmitButtonProps) { - const { uiSchema } = props; - const { t } = useTranslation(["common"]); - - const shouldHide = uiSchema?.["ui:submitButtonOptions"]?.norender === true; - - if (shouldHide) { - return null; - } - - const submitText = - (uiSchema?.["ui:options"]?.submitText as string) || - t("save", { ns: "common" }); - - return ( - - ); -} diff --git a/web/src/components/config-form/theme/widgets/AudioLabelSwitchesWidget.tsx b/web/src/components/config-form/theme/widgets/AudioLabelSwitchesWidget.tsx new file mode 100644 index 000000000..209233bed --- /dev/null +++ b/web/src/components/config-form/theme/widgets/AudioLabelSwitchesWidget.tsx @@ -0,0 +1,48 @@ +// Object Label Switches Widget - For selecting objects via switches +import type { WidgetProps } from "@rjsf/utils"; +import { SwitchesWidget } from "./SwitchesWidget"; +import type { FormContext } from "./SwitchesWidget"; +import { getTranslatedLabel } from "@/utils/i18n"; + +function getAudioLabels(context: FormContext): string[] { + let cameraLabels: string[] = []; + let globalLabels: string[] = []; + + if (context) { + // context.cameraValue and context.globalValue should be the entire objects section + const trackValue = context.cameraValue?.listen; + if (Array.isArray(trackValue)) { + cameraLabels = trackValue.filter( + (item): item is string => typeof item === "string", + ); + } + + const globalTrackValue = context.globalValue?.listen; + if (Array.isArray(globalTrackValue)) { + globalLabels = globalTrackValue.filter( + (item): item is string => typeof item === "string", + ); + } + } + + const sourceLabels = cameraLabels.length > 0 ? cameraLabels : globalLabels; + return [...sourceLabels].sort(); +} + +function getAudioLabelDisplayName(label: string): string { + return getTranslatedLabel(label, "audio"); +} + +export function AudioLabelSwitchesWidget(props: WidgetProps) { + return ( + + ); +} diff --git a/web/src/views/settings/GlobalConfigView.tsx b/web/src/views/settings/GlobalConfigView.tsx index dd0430401..e25affa68 100644 --- a/web/src/views/settings/GlobalConfigView.tsx +++ b/web/src/views/settings/GlobalConfigView.tsx @@ -14,7 +14,6 @@ import { MotionSection } from "@/components/config-form/sections/MotionSection"; import { ObjectsSection } from "@/components/config-form/sections/ObjectsSection"; import { ReviewSection } from "@/components/config-form/sections/ReviewSection"; import { AudioSection } from "@/components/config-form/sections/AudioSection"; -import { NotificationsSection } from "@/components/config-form/sections/NotificationsSection"; import { LiveSection } from "@/components/config-form/sections/LiveSection"; import { TimestampSection } from "@/components/config-form/sections/TimestampSection"; import type { RJSFSchema } from "@rjsf/utils"; @@ -46,11 +45,6 @@ const sharedSections = [ }, { key: "review", i18nNamespace: "config/review", component: ReviewSection }, { key: "audio", i18nNamespace: "config/audio", component: AudioSection }, - { - key: "notifications", - i18nNamespace: "config/notifications", - component: NotificationsSection, - }, { key: "live", i18nNamespace: "config/live", component: LiveSection }, { key: "timestamp_style", @@ -127,7 +121,6 @@ const globalSectionConfigs: Record< "trusted_proxies", "hash_iterations", "roles", - "admin_first_time_login", ], }, tls: { @@ -330,21 +323,6 @@ const globalSectionConfigs: Record< fieldOrder: [], advancedFields: [], }, - camera_groups: { - i18nNamespace: "config/camera_groups", - fieldOrder: ["cameras", "icon", "order"], - advancedFields: [], - }, - safe_mode: { - i18nNamespace: "config/safe_mode", - fieldOrder: [], - advancedFields: [], - }, - version: { - i18nNamespace: "config/version", - fieldOrder: [], - advancedFields: [], - }, }; // System sections (global only) @@ -364,9 +342,6 @@ const systemSections = [ "model", "classification", "go2rtc", - "camera_groups", - "safe_mode", - "version", ]; // Integration sections (global only)