8000 feat(ui): add full-row expandable jobs toggle with localStorage persistence by janzak-dev · Pull Request #1570 · google/xmc · GitHub
[go: up one dir, main page]

Skip to content
< 8000 link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/app-install-banner-partial-7b5673925ff36444.js" fetchpriority="low" />

feat(ui): add full-row expandable jobs toggle with localStorage persistence - #1570

Merged
janzak-dev merged 6 commits into
mainfrom
feat/expandable-jobs-full-width-takeover
Nov 4, 2026
Merged

janzak-dev merged 6 commits into
mainfrom
feat/expandable-jobs-full-width-takeover

Conversation

@janzak-dev
@janzak-dev janzak-dev commented Nov 4, 2026 •
Copy link
Copy Markdown
Collaborator

Takes over #1567 by @VLukiantsev.

Unnamed.screencast.2.webm

Summary

Adds a "View in full width" / "Exit full width" toggle button to the queue jobs card on the /resources (Resource Observability Dashboard) page that expands the jobs table into a full-width top row with the cluster queues list stacked below (flex-direction: column-reverse, gap: 24px, unmounted resize divider), and persists the user's layout preference in window.localStorage (xmc-jobs-full-width) upon toggling.

Motivation & Context

Wide multi-column job rows in the side-by-side split view can feel cramped, while hiding the cluster queues list altogether prevents inspecting queues alongside jobs. Expanding the jobs card to a full-width top row with the cluster queues list stacked below keeps both dashboard panes visible and restores the preferred layout on future visits via localStorage persistence. This approach supersedes the closed earlier prototype in #1544 (which hid the queue list, did not persist across visits, and reset on search).

Intentional Architectural Adjustments Relative to #1567

While preserving 100% of #1567's visual design and user interaction flow, we intentionally made the following architectural refinements:

  1. Switched persistence from document.cookie (xmc_jobs_full_width) to window.localStorage (xmc-jobs-full-width): Done on purpose to align with existing XMC UI client-preference storage conventions (xmc-* keys in StatusMessageFilterService) and avoid attaching a purely client-side layout flag to HTTP Cookie headers on every /api/ and /v1/ request.
  2. Decoupled QueueJobsTable via a <ng-content select="[headerActions]"> projection slot: Done on purpose for Single Responsibility Principle (SRP). Instead of coupling dashboard-specific showFullWidthToggle and isFullWidth inputs onto the shared side_panel/contents/queue_jobs_table component, QueueJobsTable exposes a generic [headerActions] slot in .title-row (queue_jobs_table.ts remains completely untouched relative to main) and ResourceDashboard owns the toggle button, state, and styles directly.
  3. Intentionally retained flex-direction: column-reverse from feat(ui): add full-row expandable jobs toggle with cookie persistence #1567: Kept on purpose so expanding immediately places the jobs table at the top of the split area while keeping both QueueJobsTable and QueueListComponent mounted in place without DOM re-creation, pagination state resets, or redundant /jobs refetches.

Key Changes

  • Queue Jobs Table (cmd/ui/app/side_panel/contents/queue_jobs_table/):
    • Added a <ng-content select="[headerActions]" /> projection slot inside .title-row (queue_jobs_table.ng.html and flex alignment in queue_jobs_table.scss) without adding layout-specific inputs or logic to QueueJobsTable.
    • Extended QueueJobsTableHarness (getHeaderActionTexts()) and queue_jobs_table_test.ts to verify empty default rendering and selective [headerActions] projection.
  • LocalStorage Layout Preference (cmd/ui/app/resource_dashboard/jobs_layout_preference.ts):
    • Added readJobsFullWidthPreference and writeJobsFullWidthPreference for reading and persisting xmc-jobs-full-width in window.localStorage (with try/catch resilience for restricted storage contexts) and 1-to-1 unit tests in jobs_layout_preference_test.ts.
  • Resource Dashboard (cmd/ui/app/resource_dashboard/):
    • Projected the pill-shaped [headerActions] toggle button ("View in full width" / fullscreen icon ↔ filled primary "Exit full width" / fullscreen_exit icon, with explicit :focus-visible offset outline) directly from ResourceDashboard into <xmc-queue-jobs-table>.
    • Initialized isJobsFullWidth from readJobsFullWidthPreference() and persisted user toggles via toggleJobsFullWidth().
    • Made leftPaneFlex and rightPaneFlex return null when isJobsFullWidth() is true, wrapped <xmc-rod-resize-divider> in @if (!isJobsFullWidth()) so the divider and its focus stop unmount in stacked mode while preserving splitRatio, and updated .rod-split-container.full-width to reset horizontal pane paddings and apply gap: 24px.
    • Extended ResourceDashboardHarness and resource_dashboard_test.ts to verify [headerActions] projection, button icon/label/active state transitions, full-row vertical stacking, custom split ratio preservation and divider unmount/remount across full-width round-trips, localStorage persistence and hydration, and state preservation across Smart Resource Finder queries and tab switches.
  • Playwright Visual Baselines (cmd/ui/screenshot_tests/resource_dashboard/):
    • Regenerated resource-dashboard-initial-chromium-linux.png and resource-dashboard-queue-selected-chromium-linux.png baselines to reflect the toggle button in the jobs card header, and added should match baseline screenshot in full-width jobs mode (resource-dashboard-full-width-chromium-linux.png).

