From fe06838bf70ea59f5a7694ffdc45981797e60182 Mon Sep 17 00:00:00 2001 From: Anso Date: Wed, 6 May 2026 20:18:33 -0400 Subject: [PATCH] refactor(frontend): migrate FleetSnapshots dialogs to Modal chrome (#950) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two AlertDialog instances move onto §10 Modal primitives: - Snapshot delete confirm -> destructive ConfirmModal hoisted to a single parent-level instance driven by confirmDeleteId state. Each row's trash button now calls setConfirmDeleteId(snapshot.id) instead of wrapping its own AlertDialog - RestoreButton's per-restore confirm -> ConfirmModal with the redeploy checkbox in the body slot. Promise-aware onConfirm closes the dialog from finally --- frontend/src/components/FleetSnapshots.tsx | 153 ++++++++++----------- 1 file changed, 71 insertions(+), 82 deletions(-) diff --git a/frontend/src/components/FleetSnapshots.tsx b/frontend/src/components/FleetSnapshots.tsx index 92f1721d..1601b592 100644 --- a/frontend/src/components/FleetSnapshots.tsx +++ b/frontend/src/components/FleetSnapshots.tsx @@ -13,11 +13,7 @@ import { Badge } from '@/components/ui/badge'; import { Skeleton } from '@/components/ui/skeleton'; import { Checkbox } from '@/components/ui/checkbox'; import { Label } from '@/components/ui/label'; -import { - AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, - AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, - AlertDialogTrigger, -} from '@/components/ui/alert-dialog'; +import { ConfirmModal } from '@/components/ui/modal'; import { ScrollArea } from '@/components/ui/scroll-area'; import { apiFetch } from '@/lib/api'; import { useAuth } from '@/context/AuthContext'; @@ -84,6 +80,7 @@ export default function FleetSnapshots() { const [previewFiles, setPreviewFiles] = useState>(new Set()); const [restoringStack, setRestoringStack] = useState(null); const [deletingId, setDeletingId] = useState(null); + const [confirmDeleteId, setConfirmDeleteId] = useState(null); const [page, setPage] = useState(0); const [cloudSnapshotIds, setCloudSnapshotIds] = useState>(new Set()); const [uploadingId, setUploadingId] = useState(null); @@ -631,39 +628,19 @@ export default function FleetSnapshots() { )} {isAdmin && ( - - - - - - - Delete snapshot? - - This will permanently delete this fleet snapshot. This action cannot be undone. - - - - Cancel - handleDelete(snapshot.id)} - > - Delete - - - - + )} @@ -674,6 +651,26 @@ export default function FleetSnapshots() { )} + + { if (!open) setConfirmDeleteId(null); }} + variant="destructive" + kicker="SNAPSHOTS · DELETE · IRREVERSIBLE" + title="Delete snapshot" + confirmLabel="Delete" + onConfirm={async () => { + if (confirmDeleteId !== null) { + const id = confirmDeleteId; + setConfirmDeleteId(null); + await handleDelete(id); + } + }} + > +

+ Permanently removes this fleet snapshot. +

+
); } @@ -691,32 +688,40 @@ function RestoreButton({ nodeId, nodeName, stackName, restoring, onRestore }: { const [open, setOpen] = useState(false); return ( - - - - - - - - Restore {stackName} on {nodeName}? - - - This will overwrite the current compose files with the snapshot version. - - -
+ <> + + { + try { + await onRestore(nodeId, stackName, redeploy); + } finally { + setOpen(false); + } + }} + > +

+ Overwrites the current compose files with the snapshot version. +

+
- - Cancel - - - - +
+ ); }