From ae7524f507e2b7199a40c676f3e7891fa20056eb Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Mon, 2 Feb 2026 23:57:14 +0000 Subject: [PATCH] monitors details --- client/src/Hooks/useStatusPageForm.ts | 4 +- client/src/Pages/StatusPage/Create/index.tsx | 101 +++++++++++++------ client/src/Validation/statusPage.ts | 2 +- 3 files changed, 76 insertions(+), 31 deletions(-) diff --git a/client/src/Hooks/useStatusPageForm.ts b/client/src/Hooks/useStatusPageForm.ts index 0ea128e0d..69401138e 100644 --- a/client/src/Hooks/useStatusPageForm.ts +++ b/client/src/Hooks/useStatusPageForm.ts @@ -6,11 +6,13 @@ interface UseStatusPageFormOptions { data?: StatusPage | null; } +const generateDefaultUrl = () => Math.floor(Math.random() * 1000000).toString(); + export const useStatusPageForm = ({ data = null }: UseStatusPageFormOptions = {}) => { return useMemo(() => { const defaults: StatusPageFormData = { companyName: data?.companyName || "", - url: data?.url || "", + url: data?.url || generateDefaultUrl(), timezone: data?.timezone || Intl.DateTimeFormat().resolvedOptions().timeZone, color: data?.color || "#4169E1", monitors: data?.monitors || [], diff --git a/client/src/Pages/StatusPage/Create/index.tsx b/client/src/Pages/StatusPage/Create/index.tsx index 7e4e94a9d..ec5245e41 100644 --- a/client/src/Pages/StatusPage/Create/index.tsx +++ b/client/src/Pages/StatusPage/Create/index.tsx @@ -2,8 +2,9 @@ import { BasePage, ConfigBox } from "@/Components/v2/design-elements"; import Stack from "@mui/material/Stack"; import Typography from "@mui/material/Typography"; import IconButton from "@mui/material/IconButton"; -import Divider from "@mui/material/Divider"; -import { Trash2 } from "lucide-react"; +import { Trash2, GripVertical } from "lucide-react"; +import { DragDropContext, Droppable, Draggable } from "@hello-pangea/dnd"; +import type { DropResult } from "@hello-pangea/dnd"; import { ImageUpload, SwitchComponent, @@ -135,8 +136,11 @@ const CreateStatusPage = () => { { - const selectedMonitors = monitors.filter((m) => field.value.includes(m.id)); + render={({ field, fieldState }) => { + // Preserve order from field.value (IDs) when building selectedMonitors + const selectedMonitors = field.value + .map((id: string) => monitors.find((m) => m.id === id)) + .filter((m): m is Monitor => m !== undefined); return ( { placeholder={t( "pages.statusPages.form.monitors.option.monitors.placeholder" )} + error={!!fieldState.error} + helperText={fieldState.error?.message ?? ""} /> )} /> {selectedMonitors.length > 0 && ( - { + if (!result.destination) return; + const reordered = Array.from(field.value); + const [removed] = reordered.splice(result.source.index, 1); + reordered.splice(result.destination.index, 0, removed); + field.onChange(reordered); + }} > - {selectedMonitors.map((monitor, index) => ( - - {monitor.name} - { - field.onChange( - field.value.filter((id: string) => id !== monitor.id) - ); - }} - aria-label="Remove monitor" + + {(provided) => ( + - - - {index < selectedMonitors.length - 1 && } - - ))} - + {selectedMonitors.map((monitor, index) => ( + + {(provided) => ( + + + {monitor.name} + { + field.onChange( + field.value.filter( + (id: string) => id !== monitor.id + ) + ); + }} + aria-label="Remove monitor" + > + + + + )} + + ))} + {provided.placeholder} + + )} + + )} ); diff --git a/client/src/Validation/statusPage.ts b/client/src/Validation/statusPage.ts index cb148e633..fbe6a0690 100644 --- a/client/src/Validation/statusPage.ts +++ b/client/src/Validation/statusPage.ts @@ -15,7 +15,7 @@ export const statusPageSchema = z.object({ ), timezone: z.string().optional(), color: z.string().min(1, "Color is required"), - monitors: z.array(z.string()), + monitors: z.array(z.string()).min(1, "At least one monitor is required"), isPublished: z.boolean(), showCharts: z.boolean(), showUptimePercentage: z.boolean(),