refactor(frontend): move ST4TS to its own /stats.html page (#1464 step 2)

Extracts the hive-wide turn-stats rollup out of the dashboard tab strip
into a standalone /stats.html page, reached from the H0M3 hub — same
minimal-chrome pattern as /flow.html and /logs.html. The dashboard tab
strip is now purely operational.

- new stats.{html,css,js}; stats.js holds the moved render JS and
  fetches /api/stats-hive on load + window change.
- migrate the window selector (#hive-stats-windows) from a bespoke
  data-w/.active toggle to the shared createTabStrip — now hash-routed
  (#1h / #24h / …) and deep-linkable, matching the per-agent /stats page.
- drop the ST4TS tab + pane from dashboard.html and the hive-stats render
  block + the stats->refreshHiveStats lazy-load from tabs.js.
- move the shared .hive-stats-table to common.css (the dashboard SYST3M >
  C0NT41N3R L04D table still uses it); the ST4TS-only window/chip/bar
  styles go to stats.css.
- add a Stats tile to the H0M3 hub (and drop the now-stale "stats" from
  the Dashboard tile desc); wire build.mjs + the nix/frontend.nix manifest.

Second slice of #1464 step 2; follows the /settings.html extraction.
This commit is contained in:
iris 2026-06-08 23:37:53 +02:00 committed by mara
commit 09cb705738
10 changed files with 367 additions and 302 deletions

View file

@ -52,7 +52,7 @@ mkdirSync(staticDir(''), { recursive: true });
// follow-up once asset sizes warrant it). esbuild writes each entry
// to `static/<name>.js` based on the entryPoint basename.
await build({
entryPoints: [src('tabs.js'), src('flow.js'), src('logs.js'), src('home.js'), src('settings.js')],
entryPoints: [src('tabs.js'), src('flow.js'), src('logs.js'), src('home.js'), src('settings.js'), src('stats.js')],
outdir: staticDir(''),
bundle: true,
format: 'esm',
@ -91,7 +91,7 @@ await build({
// so a swap replaces only it) + theme.css (the semantic derivation
// layer) + common.css (shared typography, badges, buttons, inbox, side
// panel) plus its own page-specific bundle.
for (const entry of ['colors.css', 'theme.css', 'common.css', 'dashboard.css', 'flow.css', 'logs.css', 'home.css', 'settings.css']) {
for (const entry of ['colors.css', 'theme.css', 'common.css', 'dashboard.css', 'flow.css', 'logs.css', 'home.css', 'settings.css', 'stats.css']) {
await build({
entryPoints: [src(entry)],
outfile: staticDir(entry),
@ -101,7 +101,7 @@ for (const entry of ['colors.css', 'theme.css', 'common.css', 'dashboard.css', '
});
}
for (const html of ['index.html', 'dashboard.html', 'flow.html', 'logs.html', 'settings.html']) {
for (const html of ['index.html', 'dashboard.html', 'flow.html', 'logs.html', 'settings.html', 'stats.html']) {
copyFileSync(src(html), dist(html));
}