disable id field when editing profile mask/zone

also, disable if the zone name already exists in required_zones or the base config is being edited and the id already exists on a profile
This commit is contained in:
Josh Hawkins 2026-05-24 21:08:47 -05:00
parent 709a54ade4
commit f35bbd4ac0
3 changed files with 36 additions and 6 deletions

View File

@ -258,8 +258,9 @@ export default function MotionMaskEditPane({
}, },
); );
updateConfig(); updateConfig();
// Only publish WS state for base config when mask has a name // Only publish WS state for base config when mask has a name and
if (!editingProfile && maskName) { // wasn't renamed (the hook is bound to the old name).
if (!editingProfile && maskName && !renamingMask) {
sendMotionMaskState(enabled ? "ON" : "OFF"); sendMotionMaskState(enabled ? "ON" : "OFF");
} }
} else { } else {
@ -414,6 +415,7 @@ export default function MotionMaskEditPane({
nameLabel={t("masksAndZones.motionMasks.name.title")} nameLabel={t("masksAndZones.motionMasks.name.title")}
nameDescription={t("masksAndZones.motionMasks.name.description")} nameDescription={t("masksAndZones.motionMasks.name.description")}
placeholderName={t("masksAndZones.motionMasks.name.placeholder")} placeholderName={t("masksAndZones.motionMasks.name.placeholder")}
idDisabled={!!editingProfile && polygon.name.length > 0}
/> />
<FormField <FormField
control={form.control} control={form.control}

View File

@ -263,8 +263,9 @@ export default function ObjectMaskEditPane({
}, },
); );
updateConfig(); updateConfig();
// Only publish WS state for base config when mask has a name // Only publish WS state for base config when mask has a name and
if (!editingProfile && maskName) { // wasn't renamed (the hook is bound to the old name).
if (!editingProfile && maskName && !renamingMask) {
sendObjectMaskState(enabled ? "ON" : "OFF"); sendObjectMaskState(enabled ? "ON" : "OFF");
} }
} else { } else {
@ -389,6 +390,7 @@ export default function ObjectMaskEditPane({
placeholderName={t( placeholderName={t(
"masksAndZones.objectMasks.name.placeholder", "masksAndZones.objectMasks.name.placeholder",
)} )}
idDisabled={!!editingProfile && polygon.name.length > 0}
/> />
<FormField <FormField
control={form.control} control={form.control}

View File

@ -94,6 +94,28 @@ export default function ZoneEditPane({
const zoneName = polygon?.name || ""; const zoneName = polygon?.name || "";
const { send: sendZoneState } = useZoneState(polygon?.camera || "", zoneName); const { send: sendZoneState } = useZoneState(polygon?.camera || "", zoneName);
const isExistingZone = !!polygon && polygon.name.length > 0;
const idDisabled = useMemo(() => {
if (!isExistingZone || !polygon) {
return false;
}
if (editingProfile) {
return true;
}
const cam = config?.cameras[polygon.camera];
if (!cam) {
return false;
}
const inRequiredZones =
cam.review.alerts.required_zones.includes(polygon.name) ||
cam.review.detections.required_zones.includes(polygon.name);
const hasProfileOverride = Object.values(cam.profiles ?? {}).some(
(profile) => profile?.zones && polygon.name in profile.zones,
);
return inRequiredZones || hasProfileOverride;
}, [config, polygon, editingProfile, isExistingZone]);
const cameraConfig = useMemo(() => { const cameraConfig = useMemo(() => {
if (polygon?.camera && config) { if (polygon?.camera && config) {
return config.cameras[polygon.camera]; return config.cameras[polygon.camera];
@ -419,6 +441,7 @@ export default function ZoneEditPane({
toast.error(t("toast.save.error.noMessage", { ns: "common" }), { toast.error(t("toast.save.error.noMessage", { ns: "common" }), {
position: "top-center", position: "top-center",
}); });
setIsLoading(false);
return; return;
} }
@ -444,6 +467,7 @@ export default function ZoneEditPane({
toast.error(t("toast.save.error.noMessage", { ns: "common" }), { toast.error(t("toast.save.error.noMessage", { ns: "common" }), {
position: "top-center", position: "top-center",
}); });
setIsLoading(false);
return; return;
} }
} }
@ -527,8 +551,9 @@ export default function ZoneEditPane({
}, },
); );
updateConfig(); updateConfig();
// Only publish WS state for base config when zone has a name // Only publish WS state for base config when zone has a name and
if (!editingProfile && polygon?.name) { // wasn't renamed (the hook is bound to the old name).
if (!editingProfile && polygon?.name && !renamingZone) {
sendZoneState(enabled ? "ON" : "OFF"); sendZoneState(enabled ? "ON" : "OFF");
} }
} else { } else {
@ -650,6 +675,7 @@ export default function ZoneEditPane({
nameLabel={t("masksAndZones.zones.name.title")} nameLabel={t("masksAndZones.zones.name.title")}
nameDescription={t("masksAndZones.zones.name.tips")} nameDescription={t("masksAndZones.zones.name.tips")}
placeholderName={t("masksAndZones.zones.name.inputPlaceHolder")} placeholderName={t("masksAndZones.zones.name.inputPlaceHolder")}
idDisabled={idDisabled}
/> />
<FormField <FormField
control={form.control} control={form.control}