mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-08-01 16:42:18 +03:00
refactor configs to use individual files with a template
This commit is contained in:
@@ -4,24 +4,7 @@
|
||||
import { useMemo, useCallback, useState, memo } from "react";
|
||||
import useSWR from "swr";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { DetectSection } from "@/components/config-form/sections/DetectSection";
|
||||
import { RecordSection } from "@/components/config-form/sections/RecordSection";
|
||||
import { SnapshotsSection } from "@/components/config-form/sections/SnapshotsSection";
|
||||
import { MotionSection } from "@/components/config-form/sections/MotionSection";
|
||||
import { ObjectsSection } from "@/components/config-form/sections/ObjectsSection";
|
||||
import { ReviewSection } from "@/components/config-form/sections/ReviewSection";
|
||||
import { AudioSection } from "@/components/config-form/sections/AudioSection";
|
||||
import { AudioTranscriptionSection } from "@/components/config-form/sections/AudioTranscriptionSection";
|
||||
import { BirdseyeSection } from "@/components/config-form/sections/BirdseyeSection";
|
||||
import { CameraMqttSection } from "@/components/config-form/sections/CameraMqttSection";
|
||||
import { CameraUiSection } from "@/components/config-form/sections/CameraUiSection";
|
||||
import { FaceRecognitionSection } from "@/components/config-form/sections/FaceRecognitionSection";
|
||||
import { FfmpegSection } from "@/components/config-form/sections/FfmpegSection";
|
||||
import { LprSection } from "@/components/config-form/sections/LprSection";
|
||||
import { NotificationsSection } from "@/components/config-form/sections/NotificationsSection";
|
||||
import { OnvifSection } from "@/components/config-form/sections/OnvifSection";
|
||||
import { LiveSection } from "@/components/config-form/sections/LiveSection";
|
||||
import { TimestampSection } from "@/components/config-form/sections/TimestampSection";
|
||||
import { ConfigSectionTemplate } from "@/components/config-form/sections";
|
||||
import { useAllCameraOverrides } from "@/hooks/use-config-override";
|
||||
import type { FrigateConfig } from "@/types/frigateConfig";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
@@ -203,83 +186,26 @@ const CameraConfigContent = memo(function CameraConfigContent({
|
||||
|
||||
const sections: Array<{
|
||||
key: string;
|
||||
component: typeof DetectSection;
|
||||
showOverrideIndicator?: boolean;
|
||||
}> = [
|
||||
{
|
||||
key: "detect",
|
||||
component: DetectSection,
|
||||
},
|
||||
{
|
||||
key: "ffmpeg",
|
||||
component: FfmpegSection,
|
||||
showOverrideIndicator: true,
|
||||
},
|
||||
{
|
||||
key: "record",
|
||||
component: RecordSection,
|
||||
},
|
||||
{
|
||||
key: "snapshots",
|
||||
component: SnapshotsSection,
|
||||
},
|
||||
{
|
||||
key: "motion",
|
||||
component: MotionSection,
|
||||
},
|
||||
{
|
||||
key: "objects",
|
||||
component: ObjectsSection,
|
||||
},
|
||||
{
|
||||
key: "review",
|
||||
component: ReviewSection,
|
||||
},
|
||||
{ key: "audio", component: AudioSection },
|
||||
{
|
||||
key: "audio_transcription",
|
||||
component: AudioTranscriptionSection,
|
||||
showOverrideIndicator: true,
|
||||
},
|
||||
{
|
||||
key: "notifications",
|
||||
component: NotificationsSection,
|
||||
},
|
||||
{ key: "live", component: LiveSection },
|
||||
{
|
||||
key: "birdseye",
|
||||
component: BirdseyeSection,
|
||||
showOverrideIndicator: true,
|
||||
},
|
||||
{
|
||||
key: "face_recognition",
|
||||
component: FaceRecognitionSection,
|
||||
showOverrideIndicator: true,
|
||||
},
|
||||
{
|
||||
key: "lpr",
|
||||
component: LprSection,
|
||||
showOverrideIndicator: true,
|
||||
},
|
||||
{
|
||||
key: "mqtt",
|
||||
component: CameraMqttSection,
|
||||
showOverrideIndicator: false,
|
||||
},
|
||||
{
|
||||
key: "onvif",
|
||||
component: OnvifSection,
|
||||
showOverrideIndicator: false,
|
||||
},
|
||||
{
|
||||
key: "ui",
|
||||
component: CameraUiSection,
|
||||
showOverrideIndicator: false,
|
||||
},
|
||||
{
|
||||
key: "timestamp_style",
|
||||
component: TimestampSection,
|
||||
},
|
||||
{ key: "detect" },
|
||||
{ key: "ffmpeg", showOverrideIndicator: true },
|
||||
{ key: "record" },
|
||||
{ key: "snapshots" },
|
||||
{ key: "motion" },
|
||||
{ key: "objects" },
|
||||
{ key: "review" },
|
||||
{ key: "audio" },
|
||||
{ key: "audio_transcription", showOverrideIndicator: true },
|
||||
{ key: "notifications" },
|
||||
{ key: "live" },
|
||||
{ key: "birdseye", showOverrideIndicator: true },
|
||||
{ key: "face_recognition", showOverrideIndicator: true },
|
||||
{ key: "lpr", showOverrideIndicator: true },
|
||||
{ key: "mqtt", showOverrideIndicator: false },
|
||||
{ key: "onvif", showOverrideIndicator: false },
|
||||
{ key: "ui", showOverrideIndicator: false },
|
||||
{ key: "timestamp_style" },
|
||||
];
|
||||
|
||||
return (
|
||||
@@ -327,23 +253,21 @@ const CameraConfigContent = memo(function CameraConfigContent({
|
||||
|
||||
{/* Section Content */}
|
||||
<div className="scrollbar-container flex-1 overflow-y-auto pr-4">
|
||||
{sections.map((section) => {
|
||||
const SectionComponent = section.component;
|
||||
return (
|
||||
<div
|
||||
key={section.key}
|
||||
className={cn(activeSection === section.key ? "block" : "hidden")}
|
||||
>
|
||||
<SectionComponent
|
||||
level="camera"
|
||||
cameraName={cameraName}
|
||||
showOverrideIndicator={section.showOverrideIndicator !== false}
|
||||
onSave={onSave}
|
||||
showTitle={true}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
{sections.map((section) => (
|
||||
<div
|
||||
key={section.key}
|
||||
className={cn(activeSection === section.key ? "block" : "hidden")}
|
||||
>
|
||||
<ConfigSectionTemplate
|
||||
sectionKey={section.key}
|
||||
level="camera"
|
||||
cameraName={cameraName}
|
||||
showOverrideIndicator={section.showOverrideIndicator !== false}
|
||||
onSave={onSave}
|
||||
showTitle={true}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -4,81 +4,51 @@
|
||||
import { useMemo, useCallback, useState } from "react";
|
||||
import useSWR from "swr";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { DetectSection } from "@/components/config-form/sections/DetectSection";
|
||||
import { RecordSection } from "@/components/config-form/sections/RecordSection";
|
||||
import { SnapshotsSection } from "@/components/config-form/sections/SnapshotsSection";
|
||||
import { MotionSection } from "@/components/config-form/sections/MotionSection";
|
||||
import { ObjectsSection } from "@/components/config-form/sections/ObjectsSection";
|
||||
import { ReviewSection } from "@/components/config-form/sections/ReviewSection";
|
||||
import { AudioSection } from "@/components/config-form/sections/AudioSection";
|
||||
import { AudioTranscriptionSection } from "@/components/config-form/sections/AudioTranscriptionSection";
|
||||
import { AuthSection } from "@/components/config-form/sections/AuthSection";
|
||||
import { BirdseyeSection } from "@/components/config-form/sections/BirdseyeSection";
|
||||
import { ClassificationSection } from "@/components/config-form/sections/ClassificationSection";
|
||||
import { DatabaseSection } from "@/components/config-form/sections/DatabaseSection";
|
||||
import { DetectorsSection } from "@/components/config-form/sections/DetectorsSection";
|
||||
import { EnvironmentVarsSection } from "@/components/config-form/sections/EnvironmentVarsSection";
|
||||
import { FaceRecognitionSection } from "@/components/config-form/sections/FaceRecognitionSection";
|
||||
import { FfmpegSection } from "@/components/config-form/sections/FfmpegSection";
|
||||
import { GenaiSection } from "@/components/config-form/sections/GenaiSection";
|
||||
import { LiveSection } from "@/components/config-form/sections/LiveSection";
|
||||
import { LoggerSection } from "@/components/config-form/sections/LoggerSection";
|
||||
import { LprSection } from "@/components/config-form/sections/LprSection";
|
||||
import { ModelSection } from "@/components/config-form/sections/ModelSection";
|
||||
import { MqttSection } from "@/components/config-form/sections/MqttSection";
|
||||
import { NetworkingSection } from "@/components/config-form/sections/NetworkingSection";
|
||||
import { ProxySection } from "@/components/config-form/sections/ProxySection";
|
||||
import { SemanticSearchSection } from "@/components/config-form/sections/SemanticSearchSection";
|
||||
import { TimestampSection } from "@/components/config-form/sections/TimestampSection";
|
||||
import { TelemetrySection } from "@/components/config-form/sections/TelemetrySection";
|
||||
import { TlsSection } from "@/components/config-form/sections/TlsSection";
|
||||
import { UiSection } from "@/components/config-form/sections/UiSection";
|
||||
import { ConfigSectionTemplate } from "@/components/config-form/sections";
|
||||
import type { FrigateConfig } from "@/types/frigateConfig";
|
||||
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import ActivityIndicator from "@/components/indicators/activity-indicator";
|
||||
import Heading from "@/components/ui/heading";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { getSectionConfig } from "@/components/config-form/sectionConfigs";
|
||||
|
||||
// Shared sections that can be overridden at camera level
|
||||
const sharedSections = [
|
||||
{ key: "detect", component: DetectSection },
|
||||
{ key: "record", component: RecordSection },
|
||||
{ key: "snapshots", component: SnapshotsSection },
|
||||
{ key: "motion", component: MotionSection },
|
||||
{ key: "objects", component: ObjectsSection },
|
||||
{ key: "review", component: ReviewSection },
|
||||
{ key: "audio", component: AudioSection },
|
||||
{ key: "live", component: LiveSection },
|
||||
{ key: "timestamp_style", component: TimestampSection },
|
||||
{ key: "detect" },
|
||||
{ key: "record" },
|
||||
{ key: "snapshots" },
|
||||
{ key: "motion" },
|
||||
{ key: "objects" },
|
||||
{ key: "review" },
|
||||
{ key: "audio" },
|
||||
{ key: "live" },
|
||||
{ key: "timestamp_style" },
|
||||
];
|
||||
|
||||
// System sections (global only)
|
||||
const systemSections = [
|
||||
{ key: "database", component: DatabaseSection },
|
||||
{ key: "tls", component: TlsSection },
|
||||
{ key: "auth", component: AuthSection },
|
||||
{ key: "networking", component: NetworkingSection },
|
||||
{ key: "proxy", component: ProxySection },
|
||||
{ key: "ui", component: UiSection },
|
||||
{ key: "logger", component: LoggerSection },
|
||||
{ key: "environment_vars", component: EnvironmentVarsSection },
|
||||
{ key: "telemetry", component: TelemetrySection },
|
||||
{ key: "birdseye", component: BirdseyeSection },
|
||||
{ key: "ffmpeg", component: FfmpegSection },
|
||||
{ key: "detectors", component: DetectorsSection },
|
||||
{ key: "model", component: ModelSection },
|
||||
{ key: "database" },
|
||||
{ key: "tls" },
|
||||
{ key: "auth" },
|
||||
{ key: "networking" },
|
||||
{ key: "proxy" },
|
||||
{ key: "ui" },
|
||||
{ key: "logger" },
|
||||
{ key: "environment_vars" },
|
||||
{ key: "telemetry" },
|
||||
{ key: "birdseye" },
|
||||
{ key: "ffmpeg" },
|
||||
{ key: "detectors" },
|
||||
{ key: "model" },
|
||||
];
|
||||
|
||||
// Integration sections (global only)
|
||||
const integrationSections = [
|
||||
{ key: "mqtt", component: MqttSection },
|
||||
{ key: "semantic_search", component: SemanticSearchSection },
|
||||
{ key: "genai", component: GenaiSection },
|
||||
{ key: "face_recognition", component: FaceRecognitionSection },
|
||||
{ key: "lpr", component: LprSection },
|
||||
{ key: "classification", component: ClassificationSection },
|
||||
{ key: "audio_transcription", component: AudioTranscriptionSection },
|
||||
{ key: "mqtt" },
|
||||
{ key: "semantic_search" },
|
||||
{ key: "genai" },
|
||||
{ key: "face_recognition" },
|
||||
{ key: "lpr" },
|
||||
{ key: "classification" },
|
||||
{ key: "audio_transcription" },
|
||||
];
|
||||
|
||||
export default function GlobalConfigView() {
|
||||
@@ -201,24 +171,21 @@ export default function GlobalConfigView() {
|
||||
|
||||
{/* Section Content */}
|
||||
<div className="scrollbar-container flex-1 overflow-y-auto pr-4">
|
||||
{currentSections.map((section) => {
|
||||
const SectionComponent = section.component;
|
||||
return (
|
||||
<div
|
||||
key={section.key}
|
||||
className={cn(
|
||||
activeSection === section.key ? "block" : "hidden",
|
||||
)}
|
||||
>
|
||||
<SectionComponent
|
||||
level="global"
|
||||
onSave={handleSave}
|
||||
showTitle={true}
|
||||
sectionConfig={getSectionConfig(section.key, "global")}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
{currentSections.map((section) => (
|
||||
<div
|
||||
key={section.key}
|
||||
className={cn(
|
||||
activeSection === section.key ? "block" : "hidden",
|
||||
)}
|
||||
>
|
||||
<ConfigSectionTemplate
|
||||
sectionKey={section.key}
|
||||
level="global"
|
||||
onSave={handleSave}
|
||||
showTitle={true}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Tabs>
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Heading from "@/components/ui/heading";
|
||||
import type {
|
||||
BaseSectionProps,
|
||||
SectionConfig,
|
||||
} from "@/components/config-form/sections";
|
||||
import type { SectionConfig } from "@/components/config-form/sections";
|
||||
import { ConfigSectionTemplate } from "@/components/config-form/sections";
|
||||
import type { PolygonType } from "@/types/canvas";
|
||||
|
||||
export type SettingsPageProps = {
|
||||
@@ -15,7 +13,6 @@ export type SettingsPageProps = {
|
||||
export type SingleSectionPageOptions = {
|
||||
sectionKey: string;
|
||||
level: "global" | "camera";
|
||||
SectionComponent: React.ComponentType<BaseSectionProps>;
|
||||
sectionConfig?: SectionConfig;
|
||||
requiresRestart?: boolean;
|
||||
showOverrideIndicator?: boolean;
|
||||
@@ -24,7 +21,6 @@ export type SingleSectionPageOptions = {
|
||||
export function createSingleSectionPage({
|
||||
sectionKey,
|
||||
level,
|
||||
SectionComponent,
|
||||
sectionConfig,
|
||||
requiresRestart,
|
||||
showOverrideIndicator = true,
|
||||
@@ -63,7 +59,8 @@ export function createSingleSectionPage({
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<SectionComponent
|
||||
<ConfigSectionTemplate
|
||||
sectionKey={sectionKey}
|
||||
level={level}
|
||||
cameraName={level === "camera" ? selectedCamera : undefined}
|
||||
showOverrideIndicator={showOverrideIndicator}
|
||||
|
||||
Reference in New Issue
Block a user