Assumptions

  • Visual jobs-on-top stacking via flex-direction: column-reverse — intentionally retained from PR feat(ui): add full-row expandable jobs toggle with cookie persistence #1567 so QueueJobsTable and QueueListComponent remain mounted in place without DOM re-creation or refetching — keyboard Tab focus follows DOM order (queue cards below before jobs card above); if matching DOM and visual order is prioritized later, the queue list pane can be moved via template outlet.
  • Full-width preference preserved across Smart Resource Finder searches and tab switches — assumed a persisted layout preference should remain sticky until the user explicitly clicks "Exit full width" — if searches should auto-return to side-by-side split view, onFindMatchingQueues would need to reset isJobsFullWidth.

Verification & Testing

Automated Tests

  • Commands Executed: ./.githooks/pre-commit && cd cmd/ui && npm run format:check && npm run lint && npm test -- --watch=false --browsers=ChromeHeadlessNoSandbox && npm run build && npm run test:screenshot
  • Coverage & Test Status: All 726 Angular UI unit tests pass (including 1-to-1 unit tests for localStorage persistence and error resilience, [headerActions] slot projection, toggle interactions, and full-row dashboard stacking + divider/split-ratio round-trip), Prettier and ESLint checks pass with 0 warnings/errors, production bundle build succeeds, and all 11 Playwright visual screenshot tests pass.

Live Deployment & Manual Testing

  • Deployment Target: Live GKE Development Environment via tools/dev_env/dev_env.py gke-upgrade
  • Cluster Health: Verified via deploy/ctk_v2/verify_xmc.py — all 5 sections ✅ PASS (13/13 Kubernetes pods freshly rolled out 1/1 Running with 0 restarts, services, Gateway & HTTPRoutes, TLS certificates, and GKE Log Monitor)
  • Manual Test Scenarios Executed:
    1. End-to-End GKE Upgrade & Live Bundle Verification:
      • Action: Upgraded all 9 XMC microservice OCI images and Helm release from HEAD (8b4ee8ad1), rolled out deployment/ui-deployment, verified /resources returns HTTP/2 200, and confirmed the live compiled Nginx bundle serves the xmc-jobs-full-width localStorage layout preference and [headerActions] full-width toggle button.
      • Result: ui-deployment rolled out cleanly (1/1 Running); /resources serves the "View in full width" toggle button, full-row vertical stacking, and localStorage persistence.
Live Execution Output / Logs
=== Structured Verification Summary ===
✅ PASS | 1. Kubernetes Pods         | 13/13 Ready (0 restarts)
✅ PASS | 2. Kubernetes Services     | Core ClusterIP services present
✅ PASS | 3. Gateway & HTTPRoutes    | api-route, dashboard-route, grpc-route, health-route, rod-route, ui-route bound
✅ PASS | 4. TLS Certificates        | validator-ca Ready=True
✅ PASS | 5. Log Monitor (GKE)       | Runs as GKE Deployment; Cloud Run check skipped
=======================================

Related Issues / Bugs

