mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-03-27 10:38:21 +03:00
refactor configs to use individual files with a template
This commit is contained in:
parent
c9c29b7c33
commit
a97333d881
27
web/src/components/config-form/section-configs/audio.ts
Normal file
27
web/src/components/config-form/section-configs/audio.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const audio: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: [
|
||||||
|
"enabled",
|
||||||
|
"listen",
|
||||||
|
"filters",
|
||||||
|
"min_volume",
|
||||||
|
"max_not_heard",
|
||||||
|
"num_threads",
|
||||||
|
],
|
||||||
|
fieldGroups: {
|
||||||
|
detection: ["enabled", "listen", "filters"],
|
||||||
|
sensitivity: ["min_volume", "max_not_heard"],
|
||||||
|
},
|
||||||
|
hiddenFields: ["enabled_in_config"],
|
||||||
|
advancedFields: ["min_volume", "max_not_heard", "num_threads"],
|
||||||
|
uiSchema: {
|
||||||
|
listen: {
|
||||||
|
"ui:widget": "audioLabels",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default audio;
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const audioTranscription: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: ["enabled", "language", "device", "model_size", "live_enabled"],
|
||||||
|
hiddenFields: ["enabled_in_config"],
|
||||||
|
advancedFields: ["language", "device", "model_size"],
|
||||||
|
overrideFields: ["enabled", "live_enabled"],
|
||||||
|
},
|
||||||
|
global: {
|
||||||
|
fieldOrder: ["enabled", "language", "device", "model_size", "live_enabled"],
|
||||||
|
advancedFields: ["language", "device", "model_size"],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default audioTranscription;
|
||||||
37
web/src/components/config-form/section-configs/auth.ts
Normal file
37
web/src/components/config-form/section-configs/auth.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const auth: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: [
|
||||||
|
"enabled",
|
||||||
|
"reset_admin_password",
|
||||||
|
"cookie_name",
|
||||||
|
"cookie_secure",
|
||||||
|
"session_length",
|
||||||
|
"refresh_time",
|
||||||
|
"native_oauth_url",
|
||||||
|
"failed_login_rate_limit",
|
||||||
|
"trusted_proxies",
|
||||||
|
"hash_iterations",
|
||||||
|
"roles",
|
||||||
|
],
|
||||||
|
hiddenFields: ["admin_first_time_login"],
|
||||||
|
advancedFields: [
|
||||||
|
"cookie_name",
|
||||||
|
"cookie_secure",
|
||||||
|
"session_length",
|
||||||
|
"refresh_time",
|
||||||
|
"failed_login_rate_limit",
|
||||||
|
"trusted_proxies",
|
||||||
|
"hash_iterations",
|
||||||
|
"roles",
|
||||||
|
],
|
||||||
|
uiSchema: {
|
||||||
|
reset_admin_password: {
|
||||||
|
"ui:widget": "switch",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default auth;
|
||||||
26
web/src/components/config-form/section-configs/birdseye.ts
Normal file
26
web/src/components/config-form/section-configs/birdseye.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const birdseye: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: ["enabled", "mode", "order"],
|
||||||
|
hiddenFields: [],
|
||||||
|
advancedFields: [],
|
||||||
|
overrideFields: ["enabled", "mode"],
|
||||||
|
},
|
||||||
|
global: {
|
||||||
|
fieldOrder: [
|
||||||
|
"enabled",
|
||||||
|
"restream",
|
||||||
|
"width",
|
||||||
|
"height",
|
||||||
|
"quality",
|
||||||
|
"mode",
|
||||||
|
"layout",
|
||||||
|
"inactivity_threshold",
|
||||||
|
"idle_heartbeat_fps",
|
||||||
|
],
|
||||||
|
advancedFields: ["width", "height", "quality", "inactivity_threshold"],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default birdseye;
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const classification: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
hiddenFields: ["custom"],
|
||||||
|
advancedFields: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default classification;
|
||||||
10
web/src/components/config-form/section-configs/database.ts
Normal file
10
web/src/components/config-form/section-configs/database.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const database: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: ["path"],
|
||||||
|
advancedFields: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default database;
|
||||||
29
web/src/components/config-form/section-configs/detect.ts
Normal file
29
web/src/components/config-form/section-configs/detect.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const detect: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: [
|
||||||
|
"enabled",
|
||||||
|
"fps",
|
||||||
|
"width",
|
||||||
|
"height",
|
||||||
|
"min_initialized",
|
||||||
|
"max_disappeared",
|
||||||
|
"annotation_offset",
|
||||||
|
"stationary",
|
||||||
|
],
|
||||||
|
fieldGroups: {
|
||||||
|
resolution: ["enabled", "width", "height"],
|
||||||
|
tracking: ["min_initialized", "max_disappeared"],
|
||||||
|
},
|
||||||
|
hiddenFields: ["enabled_in_config"],
|
||||||
|
advancedFields: [
|
||||||
|
"min_initialized",
|
||||||
|
"max_disappeared",
|
||||||
|
"annotation_offset",
|
||||||
|
"stationary",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default detect;
|
||||||
10
web/src/components/config-form/section-configs/detectors.ts
Normal file
10
web/src/components/config-form/section-configs/detectors.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const detectors: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: [],
|
||||||
|
advancedFields: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default detectors;
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const environmentVars: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: [],
|
||||||
|
advancedFields: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default environmentVars;
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const faceRecognition: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: ["enabled", "min_area"],
|
||||||
|
hiddenFields: [],
|
||||||
|
advancedFields: ["min_area"],
|
||||||
|
overrideFields: ["enabled", "min_area"],
|
||||||
|
},
|
||||||
|
global: {
|
||||||
|
fieldOrder: [
|
||||||
|
"enabled",
|
||||||
|
"model_size",
|
||||||
|
"unknown_score",
|
||||||
|
"detection_threshold",
|
||||||
|
"recognition_threshold",
|
||||||
|
"min_area",
|
||||||
|
"min_faces",
|
||||||
|
"save_attempts",
|
||||||
|
"blur_confidence_filter",
|
||||||
|
"device",
|
||||||
|
],
|
||||||
|
advancedFields: [
|
||||||
|
"unknown_score",
|
||||||
|
"detection_threshold",
|
||||||
|
"recognition_threshold",
|
||||||
|
"min_area",
|
||||||
|
"min_faces",
|
||||||
|
"save_attempts",
|
||||||
|
"blur_confidence_filter",
|
||||||
|
"device",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default faceRecognition;
|
||||||
192
web/src/components/config-form/section-configs/ffmpeg.ts
Normal file
192
web/src/components/config-form/section-configs/ffmpeg.ts
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const ffmpeg: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: [
|
||||||
|
"inputs",
|
||||||
|
"path",
|
||||||
|
"global_args",
|
||||||
|
"hwaccel_args",
|
||||||
|
"input_args",
|
||||||
|
"output_args",
|
||||||
|
"retry_interval",
|
||||||
|
"apple_compatibility",
|
||||||
|
"gpu",
|
||||||
|
],
|
||||||
|
hiddenFields: [],
|
||||||
|
advancedFields: [
|
||||||
|
"global_args",
|
||||||
|
"hwaccel_args",
|
||||||
|
"input_args",
|
||||||
|
"output_args",
|
||||||
|
"retry_interval",
|
||||||
|
"apple_compatibility",
|
||||||
|
"gpu",
|
||||||
|
],
|
||||||
|
overrideFields: [
|
||||||
|
"path",
|
||||||
|
"global_args",
|
||||||
|
"hwaccel_args",
|
||||||
|
"input_args",
|
||||||
|
"output_args",
|
||||||
|
"retry_interval",
|
||||||
|
"apple_compatibility",
|
||||||
|
"gpu",
|
||||||
|
],
|
||||||
|
uiSchema: {
|
||||||
|
global_args: {
|
||||||
|
"ui:widget": "ArrayAsTextWidget",
|
||||||
|
"ui:options": {
|
||||||
|
suppressMultiSchema: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
hwaccel_args: {
|
||||||
|
"ui:widget": "ArrayAsTextWidget",
|
||||||
|
"ui:options": {
|
||||||
|
suppressMultiSchema: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
input_args: {
|
||||||
|
"ui:widget": "ArrayAsTextWidget",
|
||||||
|
"ui:options": {
|
||||||
|
suppressMultiSchema: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
output_args: {
|
||||||
|
"ui:widget": "ArrayAsTextWidget",
|
||||||
|
"ui:options": {
|
||||||
|
suppressMultiSchema: true,
|
||||||
|
},
|
||||||
|
detect: {
|
||||||
|
"ui:widget": "ArrayAsTextWidget",
|
||||||
|
"ui:options": {
|
||||||
|
suppressMultiSchema: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
record: {
|
||||||
|
"ui:widget": "ArrayAsTextWidget",
|
||||||
|
"ui:options": {
|
||||||
|
suppressMultiSchema: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
items: {
|
||||||
|
detect: {
|
||||||
|
"ui:widget": "ArrayAsTextWidget",
|
||||||
|
"ui:options": {
|
||||||
|
suppressMultiSchema: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
record: {
|
||||||
|
"ui:widget": "ArrayAsTextWidget",
|
||||||
|
"ui:options": {
|
||||||
|
suppressMultiSchema: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
inputs: {
|
||||||
|
items: {
|
||||||
|
global_args: {
|
||||||
|
"ui:widget": "ArrayAsTextWidget",
|
||||||
|
"ui:options": {
|
||||||
|
suppressMultiSchema: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
hwaccel_args: {
|
||||||
|
"ui:widget": "ArrayAsTextWidget",
|
||||||
|
"ui:options": {
|
||||||
|
suppressMultiSchema: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
input_args: {
|
||||||
|
"ui:widget": "ArrayAsTextWidget",
|
||||||
|
"ui:options": {
|
||||||
|
suppressMultiSchema: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
output_args: {
|
||||||
|
"ui:widget": "ArrayAsTextWidget",
|
||||||
|
"ui:options": {
|
||||||
|
suppressMultiSchema: true,
|
||||||
|
},
|
||||||
|
items: {
|
||||||
|
detect: {
|
||||||
|
"ui:widget": "ArrayAsTextWidget",
|
||||||
|
"ui:options": {
|
||||||
|
suppressMultiSchema: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
record: {
|
||||||
|
"ui:widget": "ArrayAsTextWidget",
|
||||||
|
"ui:options": {
|
||||||
|
suppressMultiSchema: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
global: {
|
||||||
|
fieldOrder: [
|
||||||
|
"path",
|
||||||
|
"global_args",
|
||||||
|
"hwaccel_args",
|
||||||
|
"input_args",
|
||||||
|
"output_args",
|
||||||
|
"retry_interval",
|
||||||
|
"apple_compatibility",
|
||||||
|
"gpu",
|
||||||
|
],
|
||||||
|
advancedFields: [
|
||||||
|
"global_args",
|
||||||
|
"hwaccel_args",
|
||||||
|
"input_args",
|
||||||
|
"output_args",
|
||||||
|
"retry_interval",
|
||||||
|
"apple_compatibility",
|
||||||
|
"gpu",
|
||||||
|
],
|
||||||
|
uiSchema: {
|
||||||
|
global_args: {
|
||||||
|
"ui:widget": "ArrayAsTextWidget",
|
||||||
|
"ui:options": {
|
||||||
|
suppressMultiSchema: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
hwaccel_args: {
|
||||||
|
"ui:widget": "ArrayAsTextWidget",
|
||||||
|
"ui:options": {
|
||||||
|
suppressMultiSchema: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
input_args: {
|
||||||
|
"ui:widget": "ArrayAsTextWidget",
|
||||||
|
"ui:options": {
|
||||||
|
suppressMultiSchema: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
output_args: {
|
||||||
|
"ui:widget": "ArrayAsTextWidget",
|
||||||
|
"ui:options": {
|
||||||
|
suppressMultiSchema: true,
|
||||||
|
},
|
||||||
|
detect: {
|
||||||
|
"ui:widget": "ArrayAsTextWidget",
|
||||||
|
"ui:options": {
|
||||||
|
suppressMultiSchema: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
record: {
|
||||||
|
"ui:widget": "ArrayAsTextWidget",
|
||||||
|
"ui:options": {
|
||||||
|
suppressMultiSchema: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ffmpeg;
|
||||||
18
web/src/components/config-form/section-configs/genai.ts
Normal file
18
web/src/components/config-form/section-configs/genai.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const genai: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: [
|
||||||
|
"provider",
|
||||||
|
"api_key",
|
||||||
|
"base_url",
|
||||||
|
"model",
|
||||||
|
"provider_options",
|
||||||
|
"runtime_options",
|
||||||
|
],
|
||||||
|
advancedFields: ["base_url", "provider_options", "runtime_options"],
|
||||||
|
hiddenFields: ["genai.enabled_in_config"],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default genai;
|
||||||
12
web/src/components/config-form/section-configs/live.ts
Normal file
12
web/src/components/config-form/section-configs/live.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const live: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: ["stream_name", "height", "quality"],
|
||||||
|
fieldGroups: {},
|
||||||
|
hiddenFields: ["enabled_in_config"],
|
||||||
|
advancedFields: ["quality"],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default live;
|
||||||
10
web/src/components/config-form/section-configs/logger.ts
Normal file
10
web/src/components/config-form/section-configs/logger.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const logger: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: ["default", "logs"],
|
||||||
|
advancedFields: ["logs"],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default logger;
|
||||||
41
web/src/components/config-form/section-configs/lpr.ts
Normal file
41
web/src/components/config-form/section-configs/lpr.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const lpr: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: ["enabled", "expire_time", "min_area", "enhancement"],
|
||||||
|
hiddenFields: [],
|
||||||
|
advancedFields: ["expire_time", "min_area", "enhancement"],
|
||||||
|
overrideFields: ["enabled", "min_area", "enhancement"],
|
||||||
|
},
|
||||||
|
global: {
|
||||||
|
fieldOrder: [
|
||||||
|
"enabled",
|
||||||
|
"model_size",
|
||||||
|
"detection_threshold",
|
||||||
|
"min_area",
|
||||||
|
"recognition_threshold",
|
||||||
|
"min_plate_length",
|
||||||
|
"format",
|
||||||
|
"match_distance",
|
||||||
|
"known_plates",
|
||||||
|
"enhancement",
|
||||||
|
"debug_save_plates",
|
||||||
|
"device",
|
||||||
|
"replace_rules",
|
||||||
|
],
|
||||||
|
advancedFields: [
|
||||||
|
"detection_threshold",
|
||||||
|
"recognition_threshold",
|
||||||
|
"min_plate_length",
|
||||||
|
"format",
|
||||||
|
"match_distance",
|
||||||
|
"known_plates",
|
||||||
|
"enhancement",
|
||||||
|
"debug_save_plates",
|
||||||
|
"device",
|
||||||
|
"replace_rules",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default lpr;
|
||||||
25
web/src/components/config-form/section-configs/model.ts
Normal file
25
web/src/components/config-form/section-configs/model.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const model: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: [
|
||||||
|
"path",
|
||||||
|
"labelmap_path",
|
||||||
|
"width",
|
||||||
|
"height",
|
||||||
|
"input_pixel_format",
|
||||||
|
"input_tensor",
|
||||||
|
"input_dtype",
|
||||||
|
"model_type",
|
||||||
|
],
|
||||||
|
advancedFields: [
|
||||||
|
"input_pixel_format",
|
||||||
|
"input_tensor",
|
||||||
|
"input_dtype",
|
||||||
|
"model_type",
|
||||||
|
],
|
||||||
|
hiddenFields: ["labelmap", "attributes_map"],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default model;
|
||||||
32
web/src/components/config-form/section-configs/motion.ts
Normal file
32
web/src/components/config-form/section-configs/motion.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const motion: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: [
|
||||||
|
"enabled",
|
||||||
|
"threshold",
|
||||||
|
"lightning_threshold",
|
||||||
|
"improve_contrast",
|
||||||
|
"contour_area",
|
||||||
|
"delta_alpha",
|
||||||
|
"frame_alpha",
|
||||||
|
"frame_height",
|
||||||
|
"mask",
|
||||||
|
"mqtt_off_delay",
|
||||||
|
],
|
||||||
|
fieldGroups: {
|
||||||
|
sensitivity: ["enabled", "threshold", "contour_area"],
|
||||||
|
algorithm: ["improve_contrast", "delta_alpha", "frame_alpha"],
|
||||||
|
},
|
||||||
|
hiddenFields: ["enabled_in_config", "mask", "raw_mask"],
|
||||||
|
advancedFields: [
|
||||||
|
"lightning_threshold",
|
||||||
|
"delta_alpha",
|
||||||
|
"frame_alpha",
|
||||||
|
"frame_height",
|
||||||
|
"mqtt_off_delay",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default motion;
|
||||||
52
web/src/components/config-form/section-configs/mqtt.ts
Normal file
52
web/src/components/config-form/section-configs/mqtt.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const mqtt: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: [
|
||||||
|
"enabled",
|
||||||
|
"timestamp",
|
||||||
|
"bounding_box",
|
||||||
|
"crop",
|
||||||
|
"height",
|
||||||
|
"required_zones",
|
||||||
|
"quality",
|
||||||
|
],
|
||||||
|
hiddenFields: [],
|
||||||
|
advancedFields: ["height", "quality"],
|
||||||
|
overrideFields: [],
|
||||||
|
uiSchema: {
|
||||||
|
required_zones: {
|
||||||
|
"ui:widget": "zoneNames",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
global: {
|
||||||
|
fieldOrder: [
|
||||||
|
"enabled",
|
||||||
|
"host",
|
||||||
|
"port",
|
||||||
|
"user",
|
||||||
|
"password",
|
||||||
|
"topic_prefix",
|
||||||
|
"client_id",
|
||||||
|
"stats_interval",
|
||||||
|
"qos",
|
||||||
|
"tls_ca_certs",
|
||||||
|
"tls_client_cert",
|
||||||
|
"tls_client_key",
|
||||||
|
"tls_insecure",
|
||||||
|
],
|
||||||
|
advancedFields: [
|
||||||
|
"stats_interval",
|
||||||
|
"qos",
|
||||||
|
"tls_ca_certs",
|
||||||
|
"tls_client_cert",
|
||||||
|
"tls_client_key",
|
||||||
|
"tls_insecure",
|
||||||
|
],
|
||||||
|
liveValidate: true,
|
||||||
|
uiSchema: {},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default mqtt;
|
||||||
10
web/src/components/config-form/section-configs/networking.ts
Normal file
10
web/src/components/config-form/section-configs/networking.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const networking: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: [],
|
||||||
|
advancedFields: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default networking;
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const notifications: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: ["enabled", "email"],
|
||||||
|
fieldGroups: {},
|
||||||
|
hiddenFields: ["enabled_in_config"],
|
||||||
|
advancedFields: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default notifications;
|
||||||
57
web/src/components/config-form/section-configs/objects.ts
Normal file
57
web/src/components/config-form/section-configs/objects.ts
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const objects: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: ["track", "alert", "detect", "filters"],
|
||||||
|
fieldGroups: {
|
||||||
|
tracking: ["track", "alert", "detect"],
|
||||||
|
filtering: ["filters"],
|
||||||
|
},
|
||||||
|
hiddenFields: [
|
||||||
|
"enabled_in_config",
|
||||||
|
"mask",
|
||||||
|
"raw_mask",
|
||||||
|
"genai.enabled_in_config",
|
||||||
|
"filters.*.mask",
|
||||||
|
"filters.*.raw_mask",
|
||||||
|
],
|
||||||
|
advancedFields: ["filters"],
|
||||||
|
uiSchema: {
|
||||||
|
"filters.*.min_area": {
|
||||||
|
"ui:options": {
|
||||||
|
suppressMultiSchema: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"filters.*.max_area": {
|
||||||
|
"ui:options": {
|
||||||
|
suppressMultiSchema: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
track: {
|
||||||
|
"ui:widget": "objectLabels",
|
||||||
|
"ui:options": {
|
||||||
|
suppressMultiSchema: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
genai: {
|
||||||
|
objects: {
|
||||||
|
"ui:widget": "objectLabels",
|
||||||
|
"ui:options": {
|
||||||
|
suppressMultiSchema: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required_zones: {
|
||||||
|
"ui:widget": "zoneNames",
|
||||||
|
"ui:options": {
|
||||||
|
suppressMultiSchema: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
enabled_in_config: {
|
||||||
|
"ui:widget": "hidden",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default objects;
|
||||||
33
web/src/components/config-form/section-configs/onvif.ts
Normal file
33
web/src/components/config-form/section-configs/onvif.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const onvif: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: [
|
||||||
|
"host",
|
||||||
|
"port",
|
||||||
|
"user",
|
||||||
|
"password",
|
||||||
|
"tls_insecure",
|
||||||
|
"ignore_time_mismatch",
|
||||||
|
"autotracking",
|
||||||
|
],
|
||||||
|
hiddenFields: [
|
||||||
|
"autotracking.enabled_in_config",
|
||||||
|
"autotracking.movement_weights",
|
||||||
|
],
|
||||||
|
advancedFields: ["tls_insecure", "ignore_time_mismatch"],
|
||||||
|
overrideFields: [],
|
||||||
|
uiSchema: {
|
||||||
|
autotracking: {
|
||||||
|
required_zones: {
|
||||||
|
"ui:widget": "zoneNames",
|
||||||
|
},
|
||||||
|
track: {
|
||||||
|
"ui:widget": "objectLabels",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default onvif;
|
||||||
17
web/src/components/config-form/section-configs/proxy.ts
Normal file
17
web/src/components/config-form/section-configs/proxy.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const proxy: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: [
|
||||||
|
"header_map",
|
||||||
|
"logout_url",
|
||||||
|
"auth_secret",
|
||||||
|
"default_role",
|
||||||
|
"separator",
|
||||||
|
],
|
||||||
|
advancedFields: ["header_map", "auth_secret", "separator"],
|
||||||
|
liveValidate: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default proxy;
|
||||||
24
web/src/components/config-form/section-configs/record.ts
Normal file
24
web/src/components/config-form/section-configs/record.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const record: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: [
|
||||||
|
"enabled",
|
||||||
|
"expire_interval",
|
||||||
|
"continuous",
|
||||||
|
"motion",
|
||||||
|
"alerts",
|
||||||
|
"detections",
|
||||||
|
"preview",
|
||||||
|
"export",
|
||||||
|
],
|
||||||
|
fieldGroups: {
|
||||||
|
retention: ["enabled", "continuous", "motion"],
|
||||||
|
events: ["alerts", "detections"],
|
||||||
|
},
|
||||||
|
hiddenFields: ["enabled_in_config", "sync_recordings"],
|
||||||
|
advancedFields: ["expire_interval", "preview", "export"],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default record;
|
||||||
31
web/src/components/config-form/section-configs/review.ts
Normal file
31
web/src/components/config-form/section-configs/review.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const review: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: ["alerts", "detections", "genai"],
|
||||||
|
fieldGroups: {},
|
||||||
|
hiddenFields: [
|
||||||
|
"enabled_in_config",
|
||||||
|
"alerts.labels",
|
||||||
|
"alerts.enabled_in_config",
|
||||||
|
"alerts.required_zones",
|
||||||
|
"detections.labels",
|
||||||
|
"detections.enabled_in_config",
|
||||||
|
"detections.required_zones",
|
||||||
|
"genai.enabled_in_config",
|
||||||
|
],
|
||||||
|
advancedFields: [],
|
||||||
|
uiSchema: {
|
||||||
|
genai: {
|
||||||
|
additional_concerns: {
|
||||||
|
"ui:widget": "textarea",
|
||||||
|
},
|
||||||
|
activity_context_prompt: {
|
||||||
|
"ui:widget": "textarea",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default review;
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const semanticSearch: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: ["triggers"],
|
||||||
|
hiddenFields: [],
|
||||||
|
advancedFields: [],
|
||||||
|
overrideFields: [],
|
||||||
|
uiSchema: {
|
||||||
|
enabled: {
|
||||||
|
"ui:after": { render: "SemanticSearchReindex" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
global: {
|
||||||
|
fieldOrder: ["enabled", "reindex", "model", "model_size", "device"],
|
||||||
|
advancedFields: ["reindex", "device"],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default semanticSearch;
|
||||||
29
web/src/components/config-form/section-configs/snapshots.ts
Normal file
29
web/src/components/config-form/section-configs/snapshots.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const snapshots: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: [
|
||||||
|
"enabled",
|
||||||
|
"bounding_box",
|
||||||
|
"crop",
|
||||||
|
"quality",
|
||||||
|
"timestamp",
|
||||||
|
"retain",
|
||||||
|
],
|
||||||
|
fieldGroups: {
|
||||||
|
display: ["enabled", "bounding_box", "crop", "quality", "timestamp"],
|
||||||
|
},
|
||||||
|
hiddenFields: ["enabled_in_config"],
|
||||||
|
advancedFields: ["quality", "retain"],
|
||||||
|
uiSchema: {
|
||||||
|
required_zones: {
|
||||||
|
"ui:widget": "zoneNames",
|
||||||
|
"ui:options": {
|
||||||
|
suppressMultiSchema: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default snapshots;
|
||||||
10
web/src/components/config-form/section-configs/telemetry.ts
Normal file
10
web/src/components/config-form/section-configs/telemetry.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const telemetry: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: ["network_interfaces", "stats", "version_check"],
|
||||||
|
advancedFields: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default telemetry;
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const timestampStyle: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: ["position", "format", "color", "thickness"],
|
||||||
|
hiddenFields: ["effect", "enabled_in_config"],
|
||||||
|
advancedFields: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default timestampStyle;
|
||||||
10
web/src/components/config-form/section-configs/tls.ts
Normal file
10
web/src/components/config-form/section-configs/tls.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const tls: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: ["enabled", "cert", "key"],
|
||||||
|
advancedFields: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default tls;
|
||||||
7
web/src/components/config-form/section-configs/types.ts
Normal file
7
web/src/components/config-form/section-configs/types.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import type { SectionConfig } from "../sections/BaseSection";
|
||||||
|
|
||||||
|
export type SectionConfigOverrides = {
|
||||||
|
base?: SectionConfig;
|
||||||
|
global?: Partial<SectionConfig>;
|
||||||
|
camera?: Partial<SectionConfig>;
|
||||||
|
};
|
||||||
22
web/src/components/config-form/section-configs/ui.ts
Normal file
22
web/src/components/config-form/section-configs/ui.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import type { SectionConfigOverrides } from "./types";
|
||||||
|
|
||||||
|
const ui: SectionConfigOverrides = {
|
||||||
|
base: {
|
||||||
|
fieldOrder: ["dashboard", "order"],
|
||||||
|
hiddenFields: [],
|
||||||
|
advancedFields: [],
|
||||||
|
overrideFields: [],
|
||||||
|
},
|
||||||
|
global: {
|
||||||
|
fieldOrder: [
|
||||||
|
"timezone",
|
||||||
|
"time_format",
|
||||||
|
"date_style",
|
||||||
|
"time_style",
|
||||||
|
"unit_system",
|
||||||
|
],
|
||||||
|
advancedFields: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ui;
|
||||||
@ -13,830 +13,73 @@
|
|||||||
global?: Partial<SectionConfig>; // overrides for global-level UI
|
global?: Partial<SectionConfig>; // overrides for global-level UI
|
||||||
camera?: Partial<SectionConfig>; // overrides for camera-level UI
|
camera?: Partial<SectionConfig>; // overrides for camera-level UI
|
||||||
}
|
}
|
||||||
|
|
||||||
Merge rules (used by getSectionConfig):
|
|
||||||
- `base` is the canonical default and is merged with level-specific overrides.
|
|
||||||
- Arrays (e.g., `fieldOrder`, `advancedFields`, etc.) in overrides **replace**
|
|
||||||
the `base` arrays (they are not concatenated).
|
|
||||||
- `uiSchema` in an override **replaces** the base `uiSchema` rather than deep-merging
|
|
||||||
(this keeps widget overrides explicit per level).
|
|
||||||
- Other object properties are deep-merged using lodash.mergeWith with custom
|
|
||||||
behavior for arrays and `uiSchema` as described.
|
|
||||||
|
|
||||||
Example — `ffmpeg`:
|
|
||||||
- `base` (camera defaults) may include `inputs` and a `fieldOrder` that shows
|
|
||||||
`"inputs"` first.
|
|
||||||
- `global` override can replace `fieldOrder` with a different ordering
|
|
||||||
(e.g., omit `inputs` and show `path` first). Calling
|
|
||||||
`getSectionConfig("ffmpeg", "global")` will return the merged config
|
|
||||||
where `fieldOrder` comes from `global` (not concatenated with `base`).
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import mergeWith from "lodash/mergeWith";
|
import type { SectionConfigOverrides } from "./section-configs/types";
|
||||||
import type { SectionConfig } from "./sections/BaseSection";
|
import audio from "./section-configs/audio";
|
||||||
|
import audioTranscription from "./section-configs/audio_transcription";
|
||||||
|
import auth from "./section-configs/auth";
|
||||||
|
import birdseye from "./section-configs/birdseye";
|
||||||
|
import classification from "./section-configs/classification";
|
||||||
|
import database from "./section-configs/database";
|
||||||
|
import detect from "./section-configs/detect";
|
||||||
|
import detectors from "./section-configs/detectors";
|
||||||
|
import environmentVars from "./section-configs/environment_vars";
|
||||||
|
import faceRecognition from "./section-configs/face_recognition";
|
||||||
|
import ffmpeg from "./section-configs/ffmpeg";
|
||||||
|
import genai from "./section-configs/genai";
|
||||||
|
import live from "./section-configs/live";
|
||||||
|
import logger from "./section-configs/logger";
|
||||||
|
import lpr from "./section-configs/lpr";
|
||||||
|
import model from "./section-configs/model";
|
||||||
|
import motion from "./section-configs/motion";
|
||||||
|
import mqtt from "./section-configs/mqtt";
|
||||||
|
import networking from "./section-configs/networking";
|
||||||
|
import notifications from "./section-configs/notifications";
|
||||||
|
import objects from "./section-configs/objects";
|
||||||
|
import onvif from "./section-configs/onvif";
|
||||||
|
import proxy from "./section-configs/proxy";
|
||||||
|
import record from "./section-configs/record";
|
||||||
|
import review from "./section-configs/review";
|
||||||
|
import semanticSearch from "./section-configs/semantic_search";
|
||||||
|
import snapshots from "./section-configs/snapshots";
|
||||||
|
import telemetry from "./section-configs/telemetry";
|
||||||
|
import timestampStyle from "./section-configs/timestamp_style";
|
||||||
|
import tls from "./section-configs/tls";
|
||||||
|
import ui from "./section-configs/ui";
|
||||||
|
|
||||||
export type SectionConfigOverrides = {
|
export const sectionConfigs: Record<string, SectionConfigOverrides> = {
|
||||||
base?: SectionConfig;
|
detect,
|
||||||
global?: Partial<SectionConfig>;
|
record,
|
||||||
camera?: Partial<SectionConfig>;
|
snapshots,
|
||||||
|
motion,
|
||||||
|
objects,
|
||||||
|
review,
|
||||||
|
audio,
|
||||||
|
live,
|
||||||
|
timestamp_style: timestampStyle,
|
||||||
|
notifications,
|
||||||
|
onvif,
|
||||||
|
ffmpeg,
|
||||||
|
audio_transcription: audioTranscription,
|
||||||
|
birdseye,
|
||||||
|
face_recognition: faceRecognition,
|
||||||
|
lpr,
|
||||||
|
semantic_search: semanticSearch,
|
||||||
|
mqtt,
|
||||||
|
ui,
|
||||||
|
database,
|
||||||
|
auth,
|
||||||
|
tls,
|
||||||
|
networking,
|
||||||
|
proxy,
|
||||||
|
logger,
|
||||||
|
environment_vars: environmentVars,
|
||||||
|
telemetry,
|
||||||
|
detectors,
|
||||||
|
model,
|
||||||
|
genai,
|
||||||
|
classification,
|
||||||
};
|
};
|
||||||
|
|
||||||
const sectionConfigs: Record<string, SectionConfigOverrides> = {
|
export type { SectionConfigOverrides } from "./section-configs/types";
|
||||||
detect: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: [
|
|
||||||
"enabled",
|
|
||||||
"fps",
|
|
||||||
"width",
|
|
||||||
"height",
|
|
||||||
"min_initialized",
|
|
||||||
"max_disappeared",
|
|
||||||
"annotation_offset",
|
|
||||||
"stationary",
|
|
||||||
],
|
|
||||||
fieldGroups: {
|
|
||||||
resolution: ["enabled", "width", "height"],
|
|
||||||
tracking: ["min_initialized", "max_disappeared"],
|
|
||||||
},
|
|
||||||
hiddenFields: ["enabled_in_config"],
|
|
||||||
advancedFields: [
|
|
||||||
"min_initialized",
|
|
||||||
"max_disappeared",
|
|
||||||
"annotation_offset",
|
|
||||||
"stationary",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
record: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: [
|
|
||||||
"enabled",
|
|
||||||
"expire_interval",
|
|
||||||
"continuous",
|
|
||||||
"motion",
|
|
||||||
"alerts",
|
|
||||||
"detections",
|
|
||||||
"preview",
|
|
||||||
"export",
|
|
||||||
],
|
|
||||||
fieldGroups: {
|
|
||||||
retention: ["enabled", "continuous", "motion"],
|
|
||||||
events: ["alerts", "detections"],
|
|
||||||
},
|
|
||||||
hiddenFields: ["enabled_in_config", "sync_recordings"],
|
|
||||||
advancedFields: ["expire_interval", "preview", "export"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
snapshots: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: [
|
|
||||||
"enabled",
|
|
||||||
"bounding_box",
|
|
||||||
"crop",
|
|
||||||
"quality",
|
|
||||||
"timestamp",
|
|
||||||
"retain",
|
|
||||||
],
|
|
||||||
fieldGroups: {
|
|
||||||
display: ["enabled", "bounding_box", "crop", "quality", "timestamp"],
|
|
||||||
},
|
|
||||||
hiddenFields: ["enabled_in_config"],
|
|
||||||
advancedFields: ["quality", "retain"],
|
|
||||||
uiSchema: {
|
|
||||||
required_zones: {
|
|
||||||
"ui:widget": "zoneNames",
|
|
||||||
"ui:options": {
|
|
||||||
suppressMultiSchema: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
motion: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: [
|
|
||||||
"enabled",
|
|
||||||
"threshold",
|
|
||||||
"lightning_threshold",
|
|
||||||
"improve_contrast",
|
|
||||||
"contour_area",
|
|
||||||
"delta_alpha",
|
|
||||||
"frame_alpha",
|
|
||||||
"frame_height",
|
|
||||||
"mask",
|
|
||||||
"mqtt_off_delay",
|
|
||||||
],
|
|
||||||
fieldGroups: {
|
|
||||||
sensitivity: ["enabled", "threshold", "contour_area"],
|
|
||||||
algorithm: ["improve_contrast", "delta_alpha", "frame_alpha"],
|
|
||||||
},
|
|
||||||
hiddenFields: ["enabled_in_config", "mask", "raw_mask"],
|
|
||||||
advancedFields: [
|
|
||||||
"lightning_threshold",
|
|
||||||
"delta_alpha",
|
|
||||||
"frame_alpha",
|
|
||||||
"frame_height",
|
|
||||||
"mqtt_off_delay",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
objects: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: ["track", "alert", "detect", "filters"],
|
|
||||||
fieldGroups: {
|
|
||||||
tracking: ["track", "alert", "detect"],
|
|
||||||
filtering: ["filters"],
|
|
||||||
},
|
|
||||||
hiddenFields: [
|
|
||||||
"enabled_in_config",
|
|
||||||
"mask",
|
|
||||||
"raw_mask",
|
|
||||||
"genai.enabled_in_config",
|
|
||||||
"filters.*.mask",
|
|
||||||
"filters.*.raw_mask",
|
|
||||||
],
|
|
||||||
advancedFields: ["filters"],
|
|
||||||
uiSchema: {
|
|
||||||
"filters.*.min_area": {
|
|
||||||
"ui:options": {
|
|
||||||
suppressMultiSchema: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"filters.*.max_area": {
|
|
||||||
"ui:options": {
|
|
||||||
suppressMultiSchema: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
track: {
|
|
||||||
"ui:widget": "objectLabels",
|
|
||||||
"ui:options": {
|
|
||||||
suppressMultiSchema: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
genai: {
|
|
||||||
objects: {
|
|
||||||
"ui:widget": "objectLabels",
|
|
||||||
"ui:options": {
|
|
||||||
suppressMultiSchema: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
required_zones: {
|
|
||||||
"ui:widget": "zoneNames",
|
|
||||||
"ui:options": {
|
|
||||||
suppressMultiSchema: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
enabled_in_config: {
|
|
||||||
"ui:widget": "hidden",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
review: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: ["alerts", "detections", "genai"],
|
|
||||||
fieldGroups: {},
|
|
||||||
hiddenFields: [
|
|
||||||
"enabled_in_config",
|
|
||||||
"alerts.labels",
|
|
||||||
"alerts.enabled_in_config",
|
|
||||||
"alerts.required_zones",
|
|
||||||
"detections.labels",
|
|
||||||
"detections.enabled_in_config",
|
|
||||||
"detections.required_zones",
|
|
||||||
"genai.enabled_in_config",
|
|
||||||
],
|
|
||||||
advancedFields: [],
|
|
||||||
uiSchema: {
|
|
||||||
genai: {
|
|
||||||
additional_concerns: {
|
|
||||||
"ui:widget": "textarea",
|
|
||||||
},
|
|
||||||
activity_context_prompt: {
|
|
||||||
"ui:widget": "textarea",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
audio: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: [
|
|
||||||
"enabled",
|
|
||||||
"listen",
|
|
||||||
"filters",
|
|
||||||
"min_volume",
|
|
||||||
"max_not_heard",
|
|
||||||
"num_threads",
|
|
||||||
],
|
|
||||||
fieldGroups: {
|
|
||||||
detection: ["enabled", "listen", "filters"],
|
|
||||||
sensitivity: ["min_volume", "max_not_heard"],
|
|
||||||
},
|
|
||||||
hiddenFields: ["enabled_in_config"],
|
|
||||||
advancedFields: ["min_volume", "max_not_heard", "num_threads"],
|
|
||||||
uiSchema: {
|
|
||||||
listen: {
|
|
||||||
"ui:widget": "audioLabels",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
live: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: ["stream_name", "height", "quality"],
|
|
||||||
fieldGroups: {},
|
|
||||||
hiddenFields: ["enabled_in_config"],
|
|
||||||
advancedFields: ["quality"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
timestamp_style: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: ["position", "format", "color", "thickness"],
|
|
||||||
hiddenFields: ["effect", "enabled_in_config"],
|
|
||||||
advancedFields: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
notifications: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: ["enabled", "email"],
|
|
||||||
fieldGroups: {},
|
|
||||||
hiddenFields: ["enabled_in_config"],
|
|
||||||
advancedFields: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
onvif: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: [
|
|
||||||
"host",
|
|
||||||
"port",
|
|
||||||
"user",
|
|
||||||
"password",
|
|
||||||
"tls_insecure",
|
|
||||||
"ignore_time_mismatch",
|
|
||||||
"autotracking",
|
|
||||||
],
|
|
||||||
hiddenFields: [
|
|
||||||
"autotracking.enabled_in_config",
|
|
||||||
"autotracking.movement_weights",
|
|
||||||
],
|
|
||||||
advancedFields: ["tls_insecure", "ignore_time_mismatch"],
|
|
||||||
overrideFields: [],
|
|
||||||
uiSchema: {
|
|
||||||
autotracking: {
|
|
||||||
required_zones: {
|
|
||||||
"ui:widget": "zoneNames",
|
|
||||||
},
|
|
||||||
track: {
|
|
||||||
"ui:widget": "objectLabels",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
ffmpeg: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: [
|
|
||||||
"inputs",
|
|
||||||
"path",
|
|
||||||
"global_args",
|
|
||||||
"hwaccel_args",
|
|
||||||
"input_args",
|
|
||||||
"output_args",
|
|
||||||
"retry_interval",
|
|
||||||
"apple_compatibility",
|
|
||||||
"gpu",
|
|
||||||
],
|
|
||||||
hiddenFields: [],
|
|
||||||
advancedFields: [
|
|
||||||
"global_args",
|
|
||||||
"hwaccel_args",
|
|
||||||
"input_args",
|
|
||||||
"output_args",
|
|
||||||
"retry_interval",
|
|
||||||
"apple_compatibility",
|
|
||||||
"gpu",
|
|
||||||
],
|
|
||||||
overrideFields: [
|
|
||||||
"path",
|
|
||||||
"global_args",
|
|
||||||
"hwaccel_args",
|
|
||||||
"input_args",
|
|
||||||
"output_args",
|
|
||||||
"retry_interval",
|
|
||||||
"apple_compatibility",
|
|
||||||
"gpu",
|
|
||||||
],
|
|
||||||
uiSchema: {
|
|
||||||
global_args: {
|
|
||||||
"ui:widget": "ArrayAsTextWidget",
|
|
||||||
"ui:options": {
|
|
||||||
suppressMultiSchema: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
hwaccel_args: {
|
|
||||||
"ui:widget": "ArrayAsTextWidget",
|
|
||||||
"ui:options": {
|
|
||||||
suppressMultiSchema: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
input_args: {
|
|
||||||
"ui:widget": "ArrayAsTextWidget",
|
|
||||||
"ui:options": {
|
|
||||||
suppressMultiSchema: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
output_args: {
|
|
||||||
"ui:widget": "ArrayAsTextWidget",
|
|
||||||
"ui:options": {
|
|
||||||
suppressMultiSchema: true,
|
|
||||||
},
|
|
||||||
detect: {
|
|
||||||
"ui:widget": "ArrayAsTextWidget",
|
|
||||||
"ui:options": {
|
|
||||||
suppressMultiSchema: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
record: {
|
|
||||||
"ui:widget": "ArrayAsTextWidget",
|
|
||||||
"ui:options": {
|
|
||||||
suppressMultiSchema: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
items: {
|
|
||||||
detect: {
|
|
||||||
"ui:widget": "ArrayAsTextWidget",
|
|
||||||
"ui:options": {
|
|
||||||
suppressMultiSchema: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
record: {
|
|
||||||
"ui:widget": "ArrayAsTextWidget",
|
|
||||||
"ui:options": {
|
|
||||||
suppressMultiSchema: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
inputs: {
|
|
||||||
items: {
|
|
||||||
global_args: {
|
|
||||||
"ui:widget": "ArrayAsTextWidget",
|
|
||||||
"ui:options": {
|
|
||||||
suppressMultiSchema: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
hwaccel_args: {
|
|
||||||
"ui:widget": "ArrayAsTextWidget",
|
|
||||||
"ui:options": {
|
|
||||||
suppressMultiSchema: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
input_args: {
|
|
||||||
"ui:widget": "ArrayAsTextWidget",
|
|
||||||
"ui:options": {
|
|
||||||
suppressMultiSchema: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
output_args: {
|
|
||||||
"ui:widget": "ArrayAsTextWidget",
|
|
||||||
"ui:options": {
|
|
||||||
suppressMultiSchema: true,
|
|
||||||
},
|
|
||||||
items: {
|
|
||||||
detect: {
|
|
||||||
"ui:widget": "ArrayAsTextWidget",
|
|
||||||
"ui:options": {
|
|
||||||
suppressMultiSchema: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
record: {
|
|
||||||
"ui:widget": "ArrayAsTextWidget",
|
|
||||||
"ui:options": {
|
|
||||||
suppressMultiSchema: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
global: {
|
|
||||||
fieldOrder: [
|
|
||||||
"path",
|
|
||||||
"global_args",
|
|
||||||
"hwaccel_args",
|
|
||||||
"input_args",
|
|
||||||
"output_args",
|
|
||||||
"retry_interval",
|
|
||||||
"apple_compatibility",
|
|
||||||
"gpu",
|
|
||||||
],
|
|
||||||
advancedFields: [
|
|
||||||
"global_args",
|
|
||||||
"hwaccel_args",
|
|
||||||
"input_args",
|
|
||||||
"output_args",
|
|
||||||
"retry_interval",
|
|
||||||
"apple_compatibility",
|
|
||||||
"gpu",
|
|
||||||
],
|
|
||||||
uiSchema: {
|
|
||||||
global_args: {
|
|
||||||
"ui:widget": "ArrayAsTextWidget",
|
|
||||||
"ui:options": {
|
|
||||||
suppressMultiSchema: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
hwaccel_args: {
|
|
||||||
"ui:widget": "ArrayAsTextWidget",
|
|
||||||
"ui:options": {
|
|
||||||
suppressMultiSchema: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
input_args: {
|
|
||||||
"ui:widget": "ArrayAsTextWidget",
|
|
||||||
"ui:options": {
|
|
||||||
suppressMultiSchema: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
output_args: {
|
|
||||||
"ui:widget": "ArrayAsTextWidget",
|
|
||||||
"ui:options": {
|
|
||||||
suppressMultiSchema: true,
|
|
||||||
},
|
|
||||||
detect: {
|
|
||||||
"ui:widget": "ArrayAsTextWidget",
|
|
||||||
"ui:options": {
|
|
||||||
suppressMultiSchema: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
record: {
|
|
||||||
"ui:widget": "ArrayAsTextWidget",
|
|
||||||
"ui:options": {
|
|
||||||
suppressMultiSchema: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
audio_transcription: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: [
|
|
||||||
"enabled",
|
|
||||||
"language",
|
|
||||||
"device",
|
|
||||||
"model_size",
|
|
||||||
"live_enabled",
|
|
||||||
],
|
|
||||||
hiddenFields: ["enabled_in_config"],
|
|
||||||
advancedFields: ["language", "device", "model_size"],
|
|
||||||
overrideFields: ["enabled", "live_enabled"],
|
|
||||||
},
|
|
||||||
global: {
|
|
||||||
fieldOrder: [
|
|
||||||
"enabled",
|
|
||||||
"language",
|
|
||||||
"device",
|
|
||||||
"model_size",
|
|
||||||
"live_enabled",
|
|
||||||
],
|
|
||||||
advancedFields: ["language", "device", "model_size"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
birdseye: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: ["enabled", "mode", "order"],
|
|
||||||
hiddenFields: [],
|
|
||||||
advancedFields: [],
|
|
||||||
overrideFields: ["enabled", "mode"],
|
|
||||||
},
|
|
||||||
global: {
|
|
||||||
fieldOrder: [
|
|
||||||
"enabled",
|
|
||||||
"restream",
|
|
||||||
"width",
|
|
||||||
"height",
|
|
||||||
"quality",
|
|
||||||
"mode",
|
|
||||||
"layout",
|
|
||||||
"inactivity_threshold",
|
|
||||||
"idle_heartbeat_fps",
|
|
||||||
],
|
|
||||||
advancedFields: ["width", "height", "quality", "inactivity_threshold"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
face_recognition: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: ["enabled", "min_area"],
|
|
||||||
hiddenFields: [],
|
|
||||||
advancedFields: ["min_area"],
|
|
||||||
overrideFields: ["enabled", "min_area"],
|
|
||||||
},
|
|
||||||
global: {
|
|
||||||
fieldOrder: [
|
|
||||||
"enabled",
|
|
||||||
"model_size",
|
|
||||||
"unknown_score",
|
|
||||||
"detection_threshold",
|
|
||||||
"recognition_threshold",
|
|
||||||
"min_area",
|
|
||||||
"min_faces",
|
|
||||||
"save_attempts",
|
|
||||||
"blur_confidence_filter",
|
|
||||||
"device",
|
|
||||||
],
|
|
||||||
advancedFields: [
|
|
||||||
"unknown_score",
|
|
||||||
"detection_threshold",
|
|
||||||
"recognition_threshold",
|
|
||||||
"min_area",
|
|
||||||
"min_faces",
|
|
||||||
"save_attempts",
|
|
||||||
"blur_confidence_filter",
|
|
||||||
"device",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
lpr: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: ["enabled", "expire_time", "min_area", "enhancement"],
|
|
||||||
hiddenFields: [],
|
|
||||||
advancedFields: ["expire_time", "min_area", "enhancement"],
|
|
||||||
overrideFields: ["enabled", "min_area", "enhancement"],
|
|
||||||
},
|
|
||||||
global: {
|
|
||||||
fieldOrder: [
|
|
||||||
"enabled",
|
|
||||||
"model_size",
|
|
||||||
"detection_threshold",
|
|
||||||
"min_area",
|
|
||||||
"recognition_threshold",
|
|
||||||
"min_plate_length",
|
|
||||||
"format",
|
|
||||||
"match_distance",
|
|
||||||
"known_plates",
|
|
||||||
"enhancement",
|
|
||||||
"debug_save_plates",
|
|
||||||
"device",
|
|
||||||
"replace_rules",
|
|
||||||
],
|
|
||||||
advancedFields: [
|
|
||||||
"detection_threshold",
|
|
||||||
"recognition_threshold",
|
|
||||||
"min_plate_length",
|
|
||||||
"format",
|
|
||||||
"match_distance",
|
|
||||||
"known_plates",
|
|
||||||
"enhancement",
|
|
||||||
"debug_save_plates",
|
|
||||||
"device",
|
|
||||||
"replace_rules",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
semantic_search: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: ["triggers"],
|
|
||||||
hiddenFields: [],
|
|
||||||
advancedFields: [],
|
|
||||||
overrideFields: [],
|
|
||||||
uiSchema: {
|
|
||||||
enabled: {
|
|
||||||
"ui:after": { render: "SemanticSearchReindex" },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
global: {
|
|
||||||
fieldOrder: ["enabled", "reindex", "model", "model_size", "device"],
|
|
||||||
advancedFields: ["reindex", "device"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mqtt: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: [
|
|
||||||
"enabled",
|
|
||||||
"timestamp",
|
|
||||||
"bounding_box",
|
|
||||||
"crop",
|
|
||||||
"height",
|
|
||||||
"required_zones",
|
|
||||||
"quality",
|
|
||||||
],
|
|
||||||
hiddenFields: [],
|
|
||||||
advancedFields: ["height", "quality"],
|
|
||||||
overrideFields: [],
|
|
||||||
uiSchema: {
|
|
||||||
required_zones: {
|
|
||||||
"ui:widget": "zoneNames",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
global: {
|
|
||||||
fieldOrder: [
|
|
||||||
"enabled",
|
|
||||||
"host",
|
|
||||||
"port",
|
|
||||||
"user",
|
|
||||||
"password",
|
|
||||||
"topic_prefix",
|
|
||||||
"client_id",
|
|
||||||
"stats_interval",
|
|
||||||
"qos",
|
|
||||||
"tls_ca_certs",
|
|
||||||
"tls_client_cert",
|
|
||||||
"tls_client_key",
|
|
||||||
"tls_insecure",
|
|
||||||
],
|
|
||||||
advancedFields: [
|
|
||||||
"stats_interval",
|
|
||||||
"qos",
|
|
||||||
"tls_ca_certs",
|
|
||||||
"tls_client_cert",
|
|
||||||
"tls_client_key",
|
|
||||||
"tls_insecure",
|
|
||||||
],
|
|
||||||
liveValidate: true,
|
|
||||||
uiSchema: {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
ui: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: ["dashboard", "order"],
|
|
||||||
hiddenFields: [],
|
|
||||||
advancedFields: [],
|
|
||||||
overrideFields: [],
|
|
||||||
},
|
|
||||||
global: {
|
|
||||||
fieldOrder: [
|
|
||||||
"timezone",
|
|
||||||
"time_format",
|
|
||||||
"date_style",
|
|
||||||
"time_style",
|
|
||||||
"unit_system",
|
|
||||||
],
|
|
||||||
advancedFields: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
database: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: ["path"],
|
|
||||||
advancedFields: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
auth: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: [
|
|
||||||
"enabled",
|
|
||||||
"reset_admin_password",
|
|
||||||
"cookie_name",
|
|
||||||
"cookie_secure",
|
|
||||||
"session_length",
|
|
||||||
"refresh_time",
|
|
||||||
"native_oauth_url",
|
|
||||||
"failed_login_rate_limit",
|
|
||||||
"trusted_proxies",
|
|
||||||
"hash_iterations",
|
|
||||||
"roles",
|
|
||||||
],
|
|
||||||
hiddenFields: ["admin_first_time_login"],
|
|
||||||
advancedFields: [
|
|
||||||
"cookie_name",
|
|
||||||
"cookie_secure",
|
|
||||||
"session_length",
|
|
||||||
"refresh_time",
|
|
||||||
"failed_login_rate_limit",
|
|
||||||
"trusted_proxies",
|
|
||||||
"hash_iterations",
|
|
||||||
"roles",
|
|
||||||
],
|
|
||||||
uiSchema: {
|
|
||||||
reset_admin_password: {
|
|
||||||
"ui:widget": "switch",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
tls: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: ["enabled", "cert", "key"],
|
|
||||||
advancedFields: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
networking: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: ["ipv6"],
|
|
||||||
advancedFields: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
proxy: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: [
|
|
||||||
"header_map",
|
|
||||||
"logout_url",
|
|
||||||
"auth_secret",
|
|
||||||
"default_role",
|
|
||||||
"separator",
|
|
||||||
],
|
|
||||||
advancedFields: ["header_map", "auth_secret", "separator"],
|
|
||||||
liveValidate: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
logger: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: ["default", "logs"],
|
|
||||||
advancedFields: ["logs"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
environment_vars: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: [],
|
|
||||||
advancedFields: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
telemetry: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: ["network_interfaces", "stats", "version_check"],
|
|
||||||
advancedFields: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
detectors: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: [],
|
|
||||||
advancedFields: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
model: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: [
|
|
||||||
"path",
|
|
||||||
"labelmap_path",
|
|
||||||
"width",
|
|
||||||
"height",
|
|
||||||
"input_pixel_format",
|
|
||||||
"input_tensor",
|
|
||||||
"input_dtype",
|
|
||||||
"model_type",
|
|
||||||
],
|
|
||||||
advancedFields: [
|
|
||||||
"input_pixel_format",
|
|
||||||
"input_tensor",
|
|
||||||
"input_dtype",
|
|
||||||
"model_type",
|
|
||||||
],
|
|
||||||
hiddenFields: ["labelmap", "attributes_map"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
genai: {
|
|
||||||
base: {
|
|
||||||
fieldOrder: [
|
|
||||||
"provider",
|
|
||||||
"api_key",
|
|
||||||
"base_url",
|
|
||||||
"model",
|
|
||||||
"provider_options",
|
|
||||||
"runtime_options",
|
|
||||||
],
|
|
||||||
advancedFields: ["base_url", "provider_options", "runtime_options"],
|
|
||||||
hiddenFields: ["genai.enabled_in_config"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
classification: {
|
|
||||||
base: {
|
|
||||||
hiddenFields: ["custom"],
|
|
||||||
advancedFields: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const mergeSectionConfig = (
|
|
||||||
base: SectionConfig | undefined,
|
|
||||||
overrides: Partial<SectionConfig> | undefined,
|
|
||||||
): SectionConfig =>
|
|
||||||
mergeWith({}, base ?? {}, overrides ?? {}, (objValue, srcValue, key) => {
|
|
||||||
if (Array.isArray(objValue) || Array.isArray(srcValue)) {
|
|
||||||
return srcValue ?? objValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key === "uiSchema" && srcValue !== undefined) {
|
|
||||||
return srcValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
});
|
|
||||||
|
|
||||||
export function getSectionConfig(
|
|
||||||
sectionKey: string,
|
|
||||||
level: "global" | "camera",
|
|
||||||
): SectionConfig {
|
|
||||||
const entry = sectionConfigs[sectionKey];
|
|
||||||
if (!entry) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
const overrides = level === "global" ? entry.global : entry.camera;
|
|
||||||
return mergeSectionConfig(entry.base, overrides);
|
|
||||||
}
|
|
||||||
|
|||||||
32
web/src/components/config-form/sectionConfigsUtils.ts
Normal file
32
web/src/components/config-form/sectionConfigsUtils.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import mergeWith from "lodash/mergeWith";
|
||||||
|
import type { SectionConfig } from "./sections/BaseSection";
|
||||||
|
import { sectionConfigs } from "./sectionConfigs";
|
||||||
|
|
||||||
|
const mergeSectionConfig = (
|
||||||
|
base: SectionConfig | undefined,
|
||||||
|
overrides: Partial<SectionConfig> | undefined,
|
||||||
|
): SectionConfig =>
|
||||||
|
mergeWith({}, base ?? {}, overrides ?? {}, (objValue, srcValue, key) => {
|
||||||
|
if (Array.isArray(objValue) || Array.isArray(srcValue)) {
|
||||||
|
return srcValue ?? objValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key === "uiSchema" && srcValue !== undefined) {
|
||||||
|
return srcValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
export function getSectionConfig(
|
||||||
|
sectionKey: string,
|
||||||
|
level: "global" | "camera",
|
||||||
|
): SectionConfig {
|
||||||
|
const entry = sectionConfigs[sectionKey];
|
||||||
|
if (!entry) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const overrides = level === "global" ? entry.global : entry.camera;
|
||||||
|
return mergeSectionConfig(entry.base, overrides);
|
||||||
|
}
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
import { useMemo } from "react";
|
||||||
|
import { createConfigSection } from "./BaseSection";
|
||||||
|
import type { BaseSectionProps, SectionConfig } from "./BaseSection";
|
||||||
|
import { getSectionConfig } from "@/components/config-form/sectionConfigsUtils";
|
||||||
|
|
||||||
|
export type ConfigSectionTemplateProps = BaseSectionProps & {
|
||||||
|
sectionKey: string;
|
||||||
|
sectionConfig?: SectionConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function ConfigSectionTemplate({
|
||||||
|
sectionKey,
|
||||||
|
level,
|
||||||
|
sectionConfig,
|
||||||
|
...rest
|
||||||
|
}: ConfigSectionTemplateProps) {
|
||||||
|
const defaultConfig = useMemo(
|
||||||
|
() => getSectionConfig(sectionKey, level),
|
||||||
|
[sectionKey, level],
|
||||||
|
);
|
||||||
|
|
||||||
|
const SectionComponent = useMemo(
|
||||||
|
() =>
|
||||||
|
createConfigSection({
|
||||||
|
sectionPath: sectionKey,
|
||||||
|
defaultConfig,
|
||||||
|
}),
|
||||||
|
[sectionKey, defaultConfig],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SectionComponent
|
||||||
|
level={level}
|
||||||
|
sectionConfig={sectionConfig ?? defaultConfig}
|
||||||
|
{...rest}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ConfigSectionTemplate;
|
||||||
@ -7,37 +7,7 @@ export {
|
|||||||
type SectionConfig,
|
type SectionConfig,
|
||||||
type CreateSectionOptions,
|
type CreateSectionOptions,
|
||||||
} from "./BaseSection";
|
} from "./BaseSection";
|
||||||
|
export {
|
||||||
export { DetectSection } from "./DetectSection";
|
ConfigSectionTemplate,
|
||||||
export { RecordSection } from "./RecordSection";
|
type ConfigSectionTemplateProps,
|
||||||
export { SnapshotsSection } from "./SnapshotsSection";
|
} from "./ConfigSectionTemplate";
|
||||||
export { MotionSection } from "./MotionSection";
|
|
||||||
export { ObjectsSection } from "./ObjectsSection";
|
|
||||||
export { ReviewSection } from "./ReviewSection";
|
|
||||||
export { AudioSection } from "./AudioSection";
|
|
||||||
export { AudioTranscriptionSection } from "./AudioTranscriptionSection";
|
|
||||||
export { BirdseyeSection } from "./BirdseyeSection";
|
|
||||||
export { AuthSection } from "./AuthSection";
|
|
||||||
export { ClassificationSection } from "./ClassificationSection";
|
|
||||||
export { CameraMqttSection } from "./CameraMqttSection";
|
|
||||||
export { CameraUiSection } from "./CameraUiSection";
|
|
||||||
export { DatabaseSection } from "./DatabaseSection";
|
|
||||||
export { DetectorsSection } from "./DetectorsSection";
|
|
||||||
export { EnvironmentVarsSection } from "./EnvironmentVarsSection";
|
|
||||||
export { FaceRecognitionSection } from "./FaceRecognitionSection";
|
|
||||||
export { FfmpegSection } from "./FfmpegSection";
|
|
||||||
export { GenaiSection } from "./GenaiSection";
|
|
||||||
export { LprSection } from "./LprSection";
|
|
||||||
export { LoggerSection } from "./LoggerSection";
|
|
||||||
export { NotificationsSection } from "./NotificationsSection";
|
|
||||||
export { OnvifSection } from "./OnvifSection";
|
|
||||||
export { LiveSection } from "./LiveSection";
|
|
||||||
export { ModelSection } from "./ModelSection";
|
|
||||||
export { MqttSection } from "./MqttSection";
|
|
||||||
export { NetworkingSection } from "./NetworkingSection";
|
|
||||||
export { ProxySection } from "./ProxySection";
|
|
||||||
export { SemanticSearchSection } from "./SemanticSearchSection";
|
|
||||||
export { TelemetrySection } from "./TelemetrySection";
|
|
||||||
export { TimestampSection } from "./TimestampSection";
|
|
||||||
export { TlsSection } from "./TlsSection";
|
|
||||||
export { UiSection } from "./UiSection";
|
|
||||||
|
|||||||
@ -65,10 +65,6 @@ import { cn } from "@/lib/utils";
|
|||||||
import Heading from "@/components/ui/heading";
|
import Heading from "@/components/ui/heading";
|
||||||
import { LuChevronRight } from "react-icons/lu";
|
import { LuChevronRight } from "react-icons/lu";
|
||||||
import Logo from "@/components/Logo";
|
import Logo from "@/components/Logo";
|
||||||
import {
|
|
||||||
CameraMqttSection,
|
|
||||||
MqttSection,
|
|
||||||
} from "@/components/config-form/sections";
|
|
||||||
import {
|
import {
|
||||||
MobilePage,
|
MobilePage,
|
||||||
MobilePageContent,
|
MobilePageContent,
|
||||||
@ -100,13 +96,11 @@ type SettingsType = (typeof allSettingsViews)[number];
|
|||||||
const MqttSettingsPage = createSingleSectionPage({
|
const MqttSettingsPage = createSingleSectionPage({
|
||||||
sectionKey: "mqtt",
|
sectionKey: "mqtt",
|
||||||
level: "global",
|
level: "global",
|
||||||
SectionComponent: MqttSection,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const CameraMqttSettingsPage = createSingleSectionPage({
|
const CameraMqttSettingsPage = createSingleSectionPage({
|
||||||
sectionKey: "mqtt",
|
sectionKey: "mqtt",
|
||||||
level: "camera",
|
level: "camera",
|
||||||
SectionComponent: CameraMqttSection,
|
|
||||||
showOverrideIndicator: false,
|
showOverrideIndicator: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -4,24 +4,7 @@
|
|||||||
import { useMemo, useCallback, useState, memo } from "react";
|
import { useMemo, useCallback, useState, memo } from "react";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { DetectSection } from "@/components/config-form/sections/DetectSection";
|
import { ConfigSectionTemplate } from "@/components/config-form/sections";
|
||||||
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 { useAllCameraOverrides } from "@/hooks/use-config-override";
|
import { useAllCameraOverrides } from "@/hooks/use-config-override";
|
||||||
import type { FrigateConfig } from "@/types/frigateConfig";
|
import type { FrigateConfig } from "@/types/frigateConfig";
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||||
@ -203,83 +186,26 @@ const CameraConfigContent = memo(function CameraConfigContent({
|
|||||||
|
|
||||||
const sections: Array<{
|
const sections: Array<{
|
||||||
key: string;
|
key: string;
|
||||||
component: typeof DetectSection;
|
|
||||||
showOverrideIndicator?: boolean;
|
showOverrideIndicator?: boolean;
|
||||||
}> = [
|
}> = [
|
||||||
{
|
{ key: "detect" },
|
||||||
key: "detect",
|
{ key: "ffmpeg", showOverrideIndicator: true },
|
||||||
component: DetectSection,
|
{ key: "record" },
|
||||||
},
|
{ key: "snapshots" },
|
||||||
{
|
{ key: "motion" },
|
||||||
key: "ffmpeg",
|
{ key: "objects" },
|
||||||
component: FfmpegSection,
|
{ key: "review" },
|
||||||
showOverrideIndicator: true,
|
{ key: "audio" },
|
||||||
},
|
{ key: "audio_transcription", showOverrideIndicator: true },
|
||||||
{
|
{ key: "notifications" },
|
||||||
key: "record",
|
{ key: "live" },
|
||||||
component: RecordSection,
|
{ key: "birdseye", showOverrideIndicator: true },
|
||||||
},
|
{ key: "face_recognition", showOverrideIndicator: true },
|
||||||
{
|
{ key: "lpr", showOverrideIndicator: true },
|
||||||
key: "snapshots",
|
{ key: "mqtt", showOverrideIndicator: false },
|
||||||
component: SnapshotsSection,
|
{ key: "onvif", showOverrideIndicator: false },
|
||||||
},
|
{ key: "ui", showOverrideIndicator: false },
|
||||||
{
|
{ key: "timestamp_style" },
|
||||||
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,
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -327,23 +253,21 @@ const CameraConfigContent = memo(function CameraConfigContent({
|
|||||||
|
|
||||||
{/* Section Content */}
|
{/* Section Content */}
|
||||||
<div className="scrollbar-container flex-1 overflow-y-auto pr-4">
|
<div className="scrollbar-container flex-1 overflow-y-auto pr-4">
|
||||||
{sections.map((section) => {
|
{sections.map((section) => (
|
||||||
const SectionComponent = section.component;
|
<div
|
||||||
return (
|
key={section.key}
|
||||||
<div
|
className={cn(activeSection === section.key ? "block" : "hidden")}
|
||||||
key={section.key}
|
>
|
||||||
className={cn(activeSection === section.key ? "block" : "hidden")}
|
<ConfigSectionTemplate
|
||||||
>
|
sectionKey={section.key}
|
||||||
<SectionComponent
|
level="camera"
|
||||||
level="camera"
|
cameraName={cameraName}
|
||||||
cameraName={cameraName}
|
showOverrideIndicator={section.showOverrideIndicator !== false}
|
||||||
showOverrideIndicator={section.showOverrideIndicator !== false}
|
onSave={onSave}
|
||||||
onSave={onSave}
|
showTitle={true}
|
||||||
showTitle={true}
|
/>
|
||||||
/>
|
</div>
|
||||||
</div>
|
))}
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -4,81 +4,51 @@
|
|||||||
import { useMemo, useCallback, useState } from "react";
|
import { useMemo, useCallback, useState } from "react";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { DetectSection } from "@/components/config-form/sections/DetectSection";
|
import { ConfigSectionTemplate } from "@/components/config-form/sections";
|
||||||
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 type { FrigateConfig } from "@/types/frigateConfig";
|
import type { FrigateConfig } from "@/types/frigateConfig";
|
||||||
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||||
import ActivityIndicator from "@/components/indicators/activity-indicator";
|
import ActivityIndicator from "@/components/indicators/activity-indicator";
|
||||||
import Heading from "@/components/ui/heading";
|
import Heading from "@/components/ui/heading";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { getSectionConfig } from "@/components/config-form/sectionConfigs";
|
|
||||||
|
|
||||||
// Shared sections that can be overridden at camera level
|
// Shared sections that can be overridden at camera level
|
||||||
const sharedSections = [
|
const sharedSections = [
|
||||||
{ key: "detect", component: DetectSection },
|
{ key: "detect" },
|
||||||
{ key: "record", component: RecordSection },
|
{ key: "record" },
|
||||||
{ key: "snapshots", component: SnapshotsSection },
|
{ key: "snapshots" },
|
||||||
{ key: "motion", component: MotionSection },
|
{ key: "motion" },
|
||||||
{ key: "objects", component: ObjectsSection },
|
{ key: "objects" },
|
||||||
{ key: "review", component: ReviewSection },
|
{ key: "review" },
|
||||||
{ key: "audio", component: AudioSection },
|
{ key: "audio" },
|
||||||
{ key: "live", component: LiveSection },
|
{ key: "live" },
|
||||||
{ key: "timestamp_style", component: TimestampSection },
|
{ key: "timestamp_style" },
|
||||||
];
|
];
|
||||||
|
|
||||||
// System sections (global only)
|
// System sections (global only)
|
||||||
const systemSections = [
|
const systemSections = [
|
||||||
{ key: "database", component: DatabaseSection },
|
{ key: "database" },
|
||||||
{ key: "tls", component: TlsSection },
|
{ key: "tls" },
|
||||||
{ key: "auth", component: AuthSection },
|
{ key: "auth" },
|
||||||
{ key: "networking", component: NetworkingSection },
|
{ key: "networking" },
|
||||||
{ key: "proxy", component: ProxySection },
|
{ key: "proxy" },
|
||||||
{ key: "ui", component: UiSection },
|
{ key: "ui" },
|
||||||
{ key: "logger", component: LoggerSection },
|
{ key: "logger" },
|
||||||
{ key: "environment_vars", component: EnvironmentVarsSection },
|
{ key: "environment_vars" },
|
||||||
{ key: "telemetry", component: TelemetrySection },
|
{ key: "telemetry" },
|
||||||
{ key: "birdseye", component: BirdseyeSection },
|
{ key: "birdseye" },
|
||||||
{ key: "ffmpeg", component: FfmpegSection },
|
{ key: "ffmpeg" },
|
||||||
{ key: "detectors", component: DetectorsSection },
|
{ key: "detectors" },
|
||||||
{ key: "model", component: ModelSection },
|
{ key: "model" },
|
||||||
];
|
];
|
||||||
|
|
||||||
// Integration sections (global only)
|
// Integration sections (global only)
|
||||||
const integrationSections = [
|
const integrationSections = [
|
||||||
{ key: "mqtt", component: MqttSection },
|
{ key: "mqtt" },
|
||||||
{ key: "semantic_search", component: SemanticSearchSection },
|
{ key: "semantic_search" },
|
||||||
{ key: "genai", component: GenaiSection },
|
{ key: "genai" },
|
||||||
{ key: "face_recognition", component: FaceRecognitionSection },
|
{ key: "face_recognition" },
|
||||||
{ key: "lpr", component: LprSection },
|
{ key: "lpr" },
|
||||||
{ key: "classification", component: ClassificationSection },
|
{ key: "classification" },
|
||||||
{ key: "audio_transcription", component: AudioTranscriptionSection },
|
{ key: "audio_transcription" },
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function GlobalConfigView() {
|
export default function GlobalConfigView() {
|
||||||
@ -201,24 +171,21 @@ export default function GlobalConfigView() {
|
|||||||
|
|
||||||
{/* Section Content */}
|
{/* Section Content */}
|
||||||
<div className="scrollbar-container flex-1 overflow-y-auto pr-4">
|
<div className="scrollbar-container flex-1 overflow-y-auto pr-4">
|
||||||
{currentSections.map((section) => {
|
{currentSections.map((section) => (
|
||||||
const SectionComponent = section.component;
|
<div
|
||||||
return (
|
key={section.key}
|
||||||
<div
|
className={cn(
|
||||||
key={section.key}
|
activeSection === section.key ? "block" : "hidden",
|
||||||
className={cn(
|
)}
|
||||||
activeSection === section.key ? "block" : "hidden",
|
>
|
||||||
)}
|
<ConfigSectionTemplate
|
||||||
>
|
sectionKey={section.key}
|
||||||
<SectionComponent
|
level="global"
|
||||||
level="global"
|
onSave={handleSave}
|
||||||
onSave={handleSave}
|
showTitle={true}
|
||||||
showTitle={true}
|
/>
|
||||||
sectionConfig={getSectionConfig(section.key, "global")}
|
</div>
|
||||||
/>
|
))}
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import Heading from "@/components/ui/heading";
|
import Heading from "@/components/ui/heading";
|
||||||
import type {
|
import type { SectionConfig } from "@/components/config-form/sections";
|
||||||
BaseSectionProps,
|
import { ConfigSectionTemplate } from "@/components/config-form/sections";
|
||||||
SectionConfig,
|
|
||||||
} from "@/components/config-form/sections";
|
|
||||||
import type { PolygonType } from "@/types/canvas";
|
import type { PolygonType } from "@/types/canvas";
|
||||||
|
|
||||||
export type SettingsPageProps = {
|
export type SettingsPageProps = {
|
||||||
@ -15,7 +13,6 @@ export type SettingsPageProps = {
|
|||||||
export type SingleSectionPageOptions = {
|
export type SingleSectionPageOptions = {
|
||||||
sectionKey: string;
|
sectionKey: string;
|
||||||
level: "global" | "camera";
|
level: "global" | "camera";
|
||||||
SectionComponent: React.ComponentType<BaseSectionProps>;
|
|
||||||
sectionConfig?: SectionConfig;
|
sectionConfig?: SectionConfig;
|
||||||
requiresRestart?: boolean;
|
requiresRestart?: boolean;
|
||||||
showOverrideIndicator?: boolean;
|
showOverrideIndicator?: boolean;
|
||||||
@ -24,7 +21,6 @@ export type SingleSectionPageOptions = {
|
|||||||
export function createSingleSectionPage({
|
export function createSingleSectionPage({
|
||||||
sectionKey,
|
sectionKey,
|
||||||
level,
|
level,
|
||||||
SectionComponent,
|
|
||||||
sectionConfig,
|
sectionConfig,
|
||||||
requiresRestart,
|
requiresRestart,
|
||||||
showOverrideIndicator = true,
|
showOverrideIndicator = true,
|
||||||
@ -63,7 +59,8 @@ export function createSingleSectionPage({
|
|||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<SectionComponent
|
<ConfigSectionTemplate
|
||||||
|
sectionKey={sectionKey}
|
||||||
level={level}
|
level={level}
|
||||||
cameraName={level === "camera" ? selectedCamera : undefined}
|
cameraName={level === "camera" ? selectedCamera : undefined}
|
||||||
showOverrideIndicator={showOverrideIndicator}
|
showOverrideIndicator={showOverrideIndicator}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user