Teams tile: one Colors group, no Positions switches

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 <noreply@anthropic.com>
This commit is contained in:
Waters Church
2026-09-24 15:15:34 -04:00
co-authored by Claude Opus 5
parent 6d0f8828c1
commit 6c0aee5abf
3 changed files with 38 additions and 86 deletions
+4 -28
View File
@@ -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/<planPersonId> → 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