N/A

TAG=agy
CONV=23cac48a-f5e0-4dc9-b0fa-c46ba04c7f87

Add a "View in full width" / "Exit full width" toggle button to the
queue jobs table on the Resource Observability Dashboard (/resources)
that stacks the cluster queues list and jobs table into full-width rows
instead of hiding the queue list, and persists the layout preference in
the xmc_jobs_full_width browser cookie.

TAG=agy
CONV=c0655880-9a67-4bdd-aaa7-bc8e8631798f
@gemini-code-assist gemini-code-assist Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a full-width layout preference for the jobs table in the Resource Dashboard, allowing users to toggle between a side-by-side split view and a vertically stacked full-width view, with the preference persisted in document cookies. The review feedback suggests several improvements: making the cookie parsing logic more robust against spaces around the '=' character, resolving layout misalignment and hiding the inactive resize divider in full-width mode, and optimizing the Angular effect to prevent a redundant cookie write on initialization.

TAG=agy
CONV=23cac48a-f5e0-4dc9-b0fa-c46ba04c7f87
…hboard

Restore `resource_dashboard.screenshot.spec.ts` and append a single
full-width visual regression test using state-based assertions,
regenerate the Resource Dashboard Playwright baseline PNG snapshots
(`initial`, `queue-selected`, and `full-width`), format TypeScript
files with Prettier, and verify resize divider remounting and split
ratio preservation when exiting full-width mode.

Comment link: #1570 (comment)
Comment link: #1570 (comment)

TAG=agy
CONV=23cac48a-f5e0-4dc9-b0fa-c46ba04c7f87
Pin `xmc-resource-dashboard` height (`1160px`) and increase the viewport
height (`1300px`) in the full-width Playwright screenshot test, matching
the cross-environment bounding-box pattern used in sibling screenshot
specs so 1px font line-height differences between gLinux and Ubuntu CI
runners do not mismatch canvas dimensions.

TAG=agy
CONV=23cac48a-f5e0-4dc9-b0fa-c46ba04c7f87
Add an explicit `&:focus-visible` outline (`2px solid #1a73e8` with
`outline-offset: 2px`) on `button.full-width-toggle-btn` so keyboard
focus remains clearly visible in both the outlined default state and
the `#1a73e8`-filled `.active` state (WCAG 2.4.7 Focus Visible).

TAG=agy
CONV=23cac48a-f5e0-4dc9-b0fa-c46ba04c7f87
@janzak-dev janzak-dev changed the title feat(ui): add full-row expandable jobs toggle with cookie persistence feat(ui): add full-row expandable jobs toggle with localStorage persistence Nov 4, 2026
…ect header actions

Intentionally refines two internal design choices from #
8000
1567 while preserving
identical visual layout and user behavior:
- Replace `document.cookie` (`xmc_jobs_full_width`) with `window.localStorage`
  (`xmc-jobs-full-width`) to align with existing XMC frontend preference
  conventions (`StatusMessageFilterService`) and avoid sending a client-only
  layout flag in HTTP `Cookie` headers on API requests.
- Replace `showFullWidthToggle` / `isFullWidth` inputs on `QueueJobsTable` with
  a generic `<ng-content select="[headerActions]" />` slot in `.title-row` so
  `QueueJobsTable` stays layout-agnostic and `ResourceDashboard` owns the
  full-width toggle button directly.

TAG=agy
CONV=23cac48a-f5e0-4dc9-b0fa-c46ba04c7f87
@janzak-dev
janzak-dev marked this pull request as ready for review November 4, 2026 11:41
@github-actions
github-actions Bot requested a review from AntonTyb November 4, 2026 11:41
@janzak-dev
janzak-dev enabled auto-merge November 4, 2026 13:35
@janzak-dev janzak-dev added the priority::2-high top of mind. should not wait. label Nov 4, 2026
@janzak-dev
janzak-dev added this pull request to the merge queue Nov 4, 2026
Merged via the queue into main with commit 9e23436 Nov 4, 2026
16 checks passed
@janzak-dev
janzak-dev deleted the feat/expandable-jobs-full-width-takeover branch November 5, 2026 09:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

priority::2-high top of mind. should not wait.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

0