frigate/web/src/views/settings/CameraManagementView.tsx

1078 lines
34 KiB
TypeScript
Raw Normal View History

import Heading from "@/components/ui/heading";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
Full UI configuration (#22151) * use react-jsonschema-form for UI config * don't use properties wrapper when generating config i18n json * configure for full i18n support * section fields * add descriptions to all fields for i18n * motion i18n * fix nullable fields * sanitize internal fields * add switches widgets and use friendly names * fix nullable schema entries * ensure update_topic is added to api calls this needs further backend implementation to work correctly * add global sections, camera config overrides, and reset button * i18n * add reset logic to global config view * tweaks * fix sections and live validation * fix validation for schema objects that can be null * generic and custom per-field validation * improve generic error validation messages * remove show advanced fields switch * tweaks * use shadcn theme * fix array field template * i18n tweaks * remove collapsible around root section * deep merge schema for advanced fields * add array field item template and fix ffmpeg section * add missing i18n keys * tweaks * comment out api call for testing * add config groups as a separate i18n namespace * add descriptions to all pydantic fields * make titles more concise * new titles as i18n * update i18n config generation script to use json schema * tweaks * tweaks * rebase * clean up * form tweaks * add wildcards and fix object filter fields * add field template for additionalproperties schema objects * improve typing * add section description from schema and clarify global vs camera level descriptions * separate and consolidate global and camera i18n namespaces * clean up now obsolete namespaces * tweaks * refactor sections and overrides * add ability to render components before and after fields * fix titles * chore(sections): remove legacy single-section components replaced by template * refactor configs to use individual files with a template * fix review description * apply hidden fields after ui schema * move util * remove unused i18n * clean up error messages * fix fast refresh * add custom validation and use it for ffmpeg input roles * update nav tree * remove unused * re-add override and modified indicators * mark pending changes and add confirmation dialog for resets * fix red unsaved dot * tweaks * add docs links, readonly keys, and restart required per field * add special case and comments for global motion section * add section form special cases * combine review sections * tweaks * add audio labels endpoint * add audio label switches and input to filter list * fix type * remove key from config when resetting to default/global * don't show description for new key/val fields * tweaks * spacing tweaks * add activity indicator and scrollbar tweaks * add docs to filter fields * wording changes * fix global ffmpeg section * add review classification zones to review form * add backend endpoint and frontend widget for ffmpeg presets and manual args * improve wording * hide descriptions for additional properties arrays * add warning log about incorrectly nested model config * spacing and language tweaks * fix i18n keys * networking section docs and description * small wording tweaks * add layout grid field * refactor with shared utilities * field order * add individual detectors to schema add detector titles and descriptions (docstrings in pydantic are used for descriptions) and add i18n keys to globals * clean up detectors section and i18n * don't save model config back to yaml when saving detectors * add full detectors config to api model dump works around the way we use detector plugins so we can have the full detector config for the frontend * add restart button to toast when restart is required * add ui option to remove inner cards * fix buttons * section tweaks * don't zoom into text on mobile * make buttons sticky at bottom of sections * small tweaks * highlight label of changed fields * add null to enum list when unwrapping * refactor to shared utils and add save all button * add undo all button * add RJSF to dictionary * consolidate utils * preserve form data when changing cameras * add mono fonts * add popover to show what fields will be saved * fix mobile menu not re-rendering with unsaved dots * tweaks * fix logger and env vars config section saving use escaped periods in keys to retain them in the config file (eg "frigate.embeddings") * add timezone widget * role map field with validation * fix validation for model section * add another hidden field * add footer message for required restart * use rjsf for notifications view * fix config saving * add replace rules field * default column layout and add field sizing * clean up field template * refactor profile settings to match rjsf forms * tweaks * refactor frigate+ view and make tweaks to sections * show frigate+ model info in detection model settings when using a frigate+ model * update restartRequired for all fields * fix restart fields * tweaks and add ability enable disabled cameras more backend changes required * require restart when enabling camera that is disabled in config * disable save when form is invalid * refactor ffmpeg section for readability * change label * clean up camera inputs fields * misc tweaks to ffmpeg section - add raw paths endpoint to ensure credentials get saved - restart required tooltip * maintenance settings tweaks * don't mutate with lodash * fix description re-rendering for nullable object fields * hide reindex field * update rjsf * add frigate+ description to settings pane * disable save all when any section is invalid * show translated field name in validation error pane * clean up * remove unused * fix genai merge * fix genai
2026-02-27 18:55:36 +03:00
import {
CONTROL_COLUMN_CLASS_NAME,
SettingsGroupCard,
SPLIT_ROW_CLASS_NAME,
} from "@/components/card/SettingsGroupCard";
import { toast } from "sonner";
import { Toaster } from "@/components/ui/sonner";
import { Button } from "@/components/ui/button";
import useSWR from "swr";
import { FrigateConfig } from "@/types/frigateConfig";
import { useTranslation } from "react-i18next";
import CameraEditForm from "@/components/settings/CameraEditForm";
import CameraWizardDialog from "@/components/settings/CameraWizardDialog";
import DeleteCameraDialog from "@/components/overlay/dialog/DeleteCameraDialog";
import {
LuCheck,
LuExternalLink,
LuGripVertical,
LuPencil,
LuPlus,
LuTrash2,
} from "react-icons/lu";
import { Reorder, useDragControls } from "framer-motion";
import { IoMdArrowRoundBack } from "react-icons/io";
import { Link } from "react-router-dom";
import { useDocDomain } from "@/hooks/use-doc-domain";
import { isDesktop } from "react-device-detect";
import { CameraNameLabel } from "@/components/camera/FriendlyNameLabel";
import { Switch } from "@/components/ui/switch";
import { Trans } from "react-i18next";
Full UI configuration (#22151) * use react-jsonschema-form for UI config * don't use properties wrapper when generating config i18n json * configure for full i18n support * section fields * add descriptions to all fields for i18n * motion i18n * fix nullable fields * sanitize internal fields * add switches widgets and use friendly names * fix nullable schema entries * ensure update_topic is added to api calls this needs further backend implementation to work correctly * add global sections, camera config overrides, and reset button * i18n * add reset logic to global config view * tweaks * fix sections and live validation * fix validation for schema objects that can be null * generic and custom per-field validation * improve generic error validation messages * remove show advanced fields switch * tweaks * use shadcn theme * fix array field template * i18n tweaks * remove collapsible around root section * deep merge schema for advanced fields * add array field item template and fix ffmpeg section * add missing i18n keys * tweaks * comment out api call for testing * add config groups as a separate i18n namespace * add descriptions to all pydantic fields * make titles more concise * new titles as i18n * update i18n config generation script to use json schema * tweaks * tweaks * rebase * clean up * form tweaks * add wildcards and fix object filter fields * add field template for additionalproperties schema objects * improve typing * add section description from schema and clarify global vs camera level descriptions * separate and consolidate global and camera i18n namespaces * clean up now obsolete namespaces * tweaks * refactor sections and overrides * add ability to render components before and after fields * fix titles * chore(sections): remove legacy single-section components replaced by template * refactor configs to use individual files with a template * fix review description * apply hidden fields after ui schema * move util * remove unused i18n * clean up error messages * fix fast refresh * add custom validation and use it for ffmpeg input roles * update nav tree * remove unused * re-add override and modified indicators * mark pending changes and add confirmation dialog for resets * fix red unsaved dot * tweaks * add docs links, readonly keys, and restart required per field * add special case and comments for global motion section * add section form special cases * combine review sections * tweaks * add audio labels endpoint * add audio label switches and input to filter list * fix type * remove key from config when resetting to default/global * don't show description for new key/val fields * tweaks * spacing tweaks * add activity indicator and scrollbar tweaks * add docs to filter fields * wording changes * fix global ffmpeg section * add review classification zones to review form * add backend endpoint and frontend widget for ffmpeg presets and manual args * improve wording * hide descriptions for additional properties arrays * add warning log about incorrectly nested model config * spacing and language tweaks * fix i18n keys * networking section docs and description * small wording tweaks * add layout grid field * refactor with shared utilities * field order * add individual detectors to schema add detector titles and descriptions (docstrings in pydantic are used for descriptions) and add i18n keys to globals * clean up detectors section and i18n * don't save model config back to yaml when saving detectors * add full detectors config to api model dump works around the way we use detector plugins so we can have the full detector config for the frontend * add restart button to toast when restart is required * add ui option to remove inner cards * fix buttons * section tweaks * don't zoom into text on mobile * make buttons sticky at bottom of sections * small tweaks * highlight label of changed fields * add null to enum list when unwrapping * refactor to shared utils and add save all button * add undo all button * add RJSF to dictionary * consolidate utils * preserve form data when changing cameras * add mono fonts * add popover to show what fields will be saved * fix mobile menu not re-rendering with unsaved dots * tweaks * fix logger and env vars config section saving use escaped periods in keys to retain them in the config file (eg "frigate.embeddings") * add timezone widget * role map field with validation * fix validation for model section * add another hidden field * add footer message for required restart * use rjsf for notifications view * fix config saving * add replace rules field * default column layout and add field sizing * clean up field template * refactor profile settings to match rjsf forms * tweaks * refactor frigate+ view and make tweaks to sections * show frigate+ model info in detection model settings when using a frigate+ model * update restartRequired for all fields * fix restart fields * tweaks and add ability enable disabled cameras more backend changes required * require restart when enabling camera that is disabled in config * disable save when form is invalid * refactor ffmpeg section for readability * change label * clean up camera inputs fields * misc tweaks to ffmpeg section - add raw paths endpoint to ensure credentials get saved - restart required tooltip * maintenance settings tweaks * don't mutate with lodash * fix description re-rendering for nullable object fields * hide reindex field * update rjsf * add frigate+ description to settings pane * disable save all when any section is invalid * show translated field name in validation error pane * clean up * remove unused * fix genai merge * fix genai
2026-02-27 18:55:36 +03:00
import { useEnabledState, useRestart } from "@/api/ws";
import { Label } from "@/components/ui/label";
import axios from "axios";
import ActivityIndicator from "@/components/indicators/activity-indicator";
import RestartDialog from "@/components/overlay/dialog/RestartDialog";
import RestartRequiredIndicator from "@/components/indicators/RestartRequiredIndicator";
import TextEntryDialog from "@/components/overlay/dialog/TextEntryDialog";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
Camera profile support (#22482) * add CameraProfileConfig model for named config overrides * add profiles field to CameraConfig * add active_profile field to FrigateConfig Runtime-only field excluded from YAML serialization, tracks which profile is currently active. * add ProfileManager for profile activation and persistence Handles snapshotting base configs, applying profile overrides via deep_merge + apply_section_update, publishing ZMQ updates, and persisting active profile to /config/.active_profile. * add profile API endpoints (GET /profiles, GET/PUT /profile) * add MQTT and dispatcher integration for profiles - Subscribe to frigate/profile/set MQTT topic - Publish profile/state and profiles/available on connect - Add _on_profile_command handler to dispatcher - Broadcast active profile state on WebSocket connect * wire ProfileManager into app startup and FastAPI - Create ProfileManager after dispatcher init - Restore persisted profile on startup - Pass dispatcher and profile_manager to FastAPI app * add tests for invalid profile values and keys Tests that Pydantic rejects: invalid field values (fps: "not_a_number"), unknown section keys (ffmpeg in profile), invalid nested values, and invalid profiles in full config parsing. * formatting * fix CameraLiveConfig JSON serialization error on profile activation refactor _publish_updates to only publish ZMQ updates for sections that actually changed, not all sections on affected cameras. * consolidate * add enabled field to camera profiles for enabling/disabling cameras * add zones support to camera profiles * add frontend profile types, color utility, and config save support * add profile state management and save preview support * add profileName prop to BaseSection for profile-aware config editing * add profile section dropdown and wire into camera settings pages * add per-profile camera enable/disable to Camera Management view * add profiles summary page with card-based layout and fix backend zone comparison bug * add active profile badge to settings toolbar * i18n * add red dot for any pending changes including profiles * profile support for mask and zone editor * fix hidden field validation errors caused by lodash wildcard and schema gaps lodash unset does not support wildcard (*) segments, so hidden fields like filters.*.mask were never stripped from form data, leaving null raw_coordinates that fail RJSF anyOf validation. Add unsetWithWildcard helper and also strip hidden fields from the JSON schema itself as defense-in-depth. * add face_recognition and lpr to profile-eligible sections * move profile dropdown from section panes to settings header * add profiles enable toggle and improve empty state * formatting * tweaks * tweak colors and switch * fix profile save diff, masksAndZones delete, and config sync * ui tweaks * ensure profile manager gets updated config * rename profile settings to ui settings * refactor profilesview and add dots/border colors when overridden * implement an update_config method for profile manager * fix mask deletion * more unique colors * add top-level profiles config section with friendly names * implement profile friendly names and improve profile UI - Add ProfileDefinitionConfig type and profiles field to FrigateConfig - Use ProfilesApiResponse type with friendly_name support throughout - Replace Record<string, unknown> with proper JsonObject/JsonValue types - Add profile creation form matching zone pattern (Zod + NameAndIdFields) - Add pencil icon for renaming profile friendly names in ProfilesView - Move Profiles menu item to first under Camera Configuration - Add activity indicators on save/rename/delete buttons - Display friendly names in CameraManagementView profile selector - Fix duplicate colored dots in management profile dropdown - Fix i18n namespace for overridden base config tooltips - Move profile override deletion from dropdown trash icon to footer button with confirmation dialog, matching Reset to Global pattern - Remove Add Profile from section header dropdown to prevent saving camera overrides before top-level profile definition exists - Clean up newProfiles state after API profile deletion - Refresh profiles SWR cache after saving profile definitions * remove profile badge in settings and add profiles to main menu * use icon only on mobile * change color order * docs * show activity indicator on trash icon while deleting a profile * tweak language * immediately create profiles on backend instead of deferring to Save All * hide restart-required fields when editing a profile section fields that require a restart cannot take effect via profile switching, so they are merged into hiddenFields when profileName is set * show active profile indicator in desktop status bar * fix profile config inheritance bug where Pydantic defaults override base values The /config API was dumping profile overrides with model_dump() which included all Pydantic defaults. When the frontend merged these over the camera's base config, explicitly-set base values were lost. Now profile overrides are re-dumped with exclude_unset=True so only user-specified fields are returned. Also fixes the Save All path generating spurious deletion markers for restart-required fields that are hidden during profile editing but not excluded from the raw data sanitization in prepareSectionSavePayload. * docs tweaks * docs tweak * formatting * formatting * fix typing * fix test pollution test_maintainer was injecting MagicMock() into sys.modules["frigate.config.camera.updater"] at module load time and never restoring it. When the profile tests later imported CameraConfigUpdateEnum and CameraConfigUpdateTopic from that module, they got mock objects instead of the real dataclass/enum, so equality comparisons always failed * remove * fix settings showing profile-merged values when editing base config When a profile is active, the in-memory config contains effective (profile-merged) values. The settings UI was displaying these merged values even when the "Base Config" view was selected. Backend: snapshot pre-profile base configs in ProfileManager and expose them via a `base_config` key in the /api/config camera response when a profile is active. The top-level sections continue to reflect the effective running config. Frontend: read from `base_config` when available in BaseSection, useConfigOverride, useAllCameraOverrides, and prepareSectionSavePayload. Include formData labels in Object/Audio switches widgets so that labels added only by a profile override remain visible when editing that profile. * use rasterized_mask as field makes it easier to exclude from the schema with exclude=True prevents leaking of the field when using model_dump for profiles * fix zones - Fix zone colors not matching across profiles by falling back to base zone color when profile zone data lacks a color field - Use base_config for base-layer values in masks/zones view so profile-merged values don't pollute the base config editing view - Handle zones separately in profile manager snapshot/restore since ZoneConfig requires special serialization (color as private attr, contour generation) - Inherit base zone color and generate contours for profile zone overrides in profile manager * formatting * don't require restart for camera enabled change for profiles * publish camera state when changing profiles * formatting * remove available profiles from mqtt * improve typing
2026-03-19 17:47:57 +03:00
import type { ProfileState } from "@/types/profile";
import { getProfileColor } from "@/utils/profileColors";
import { cn } from "@/lib/utils";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const REORDER_SAVED_INDICATOR_MS = 1500;
type ReorderSaveStatus = "idle" | "saving" | "saved";
type CameraManagementViewProps = {
setUnsavedChanges: React.Dispatch<React.SetStateAction<boolean>>;
Camera profile support (#22482) * add CameraProfileConfig model for named config overrides * add profiles field to CameraConfig * add active_profile field to FrigateConfig Runtime-only field excluded from YAML serialization, tracks which profile is currently active. * add ProfileManager for profile activation and persistence Handles snapshotting base configs, applying profile overrides via deep_merge + apply_section_update, publishing ZMQ updates, and persisting active profile to /config/.active_profile. * add profile API endpoints (GET /profiles, GET/PUT /profile) * add MQTT and dispatcher integration for profiles - Subscribe to frigate/profile/set MQTT topic - Publish profile/state and profiles/available on connect - Add _on_profile_command handler to dispatcher - Broadcast active profile state on WebSocket connect * wire ProfileManager into app startup and FastAPI - Create ProfileManager after dispatcher init - Restore persisted profile on startup - Pass dispatcher and profile_manager to FastAPI app * add tests for invalid profile values and keys Tests that Pydantic rejects: invalid field values (fps: "not_a_number"), unknown section keys (ffmpeg in profile), invalid nested values, and invalid profiles in full config parsing. * formatting * fix CameraLiveConfig JSON serialization error on profile activation refactor _publish_updates to only publish ZMQ updates for sections that actually changed, not all sections on affected cameras. * consolidate * add enabled field to camera profiles for enabling/disabling cameras * add zones support to camera profiles * add frontend profile types, color utility, and config save support * add profile state management and save preview support * add profileName prop to BaseSection for profile-aware config editing * add profile section dropdown and wire into camera settings pages * add per-profile camera enable/disable to Camera Management view * add profiles summary page with card-based layout and fix backend zone comparison bug * add active profile badge to settings toolbar * i18n * add red dot for any pending changes including profiles * profile support for mask and zone editor * fix hidden field validation errors caused by lodash wildcard and schema gaps lodash unset does not support wildcard (*) segments, so hidden fields like filters.*.mask were never stripped from form data, leaving null raw_coordinates that fail RJSF anyOf validation. Add unsetWithWildcard helper and also strip hidden fields from the JSON schema itself as defense-in-depth. * add face_recognition and lpr to profile-eligible sections * move profile dropdown from section panes to settings header * add profiles enable toggle and improve empty state * formatting * tweaks * tweak colors and switch * fix profile save diff, masksAndZones delete, and config sync * ui tweaks * ensure profile manager gets updated config * rename profile settings to ui settings * refactor profilesview and add dots/border colors when overridden * implement an update_config method for profile manager * fix mask deletion * more unique colors * add top-level profiles config section with friendly names * implement profile friendly names and improve profile UI - Add ProfileDefinitionConfig type and profiles field to FrigateConfig - Use ProfilesApiResponse type with friendly_name support throughout - Replace Record<string, unknown> with proper JsonObject/JsonValue types - Add profile creation form matching zone pattern (Zod + NameAndIdFields) - Add pencil icon for renaming profile friendly names in ProfilesView - Move Profiles menu item to first under Camera Configuration - Add activity indicators on save/rename/delete buttons - Display friendly names in CameraManagementView profile selector - Fix duplicate colored dots in management profile dropdown - Fix i18n namespace for overridden base config tooltips - Move profile override deletion from dropdown trash icon to footer button with confirmation dialog, matching Reset to Global pattern - Remove Add Profile from section header dropdown to prevent saving camera overrides before top-level profile definition exists - Clean up newProfiles state after API profile deletion - Refresh profiles SWR cache after saving profile definitions * remove profile badge in settings and add profiles to main menu * use icon only on mobile * change color order * docs * show activity indicator on trash icon while deleting a profile * tweak language * immediately create profiles on backend instead of deferring to Save All * hide restart-required fields when editing a profile section fields that require a restart cannot take effect via profile switching, so they are merged into hiddenFields when profileName is set * show active profile indicator in desktop status bar * fix profile config inheritance bug where Pydantic defaults override base values The /config API was dumping profile overrides with model_dump() which included all Pydantic defaults. When the frontend merged these over the camera's base config, explicitly-set base values were lost. Now profile overrides are re-dumped with exclude_unset=True so only user-specified fields are returned. Also fixes the Save All path generating spurious deletion markers for restart-required fields that are hidden during profile editing but not excluded from the raw data sanitization in prepareSectionSavePayload. * docs tweaks * docs tweak * formatting * formatting * fix typing * fix test pollution test_maintainer was injecting MagicMock() into sys.modules["frigate.config.camera.updater"] at module load time and never restoring it. When the profile tests later imported CameraConfigUpdateEnum and CameraConfigUpdateTopic from that module, they got mock objects instead of the real dataclass/enum, so equality comparisons always failed * remove * fix settings showing profile-merged values when editing base config When a profile is active, the in-memory config contains effective (profile-merged) values. The settings UI was displaying these merged values even when the "Base Config" view was selected. Backend: snapshot pre-profile base configs in ProfileManager and expose them via a `base_config` key in the /api/config camera response when a profile is active. The top-level sections continue to reflect the effective running config. Frontend: read from `base_config` when available in BaseSection, useConfigOverride, useAllCameraOverrides, and prepareSectionSavePayload. Include formData labels in Object/Audio switches widgets so that labels added only by a profile override remain visible when editing that profile. * use rasterized_mask as field makes it easier to exclude from the schema with exclude=True prevents leaking of the field when using model_dump for profiles * fix zones - Fix zone colors not matching across profiles by falling back to base zone color when profile zone data lacks a color field - Use base_config for base-layer values in masks/zones view so profile-merged values don't pollute the base config editing view - Handle zones separately in profile manager snapshot/restore since ZoneConfig requires special serialization (color as private attr, contour generation) - Inherit base zone color and generate contours for profile zone overrides in profile manager * formatting * don't require restart for camera enabled change for profiles * publish camera state when changing profiles * formatting * remove available profiles from mqtt * improve typing
2026-03-19 17:47:57 +03:00
profileState?: ProfileState;
};
export default function CameraManagementView({
setUnsavedChanges,
Camera profile support (#22482) * add CameraProfileConfig model for named config overrides * add profiles field to CameraConfig * add active_profile field to FrigateConfig Runtime-only field excluded from YAML serialization, tracks which profile is currently active. * add ProfileManager for profile activation and persistence Handles snapshotting base configs, applying profile overrides via deep_merge + apply_section_update, publishing ZMQ updates, and persisting active profile to /config/.active_profile. * add profile API endpoints (GET /profiles, GET/PUT /profile) * add MQTT and dispatcher integration for profiles - Subscribe to frigate/profile/set MQTT topic - Publish profile/state and profiles/available on connect - Add _on_profile_command handler to dispatcher - Broadcast active profile state on WebSocket connect * wire ProfileManager into app startup and FastAPI - Create ProfileManager after dispatcher init - Restore persisted profile on startup - Pass dispatcher and profile_manager to FastAPI app * add tests for invalid profile values and keys Tests that Pydantic rejects: invalid field values (fps: "not_a_number"), unknown section keys (ffmpeg in profile), invalid nested values, and invalid profiles in full config parsing. * formatting * fix CameraLiveConfig JSON serialization error on profile activation refactor _publish_updates to only publish ZMQ updates for sections that actually changed, not all sections on affected cameras. * consolidate * add enabled field to camera profiles for enabling/disabling cameras * add zones support to camera profiles * add frontend profile types, color utility, and config save support * add profile state management and save preview support * add profileName prop to BaseSection for profile-aware config editing * add profile section dropdown and wire into camera settings pages * add per-profile camera enable/disable to Camera Management view * add profiles summary page with card-based layout and fix backend zone comparison bug * add active profile badge to settings toolbar * i18n * add red dot for any pending changes including profiles * profile support for mask and zone editor * fix hidden field validation errors caused by lodash wildcard and schema gaps lodash unset does not support wildcard (*) segments, so hidden fields like filters.*.mask were never stripped from form data, leaving null raw_coordinates that fail RJSF anyOf validation. Add unsetWithWildcard helper and also strip hidden fields from the JSON schema itself as defense-in-depth. * add face_recognition and lpr to profile-eligible sections * move profile dropdown from section panes to settings header * add profiles enable toggle and improve empty state * formatting * tweaks * tweak colors and switch * fix profile save diff, masksAndZones delete, and config sync * ui tweaks * ensure profile manager gets updated config * rename profile settings to ui settings * refactor profilesview and add dots/border colors when overridden * implement an update_config method for profile manager * fix mask deletion * more unique colors * add top-level profiles config section with friendly names * implement profile friendly names and improve profile UI - Add ProfileDefinitionConfig type and profiles field to FrigateConfig - Use ProfilesApiResponse type with friendly_name support throughout - Replace Record<string, unknown> with proper JsonObject/JsonValue types - Add profile creation form matching zone pattern (Zod + NameAndIdFields) - Add pencil icon for renaming profile friendly names in ProfilesView - Move Profiles menu item to first under Camera Configuration - Add activity indicators on save/rename/delete buttons - Display friendly names in CameraManagementView profile selector - Fix duplicate colored dots in management profile dropdown - Fix i18n namespace for overridden base config tooltips - Move profile override deletion from dropdown trash icon to footer button with confirmation dialog, matching Reset to Global pattern - Remove Add Profile from section header dropdown to prevent saving camera overrides before top-level profile definition exists - Clean up newProfiles state after API profile deletion - Refresh profiles SWR cache after saving profile definitions * remove profile badge in settings and add profiles to main menu * use icon only on mobile * change color order * docs * show activity indicator on trash icon while deleting a profile * tweak language * immediately create profiles on backend instead of deferring to Save All * hide restart-required fields when editing a profile section fields that require a restart cannot take effect via profile switching, so they are merged into hiddenFields when profileName is set * show active profile indicator in desktop status bar * fix profile config inheritance bug where Pydantic defaults override base values The /config API was dumping profile overrides with model_dump() which included all Pydantic defaults. When the frontend merged these over the camera's base config, explicitly-set base values were lost. Now profile overrides are re-dumped with exclude_unset=True so only user-specified fields are returned. Also fixes the Save All path generating spurious deletion markers for restart-required fields that are hidden during profile editing but not excluded from the raw data sanitization in prepareSectionSavePayload. * docs tweaks * docs tweak * formatting * formatting * fix typing * fix test pollution test_maintainer was injecting MagicMock() into sys.modules["frigate.config.camera.updater"] at module load time and never restoring it. When the profile tests later imported CameraConfigUpdateEnum and CameraConfigUpdateTopic from that module, they got mock objects instead of the real dataclass/enum, so equality comparisons always failed * remove * fix settings showing profile-merged values when editing base config When a profile is active, the in-memory config contains effective (profile-merged) values. The settings UI was displaying these merged values even when the "Base Config" view was selected. Backend: snapshot pre-profile base configs in ProfileManager and expose them via a `base_config` key in the /api/config camera response when a profile is active. The top-level sections continue to reflect the effective running config. Frontend: read from `base_config` when available in BaseSection, useConfigOverride, useAllCameraOverrides, and prepareSectionSavePayload. Include formData labels in Object/Audio switches widgets so that labels added only by a profile override remain visible when editing that profile. * use rasterized_mask as field makes it easier to exclude from the schema with exclude=True prevents leaking of the field when using model_dump for profiles * fix zones - Fix zone colors not matching across profiles by falling back to base zone color when profile zone data lacks a color field - Use base_config for base-layer values in masks/zones view so profile-merged values don't pollute the base config editing view - Handle zones separately in profile manager snapshot/restore since ZoneConfig requires special serialization (color as private attr, contour generation) - Inherit base zone color and generate contours for profile zone overrides in profile manager * formatting * don't require restart for camera enabled change for profiles * publish camera state when changing profiles * formatting * remove available profiles from mqtt * improve typing
2026-03-19 17:47:57 +03:00
profileState,
}: CameraManagementViewProps) {
const { t } = useTranslation(["views/settings", "common"]);
const { data: config, mutate: updateConfig } =
useSWR<FrigateConfig>("config");
const [viewMode, setViewMode] = useState<"settings" | "add" | "edit">(
"settings",
); // Control view state
const [editCameraName, setEditCameraName] = useState<string | undefined>(
undefined,
); // Track camera being edited
const [showWizard, setShowWizard] = useState(false);
const [showDeleteDialog, setShowDeleteDialog] = useState(false);
Full UI configuration (#22151) * use react-jsonschema-form for UI config * don't use properties wrapper when generating config i18n json * configure for full i18n support * section fields * add descriptions to all fields for i18n * motion i18n * fix nullable fields * sanitize internal fields * add switches widgets and use friendly names * fix nullable schema entries * ensure update_topic is added to api calls this needs further backend implementation to work correctly * add global sections, camera config overrides, and reset button * i18n * add reset logic to global config view * tweaks * fix sections and live validation * fix validation for schema objects that can be null * generic and custom per-field validation * improve generic error validation messages * remove show advanced fields switch * tweaks * use shadcn theme * fix array field template * i18n tweaks * remove collapsible around root section * deep merge schema for advanced fields * add array field item template and fix ffmpeg section * add missing i18n keys * tweaks * comment out api call for testing * add config groups as a separate i18n namespace * add descriptions to all pydantic fields * make titles more concise * new titles as i18n * update i18n config generation script to use json schema * tweaks * tweaks * rebase * clean up * form tweaks * add wildcards and fix object filter fields * add field template for additionalproperties schema objects * improve typing * add section description from schema and clarify global vs camera level descriptions * separate and consolidate global and camera i18n namespaces * clean up now obsolete namespaces * tweaks * refactor sections and overrides * add ability to render components before and after fields * fix titles * chore(sections): remove legacy single-section components replaced by template * refactor configs to use individual files with a template * fix review description * apply hidden fields after ui schema * move util * remove unused i18n * clean up error messages * fix fast refresh * add custom validation and use it for ffmpeg input roles * update nav tree * remove unused * re-add override and modified indicators * mark pending changes and add confirmation dialog for resets * fix red unsaved dot * tweaks * add docs links, readonly keys, and restart required per field * add special case and comments for global motion section * add section form special cases * combine review sections * tweaks * add audio labels endpoint * add audio label switches and input to filter list * fix type * remove key from config when resetting to default/global * don't show description for new key/val fields * tweaks * spacing tweaks * add activity indicator and scrollbar tweaks * add docs to filter fields * wording changes * fix global ffmpeg section * add review classification zones to review form * add backend endpoint and frontend widget for ffmpeg presets and manual args * improve wording * hide descriptions for additional properties arrays * add warning log about incorrectly nested model config * spacing and language tweaks * fix i18n keys * networking section docs and description * small wording tweaks * add layout grid field * refactor with shared utilities * field order * add individual detectors to schema add detector titles and descriptions (docstrings in pydantic are used for descriptions) and add i18n keys to globals * clean up detectors section and i18n * don't save model config back to yaml when saving detectors * add full detectors config to api model dump works around the way we use detector plugins so we can have the full detector config for the frontend * add restart button to toast when restart is required * add ui option to remove inner cards * fix buttons * section tweaks * don't zoom into text on mobile * make buttons sticky at bottom of sections * small tweaks * highlight label of changed fields * add null to enum list when unwrapping * refactor to shared utils and add save all button * add undo all button * add RJSF to dictionary * consolidate utils * preserve form data when changing cameras * add mono fonts * add popover to show what fields will be saved * fix mobile menu not re-rendering with unsaved dots * tweaks * fix logger and env vars config section saving use escaped periods in keys to retain them in the config file (eg "frigate.embeddings") * add timezone widget * role map field with validation * fix validation for model section * add another hidden field * add footer message for required restart * use rjsf for notifications view * fix config saving * add replace rules field * default column layout and add field sizing * clean up field template * refactor profile settings to match rjsf forms * tweaks * refactor frigate+ view and make tweaks to sections * show frigate+ model info in detection model settings when using a frigate+ model * update restartRequired for all fields * fix restart fields * tweaks and add ability enable disabled cameras more backend changes required * require restart when enabling camera that is disabled in config * disable save when form is invalid * refactor ffmpeg section for readability * change label * clean up camera inputs fields * misc tweaks to ffmpeg section - add raw paths endpoint to ensure credentials get saved - restart required tooltip * maintenance settings tweaks * don't mutate with lodash * fix description re-rendering for nullable object fields * hide reindex field * update rjsf * add frigate+ description to settings pane * disable save all when any section is invalid * show translated field name in validation error pane * clean up * remove unused * fix genai merge * fix genai
2026-02-27 18:55:36 +03:00
// State for restart dialog when enabling a disabled camera
const [restartDialogOpen, setRestartDialogOpen] = useState(false);
const { send: sendRestart } = useRestart();
const enabledCameras = useMemo(() => {
if (config) {
return Object.keys(config.cameras)
.filter((camera) => config.cameras[camera].enabled_in_config)
.sort((a, b) => {
const orderA = config.cameras[a].ui?.order ?? 0;
const orderB = config.cameras[b].ui?.order ?? 0;
if (orderA !== orderB) return orderA - orderB;
return a.localeCompare(b);
});
Full UI configuration (#22151) * use react-jsonschema-form for UI config * don't use properties wrapper when generating config i18n json * configure for full i18n support * section fields * add descriptions to all fields for i18n * motion i18n * fix nullable fields * sanitize internal fields * add switches widgets and use friendly names * fix nullable schema entries * ensure update_topic is added to api calls this needs further backend implementation to work correctly * add global sections, camera config overrides, and reset button * i18n * add reset logic to global config view * tweaks * fix sections and live validation * fix validation for schema objects that can be null * generic and custom per-field validation * improve generic error validation messages * remove show advanced fields switch * tweaks * use shadcn theme * fix array field template * i18n tweaks * remove collapsible around root section * deep merge schema for advanced fields * add array field item template and fix ffmpeg section * add missing i18n keys * tweaks * comment out api call for testing * add config groups as a separate i18n namespace * add descriptions to all pydantic fields * make titles more concise * new titles as i18n * update i18n config generation script to use json schema * tweaks * tweaks * rebase * clean up * form tweaks * add wildcards and fix object filter fields * add field template for additionalproperties schema objects * improve typing * add section description from schema and clarify global vs camera level descriptions * separate and consolidate global and camera i18n namespaces * clean up now obsolete namespaces * tweaks * refactor sections and overrides * add ability to render components before and after fields * fix titles * chore(sections): remove legacy single-section components replaced by template * refactor configs to use individual files with a template * fix review description * apply hidden fields after ui schema * move util * remove unused i18n * clean up error messages * fix fast refresh * add custom validation and use it for ffmpeg input roles * update nav tree * remove unused * re-add override and modified indicators * mark pending changes and add confirmation dialog for resets * fix red unsaved dot * tweaks * add docs links, readonly keys, and restart required per field * add special case and comments for global motion section * add section form special cases * combine review sections * tweaks * add audio labels endpoint * add audio label switches and input to filter list * fix type * remove key from config when resetting to default/global * don't show description for new key/val fields * tweaks * spacing tweaks * add activity indicator and scrollbar tweaks * add docs to filter fields * wording changes * fix global ffmpeg section * add review classification zones to review form * add backend endpoint and frontend widget for ffmpeg presets and manual args * improve wording * hide descriptions for additional properties arrays * add warning log about incorrectly nested model config * spacing and language tweaks * fix i18n keys * networking section docs and description * small wording tweaks * add layout grid field * refactor with shared utilities * field order * add individual detectors to schema add detector titles and descriptions (docstrings in pydantic are used for descriptions) and add i18n keys to globals * clean up detectors section and i18n * don't save model config back to yaml when saving detectors * add full detectors config to api model dump works around the way we use detector plugins so we can have the full detector config for the frontend * add restart button to toast when restart is required * add ui option to remove inner cards * fix buttons * section tweaks * don't zoom into text on mobile * make buttons sticky at bottom of sections * small tweaks * highlight label of changed fields * add null to enum list when unwrapping * refactor to shared utils and add save all button * add undo all button * add RJSF to dictionary * consolidate utils * preserve form data when changing cameras * add mono fonts * add popover to show what fields will be saved * fix mobile menu not re-rendering with unsaved dots * tweaks * fix logger and env vars config section saving use escaped periods in keys to retain them in the config file (eg "frigate.embeddings") * add timezone widget * role map field with validation * fix validation for model section * add another hidden field * add footer message for required restart * use rjsf for notifications view * fix config saving * add replace rules field * default column layout and add field sizing * clean up field template * refactor profile settings to match rjsf forms * tweaks * refactor frigate+ view and make tweaks to sections * show frigate+ model info in detection model settings when using a frigate+ model * update restartRequired for all fields * fix restart fields * tweaks and add ability enable disabled cameras more backend changes required * require restart when enabling camera that is disabled in config * disable save when form is invalid * refactor ffmpeg section for readability * change label * clean up camera inputs fields * misc tweaks to ffmpeg section - add raw paths endpoint to ensure credentials get saved - restart required tooltip * maintenance settings tweaks * don't mutate with lodash * fix description re-rendering for nullable object fields * hide reindex field * update rjsf * add frigate+ description to settings pane * disable save all when any section is invalid * show translated field name in validation error pane * clean up * remove unused * fix genai merge * fix genai
2026-02-27 18:55:36 +03:00
}
return [];
}, [config]);
// Diverges from config during a drag and while the save is in flight.
const [orderedCameras, setOrderedCameras] =
useState<string[]>(enabledCameras);
const orderedCamerasRef = useRef(orderedCameras);
useEffect(() => {
orderedCamerasRef.current = orderedCameras;
}, [orderedCameras]);
useEffect(() => {
setOrderedCameras((prev) => {
if (
prev.length === enabledCameras.length &&
prev.every((cam, i) => cam === enabledCameras[i])
) {
return prev;
}
return enabledCameras;
});
}, [enabledCameras]);
const [reorderSaveStatus, setReorderSaveStatus] =
useState<ReorderSaveStatus>("idle");
const reorderSavedTimerRef = useRef<ReturnType<typeof setTimeout> | null>(
null,
);
useEffect(() => {
return () => {
if (reorderSavedTimerRef.current) {
clearTimeout(reorderSavedTimerRef.current);
}
};
}, []);
const handleReorderDragEnd = useCallback(async () => {
const current = orderedCamerasRef.current;
if (
current.length === enabledCameras.length &&
current.every((cam, i) => cam === enabledCameras[i])
) {
return;
}
const cameraUpdates: Record<string, { ui: { order: number } }> = {};
current.forEach((cam, i) => {
cameraUpdates[cam] = { ui: { order: i * 10 } };
});
if (reorderSavedTimerRef.current) {
clearTimeout(reorderSavedTimerRef.current);
reorderSavedTimerRef.current = null;
}
setReorderSaveStatus("saving");
try {
await axios.put("config/set", {
requires_restart: 0,
config_data: { cameras: cameraUpdates },
});
await updateConfig();
setReorderSaveStatus("saved");
reorderSavedTimerRef.current = setTimeout(() => {
setReorderSaveStatus("idle");
reorderSavedTimerRef.current = null;
}, REORDER_SAVED_INDICATOR_MS);
} catch (error) {
setOrderedCameras(enabledCameras);
setReorderSaveStatus("idle");
const errorMessage =
axios.isAxiosError(error) &&
(error.response?.data?.message || error.response?.data?.detail)
? error.response?.data?.message || error.response?.data?.detail
: t("toast.save.error.noMessage", { ns: "common" });
toast.error(t("toast.save.error.title", { errorMessage, ns: "common" }), {
position: "top-center",
});
}
}, [enabledCameras, updateConfig, t]);
Full UI configuration (#22151) * use react-jsonschema-form for UI config * don't use properties wrapper when generating config i18n json * configure for full i18n support * section fields * add descriptions to all fields for i18n * motion i18n * fix nullable fields * sanitize internal fields * add switches widgets and use friendly names * fix nullable schema entries * ensure update_topic is added to api calls this needs further backend implementation to work correctly * add global sections, camera config overrides, and reset button * i18n * add reset logic to global config view * tweaks * fix sections and live validation * fix validation for schema objects that can be null * generic and custom per-field validation * improve generic error validation messages * remove show advanced fields switch * tweaks * use shadcn theme * fix array field template * i18n tweaks * remove collapsible around root section * deep merge schema for advanced fields * add array field item template and fix ffmpeg section * add missing i18n keys * tweaks * comment out api call for testing * add config groups as a separate i18n namespace * add descriptions to all pydantic fields * make titles more concise * new titles as i18n * update i18n config generation script to use json schema * tweaks * tweaks * rebase * clean up * form tweaks * add wildcards and fix object filter fields * add field template for additionalproperties schema objects * improve typing * add section description from schema and clarify global vs camera level descriptions * separate and consolidate global and camera i18n namespaces * clean up now obsolete namespaces * tweaks * refactor sections and overrides * add ability to render components before and after fields * fix titles * chore(sections): remove legacy single-section components replaced by template * refactor configs to use individual files with a template * fix review description * apply hidden fields after ui schema * move util * remove unused i18n * clean up error messages * fix fast refresh * add custom validation and use it for ffmpeg input roles * update nav tree * remove unused * re-add override and modified indicators * mark pending changes and add confirmation dialog for resets * fix red unsaved dot * tweaks * add docs links, readonly keys, and restart required per field * add special case and comments for global motion section * add section form special cases * combine review sections * tweaks * add audio labels endpoint * add audio label switches and input to filter list * fix type * remove key from config when resetting to default/global * don't show description for new key/val fields * tweaks * spacing tweaks * add activity indicator and scrollbar tweaks * add docs to filter fields * wording changes * fix global ffmpeg section * add review classification zones to review form * add backend endpoint and frontend widget for ffmpeg presets and manual args * improve wording * hide descriptions for additional properties arrays * add warning log about incorrectly nested model config * spacing and language tweaks * fix i18n keys * networking section docs and description * small wording tweaks * add layout grid field * refactor with shared utilities * field order * add individual detectors to schema add detector titles and descriptions (docstrings in pydantic are used for descriptions) and add i18n keys to globals * clean up detectors section and i18n * don't save model config back to yaml when saving detectors * add full detectors config to api model dump works around the way we use detector plugins so we can have the full detector config for the frontend * add restart button to toast when restart is required * add ui option to remove inner cards * fix buttons * section tweaks * don't zoom into text on mobile * make buttons sticky at bottom of sections * small tweaks * highlight label of changed fields * add null to enum list when unwrapping * refactor to shared utils and add save all button * add undo all button * add RJSF to dictionary * consolidate utils * preserve form data when changing cameras * add mono fonts * add popover to show what fields will be saved * fix mobile menu not re-rendering with unsaved dots * tweaks * fix logger and env vars config section saving use escaped periods in keys to retain them in the config file (eg "frigate.embeddings") * add timezone widget * role map field with validation * fix validation for model section * add another hidden field * add footer message for required restart * use rjsf for notifications view * fix config saving * add replace rules field * default column layout and add field sizing * clean up field template * refactor profile settings to match rjsf forms * tweaks * refactor frigate+ view and make tweaks to sections * show frigate+ model info in detection model settings when using a frigate+ model * update restartRequired for all fields * fix restart fields * tweaks and add ability enable disabled cameras more backend changes required * require restart when enabling camera that is disabled in config * disable save when form is invalid * refactor ffmpeg section for readability * change label * clean up camera inputs fields * misc tweaks to ffmpeg section - add raw paths endpoint to ensure credentials get saved - restart required tooltip * maintenance settings tweaks * don't mutate with lodash * fix description re-rendering for nullable object fields * hide reindex field * update rjsf * add frigate+ description to settings pane * disable save all when any section is invalid * show translated field name in validation error pane * clean up * remove unused * fix genai merge * fix genai
2026-02-27 18:55:36 +03:00
const disabledCameras = useMemo(() => {
if (config) {
Full UI configuration (#22151) * use react-jsonschema-form for UI config * don't use properties wrapper when generating config i18n json * configure for full i18n support * section fields * add descriptions to all fields for i18n * motion i18n * fix nullable fields * sanitize internal fields * add switches widgets and use friendly names * fix nullable schema entries * ensure update_topic is added to api calls this needs further backend implementation to work correctly * add global sections, camera config overrides, and reset button * i18n * add reset logic to global config view * tweaks * fix sections and live validation * fix validation for schema objects that can be null * generic and custom per-field validation * improve generic error validation messages * remove show advanced fields switch * tweaks * use shadcn theme * fix array field template * i18n tweaks * remove collapsible around root section * deep merge schema for advanced fields * add array field item template and fix ffmpeg section * add missing i18n keys * tweaks * comment out api call for testing * add config groups as a separate i18n namespace * add descriptions to all pydantic fields * make titles more concise * new titles as i18n * update i18n config generation script to use json schema * tweaks * tweaks * rebase * clean up * form tweaks * add wildcards and fix object filter fields * add field template for additionalproperties schema objects * improve typing * add section description from schema and clarify global vs camera level descriptions * separate and consolidate global and camera i18n namespaces * clean up now obsolete namespaces * tweaks * refactor sections and overrides * add ability to render components before and after fields * fix titles * chore(sections): remove legacy single-section components replaced by template * refactor configs to use individual files with a template * fix review description * apply hidden fields after ui schema * move util * remove unused i18n * clean up error messages * fix fast refresh * add custom validation and use it for ffmpeg input roles * update nav tree * remove unused * re-add override and modified indicators * mark pending changes and add confirmation dialog for resets * fix red unsaved dot * tweaks * add docs links, readonly keys, and restart required per field * add special case and comments for global motion section * add section form special cases * combine review sections * tweaks * add audio labels endpoint * add audio label switches and input to filter list * fix type * remove key from config when resetting to default/global * don't show description for new key/val fields * tweaks * spacing tweaks * add activity indicator and scrollbar tweaks * add docs to filter fields * wording changes * fix global ffmpeg section * add review classification zones to review form * add backend endpoint and frontend widget for ffmpeg presets and manual args * improve wording * hide descriptions for additional properties arrays * add warning log about incorrectly nested model config * spacing and language tweaks * fix i18n keys * networking section docs and description * small wording tweaks * add layout grid field * refactor with shared utilities * field order * add individual detectors to schema add detector titles and descriptions (docstrings in pydantic are used for descriptions) and add i18n keys to globals * clean up detectors section and i18n * don't save model config back to yaml when saving detectors * add full detectors config to api model dump works around the way we use detector plugins so we can have the full detector config for the frontend * add restart button to toast when restart is required * add ui option to remove inner cards * fix buttons * section tweaks * don't zoom into text on mobile * make buttons sticky at bottom of sections * small tweaks * highlight label of changed fields * add null to enum list when unwrapping * refactor to shared utils and add save all button * add undo all button * add RJSF to dictionary * consolidate utils * preserve form data when changing cameras * add mono fonts * add popover to show what fields will be saved * fix mobile menu not re-rendering with unsaved dots * tweaks * fix logger and env vars config section saving use escaped periods in keys to retain them in the config file (eg "frigate.embeddings") * add timezone widget * role map field with validation * fix validation for model section * add another hidden field * add footer message for required restart * use rjsf for notifications view * fix config saving * add replace rules field * default column layout and add field sizing * clean up field template * refactor profile settings to match rjsf forms * tweaks * refactor frigate+ view and make tweaks to sections * show frigate+ model info in detection model settings when using a frigate+ model * update restartRequired for all fields * fix restart fields * tweaks and add ability enable disabled cameras more backend changes required * require restart when enabling camera that is disabled in config * disable save when form is invalid * refactor ffmpeg section for readability * change label * clean up camera inputs fields * misc tweaks to ffmpeg section - add raw paths endpoint to ensure credentials get saved - restart required tooltip * maintenance settings tweaks * don't mutate with lodash * fix description re-rendering for nullable object fields * hide reindex field * update rjsf * add frigate+ description to settings pane * disable save all when any section is invalid * show translated field name in validation error pane * clean up * remove unused * fix genai merge * fix genai
2026-02-27 18:55:36 +03:00
return Object.keys(config.cameras)
.filter((camera) => !config.cameras[camera].enabled_in_config)
.sort();
}
return [];
}, [config]);
const allCameras = useMemo(() => {
if (config) {
return Object.keys(config.cameras).sort();
}
return [];
}, [config]);
useEffect(() => {
document.title = t("documentTitle.cameraManagement");
}, [t]);
// Handle back navigation from add/edit form
const handleBack = useCallback(() => {
setViewMode("settings");
setEditCameraName(undefined);
setUnsavedChanges(false);
updateConfig();
}, [updateConfig, setUnsavedChanges]);
return (
<>
<Toaster
richColors
className="z-[1000]"
position="top-center"
closeButton
/>
Full UI configuration (#22151) * use react-jsonschema-form for UI config * don't use properties wrapper when generating config i18n json * configure for full i18n support * section fields * add descriptions to all fields for i18n * motion i18n * fix nullable fields * sanitize internal fields * add switches widgets and use friendly names * fix nullable schema entries * ensure update_topic is added to api calls this needs further backend implementation to work correctly * add global sections, camera config overrides, and reset button * i18n * add reset logic to global config view * tweaks * fix sections and live validation * fix validation for schema objects that can be null * generic and custom per-field validation * improve generic error validation messages * remove show advanced fields switch * tweaks * use shadcn theme * fix array field template * i18n tweaks * remove collapsible around root section * deep merge schema for advanced fields * add array field item template and fix ffmpeg section * add missing i18n keys * tweaks * comment out api call for testing * add config groups as a separate i18n namespace * add descriptions to all pydantic fields * make titles more concise * new titles as i18n * update i18n config generation script to use json schema * tweaks * tweaks * rebase * clean up * form tweaks * add wildcards and fix object filter fields * add field template for additionalproperties schema objects * improve typing * add section description from schema and clarify global vs camera level descriptions * separate and consolidate global and camera i18n namespaces * clean up now obsolete namespaces * tweaks * refactor sections and overrides * add ability to render components before and after fields * fix titles * chore(sections): remove legacy single-section components replaced by template * refactor configs to use individual files with a template * fix review description * apply hidden fields after ui schema * move util * remove unused i18n * clean up error messages * fix fast refresh * add custom validation and use it for ffmpeg input roles * update nav tree * remove unused * re-add override and modified indicators * mark pending changes and add confirmation dialog for resets * fix red unsaved dot * tweaks * add docs links, readonly keys, and restart required per field * add special case and comments for global motion section * add section form special cases * combine review sections * tweaks * add audio labels endpoint * add audio label switches and input to filter list * fix type * remove key from config when resetting to default/global * don't show description for new key/val fields * tweaks * spacing tweaks * add activity indicator and scrollbar tweaks * add docs to filter fields * wording changes * fix global ffmpeg section * add review classification zones to review form * add backend endpoint and frontend widget for ffmpeg presets and manual args * improve wording * hide descriptions for additional properties arrays * add warning log about incorrectly nested model config * spacing and language tweaks * fix i18n keys * networking section docs and description * small wording tweaks * add layout grid field * refactor with shared utilities * field order * add individual detectors to schema add detector titles and descriptions (docstrings in pydantic are used for descriptions) and add i18n keys to globals * clean up detectors section and i18n * don't save model config back to yaml when saving detectors * add full detectors config to api model dump works around the way we use detector plugins so we can have the full detector config for the frontend * add restart button to toast when restart is required * add ui option to remove inner cards * fix buttons * section tweaks * don't zoom into text on mobile * make buttons sticky at bottom of sections * small tweaks * highlight label of changed fields * add null to enum list when unwrapping * refactor to shared utils and add save all button * add undo all button * add RJSF to dictionary * consolidate utils * preserve form data when changing cameras * add mono fonts * add popover to show what fields will be saved * fix mobile menu not re-rendering with unsaved dots * tweaks * fix logger and env vars config section saving use escaped periods in keys to retain them in the config file (eg "frigate.embeddings") * add timezone widget * role map field with validation * fix validation for model section * add another hidden field * add footer message for required restart * use rjsf for notifications view * fix config saving * add replace rules field * default column layout and add field sizing * clean up field template * refactor profile settings to match rjsf forms * tweaks * refactor frigate+ view and make tweaks to sections * show frigate+ model info in detection model settings when using a frigate+ model * update restartRequired for all fields * fix restart fields * tweaks and add ability enable disabled cameras more backend changes required * require restart when enabling camera that is disabled in config * disable save when form is invalid * refactor ffmpeg section for readability * change label * clean up camera inputs fields * misc tweaks to ffmpeg section - add raw paths endpoint to ensure credentials get saved - restart required tooltip * maintenance settings tweaks * don't mutate with lodash * fix description re-rendering for nullable object fields * hide reindex field * update rjsf * add frigate+ description to settings pane * disable save all when any section is invalid * show translated field name in validation error pane * clean up * remove unused * fix genai merge * fix genai
2026-02-27 18:55:36 +03:00
<div className="flex size-full space-y-6">
<div className="scrollbar-container flex-1 overflow-y-auto pb-2">
{viewMode === "settings" ? (
<>
<Heading as="h4" className="mb-2">
{t("cameraManagement.title")}
</Heading>
<p className="mb-6 max-w-5xl text-sm text-muted-foreground">
{t("cameraManagement.description")}
</p>
Full UI configuration (#22151) * use react-jsonschema-form for UI config * don't use properties wrapper when generating config i18n json * configure for full i18n support * section fields * add descriptions to all fields for i18n * motion i18n * fix nullable fields * sanitize internal fields * add switches widgets and use friendly names * fix nullable schema entries * ensure update_topic is added to api calls this needs further backend implementation to work correctly * add global sections, camera config overrides, and reset button * i18n * add reset logic to global config view * tweaks * fix sections and live validation * fix validation for schema objects that can be null * generic and custom per-field validation * improve generic error validation messages * remove show advanced fields switch * tweaks * use shadcn theme * fix array field template * i18n tweaks * remove collapsible around root section * deep merge schema for advanced fields * add array field item template and fix ffmpeg section * add missing i18n keys * tweaks * comment out api call for testing * add config groups as a separate i18n namespace * add descriptions to all pydantic fields * make titles more concise * new titles as i18n * update i18n config generation script to use json schema * tweaks * tweaks * rebase * clean up * form tweaks * add wildcards and fix object filter fields * add field template for additionalproperties schema objects * improve typing * add section description from schema and clarify global vs camera level descriptions * separate and consolidate global and camera i18n namespaces * clean up now obsolete namespaces * tweaks * refactor sections and overrides * add ability to render components before and after fields * fix titles * chore(sections): remove legacy single-section components replaced by template * refactor configs to use individual files with a template * fix review description * apply hidden fields after ui schema * move util * remove unused i18n * clean up error messages * fix fast refresh * add custom validation and use it for ffmpeg input roles * update nav tree * remove unused * re-add override and modified indicators * mark pending changes and add confirmation dialog for resets * fix red unsaved dot * tweaks * add docs links, readonly keys, and restart required per field * add special case and comments for global motion section * add section form special cases * combine review sections * tweaks * add audio labels endpoint * add audio label switches and input to filter list * fix type * remove key from config when resetting to default/global * don't show description for new key/val fields * tweaks * spacing tweaks * add activity indicator and scrollbar tweaks * add docs to filter fields * wording changes * fix global ffmpeg section * add review classification zones to review form * add backend endpoint and frontend widget for ffmpeg presets and manual args * improve wording * hide descriptions for additional properties arrays * add warning log about incorrectly nested model config * spacing and language tweaks * fix i18n keys * networking section docs and description * small wording tweaks * add layout grid field * refactor with shared utilities * field order * add individual detectors to schema add detector titles and descriptions (docstrings in pydantic are used for descriptions) and add i18n keys to globals * clean up detectors section and i18n * don't save model config back to yaml when saving detectors * add full detectors config to api model dump works around the way we use detector plugins so we can have the full detector config for the frontend * add restart button to toast when restart is required * add ui option to remove inner cards * fix buttons * section tweaks * don't zoom into text on mobile * make buttons sticky at bottom of sections * small tweaks * highlight label of changed fields * add null to enum list when unwrapping * refactor to shared utils and add save all button * add undo all button * add RJSF to dictionary * consolidate utils * preserve form data when changing cameras * add mono fonts * add popover to show what fields will be saved * fix mobile menu not re-rendering with unsaved dots * tweaks * fix logger and env vars config section saving use escaped periods in keys to retain them in the config file (eg "frigate.embeddings") * add timezone widget * role map field with validation * fix validation for model section * add another hidden field * add footer message for required restart * use rjsf for notifications view * fix config saving * add replace rules field * default column layout and add field sizing * clean up field template * refactor profile settings to match rjsf forms * tweaks * refactor frigate+ view and make tweaks to sections * show frigate+ model info in detection model settings when using a frigate+ model * update restartRequired for all fields * fix restart fields * tweaks and add ability enable disabled cameras more backend changes required * require restart when enabling camera that is disabled in config * disable save when form is invalid * refactor ffmpeg section for readability * change label * clean up camera inputs fields * misc tweaks to ffmpeg section - add raw paths endpoint to ensure credentials get saved - restart required tooltip * maintenance settings tweaks * don't mutate with lodash * fix description re-rendering for nullable object fields * hide reindex field * update rjsf * add frigate+ description to settings pane * disable save all when any section is invalid * show translated field name in validation error pane * clean up * remove unused * fix genai merge * fix genai
2026-02-27 18:55:36 +03:00
<div className="w-full max-w-5xl space-y-6">
<div className="flex gap-2">
<Button
variant="select"
onClick={() => setShowWizard(true)}
className="mb-2 flex max-w-48 items-center gap-2"
>
<LuPlus className="h-4 w-4" />
{t("cameraManagement.addCamera")}
</Button>
{enabledCameras.length + disabledCameras.length > 0 && (
<Button
variant="destructive"
onClick={() => setShowDeleteDialog(true)}
className="mb-2 flex max-w-48 items-center gap-2 text-white"
>
<LuTrash2 className="h-4 w-4" />
{t("cameraManagement.deleteCamera")}
</Button>
)}
</div>
Full UI configuration (#22151) * use react-jsonschema-form for UI config * don't use properties wrapper when generating config i18n json * configure for full i18n support * section fields * add descriptions to all fields for i18n * motion i18n * fix nullable fields * sanitize internal fields * add switches widgets and use friendly names * fix nullable schema entries * ensure update_topic is added to api calls this needs further backend implementation to work correctly * add global sections, camera config overrides, and reset button * i18n * add reset logic to global config view * tweaks * fix sections and live validation * fix validation for schema objects that can be null * generic and custom per-field validation * improve generic error validation messages * remove show advanced fields switch * tweaks * use shadcn theme * fix array field template * i18n tweaks * remove collapsible around root section * deep merge schema for advanced fields * add array field item template and fix ffmpeg section * add missing i18n keys * tweaks * comment out api call for testing * add config groups as a separate i18n namespace * add descriptions to all pydantic fields * make titles more concise * new titles as i18n * update i18n config generation script to use json schema * tweaks * tweaks * rebase * clean up * form tweaks * add wildcards and fix object filter fields * add field template for additionalproperties schema objects * improve typing * add section description from schema and clarify global vs camera level descriptions * separate and consolidate global and camera i18n namespaces * clean up now obsolete namespaces * tweaks * refactor sections and overrides * add ability to render components before and after fields * fix titles * chore(sections): remove legacy single-section components replaced by template * refactor configs to use individual files with a template * fix review description * apply hidden fields after ui schema * move util * remove unused i18n * clean up error messages * fix fast refresh * add custom validation and use it for ffmpeg input roles * update nav tree * remove unused * re-add override and modified indicators * mark pending changes and add confirmation dialog for resets * fix red unsaved dot * tweaks * add docs links, readonly keys, and restart required per field * add special case and comments for global motion section * add section form special cases * combine review sections * tweaks * add audio labels endpoint * add audio label switches and input to filter list * fix type * remove key from config when resetting to default/global * don't show description for new key/val fields * tweaks * spacing tweaks * add activity indicator and scrollbar tweaks * add docs to filter fields * wording changes * fix global ffmpeg section * add review classification zones to review form * add backend endpoint and frontend widget for ffmpeg presets and manual args * improve wording * hide descriptions for additional properties arrays * add warning log about incorrectly nested model config * spacing and language tweaks * fix i18n keys * networking section docs and description * small wording tweaks * add layout grid field * refactor with shared utilities * field order * add individual detectors to schema add detector titles and descriptions (docstrings in pydantic are used for descriptions) and add i18n keys to globals * clean up detectors section and i18n * don't save model config back to yaml when saving detectors * add full detectors config to api model dump works around the way we use detector plugins so we can have the full detector config for the frontend * add restart button to toast when restart is required * add ui option to remove inner cards * fix buttons * section tweaks * don't zoom into text on mobile * make buttons sticky at bottom of sections * small tweaks * highlight label of changed fields * add null to enum list when unwrapping * refactor to shared utils and add save all button * add undo all button * add RJSF to dictionary * consolidate utils * preserve form data when changing cameras * add mono fonts * add popover to show what fields will be saved * fix mobile menu not re-rendering with unsaved dots * tweaks * fix logger and env vars config section saving use escaped periods in keys to retain them in the config file (eg "frigate.embeddings") * add timezone widget * role map field with validation * fix validation for model section * add another hidden field * add footer message for required restart * use rjsf for notifications view * fix config saving * add replace rules field * default column layout and add field sizing * clean up field template * refactor profile settings to match rjsf forms * tweaks * refactor frigate+ view and make tweaks to sections * show frigate+ model info in detection model settings when using a frigate+ model * update restartRequired for all fields * fix restart fields * tweaks and add ability enable disabled cameras more backend changes required * require restart when enabling camera that is disabled in config * disable save when form is invalid * refactor ffmpeg section for readability * change label * clean up camera inputs fields * misc tweaks to ffmpeg section - add raw paths endpoint to ensure credentials get saved - restart required tooltip * maintenance settings tweaks * don't mutate with lodash * fix description re-rendering for nullable object fields * hide reindex field * update rjsf * add frigate+ description to settings pane * disable save all when any section is invalid * show translated field name in validation error pane * clean up * remove unused * fix genai merge * fix genai
2026-02-27 18:55:36 +03:00
{enabledCameras.length > 0 && (
<SettingsGroupCard
title={
<Trans ns="views/settings">
cameraManagement.streams.title
</Trans>
}
>
<div className={SPLIT_ROW_CLASS_NAME}>
<div className="space-y-1.5">
<Label
className="cursor-pointer"
htmlFor={"enabled-cameras-switch"}
>
{t("cameraManagement.streams.enableLabel")}
<p className="hidden text-sm text-muted-foreground md:block">
<Trans ns="views/settings">
cameraManagement.streams.enableDesc
</Trans>
</p>
</Label>
</div>
<div className="max-w-md space-y-1.5">
<Reorder.Group
as="div"
axis="y"
values={orderedCameras}
onReorder={setOrderedCameras}
className="space-y-2 rounded-lg bg-secondary p-4"
>
{orderedCameras.map((camera) => (
<EnabledCameraRow
key={camera}
camera={camera}
onConfigChanged={updateConfig}
onDragEnd={handleReorderDragEnd}
/>
))}
</Reorder.Group>
<ReorderSaveStatusIndicator
status={reorderSaveStatus}
/>
</div>
Full UI configuration (#22151) * use react-jsonschema-form for UI config * don't use properties wrapper when generating config i18n json * configure for full i18n support * section fields * add descriptions to all fields for i18n * motion i18n * fix nullable fields * sanitize internal fields * add switches widgets and use friendly names * fix nullable schema entries * ensure update_topic is added to api calls this needs further backend implementation to work correctly * add global sections, camera config overrides, and reset button * i18n * add reset logic to global config view * tweaks * fix sections and live validation * fix validation for schema objects that can be null * generic and custom per-field validation * improve generic error validation messages * remove show advanced fields switch * tweaks * use shadcn theme * fix array field template * i18n tweaks * remove collapsible around root section * deep merge schema for advanced fields * add array field item template and fix ffmpeg section * add missing i18n keys * tweaks * comment out api call for testing * add config groups as a separate i18n namespace * add descriptions to all pydantic fields * make titles more concise * new titles as i18n * update i18n config generation script to use json schema * tweaks * tweaks * rebase * clean up * form tweaks * add wildcards and fix object filter fields * add field template for additionalproperties schema objects * improve typing * add section description from schema and clarify global vs camera level descriptions * separate and consolidate global and camera i18n namespaces * clean up now obsolete namespaces * tweaks * refactor sections and overrides * add ability to render components before and after fields * fix titles * chore(sections): remove legacy single-section components replaced by template * refactor configs to use individual files with a template * fix review description * apply hidden fields after ui schema * move util * remove unused i18n * clean up error messages * fix fast refresh * add custom validation and use it for ffmpeg input roles * update nav tree * remove unused * re-add override and modified indicators * mark pending changes and add confirmation dialog for resets * fix red unsaved dot * tweaks * add docs links, readonly keys, and restart required per field * add special case and comments for global motion section * add section form special cases * combine review sections * tweaks * add audio labels endpoint * add audio label switches and input to filter list * fix type * remove key from config when resetting to default/global * don't show description for new key/val fields * tweaks * spacing tweaks * add activity indicator and scrollbar tweaks * add docs to filter fields * wording changes * fix global ffmpeg section * add review classification zones to review form * add backend endpoint and frontend widget for ffmpeg presets and manual args * improve wording * hide descriptions for additional properties arrays * add warning log about incorrectly nested model config * spacing and language tweaks * fix i18n keys * networking section docs and description * small wording tweaks * add layout grid field * refactor with shared utilities * field order * add individual detectors to schema add detector titles and descriptions (docstrings in pydantic are used for descriptions) and add i18n keys to globals * clean up detectors section and i18n * don't save model config back to yaml when saving detectors * add full detectors config to api model dump works around the way we use detector plugins so we can have the full detector config for the frontend * add restart button to toast when restart is required * add ui option to remove inner cards * fix buttons * section tweaks * don't zoom into text on mobile * make buttons sticky at bottom of sections * small tweaks * highlight label of changed fields * add null to enum list when unwrapping * refactor to shared utils and add save all button * add undo all button * add RJSF to dictionary * consolidate utils * preserve form data when changing cameras * add mono fonts * add popover to show what fields will be saved * fix mobile menu not re-rendering with unsaved dots * tweaks * fix logger and env vars config section saving use escaped periods in keys to retain them in the config file (eg "frigate.embeddings") * add timezone widget * role map field with validation * fix validation for model section * add another hidden field * add footer message for required restart * use rjsf for notifications view * fix config saving * add replace rules field * default column layout and add field sizing * clean up field template * refactor profile settings to match rjsf forms * tweaks * refactor frigate+ view and make tweaks to sections * show frigate+ model info in detection model settings when using a frigate+ model * update restartRequired for all fields * fix restart fields * tweaks and add ability enable disabled cameras more backend changes required * require restart when enabling camera that is disabled in config * disable save when form is invalid * refactor ffmpeg section for readability * change label * clean up camera inputs fields * misc tweaks to ffmpeg section - add raw paths endpoint to ensure credentials get saved - restart required tooltip * maintenance settings tweaks * don't mutate with lodash * fix description re-rendering for nullable object fields * hide reindex field * update rjsf * add frigate+ description to settings pane * disable save all when any section is invalid * show translated field name in validation error pane * clean up * remove unused * fix genai merge * fix genai
2026-02-27 18:55:36 +03:00
<p className="text-sm text-muted-foreground md:hidden">
<Trans ns="views/settings">
cameraManagement.streams.enableDesc
</Trans>
</p>
</div>
Full UI configuration (#22151) * use react-jsonschema-form for UI config * don't use properties wrapper when generating config i18n json * configure for full i18n support * section fields * add descriptions to all fields for i18n * motion i18n * fix nullable fields * sanitize internal fields * add switches widgets and use friendly names * fix nullable schema entries * ensure update_topic is added to api calls this needs further backend implementation to work correctly * add global sections, camera config overrides, and reset button * i18n * add reset logic to global config view * tweaks * fix sections and live validation * fix validation for schema objects that can be null * generic and custom per-field validation * improve generic error validation messages * remove show advanced fields switch * tweaks * use shadcn theme * fix array field template * i18n tweaks * remove collapsible around root section * deep merge schema for advanced fields * add array field item template and fix ffmpeg section * add missing i18n keys * tweaks * comment out api call for testing * add config groups as a separate i18n namespace * add descriptions to all pydantic fields * make titles more concise * new titles as i18n * update i18n config generation script to use json schema * tweaks * tweaks * rebase * clean up * form tweaks * add wildcards and fix object filter fields * add field template for additionalproperties schema objects * improve typing * add section description from schema and clarify global vs camera level descriptions * separate and consolidate global and camera i18n namespaces * clean up now obsolete namespaces * tweaks * refactor sections and overrides * add ability to render components before and after fields * fix titles * chore(sections): remove legacy single-section components replaced by template * refactor configs to use individual files with a template * fix review description * apply hidden fields after ui schema * move util * remove unused i18n * clean up error messages * fix fast refresh * add custom validation and use it for ffmpeg input roles * update nav tree * remove unused * re-add override and modified indicators * mark pending changes and add confirmation dialog for resets * fix red unsaved dot * tweaks * add docs links, readonly keys, and restart required per field * add special case and comments for global motion section * add section form special cases * combine review sections * tweaks * add audio labels endpoint * add audio label switches and input to filter list * fix type * remove key from config when resetting to default/global * don't show description for new key/val fields * tweaks * spacing tweaks * add activity indicator and scrollbar tweaks * add docs to filter fields * wording changes * fix global ffmpeg section * add review classification zones to review form * add backend endpoint and frontend widget for ffmpeg presets and manual args * improve wording * hide descriptions for additional properties arrays * add warning log about incorrectly nested model config * spacing and language tweaks * fix i18n keys * networking section docs and description * small wording tweaks * add layout grid field * refactor with shared utilities * field order * add individual detectors to schema add detector titles and descriptions (docstrings in pydantic are used for descriptions) and add i18n keys to globals * clean up detectors section and i18n * don't save model config back to yaml when saving detectors * add full detectors config to api model dump works around the way we use detector plugins so we can have the full detector config for the frontend * add restart button to toast when restart is required * add ui option to remove inner cards * fix buttons * section tweaks * don't zoom into text on mobile * make buttons sticky at bottom of sections * small tweaks * highlight label of changed fields * add null to enum list when unwrapping * refactor to shared utils and add save all button * add undo all button * add RJSF to dictionary * consolidate utils * preserve form data when changing cameras * add mono fonts * add popover to show what fields will be saved * fix mobile menu not re-rendering with unsaved dots * tweaks * fix logger and env vars config section saving use escaped periods in keys to retain them in the config file (eg "frigate.embeddings") * add timezone widget * role map field with validation * fix validation for model section * add another hidden field * add footer message for required restart * use rjsf for notifications view * fix config saving * add replace rules field * default column layout and add field sizing * clean up field template * refactor profile settings to match rjsf forms * tweaks * refactor frigate+ view and make tweaks to sections * show frigate+ model info in detection model settings when using a frigate+ model * update restartRequired for all fields * fix restart fields * tweaks and add ability enable disabled cameras more backend changes required * require restart when enabling camera that is disabled in config * disable save when form is invalid * refactor ffmpeg section for readability * change label * clean up camera inputs fields * misc tweaks to ffmpeg section - add raw paths endpoint to ensure credentials get saved - restart required tooltip * maintenance settings tweaks * don't mutate with lodash * fix description re-rendering for nullable object fields * hide reindex field * update rjsf * add frigate+ description to settings pane * disable save all when any section is invalid * show translated field name in validation error pane * clean up * remove unused * fix genai merge * fix genai
2026-02-27 18:55:36 +03:00
{disabledCameras.length > 0 && (
<div className={SPLIT_ROW_CLASS_NAME}>
<div className="space-y-1.5">
<Label
className="cursor-pointer"
htmlFor={"disabled-cameras-switch"}
>
{t("cameraManagement.streams.disableLabel")}
<RestartRequiredIndicator className="ml-1" />
</Label>
<p className="hidden text-sm text-muted-foreground md:block">
{t("cameraManagement.streams.disableDesc")}
</p>
</div>
<div
className={`${CONTROL_COLUMN_CLASS_NAME} space-y-1.5`}
>
<div className="max-w-md space-y-2 rounded-lg bg-secondary p-4">
{disabledCameras.map((camera) => (
<div
key={camera}
className="flex flex-row items-center justify-between"
>
<CameraNameLabel camera={camera} />
<CameraConfigEnableSwitch
cameraName={camera}
onConfigChanged={updateConfig}
setRestartDialogOpen={setRestartDialogOpen}
/>
</div>
))}
</div>
<p className="text-sm text-muted-foreground md:hidden">
{t("cameraManagement.streams.disableDesc")}
</p>
</div>
</div>
)}
</SettingsGroupCard>
)}
Camera profile support (#22482) * add CameraProfileConfig model for named config overrides * add profiles field to CameraConfig * add active_profile field to FrigateConfig Runtime-only field excluded from YAML serialization, tracks which profile is currently active. * add ProfileManager for profile activation and persistence Handles snapshotting base configs, applying profile overrides via deep_merge + apply_section_update, publishing ZMQ updates, and persisting active profile to /config/.active_profile. * add profile API endpoints (GET /profiles, GET/PUT /profile) * add MQTT and dispatcher integration for profiles - Subscribe to frigate/profile/set MQTT topic - Publish profile/state and profiles/available on connect - Add _on_profile_command handler to dispatcher - Broadcast active profile state on WebSocket connect * wire ProfileManager into app startup and FastAPI - Create ProfileManager after dispatcher init - Restore persisted profile on startup - Pass dispatcher and profile_manager to FastAPI app * add tests for invalid profile values and keys Tests that Pydantic rejects: invalid field values (fps: "not_a_number"), unknown section keys (ffmpeg in profile), invalid nested values, and invalid profiles in full config parsing. * formatting * fix CameraLiveConfig JSON serialization error on profile activation refactor _publish_updates to only publish ZMQ updates for sections that actually changed, not all sections on affected cameras. * consolidate * add enabled field to camera profiles for enabling/disabling cameras * add zones support to camera profiles * add frontend profile types, color utility, and config save support * add profile state management and save preview support * add profileName prop to BaseSection for profile-aware config editing * add profile section dropdown and wire into camera settings pages * add per-profile camera enable/disable to Camera Management view * add profiles summary page with card-based layout and fix backend zone comparison bug * add active profile badge to settings toolbar * i18n * add red dot for any pending changes including profiles * profile support for mask and zone editor * fix hidden field validation errors caused by lodash wildcard and schema gaps lodash unset does not support wildcard (*) segments, so hidden fields like filters.*.mask were never stripped from form data, leaving null raw_coordinates that fail RJSF anyOf validation. Add unsetWithWildcard helper and also strip hidden fields from the JSON schema itself as defense-in-depth. * add face_recognition and lpr to profile-eligible sections * move profile dropdown from section panes to settings header * add profiles enable toggle and improve empty state * formatting * tweaks * tweak colors and switch * fix profile save diff, masksAndZones delete, and config sync * ui tweaks * ensure profile manager gets updated config * rename profile settings to ui settings * refactor profilesview and add dots/border colors when overridden * implement an update_config method for profile manager * fix mask deletion * more unique colors * add top-level profiles config section with friendly names * implement profile friendly names and improve profile UI - Add ProfileDefinitionConfig type and profiles field to FrigateConfig - Use ProfilesApiResponse type with friendly_name support throughout - Replace Record<string, unknown> with proper JsonObject/JsonValue types - Add profile creation form matching zone pattern (Zod + NameAndIdFields) - Add pencil icon for renaming profile friendly names in ProfilesView - Move Profiles menu item to first under Camera Configuration - Add activity indicators on save/rename/delete buttons - Display friendly names in CameraManagementView profile selector - Fix duplicate colored dots in management profile dropdown - Fix i18n namespace for overridden base config tooltips - Move profile override deletion from dropdown trash icon to footer button with confirmation dialog, matching Reset to Global pattern - Remove Add Profile from section header dropdown to prevent saving camera overrides before top-level profile definition exists - Clean up newProfiles state after API profile deletion - Refresh profiles SWR cache after saving profile definitions * remove profile badge in settings and add profiles to main menu * use icon only on mobile * change color order * docs * show activity indicator on trash icon while deleting a profile * tweak language * immediately create profiles on backend instead of deferring to Save All * hide restart-required fields when editing a profile section fields that require a restart cannot take effect via profile switching, so they are merged into hiddenFields when profileName is set * show active profile indicator in desktop status bar * fix profile config inheritance bug where Pydantic defaults override base values The /config API was dumping profile overrides with model_dump() which included all Pydantic defaults. When the frontend merged these over the camera's base config, explicitly-set base values were lost. Now profile overrides are re-dumped with exclude_unset=True so only user-specified fields are returned. Also fixes the Save All path generating spurious deletion markers for restart-required fields that are hidden during profile editing but not excluded from the raw data sanitization in prepareSectionSavePayload. * docs tweaks * docs tweak * formatting * formatting * fix typing * fix test pollution test_maintainer was injecting MagicMock() into sys.modules["frigate.config.camera.updater"] at module load time and never restoring it. When the profile tests later imported CameraConfigUpdateEnum and CameraConfigUpdateTopic from that module, they got mock objects instead of the real dataclass/enum, so equality comparisons always failed * remove * fix settings showing profile-merged values when editing base config When a profile is active, the in-memory config contains effective (profile-merged) values. The settings UI was displaying these merged values even when the "Base Config" view was selected. Backend: snapshot pre-profile base configs in ProfileManager and expose them via a `base_config` key in the /api/config camera response when a profile is active. The top-level sections continue to reflect the effective running config. Frontend: read from `base_config` when available in BaseSection, useConfigOverride, useAllCameraOverrides, and prepareSectionSavePayload. Include formData labels in Object/Audio switches widgets so that labels added only by a profile override remain visible when editing that profile. * use rasterized_mask as field makes it easier to exclude from the schema with exclude=True prevents leaking of the field when using model_dump for profiles * fix zones - Fix zone colors not matching across profiles by falling back to base zone color when profile zone data lacks a color field - Use base_config for base-layer values in masks/zones view so profile-merged values don't pollute the base config editing view - Handle zones separately in profile manager snapshot/restore since ZoneConfig requires special serialization (color as private attr, contour generation) - Inherit base zone color and generate contours for profile zone overrides in profile manager * formatting * don't require restart for camera enabled change for profiles * publish camera state when changing profiles * formatting * remove available profiles from mqtt * improve typing
2026-03-19 17:47:57 +03:00
{profileState &&
profileState.allProfileNames.length > 0 &&
enabledCameras.length > 0 && (
<ProfileCameraEnableSection
profileState={profileState}
cameras={enabledCameras}
config={config}
onConfigChanged={updateConfig}
/>
)}
{config?.lpr?.enabled && allCameras.length > 0 && (
<CameraTypeSection
cameras={allCameras}
config={config}
onConfigChanged={updateConfig}
setRestartDialogOpen={setRestartDialogOpen}
/>
)}
</div>
</>
) : (
<>
<div className="mb-4 flex items-center gap-2">
<Button
className={`flex items-center gap-2.5 rounded-lg`}
aria-label={t("label.back", { ns: "common" })}
size="sm"
onClick={handleBack}
>
<IoMdArrowRoundBack className="size-5 text-secondary-foreground" />
{isDesktop && (
<div className="text-primary">
{t("button.back", { ns: "common" })}
</div>
)}
</Button>
</div>
<div className="md:max-w-5xl">
<CameraEditForm
cameraName={viewMode === "edit" ? editCameraName : undefined}
onSave={handleBack}
onCancel={handleBack}
/>
</div>
</>
)}
</div>
</div>
<CameraWizardDialog
open={showWizard}
onClose={() => setShowWizard(false)}
/>
<DeleteCameraDialog
show={showDeleteDialog}
cameras={[...enabledCameras, ...disabledCameras]}
onClose={() => setShowDeleteDialog(false)}
onDeleted={() => {
setShowDeleteDialog(false);
updateConfig();
}}
/>
Full UI configuration (#22151) * use react-jsonschema-form for UI config * don't use properties wrapper when generating config i18n json * configure for full i18n support * section fields * add descriptions to all fields for i18n * motion i18n * fix nullable fields * sanitize internal fields * add switches widgets and use friendly names * fix nullable schema entries * ensure update_topic is added to api calls this needs further backend implementation to work correctly * add global sections, camera config overrides, and reset button * i18n * add reset logic to global config view * tweaks * fix sections and live validation * fix validation for schema objects that can be null * generic and custom per-field validation * improve generic error validation messages * remove show advanced fields switch * tweaks * use shadcn theme * fix array field template * i18n tweaks * remove collapsible around root section * deep merge schema for advanced fields * add array field item template and fix ffmpeg section * add missing i18n keys * tweaks * comment out api call for testing * add config groups as a separate i18n namespace * add descriptions to all pydantic fields * make titles more concise * new titles as i18n * update i18n config generation script to use json schema * tweaks * tweaks * rebase * clean up * form tweaks * add wildcards and fix object filter fields * add field template for additionalproperties schema objects * improve typing * add section description from schema and clarify global vs camera level descriptions * separate and consolidate global and camera i18n namespaces * clean up now obsolete namespaces * tweaks * refactor sections and overrides * add ability to render components before and after fields * fix titles * chore(sections): remove legacy single-section components replaced by template * refactor configs to use individual files with a template * fix review description * apply hidden fields after ui schema * move util * remove unused i18n * clean up error messages * fix fast refresh * add custom validation and use it for ffmpeg input roles * update nav tree * remove unused * re-add override and modified indicators * mark pending changes and add confirmation dialog for resets * fix red unsaved dot * tweaks * add docs links, readonly keys, and restart required per field * add special case and comments for global motion section * add section form special cases * combine review sections * tweaks * add audio labels endpoint * add audio label switches and input to filter list * fix type * remove key from config when resetting to default/global * don't show description for new key/val fields * tweaks * spacing tweaks * add activity indicator and scrollbar tweaks * add docs to filter fields * wording changes * fix global ffmpeg section * add review classification zones to review form * add backend endpoint and frontend widget for ffmpeg presets and manual args * improve wording * hide descriptions for additional properties arrays * add warning log about incorrectly nested model config * spacing and language tweaks * fix i18n keys * networking section docs and description * small wording tweaks * add layout grid field * refactor with shared utilities * field order * add individual detectors to schema add detector titles and descriptions (docstrings in pydantic are used for descriptions) and add i18n keys to globals * clean up detectors section and i18n * don't save model config back to yaml when saving detectors * add full detectors config to api model dump works around the way we use detector plugins so we can have the full detector config for the frontend * add restart button to toast when restart is required * add ui option to remove inner cards * fix buttons * section tweaks * don't zoom into text on mobile * make buttons sticky at bottom of sections * small tweaks * highlight label of changed fields * add null to enum list when unwrapping * refactor to shared utils and add save all button * add undo all button * add RJSF to dictionary * consolidate utils * preserve form data when changing cameras * add mono fonts * add popover to show what fields will be saved * fix mobile menu not re-rendering with unsaved dots * tweaks * fix logger and env vars config section saving use escaped periods in keys to retain them in the config file (eg "frigate.embeddings") * add timezone widget * role map field with validation * fix validation for model section * add another hidden field * add footer message for required restart * use rjsf for notifications view * fix config saving * add replace rules field * default column layout and add field sizing * clean up field template * refactor profile settings to match rjsf forms * tweaks * refactor frigate+ view and make tweaks to sections * show frigate+ model info in detection model settings when using a frigate+ model * update restartRequired for all fields * fix restart fields * tweaks and add ability enable disabled cameras more backend changes required * require restart when enabling camera that is disabled in config * disable save when form is invalid * refactor ffmpeg section for readability * change label * clean up camera inputs fields * misc tweaks to ffmpeg section - add raw paths endpoint to ensure credentials get saved - restart required tooltip * maintenance settings tweaks * don't mutate with lodash * fix description re-rendering for nullable object fields * hide reindex field * update rjsf * add frigate+ description to settings pane * disable save all when any section is invalid * show translated field name in validation error pane * clean up * remove unused * fix genai merge * fix genai
2026-02-27 18:55:36 +03:00
<RestartDialog
isOpen={restartDialogOpen}
onClose={() => setRestartDialogOpen(false)}
onRestart={() => sendRestart("restart")}
/>
</>
);
}
type ReorderSaveStatusIndicatorProps = {
status: ReorderSaveStatus;
};
function ReorderSaveStatusIndicator({
status,
}: ReorderSaveStatusIndicatorProps) {
const { t } = useTranslation(["views/settings"]);
return (
<div
aria-live="polite"
className={cn(
"flex h-4 items-center justify-start gap-1 text-xs transition-opacity duration-200",
status === "idle" ? "opacity-0" : "opacity-100",
)}
>
{status === "saving" && (
<span className="text-muted-foreground">
{t("cameraManagement.streams.saving")}
</span>
)}
{status === "saved" && (
<span className="flex items-center gap-1 text-success">
<LuCheck className="size-3.5" />
{t("cameraManagement.streams.saved")}
</span>
)}
</div>
);
}
type EnabledCameraRowProps = {
camera: string;
onConfigChanged: () => Promise<unknown>;
onDragEnd: () => void;
};
function EnabledCameraRow({
camera,
onConfigChanged,
onDragEnd,
}: EnabledCameraRowProps) {
const { t } = useTranslation(["views/settings"]);
const controls = useDragControls();
return (
<Reorder.Item
as="div"
value={camera}
dragListener={false}
dragControls={controls}
onDragEnd={onDragEnd}
className="flex flex-row items-center justify-between"
>
<div className="flex items-center gap-1">
<button
type="button"
onPointerDown={(e) => controls.start(e)}
className="-ml-1 cursor-grab touch-none rounded p-1 text-muted-foreground hover:text-primary active:cursor-grabbing"
aria-label={t("cameraManagement.streams.reorderHandle")}
>
<LuGripVertical className="size-4" />
</button>
<CameraNameLabel camera={camera} />
<CameraFriendlyNameEditor
cameraName={camera}
onConfigChanged={onConfigChanged}
/>
</div>
<CameraEnableSwitch cameraName={camera} />
</Reorder.Item>
);
}
type CameraEnableSwitchProps = {
cameraName: string;
};
function CameraEnableSwitch({ cameraName }: CameraEnableSwitchProps) {
const { payload: enabledState, send: sendEnabled } =
useEnabledState(cameraName);
UI fixes (#23127) * hide camera overrides badge from system sections * show empty card on camera metrics page when no cameras are defined * fix enabled camera state switch after adding via wizard Cameras added mid-session have no WS state until the dispatcher publishes camera_activity (which only happens on a fresh onConnect). Fall back to the config's enabled value so the switch reflects reality immediately after the wizard closes. * guard camera enabled access console would throw errors after adding via camera wizard * fix useOptimisticState dropping debounced setState under StrictMode * use openvino on cpu as default model - faster than tflite on cpu - add to default generated config * use an enum for model_size the frontend will then render this as a select dropdown because of the changes in the json schema * i18n * sync object filter entries with tracked labels in camera config form Filter sub-collapsibles in the camera Objects section are driven by `filters` dict keys, but profile merges and live track-switch edits don't add matching entries, so newly tracked labels (like from a profile override) had no collapsible. Synthesize default filter entries from `track` in the form data so every tracked label renders a collapsible; baseline data also gets the synthesized entries, so save payloads are unchanged. * revalidate raw paths cache after config save so CameraPathWidget shows fresh credentials * fix test * restore masked ffmpeg credentials when persisting camera config * formatting * rebuild ffmpeg commands when enabling recording for the first time Toggling record.enabled from the config UI updated the in-memory config but left ffmpeg running with its original command, so the record output args were never wired in and nothing landed in the cache for the maintainer to move. The record config update now rebuilds ffmpeg_cmds when enabled_in_config transitions, and the camera watchdog restarts ffmpeg on a false to true transition so the record output gets wired in. MQTT toggles, which only flip record.enabled at runtime, are unaffected and continue to work via the maintainer's drop/keep gate. * keep record toggle switch in single camera view disabled until enabled in config * fix override detection for sections unset in the global config Override badges and the blue dot now compare against schema defaults for sections like motion that the API serializes as null when omitted from the global YAML, instead of treating any populated camera config as an override * add support for config-aware patterns in section hiddenFields Section configs can now declare dynamic hidden-field entries as functions of the loaded config; objects.ts uses this to hide auto-populated attribute filters (DHL, face, license_plate, etc.) from the form, save flow, and override popover when those labels aren't user-settable * siimplify object filters handling live updating was getting very messy. users will just need to save once they enable a new object in order to see filters for that object * tweaks * update docs for new detector default * make genai provider required and add special case for UI prevent validation errors from appearing on initial creation of genai provider by setting the first option in the select dropdown as default
2026-05-07 16:53:07 +03:00
const { data: config } = useSWR<FrigateConfig>("config");
const isChecked =
enabledState === "ON" || enabledState === "OFF"
? enabledState === "ON"
: (config?.cameras?.[cameraName]?.enabled ?? false);
return (
<div className="flex flex-row items-center">
<Switch
id={`camera-enabled-${cameraName}`}
UI fixes (#23127) * hide camera overrides badge from system sections * show empty card on camera metrics page when no cameras are defined * fix enabled camera state switch after adding via wizard Cameras added mid-session have no WS state until the dispatcher publishes camera_activity (which only happens on a fresh onConnect). Fall back to the config's enabled value so the switch reflects reality immediately after the wizard closes. * guard camera enabled access console would throw errors after adding via camera wizard * fix useOptimisticState dropping debounced setState under StrictMode * use openvino on cpu as default model - faster than tflite on cpu - add to default generated config * use an enum for model_size the frontend will then render this as a select dropdown because of the changes in the json schema * i18n * sync object filter entries with tracked labels in camera config form Filter sub-collapsibles in the camera Objects section are driven by `filters` dict keys, but profile merges and live track-switch edits don't add matching entries, so newly tracked labels (like from a profile override) had no collapsible. Synthesize default filter entries from `track` in the form data so every tracked label renders a collapsible; baseline data also gets the synthesized entries, so save payloads are unchanged. * revalidate raw paths cache after config save so CameraPathWidget shows fresh credentials * fix test * restore masked ffmpeg credentials when persisting camera config * formatting * rebuild ffmpeg commands when enabling recording for the first time Toggling record.enabled from the config UI updated the in-memory config but left ffmpeg running with its original command, so the record output args were never wired in and nothing landed in the cache for the maintainer to move. The record config update now rebuilds ffmpeg_cmds when enabled_in_config transitions, and the camera watchdog restarts ffmpeg on a false to true transition so the record output gets wired in. MQTT toggles, which only flip record.enabled at runtime, are unaffected and continue to work via the maintainer's drop/keep gate. * keep record toggle switch in single camera view disabled until enabled in config * fix override detection for sections unset in the global config Override badges and the blue dot now compare against schema defaults for sections like motion that the API serializes as null when omitted from the global YAML, instead of treating any populated camera config as an override * add support for config-aware patterns in section hiddenFields Section configs can now declare dynamic hidden-field entries as functions of the loaded config; objects.ts uses this to hide auto-populated attribute filters (DHL, face, license_plate, etc.) from the form, save flow, and override popover when those labels aren't user-settable * siimplify object filters handling live updating was getting very messy. users will just need to save once they enable a new object in order to see filters for that object * tweaks * update docs for new detector default * make genai provider required and add special case for UI prevent validation errors from appearing on initial creation of genai provider by setting the first option in the select dropdown as default
2026-05-07 16:53:07 +03:00
checked={isChecked}
onCheckedChange={(isChecked) => {
sendEnabled(isChecked ? "ON" : "OFF");
}}
/>
</div>
);
}
Full UI configuration (#22151) * use react-jsonschema-form for UI config * don't use properties wrapper when generating config i18n json * configure for full i18n support * section fields * add descriptions to all fields for i18n * motion i18n * fix nullable fields * sanitize internal fields * add switches widgets and use friendly names * fix nullable schema entries * ensure update_topic is added to api calls this needs further backend implementation to work correctly * add global sections, camera config overrides, and reset button * i18n * add reset logic to global config view * tweaks * fix sections and live validation * fix validation for schema objects that can be null * generic and custom per-field validation * improve generic error validation messages * remove show advanced fields switch * tweaks * use shadcn theme * fix array field template * i18n tweaks * remove collapsible around root section * deep merge schema for advanced fields * add array field item template and fix ffmpeg section * add missing i18n keys * tweaks * comment out api call for testing * add config groups as a separate i18n namespace * add descriptions to all pydantic fields * make titles more concise * new titles as i18n * update i18n config generation script to use json schema * tweaks * tweaks * rebase * clean up * form tweaks * add wildcards and fix object filter fields * add field template for additionalproperties schema objects * improve typing * add section description from schema and clarify global vs camera level descriptions * separate and consolidate global and camera i18n namespaces * clean up now obsolete namespaces * tweaks * refactor sections and overrides * add ability to render components before and after fields * fix titles * chore(sections): remove legacy single-section components replaced by template * refactor configs to use individual files with a template * fix review description * apply hidden fields after ui schema * move util * remove unused i18n * clean up error messages * fix fast refresh * add custom validation and use it for ffmpeg input roles * update nav tree * remove unused * re-add override and modified indicators * mark pending changes and add confirmation dialog for resets * fix red unsaved dot * tweaks * add docs links, readonly keys, and restart required per field * add special case and comments for global motion section * add section form special cases * combine review sections * tweaks * add audio labels endpoint * add audio label switches and input to filter list * fix type * remove key from config when resetting to default/global * don't show description for new key/val fields * tweaks * spacing tweaks * add activity indicator and scrollbar tweaks * add docs to filter fields * wording changes * fix global ffmpeg section * add review classification zones to review form * add backend endpoint and frontend widget for ffmpeg presets and manual args * improve wording * hide descriptions for additional properties arrays * add warning log about incorrectly nested model config * spacing and language tweaks * fix i18n keys * networking section docs and description * small wording tweaks * add layout grid field * refactor with shared utilities * field order * add individual detectors to schema add detector titles and descriptions (docstrings in pydantic are used for descriptions) and add i18n keys to globals * clean up detectors section and i18n * don't save model config back to yaml when saving detectors * add full detectors config to api model dump works around the way we use detector plugins so we can have the full detector config for the frontend * add restart button to toast when restart is required * add ui option to remove inner cards * fix buttons * section tweaks * don't zoom into text on mobile * make buttons sticky at bottom of sections * small tweaks * highlight label of changed fields * add null to enum list when unwrapping * refactor to shared utils and add save all button * add undo all button * add RJSF to dictionary * consolidate utils * preserve form data when changing cameras * add mono fonts * add popover to show what fields will be saved * fix mobile menu not re-rendering with unsaved dots * tweaks * fix logger and env vars config section saving use escaped periods in keys to retain them in the config file (eg "frigate.embeddings") * add timezone widget * role map field with validation * fix validation for model section * add another hidden field * add footer message for required restart * use rjsf for notifications view * fix config saving * add replace rules field * default column layout and add field sizing * clean up field template * refactor profile settings to match rjsf forms * tweaks * refactor frigate+ view and make tweaks to sections * show frigate+ model info in detection model settings when using a frigate+ model * update restartRequired for all fields * fix restart fields * tweaks and add ability enable disabled cameras more backend changes required * require restart when enabling camera that is disabled in config * disable save when form is invalid * refactor ffmpeg section for readability * change label * clean up camera inputs fields * misc tweaks to ffmpeg section - add raw paths endpoint to ensure credentials get saved - restart required tooltip * maintenance settings tweaks * don't mutate with lodash * fix description re-rendering for nullable object fields * hide reindex field * update rjsf * add frigate+ description to settings pane * disable save all when any section is invalid * show translated field name in validation error pane * clean up * remove unused * fix genai merge * fix genai
2026-02-27 18:55:36 +03:00
type CameraFriendlyNameEditorProps = {
cameraName: string;
onConfigChanged: () => Promise<unknown>;
};
function CameraFriendlyNameEditor({
cameraName,
onConfigChanged,
}: CameraFriendlyNameEditorProps) {
const { t } = useTranslation(["views/settings", "common"]);
const { data: config } = useSWR<FrigateConfig>("config");
const [open, setOpen] = useState(false);
const [isSaving, setIsSaving] = useState(false);
const currentFriendlyName = config?.cameras?.[cameraName]?.friendly_name;
const onSave = useCallback(
async (text: string) => {
if (isSaving) return;
setIsSaving(true);
try {
await axios.put("config/set", {
requires_restart: 0,
config_data: {
cameras: {
[cameraName]: {
friendly_name: text.trim() || null,
},
},
},
});
await onConfigChanged();
setOpen(false);
toast.success(t("toast.save.success", { ns: "common" }), {
position: "top-center",
});
} catch (error) {
const errorMessage =
axios.isAxiosError(error) &&
(error.response?.data?.message || error.response?.data?.detail)
? error.response?.data?.message || error.response?.data?.detail
: t("toast.save.error.noMessage", { ns: "common" });
toast.error(
t("toast.save.error.title", { errorMessage, ns: "common" }),
{ position: "top-center" },
);
} finally {
setIsSaving(false);
}
},
[cameraName, isSaving, onConfigChanged, t],
);
const renameLabel = t("cameraManagement.streams.friendlyName.rename", {
ns: "views/settings",
});
return (
<>
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="ghost"
size="icon"
className="size-7"
aria-label={renameLabel}
onClick={() => setOpen(true)}
disabled={isSaving}
>
<LuPencil className="size-3.5" />
</Button>
</TooltipTrigger>
<TooltipContent>{renameLabel}</TooltipContent>
</Tooltip>
<TextEntryDialog
open={open}
setOpen={setOpen}
title={t("cameraManagement.streams.friendlyName.title", {
ns: "views/settings",
})}
description={t("cameraManagement.streams.friendlyName.description", {
ns: "views/settings",
})}
defaultValue={currentFriendlyName ?? ""}
placeholder={currentFriendlyName ? undefined : cameraName}
allowEmpty
isSaving={isSaving}
onSave={onSave}
/>
</>
);
}
Full UI configuration (#22151) * use react-jsonschema-form for UI config * don't use properties wrapper when generating config i18n json * configure for full i18n support * section fields * add descriptions to all fields for i18n * motion i18n * fix nullable fields * sanitize internal fields * add switches widgets and use friendly names * fix nullable schema entries * ensure update_topic is added to api calls this needs further backend implementation to work correctly * add global sections, camera config overrides, and reset button * i18n * add reset logic to global config view * tweaks * fix sections and live validation * fix validation for schema objects that can be null * generic and custom per-field validation * improve generic error validation messages * remove show advanced fields switch * tweaks * use shadcn theme * fix array field template * i18n tweaks * remove collapsible around root section * deep merge schema for advanced fields * add array field item template and fix ffmpeg section * add missing i18n keys * tweaks * comment out api call for testing * add config groups as a separate i18n namespace * add descriptions to all pydantic fields * make titles more concise * new titles as i18n * update i18n config generation script to use json schema * tweaks * tweaks * rebase * clean up * form tweaks * add wildcards and fix object filter fields * add field template for additionalproperties schema objects * improve typing * add section description from schema and clarify global vs camera level descriptions * separate and consolidate global and camera i18n namespaces * clean up now obsolete namespaces * tweaks * refactor sections and overrides * add ability to render components before and after fields * fix titles * chore(sections): remove legacy single-section components replaced by template * refactor configs to use individual files with a template * fix review description * apply hidden fields after ui schema * move util * remove unused i18n * clean up error messages * fix fast refresh * add custom validation and use it for ffmpeg input roles * update nav tree * remove unused * re-add override and modified indicators * mark pending changes and add confirmation dialog for resets * fix red unsaved dot * tweaks * add docs links, readonly keys, and restart required per field * add special case and comments for global motion section * add section form special cases * combine review sections * tweaks * add audio labels endpoint * add audio label switches and input to filter list * fix type * remove key from config when resetting to default/global * don't show description for new key/val fields * tweaks * spacing tweaks * add activity indicator and scrollbar tweaks * add docs to filter fields * wording changes * fix global ffmpeg section * add review classification zones to review form * add backend endpoint and frontend widget for ffmpeg presets and manual args * improve wording * hide descriptions for additional properties arrays * add warning log about incorrectly nested model config * spacing and language tweaks * fix i18n keys * networking section docs and description * small wording tweaks * add layout grid field * refactor with shared utilities * field order * add individual detectors to schema add detector titles and descriptions (docstrings in pydantic are used for descriptions) and add i18n keys to globals * clean up detectors section and i18n * don't save model config back to yaml when saving detectors * add full detectors config to api model dump works around the way we use detector plugins so we can have the full detector config for the frontend * add restart button to toast when restart is required * add ui option to remove inner cards * fix buttons * section tweaks * don't zoom into text on mobile * make buttons sticky at bottom of sections * small tweaks * highlight label of changed fields * add null to enum list when unwrapping * refactor to shared utils and add save all button * add undo all button * add RJSF to dictionary * consolidate utils * preserve form data when changing cameras * add mono fonts * add popover to show what fields will be saved * fix mobile menu not re-rendering with unsaved dots * tweaks * fix logger and env vars config section saving use escaped periods in keys to retain them in the config file (eg "frigate.embeddings") * add timezone widget * role map field with validation * fix validation for model section * add another hidden field * add footer message for required restart * use rjsf for notifications view * fix config saving * add replace rules field * default column layout and add field sizing * clean up field template * refactor profile settings to match rjsf forms * tweaks * refactor frigate+ view and make tweaks to sections * show frigate+ model info in detection model settings when using a frigate+ model * update restartRequired for all fields * fix restart fields * tweaks and add ability enable disabled cameras more backend changes required * require restart when enabling camera that is disabled in config * disable save when form is invalid * refactor ffmpeg section for readability * change label * clean up camera inputs fields * misc tweaks to ffmpeg section - add raw paths endpoint to ensure credentials get saved - restart required tooltip * maintenance settings tweaks * don't mutate with lodash * fix description re-rendering for nullable object fields * hide reindex field * update rjsf * add frigate+ description to settings pane * disable save all when any section is invalid * show translated field name in validation error pane * clean up * remove unused * fix genai merge * fix genai
2026-02-27 18:55:36 +03:00
type CameraConfigEnableSwitchProps = {
cameraName: string;
setRestartDialogOpen: React.Dispatch<React.SetStateAction<boolean>>;
onConfigChanged: () => Promise<unknown>;
};
function CameraConfigEnableSwitch({
cameraName,
onConfigChanged,
setRestartDialogOpen,
}: CameraConfigEnableSwitchProps) {
const { t } = useTranslation([
"common",
"views/settings",
"components/dialog",
]);
const [isSaving, setIsSaving] = useState(false);
const onCheckedChange = useCallback(
async (isChecked: boolean) => {
if (!isChecked || isSaving) {
return;
}
setIsSaving(true);
try {
await axios.put("config/set", {
requires_restart: 1,
config_data: {
cameras: {
[cameraName]: {
enabled: true,
},
},
},
});
await onConfigChanged();
toast.success(
t("cameraManagement.streams.enableSuccess", {
ns: "views/settings",
cameraName,
}),
{
position: "top-center",
action: (
<a onClick={() => setRestartDialogOpen(true)}>
<Button>
{t("restart.button", { ns: "components/dialog" })}
</Button>
</a>
),
},
);
} catch (error) {
const errorMessage =
axios.isAxiosError(error) &&
(error.response?.data?.message || error.response?.data?.detail)
? error.response?.data?.message || error.response?.data?.detail
: t("toast.save.error.noMessage", { ns: "common" });
toast.error(
t("toast.save.error.title", { errorMessage, ns: "common" }),
{
position: "top-center",
},
);
} finally {
setIsSaving(false);
}
},
[cameraName, isSaving, onConfigChanged, setRestartDialogOpen, t],
);
return (
<div className="flex flex-row items-center">
{isSaving ? (
<ActivityIndicator className="h-5 w-8" size={16} />
) : (
<Switch
id={`camera-enabled-${cameraName}`}
checked={false}
onCheckedChange={onCheckedChange}
/>
)}
</div>
);
}
Camera profile support (#22482) * add CameraProfileConfig model for named config overrides * add profiles field to CameraConfig * add active_profile field to FrigateConfig Runtime-only field excluded from YAML serialization, tracks which profile is currently active. * add ProfileManager for profile activation and persistence Handles snapshotting base configs, applying profile overrides via deep_merge + apply_section_update, publishing ZMQ updates, and persisting active profile to /config/.active_profile. * add profile API endpoints (GET /profiles, GET/PUT /profile) * add MQTT and dispatcher integration for profiles - Subscribe to frigate/profile/set MQTT topic - Publish profile/state and profiles/available on connect - Add _on_profile_command handler to dispatcher - Broadcast active profile state on WebSocket connect * wire ProfileManager into app startup and FastAPI - Create ProfileManager after dispatcher init - Restore persisted profile on startup - Pass dispatcher and profile_manager to FastAPI app * add tests for invalid profile values and keys Tests that Pydantic rejects: invalid field values (fps: "not_a_number"), unknown section keys (ffmpeg in profile), invalid nested values, and invalid profiles in full config parsing. * formatting * fix CameraLiveConfig JSON serialization error on profile activation refactor _publish_updates to only publish ZMQ updates for sections that actually changed, not all sections on affected cameras. * consolidate * add enabled field to camera profiles for enabling/disabling cameras * add zones support to camera profiles * add frontend profile types, color utility, and config save support * add profile state management and save preview support * add profileName prop to BaseSection for profile-aware config editing * add profile section dropdown and wire into camera settings pages * add per-profile camera enable/disable to Camera Management view * add profiles summary page with card-based layout and fix backend zone comparison bug * add active profile badge to settings toolbar * i18n * add red dot for any pending changes including profiles * profile support for mask and zone editor * fix hidden field validation errors caused by lodash wildcard and schema gaps lodash unset does not support wildcard (*) segments, so hidden fields like filters.*.mask were never stripped from form data, leaving null raw_coordinates that fail RJSF anyOf validation. Add unsetWithWildcard helper and also strip hidden fields from the JSON schema itself as defense-in-depth. * add face_recognition and lpr to profile-eligible sections * move profile dropdown from section panes to settings header * add profiles enable toggle and improve empty state * formatting * tweaks * tweak colors and switch * fix profile save diff, masksAndZones delete, and config sync * ui tweaks * ensure profile manager gets updated config * rename profile settings to ui settings * refactor profilesview and add dots/border colors when overridden * implement an update_config method for profile manager * fix mask deletion * more unique colors * add top-level profiles config section with friendly names * implement profile friendly names and improve profile UI - Add ProfileDefinitionConfig type and profiles field to FrigateConfig - Use ProfilesApiResponse type with friendly_name support throughout - Replace Record<string, unknown> with proper JsonObject/JsonValue types - Add profile creation form matching zone pattern (Zod + NameAndIdFields) - Add pencil icon for renaming profile friendly names in ProfilesView - Move Profiles menu item to first under Camera Configuration - Add activity indicators on save/rename/delete buttons - Display friendly names in CameraManagementView profile selector - Fix duplicate colored dots in management profile dropdown - Fix i18n namespace for overridden base config tooltips - Move profile override deletion from dropdown trash icon to footer button with confirmation dialog, matching Reset to Global pattern - Remove Add Profile from section header dropdown to prevent saving camera overrides before top-level profile definition exists - Clean up newProfiles state after API profile deletion - Refresh profiles SWR cache after saving profile definitions * remove profile badge in settings and add profiles to main menu * use icon only on mobile * change color order * docs * show activity indicator on trash icon while deleting a profile * tweak language * immediately create profiles on backend instead of deferring to Save All * hide restart-required fields when editing a profile section fields that require a restart cannot take effect via profile switching, so they are merged into hiddenFields when profileName is set * show active profile indicator in desktop status bar * fix profile config inheritance bug where Pydantic defaults override base values The /config API was dumping profile overrides with model_dump() which included all Pydantic defaults. When the frontend merged these over the camera's base config, explicitly-set base values were lost. Now profile overrides are re-dumped with exclude_unset=True so only user-specified fields are returned. Also fixes the Save All path generating spurious deletion markers for restart-required fields that are hidden during profile editing but not excluded from the raw data sanitization in prepareSectionSavePayload. * docs tweaks * docs tweak * formatting * formatting * fix typing * fix test pollution test_maintainer was injecting MagicMock() into sys.modules["frigate.config.camera.updater"] at module load time and never restoring it. When the profile tests later imported CameraConfigUpdateEnum and CameraConfigUpdateTopic from that module, they got mock objects instead of the real dataclass/enum, so equality comparisons always failed * remove * fix settings showing profile-merged values when editing base config When a profile is active, the in-memory config contains effective (profile-merged) values. The settings UI was displaying these merged values even when the "Base Config" view was selected. Backend: snapshot pre-profile base configs in ProfileManager and expose them via a `base_config` key in the /api/config camera response when a profile is active. The top-level sections continue to reflect the effective running config. Frontend: read from `base_config` when available in BaseSection, useConfigOverride, useAllCameraOverrides, and prepareSectionSavePayload. Include formData labels in Object/Audio switches widgets so that labels added only by a profile override remain visible when editing that profile. * use rasterized_mask as field makes it easier to exclude from the schema with exclude=True prevents leaking of the field when using model_dump for profiles * fix zones - Fix zone colors not matching across profiles by falling back to base zone color when profile zone data lacks a color field - Use base_config for base-layer values in masks/zones view so profile-merged values don't pollute the base config editing view - Handle zones separately in profile manager snapshot/restore since ZoneConfig requires special serialization (color as private attr, contour generation) - Inherit base zone color and generate contours for profile zone overrides in profile manager * formatting * don't require restart for camera enabled change for profiles * publish camera state when changing profiles * formatting * remove available profiles from mqtt * improve typing
2026-03-19 17:47:57 +03:00
type CameraTypeSectionProps = {
cameras: string[];
config: FrigateConfig | undefined;
onConfigChanged: () => Promise<unknown>;
setRestartDialogOpen: React.Dispatch<React.SetStateAction<boolean>>;
};
function CameraTypeSection({
cameras,
config,
onConfigChanged,
setRestartDialogOpen,
}: CameraTypeSectionProps) {
const { t } = useTranslation([
"views/settings",
"common",
"components/dialog",
]);
const { getLocaleDocUrl } = useDocDomain();
const [savingCamera, setSavingCamera] = useState<string | null>(null);
// Optimistic local state: the parsed config API doesn't reflect type
// changes until Frigate restarts, so we track saved values locally.
const [localOverrides, setLocalOverrides] = useState<Record<string, string>>(
{},
);
const handleTypeChange = useCallback(
async (camera: string, value: string) => {
setSavingCamera(camera);
try {
const typeValue = value === "lpr" ? "lpr" : null;
await axios.put("config/set", {
requires_restart: 1,
config_data: {
cameras: {
[camera]: {
type: typeValue,
},
},
},
});
await onConfigChanged();
setLocalOverrides((prev) => ({
...prev,
[camera]: value,
}));
toast.success(
t("cameraManagement.cameraType.saveSuccess", {
ns: "views/settings",
cameraName: camera,
}),
{
position: "top-center",
action: (
<a onClick={() => setRestartDialogOpen(true)}>
<Button>
{t("restart.button", { ns: "components/dialog" })}
</Button>
</a>
),
},
);
} catch (error) {
const errorMessage =
axios.isAxiosError(error) &&
(error.response?.data?.message || error.response?.data?.detail)
? error.response?.data?.message || error.response?.data?.detail
: t("toast.save.error.noMessage", { ns: "common" });
toast.error(
t("toast.save.error.title", { errorMessage, ns: "common" }),
{ position: "top-center" },
);
} finally {
setSavingCamera(null);
}
},
[onConfigChanged, setRestartDialogOpen, t],
);
const getCameraType = useCallback(
(camera: string): string => {
const localValue = localOverrides[camera];
if (localValue) return localValue;
const type = config?.cameras?.[camera]?.type;
return type === "lpr" ? "lpr" : "normal";
},
[config, localOverrides],
);
return (
<SettingsGroupCard
title={t("cameraManagement.cameraType.title", {
ns: "views/settings",
})}
>
<div className={SPLIT_ROW_CLASS_NAME}>
<div className="space-y-1.5">
<Label>
{t("cameraManagement.cameraType.label", {
ns: "views/settings",
})}
<RestartRequiredIndicator className="ml-1" />
</Label>
<p className="hidden text-sm text-muted-foreground md:block">
{t("cameraManagement.cameraType.description", {
ns: "views/settings",
})}
</p>
<div className="hidden items-center text-sm text-primary md:flex">
<Link
to={getLocaleDocUrl(
"configuration/license_plate_recognition#dedicated-lpr-cameras",
)}
target="_blank"
rel="noopener noreferrer"
className="inline"
>
{t("readTheDocumentation", { ns: "common" })}
<LuExternalLink className="ml-2 inline-flex size-3" />
</Link>
</div>
</div>
<div className={`${CONTROL_COLUMN_CLASS_NAME} space-y-1.5`}>
<div className="max-w-md space-y-2 rounded-lg bg-secondary p-4">
{cameras.map((camera) => {
const currentType = getCameraType(camera);
const isSaving = savingCamera === camera;
return (
<div
key={camera}
className="flex flex-row items-center justify-between"
>
<CameraNameLabel camera={camera} />
{isSaving ? (
<ActivityIndicator className="h-5 w-20" size={16} />
) : (
<Select
value={currentType}
onValueChange={(v) => handleTypeChange(camera, v)}
>
<SelectTrigger className="h-7 w-full max-w-[140px] text-xs">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="normal">
{t("cameraManagement.cameraType.normal", {
ns: "views/settings",
})}
</SelectItem>
<SelectItem value="lpr">
{t("cameraManagement.cameraType.dedicatedLpr", {
ns: "views/settings",
})}
</SelectItem>
</SelectContent>
</Select>
)}
</div>
);
})}
</div>
<p className="text-sm text-muted-foreground md:hidden">
{t("cameraManagement.cameraType.description", {
ns: "views/settings",
})}
</p>
<div className="flex items-center text-sm text-primary md:hidden">
<Link
to={getLocaleDocUrl(
"configuration/license_plate_recognition#dedicated-lpr-cameras",
)}
target="_blank"
rel="noopener noreferrer"
className="inline"
>
{t("readTheDocumentation", { ns: "common" })}
<LuExternalLink className="ml-2 inline-flex size-3" />
</Link>
</div>
</div>
</div>
</SettingsGroupCard>
);
}
Camera profile support (#22482) * add CameraProfileConfig model for named config overrides * add profiles field to CameraConfig * add active_profile field to FrigateConfig Runtime-only field excluded from YAML serialization, tracks which profile is currently active. * add ProfileManager for profile activation and persistence Handles snapshotting base configs, applying profile overrides via deep_merge + apply_section_update, publishing ZMQ updates, and persisting active profile to /config/.active_profile. * add profile API endpoints (GET /profiles, GET/PUT /profile) * add MQTT and dispatcher integration for profiles - Subscribe to frigate/profile/set MQTT topic - Publish profile/state and profiles/available on connect - Add _on_profile_command handler to dispatcher - Broadcast active profile state on WebSocket connect * wire ProfileManager into app startup and FastAPI - Create ProfileManager after dispatcher init - Restore persisted profile on startup - Pass dispatcher and profile_manager to FastAPI app * add tests for invalid profile values and keys Tests that Pydantic rejects: invalid field values (fps: "not_a_number"), unknown section keys (ffmpeg in profile), invalid nested values, and invalid profiles in full config parsing. * formatting * fix CameraLiveConfig JSON serialization error on profile activation refactor _publish_updates to only publish ZMQ updates for sections that actually changed, not all sections on affected cameras. * consolidate * add enabled field to camera profiles for enabling/disabling cameras * add zones support to camera profiles * add frontend profile types, color utility, and config save support * add profile state management and save preview support * add profileName prop to BaseSection for profile-aware config editing * add profile section dropdown and wire into camera settings pages * add per-profile camera enable/disable to Camera Management view * add profiles summary page with card-based layout and fix backend zone comparison bug * add active profile badge to settings toolbar * i18n * add red dot for any pending changes including profiles * profile support for mask and zone editor * fix hidden field validation errors caused by lodash wildcard and schema gaps lodash unset does not support wildcard (*) segments, so hidden fields like filters.*.mask were never stripped from form data, leaving null raw_coordinates that fail RJSF anyOf validation. Add unsetWithWildcard helper and also strip hidden fields from the JSON schema itself as defense-in-depth. * add face_recognition and lpr to profile-eligible sections * move profile dropdown from section panes to settings header * add profiles enable toggle and improve empty state * formatting * tweaks * tweak colors and switch * fix profile save diff, masksAndZones delete, and config sync * ui tweaks * ensure profile manager gets updated config * rename profile settings to ui settings * refactor profilesview and add dots/border colors when overridden * implement an update_config method for profile manager * fix mask deletion * more unique colors * add top-level profiles config section with friendly names * implement profile friendly names and improve profile UI - Add ProfileDefinitionConfig type and profiles field to FrigateConfig - Use ProfilesApiResponse type with friendly_name support throughout - Replace Record<string, unknown> with proper JsonObject/JsonValue types - Add profile creation form matching zone pattern (Zod + NameAndIdFields) - Add pencil icon for renaming profile friendly names in ProfilesView - Move Profiles menu item to first under Camera Configuration - Add activity indicators on save/rename/delete buttons - Display friendly names in CameraManagementView profile selector - Fix duplicate colored dots in management profile dropdown - Fix i18n namespace for overridden base config tooltips - Move profile override deletion from dropdown trash icon to footer button with confirmation dialog, matching Reset to Global pattern - Remove Add Profile from section header dropdown to prevent saving camera overrides before top-level profile definition exists - Clean up newProfiles state after API profile deletion - Refresh profiles SWR cache after saving profile definitions * remove profile badge in settings and add profiles to main menu * use icon only on mobile * change color order * docs * show activity indicator on trash icon while deleting a profile * tweak language * immediately create profiles on backend instead of deferring to Save All * hide restart-required fields when editing a profile section fields that require a restart cannot take effect via profile switching, so they are merged into hiddenFields when profileName is set * show active profile indicator in desktop status bar * fix profile config inheritance bug where Pydantic defaults override base values The /config API was dumping profile overrides with model_dump() which included all Pydantic defaults. When the frontend merged these over the camera's base config, explicitly-set base values were lost. Now profile overrides are re-dumped with exclude_unset=True so only user-specified fields are returned. Also fixes the Save All path generating spurious deletion markers for restart-required fields that are hidden during profile editing but not excluded from the raw data sanitization in prepareSectionSavePayload. * docs tweaks * docs tweak * formatting * formatting * fix typing * fix test pollution test_maintainer was injecting MagicMock() into sys.modules["frigate.config.camera.updater"] at module load time and never restoring it. When the profile tests later imported CameraConfigUpdateEnum and CameraConfigUpdateTopic from that module, they got mock objects instead of the real dataclass/enum, so equality comparisons always failed * remove * fix settings showing profile-merged values when editing base config When a profile is active, the in-memory config contains effective (profile-merged) values. The settings UI was displaying these merged values even when the "Base Config" view was selected. Backend: snapshot pre-profile base configs in ProfileManager and expose them via a `base_config` key in the /api/config camera response when a profile is active. The top-level sections continue to reflect the effective running config. Frontend: read from `base_config` when available in BaseSection, useConfigOverride, useAllCameraOverrides, and prepareSectionSavePayload. Include formData labels in Object/Audio switches widgets so that labels added only by a profile override remain visible when editing that profile. * use rasterized_mask as field makes it easier to exclude from the schema with exclude=True prevents leaking of the field when using model_dump for profiles * fix zones - Fix zone colors not matching across profiles by falling back to base zone color when profile zone data lacks a color field - Use base_config for base-layer values in masks/zones view so profile-merged values don't pollute the base config editing view - Handle zones separately in profile manager snapshot/restore since ZoneConfig requires special serialization (color as private attr, contour generation) - Inherit base zone color and generate contours for profile zone overrides in profile manager * formatting * don't require restart for camera enabled change for profiles * publish camera state when changing profiles * formatting * remove available profiles from mqtt * improve typing
2026-03-19 17:47:57 +03:00
type ProfileCameraEnableSectionProps = {
profileState: ProfileState;
cameras: string[];
config: FrigateConfig | undefined;
onConfigChanged: () => Promise<unknown>;
};
function ProfileCameraEnableSection({
profileState,
cameras,
config,
onConfigChanged,
}: ProfileCameraEnableSectionProps) {
const { t } = useTranslation(["views/settings", "common"]);
const [selectedProfile, setSelectedProfile] = useState<string>(
profileState.allProfileNames[0] ?? "",
);
const [savingCamera, setSavingCamera] = useState<string | null>(null);
// Optimistic local state: the parsed config API doesn't reflect profile
// enabled changes until Frigate restarts, so we track saved values locally.
const [localOverrides, setLocalOverrides] = useState<
Record<string, Record<string, string>>
>({});
const handleEnabledChange = useCallback(
async (camera: string, value: string) => {
setSavingCamera(camera);
try {
const enabledValue =
value === "enabled" ? true : value === "disabled" ? false : null;
const configData =
enabledValue === null
? {
cameras: {
[camera]: {
profiles: { [selectedProfile]: { enabled: "" } },
},
},
}
: {
cameras: {
[camera]: {
profiles: { [selectedProfile]: { enabled: enabledValue } },
},
},
};
await axios.put("config/set", {
requires_restart: 0,
config_data: configData,
});
await onConfigChanged();
setLocalOverrides((prev) => ({
...prev,
[selectedProfile]: {
...prev[selectedProfile],
[camera]: value,
},
}));
toast.success(t("toast.save.success", { ns: "common" }), {
position: "top-center",
});
} catch {
toast.error(t("toast.save.error.title", { ns: "common" }), {
position: "top-center",
});
} finally {
setSavingCamera(null);
}
},
[selectedProfile, onConfigChanged, t],
);
const getEnabledState = useCallback(
(camera: string): string => {
// Check optimistic local state first
const localValue = localOverrides[selectedProfile]?.[camera];
if (localValue) return localValue;
const profileData =
config?.cameras?.[camera]?.profiles?.[selectedProfile];
if (!profileData || profileData.enabled === undefined) return "inherit";
return profileData.enabled ? "enabled" : "disabled";
},
[config, selectedProfile, localOverrides],
);
if (!selectedProfile) return null;
return (
<SettingsGroupCard
title={t("cameraManagement.profiles.title", {
ns: "views/settings",
})}
>
<div className={SPLIT_ROW_CLASS_NAME}>
<div className="space-y-1.5">
<Label>
{t("cameraManagement.profiles.selectLabel", {
ns: "views/settings",
})}
</Label>
<p className="text-sm text-muted-foreground">
{t("cameraManagement.profiles.description", {
ns: "views/settings",
})}
</p>
</div>
<div className={`${CONTROL_COLUMN_CLASS_NAME} space-y-4`}>
<Select value={selectedProfile} onValueChange={setSelectedProfile}>
<SelectTrigger className="w-full max-w-[200px]">
<SelectValue />
</SelectTrigger>
<SelectContent>
{profileState.allProfileNames.map((profile) => {
const color = getProfileColor(
profile,
profileState.allProfileNames,
);
return (
<SelectItem key={profile} value={profile}>
<div className="flex items-center gap-2">
<span
className={cn(
"h-2 w-2 shrink-0 rounded-full",
color.dot,
)}
/>
{profileState.profileFriendlyNames.get(profile) ??
profile}
</div>
</SelectItem>
);
})}
</SelectContent>
</Select>
<div className="max-w-md space-y-2 rounded-lg bg-secondary p-4">
{cameras.map((camera) => {
const state = getEnabledState(camera);
const isSaving = savingCamera === camera;
return (
<div
key={camera}
className="flex flex-row items-center justify-between"
>
<CameraNameLabel camera={camera} />
{isSaving ? (
<ActivityIndicator className="h-5 w-20" size={16} />
) : (
<Select
value={state}
onValueChange={(v) => handleEnabledChange(camera, v)}
>
<SelectTrigger className="h-7 w-[120px] text-xs">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="inherit">
{t("cameraManagement.profiles.inherit", {
ns: "views/settings",
})}
</SelectItem>
<SelectItem value="enabled">
{t("cameraManagement.profiles.enabled", {
ns: "views/settings",
})}
</SelectItem>
<SelectItem value="disabled">
{t("cameraManagement.profiles.disabled", {
ns: "views/settings",
})}
</SelectItem>
</SelectContent>
</Select>
)}
</div>
);
})}
</div>
</div>
</div>
</SettingsGroupCard>
);
}