From d3548dde105f764ed8b2659def06f53a262cde3c Mon Sep 17 00:00:00 2001 From: abccodes Date: Sat, 20 Jun 2026 17:55:25 -0700 Subject: [PATCH] [aidan] ux/missed-runs: add per-group select-all toggle and rename skip action --- .../app/pages/Workflows/MissedRunsCard.tsx | 38 +++++++++++++++++-- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/pages/Workflows/MissedRunsCard.tsx b/frontend/src/app/pages/Workflows/MissedRunsCard.tsx index 4860adec..dcce4b5d 100644 --- a/frontend/src/app/pages/Workflows/MissedRunsCard.tsx +++ b/frontend/src/app/pages/Workflows/MissedRunsCard.tsx @@ -92,6 +92,20 @@ const MissedRunsCard: React.FC = ({ }); }, []); + // A group header's checkbox flips every run under it: if any are checked, + // clear the lot; otherwise check the lot. + const toggleGroup = useCallback((runs: MissedRunItem[]) => { + setConfirming(false); + setUnchecked((prev) => { + const anyChecked = runs.some((r) => !prev.has(r.id)); + const next = new Set(prev); + for (const r of runs) { + if (anyChecked) next.add(r.id); else next.delete(r.id); + } + return next; + }); + }, []); + const runSelected = useCallback(() => { if (selectedIds.length === 0) return; if (selectedIds.length > CONFIRM_THRESHOLD && !confirming) { @@ -260,9 +274,24 @@ const MissedRunsCard: React.FC = ({ {/* Scrollable list grouped by workflow */} - {groups.map((g) => ( + {groups.map((g) => { + const checkedCount = g.runs.filter((r) => !unchecked.has(r.id)).length; + const allChecked = checkedCount === g.runs.length; + return ( - + toggleGroup(g.runs)} + sx={{ display: 'flex', alignItems: 'center', gap: 0.4, px: 0.75, py: 0.4, borderRadius: `${c.radius.sm}px`, cursor: 'pointer', '&:hover': { bgcolor: c.bg.elevated } }} + > + 0 && !allChecked} + onChange={() => toggleGroup(g.runs)} + onClick={(e) => e.stopPropagation()} + sx={{ p: 0.25, color: c.text.muted, '&.Mui-checked': { color: c.accent.primary }, '&.MuiCheckbox-indeterminate': { color: c.accent.primary } }} + /> {g.runs.length} {g.title} @@ -289,7 +318,8 @@ const MissedRunsCard: React.FC = ({ ))} - ))} + ); + })} {/* Footer actions */} @@ -306,7 +336,7 @@ const MissedRunsCard: React.FC = ({ onClick={confirming ? () => setConfirming(false) : closeAndDismissRest} sx={{ fontSize: '0.78rem', color: c.text.muted, cursor: 'pointer', px: 1, py: 0.5, '&:hover': { color: c.text.primary } }} > - {confirming ? 'Cancel' : 'Skip the rest'} + {confirming ? 'Cancel' : 'Skip all'}