Skip to content

fix(web): stabilize dashboard and handoff state - #1216

Open
PsiACE wants to merge 4 commits into
masterfrom
codex/fix-web-navigation-state
Open

fix(web): stabilize dashboard and handoff state#1216
PsiACE wants to merge 4 commits into
masterfrom
codex/fix-web-navigation-state

Conversation

@PsiACE

@PsiACE PsiACE commented Aug 12, 2026

Copy link
Copy Markdown
Member

Which issue or RFC does this PR close?

N/A

Rationale for this change

Dashboard and Handoff could briefly show empty or stale states during authentication and navigation.

What changes are included in this PR?

  • Share page UI state and request gating.
  • Prevent stale Dashboard requests from restoring signed-out views.
  • Add a Handoff Project selector and restore the previous selection when loading fails.
  • Preserve the existing Handoff Report layout and Dashboard scope-ID behavior.

Are there any user-facing changes?

Navigation no longer flashes login/loading content. Handoff Projects use a selector. No API, schema, or migration changes.

How was this change tested?

  • make check
  • make test — 433 passed, 7 skipped
  • JavaScript ES module syntax checks
  • Delayed sign-out and failed Project-switch reproductions

AI usage statement

Implemented and reviewed with OpenAI Codex.

@PsiACE
PsiACE marked this pull request as ready for review August 12, 2026 08:14
Copilot AI lite review requested due to automatic review settings August 12, 2026 08:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR stabilizes the Dashboard and Handoff web UIs by introducing a shared “status shell” and request gating to prevent brief flashes of empty/stale state during auth and navigation, plus a new Handoff Project selector with selection restore behavior.

Changes:

  • Add a reusable status.html template and CSS gating based on data-server-session to avoid login/loading flashes.
  • Introduce shared page-ui.js (i18n/theme helpers + request gate) and refactor Dashboard/Handoff scripts to use request sequencing and retryable status UI.
  • Update Handoff Report to use a <select> project picker (replacing tab UI) and adjust tests accordingly.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated no comments.

Show a summary per file
File Description
tests/test_dashboard.py Adds assertions to verify new session/status shells and updated script URLs/controls.
src/powercontext/server/templates/pages/handoff_report.html Adds status component and replaces project tabs with a project <select>.
src/powercontext/server/templates/pages/dashboard.html Adds status component and removes default hidden gating from the dashboard shell.
src/powercontext/server/templates/components/status.html New reusable status shell with message + optional Retry button.
src/powercontext/server/templates/base.html Adds server-session dataset initialization and cache-busted CSS URL.
src/powercontext/server/static/site.css Adds auth/server-content visibility gating and styles status + new report picker layout.
src/powercontext/server/static/page-ui.js New shared page UI utilities (translate/locale/theme + request gate).
src/powercontext/server/static/handoff-report.js Refactors to request gating + status shell, adds project selector handling and retry flow.
src/powercontext/server/static/dashboard.js Refactors to request gating + status shell and adds retry flow.
src/powercontext/server/static/auth.js Updates token storage to set data-server-session for CSS gating.
Suppressed comments (2)

src/powercontext/server/static/auth.js:21

  • storeServerToken() marks the session as active even when sessionStorage.setItem() throws, but readServerToken() returns null on storage errors. In browsers where sessionStorage is blocked/throws, this combination can leave the page in the "active" CSS state while subsequent actions see no token (and showLogin() won't be visible due to data-server-session="active"). Consider keeping an in-memory fallback token so readServerToken() can still return the current token when sessionStorage is unavailable.

This issue also appears on line 24 of the same file.

export function readServerToken() {
  try {
    return sessionStorage.getItem(tokenKey);
  } catch (error) {
    return null;
  }
}

export function storeServerToken(token) {
  setSessionState("active");
  try {
    sessionStorage.setItem(tokenKey, token);
  } catch (error) {
    // Authentication still applies to the current request when storage is unavailable.
  }

src/powercontext/server/static/auth.js:30

  • With the in-memory token fallback, clearServerToken() should also clear the in-memory copy; otherwise readServerToken() can keep returning a stale token when sessionStorage is unavailable.
export function clearServerToken() {
  setSessionState("missing");
  try {
    sessionStorage.removeItem(tokenKey);
  } catch (error) {
    // The current page can still return to its signed-out state.
  }

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Copilot AI review requested due to automatic review settings August 13, 2026 03:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/powercontext/server/static/auth.js:19

  • storeServerToken() sets data-server-session="active" before attempting sessionStorage.setItem. If browser storage is blocked/unavailable, readServerToken() returns null but the page stays in the "active" CSS mode (hiding .auth-shell and showing .server-content), which can leave users stuck unable to re-authenticate/refresh.

Consider keeping an in-memory token fallback (current-tab only) so the UI state and readServerToken() remain consistent even when sessionStorage throws.

export function storeServerToken(token) {
  setSessionState("active");
  try {
    sessionStorage.setItem(tokenKey, token);
  } catch (error) {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants