From 543ff91cfe626991c7a9f874bcba7abc72a763fc Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Mon, 17 Mar 2025 13:16:15 -0500 Subject: [PATCH] add frigate+ page in settings --- web/public/locales/en/views/settings.json | 37 ++- web/src/pages/Settings.tsx | 3 + .../settings/FrigatePlusSettingsView.tsx | 229 ++++++++++++++++++ 3 files changed, 267 insertions(+), 2 deletions(-) create mode 100644 web/src/views/settings/FrigatePlusSettingsView.tsx diff --git a/web/public/locales/en/views/settings.json b/web/public/locales/en/views/settings.json index f19ac5ee6..3d25b92c1 100644 --- a/web/public/locales/en/views/settings.json +++ b/web/public/locales/en/views/settings.json @@ -7,7 +7,8 @@ "masksAndZones": "Mask and Zone Editor - Frigate", "motionTuner": "Motion Tuner - Frigate", "object": "Object Settings - Frigate", - "general": "General Settings - Frigate" + "general": "General Settings - Frigate", + "frigatePlus": "Frigate+ Settings - Frigate" }, "menu": { "uiSettings": "UI Settings", @@ -17,7 +18,8 @@ "motionTuner": "Motion Tuner", "debug": "Debug", "users": "Users", - "notifications": "Notifications" + "notifications": "Notifications", + "frigateplus": "Frigate+" }, "dialog": { "unsavedChanges": { @@ -515,5 +517,36 @@ "registerFailed": "Failed to save notification registration." } } + }, + "frigatePlus": { + "title": "Frigate+ Settings", + "apiKey": { + "title": "Frigate+ API Key", + "validated": "Frigate+ API key is detected and validated", + "notValidated": "Frigate+ API key is not detected or not validated", + "desc": "The Frigate+ API key enables integration with the Frigate+ service.", + "plusLink": "Read more about Frigate+" + }, + "snapshotConfig": { + "title": "Snapshot Configuration", + "desc": "Submitting to Frigate+ requires both snapshots and clean_copy snapshots to be enabled in your config.", + "documentation": "Read the documentation", + "cleanCopyWarning": "Some cameras have snapshots enabled but have the clean copy disabled. You need to enable clean_copy in your snapshot config to be able to submit images from these cameras to Frigate+.", + "table": { + "camera": "Camera", + "snapshots": "Snapshots", + "cleanCopySnapshots": "clean_copy Snapshots" + } + }, + "modelInfo": { + "title": "Model Information", + "modelType": "Model Type", + "trainDate": "Train Date", + "baseModel": "Base Model", + "supportedDetectors": "Supported Detectors", + "cameras": "Cameras", + "loading": "Loading model information...", + "error": "Failed to load model information" + } } } diff --git a/web/src/pages/Settings.tsx b/web/src/pages/Settings.tsx index 353d0dbf8..6ccda34f3 100644 --- a/web/src/pages/Settings.tsx +++ b/web/src/pages/Settings.tsx @@ -37,6 +37,7 @@ import AuthenticationView from "@/views/settings/AuthenticationView"; import NotificationView from "@/views/settings/NotificationsSettingsView"; import ClassificationSettingsView from "@/views/settings/ClassificationSettingsView"; import UiSettingsView from "@/views/settings/UiSettingsView"; +import FrigatePlusSettingsView from "@/views/settings/FrigatePlusSettingsView"; import { useSearchEffect } from "@/hooks/use-overlay-state"; import { useSearchParams } from "react-router-dom"; import { useInitialCameraState } from "@/api/ws"; @@ -54,6 +55,7 @@ const allSettingsViews = [ "debug", "users", "notifications", + "frigateplus", ] as const; type SettingsType = (typeof allSettingsViews)[number]; @@ -279,6 +281,7 @@ export default function Settings() { {page == "notifications" && ( )} + {page == "frigateplus" && } {confirmationDialogOpen && ( ("config"); + const { t } = useTranslation("views/settings"); + + useEffect(() => { + document.title = t("documentTitle.frigatePlus"); + }, [t]); + + const needCleanSnapshots = () => { + if (!config) { + return false; + } + return Object.values(config.cameras).some( + (camera) => camera.snapshots.enabled && !camera.snapshots.clean_copy, + ); + }; + + return ( + <> +
+ +
+ + {t("frigatePlus.title")} + + + + + + {t("frigatePlus.apiKey.title")} + + +
+
+
+ {config?.plus?.enabled ? ( + + ) : ( + + )} + +
+
+

{t("frigatePlus.apiKey.desc")}

+ {!config?.model.plus && ( + <> +
+ + {t("frigatePlus.apiKey.plusLink")} + + +
+ + )} +
+
+ + {config?.model.plus && ( + <> + +
+ + {t("frigatePlus.modelInfo.title")} + +
+ {!config?.model?.plus && ( +

+ {t("frigatePlus.modelInfo.loading")} +

+ )} + {config?.model?.plus === null && ( +

+ {t("frigatePlus.modelInfo.error")} +

+ )} + {config?.model?.plus && ( +
+
+ +

{config.model.plus.name}

+
+
+ +

+ {new Date( + config.model.plus.trainDate, + ).toLocaleString()} +

+
+
+ +

{config.model.plus.baseModel}

+
+
+ +

+ {config.model.plus.supportedDetectors.join(", ")} +

+
+
+ )} +
+
+ + )} + + + +
+ + {t("frigatePlus.snapshotConfig.title")} + +
+
+

+ + frigatePlus.snapshotConfig.desc + +

+
+ + {t("frigatePlus.snapshotConfig.documentation")} + + +
+
+ {config && ( +
+ + + + + + + + + + {Object.entries(config.cameras).map( + ([name, camera]) => ( + + + + + + ), + )} + +
+ {t("frigatePlus.snapshotConfig.table.camera")} + + {t("frigatePlus.snapshotConfig.table.snapshots")} + + + frigatePlus.snapshotConfig.table.cleanCopySnapshots + +
{name} + {camera.snapshots.enabled ? ( + + ) : ( + + )} + + {camera.snapshots?.enabled && + camera.snapshots?.clean_copy ? ( + + ) : ( + + )} +
+
+ )} + {needCleanSnapshots() && ( +
+
+ +
+ + frigatePlus.snapshotConfig.cleanCopyWarning + +
+
+
+ )} +
+
+
+
+
+ + ); +}