Skip to content

feat(ui): add a grid view to installed services - #3868

Merged
MattDHill merged 1 commit into
masterfrom
feat/services-grid-view
Sep 3, 2026
Merged

feat(ui): add a grid view to installed services#3868
MattDHill merged 1 commit into
masterfrom
feat/services-grid-view

Conversation

@MattDHill

Copy link
Copy Markdown
Member

Closes #3740.

The Installed services page has had exactly one layout: a table. That is the right shape for a handful of services and the wrong one for a wall of them — five columns of mostly-repeated text where someone scanning for "is Nextcloud up" wants an icon and a status. This adds a grid of service tiles beside it, on the same layout as the marketplace grid.

The toggle

Two icon buttons in a tui-segmented at the top right of the page pick the renderer. The choice lands in the ui node of patch-db (servicesView) rather than localStorage, alongside registries, startosRegistry and hiddenUpdates, so it follows the user to any browser pointed at the server. Both patchdb-ui-seed.json and patchdb-ui-seed.beta.json seed it.

The field is optional on UIData and defaults in the UI, so a server upgraded from a version without it behaves exactly as the seed does and no start-core migration is needed.

Sorting

Dropping the column headers would drop sort control with them, so the grid carries an A–Z / Z–A toggle, persisted next to the layout. Both renderers import the same byName comparator from a new sorters.ts — lifted out of table.component.ts — so they can never disagree about what sorted-by-name means. Sorting by status stays a table-only affordance, driven by its headers and not remembered.

Mobile is grid-only

Below the app's _mobile breakpoint the table already stopped being a table: .g-table hides thead and the row re-grids itself into an icon-plus-stacked-text block. The columns and click-to-sort headers that justify the list view are gone there, so the toggle was offering a choice between a card and a worse card. The grid is now forced below that breakpoint and the toggle is hidden — a control that cannot change anything is worse than no control — which let ~55 lines of mobile row CSS and the markup it propped up (the grid-area bindings, the desktop-hidden Uptime: label) go.

The layout preference is named desktopLayout to say so; the sort direction is not desktop-scoped and applies everywhere.

Two things worth a look

appearance="floating" resolves to background: var(--tui-background-elevation-1), which this theme defines as the same colour as g-page's own ground, and Taiga force-disables the card shadow in dark mode. Tiles were invisible. The marketplace only escapes this because its shell paints a lighter ground behind the same cards. The tile repoints that token at the surface value the header chrome uses rather than special-casing the page background.

The preference is seeded once from patch-db (take(1)) instead of being reconciled continuously. A write's echo arriving after a newer local change would otherwise reset the view to the older value; writes are also chained so rapid clicks reach the server in click order. The cost is that a second tab's change is not picked up until reload, which seems right for a view preference.

Fixtures

mockPatchData gains five more installed services covering running, health-loading, stopped, health-failure and error states, so the grid is actually a grid under mocks. The mock setDbValue also now applies its patch to mockPatchData.ui and persists it to sessionStorage, and subscribeToPatchDB merges it back — previously mockRevision only pushed a patch to the client stream, so no patch-db write survived a refresh under mocks. That gap applied to hiddenUpdates and startosRegistry too.

🤖 Generated with Claude Code

The Installed services page renders a grid of service tiles as well as the
table, chosen by a toggle in the page header and remembered in the ui node
of patch-db so the choice follows the user across browsers.

Below the mobile breakpoint the table loses its headers and re-grids every
row, so the grid is forced there and the toggle is hidden; the row's mobile
styles go with it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@MattDHill
MattDHill force-pushed the feat/services-grid-view branch from 93faf6b to c816d5d Compare September 3, 2026 02:48
@MattDHill
MattDHill merged commit 73fa2bb into master Sep 3, 2026
17 checks passed
@MattDHill
MattDHill deleted the feat/services-grid-view branch September 3, 2026 03:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

installed services: let the user toggle between list and grid view, with a sort control for grid

2 participants