Commit Graph
123 Commits
Author SHA1 Message Date
Waters ChurchandClaude Fable 5 444f03938d Timers: LTC timecode via the stage-display websocket
ProPresenter's HTTP API has no timecode route (verified: 21.4 returns
404), but its classic stage-display websocket still answers — so LTC now
comes from a stage layout field labeled "LTC": a zero-dependency RFC6455
client (stage-ws.js) authenticates (new stagePassword admin config),
resolves the LTC-labeled frame's uid from the layout list, and treats any
message carrying that uid as the timecode text. "Receiving" is a 2.5s
staleness heuristic; frozen or placeholder text reads as no-signal. The
HTTP probe stays authoritative when it ever answers (a 404 verdict is
retried once a minute), and the LTC card surfaces the reason when
timecode is unavailable (bad stage password, no LTC field). pp-timers-mock
grows a /stagedisplay websocket with --stage-pwd and --no-ltc-field to
exercise every path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 17:05:23 -04:00
Michael McGary f80790e3a1 Merge pull request #6 from michaelmcgary2008/claude/proddash-app-build-gnwq7y
Unified endpoint config + fullscreen auto-fit and UI polish
2026-08-31 16:59:22 -04:00
Claude 18ab8e92f1 Animated bars, inline ProdCom timestamps, fullscreen auto-fit, dual resize corners
Title bars (tiles and the main menubar, which gains the same notch tab)
now collapse and reopen with a height animation instead of popping. The
menubar's hidden state persists per browser. ProdCom timestamps move
inline to the right of the channel name, keeping their text style; the
clock button toggles just their visibility. New fullscreen button (left
of +): entering fullscreen auto-hides the menubar and auto-fits the
layout — occupied columns stretch proportionally across the width, tiles
whose bottom edge lands within two rows of the viewport bottom stretch
to end exactly at it, small tiles (h ≤ 2) alone in their columns are
exempt, and scrolling is disabled when nothing extends below the fold
(deeper layouts keep natural rows and scrolling). All fullscreen fitting
is visual-only and reverts on exit; editing affordances are parked while
in it. Corner resize indicators now appear only on tile hover, and a
second resize handle on the bottom-left corner resizes from that edge.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNYUv9EyrGSFmCnmH7WYKH
2026-08-31 20:55:28 +00:00
Claude a06bc921ce Unified endpoint config type: one Host/IP : Port control in admin
New configSchema type 'endpoint' declared in the module spec: anything
that points at a device or service on the network must be one endpoint
field, rendered identically for every module in /admin as a joined
Host/IP : Port control and stored/handed to the module server as
{ host, port }. Migrates all three connection modules — ProdCom (was a
full URL field), ProPresenter and Timers (were separate host + port
fields). Legacy stored configs (prodcomUrl / flat host+port) keep
working until the admin form is re-saved, at which point the new shape
replaces them. MODULE-GUIDE documents the type and the presentation
rule: no split host/port fields, and full URLs only for genuine web
addresses.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNYUv9EyrGSFmCnmH7WYKH
2026-08-31 19:33:08 +00:00
Michael McGary 6412dd9524 Merge pull request #3 from michaelmcgary2008/claude/propresenter-timers-module
Timers module: live ProPresenter timers and LTC timecode
2026-08-31 14:48:24 -04:00
Waters ChurchandClaude Fable 5 12245cba93 Timers: present each timer and LTC in the Add-tile picker
Adopt main's new multi-tile contract: the module's server exports
tiles() (answered from the poller's held state, never a fresh upstream
request) listing All timers, one entry per discovered timer, and LTC
timecode. The client branches on moduleApi.variant — solo tiles render
exactly one card with no selection menu, and a solo timer that vanishes
from ProPresenter shows a labeled "Not in ProPresenter" card instead of
erroring (visible even in the compact layout). pp-timers-mock gains
--drop=<uuid,...> to simulate a timer deleted in ProPresenter.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 14:34:59 -04:00
Waters ChurchandClaude Fable 5 a8a382c171 Timers module: live ProPresenter timers and LTC timecode
New propresenter-timers module: polls /v1/timers + /v1/timers/current
(shapes verified against openapi.propresenter.com), probes the
undocumented /v1/timecode/status for LTC and honestly reports
"not available on this ProPresenter" when absent. Per-tile timer/LTC
selection via a Timers ▾ header menu (never-seen timers default on),
responsive auto-sized cards with state-derived colors (the API exposes
no per-timer color), unmistakable overrun. Includes tools/pp-timers-mock.js
for developing without a real ProPresenter.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 14:31:04 -04:00
Michael McGary 40e7679d18 Merge pull request #4 from michaelmcgary2008/claude/proddash-app-build-gnwq7y
Module contract: modules can present multiple tiles
2026-08-31 14:09:29 -04:00
Claude 6211538b34 Module contract: modules can present multiple tiles to the picker
A module may now present a list of tiles instead of a single picker
entry. A server module exports tiles({config, log}) — sync or async,
called on every picker load so the list can be live data (discovered
ProPresenter timers, admin-configured pages); a client-only module can
declare a static tiles array in module.json. The + picker groups the
entries under the module's name; adding one presets that entry's
instance settings, gives the tile the entry's name as its title, and
honors per-entry default/min sizes, all persisted with the layout.
moduleApi.variant tells the instance which entry it was added as. A
throwing or hung tiles() (2 s deadline) falls back to the classic single
entry so a dead upstream can never break the picker; modules without
tiles are byte-for-byte unaffected. Documented in docs/MODULE-GUIDE.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNYUv9EyrGSFmCnmH7WYKH
2026-08-31 17:53:06 +00:00
Michael McGary 404b840154 Merge pull request #2 from michaelmcgary2008/claude/proddash-app-build-gnwq7y
CLAUDE.md: point future sessions at the module guide
2026-08-31 10:31:05 -04:00
Claude c55f1a760c CLAUDE.md: point future sessions at docs/MODULE-GUIDE.md for new modules
The initial build is merged; SPEC.md is no longer the live authority.
New-module work should follow the module guide and its ground rules
(self-contained folder, no shell changes, server-side proxying, scoped
CSS-variable styling, resilience checklist, mocks for testing).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNYUv9EyrGSFmCnmH7WYKH
2026-08-31 14:24:06 +00:00
Michael McGary f0c1aa3920 Merge pull request #1 from michaelmcgary2008/claude/proddash-app-build-gnwq7y
Initial ProdDash implementation: modular dashboard shell with modules
2026-08-31 09:47:01 -04:00
Claude 54338ddf16 Icon topbar, module title-bar controls, hideable title bars, renames
Topbar: the add button is now just + and the layout button a 3-segment
grid icon (two squares + one tall rectangle). Modules no longer build
their own toolbars — moduleApi.header.addButton/addMenu put controls in
the tile's title bar next to the gear/close (menus are fixed-positioned
by the shell so a tile's overflow can't clip them, and everything a
module adds is removed automatically on unmount). Each title bar grows a
notch on its bottom edge that hides/shows the bar, ProdCom-Listener
style; the choice persists with the layout. Modules renamed: ProdCom and
ProPresenter. The ProdCom tile regains the original listener tools as
icon buttons in its title bar: timestamps toggle (clock), A−/A+ text
size, jump-to-latest, and a circle-with-cross clear button, plus the
Channels menu. MODULE-GUIDE documents the header API; README updated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNYUv9EyrGSFmCnmH7WYKH
2026-08-30 16:39:22 +00:00
Claude af46499d92 Flush tile grid + macOS-style seam pill for resizing adjacent tiles
Tiles now sit with zero gap (their 1px borders are the only seam) and the
grid runs edge to edge. Wherever two tiles share a vertical edge, an
invisible strip sits on the seam; hovering reveals a small grab pill
(split-view style) and dragging it moves the shared edge, trading width
between the two tiles. The combined span is preserved, both tiles' min
sizes are honored, and a third tile sitting behind part of the seam
blocks the drag instead of being overlapped. Pills hide during tile
drags/resizes and rebuild for the new geometry on release; seam sizes
persist with the layout. Also fixes cellMetrics treating a 0px grid gap
as falsy and falling back to 10px.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNYUv9EyrGSFmCnmH7WYKH
2026-08-30 16:16:32 +00:00
Claude b14bc4a182 Docs, README, launchers, PWA install
Milestone 7. docs/MODULE-GUIDE.md documents the whole module contract
from an author's point of view — manifest reference, client factory +
moduleApi, server init/routes/health, scoping and resilience rules, a
copy-paste minimal module, and a testing section with the two mocks and a
resilience checklist. README rewritten with run/configure/use
instructions in the prodcom-listener style, plus double-click launchers
for macOS and Windows. PWA: manifest, icons, and a minimal network-first
service worker that never touches /api/*.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNYUv9EyrGSFmCnmH7WYKH
2026-08-30 15:21:05 +00:00
Claude f0c5a0f1a7 Named layouts: save to server, load from any browser, admin management
Milestone 6. Layouts CRUD as JSON under config/layouts/ — GET list,
GET/PUT by name (open to every dashboard), DELETE and rename gated by the
admin passcode. Layout menu grows 'Save as named layout…' and a
'Load from server' list; loading copies the layout into the browser's own
local state, never live-links viewers. Admin page lists, renames and
deletes named layouts. Verified with two isolated browser contexts
holding different layouts simultaneously.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNYUv9EyrGSFmCnmH7WYKH
2026-08-30 15:17:52 +00:00
Claude 0b53616160 Admin page: schema-driven config, enable/disable, live re-init
Milestone 5. GET /api/admin/state, PUT /api/admin/modules/<id>/config and
/enabled persist to config/modules.json and re-init the module in place —
no restart. /api/events (SSE) tells open dashboards about admin changes;
the shell then calls onConfigChange(cfg) on instances that implement it
and cleanly remounts the rest, so tiles reconnect on their own. Admin
page renders forms from each configSchema (text/number/boolean/select/
password), shows module health from handle.health(), and never echoes
password values back to a browser. Optional shared passcode
(config/proddash.json adminPasscode or PRODDASH_PASSCODE) gates the admin
API behind a cookie; the dashboard API stays open.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNYUv9EyrGSFmCnmH7WYKH
2026-08-30 15:16:09 +00:00
Claude 9298b4d142 propresenter-now-next module: Now/Next tile fed by propresenter-core
Milestone 4. propresenter-core copied in unchanged (single home for every
ProPresenter 7/20 quirk). Server part owns the one polling connection and
exposes GET /state plus GET /stream (SSE, change-detected, heartbeated);
health reported for the admin page. Client ports the wall display's
rendering: fill-the-box title fit that never breaks words, tidied titles,
slide meta + progress bar, NEXT list with hidden-row '+ N more' overflow,
playlist name and live chip, all scaled to the tile via a JS-set --unit.
Verified against pp-mock.js including the arrangement-repeat case (the
counter follows core's honest-live-index rule, never X > Y) and
kill-and-restart recovery.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNYUv9EyrGSFmCnmH7WYKH
2026-08-30 15:09:46 +00:00
Claude a549bb065a prodcom-transcript module: ProdCom proxy + live transcript tile
Milestone 3. Server part proxies /prodcom/* (SSE passthrough included) to
the admin-configured ProdCom URL, adding the Bearer key server-side so it
never reaches browsers; reports proxy health for the admin page. Client
ports the prodcom-listener UI into the module contract: history load,
live SSE with in-place updates of in-progress speech, channel colors,
channel visibility toggles + group presets (persisted per tile), hard
channel filter / text size / timestamps as instance settings, auto-scroll
with a jump-to-latest pill. tools/prodcom-mock.js simulates ProdCom
(word-by-word in-progress speech) for testing; verified against it,
including kill-and-restart recovery.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNYUv9EyrGSFmCnmH7WYKH
2026-08-30 15:03:12 +00:00
Claude 3ac70fc44d Module system: discovery, route mounting, client loader, clock module
Milestone 2. Server scans modules/*/module.json, serves module assets at
/modules/<id>/, mounts optional server routes (exact + trailing-/* prefix
patterns) under /api/modules/<id>/ with per-module config from
config/modules.json, and lists enabled manifests at GET /api/modules.
Shell dynamically imports each module's client.js and hands it the
moduleApi (config, instanceSettings, scoped fetch, auto-reconnecting sse,
setStatus). Clock module proves the contract end to end; password-typed
config fields never leave the server.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNYUv9EyrGSFmCnmH7WYKH
2026-08-30 14:55:25 +00:00
Claude 9d9b92e6d9 Shell: server, dashboard grid with drag/resize/remove, localStorage layouts
Milestone 1 of SPEC.md. Zero-dependency Node server serving public/;
12-column tile grid with add (placeholder tile), drag to move, drag to
resize, remove; collision-free placement; layout autosaves to this
browser's localStorage and survives reload.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNYUv9EyrGSFmCnmH7WYKH
2026-08-30 14:50:37 +00:00
Waters ChurchandClaude Fable 5 7ec3637a73 Add build spec: dashboard shell, module system, admin page, initial modules
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-30 10:24:13 -04:00
Waters ChurchandClaude Fable 5 150797389e ProdDash: new project with reference forks of ProdCom Listener and BandLineupDisplay
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-30 10:09:41 -04:00