Watch
0
0
Fork
You've already forked hyperhive
0
hyperhive/frontend/packages/dashboard/src/builds.js
iris deeb5ecd86 hive ui: remove the BUILD L0GS tab and the live build-log panel
A build's output and history are the swarm's builds Grafana board now, from the
lines hive-c0re logs. Removes the tab and its pane, the live log under the
rebuild queue, their styles, the log stream helper and the duration formatter
only they used, and the docs; also the tab-counts sentence 5925 missed.
2026-11-01 17:19:26 +01:00

100 lines
4.3 KiB
JavaScript

// The rebuild queue tab of the dashboard (R3BU1LD QU3U3): pending and running
// rebuilds as a `JobqGraph`. Not an entry point: tabs.js imports it, owns the
// tab strip and the dashboard event stream, and calls the exports below. The
// builds' output and history are not here: they are the `builds` Grafana board,
// from the lines hive-c0re logs for each build.
import { $ } from "./common.js";
import { themedConfirm } from "@hive/shared/modal.js";
import { h, render } from "preact";
import { JobqGraph } from "@hive/shared/jobq-graph.js";
// Kept in sync from JobqGraph's `onUpdate` callback (see renderRebuildQueue
// below) — the component owns fetching GET /api/jobq/graph and renders the tree
// itself; this flat array is only for `onCancel`, which names the node it
// cancels in its confirm.
let jobqNodes = [];
let jobqGraphToken = 0;
// ─── rebuild queue ────────────────────────────────────────────────────────────
// R3BU1LD QU3U3 is `JobqGraph` (Preact, rendered via plain `render(h(...))`
// — no JSX pragma needed for either call, no mount wrapper: `render` is
// already the re-render/diff entry point, per mara on review) directly —
// no hand-rolled tree/roll-up rendering here anymore. The component owns
// fetching GET /api/jobq/graph and its own refetch (bump `jobqGraphToken`
// and render again); this page just reads its `onUpdate` callback to keep
// `jobqNodes` (the flat array) in sync for `onCancel` below.
//
// Cancel is the one action this page *does* wire up: the `cancellable`
// prop turns on the component's own per-node cancel button, which calls
// `onCancel(id)` rather than posting anything — the endpoint
// (`/api/rebuild-queue/{id}/cancel`) is this page's domain concept, not
// the generic component's.
// Split from `renderRebuildQueue` below: `replaceChildren()` only
// belongs on the *first* render, to clear the static "loading…"
// placeholder `#rebuild-queue-section` starts with in `index.html` —
// Preact doesn't know that placeholder is there, so a later render
// call must NOT repeat `replaceChildren()` (it would wipe Preact's own
// tracked children out from under its diffing rather than let it
// update them minimally).
function mountRebuildQueue() {
const root = $("rebuild-queue-section");
if (!root) return;
root.replaceChildren();
renderRebuildQueue();
}
function renderRebuildQueue() {
const root = $("rebuild-queue-section");
if (!root) return;
render(
h(JobqGraph, {
endpoint: "/api/jobq/graph",
cancellable: true,
refreshToken: jobqGraphToken,
onUpdate: (nodes) => {
jobqNodes = nodes || [];
},
onCancel: async (id) => {
const node = jobqNodes.find((n) => n.id === id);
const label = node ? node.payload.label : "node " + id;
if (
!(await themedConfirm({
message: `cancel ${label}? a group root cancels the whole subtree; a mid-tree node cancels just that branch.`,
danger: true,
confirmLabel: "✕ cancel",
}))
)
return;
try {
const r = await fetch("/api/rebuild-queue/" + id + "/cancel", {
method: "POST",
});
if (!r.ok) throw new Error("http " + r.status);
// No manual refresh: cancel flips node state, which fires
// rebuild_queue_changed over SSE — the existing handler below
// already bumps jobqGraphToken and re-renders on that tick.
} catch (err) {
console.error("cancel failed", err);
}
},
}),
root,
);
}
// ─── entry points for tabs.js ─────────────────────────────────────────────────
// Everything below is called by tabs.js, which owns the tab strip, the
// `/api/state` snapshot and the dashboard event stream.
/** Mount the rebuild queue. Called once, after the tab strip exists. The queue
* self-fetches on mount (JobqGraph's own effect). */
export function initBuilds() {
mountRebuildQueue();
}
/** `rebuild_queue_changed`: a payload-less refetch trigger — `JobqGraph`
* owns the actual fetch. */
export function onRebuildQueueChanged() {
jobqGraphToken += 1;
renderRebuildQueue();
}