pco-plan: display settings are per tile again (gear menu), admin keeps the connection

Top bar (template, item-type tint, key color) and the whole show/hide
checklist move from admin config to instanceSchema, grouped in the gear
popover ("Top bar" open, "Show / hide" folded, three columns). They are
browser-side choices stored with the layout, not server state. Admin now
holds only credentials, service type, plan, poll interval and the
ProPresenter follow switch. noteCategories moves to the tile too.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Waters Church
2026-09-10 16:20:46 -04:00
co-authored by Claude Fable 5.1
parent 01eac1bdc4
commit 4c5d7956ab
3 changed files with 31 additions and 27 deletions
+7 -6
View File
@@ -140,12 +140,13 @@ ignored from then on.
description and item notes. When the ProPresenter module is running it
follows that module's live item, highlights the matching plan item, dims
what's done and shows the elapsed vs planned runtime and how far
ahead/behind the service is. Everything is configured in `/admin`:
Planning Center credentials (Personal Access Token app ID + secret, or an
OAuth token), the service type (a list grouped by your Planning Center
folders), an optional pinned plan, the top-bar text (placeholders such as
`{series} • {part} | {serviceType} • {date}`), colors, and a show/hide
checklist for every detail. Tiles only choose their text size.
ahead/behind the service is. Admin config is the connection: Planning
Center credentials (Personal Access Token app ID + secret, or an OAuth
token), the service type (a list grouped by your Planning Center folders)
and an optional pinned plan. Everything about the display is per tile
(gear menu): the top-bar text (placeholders such as
`{series} • {part} | {serviceType} • {date}`), colors, text size, and a
show/hide checklist for every detail.
- **Clock** — a big booth clock; also the smallest possible module and the
reference for module authors.
+9 -11
View File
@@ -2,9 +2,9 @@
The server part reads Planning Center and (optionally) follows the
ProPresenter module's live item; this tile only renders the plan it is
streamed. What is shown is decided server-wide in /admin (moduleApi.config:
show/hide checklist, top-bar template, colors); the tile itself only owns
its text size and auto-scroll. */
streamed. What is shown is this tile's own choice (gear menu →
moduleApi.instanceSettings: show/hide checklist, top-bar template,
colors, text size); /admin only holds the connection settings. */
const REFRESH_SVG = '<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-2.64-6.36"/><path d="M21 3v6h-6"/></svg>';
@@ -43,10 +43,10 @@ export default function create({ root, moduleApi }) {
const listEl = root.querySelector('.pp-list');
const footEl = root.querySelector('.pp-foot');
/** Admin-wide display settings (the show/hide checklist lives there). */
const cfg = () => moduleApi.config || {};
/** This tile's display settings (gear menu) — read fresh on every render. */
const cfg = () => moduleApi.instanceSettings || {};
const on = (key) => cfg()[key] !== false; // unset = shown
const tilePrefs = () => moduleApi.instanceSettings;
const tilePrefs = cfg;
const serverNow = () => Date.now() + skew;
/* ── title-bar controls ─────────────────────────────────────────── */
@@ -270,7 +270,7 @@ export default function create({ root, moduleApi }) {
hint: `${state.serviceType?.name || 'This service type'} has no upcoming or recent plans in Planning Center.`,
};
}
if (!visibleItems().length) return { title: 'Nothing to show', hint: 'Every item is hidden by the PCO Plan settings in Admin.' };
if (!visibleItems().length) return { title: 'Nothing to show', hint: 'Every item is hidden by this tile’s settings (gear menu).' };
return null;
}
@@ -612,10 +612,8 @@ export default function create({ root, moduleApi }) {
root.innerHTML = '';
},
onConfigChange() {
// Display settings changed in Admin: re-render from the new
// moduleApi.config. The server re-inits too and re-sends its state.
lastListKey = '';
render();
// Admin holds only connection settings; the server re-inits and its
// stream re-sends the state. Nothing cached here to refresh.
},
};
}
+15 -10
View File
@@ -1,7 +1,7 @@
{
"id": "pco-plan",
"name": "PCO Plan",
"version": "1.1.0",
"version": "1.2.0",
"description": "Order of service from Planning Center Services, following ProPresenter live",
"client": "client.js",
"server": "server.js",
@@ -12,11 +12,6 @@
"Planning Center credentials": {
"collapsed": "whenSet",
"help": "Create a Personal Access Token at api.planningcenteronline.com (Application ID + Secret), or paste an OAuth 2.0 access token instead. Saved secrets never reach browsers."
},
"Show / hide": {
"collapsed": true,
"columns": 3,
"help": "Untick anything the tiles should not show. Applies to every PCO Plan tile."
}
},
"configSchema": {
@@ -63,7 +58,21 @@
"type": "switch",
"label": "Follow the ProPresenter module's live item to highlight the current plan item and time it",
"default": true
}
},
"instanceGroups": {
"Top bar": {
"collapsed": false
},
"Show / hide": {
"collapsed": true,
"columns": 3,
"help": "Untick anything this tile should not show."
}
},
"instanceSchema": {
"textSize": { "type": "number", "label": "Text size (px)", "default": 14 },
"autoScroll": { "type": "boolean", "label": "Keep the current item in view", "default": true },
"noteCategories": {
"type": "string",
"label": "Item note categories to show (comma-separated, blank = all)",
@@ -114,9 +123,5 @@
"showItemRuntime": { "type": "boolean", "label": "Item runtime (elapsed vs planned)", "default": true, "group": "Show / hide" },
"dimCompleted": { "type": "boolean", "label": "Dim completed items", "default": true, "group": "Show / hide" },
"showLiveFooter": { "type": "boolean", "label": "ProPresenter match line", "default": true, "group": "Show / hide" }
},
"instanceSchema": {
"textSize": { "type": "number", "label": "Text size (px)", "default": 14 },
"autoScroll": { "type": "boolean", "label": "Keep the current item in view", "default": true }
}
}