The Monitors tab is called Dashboard again

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Mitchell-Johnson
2026-09-20 18:29:09 -07:00
co-authored by Claude Opus 5
parent 1e992ca1eb
commit 885b050d02
4 changed files with 9 additions and 8 deletions
+4 -3
View File
@@ -166,7 +166,7 @@ something long in one, switch away and back, refresh — it's all still there.
CPU (total + per core), memory/swap, load, uptime, hwmon temps and fans read straight CPU (total + per core), memory/swap, load, uptime, hwmon temps and fans read straight
from `/sys` (no lm-sensors), per-interface network rates, per-disk read/write/busy from `/sys` (no lm-sensors), per-interface network rates, per-disk read/write/busy
from `/proc/diskstats`, filesystem usage, UPS via `sudo -n pwrstat -status`. Sampled from `/proc/diskstats`, filesystem usage, UPS via `sudo -n pwrstat -status`. Sampled
every 2 s into an in-memory ring of 10 min; the UI (the **Monitors** tab every 2 s into an in-memory ring of 10 min; the UI (the **Dashboard** tab
since 2026-09-19) reads it all through the sensor API — see Sensors below. **Customizable**: a since 2026-09-19) reads it all through the sensor API — see Sensors below. **Customizable**: a
Customize mode reorders and hides modules (CPU, Memory, Load, Uptime, Temperatures, Customize mode reorders and hides modules (CPU, Memory, Load, Uptime, Temperatures,
Fans, Network, Disks, Filesystems, UPS) and hides individual rows (an interface, a Fans, Network, Disks, Filesystems, UPS) and hides individual rows (an interface, a
@@ -184,8 +184,9 @@ something long in one, switch away and back, refresh — it's all still there.
machine and a static schema would collapse to `sensor(id:)`), the same query as a live machine and a static schema would collapse to `sensor(id:)`), the same query as a live
SSE stream, Prometheus `/metrics`, read-only `sensors:read` tokens (never full tokens in SSE stream, Prometheus `/metrics`, read-only `sensors:read` tokens (never full tokens in
a URL), status sensors (services, updates, ZFS, SMART), a widget library, custom widgets a URL), status sensors (services, updates, ZFS, SMART), a widget library, custom widgets
on the Monitors tab (was "Dashboard"; the view id and URL are still `dashboard`), and a on the Dashboard tab (briefly renamed "Monitors" 2026-09-19, back to "Dashboard"
frameable `/embed/widget` for Glance and friends. The stock Monitors modules and the Disks 2026-09-20 at Mitchell's request; the view id and URL were always `dashboard`), and a
frameable `/embed/widget` for Glance and friends. The stock Dashboard modules and the Disks
tab read the sensor API too (`sampleAdapter.ts`); `/api/metrics` is retired. tab read the sensor API too (`sampleAdapter.ts`); `/api/metrics` is retired.
Also per-service and per-container sensors (memory and CPU from cgroups), tokens limited Also per-service and per-container sensors (memory and CPU from cgroups), tokens limited
to ID patterns, and `/api/fleet/sensors/query` for the whole fleet in one request. to ID patterns, and `/api/fleet/sensors/query` for the whole fleet in one request.
+2 -2
View File
@@ -151,7 +151,7 @@ A widget is a spec — `{type, sensor, title?}` — over this API and nothing el
`gauge`, `bar`, `spark`, and `list` for a pattern. Scale and colour come from the `gauge`, `bar`, `spark`, and `list` for a pattern. Scale and colour come from the
sensor's own `min`/`max`/`warn`/`crit`. sensor's own `min`/`max`/`warn`/`crit`.
- **In Ham Lab:** Monitors → Customize → **+ Add widget**. Saved with the layout, - **In Ham Lab:** Dashboard → Customize → **+ Add widget**. Saved with the layout,
per machine; all of a page's widgets share one stream. per machine; all of a page's widgets share one stream.
- **Widgets tab:** every widget type, then every sensor on the machine drawn once, live, - **Widgets tab:** every widget type, then every sensor on the machine drawn once, live,
grouped by family (`web/src/Gallery.tsx`). Tap a tile to copy its sensor ID — the grouped by family (`web/src/Gallery.tsx`). Tap a tile to copy its sensor ID — the
@@ -199,7 +199,7 @@ GET /api/fleet/sensors/query?machines=grid,wyse&cpu=cpu.usage&failed=services.f
## What Ham Lab itself runs on ## What Ham Lab itself runs on
Since 2026-09-19 the Monitors tab (stock modules and custom widgets) and the Disks tab's Since 2026-09-19 the Dashboard tab (stock modules and custom widgets) and the Disks tab's
live rates read only this API: the catalog once, one batch of histories, one stream — live rates read only this API: the catalog once, one batch of histories, one stream —
closed while the page is hidden, refilled when it returns. `web/src/sampleAdapter.ts` is closed while the page is hidden, refilled when it returns. `web/src/sampleAdapter.ts` is
the seam that hands the stock modules the object they were written against. The old the seam that hands the stock modules the object they were written against. The old
+2 -2
View File
@@ -49,7 +49,7 @@ const BellIcon = (
) )
const GROUPS: Group[] = [ const GROUPS: Group[] = [
{ id: 'dashboard', label: 'Monitors', icon: '◔' }, { id: 'dashboard', label: 'Dashboard', icon: '◔' },
{ id: 'procs', label: 'Processes', icon: '≡' }, { id: 'procs', label: 'Processes', icon: '≡' },
{ id: 'terminal', label: 'Terminal', icon: '>_' }, { id: 'terminal', label: 'Terminal', icon: '>_' },
{ id: 'services', label: 'Services', icon: '◈' }, { id: 'services', label: 'Services', icon: '◈' },
@@ -283,7 +283,7 @@ export default function Shell({ me: hubMe, onLoggedOut }: { me: Me; onLoggedOut:
<span>{machine ? `${machine} · ` : ''}{me.version.startsWith('v') ? me.version : 'v' + me.version}</span> <span>{machine ? `${machine} · ` : ''}{me.version.startsWith('v') ? me.version : 'v' + me.version}</span>
<span>up {fmtUptime(me.uptime)}</span> <span>up {fmtUptime(me.uptime)}</span>
<span className="spacer" /> <span className="spacer" />
<span className="muted">{view === 'dashboard' ? 'Monitors' : view === 'widgets' ? 'Widgets' : view === 'docker' ? 'Docker' : view === 'alerts' ? 'Alerts' : view === 'services' ? 'Services' : view === 'cron' ? 'Cron' : view === 'updates' ? 'Updates' : view === 'disks' ? 'Disks' : view === 'files' ? 'Files' : view === 'procs' ? 'Processes' : view === 'machines' ? 'Machines' : view === 'settings' ? 'Settings' : activeTerm ? activeTerm.name : ''}</span> <span className="muted">{view === 'dashboard' ? 'Dashboard' : view === 'widgets' ? 'Widgets' : view === 'docker' ? 'Docker' : view === 'alerts' ? 'Alerts' : view === 'services' ? 'Services' : view === 'cron' ? 'Cron' : view === 'updates' ? 'Updates' : view === 'disks' ? 'Disks' : view === 'files' ? 'Files' : view === 'procs' ? 'Processes' : view === 'machines' ? 'Machines' : view === 'settings' ? 'Settings' : activeTerm ? activeTerm.name : ''}</span>
</footer> </footer>
</div> </div>
) )
+1 -1
View File
@@ -1,4 +1,4 @@
// The stock Monitors modules were written against one Sample object. They now read the // The stock Dashboard modules were written against one Sample object. They now read the
// sensor API like everything else; this file is the seam — it rebuilds that object from // sensor API like everything else; this file is the seam — it rebuilds that object from
// sensor values (the live stream) and sensor metadata (the catalog: labels, thresholds). // sensor values (the live stream) and sensor metadata (the catalog: labels, thresholds).
import { Sample, Series } from './api' import { Sample, Series } from './api'