From 6c0aee5abf610ebc9b723f6b1c049dc60f26b67a Mon Sep 17 00:00:00 2001 From: Waters Church Date: Thu, 24 Sep 2026 15:15:34 -0400 Subject: [PATCH] Teams tile: one Colors group, no Positions switches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Colors and Status colors were two groups asking the same question, so they are one: team header, the tints and the three status colours together. The Positions switches go entirely — the team switches already decide what a tile shows, and "Group by position" still arranges what is left. With them go GET /positions and positionOptions(). Two rules the tile was breaking on the way past: a gear group may carry no `help` (rule 5), and only hide-toggles belong in Show (rule 8) — so the group blurbs are gone and the Columns picker sits loose at the top beside the team switches. Co-Authored-By: Claude Opus 5 --- modules/pco-plan/module.json | 90 ++++++++++++-------------------- modules/pco-plan/server.js | 32 ++---------- modules/pco-plan/teams-client.js | 2 - 3 files changed, 38 insertions(+), 86 deletions(-) diff --git a/modules/pco-plan/module.json b/modules/pco-plan/module.json index aaecab2..6c0d9f6 100644 --- a/modules/pco-plan/module.json +++ b/modules/pco-plan/module.json @@ -411,21 +411,35 @@ "h": 2 }, "instanceSchema": { + "columns": { + "type": "select", + "label": "Columns", + "default": "auto", + "options": [ + { + "value": "auto", + "label": "Fit the tile" + }, + { + "value": "1", + "label": "One" + }, + { + "value": "2", + "label": "Two" + }, + { + "value": "3", + "label": "Three" + } + ] + }, "teams": { "type": "multiselect", "label": "Teams", - "group": "Teams", - "optionsRoute": "/teams", - "columns": 1, - "allByDefault": true - }, - "positions": { - "type": "multiselect", - "label": "Positions", - "group": "Positions", - "optionsRoute": "/positions", "columns": 2, - "allByDefault": true + "allByDefault": true, + "optionsRoute": "/teams" }, "headerTemplate": { "type": "template", @@ -484,12 +498,6 @@ "default": false, "group": "Colors" }, - "headerGradient": { - "type": "boolean", - "label": "Header fade", - "default": true, - "group": "Colors" - }, "tintRows": { "type": "boolean", "label": "Tint rows too", @@ -497,23 +505,29 @@ "group": "Colors", "showWhen": "tintTeams" }, + "headerGradient": { + "type": "boolean", + "label": "Header fade", + "default": true, + "group": "Colors" + }, "confirmedColor": { "type": "color", "label": "Confirmed", "default": "#2ee59a", - "group": "Status colors" + "group": "Colors" }, "unconfirmedColor": { "type": "color", "label": "Unconfirmed", "default": "#f0b429", - "group": "Status colors" + "group": "Colors" }, "declinedColor": { "type": "color", "label": "Declined", "default": "#f4433c", - "group": "Status colors" + "group": "Colors" }, "showTopBar": { "type": "boolean", @@ -580,52 +594,16 @@ "label": "Teams with nobody", "default": false, "group": "Show" - }, - "columns": { - "type": "select", - "label": "Columns", - "default": "auto", - "group": "Show", - "options": [ - { - "value": "auto", - "label": "Fit the tile" - }, - { - "value": "1", - "label": "One" - }, - { - "value": "2", - "label": "Two" - }, - { - "value": "3", - "label": "Three" - } - ] } }, "instanceGroups": { "Top bar": { "collapsed": false }, - "Teams": { - "collapsed": true, - "help": "Untick a team to leave it out of this tile." - }, - "Positions": { - "collapsed": true, - "help": "Untick a position to leave it out. Positions follow the teams above." - }, "Colors": { "collapsed": false, "columns": 2 }, - "Status colors": { - "collapsed": true, - "columns": 3 - }, "Show": { "collapsed": true, "columns": 2 diff --git a/modules/pco-plan/server.js b/modules/pco-plan/server.js index 27ad737..d1136bd 100644 --- a/modules/pco-plan/server.js +++ b/modules/pco-plan/server.js @@ -18,7 +18,6 @@ * GET /note-categories → { options } for a tile's "Item notes" categories: * the service type's item note categories, by name * GET /teams → { options } for a Teams tile's "Teams" switches - * GET /positions → { options } for a Teams tile's "Positions" switches * GET /team-avatar/ → that person's photo, proxied + cached * GET /timers → snapshot for the Timers module (guide: "Offering * GET /timers/stream → SSE, `timers` events timers to the Timers module") @@ -821,24 +820,6 @@ module.exports = { return { options: state.teams.map((t) => ({ value: t.id, label: t.name })) }; } - /** - * Options for a Teams tile's "Positions" switches. Positions are named, - * not numbered, in Planning Center, so the name is the value; the team - * name groups them so two "Leader" positions stay apart in the list. - */ - function positionOptions() { - const seen = new Set(); - const options = []; - for (const team of state.teams) { - for (const m of team.members) { - const value = m.position || '(no position)'; - if (seen.has(value)) continue; - seen.add(value); - options.push({ value, label: value, group: team.name }); - } - } - return { options }; - } async function readPlan() { if (!pco.configured || !serviceTypeId) return; @@ -1589,7 +1570,6 @@ module.exports = { documentOptions, noteCategoryOptions, teamOptions, - positionOptions, avatarUrlFor: (id) => teamPhotos.get(String(id)) || "", }; @@ -1684,19 +1664,15 @@ module.exports = { }, /** - * Options for a Teams tile's "Teams" and "Positions" switches. Like the - * note categories, always a 200 with a list: an empty one simply means - * there is nothing scheduled to choose from yet, which the gear window - * says plainly. + * Options for a Teams tile's "Teams" switches. Like the note + * categories, always a 200 with a list: an empty one simply means there + * is nothing scheduled to choose from yet, which the gear window says + * plainly. */ 'GET /teams': (req, res) => { json(res, 200, current ? current.teamOptions() : { options: [] }); }, - 'GET /positions': (req, res) => { - json(res, 200, current ? current.positionOptions() : { options: [] }); - }, - /** * A scheduled person's photo, proxied from Planning Center and cached. * The tile asks by plan-person id and never sees the CDN URL; an id the diff --git a/modules/pco-plan/teams-client.js b/modules/pco-plan/teams-client.js index a6e3c54..a1fa702 100644 --- a/modules/pco-plan/teams-client.js +++ b/modules/pco-plan/teams-client.js @@ -94,12 +94,10 @@ export default function createTeams({ root, moduleApi }) { function visibleTeams() { const teams = Array.isArray(state?.teams) ? state.teams : []; const wantTeams = chosen('teams'); - const wantPositions = chosen('positions'); const out = []; for (const team of teams) { if (wantTeams && !wantTeams.includes(team.id)) continue; const members = team.members.filter((m) => { - if (wantPositions && !wantPositions.includes(m.position || '(no position)')) return false; if (m.status === 'declined' && !on('showDeclined')) return false; if (m.status === 'unconfirmed' && !on('showUnconfirmed')) return false; return true;