screentinker/server
ScreenTinker 12fe0e43eb fix(zones): frontend assignment-flow picker + missed devices.js zone_id projection
Follow-up to 73f41c3 (server-side zone_id wiring). With this commit
the zone feature is verified working end-to-end: dashboard zone
picker renders correctly, zone_id saves and persists, the per-row
zone dropdown reflects the saved zone after reload, and a live
player run with computed-style inspection confirmed zone divs and
video elements size correctly within their geometry.

Frontend (device-detail.js, en.js):
- Add-content modal: zone picker slot now renders in all four states
  (has_zones / no_layout / fetch_failed / empty_layout) instead of
  silently vanishing when zones.length === 0. Informational rows
  match form-group styling and tell the user which control to use
  next. Closes the gate-4 symptom where 38-of-42 devices (no layout
  assigned) silently dropped zone_id on every assignment.
- Both /api/layouts/:id fetches (add modal, edit-path) now have
  !res.ok throw guards and surface failures via console.warn instead
  of swallowing them. The add modal additionally exposes the failure
  state to the user via the fetch_failed info row.
- Edit-path zone dropdown: replaced brittle DOM-scraping (reading
  the i18n label text and matching z.id.slice(0,8) against rendered
  meta HTML) with a data-current-zone-id attribute stashed at row
  render from a.zone_id. Removes the i18n-format coupling and gives
  exact UUID match.
- 3 new i18n keys in en.js (other locales fall back).

Server (devices.js):
- The GET /api/devices/:id assignments query had its own ad-hoc
  SELECT projection that was missed during the 73f41c3 site survey.
  Without pi.zone_id in this projection, loadDevice() got assignments
  without zone_id and the edit-path dropdown displayed "No zone"
  after every save+reload even though the DB had the correct value.
  One-line fix: add pi.zone_id, mirroring the ITEM_SELECT change in
  routes/assignments.js. Listed as the 8th site that 73f41c3's
  original survey missed; this commit closes it.

Verification:
- JS parse + en.js ESM load + server module load all clean.
- Live SQL probe: GET /api/devices/:id projection now returns zone_id
  for the test rows (id=31 zone_id=z-sh-1, id=54 zone_id=z-sh-2).
- Browser test by hand: zone picker renders per state, zone_id
  persists, reload shows saved zone, computed styles on rendered
  .zone divs match expected geometry.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 21:26:58 -05:00
..
config fix: log real client IPs through Cloudflare instead of CF edge 2026-05-07 15:26:37 -05:00
db fix(zone-id): restore zone-aware playlist_items wiring (issue #3 follow-up) 2026-05-14 19:20:44 -05:00
lib feat(socket): delivery queue for offline-device emits 2026-05-14 13:06:43 -05:00
middleware feat(email): Microsoft Graph send + alert spam protection + preferences UI 2026-05-12 18:16:40 -05:00
player Fix possible race condition in player auto-connect 2026-05-14 14:54:17 -06:00
routes fix(zones): frontend assignment-flow picker + missed devices.js zone_id projection 2026-05-14 21:26:58 -05:00
services feat(socket): delivery queue for offline-device emits 2026-05-14 13:06:43 -05:00
ws fix(socket): offline debounce + truthful single-device command feedback 2026-05-14 13:11:40 -05:00
.gitignore feat(email): Microsoft Graph send + alert spam protection + preferences UI 2026-05-12 18:16:40 -05:00
config.js feat(socket): delivery queue for offline-device emits 2026-05-14 13:06:43 -05:00
package-lock.json feat(email): Microsoft Graph send + alert spam protection + preferences UI 2026-05-12 18:16:40 -05:00
package.json feat(email): Microsoft Graph send + alert spam protection + preferences UI 2026-05-12 18:16:40 -05:00
server.js fix(landing): replace broken Custom pricing card with enterprise contact form 2026-05-14 13:52:24 -05:00