From 1ced2409566d14e38ada317947a86900adf623ac Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Sun, 8 Dec 2024 12:27:12 -0600 Subject: [PATCH] rename vars and add validation --- web/src/components/settings/ZoneEditPane.tsx | 220 ++++++++++--------- web/src/types/canvas.ts | 8 +- 2 files changed, 120 insertions(+), 108 deletions(-) diff --git a/web/src/components/settings/ZoneEditPane.tsx b/web/src/components/settings/ZoneEditPane.tsx index abdc90e93..aee16ec60 100644 --- a/web/src/components/settings/ZoneEditPane.tsx +++ b/web/src/components/settings/ZoneEditPane.tsx @@ -82,7 +82,7 @@ export default function ZoneEditPane({ } }, [polygon, config]); - const [topWidth, bottomWidth, leftDepth, rightDepth] = useMemo(() => { + const [lineA, lineB, lineC, lineD] = useMemo(() => { const distances = polygon?.camera && polygon?.name && @@ -93,94 +93,107 @@ export default function ZoneEditPane({ : [0, 0, 0, 0]; }, [polygon, config]); - const formSchema = z.object({ - name: z - .string() - .min(2, { - message: "Zone name must be at least 2 characters.", - }) - .transform((val: string) => val.trim().replace(/\s+/g, "_")) - .refine( - (value: string) => { - return !cameras.map((cam) => cam.name).includes(value); - }, - { - message: "Zone name must not be the name of a camera.", - }, - ) - .refine( - (value: string) => { - const otherPolygonNames = - polygons - ?.filter((_, index) => index !== activePolygonIndex) - .map((polygon) => polygon.name) || []; + const formSchema = z + .object({ + name: z + .string() + .min(2, { + message: "Zone name must be at least 2 characters.", + }) + .transform((val: string) => val.trim().replace(/\s+/g, "_")) + .refine( + (value: string) => { + return !cameras.map((cam) => cam.name).includes(value); + }, + { + message: "Zone name must not be the name of a camera.", + }, + ) + .refine( + (value: string) => { + const otherPolygonNames = + polygons + ?.filter((_, index) => index !== activePolygonIndex) + .map((polygon) => polygon.name) || []; - return !otherPolygonNames.includes(value); - }, - { - message: "Zone name already exists on this camera.", - }, - ) - .refine( - (value: string) => { - return !value.includes("."); - }, - { - message: "Zone name must not contain a period.", - }, - ) - .refine((value: string) => /^[a-zA-Z0-9_-]+$/.test(value), { - message: "Zone name has an illegal character.", + return !otherPolygonNames.includes(value); + }, + { + message: "Zone name already exists on this camera.", + }, + ) + .refine( + (value: string) => { + return !value.includes("."); + }, + { + message: "Zone name must not contain a period.", + }, + ) + .refine((value: string) => /^[a-zA-Z0-9_-]+$/.test(value), { + message: "Zone name has an illegal character.", + }), + inertia: z.coerce + .number() + .min(1, { + message: "Inertia must be above 0.", + }) + .or(z.literal("")), + loitering_time: z.coerce + .number() + .min(0, { + message: "Loitering time must be greater than or equal to 0.", + }) + .optional() + .or(z.literal("")), + isFinished: z.boolean().refine(() => polygon?.isFinished === true, { + message: "The polygon drawing must be finished before saving.", }), - inertia: z.coerce - .number() - .min(1, { - message: "Inertia must be above 0.", - }) - .or(z.literal("")), - loitering_time: z.coerce - .number() - .min(0, { - message: "Loitering time must be greater than or equal to 0.", - }) - .optional() - .or(z.literal("")), - isFinished: z.boolean().refine(() => polygon?.isFinished === true, { - message: "The polygon drawing must be finished before saving.", - }), - objects: z.array(z.string()).optional(), - review_alerts: z.boolean().default(false).optional(), - review_detections: z.boolean().default(false).optional(), - speedEstimation: z.boolean().default(false), - topWidth: z.coerce - .number() - .min(0.1, { - message: "Distance must be greater than or equal to 0.1", - }) - .optional() - .or(z.literal("")), - bottomWidth: z.coerce - .number() - .min(0.1, { - message: "Distance must be greater than or equal to 0.1", - }) - .optional() - .or(z.literal("")), - leftDepth: z.coerce - .number() - .min(0.1, { - message: "Distance must be greater than or equal to 0.1", - }) - .optional() - .or(z.literal("")), - rightDepth: z.coerce - .number() - .min(0.1, { - message: "Distance must be greater than or equal to 0.1", - }) - .optional() - .or(z.literal("")), - }); + objects: z.array(z.string()).optional(), + review_alerts: z.boolean().default(false).optional(), + review_detections: z.boolean().default(false).optional(), + speedEstimation: z.boolean().default(false), + lineA: z.coerce + .number() + .min(0.1, { + message: "Distance must be greater than or equal to 0.1", + }) + .optional() + .or(z.literal("")), + lineB: z.coerce + .number() + .min(0.1, { + message: "Distance must be greater than or equal to 0.1", + }) + .optional() + .or(z.literal("")), + lineC: z.coerce + .number() + .min(0.1, { + message: "Distance must be greater than or equal to 0.1", + }) + .optional() + .or(z.literal("")), + lineD: z.coerce + .number() + .min(0.1, { + message: "Distance must be greater than or equal to 0.1", + }) + .optional() + .or(z.literal("")), + }) + .refine( + (data) => { + if (data.speedEstimation) { + return !!data.lineA && !!data.lineB && !!data.lineC && !!data.lineD; + } + return true; + }, + { + message: "All distance fields must be filled to use speed estimation.", + path: ["speedEstimation"], + }, + ); const form = useForm>({ resolver: zodResolver(formSchema), @@ -197,11 +210,11 @@ export default function ZoneEditPane({ config?.cameras[polygon.camera]?.zones[polygon.name]?.loitering_time, isFinished: polygon?.isFinished ?? false, objects: polygon?.objects ?? [], - speedEstimation: !!(topWidth || bottomWidth || leftDepth || rightDepth), - topWidth, - bottomWidth, - leftDepth, - rightDepth, + speedEstimation: !!(lineA || lineB || lineC || lineD), + lineA, + lineB, + lineC, + lineD, }, }); @@ -213,10 +226,10 @@ export default function ZoneEditPane({ loitering_time, objects: form_objects, speedEstimation, - topWidth, - bottomWidth, - leftDepth, - rightDepth, + lineA, + lineB, + lineC, + lineD, }: ZoneFormValuesType, // values submitted via the form objects: string[], ) => { @@ -314,9 +327,7 @@ export default function ZoneEditPane({ } let distancesQuery = ""; - const distances = [topWidth, bottomWidth, leftDepth, rightDepth].join( - ",", - ); + const distances = [lineA, lineB, lineC, lineD].join(","); if (speedEstimation) { distancesQuery = `&cameras.${polygon?.camera}.zones.${zoneName}.distances=${distances}`; } else { @@ -543,7 +554,7 @@ export default function ZoneEditPane({ polygons[activePolygonIndex].points.length !== 4 ) { toast.error( - "Zones with speed estimation must have exactly 4 points", + "Zones with speed estimation must have exactly 4 points.", ); return; } @@ -557,6 +568,7 @@ export default function ZoneEditPane({ Enable speed estimation for objects in this zone. The zone must have exactly 4 points. + )} /> @@ -568,7 +580,7 @@ export default function ZoneEditPane({ <> ( Line A distance @@ -584,7 +596,7 @@ export default function ZoneEditPane({ /> ( Line B distance @@ -600,7 +612,7 @@ export default function ZoneEditPane({ /> ( Line C distance @@ -616,7 +628,7 @@ export default function ZoneEditPane({ /> ( Line D distance diff --git a/web/src/types/canvas.ts b/web/src/types/canvas.ts index 045d5897d..d6d9f84f7 100644 --- a/web/src/types/canvas.ts +++ b/web/src/types/canvas.ts @@ -20,10 +20,10 @@ export type ZoneFormValuesType = { isFinished: boolean; objects: string[]; speedEstimation: boolean; - topWidth: number; - bottomWidth: number; - leftDepth: number; - rightDepth: number; + lineA: number; + lineB: number; + lineC: number; + lineD: number; }; export type ObjectMaskFormValuesType = {