diff --git a/.gsd/milestones/M007/slices/S04/S04-PLAN.md b/.gsd/milestones/M007/slices/S04/S04-PLAN.md index 66a2da5..83b4b32 100644 --- a/.gsd/milestones/M007/slices/S04/S04-PLAN.md +++ b/.gsd/milestones/M007/slices/S04/S04-PLAN.md @@ -15,7 +15,7 @@ Steps: - Estimate: 45m - Files: frontend/src/api/public-client.ts, frontend/src/pages/AdminPipeline.tsx, frontend/src/App.css - Verify: ssh ub01 "cd /vmPool/r/repos/xpltdco/chrysopedia && docker compose build chrysopedia-web" succeeds with exit 0 -- [ ] **T02: Prune dead UI, rename view toggle, add debug indicator on trigger, add review queue cross-link** — Clean up the pipeline page: remove low-value UI elements, rename confusing labels, add debug mode context to trigger button, and add cross-navigation to review queue. +- [x] **T02: Pruned dead UI, renamed view toggle to Oldest/Newest first, added debug indicator on trigger button, added review queue cross-link on video cards** — Clean up the pipeline page: remove low-value UI elements, rename confusing labels, add debug mode context to trigger button, and add cross-navigation to review queue. Steps: 1. In EventLog component, rename 'Head'/'Tail' buttons to 'Oldest first'/'Newest first'. The buttons are in the `.pipeline-events__view-toggle` div. Just change the button text. diff --git a/.gsd/milestones/M007/slices/S04/tasks/T01-VERIFY.json b/.gsd/milestones/M007/slices/S04/tasks/T01-VERIFY.json new file mode 100644 index 0000000..96afb2a --- /dev/null +++ b/.gsd/milestones/M007/slices/S04/tasks/T01-VERIFY.json @@ -0,0 +1,24 @@ +{ + "schemaVersion": 1, + "taskId": "T01", + "unitId": "M007/S04/T01", + "timestamp": 1774899251289, + "passed": false, + "discoverySource": "task-plan", + "checks": [ + { + "command": "ssh ub01 \"cd /vmPool/r/repos/xpltdco/chrysopedia", + "exitCode": 2, + "durationMs": 5, + "verdict": "fail" + }, + { + "command": "docker compose build chrysopedia-web\" succeeds with exit 0", + "exitCode": 2, + "durationMs": 5, + "verdict": "fail" + } + ], + "retryAttempt": 1, + "maxRetries": 2 +} diff --git a/.gsd/milestones/M007/slices/S04/tasks/T02-SUMMARY.md b/.gsd/milestones/M007/slices/S04/tasks/T02-SUMMARY.md new file mode 100644 index 0000000..a1dbfc2 --- /dev/null +++ b/.gsd/milestones/M007/slices/S04/tasks/T02-SUMMARY.md @@ -0,0 +1,76 @@ +--- +id: T02 +parent: S04 +milestone: M007 +provides: [] +requires: [] +affects: [] +key_files: ["frontend/src/pages/AdminPipeline.tsx", "frontend/src/App.css"] +key_decisions: ["Lifted debug mode state from DebugModeToggle to AdminPipeline parent so trigger button can show debug indicator"] +patterns_established: [] +drill_down_paths: [] +observability_surfaces: [] +duration: "" +verification_result: "Docker build of chrysopedia-web succeeded with exit 0. TypeScript compiled cleanly, Vite bundled 48 modules, nginx image produced." +completed_at: 2026-03-30T19:36:31.974Z +blocker_discovered: false +--- + +# T02: Pruned dead UI, renamed view toggle to Oldest/Newest first, added debug indicator on trigger button, added review queue cross-link on video cards + +> Pruned dead UI, renamed view toggle to Oldest/Newest first, added debug indicator on trigger button, added review queue cross-link on video cards + +## What Happened +--- +id: T02 +parent: S04 +milestone: M007 +key_files: + - frontend/src/pages/AdminPipeline.tsx + - frontend/src/App.css +key_decisions: + - Lifted debug mode state from DebugModeToggle to AdminPipeline parent so trigger button can show debug indicator +duration: "" +verification_result: passed +completed_at: 2026-03-30T19:36:31.974Z +blocker_discovered: false +--- + +# T02: Pruned dead UI, renamed view toggle to Oldest/Newest first, added debug indicator on trigger button, added review queue cross-link on video cards + +**Pruned dead UI, renamed view toggle to Oldest/Newest first, added debug indicator on trigger button, added review queue cross-link on video cards** + +## What Happened + +Six changes to AdminPipeline.tsx: renamed Head/Tail view toggle to Oldest first/Newest first; removed duplicate event-level refresh button; removed truncated ID from expanded detail; lifted debugMode state to parent component so trigger button shows '▶ Trigger (debug)' when active; added '→ Moments' cross-link on each video card linking to /admin/review with accent-colored subtle styling. + +## Verification + +Docker build of chrysopedia-web succeeded with exit 0. TypeScript compiled cleanly, Vite bundled 48 modules, nginx image produced. + +## Verification Evidence + +| # | Command | Exit Code | Verdict | Duration | +|---|---------|-----------|---------|----------| +| 1 | `ssh ub01 "cd /vmPool/r/repos/xpltdco/chrysopedia && docker compose build chrysopedia-web"` | 0 | ✅ pass | 5500ms | + + +## Deviations + +None. + +## Known Issues + +Review queue cross-link goes to /admin/review without video-specific filtering since the review queue doesn't support URL-based video filtering yet. + +## Files Created/Modified + +- `frontend/src/pages/AdminPipeline.tsx` +- `frontend/src/App.css` + + +## Deviations +None. + +## Known Issues +Review queue cross-link goes to /admin/review without video-specific filtering since the review queue doesn't support URL-based video filtering yet. diff --git a/frontend/src/App.css b/frontend/src/App.css index c641cf9..ccd3f53 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -2776,6 +2776,20 @@ a.app-footer__repo:hover { white-space: nowrap; } +.pipeline-video__review-link { + color: var(--color-accent); + font-size: 0.75rem; + text-decoration: none; + white-space: nowrap; + opacity: 0.7; + transition: opacity 0.15s; +} + +.pipeline-video__review-link:hover { + opacity: 1; + text-decoration: underline; +} + .pipeline-video__actions { display: flex; gap: 0.375rem; diff --git a/frontend/src/pages/AdminPipeline.tsx b/frontend/src/pages/AdminPipeline.tsx index f8f9c73..6f10b80 100644 --- a/frontend/src/pages/AdminPipeline.tsx +++ b/frontend/src/pages/AdminPipeline.tsx @@ -245,16 +245,15 @@ function EventLog({ videoId }: { videoId: string }) { className={`pipeline-events__view-btn${viewMode === "head" ? " pipeline-events__view-btn--active" : ""}`} onClick={() => { setViewMode("head"); setOffset(0); }} > - Head + Oldest first -
@@ -368,28 +367,21 @@ function WorkerStatus() { // ── Debug Mode Toggle ──────────────────────────────────────────────────────── -function DebugModeToggle() { - const [debugMode, setDebugModeState] = useState(null); +function DebugModeToggle({ + debugMode, + onDebugModeChange, +}: { + debugMode: boolean | null; + onDebugModeChange: (mode: boolean) => void; +}) { const [debugLoading, setDebugLoading] = useState(false); - useEffect(() => { - let cancelled = false; - fetchDebugMode() - .then((res) => { - if (!cancelled) setDebugModeState(res.debug_mode); - }) - .catch(() => { - // silently fail — toggle stays hidden - }); - return () => { cancelled = true; }; - }, []); - async function handleToggle() { if (debugMode === null || debugLoading) return; setDebugLoading(true); try { const res = await setDebugMode(!debugMode); - setDebugModeState(res.debug_mode); + onDebugModeChange(res.debug_mode); } catch { // swallow — leave previous state } finally { @@ -463,6 +455,7 @@ export default function AdminPipeline() { const [actionLoading, setActionLoading] = useState(null); const [actionMessage, setActionMessage] = useState<{ id: string; text: string; ok: boolean } | null>(null); const [activeFilter, setActiveFilter] = useState(null); + const [debugMode, setDebugModeState] = useState(null); const load = useCallback(async () => { setLoading(true); @@ -481,6 +474,18 @@ export default function AdminPipeline() { void load(); }, [load]); + useEffect(() => { + let cancelled = false; + fetchDebugMode() + .then((res) => { + if (!cancelled) setDebugModeState(res.debug_mode); + }) + .catch(() => { + // silently fail — toggle stays hidden + }); + return () => { cancelled = true; }; + }, []); + const handleTrigger = async (videoId: string) => { setActionLoading(videoId); setActionMessage(null); @@ -538,7 +543,7 @@ export default function AdminPipeline() {

- +
e.stopPropagation()}> @@ -597,7 +610,7 @@ export default function AdminPipeline() { disabled={actionLoading === video.id} title="Retrigger pipeline" > - {actionLoading === video.id ? "…" : "▶ Trigger"} + {actionLoading === video.id ? "…" : debugMode ? "▶ Trigger (debug)" : "▶ Trigger"}