mirror of
https://github.com/0xWheatyz/handler.git
synced 2026-09-06 13:46:24 +00:00
Split the web UI into a page per section
The dashboard was a single route that swapped section components via a `section` state field. Convert it to the App Router's multi-page model so each left-nav selection is its own route (/, /repositories, /agents, /schedules, /approvals, /servers, /activity, /shared, /login), making the pages modular and independently updatable. - Move the token gate + store provider + sidebar into a persistent frame (AppFrame + Shell) rendered by the root layout, so auth, the polling loop, and shared state survive client-side navigation. - Sidebar items are now <Link> routes; the active item and the store's polled section are derived from the URL (lib/nav). - Each section gets an app/<section>/page.tsx; Runs stays at root and keeps its full-height split layout, the rest render in the shared scroll frame. - Emit per-route index.html (trailingSlash) so the FastAPI StaticFiles mount serves clean slash-terminated URLs with no SPA rewrite. - Regenerate the bundled static export. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PsAeGVadULRzPhV2PRDttM
This commit is contained in:
@@ -189,17 +189,22 @@ export function useDashboard(): StoreValue {
|
||||
export function DashboardProvider({
|
||||
token,
|
||||
onUnauthorized,
|
||||
initialSection = "runs",
|
||||
children,
|
||||
}: {
|
||||
token: string;
|
||||
onUnauthorized: () => void;
|
||||
/* Which section is on screen at mount, derived from the URL by the auth frame. The
|
||||
* provider lives in the root layout and mounts once, so this only seeds the first
|
||||
* poll; later navigation updates the section through setSection. */
|
||||
initialSection?: Section;
|
||||
children: ReactNode;
|
||||
}) {
|
||||
const client = useMemo(() => createClient(token, onUnauthorized), [token, onUnauthorized]);
|
||||
const clientRef = useRef(client);
|
||||
clientRef.current = client;
|
||||
|
||||
const [section, setSectionRaw] = useState<Section>("runs");
|
||||
const [section, setSectionRaw] = useState<Section>(initialSection);
|
||||
const [projects, setProjects] = useState<Project[]>([]);
|
||||
const [agents, setAgents] = useState<RunAgent[]>([]);
|
||||
const [selectedProjectId, setSelectedProjectId] = useState<string>("");
|
||||
|
||||
Reference in New Issue
Block a user