make open dashboard an anchor, and close the preview-navigate verify

Four navigates were flagged; one was real. The two ProjectPreview lines are
void — Projects was deleted in July. Of the two in DashboardPreview, the
create path writes the dashboard and then goes there, which a link cannot
express, so it stays. The Open Dashboard button in the edit form was pure
navigation and is now a link.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-07 12:50:59 +00:00
co-authored by Claude Opus 5
parent 667d622918
commit bbcb041ef3
2 changed files with 23 additions and 13 deletions
+16 -10
View File
@@ -68,10 +68,10 @@ are good building blocks. The **Workspace/Panel framework** contains **zero** ro
| H4 | `workspaces/…/apps/ChatHistory/ChatDetailPanel.tsx:136` | which chat to render | reads `usePanelChannel('chat:selected-session')`, **not** `useParams` | make the route the source of truth: read `sessionId` from `useParams`, fetch by id, retire `chat:selected-session` (or make it a derived cache). **Finishes the /chat fix.** |
| ~~H5~~ | ~~`Screens/Dashboard/Email/EmailList.tsx:336`~~ | ~~an email~~ | ~~`<button data-email-id onClick={setSelectedId}>` + `EMAIL_SELECTED` channel + a state↔URL sync effect (`EmailScreen.tsx:27-33`)~~ | **Done.** Rows are `<Link to={emailPath(msg.id)}>`, list + reader + mobile-panel all read `useSelectedEmailId()` (`Email/shared.ts`), and `EMAIL_SELECTED` plus both sync effects are deleted. Arrow-key browsing navigates with `replace` so a sweep doesn't stack history. |
> **Verify:** `Dashboards/DashboardPreview.tsx:355,377` and `Projects/ProjectPreview.tsx:430,457` also
> `navigate('/…/:id')`. The nav auditor read these as HIGH "open entity"; the apps auditor read the Project
> ones as *correct* post-create/edit flows. Eyeball them during H2/H3 — convert the ones that are "open an
> existing entity from a preview", leave genuine post-mutation redirects.
> ~~**Verify:**~~ **Verified.** Of the four `navigate('/…/:id')` calls flagged here, the two in
> `ProjectPreview` are void (Projects was deleted on 2026-07-30) and one of the two in `DashboardPreview`
> is a genuine post-create redirect. The apps auditor was right and the nav auditor was wrong: exactly one
> — the "Open Dashboard" button in the edit form — was an opaque click, and it is a `<Link>` now.
### 🟠 MEDIUM — navigable entity with **no route yet** (add a route, then link)
@@ -171,13 +171,13 @@ publishers means changing the chat panel, which is another agent's, so it is wri
| 1 | `Jobs/JobsPage.tsx:109` | job list row | `/jobs/:id` | **YES** | H1 |
| 2 | `Dashboards/DashboardListApp.tsx:90` | dashboard row (off-page) | `/dashboards/:id` | YES | H2 |
| 3 | `Dashboards/DashboardListApp.tsx:114` | inside "New Dashboard" | `/dashboards` | ~ | create action |
| 4 | `Dashboards/DashboardPreview.tsx:355` | open dashboard | `/dashboards/:id` | YES | verify vs H2 |
| 5 | `Dashboards/DashboardPreview.tsx:377` | open dashboard | `/dashboards/:id` | YES | verify vs H2 |
| ~~4~~ | `Dashboards/DashboardPreview.tsx` (create) | open dashboard | `/dashboards/:id` | no | **stays.** post-create redirect — a link cannot write the row first |
| ~~5~~ | `Dashboards/DashboardPreview.tsx` (edit form) | open dashboard | `/dashboards/:id` | YES | **done**`<Button asChild><Link>` |
| 6 | `Projects/ProjectListApp.tsx:116` | project row (off-page) | `/projects/:id` | YES | H3 |
| 7 | `Projects/ProjectListApp.tsx:142` | inside "New Project" | `/projects` | ~ | create action |
| 8 | `Projects/ProjectPreview.tsx:430` | open project | `/projects/:id` | YES | verify vs H3 |
| 9 | `Projects/ProjectPreview.tsx:457` | open project | `/projects/:id` | YES | verify vs H3 |
| 10 | `Jobs/JobDetail.tsx:709` | back button | `/jobs` | YES | use `BackButton`/`<Link>` |
| ~~8~~ | ~~`Projects/ProjectPreview.tsx:430`~~ | — | — | — | void: Projects deleted 2026-07-30 |
| ~~9~~ | ~~`Projects/ProjectPreview.tsx:457`~~ | — | — | — | void: Projects deleted 2026-07-30 |
| ~~10~~ | `Jobs/JobDetail.tsx` | back button | `/jobs` | YES | **done**`<Link>`; `BackButton` was dead and is deleted |
| 11 | `ChatHistory/SessionList.tsx:70` | "New Chat" | `/chat/new` | ~ | borderline (LOW) |
| ~~12~~ | ~~`components/Combobox.tsx:54`~~ | nav combobox option | `option.href` | — | M7 — file deleted, it had no callers |
| ~~13~~ | `MusicPlayer/MusicPlayerHost.tsx:251` | open current album (setCwd+nav) | `/music` | ~ | **Done** — the side-effect was the `setCwd`; with the location in the URL the tile is a plain `<Link>` to `musicPath(albumRel)`. |
@@ -214,7 +214,13 @@ publishers means changing the chat panel, which is another agent's, so it is wri
- [ ] **H4** Chat detail: read `sessionId` from `useParams`, retire `chat:selected-session` as source of truth (`ChatDetailPanel.tsx:136`) — **finishes the /chat fix**. *Deferred: overlaps the in-flight `sidecars-*` chat-comms work; do after that lands.*
- [x] **H5** Email rows → `<Link>` driven by `useParams().emailId`; the `EMAIL_SELECTED` global and both state↔URL sync effects are gone. **Needs runtime test.** (`EMAIL_FOLDER` stays a `useGlobal` for now — it is read in one component and is view state, not selection; putting the folder in `?folder=` is a separate, smaller item.)
- [x] **M8** Dead `/settings/resources` menu item removed from `UserMenu.tsx`, along with its now-orphaned `en`/`pt` locale keys. **Needs runtime test.**
- [ ] Verify + convert the 4 preview "open" navigates (`DashboardPreview:355,377`, `ProjectPreview:430,457`); leave genuine post-mutation redirects.
- [x] Verified + converted the preview "open" navigates. Four were listed; **one** was real. The two
`ProjectPreview` lines are void — Projects was deleted end to end on 2026-07-30. Of the two in
`DashboardPreview`, the create path (`navigate` after writing the dashboard) is a genuine
post-mutation redirect and stays; only the "Open Dashboard" button in the edit form was pure
navigation, and it is now `<Button asChild><Link …>`. The big click-through overlay on the preview
was already a `<Link>`. `DashboardListApp`'s "New Dashboard" also stays a button: it sets six pieces
of form state and only *then* conditionally navigates.
### Phase 2 — Add a route, then link (per-entity, medium effort)
- [x] **M6** Settings sub-sections → `/settings/:page/:section`; `SectionButton` is now a `SectionLink` (`<NavLink>`), the five `*_SELECTED` globals and `INTEGRATIONS_SETTINGS_TAB` are gone, and each page renders one `SettingsRoute` guard that canonicalises the bare route and a bogus section. **Needs runtime test.**
@@ -395,10 +395,14 @@ const CreatePanel = () => {
<Plus className="h-4 w-4 mr-1" />
{isEditing ? 'Update Dashboard' : 'Create Dashboard'}
</Button>
{/* Pure navigation, so it is an anchor. The create button above stays a button on purpose: it
writes a dashboard and *then* goes there, and a link cannot express the "and then". */}
{isEditing && (
<Button onClick={() => navigate(`/dashboards/${editingId}`)} variant="outline" className="cursor-pointer">
<Button asChild variant="outline" className="cursor-pointer">
<Link to={`/dashboards/${editingId}`}>
<ArrowRight className="h-4 w-4 mr-1" />
Open Dashboard
</Link>
</Button>
)}
</div>