Watch
0
0
Fork
You've already forked hyperhive
0

swarm-ui: repoint the HivesPage comments at HivesCard and pin the nav filter and lazy roster

This commit is contained in:
iris 2026-10-26 16:51:14 +01:00 • committed by mara
commit 209a286d7c
7 changed files with 63 additions and 18 deletions

View file

@ -1,7 +1,7 @@
// <AlertsPage> — `/alerts`' content: the alerts the swarm's Grafana holds
// now, from swarm-controller's `GET /api/alerts`. Only the firing ones show at
// first; a button in the header adds the pending, no-data and errored ones.
// Same shape as `HivesPage`: one fetch on a `RefreshIntervalPicker` cadence,
// Same shape as `HivesCard`: one fetch on a `RefreshIntervalPicker` cadence,
// rendered as a `Table`.
import { useState } from "preact/hooks";
import { ApiErrorPanel } from "@hive/shared/api-error-panel.js";

View file

@ -80,7 +80,7 @@ const TABLE_COLUMNS: TableColumn<Row>[] = [
render: (r) => r.detail,
// One filterable column, multiselect mode — the checkbox-list popover
// + reset-filters button are both real `Table` behavior an operator
// hits daily (`AgentsPage`/`HivesPage`), so the demo shows them rather
// hits daily (`AgentsPage`/`HivesCard`), so the demo shows them rather
// than a plain unfilterable grid.
filterValues: (r) => [r.detail],
filterMode: "multiselect",
@ -408,7 +408,7 @@ export function ComponentsPage() {
panel body content
</Panel>
</Sample>
<Sample label="with actions (e.g. HivesPage's refresh picker)">
<Sample label="with actions (e.g. HivesCard's refresh picker)">
<Panel
title="example title"
actions={

View file

@ -71,7 +71,7 @@ import {
} from "./CreateAgentSteps.js";
import "./CreateAgentForm.css";
// Mirrors swarm-controller's `HiveEntry` — same shape `HivesPage`
// Mirrors swarm-controller's `HiveEntry` — same shape `HivesCard`
// consumes off `/api/hives/status`, but this page hits the plain
// `/api/hives` roster (no status/freshness needed, just "what hives
// exist to spawn into").

View file

@ -12,7 +12,7 @@
// the dashboard's 4G3NTS tab shows — no `queueHref`, since a "view
// queue →" link back to this same page would be noise.
//
// Auto-refresh reuses `HivesPage`'s exact pattern (`RefreshIntervalPicker`
// Auto-refresh reuses `HivesCard`'s exact pattern (`RefreshIntervalPicker`
// in the `Panel`'s `actions` slot, `useRefreshInterval` driving the
// re-fetch), but ticks a `refreshToken` bump instead of doing its own
// fetch — both `JobqGraph`/`JobqRollup` already accept that prop
@ -29,7 +29,7 @@ import {
} from "../ui/refresh-interval/RefreshInterval.js";
import "./JobsPage.css";
// Same 30s default + same reasoning as `HivesPage`: no inputs on this
// Same 30s default + same reasoning as `HivesCard`: no inputs on this
// page for a refresh to clobber, so the out-of-the-box behaviour should
// just solve staleness rather than require an opt-in every visit.
const DEFAULT_INTERVAL_MS: RefreshIntervalMs = 30_000;

View file

@ -4,7 +4,7 @@
// status panel has anything to render against without a roster to embed
// in — so all three ended up as one page.
//
// One fetch, on a refresh-interval cadence like HivesPage: `GET
// One fetch, on a refresh-interval cadence like HivesCard: `GET
// /api/agents/status` — one row per roster agent (identity store is the
// roster, so a never-reported agent still gets a row), each already
// carrying its freshness/snapshot/config PR/wanted state. Used to be
@ -51,7 +51,7 @@ import { CreateAgentForm } from "../CreateAgentForm.js";
import { WantedMenu } from "../../agent/roster/WantedMenu.js";
import "./AgentsPage.css";
// Same 30s default + same reasoning as HivesPage: no inputs on this page
// Same 30s default + same reasoning as HivesCard: no inputs on this page
// for a refresh to clobber, so the out-of-the-box behaviour should just
// solve staleness rather than require an opt-in every visit.
const DEFAULT_INTERVAL_MS: RefreshIntervalMs = 30_000;

View file

@ -25,6 +25,7 @@ import {
import { fetchJson, usePolled } from "../../ui/polled/usePolled.js";
import { Table, type TableColumn } from "../../ui/table/Table.js";
import { domainCell } from "../hive-domain.js";
import { builtAfterToggle } from "./lazy-open.js";
type Freshness = "fresh" | "stale" | "never_reported" | "unknown";
@ -160,7 +161,7 @@ export function HivesCard() {
open={open}
onToggle={(next) => {
setOpen(next);
if (next) setBuilt(true);
setBuilt((was) => builtAfterToggle(was, next));
}}
>
{built ? <HiveRoster /> : null}

View file

@ -0,0 +1,5 @@
// A folded card builds its body on the first open and keeps it after, so a
// card nobody opens never fetches, and closing it does not drop what it read.
export function builtAfterToggle(built: boolean, open: boolean): boolean {
return built || open;
}