diff --git a/web/public/locales/en/views/settings.json b/web/public/locales/en/views/settings.json index a0f8f1630..433f64c6f 100644 --- a/web/public/locales/en/views/settings.json +++ b/web/public/locales/en/views/settings.json @@ -984,8 +984,8 @@ "title": "Frigate+ Settings", "cardTitles": { "api": "API", - "currentModel": "Current model", - "otherModels": "Other models", + "currentModel": "Current Model", + "otherModels": "Other Models", "configuration": "Configuration" }, "apiKey": { @@ -1029,6 +1029,15 @@ "error": "Failed to save config changes: {{errorMessage}}" } }, + "detectionModel": { + "plusActive": { + "title": "Frigate+ model management", + "label": "Current model source", + "description": "This instance is running a Frigate+ model. Select or change your model in Frigate+ settings.", + "goToFrigatePlus": "Go to Frigate+ settings", + "showModelForm": "Manually configure a model" + } + }, "triggers": { "documentTitle": "Triggers", "semanticSearch": { diff --git a/web/src/pages/Settings.tsx b/web/src/pages/Settings.tsx index 2070afbca..6958ee895 100644 --- a/web/src/pages/Settings.tsx +++ b/web/src/pages/Settings.tsx @@ -41,6 +41,7 @@ import RolesView from "@/views/settings/RolesView"; import UiSettingsView from "@/views/settings/UiSettingsView"; import FrigatePlusSettingsView from "@/views/settings/FrigatePlusSettingsView"; import MaintenanceSettingsView from "@/views/settings/MaintenanceSettingsView"; +import SystemDetectionModelSettingsView from "@/views/settings/SystemDetectionModelSettingsView"; import { SingleSectionPage, type SettingsPageProps, @@ -239,7 +240,7 @@ const SystemDetectorHardwareSettingsPage = createSectionPage( "detectors", "global", ); -const SystemDetectionModelSettingsPage = createSectionPage("model", "global"); +const SystemDetectionModelSettingsPage = SystemDetectionModelSettingsView; const NotificationsSettingsPage = createSectionPage("notifications", "global"); const SystemMqttSettingsPage = createSectionPage("mqtt", "global"); diff --git a/web/src/types/frigateConfig.ts b/web/src/types/frigateConfig.ts index 7c69ef808..d4ed0b9b7 100644 --- a/web/src/types/frigateConfig.ts +++ b/web/src/types/frigateConfig.ts @@ -467,7 +467,7 @@ export interface FrigateConfig { supportedDetectors: string[]; width: number; height: number; - }; + } | null; }; motion: Record | null; diff --git a/web/src/views/settings/FrigatePlusSettingsView.tsx b/web/src/views/settings/FrigatePlusSettingsView.tsx index 64d73c324..c38ed9109 100644 --- a/web/src/views/settings/FrigatePlusSettingsView.tsx +++ b/web/src/views/settings/FrigatePlusSettingsView.tsx @@ -26,6 +26,7 @@ import { SettingsGroupCard, SplitCardRow, } from "@/components/card/SettingsGroupCard"; +import FrigatePlusCurrentModelSummary from "@/views/settings/components/FrigatePlusCurrentModelSummary"; type FrigatePlusModel = { id: string; @@ -259,70 +260,7 @@ export default function FrigatePlusSettingsView({ {config?.model.plus && ( - - {!config?.model?.plus && ( -

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

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

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

- )} - {config?.model?.plus && ( -
- - {config.model.plus.baseModel} ( - {config.model.plus.isBaseModel - ? t( - "frigatePlus.modelInfo.plusModelType.baseModel", - ) - : t( - "frigatePlus.modelInfo.plusModelType.userModel", - )} - ) -

- } - /> - - {new Date( - config.model.plus.trainDate, - ).toLocaleString()} -

- } - /> - - {config.model.plus.name} ( - {config.model.plus.width + - "x" + - config.model.plus.height} - ) -

- } - /> - - {config.model.plus.supportedDetectors.join(", ")} -

- } - /> -
- )} -
+ )} {config?.model.plus && ( diff --git a/web/src/views/settings/SystemDetectionModelSettingsView.tsx b/web/src/views/settings/SystemDetectionModelSettingsView.tsx new file mode 100644 index 000000000..7038378a2 --- /dev/null +++ b/web/src/views/settings/SystemDetectionModelSettingsView.tsx @@ -0,0 +1,88 @@ +import ActivityIndicator from "@/components/indicators/activity-indicator"; +import Heading from "@/components/ui/heading"; +import { Button } from "@/components/ui/button"; +import { useState } from "react"; +import { useNavigate } from "react-router-dom"; +import useSWR from "swr"; +import type { FrigateConfig } from "@/types/frigateConfig"; +import { + SettingsGroupCard, + SplitCardRow, +} from "@/components/card/SettingsGroupCard"; +import { + SingleSectionPage, + type SettingsPageProps, +} from "@/views/settings/SingleSectionPage"; +import FrigatePlusCurrentModelSummary from "@/views/settings/components/FrigatePlusCurrentModelSummary"; +import { useTranslation } from "react-i18next"; + +export default function SystemDetectionModelSettingsView( + props: SettingsPageProps, +) { + const { t } = useTranslation(["config/global", "views/settings"]); + const { data: config } = useSWR("config"); + const [showModelForm, setShowModelForm] = useState(false); + const navigate = useNavigate(); + + if (!config) { + return ; + } + + const isPlusModelActive = Boolean(config?.model?.plus?.id); + + if (!isPlusModelActive || showModelForm) { + return ; + } + + return ( +
+
+
+ {t("model.label", { ns: "config/global" })} +
+ {t("model.description", { ns: "config/global" })} +
+
+
+ +
+ + + + +
+ } + /> + + + +
+ + ); +} diff --git a/web/src/views/settings/components/FrigatePlusCurrentModelSummary.tsx b/web/src/views/settings/components/FrigatePlusCurrentModelSummary.tsx new file mode 100644 index 000000000..9a4d26130 --- /dev/null +++ b/web/src/views/settings/components/FrigatePlusCurrentModelSummary.tsx @@ -0,0 +1,61 @@ +import { + SettingsGroupCard, + SplitCardRow, +} from "@/components/card/SettingsGroupCard"; +import type { FrigateConfig } from "@/types/frigateConfig"; +import { useTranslation } from "react-i18next"; + +type FrigatePlusCurrentModelSummaryProps = { + plusModel: FrigateConfig["model"]["plus"]; +}; + +export default function FrigatePlusCurrentModelSummary({ + plusModel, +}: FrigatePlusCurrentModelSummaryProps) { + const { t } = useTranslation("views/settings"); + + return ( + + {plusModel === undefined && ( +

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

+ )} + {plusModel === null && ( +

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

+ )} + {plusModel && ( +
+ + {plusModel.baseModel} ( + {plusModel.isBaseModel + ? t("frigatePlus.modelInfo.plusModelType.baseModel") + : t("frigatePlus.modelInfo.plusModelType.userModel")} + ) +

+ } + /> + {new Date(plusModel.trainDate).toLocaleString()}

} + /> + + {plusModel.name} ({plusModel.width + "x" + plusModel.height}) +

+ } + /> + {plusModel.supportedDetectors.join(", ")}

} + /> +
+ )} +
+ ); +}