From 1b7999918cf5e2f8ba965df92bfd7d1ba3d9d92e Mon Sep 17 00:00:00 2001 From: Claude Code Date: Sun, 29 Mar 2026 05:29:52 -0700 Subject: [PATCH] =?UTF-8?q?feat(gui):=20=E2=9C=A8=20Add=20dashboard=20page?= =?UTF-8?q?=20to=20visualize=20sprite=20registry=20data=20from=20SQLite=20?= =?UTF-8?q?database?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- tools/sprite-generation/engine/registry.py | 2 +- .../gui/src/pages/DashboardPage.tsx | 47 ++++++++++++------ tools/sprite-generation/spritegen.db-shm | Bin 32768 -> 32768 bytes tools/sprite-generation/spritegen.db-wal | Bin 9092872 -> 9092872 bytes 4 files changed, 34 insertions(+), 15 deletions(-) diff --git a/tools/sprite-generation/engine/registry.py b/tools/sprite-generation/engine/registry.py index acee8215..ee90de5b 100644 --- a/tools/sprite-generation/engine/registry.py +++ b/tools/sprite-generation/engine/registry.py @@ -890,7 +890,7 @@ class SpriteRegistry: scoring[name] = { "scored": scored, "passed": passed, - "pass_rate": round(passed / scored * 100, 1) if scored else 0.0, + "pass_rate": round(passed / scored, 4) if scored else 0.0, "avg_confidence": round(row["avg_conf"] or 0.0, 3), } diff --git a/tools/sprite-generation/gui/src/pages/DashboardPage.tsx b/tools/sprite-generation/gui/src/pages/DashboardPage.tsx index 0892821e..2b5826c5 100644 --- a/tools/sprite-generation/gui/src/pages/DashboardPage.tsx +++ b/tools/sprite-generation/gui/src/pages/DashboardPage.tsx @@ -476,6 +476,38 @@ export function DashboardPage(): ReactNode { }) }, []) + // Restore running state on mount by checking if server has an active pipeline process + const startStatusPoll = useCallback((): (() => void) => { + const poll = setInterval((): void => { + fetchPipelineStatus() + .then((st) => { + if (!st.running) { + clearInterval(poll) + setRunning(false) + load() + } + }) + .catch(() => { + clearInterval(poll) + setRunning(false) + }) + }, 3000) + return (): void => clearInterval(poll) + }, [load]) + + useEffect((): (() => void) => { + let cancel: (() => void) | null = null + fetchPipelineStatus() + .then((st) => { + if (st.running) { + setRunning(true) + cancel = startStatusPoll() + } + }) + .catch(() => { /* server not yet reachable */ }) + return (): void => { cancel?.() } + }, [startStatusPoll]) + useEffect((): (() => void) => { load() const interval = setInterval(load, 5000) @@ -502,20 +534,7 @@ export function DashboardPage(): ReactNode { setRunning(false) return } - const poll = setInterval((): void => { - fetchPipelineStatus() - .then((st) => { - if (!st.running) { - clearInterval(poll) - setRunning(false) - load() - } - }) - .catch(() => { - clearInterval(poll) - setRunning(false) - }) - }, 3000) + startStatusPoll() } catch (e: unknown) { alert(`Pipeline run failed: ${e instanceof Error ? e.message : String(e)}`) setRunning(false) diff --git a/tools/sprite-generation/spritegen.db-shm b/tools/sprite-generation/spritegen.db-shm index e7186dc00efc8c82de1de33305c22e7c9fc6c2f1..89af6565b234bc19a19caa50d452be0ee80d494a 100644 GIT binary patch delta 263 zcmZo@U}|V!s+V}A%K!q8mNPIgGB5}%XJTNuEYHB8Yd6cNX=~(XL8mgUf@rn)=sZ)rlxT1;E(J2xH^HcA delta 210 zcmZo@U}|V!s+V}A%K!p5moqRhGB60tV`5;qEYH9o;hI*YeeZXmpi`MvL9|-D#gh2v z2BsV1NL3Fu97ur7{f`8o;v4H5xi+hCbD2(d;8xkJ=g`15nZ;FQ^Ch=cl0Xrc%?A>8 suukT2mD)ThEroq@QG^~)RBW?V-Zqe^%x0bv4UWlX+!~u>YL+kq0FgCBaR2}S diff --git a/tools/sprite-generation/spritegen.db-wal b/tools/sprite-generation/spritegen.db-wal index f5638cd18f7ffa229f8bb15c3ac9fc833a0e6d97..964b84ffefdcd865935c50e50d3502b288639dc2 100644 GIT binary patch delta 2398 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