From 6ee5e70005596ce034c271ec8e74b1429f74e4ca Mon Sep 17 00:00:00 2001
From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
Date: Sun, 29 Mar 2026 13:06:52 -0500
Subject: [PATCH] add a basic set of messages
---
web/public/locales/en/views/settings.json | 23 ++++++++++++++++++-
.../config-form/ConfigMessageBanner.tsx | 4 ++--
.../section-configs/audio_transcription.ts | 13 +++++++++++
.../config-form/section-configs/birdseye.ts | 14 +++++++++++
.../section-configs/face_recognition.ts | 20 ++++++++++++++++
.../config-form/section-configs/lpr.ts | 22 ++++++++++++++++++
.../config-form/section-configs/record.ts | 13 +++++++++++
.../config-form/section-configs/review.ts | 11 +++++++++
.../config-form/section-configs/snapshots.ts | 11 +++++++++
9 files changed, 128 insertions(+), 3 deletions(-)
diff --git a/web/public/locales/en/views/settings.json b/web/public/locales/en/views/settings.json
index 1ff14f63c..1c69fe4b5 100644
--- a/web/public/locales/en/views/settings.json
+++ b/web/public/locales/en/views/settings.json
@@ -1609,13 +1609,34 @@
},
"configMessages": {
"review": {
- "recordDisabled": "Recording is disabled, review items will not be generated."
+ "recordDisabled": "Recording is disabled, review items will not be generated.",
+ "detectDisabled": "Object detection is disabled. Review items require detected objects to categorize alerts and detections."
},
"audio": {
"noAudioRole": "No streams have the audio role defined. You must enable the audio role for audio detection to function."
},
+ "audioTranscription": {
+ "audioDetectionDisabled": "Audio detection is not enabled for this camera. Audio transcription requires audio detection to be active."
+ },
"detect": {
"fpsGreaterThanFive": "Setting the detect FPS higher than 5 is not recommended."
+ },
+ "faceRecognition": {
+ "globalDisabled": "Face recognition is not enabled at the global level. Enable it in global settings for camera-level face recognition to function.",
+ "personNotTracked": "Face recognition requires the 'person' object to be tracked. Ensure 'person' is in the object tracking list."
+ },
+ "lpr": {
+ "globalDisabled": "License plate recognition is not enabled at the global level. Enable it in global settings for camera-level LPR to function.",
+ "vehicleNotTracked": "License plate recognition requires 'car' or 'motorcycle' to be tracked."
+ },
+ "record": {
+ "noRecordRole": "No streams have the record role defined. Recording will not function."
+ },
+ "birdseye": {
+ "objectsModeDetectDisabled": "Birdseye is set to 'objects' mode, but object detection is disabled for this camera. The camera will not appear in Birdseye."
+ },
+ "snapshots": {
+ "detectDisabled": "Object detection is disabled. Snapshots are generated from tracked objects and will not be created."
}
}
}
diff --git a/web/src/components/config-form/ConfigMessageBanner.tsx b/web/src/components/config-form/ConfigMessageBanner.tsx
index 15455705d..f5b828000 100644
--- a/web/src/components/config-form/ConfigMessageBanner.tsx
+++ b/web/src/components/config-form/ConfigMessageBanner.tsx
@@ -36,12 +36,12 @@ export function ConfigMessageBanner({ messages }: ConfigMessageBannerProps) {
if (messages.length === 0) return null;
return (
-
+
{messages.map((msg) => (
{t(msg.messageKey)}
diff --git a/web/src/components/config-form/section-configs/audio_transcription.ts b/web/src/components/config-form/section-configs/audio_transcription.ts
index 169a77954..8e8e70d77 100644
--- a/web/src/components/config-form/section-configs/audio_transcription.ts
+++ b/web/src/components/config-form/section-configs/audio_transcription.ts
@@ -3,6 +3,19 @@ import type { SectionConfigOverrides } from "./types";
const audioTranscription: SectionConfigOverrides = {
base: {
sectionDocs: "/configuration/audio_detectors#audio-transcription",
+ messages: [
+ {
+ key: "audio-detection-disabled",
+ messageKey: "configMessages.audioTranscription.audioDetectionDisabled",
+ severity: "warning",
+ condition: (ctx) => {
+ if (ctx.level === "camera" && ctx.fullCameraConfig) {
+ return ctx.fullCameraConfig.audio.enabled === false;
+ }
+ return false;
+ },
+ },
+ ],
restartRequired: [],
fieldOrder: ["enabled", "language", "device", "model_size"],
hiddenFields: ["enabled_in_config", "live_enabled"],
diff --git a/web/src/components/config-form/section-configs/birdseye.ts b/web/src/components/config-form/section-configs/birdseye.ts
index 63fae75d9..d621c9203 100644
--- a/web/src/components/config-form/section-configs/birdseye.ts
+++ b/web/src/components/config-form/section-configs/birdseye.ts
@@ -3,6 +3,20 @@ import type { SectionConfigOverrides } from "./types";
const birdseye: SectionConfigOverrides = {
base: {
sectionDocs: "/configuration/birdseye",
+ messages: [
+ {
+ key: "objects-mode-detect-disabled",
+ messageKey: "configMessages.birdseye.objectsModeDetectDisabled",
+ severity: "info",
+ condition: (ctx) => {
+ if (ctx.level !== "camera" || !ctx.fullCameraConfig) return false;
+ return (
+ ctx.formData?.mode === "objects" &&
+ ctx.fullCameraConfig.detect?.enabled === false
+ );
+ },
+ },
+ ],
restartRequired: [],
fieldOrder: ["enabled", "mode", "order"],
hiddenFields: [],
diff --git a/web/src/components/config-form/section-configs/face_recognition.ts b/web/src/components/config-form/section-configs/face_recognition.ts
index ef9e43506..822f6ffe0 100644
--- a/web/src/components/config-form/section-configs/face_recognition.ts
+++ b/web/src/components/config-form/section-configs/face_recognition.ts
@@ -3,6 +3,26 @@ import type { SectionConfigOverrides } from "./types";
const faceRecognition: SectionConfigOverrides = {
base: {
sectionDocs: "/configuration/face_recognition",
+ messages: [
+ {
+ key: "global-disabled",
+ messageKey: "configMessages.faceRecognition.globalDisabled",
+ severity: "warning",
+ condition: (ctx) => {
+ if (ctx.level !== "camera") return false;
+ return ctx.fullConfig.face_recognition?.enabled === false;
+ },
+ },
+ {
+ key: "person-not-tracked",
+ messageKey: "configMessages.faceRecognition.personNotTracked",
+ severity: "info",
+ condition: (ctx) => {
+ if (ctx.level !== "camera" || !ctx.fullCameraConfig) return false;
+ return !ctx.fullCameraConfig.objects?.track?.includes("person");
+ },
+ },
+ ],
restartRequired: [],
fieldOrder: ["enabled", "min_area"],
hiddenFields: [],
diff --git a/web/src/components/config-form/section-configs/lpr.ts b/web/src/components/config-form/section-configs/lpr.ts
index 514dba9be..4997d766f 100644
--- a/web/src/components/config-form/section-configs/lpr.ts
+++ b/web/src/components/config-form/section-configs/lpr.ts
@@ -3,6 +3,28 @@ import type { SectionConfigOverrides } from "./types";
const lpr: SectionConfigOverrides = {
base: {
sectionDocs: "/configuration/license_plate_recognition",
+ messages: [
+ {
+ key: "global-disabled",
+ messageKey: "configMessages.lpr.globalDisabled",
+ severity: "warning",
+ condition: (ctx) => {
+ if (ctx.level !== "camera") return false;
+ return ctx.fullConfig.lpr?.enabled === false;
+ },
+ },
+ {
+ key: "vehicle-not-tracked",
+ messageKey: "configMessages.lpr.vehicleNotTracked",
+ severity: "info",
+ condition: (ctx) => {
+ if (ctx.level !== "camera" || !ctx.fullCameraConfig) return false;
+ if (ctx.fullCameraConfig.type === "lpr") return false;
+ const tracked = ctx.fullCameraConfig.objects?.track ?? [];
+ return !tracked.some((o) => ["car", "motorcycle"].includes(o));
+ },
+ },
+ ],
fieldDocs: {
enhancement: "/configuration/license_plate_recognition#enhancement",
},
diff --git a/web/src/components/config-form/section-configs/record.ts b/web/src/components/config-form/section-configs/record.ts
index 05a21f224..35f3b1ef7 100644
--- a/web/src/components/config-form/section-configs/record.ts
+++ b/web/src/components/config-form/section-configs/record.ts
@@ -3,6 +3,19 @@ import type { SectionConfigOverrides } from "./types";
const record: SectionConfigOverrides = {
base: {
sectionDocs: "/configuration/record",
+ messages: [
+ {
+ key: "no-record-role",
+ messageKey: "configMessages.record.noRecordRole",
+ severity: "warning",
+ condition: (ctx) => {
+ if (ctx.level !== "camera" || !ctx.fullCameraConfig) return false;
+ return !ctx.fullCameraConfig.ffmpeg?.inputs?.some((i) =>
+ i.roles?.includes("record"),
+ );
+ },
+ },
+ ],
restartRequired: [],
fieldOrder: [
"enabled",
diff --git a/web/src/components/config-form/section-configs/review.ts b/web/src/components/config-form/section-configs/review.ts
index 6805e8cc3..8b8fdc5af 100644
--- a/web/src/components/config-form/section-configs/review.ts
+++ b/web/src/components/config-form/section-configs/review.ts
@@ -15,6 +15,17 @@ const review: SectionConfigOverrides = {
return ctx.fullConfig.record?.enabled === false;
},
},
+ {
+ key: "detect-disabled",
+ messageKey: "configMessages.review.detectDisabled",
+ severity: "info",
+ condition: (ctx) => {
+ if (ctx.level === "camera" && ctx.fullCameraConfig) {
+ return ctx.fullCameraConfig.detect?.enabled === false;
+ }
+ return false;
+ },
+ },
],
fieldDocs: {
"alerts.labels": "/configuration/review/#alerts-and-detections",
diff --git a/web/src/components/config-form/section-configs/snapshots.ts b/web/src/components/config-form/section-configs/snapshots.ts
index 126ecd496..7d08cc728 100644
--- a/web/src/components/config-form/section-configs/snapshots.ts
+++ b/web/src/components/config-form/section-configs/snapshots.ts
@@ -3,6 +3,17 @@ import type { SectionConfigOverrides } from "./types";
const snapshots: SectionConfigOverrides = {
base: {
sectionDocs: "/configuration/snapshots",
+ messages: [
+ {
+ key: "detect-disabled",
+ messageKey: "configMessages.snapshots.detectDisabled",
+ severity: "info",
+ condition: (ctx) => {
+ if (ctx.level !== "camera" || !ctx.fullCameraConfig) return false;
+ return ctx.fullCameraConfig.detect?.enabled === false;
+ },
+ },
+ ],
restartRequired: [],
fieldOrder: [
"enabled",