Watch
0
0
Fork
You've already forked hyperhive
0

swarm-ui: builds are a card under the job graph on the jobs tab

The builds tab is gone from the nav; its card sits below the jobs card on
/jobs. The swarm-builder commit status now links to /jobs?run=<id>, and the old
/builds address redirects there with its query so links already on PRs still
open the build. Docs and the link test follow.
This commit is contained in:
iris 2026-10-26 20:02:57 +01:00
commit a2f000bab4
4 changed files with 64 additions and 21 deletions

View file

@ -7,3 +7,10 @@
per bundle call). */
@import "@hive/shared/jobq-graph.css";
@import "@hive/shared/jobq-rollup.css";
/* The jobs tab: the job graph's card, then the builds card, one gap apart. */
.ui-jobs-page {
display: flex;
flex-direction: column;
gap: 1em;
}

View file

@ -22,6 +22,7 @@ import { useState } from "preact/hooks";
import { JobqGraph } from "@hive/shared/jobq-graph.js";
import { JobqRollup } from "@hive/shared/jobq-rollup.js";
import { Panel } from "../ui/panel/Panel.js";
import { BuildsCard } from "./builds/BuildsPage.js";
import {
RefreshIntervalPicker,
useRefreshInterval,
@ -34,7 +35,7 @@ import "./JobsPage.css";
// just solve staleness rather than require an opt-in every visit.
const DEFAULT_INTERVAL_MS: RefreshIntervalMs = 30_000;
export function JobsPage() {
function JobsCard() {
const [intervalMs, setIntervalMs] =
useState<RefreshIntervalMs>(DEFAULT_INTERVAL_MS);
const [refreshToken, setRefreshToken] = useState(0);
@ -66,3 +67,14 @@ export function JobsPage() {
</Panel>
);
}
// The jobs tab holds two cards: the controller's job graph, and the swarm
// builder's recent builds under it.
export function JobsPage() {
return (
<div class="ui-jobs-page">
<JobsCard />
<BuildsCard />
</div>
);
}

View file

@ -1,8 +1,10 @@
// <BuildsPage> — the swarm builder's recent builds, newest first: which agent
// <BuildsCard> — the swarm builder's recent builds, newest first: which agent
// config PR heads it built, how each ended, and what `nix` printed when one
// failed. One card per build; selecting a card opens it. Reads
// `GET /api/builder/runs`. A `swarm-builder` commit status links here as
// `/builds?run=<id>`, which opens that build's card and scrolls to it.
// `GET /api/builder/runs`. A `swarm-builder` commit status links to the jobs
// page as `/jobs?run=<id>`, which opens that build's card and scrolls to it.
// The card sits under the job graph on that page; the old `/builds` address
// redirects there with its query.
import { useEffect, useRef, useState } from "preact/hooks";
import { useSearch } from "wouter-preact";
import { ApiErrorPanel } from "@hive/shared/api-error-panel.js";
@ -91,7 +93,7 @@ function BuildCard({
);
}
export function BuildsPage() {
export function BuildsCard() {
const wanted = wantedRun(useSearch());
const [intervalMs, setIntervalMs] =
useState<RefreshIntervalMs>(DEFAULT_INTERVAL_MS);

View file

@ -37,6 +37,11 @@ export const OUTCOME_TONE: Record<BuildOutcome, BadgeTone> = {
error: "warning",
};
/** Where an old `/builds` link goes: the jobs page, keeping its query. */
export function jobsHref(search: string): string {
return search === "" ? "/jobs" : `/jobs?${search}`;
}
/** The run a `?run=<id>` query names, or `null` when it names none. */
export function wantedRun(search: string): string | null {
const id = new URLSearchParams(search).get("run");