put the monitor scope in the url

/system-monitor/:scope, the same shape as /photos: route pair, one Navigate guard after the
hooks, scope list as react-router NavLinks, and both panels reading useParams instead of
agreeing over a `monitor:scope` channel. The Dock's isActive is a startsWith, so its
highlight survives the redirect off the bare route.
This commit is contained in:
2026-08-07 11:41:16 +00:00
parent 2502c33804
commit 00332e275a
8 changed files with 66 additions and 41 deletions
@@ -1,14 +1,20 @@
import { Navigate, useParams } from 'react-router';
import type { LayoutNode } from 'officerdev';
import { WorkspaceView } from 'officerdev';
import { WorkspaceView, DEFAULT_MONITOR_SCOPE, monitorScopePath, isMonitorScope } from 'officerdev';
import { useDashboardState } from 'state/useDashboardState';
import { defaultLayout } from './defaultLayout';
// /system-monitor uses the Workspace/Panel system (like /music): a horizontal split with an (empty for
// now) left panel and the system snapshot on the right.
// /system-monitor uses the Workspace/Panel system (like /photos): the scope list on the left, the scope
// itself on the right. Which scope is open is `:scope` in the URL, not a panel channel.
export const SystemMonitorScreen = () => {
const { scope } = useParams();
const workspace = useDashboardState<LayoutNode>('screens/system-monitor', defaultLayout);
// After the hooks — it returns early. Bare /system-monitor and a scope that doesn't exist both
// canonicalise, so the list's router-driven highlight can never disagree with the pane.
if (!isMonitorScope(scope)) return <Navigate to={monitorScopePath(DEFAULT_MONITOR_SCOPE)} replace />;
return (
<div className="h-full w-full pt-2">
<WorkspaceView