From b4462138fb6eb235de3cca7a3be81a4c757ca212 Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Fri, 16 Jan 2026 08:00:50 -0600 Subject: [PATCH] allow toggle from icon --- web/src/components/settings/PolygonItem.tsx | 198 +++++++++++++++++++- 1 file changed, 189 insertions(+), 9 deletions(-) diff --git a/web/src/components/settings/PolygonItem.tsx b/web/src/components/settings/PolygonItem.tsx index dc5dbe6f6..21815563b 100644 --- a/web/src/components/settings/PolygonItem.tsx +++ b/web/src/components/settings/PolygonItem.tsx @@ -32,6 +32,7 @@ import { reviewQueries } from "@/utils/zoneEdutUtil"; import IconWrapper from "../ui/icon-wrapper"; import { buttonVariants } from "../ui/button"; import { Trans, useTranslation } from "react-i18next"; +import ActivityIndicator from "../indicators/activity-indicator"; type PolygonItemProps = { polygon: Polygon; @@ -242,6 +243,158 @@ export default function PolygonItem({ saveToConfig(polygon); }; + const handleToggleEnabled = useCallback( + async (e: React.MouseEvent) => { + e.stopPropagation(); + if (!polygon || !cameraConfig) { + return; + } + + const newEnabledState = polygon.enabled === false; + const updateTopicType = + polygon.type === "zone" + ? "zones" + : polygon.type === "motion_mask" + ? "motion" + : polygon.type === "object_mask" + ? "objects" + : polygon.type; + + setIsLoading(true); + + if (polygon.type === "zone") { + // Zones use query string format + const url = `cameras.${polygon.camera}.zones.${polygon.name}.enabled=${newEnabledState ? "True" : "False"}`; + + await axios + .put(`config/set?${url}`, { + requires_restart: 0, + update_topic: `config/cameras/${polygon.camera}/${updateTopicType}`, + }) + .then((res) => { + if (res.status === 200) { + updateConfig(); + } else { + toast.error( + t("toast.save.error.title", { + ns: "common", + errorMessage: res.statusText, + }), + { position: "top-center" }, + ); + } + }) + .catch((error) => { + const errorMessage = + error.response?.data?.message || + error.response?.data?.detail || + "Unknown error"; + toast.error( + t("toast.save.error.title", { errorMessage, ns: "common" }), + { position: "top-center" }, + ); + }) + .finally(() => { + setIsLoading(false); + }); + return; + } + + // Motion masks and object masks use JSON body format + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let configUpdate: any = {}; + + if (polygon.type === "motion_mask") { + configUpdate = { + cameras: { + [polygon.camera]: { + motion: { + mask: { + [polygon.name]: { + enabled: newEnabledState, + }, + }, + }, + }, + }, + }; + } + + if (polygon.type === "object_mask") { + // Determine if this is a global mask or object-specific mask + const isGlobalMask = !polygon.objects.length; + + if (isGlobalMask) { + configUpdate = { + cameras: { + [polygon.camera]: { + objects: { + mask: { + [polygon.name]: { + enabled: newEnabledState, + }, + }, + }, + }, + }, + }; + } else { + configUpdate = { + cameras: { + [polygon.camera]: { + objects: { + filters: { + [polygon.objects[0]]: { + mask: { + [polygon.name]: { + enabled: newEnabledState, + }, + }, + }, + }, + }, + }, + }, + }; + } + } + + await axios + .put("config/set", { + config_data: configUpdate, + requires_restart: 0, + update_topic: `config/cameras/${polygon.camera}/${updateTopicType}`, + }) + .then((res) => { + if (res.status === 200) { + updateConfig(); + } else { + toast.error( + t("toast.save.error.title", { + ns: "common", + errorMessage: res.statusText, + }), + { position: "top-center" }, + ); + } + }) + .catch((error) => { + const errorMessage = + error.response?.data?.message || + error.response?.data?.detail || + "Unknown error"; + toast.error( + t("toast.save.error.title", { errorMessage, ns: "common" }), + { position: "top-center" }, + ); + }) + .finally(() => { + setIsLoading(false); + }); + }, + [updateConfig, cameraConfig, t, polygon], + ); + return ( <> @@ -266,15 +419,42 @@ export default function PolygonItem({ : "text-primary-variant" }`} > - {PolygonItemIcon && ( - - )} + {PolygonItemIcon && + (isLoading ? ( +
+ +
+ ) : ( + + + + + + {polygon.enabled === false + ? t("button.enable", { ns: "common" }) + : t("button.disable", { ns: "common" })} + + + ))}