From 9ab7819b244dc3fd784e49eb185c79324811e970 Mon Sep 17 00:00:00 2001 From: Anso Date: Wed, 6 May 2026 20:19:07 -0400 Subject: [PATCH] refactor(frontend): migrate Stack/Fleet confirms and Git source dialog (#951) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor(frontend): migrate Stack/Fleet confirms and Git source dialog - LocalUpdateConfirmDialog -> ConfirmModal with kicker LOCAL · UPDATE - GitSourcePanel form -> Modal with kicker {STACK} · GIT SOURCE; the custom three-button footer (Remove / Pull now / Save) stays as-is since ModalFooter's two-slot pattern doesn't fit a left-aligned destructive action; ModalHeader provides the canonical chrome - GitSourcePanel remove confirm -> destructive ConfirmModal with kicker {STACK} · GIT · DISCONNECT * test(e2e): scope git-source dialog assertion to the heading The migration adds a kicker rune " · GIT SOURCE" inside the dialog. The previous locator getByText('Git Source', { exact: false }) matched both the kicker (uppercase, mono) and the italic-serif title, producing a strict-mode violation. Use getByRole('heading') to target the title specifically. --- e2e/git-sources.spec.ts | 4 +- .../FleetView/LocalUpdateConfirmDialog.tsx | 40 +++++------ .../src/components/stack/GitSourcePanel.tsx | 68 ++++++++----------- 3 files changed, 48 insertions(+), 64 deletions(-) diff --git a/e2e/git-sources.spec.ts b/e2e/git-sources.spec.ts index cf26d2fd..fe3c1611 100644 --- a/e2e/git-sources.spec.ts +++ b/e2e/git-sources.spec.ts @@ -36,7 +36,9 @@ async function openGitSourcePanel(page: Page) { const gitBtn = page.getByRole('button', { name: /Git Source/i }); await expect(gitBtn).toBeVisible({ timeout: 10_000 }); await gitBtn.click(); - await expect(page.getByRole('dialog').getByText('Git Source', { exact: false })).toBeVisible({ timeout: 5_000 }); + // Match the title heading specifically; the modal also has a mono kicker + // (" · GIT SOURCE") that would satisfy a plain getByText match. + await expect(page.getByRole('dialog').getByRole('heading', { name: /git source/i })).toBeVisible({ timeout: 5_000 }); } test.describe('Git Sources', () => { diff --git a/frontend/src/components/FleetView/LocalUpdateConfirmDialog.tsx b/frontend/src/components/FleetView/LocalUpdateConfirmDialog.tsx index e4f91245..6c43499d 100644 --- a/frontend/src/components/FleetView/LocalUpdateConfirmDialog.tsx +++ b/frontend/src/components/FleetView/LocalUpdateConfirmDialog.tsx @@ -1,8 +1,5 @@ import { Download } from 'lucide-react'; -import { - AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, - AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, -} from '@/components/ui/alert-dialog'; +import { ConfirmModal } from '@/components/ui/modal'; interface LocalUpdateConfirmDialogProps { open: boolean; @@ -12,23 +9,22 @@ interface LocalUpdateConfirmDialogProps { export function LocalUpdateConfirmDialog({ open, onOpenChange, onConfirm }: LocalUpdateConfirmDialogProps) { return ( - - - - Update local node? - - This will pull the latest Sencho image and restart the server. The dashboard will be - briefly disconnected and will automatically reconnect when the update completes. - - - - Cancel - - - Update & Restart - - - - + + + Update & restart + + } + onConfirm={onConfirm} + > +

+ Pulls the latest Sencho image and restarts the server. The dashboard briefly disconnects and reconnects automatically when the update completes. +

+
); } diff --git a/frontend/src/components/stack/GitSourcePanel.tsx b/frontend/src/components/stack/GitSourcePanel.tsx index 7ed52bf0..5b037c6e 100644 --- a/frontend/src/components/stack/GitSourcePanel.tsx +++ b/frontend/src/components/stack/GitSourcePanel.tsx @@ -1,16 +1,6 @@ import { useState, useEffect, useCallback } from 'react'; import { GitBranch, Loader2, Trash2, RefreshCw, Save, AlertCircle } from 'lucide-react'; -import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog'; -import { - AlertDialog, - AlertDialogAction, - AlertDialogCancel, - AlertDialogContent, - AlertDialogDescription, - AlertDialogFooter, - AlertDialogHeader, - AlertDialogTitle, -} from '@/components/ui/alert-dialog'; +import { Modal, ModalHeader, ConfirmModal } from '@/components/ui/modal'; import { Button } from '@/components/ui/button'; import { Skeleton } from '@/components/ui/skeleton'; import { ScrollArea } from '@/components/ui/scroll-area'; @@ -290,18 +280,17 @@ export function GitSourcePanel({ return ( <> - - - - - - Git Source - {stackName} - - - Link this stack to a Git repository so compose updates can be pulled on demand or via webhook. - - + + + + Git source + + } + description="Link this stack to a Git repository so compose updates can be pulled on demand or via webhook." + />
@@ -416,8 +405,7 @@ export function GitSourcePanel({ )}
-
-
+ - - - - Remove Git source? - - The stack files on disk will be left in place. You can reconfigure the source later at any time. - - - - Cancel - - Remove - - - - + +

+ Disconnects the stack from its Git source. The stack files on disk are left in place and you can reconfigure the source later at any time. +

+
); }