extract build-queue rollup as a shared Preact component

New @hive/shared/jobq-rollup.js (JobqRollup.tsx + jobq-rollup.css),
mirroring JobqGraph's shape exactly: JSX use plus an imperative
mountJobqRollup(container, props) for a plain-.js call site. Fetches
Vec<hive_jobq_wire::StateCount> off `endpoint`, sums Running+Finishing
roots as "running" and Pending roots as "queued", renders nothing when
both are zero. Optional `queueHref` adds a "view queue -> " link.

Swapped dashboard's hand-rolled queue-summary banner (swarm.js) over to
this component instead of keeping two parallel implementations - same
"one shared component" pattern JobqGraph already set for the rebuild
queue tree view. Mounted once into a new #jobq-rollup-section, kept as
a sibling of (not inside) #containers-section since that section gets
replaceChildren()-wiped on every container-state render, which would
tear down and remount a Preact tree on every tick. Refreshed via the
mount handle's .refresh() on rebuild_queue_changed, same as builds.js's
JobqGraph handle.

Also mounted in swarm-ui's /jobs page, above JobqGraph, with no
queueHref (a link back to the page you're already on is noise) - the
literal ask on hyperhive#3364.

Verified: npm run build (whole workspace) and swarm-ui typecheck both
clean, comment-block + issue-ref lints run manually, headless-chromium
screenshots of both the dashboard SW4RM tab and swarm-ui's /jobs page
against mocked /api/jobq/rollup payloads - banner renders identically
in both, with and without the queue link as expected.
This commit is contained in:
iris 2026-08-16 21:21:12 +02:00 committed by mara
commit 1111577c91
10 changed files with 208 additions and 99 deletions

View file

@ -1,7 +1,9 @@
/* JobsPage wraps the shared JobqGraph component pointed at the
swarm-controller's own /api/jobq/graph endpoint (same wire shape
hive-c0re's dashboard consumes, see hive-jobq-wire's README). Styles
are @hive/shared's jobq-graph.css, @import'ed here rather than from
the component file itself see JobqGraph.tsx's own comment for why
that split exists (esbuild's loader map is global per bundle call). */
/* JobsPage wraps the shared JobqGraph + JobqRollup components pointed
at the swarm-controller's own /api/jobq/{graph,rollup} endpoints (same
wire shapes hive-c0re's dashboard consumes, see hive-jobq-wire's
README). Styles are @hive/shared's own CSS files, @import'ed here
rather than from the component files themselves see JobqGraph.tsx's
own comment for why that split exists (esbuild's loader map is global
per bundle call). */
@import "@hive/shared/jobq-graph.css";
@import "@hive/shared/jobq-rollup.css";

View file

@ -7,13 +7,19 @@
// SwarmNodeKind/SwarmResourceKind), so this renders an empty tree today
// — the page exists so the wiring is in place before the first real
// swarm-level job (e.g. CreateAgent) lands.
//
// JobqRollup sits above the graph, same "N running / M queued" banner
// the dashboard's SW4RM tab shows — no `queueHref`, since a "view
// queue →" link back to this same page would be noise.
import { JobqGraph } from '@hive/shared/jobq-graph.js';
import { JobqRollup } from '@hive/shared/jobq-rollup.js';
import { Panel } from '../ui/panel/Panel.js';
import './JobsPage.css';
export function JobsPage() {
return (
<Panel title="jobs">
<JobqRollup endpoint="/api/jobq/rollup" />
<JobqGraph endpoint="/api/jobq/graph" />
</Panel>
);