From 213e0a1b89da4e734c9aed0d6c8cebba4f1f9916 Mon Sep 17 00:00:00 2001 From: iris Date: Wed, 19 Aug 2026 19:28:31 +0200 Subject: [PATCH] swarm-ui: jobs page auto-refresh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reuses HivesPage's exact RefreshIntervalPicker/useRefreshInterval pattern (30s default, off/10s/30s/1m presets, pauses while the tab is backgrounded). Ticks a refreshToken bump rather than doing its own fetch — JobqGraph/JobqRollup already accept that prop as their documented refetch lever, from the dashboard's rebuild-queue view. --- .../packages/swarm-ui/src/pages/JobsPage.tsx | 41 +++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/frontend/packages/swarm-ui/src/pages/JobsPage.tsx b/frontend/packages/swarm-ui/src/pages/JobsPage.tsx index 932b425c..4d405b75 100644 --- a/frontend/packages/swarm-ui/src/pages/JobsPage.tsx +++ b/frontend/packages/swarm-ui/src/pages/JobsPage.tsx @@ -11,16 +11,51 @@ // 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. +// +// Auto-refresh reuses `HivesPage`'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 +// (bumping it is their documented "refetch now" lever) since the +// dashboard's own rebuild-queue view needed the same thing first. +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 { + RefreshIntervalPicker, + useRefreshInterval, + type RefreshIntervalMs, +} from '../ui/refresh-interval/RefreshInterval.js'; import './JobsPage.css'; +// Same 30s default + same reasoning as `HivesPage`: 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; + export function JobsPage() { + const [intervalMs, setIntervalMs] = useState(DEFAULT_INTERVAL_MS); + const [refreshToken, setRefreshToken] = useState(0); + + // `useRefreshInterval` ticks once immediately on mount (by design — + // see its own doc comment), which lands on top of `JobqGraph`'s / + // `JobqRollup`'s own unconditional mount-time fetch and costs one + // harmless duplicate request on page load. Not worth a special case + // in the shared hook for: the alternative (skip the first tick) would + // need every other `useRefreshInterval` caller to reason about + // whether it's the sole fetcher or not, for a one-page, one-time, + // zero-user-visible-effect cost here. + useRefreshInterval(intervalMs, () => setRefreshToken((t) => t + 1)); + return ( - - - + } + > + + ); }