Add a global, colour-coded team selector to the nav
state.js's currentTeam() was hard-coded to teams[0] and never really meant "the team currently selected" — team.js's settings page and queue.js's filter chips each kept their own separate, unsynchronized notion of "which team" instead, so picking one on one page had no effect on the other. Replaces both with a single state.selectedTeamID, set only through the new setSelectedTeam (persisted in localStorage, unlike the queue's old per-tab sessionStorage filter) and broadcast to listeners via onTeamChange. A new teamselector.js control — a coloured dot plus the team's name, or "All teams" — sits at the top of both the desktop sidebar and the mobile topbar, opening the existing bottom-sheet menu to switch. Shown only once someone is in more than one team, matching every other team-aware control in this app. Colours come from a new teamColorClass() in format.js, hashing a team's id into the six-colour rc1..rc6 palette already used for the rota's per-person chips, so no schema or API change is needed. The queue's team filter chips pick up the same colours.
This commit is contained in:
@@ -19,7 +19,7 @@
|
||||
|
||||
import * as api from './api.js';
|
||||
import { h, clear, spinner, confirm, icon, openSheet, closeSheet, menuCard, badge, labelChip, ssoBadge, SSO_MANAGED } from './ui.js';
|
||||
import { state, currentTeam, users as allUsers, myID } from './state.js';
|
||||
import { state, currentTeam, onTeamChange, users as allUsers, myID } from './state.js';
|
||||
import { isoDate, addDays, mondayOf, isoWeek, initial, ago, when, duration } from './format.js';
|
||||
|
||||
const view = () => document.getElementById('view-team');
|
||||
@@ -41,6 +41,9 @@ export const TABS = [
|
||||
{ tab: 'deadman', path: '/team/deadman', label: 'Switches', title: 'Dead man’s switches' },
|
||||
];
|
||||
|
||||
// Cached from currentTeam() on each refresh(), for the many actions below
|
||||
// (assignSchedule, addTeamMember, ...) that need a plain id rather than a
|
||||
// round trip through state.
|
||||
let teamID = null;
|
||||
// Which sub-section is open. Remembered rather than passed, because the poll
|
||||
// loop calls refresh() with no route.
|
||||
@@ -49,6 +52,13 @@ let data = null; // { team, ... }; which fields are present varies by tab
|
||||
let error = null;
|
||||
let freshKey = null; // an integration key, shown once, until the view is left
|
||||
|
||||
// The global team selector is what changes which team this page shows now;
|
||||
// re-fetch under whichever sub-section is open when it fires.
|
||||
onTeamChange(() => {
|
||||
data = null;
|
||||
refresh();
|
||||
});
|
||||
|
||||
export function show(route) {
|
||||
const next = route?.tab ?? null;
|
||||
// A different sub-section wants different data, so the old answer goes
|
||||
@@ -61,13 +71,8 @@ export function show(route) {
|
||||
refresh();
|
||||
}
|
||||
|
||||
function selectedTeam() {
|
||||
const teams = state.teams || [];
|
||||
return teams.find((t) => t.id === teamID) || currentTeam();
|
||||
}
|
||||
|
||||
export async function refresh() {
|
||||
const team = selectedTeam();
|
||||
const team = currentTeam();
|
||||
if (!team) {
|
||||
data = null;
|
||||
render();
|
||||
@@ -172,24 +177,12 @@ function subnav() {
|
||||
})));
|
||||
}
|
||||
|
||||
// Only shown to somebody in more than one team, like the queue's filter chips.
|
||||
// It is above the sections rather than inside one because it changes the
|
||||
// subject of all six.
|
||||
// Names which team's settings the six sections below belong to. It used to be
|
||||
// a picker of its own for somebody in more than one team; that job now belongs
|
||||
// to the global team selector in the nav, which is what onTeamChange above
|
||||
// reacts to.
|
||||
function teamPicker() {
|
||||
if ((state.teams || []).length < 2) {
|
||||
return h('div', { class: 'card' }, h('h2', { text: data.team.name }));
|
||||
}
|
||||
const select = h('select', { class: 'team-picker' },
|
||||
...state.teams.map((t) => h('option', {
|
||||
value: String(t.id), text: t.name, selected: t.id === teamID,
|
||||
})));
|
||||
select.addEventListener('change', () => {
|
||||
teamID = Number(select.value);
|
||||
data = null;
|
||||
freshKey = null;
|
||||
refresh();
|
||||
});
|
||||
return h('div', { class: 'card' }, h('h2', { text: 'Team' }), select);
|
||||
return h('div', { class: 'card' }, h('h2', { text: data.team.name }));
|
||||
}
|
||||
|
||||
// --- overview --------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user