Repository navigation
Conversation
|
Dev server on box |
|
📍 Walkthrough · 4 stops · 38dec72 — Open the walkthrough
|
38dec72 to
f428f6a
Compare
580f6df to
a7d0107
Compare
a7d0107 to
5582763
Compare
a057625 to
540a87e
Compare
…oard menu entry The admin dashboard page existed at /admin/dashboard but no menu reached it, it read the ambient header project, and the member dashboard still carried the superadmin cards. Project admins and superadmins now each have a dashboard behind one "Dashboard" entry at the top of the admin sidebar. - Routes: AdminDashboardPage takes `page`. `/admin/dashboard` mounts it as `admin` (access superadmin) and `/project/:projectName/admin/dashboard` as `projectAdmin`, both with menuKey `admin-dashboard`. The project admin page reads its project from the URL (useUrlProjectValidity); the superadmin page passes `null` and its page query counts the current domain (`domain:<name>`, ADR 0012). Legacy `/admin-dashboard` redirects by role. Domain admins can still open the project admin page by URL through the subtree's default `projectAdmin` access; only the menu hides it from them. - Menu: `admin-dashboard` is the first admin item for superadmins and for the current project's project admin, and absent for domain admins. pathBuilder gains PROJECT_ADMIN_MENU_KEY_ROUTES, resolveMenuKeyScopeFeature (superadmin wins over project admin) and featureKeyInScope, which the inverse lookups in useRouteScope and WebUIHeaderProjectSelect now use. getPathFromMenuKey takes the admin role; the sider's "Admin settings" entry and the /admin index redirect use the role-resolved item `to`, and the /project/:name/admin index redirect resolves as project admin. - Project-agnostic surface: `admin-dashboard` joins PROJECT_AGNOSTIC_MENU_KEYS for `/admin/dashboard` only. useIsProjectAgnosticPage now requires the `admin` route scope for the menu-key match, so the project admin page keeps the header project selector; the legacy path regex fallback is unchanged. - Explicit project: DashboardPanelBoard takes `project` and its filter context now carries it (and wraps the panel modal). Cards read it through useDashboardProject, custom panel queries through useDashboardQueryScope (the session preset falls back to the current domain when the project is null). AdminDashboardPage and components/DashboardPanels/** join the ESLint ban on useCurrentProjectValue. - Catalog: agentStats and activeAgents live on the superadmin page only, activeSessions on the project admin and superadmin pages; the member page query no longer asks for agent stats. - Pinned boards (open item from #10582): on the project admin page, choosing a pinned board whose pins do not contain the URL project moves the URL path to the first pinned project the viewer administers; a header project change inside the pins keeps the pinned board. The project picker always offers the URL project, so a superadmin who opens the project admin page by URL sees its name instead of its id. - ADR 0001 drops the "admin dashboard is the only exception" sentences and records the dashboards; ADR 0015 records the pinned-board navigation and the page project; the ARCHITECTURE row follows. - The route label is `webui.menu.Dashboard`; the now unused `webui.menu.AdminDashboard` is removed from all 21 locales. Search index regenerated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…work Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#10552 split the sider into a system admin menu (entered from the user menu) and a Project Settings menu, and rebasing onto it left the role-aware Dashboard entry broken: the project admin menu listed the superadmin's dashboard at /admin/dashboard, /admin/dashboard selected the Project Settings sider because its menu key is in both menus, a domain admin who administers the project had no project dashboard, and the sider no longer imported getPathFromMenuKey. - The Project Settings menu always links a per-role key to its project admin route; the system admin menu keeps it only for superadmins. - A per-role key is selected only in the menu whose item points at the current URL's scope. - The dashboard item exists for superadmins and for anyone administering the current project; domain admins alone still have none. - The sider's Project Settings entry, the user menu's system admin entry and the root redirect use the role-resolved item `to`. - The menu test follows the split menus. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…in pages The dashboard Edit button is rendered in the breadcrumb, which sat outside the admin accent provider that wraps the page content, so on the project admin dashboard it kept the user theme's primary color. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
540a87e to
4fba318
Compare
The sider no longer labels a card "Superadmin only" or shows a greyed-out "Not available in this environment" entry: role-limited cards were already absent for other roles, and config-locked cards are now left out too. The superadmin-only agent cards move into the Resources group, and the two unused strings leave every locale. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…admin-dashboard-routes
The dashboard edit toggle it was added for is a secondary button now. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…admin-dashboard-routes
…admin-dashboard-routes # Conflicts: # react/src/components/DashboardPanels/DashboardPanelBoard.tsx
…admin-dashboard-routes
…admin-dashboard-routes
…admin-dashboard-routes # Conflicts: # react/src/components/DashboardPanels/useDashboardFilters.tsx
Ready-gate agent review (Opus) - blocking issues onlyNo blocking issues. Copilot: unavailable (insufficient remaining quota) - this review gated the PR alone. The fixes above landed after the review and were not re-reviewed; verified by |
…admin-dashboard-routes
The dashboard page query carried the session count, recently created sessions, total resources and agent stats fragments on every page and refreshed all of them on the page timer, whether or not a card on the board reads them. The project admin page offers none of the last three cards, yet fetched recently created sessions and up to 100 agents with their slots every 30s (plus agent stats for a superadmin); a card removed from a board kept being fetched too. Each fragment is now included only while a rendered card reads it, the page query refreshes no faster than its fastest reader (never faster than the previous page interval), and it stops refreshing when no card reads it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…admin-dashboard-routes
…admin-dashboard-routes # Conflicts: # react/src/components/DashboardPanels/DashboardPanelBoard.tsx
…admin-dashboard-routes
…admin-dashboard-routes The page query now refreshes on every dashboard tick while a rendered card reads it; `pageQueryRefresh` (the fastest reader's `refresh.min`) is gone with the per-card minimums (ADR 0017).
…admin-dashboard-routes
…admin-dashboard-routes
agatha197
left a comment
There was a problem hiding this comment.
Ready-gate agent review — 7 findings — 5 Important, 2 Nit, 0 Pre-existing. The summary comment on this PR lists every finding and its outcome.
|
7 findings — 5 Important, 2 Nit, 0 Pre-existing Round 1 —
|
| # | Tag | File:line | Finding | Outcome |
|---|---|---|---|---|
| 1 | Important | react/eslint.config.js:205 |
This per-file block redeclares no-restricted-imports, which replaces the global options, and its patterns omit the FR-3428 useSetCurrentProject ban; adding AdminDashboardPage.tsx and DashboardPanels/** here lifts that ban for those files, contrary to the block's own note that the global patterns are repeated. |
fixed ec5b272 |
| 2 | Important | react/src/components/DashboardPanels/SessionResourceGridPanel.tsx:77 |
On the superadmin page project is null, so the grid runs compute_session_list(group_id: null) with no domain_name and lists sessions from every domain, while the same panel in table view scopes to domain:<current>; ADR 0018 (amended in this PR) says a null project means the current domain. |
fixed ec5b272 |
| 3 | Nit | react/src/components/DashboardPanels/panelCatalog.tsx:52 |
Page-query cards render null while their fragment is excluded, and the fragment set is deferred, so a newly added My Sessions / Active Sessions card shows an empty body with no skeleton for the whole background round trip. |
not-worth |
| 4 | Nit | react/src/components/DashboardPanels/types.ts:215 |
The old JSDoc ('Fragment keys of the page queries the built-in cards still read...') was left stacked above the new one on DashboardPageQueryRefs and describes the removed shape. |
fixed ec5b272 |
| 5 | Important | react/src/components/DashboardPanels/types.ts:283 |
The new domainName scope (null project = current domain) is ignored by the deployment and vfolder presets in resourceRegistry.tsx: deployment drops its project filter and queries myDeployments unfiltered on the superadmin page, and vfolder's makeOffsetVariables ignores both project and domain, so on the newly routed project admin page it lists every folder in the system. |
fixed ec5b272 |
| 6 | Important | react/src/helper/projectAgnosticRoutes.ts:47 |
Making /admin/dashboard project-agnostic unmounts the header project selector, but the superadmin page still takes its resource group from the now-hidden ambient project (useCurrentResourceGroupValue in AdminDashboardPage, useDashboardFilters, and the Total Resources card's SharedResourceGroupSelectForCurrentProject), so resource groups not bound to that project become unreachable. |
fixed ec5b272 |
| 7 | Important | react/src/pages/AdminDashboardPage.tsx:56 |
queryFetchKey switches on the non-deferred fragmentsKey while the variables use deferredFragmentsKey, so adding the first page-query card after a refresh tick gives the urgent render a new fetchKey with network-only and the query suspends into the route-level skeleton (the FR-3386 flash the deferral exists to prevent). The same block is in DashboardPage.tsx:47; basing queryFetchKey on deferredFragmentsKey avoids it. |
intentional — superseded: the page query is removed in #10596 |
Security review: 0 findings
Posted inline: 7 · already inline from this round: 0 · table only (outside the diff): 0 · repeats of an earlier round dropped: 0 · Nits over the cap of 3 dropped: 0 · not posted (no file:line, or style-only): 0
# Conflicts: # react/src/components/DashboardPanels/DashboardPanelBoard.tsx # react/src/components/DashboardPanels/boardModel.test.ts # react/src/pages/AdminDashboardPage.tsx # react/src/pages/DashboardPage.tsx
…n page, lint ban - The superadmin dashboard keeps its own resource group (superadminResourceGroupAtom via usePageResourceGroup), since its route hides the header project selector. It starts from the hidden current project's group, cards default to it, and the Total Resources card's picker lists every resource group of the current domain. - The session grid view passes domain_name when the page has no project, so the superadmin grid reads the current domain like the table view. - The deployment and data presets read scopedDeployments and scopedVFoldersV2 with the card's scope: the viewer on the member page, the URL project on the project admin page, the current domain on the superadmin page. ResourceQueryArgs carries domainId and ownerId. - The project-agnostic eslint block repeats the global FR-3428 useSetCurrentProject ban, which its own no-restricted-imports replaced. - The stale JSDoc above DashboardPageQueryRefs is removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…admin-dashboard-routes
…admin-dashboard-routes
…admin-dashboard-routes
Resolves #10583
Summary
Fourth layer of the role-aware dashboard stack (#10422). The admin dashboard gets real routes and one menu entry that resolves by role.
AdminDashboardPagetakes apageprop and is mounted at/admin/dashboard(admin, superadmin only) and/project/:projectName/admin/dashboard(projectAdmin). The project admin page reads its project from the URL only; the superadmin page passes no project and its page query counts the current domain (ADR 0012). Legacy/admin-dashboardredirects by role.admin-dashboardis the first admin sidebar item for superadmins and for the current project's project admin; domain admins keep today's behaviour (no dashboard entry).pathBuilder.tsgains a role-aware resolver (superadmin wins);getPathFromMenuKeytakes the admin role;/project/:name/adminlands a project admin on the dashboard./admin:admin-dashboardis inPROJECT_AGNOSTIC_MENU_KEYSwith canonical path/admin/dashboard, anduseIsProjectAgnosticPagealso checks the route scope, so the project admin page keeps the header project selector.DashboardPanelBoardtakes aprojectprop; cards read it throughuseDashboardProject/useDashboardQueryScope.AdminDashboardPage.tsxandDashboardPanels/**join the ESLint ban on the ambient project.docs/ARCHITECTURE.mdrow updated.Changes after the 2026-10-26 review
Behaviour notes for review
/project/:n/admin/dashboardby URL through the subtree's default access (a comment on the route says so); scoped reads authorize the data.webui.menu.AdminDashboardhad no other users and is removed from all locales; the route label iswebui.menu.Dashboard.Verification
VERIFY_TESTS=1: react Vitest 76 files, 841 tests pass; newuseWebUIMenuItems.test.tsxrole matrix (superadmin, domain admin, project admin, user); updated path, header and project-agnostic tests./admin/dashboard, whose first sidebar item is "Dashboard"; the page shows the board tab, the filter bar and the admin cards without a header project selector;/admin-dashboardredirects there;/project/default/admin/dashboardkeeps the header selector; the member dashboard no longer shows agent cards.Server load
🤖 Generated with Claude Code
Walkthrough
Not shown in the walkthrough:
Decisions (2026-10-29)
pageQueryRefresh(the fastest reader's minimum) is removed with the per-card minimums (ADR 0018).Risk tier: High —
docs/ARCHITECTURE.md,docs/adr/0001-explicit-project-prop-contract.md,docs/adr/0018-dashboard-filter-bar.md,react/eslint.config.js,react/src/hooks/useRouteScope.tsSuggested human approvals: 2 (branch protection decides)
Reviewed by fw ready gate at
afa5dda(round 1)Ready gate (round 1)