[cueweb] Add view presets, immersive mode, and split-view workspaces#2449
Conversation
Three web-native replacements for CueGUI window/layout affordances, all sharing the existing localStorage + cross-tab `storage`-event conventions. Saveable view presets (CueGUI "Save Window Settings"): - New components/ui/views-menu.tsx: per-table "Views" dropdown to Save as…, Apply, Rename, Delete named presets capturing column order/visibility, sort, filters, and page size. Persists under cueweb.views.<page> with the active preset under cueweb.views.<page>.active; syncs across tabs. Built-in "Default" entry restores documented defaults and can't be renamed/deleted. - Operates on the TanStack table instance, so it's table-agnostic. Wired into SimpleDataTable (hosts, allocations, shows, layers, frames) and the Jobs data-table toolbar. Immersive (full-screen) mode (CueGUI Toggle Full-Screen): - New app/utils/use_immersive_mode.ts + components/ui/app-shell.tsx: hides the header, sidebar, and status bar so the active table gets the full viewport. - Toggled via `F` / Cmd-Ctrl+Shift+F, the Other menu, and a floating Exit-immersive button. Persists under cueweb.layout.immersive; syncs tabs. Multi-pane split workspaces (CueGUI Window > "Add new window"): - New /split route + components/ui/split-view.tsx: open two pages side-by-side in resizable iframe panes, each with its own URL (/split?left=/jobs&right=/hosts/server-01). Drag/keyboard divider resize (ratio persisted under cueweb.split.ratio); in-pane navigation syncs back to the URL so reload restores both panes. AppShell hides chrome inside panes. Also: register Immersive + Split view in the menu registry (Help search), add Suspense around useSearchParams on /split, and document all three in README + docs/_docs/reference/cueweb.md. Tests: views-menu, immersive_mode, and split_view_utils unit suites (jest green; tsc + lint clean; production build passes).
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (3)
📝 WalkthroughWalkthroughAdds three CueGUI-parity workspace features to CueWeb: (1) a per-page saveable "Views" dropdown that persists table column/sort/filter presets to ChangesSaveable Table View Presets
Immersive Full-Screen Mode
Multi-Pane Split Workspace
Sequence DiagramssequenceDiagram
participant User
participant AppHeader
participant useImmersiveMode
participant AppShell
participant localStorage
User->>AppHeader: click "Immersive (full-screen)"
AppHeader->>useImmersiveMode: toggleImmersive()
useImmersiveMode->>localStorage: write cueweb.layout.immersive=true
useImmersiveMode->>useImmersiveMode: dispatch cueweb:immersive-changed
useImmersiveMode-->>AppShell: immersive=true
AppShell->>AppShell: hideChrome → unmount sidebar/header/statusbar
AppShell->>AppShell: render fixed "Exit immersive" button
User->>AppShell: click "Exit immersive"
AppShell->>useImmersiveMode: setImmersive(false)
useImmersiveMode->>localStorage: write cueweb.layout.immersive=false
useImmersiveMode-->>AppShell: immersive=false
AppShell->>AppShell: restore chrome
sequenceDiagram
participant User
participant SplitView
participant Pane as Pane (iframe)
participant split_view_utils
participant localStorage
User->>SplitView: navigate to /split?left=/jobs&right=/hosts
SplitView->>split_view_utils: sanitizePanePath(left), sanitizePanePath(right)
SplitView->>localStorage: readRatio()
localStorage-->>SplitView: persisted ratio
SplitView->>Pane: render left iframe src=/jobs
SplitView->>Pane: render right iframe src=/hosts
Pane-->>SplitView: onNavigate(newPath) on iframe load
SplitView->>SplitView: router.replace({left:newPath})
User->>SplitView: drag divider
SplitView->>split_view_utils: clampRatio(newRatio)
SplitView->>localStorage: writeRatio(clampedRatio)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@cueweb/app/utils/use_immersive_mode.ts`:
- Around line 71-94: The same-tab synchronization re-reads from localStorage
every time instead of propagating the actual value being set, which causes
reliability issues when storage writes fail. Modify the CustomEvent dispatched
in the setImmersive function to include the value being set as part of the event
detail. Then update the handler function (which listens for CHANGE_EVENT) to
extract and use that value from the event detail instead of calling
readImmersiveFromStorage(). Keep the storageHandler as is to continue handling
cross-tab synchronization through actual storage reads.
In `@cueweb/components/ui/views-menu.tsx`:
- Around line 379-420: The rename and delete buttons (with openRenameDialog and
handleDelete callbacks) are nested as interactive elements within the
DropdownMenuItem component, making them difficult to access via keyboard
navigation. Refactor this structure by promoting the rename and delete actions
to first-class menu items instead of nesting them within the view row. You can
achieve this by either creating separate DropdownMenuItem entries for each
view's rename and delete actions, or by implementing a submenu pattern. This
will allow keyboard-only users to navigate and activate these actions using
standard menu keyboard navigation patterns.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 147e282a-1802-4a83-aa81-28bdb45645b2
📒 Files selected for processing (22)
cueweb/README.mdcueweb/app/__tests__/components/views-menu.test.tscueweb/app/__tests__/utils/immersive_mode.test.tscueweb/app/__tests__/utils/split_view_utils.test.tscueweb/app/allocations/page.tsxcueweb/app/hosts/page.tsxcueweb/app/jobs/[job-name]/page.tsxcueweb/app/jobs/data-table.tsxcueweb/app/layout.tsxcueweb/app/shows/shows-client.tsxcueweb/app/split/page.tsxcueweb/app/utils/split_view_utils.tscueweb/app/utils/use_immersive_mode.tscueweb/app/utils/use_menu_registry.tscueweb/components/ui/app-header.tsxcueweb/components/ui/app-shell.tsxcueweb/components/ui/job-details-inline.tsxcueweb/components/ui/shortcuts-overlay.tsxcueweb/components/ui/simple-data-table.tsxcueweb/components/ui/split-view.tsxcueweb/components/ui/views-menu.tsxdocs/_docs/reference/cueweb.md
- use_immersive_mode: carry toggled value on the CHANGE_EVENT detail (and flip in-memory state) so a failed localStorage write no longer reverts the toggle; cross-tab still reads storage. Adds a regression test. - views-menu: make each saved view a submenu (Apply / Rename / Delete as real menu items) so rename/delete are keyboard-navigable, not nested buttons.
….com/ramonfigueiredo/OpenCue into cueweb/workspace-layout-enhancements
Related Issues
Summarize your change.
[cueweb] Add view presets, immersive mode, and split-view workspaces
Three web-native replacements for CueGUI window/layout affordances, all sharing the existing localStorage + cross-tab
storage-event conventions.Saveable view presets (CueGUI "Save Window Settings"):
Immersive (full-screen) mode (CueGUI Toggle Full-Screen):
F/ Cmd-Ctrl+Shift+F, the Other menu, and a floating Exit-immersive button. Persists under cueweb.layout.immersive; syncs tabs.Multi-pane split workspaces (CueGUI Window > "Add new window"):
New /split route + components/ui/split-view.tsx: open two pages side-by-side in resizable iframe panes, each with its own URL (/split?left=/jobs&right=/hosts/server-01). Drag/keyboard divider resize (ratio persisted under cueweb.split.ratio); in-pane navigation syncs back to the URL so reload restores both panes. AppShell hides chrome inside panes.
Also: register Immersive + Split view in the menu registry (Help search), add Suspense around useSearchParams on /split, and document all three in README + docs/_docs/reference/cueweb.md.
Tests: views-menu, immersive_mode, and split_view_utils unit suites (jest green; tsc + lint clean; production build passes).
LLM usage disclosure
Parts of this solution's implementation were developed with assistance from Claude Opus.