From d947128951bf35bd5cc1d68ec8836c5f1ea99c83 Mon Sep 17 00:00:00 2001 From: Michele Bigi Date: Sun, 13 Sep 2026 16:22:16 +0200 Subject: [PATCH] Fix project sidebar stuck on the report page. Open finished projects on the hub instead of /report, and hard-navigate when leaving nested report/progress/placement routes for Dashboard, Library, and hub tabs. Co-authored-by: Cursor --- frontend/content/changelog.md | 7 ++ .../src/components/dashboard/project-card.tsx | 7 +- .../components/dashboard/projects-table.tsx | 2 +- frontend/src/components/layout/sidebar.tsx | 99 ++++++++++++------- 4 files changed, 78 insertions(+), 37 deletions(-) diff --git a/frontend/content/changelog.md b/frontend/content/changelog.md index 4f3500a..44a6da1 100644 --- a/frontend/content/changelog.md +++ b/frontend/content/changelog.md @@ -2,6 +2,13 @@ What's new in Pinscope. +## 2.28.2 — 2026-09-13 — Fix project sidebar navigation + +Opening a finished project no longer dumps you on the report with a stuck left menu. Hub first; Report stays in the sidebar. Leaving `/report` for BOM/tabs uses a full navigation so the page actually changes. + +- [Fixed] Dashboard project cards/table open `/project/{id}` (not `/report`). +- [Fixed] Sidebar Dashboard / Library / BOM tabs escape nested report/progress/placement routes. + ## 2.28.1 — 2026-09-12 — Placement pipeline (parallel) Dedicated Placement job builds the routing-first topology plan without touching the analysis pipeline status or spending credits. No millimetres — domains, IC groups, satellites only. diff --git a/frontend/src/components/dashboard/project-card.tsx b/frontend/src/components/dashboard/project-card.tsx index 879e637..64f1fe3 100644 --- a/frontend/src/components/dashboard/project-card.tsx +++ b/frontend/src/components/dashboard/project-card.tsx @@ -155,8 +155,9 @@ export function ProjectCard({ ); } - // Open the report by default — that's what users want to see for a finished - // project. In-flight or paused runs go to the progress page where the SSE + // Open the project hub by default so BOM / derating / settings in the + // sidebar work immediately. Report stays one click away in ProjectNav. + // In-flight or paused runs go to the progress page where the SSE // stepper and resume controls live. const inFlight = project.status === "running" @@ -164,6 +165,6 @@ export function ProjectCard({ || project.status === "paused_by_user"; const href = inFlight ? `/project/${project.id}/progress` - : `/project/${project.id}/report`; + : `/project/${project.id}`; return {card}; } diff --git a/frontend/src/components/dashboard/projects-table.tsx b/frontend/src/components/dashboard/projects-table.tsx index a4cd117..1c3bbc5 100644 --- a/frontend/src/components/dashboard/projects-table.tsx +++ b/frontend/src/components/dashboard/projects-table.tsx @@ -105,7 +105,7 @@ function ProjectRow({ || project.status === "paused_by_user"; const href = inFlight ? `/project/${project.id}/progress` - : `/project/${project.id}/report`; + : `/project/${project.id}`; const nameCell = (
diff --git a/frontend/src/components/layout/sidebar.tsx b/frontend/src/components/layout/sidebar.tsx index 6442a9c..4bd2dfe 100644 --- a/frontend/src/components/layout/sidebar.tsx +++ b/frontend/src/components/layout/sidebar.tsx @@ -2,7 +2,7 @@ import Link from "next/link"; import { usePathname, useSearchParams } from "next/navigation"; -import { useState, useEffect } from "react"; +import { Suspense, useState, useEffect, type ReactNode } from "react"; import { LayoutDashboard, Cpu, @@ -77,7 +77,14 @@ export function Sidebar() {
{projectId ? ( - + }> + + ) : ( )} @@ -185,6 +192,37 @@ const PROJECT_NAV_ITEMS: NavItem[] = [ { type: "tab", tab: "settings", label: "Settings", icon: Settings }, ]; +function NavLink({ + href, + active, + children, + forceDocument, +}: { + href: string; + active?: boolean; + children: ReactNode; + forceDocument?: boolean; +}) { + const className = cn( + "flex items-center gap-2 px-3 py-2 rounded-md text-sm transition-colors", + active + ? "bg-accent text-accent-foreground" + : "text-muted-foreground hover:text-foreground hover:bg-accent/50" + ); + if (forceDocument) { + return ( + + {children} + + ); + } + return ( + + {children} + + ); +} + function ProjectNav({ pathname, projectId, @@ -201,11 +239,18 @@ function ProjectNav({ const currentTab = searchParams.get("tab"); const isRunning = project?.status === "running"; const isOnProgress = pathname === `${base}/progress`; + // Nested routes (report / progress / placement): soft-nav to `?tab=` can + // leave the report page mounted — use a full document navigation instead. + const onNestedRoute = pathname.startsWith(`${base}/`); function isActive(item: NavItem): boolean { if (item.type === "route") { return pathname === `${base}${item.path}` && !currentTab; } + // Hub with no tab defaults to BOM in the project page. + if (item.tab === "bom") { + return pathname === base && (currentTab === "bom" || currentTab === null); + } return pathname === base && currentTab === item.tab; } @@ -216,20 +261,14 @@ function ProjectNav({ return (