From 82128d17ba9644d1e3d4a93f43ef7ecc22bed7ce Mon Sep 17 00:00:00 2001 From: Paul Nothaft Date: Tue, 8 Sep 2026 21:41:05 +0200 Subject: [PATCH 1/2] fix(portal): land on Overview after connecting, not Feature requests The #connect= token flow routed a newly-signed-in participant straight to /requests. Reported from the PicPeak admin side: the "Open usage portal" button is meant to show what's being used across installations, and users expect that landing page to be the Overview, not the feature-request list. --- web/main.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/main.tsx b/web/main.tsx index 82bcd7d..12634fa 100644 --- a/web/main.tsx +++ b/web/main.tsx @@ -1136,8 +1136,8 @@ function App() { token: connect, expiresAt: Date.parse(value.expires_at), }); - setRoute("/requests"); - history.replaceState(null, "", "/requests"); + setRoute("/"); + history.replaceState(null, "", "/"); }) .catch(() => { if (!controller.signal.aborted) setSessionError(true); From bdb50af7b27f58f894f1a2fcfdd264626c8e47a6 Mon Sep 17 00:00:00 2001 From: Paul Nothaft Date: Tue, 8 Sep 2026 22:05:05 +0200 Subject: [PATCH 2/2] fix(portal): show the voting-connected confirmation on Overview too Redirecting to Overview after #connect= (previous commit) silently dropped the "You are connected for voting." confirmation, since it only rendered on the Requests page. Render it on Overview whenever a voting session is active, and update the two e2e tests that assumed connecting landed directly on Requests with a ready-to-click vote button. Found by CI (required e2e checks) after the previous commit. --- test/browser/security.spec.ts | 3 +++ web/main.tsx | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/test/browser/security.spec.ts b/test/browser/security.spec.ts index 20617ec..1279794 100644 --- a/test/browser/security.spec.ts +++ b/test/browser/security.spec.ts @@ -663,6 +663,9 @@ test("session sign-in keeps reading after the original voting deadline and clear test("an expired vote removes voting access without discarding the reading hash", async ({ page, collector }) => { const session = await collector.send("session", 3); await page.goto(`${collector.url}/#connect=${session.session_token}`); + await expect(page.getByText("You are connected for voting.", { exact: true })).toBeVisible(); + await page.getByRole("navigation", { name: "Main navigation" }) + .getByRole("link", { name: "Feature requests", exact: true }).click(); const vote = page.getByRole("button", { name: "Vote for Synthetic request", exact: true }); await expect(vote).toBeEnabled(); // The server expires first (clock skew or a suspended browser timer). diff --git a/web/main.tsx b/web/main.tsx index 12634fa..925a831 100644 --- a/web/main.tsx +++ b/web/main.tsx @@ -158,10 +158,12 @@ function AccessForm({ function Overview({ credential, + voting, unlock, expire, }: { credential: string; + voting: boolean; unlock: (hash: string) => void; expire: () => void; }) { @@ -283,6 +285,11 @@ function Overview({ + {voting && ( +
+ {t.votingConnected} {t.votingDuration} +
+ )} {!data.installations && (
{t.firstReportsTitle} {t.firstReportsIntro} @@ -1192,6 +1199,7 @@ function App() {