From f837e5796903904dd010a9b3a45185036cae8d66 Mon Sep 17 00:00:00 2001 From: Zac Date: Sat, 30 May 2026 14:59:59 +0000 Subject: [PATCH] feat(web-ui): add Playout tile to home screen Fetches /playout/channels separately and degrades silently when the endpoint or schema is absent. Co-Authored-By: Claude Opus 4.7 --- services/web-ui/public/screens-home.jsx | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/services/web-ui/public/screens-home.jsx b/services/web-ui/public/screens-home.jsx index fb1b71a..50fe5f7 100644 --- a/services/web-ui/public/screens-home.jsx +++ b/services/web-ui/public/screens-home.jsx @@ -23,12 +23,19 @@ function Home({ navigate }) { // Pull live counts so the tile subtitles ("34 assets", "0 live", "3 running") // reflect what's actually in the DB right now, not a stale boot-time cache. const [cards, setCards] = React.useState({}); + // Playout has no /metrics/home card yet (and the playout schema may not be + // migrated on every install); fetch /playout/channels separately and degrade + // silently — the tile just shows "No channels" if the endpoint isn't there. + const [playoutChannels, setPlayoutChannels] = React.useState(null); React.useEffect(() => { let cancelled = false; const load = () => { window.ZAMPP_API.fetch('/metrics/home?hours=1') .then(d => { if (!cancelled) setCards(d?.cards || {}); }) .catch(() => {}); + window.ZAMPP_API.fetch('/playout/channels') + .then(d => { if (!cancelled) setPlayoutChannels(Array.isArray(d) ? d : []); }) + .catch(() => { if (!cancelled) setPlayoutChannels([]); }); }; load(); const t = setInterval(load, 30_000); @@ -63,6 +70,21 @@ function Home({ navigate }) { : totalRecs + ' configured', desc: 'SDI · SRT · RTMP ingest. Start, stop, schedule.', }, + { + id: 'playout', + label: 'Playout', + icon: 'monitor', + tone: 'accent', + sub: (() => { + if (playoutChannels === null) return '·'; + const total = playoutChannels.length; + const onAir = playoutChannels.filter(c => c.status === 'running').length; + if (total === 0) return 'No channels'; + if (onAir > 0) return onAir + ' on air · ' + total + ' channel' + (total === 1 ? '' : 's'); + return total + ' channel' + (total === 1 ? '' : 's'); + })(), + desc: 'Master Control. SDI · NDI · SRT · RTMP playout, playlists, as-run.', + }, { id: '__premiere', label: 'Premiere panel',