feat: unify workspace and dashboard routing (#407)#411
Merged
Conversation
Route Workbench and Dashboard through one canonical /sql entry point, keep workspace state live across surface changes, and retire detached dashboard handoff storage. Preserve state-bound OAuth return routes, harden asynchronous workspace navigation, and update deployment, architecture, and regression coverage. Co-Authored-By: OpenAI Codex <noreply@openai.com> Claude-Session: unavailable (OpenAI Codex)
Co-Authored-By: OpenAI Codex <noreply@openai.com> Claude-Session: unavailable (OpenAI Codex)
Co-Authored-By: OpenAI Codex <noreply@openai.com> Claude-Session: unavailable (OpenAI Codex)
Co-Authored-By: OpenAI Codex <noreply@openai.com> Claude-Session: unavailable (OpenAI Codex)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Closes #407.
Unifies Workbench and Dashboard under the canonical
/sqlentry point. Both surfaces use the original shared Workbench header row and share the SQL Browser/Dashboard selector. Dashboard keeps its route chrome on one top row: host, tile count, File, active layout menu, dashboard title, View/Edit, Updated, Refresh, and theme. The layout trigger and list use the same button/menu grammar as File with no extra Style label, and Refresh matches the Edit control dimensions. Workbench-only connection, GitHub, keyboard, and user controls are omitted on Dashboard.Surface and Dashboard view mode live in URL query state, surface changes stay in the same tab, and both surfaces project the same active workspace. This also removes the detached Dashboard snapshot/handoff subsystem and preserves state-bound OAuth return routes.
Navigation enters a synchronous inert loading route before awaiting storage. Global shortcuts fail closed unless the ready Workbench route and projected workspace agree. An independent surface generation prevents obsolete Dashboard and Workbench async callbacks from settling into replacement renderers while allowing durable commits to finish and refresh the current surface. Empty Dashboards react to cross-tab creation.
The ClickHouse version probe starts from shared signed-in startup for direct Dashboard routes, after the initial surface is mounted. An authentication rejection can therefore replace the application with Login without a delayed workspace load overwriting Login afterward.
Checklist
npm testpasses (5,056 tests; 100% statements and lines)npm run buildsucceeds (single-filedist/sql.html)src/core/, network insrc/net/, DOM insrc/ui/CHANGELOG.md([Unreleased]) updated--workers=1)Review notes
The active surface and Dashboard mode buttons are intentionally disabled. Surface changes use
pushState; Dashboard View/Edit changes usereplaceState. Cross-workspace navigation immediately replaces and disables the old surface before awaiting storage, while same-workspace history changes render without a repository reload. OAuth callback restoration remains tied to the matching CSRF state and returns to the exact pre-auth/sqlquery route.