Shell 1.13.0: the Layouts menu lists the tiles a layout holds but the board is not showing, with a ✕ to remove each #46

Merged
michael merged 1 commits from claude/layouts-menu-not-shown into main 2026-10-11 09:54:07 -04:00
Owner

The problem

A layout keeps every tile it was given, and a tile whose module no longer offers its picker entry keeps its place and draws nothing — deliberately, so a Service timer can wait for PCO Plan. But that tile still holds its grid cells for collision, and nothing anywhere could delete a tile that is not drawn. The Send Message rollout (#40) made this bite: Slack stopped offering send and quick, so every booth layout now carries invisible Send message / Quick replies tiles locking their space.

The change

Layouts menu → Not shown section (public/shell.js, public/style.css), present only while the layout holds a tile the board is not drawing:

  • One row per tile: its title (falling back to the module's name plus the variant id, or the module id when the module is not installed), a muted reason — not offered right now, module disabled, module needs a newer ProdDash, module not installed — and a drawn ✕ (inline SVG, tooltip "Remove", aria-label) that calls the existing removeTile(), which saves the layout and frees the cells, exactly as a drawn tile's ✕ does (no toast there either).
  • The menu stays open after a remove, like the Grid Size stepper and the Alerts fold, so the next row (or none) is seen.
  • The section repaints while the menu is open from reconcileOfferedTiles(), so a row leaves the moment its tile is drawn again (module re-enabled, entry offered again) — and only when the list actually changed, so the 6-second registry recheck does not rebuild rows under the pointer.
  • The toast after loading a named layout now ends "…aren't offered right now; the Layouts menu can remove them".
  • Existing menu classes and CSS variables only (--muted, --danger, --border); the heading matches "Load from server".

GET /api/modules returns inactive (server.js): the installed modules that are not running, as { id, name, reason: 'disabled' | 'incompatible' }. The dashboard's registry only ever held active modules, so without this the client could not tell "module disabled" from "module not installed". Id and name only — none of a module's config travels with it. The reconcile/remount logic is unchanged (registry still holds active manifests only).

Docs and version: package.json 1.12.0 → 1.13.0; README's Layouts-menu paragraph and toast quote; module guide's "Presenting multiple tiles" bullet (the operator can remove a retired entry's tile) and the GET /api/modules line.

A tile that merely waits for its module is listed too, but nothing happens to it unless the operator removes it — the keep-its-place behaviour is untouched.

Testing

Run from a scratch data directory on :24500 with the app's browser preview:

  • Layout with a shown Service Times tile, a shown Slack transcript tile, and four not-shown tiles: Slack send and quick (Slack configured with one channel, so it offers only transcript:…), a Clock tile with Clock disabled in admin, and a tile for a module that does not exist. The menu listed all four with the right reasons; the board showed the dead area to the right.
  • ✕ removed Send message: row gone, menu stayed open, localStorage['proddash:layout'] dropped the tile, tooltip "Remove" shown. Reload kept the removal.
  • Re-enabling Clock from the admin API with the menu open: its row left on the modules-changed event and the Clock tile drew in its kept place.
  • Removing the last two rows made the section disappear with the menu still open. Adding a Clock from the + picker then landed at column 4, row 0 — the cells the removed Send message tile had held.
  • Saved a named layout carrying send/quick and loaded it: toast reads Loaded "Test": 3 tiles, 2 not shown — Send message, Quick replies aren't offered right now; the Layouts menu can remove them with Undo.
  • No browser console errors, no server errors in the log.
  • node tools/layout-roundtrip.test.js, node tools/unbundled.test.js, node tools/update-check.test.js: every check passed.

.claude/launch.json was used with a temporary dev entry and restored from git before committing. No module files touched.

🤖 Generated with Claude Code

## The problem A layout keeps every tile it was given, and a tile whose module no longer offers its picker entry keeps its place and draws nothing — deliberately, so a Service timer can wait for PCO Plan. But that tile still holds its grid cells for collision, and nothing anywhere could delete a tile that is not drawn. The Send Message rollout (#40) made this bite: Slack stopped offering `send` and `quick`, so every booth layout now carries invisible Send message / Quick replies tiles locking their space. ## The change **Layouts menu → Not shown section** (`public/shell.js`, `public/style.css`), present only while the layout holds a tile the board is not drawing: - One row per tile: its title (falling back to the module's name plus the variant id, or the module id when the module is not installed), a muted reason — *not offered right now*, *module disabled*, *module needs a newer ProdDash*, *module not installed* — and a drawn ✕ (inline SVG, tooltip "Remove", `aria-label`) that calls the existing `removeTile()`, which saves the layout and frees the cells, exactly as a drawn tile's ✕ does (no toast there either). - The menu stays open after a remove, like the Grid Size stepper and the Alerts fold, so the next row (or none) is seen. - The section repaints while the menu is open from `reconcileOfferedTiles()`, so a row leaves the moment its tile is drawn again (module re-enabled, entry offered again) — and only when the list actually changed, so the 6-second registry recheck does not rebuild rows under the pointer. - The toast after loading a named layout now ends "…aren't offered right now; the Layouts menu can remove them". - Existing menu classes and CSS variables only (`--muted`, `--danger`, `--border`); the heading matches "Load from server". **`GET /api/modules` returns `inactive`** (`server.js`): the installed modules that are not running, as `{ id, name, reason: 'disabled' | 'incompatible' }`. The dashboard's registry only ever held active modules, so without this the client could not tell "module disabled" from "module not installed". Id and name only — none of a module's config travels with it. The reconcile/remount logic is unchanged (`registry` still holds active manifests only). **Docs and version**: `package.json` 1.12.0 → 1.13.0; README's Layouts-menu paragraph and toast quote; module guide's "Presenting multiple tiles" bullet (the operator can remove a retired entry's tile) and the `GET /api/modules` line. A tile that merely waits for its module is listed too, but nothing happens to it unless the operator removes it — the keep-its-place behaviour is untouched. ## Testing Run from a scratch data directory on :24500 with the app's browser preview: - Layout with a shown Service Times tile, a shown Slack transcript tile, and four not-shown tiles: Slack `send` and `quick` (Slack configured with one channel, so it offers only `transcript:…`), a Clock tile with Clock disabled in admin, and a tile for a module that does not exist. The menu listed all four with the right reasons; the board showed the dead area to the right. - ✕ removed Send message: row gone, menu stayed open, `localStorage['proddash:layout']` dropped the tile, tooltip "Remove" shown. Reload kept the removal. - Re-enabling Clock from the admin API with the menu open: its row left on the `modules-changed` event and the Clock tile drew in its kept place. - Removing the last two rows made the section disappear with the menu still open. Adding a Clock from the + picker then landed at column 4, row 0 — the cells the removed Send message tile had held. - Saved a named layout carrying `send`/`quick` and loaded it: toast reads *Loaded "Test": 3 tiles, 2 not shown — Send message, Quick replies aren't offered right now; the Layouts menu can remove them* with Undo. - No browser console errors, no server errors in the log. - `node tools/layout-roundtrip.test.js`, `node tools/unbundled.test.js`, `node tools/update-check.test.js`: every check passed. `.claude/launch.json` was used with a temporary dev entry and restored from git before committing. No module files touched. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
michael added 1 commit 2026-10-07 11:47:28 -04:00
A tile whose module stopped offering its picker entry — Slack's Send message
and Quick replies since the Send Message module took them over — kept its
place in the layout and drew nothing, as designed, but still held its grid
cells with no control anywhere to let them go: a dead area the operator
could not place anything in.

The Layouts menu now has a Not shown section, present only while the layout
holds such a tile. One row per tile: its title (or the module's name plus
the variant, or the module id when it is not installed), why in a few words
— "not offered right now", "module disabled", "module needs a newer
ProdDash", "module not installed" — and a drawn ✕ with a tooltip that
removes it, saves the layout and frees the cells, leaving the menu open as
the Grid Size stepper and Alerts do. The section repaints while the menu is
open whenever tiles become offered or stop being, and only when the list
changed. A tile that merely waits for its module keeps its place as before.

GET /api/modules also returns `inactive` — the installed modules that are
not running, id, name and reason only — so a dashboard can tell a disabled
module from one that is not installed. The toast after loading a named
layout now says the Layouts menu can remove the tiles it did not show.
README and the module guide updated.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
michael merged commit 1410cbc169 into main 2026-10-11 09:54:07 -04:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: michael/ProdDash#46