Band Lineup 1.11.1: Sync replaces last week's hand-placed people #50
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"id": "band-lineup",
|
"id": "band-lineup",
|
||||||
"name": "Band Lineup",
|
"name": "Band Lineup",
|
||||||
"version": "1.11.0",
|
"version": "1.11.1",
|
||||||
"proddash": ">=1.4.0",
|
"proddash": ">=1.4.0",
|
||||||
"description": "Stage lineup photos with mic/pack labels — a drag-in photo library plus optional Planning Center auto-fill",
|
"description": "Stage lineup photos with mic/pack labels — a drag-in photo library plus optional Planning Center auto-fill",
|
||||||
"client": "client.js",
|
"client": "client.js",
|
||||||
|
|||||||
@@ -247,7 +247,7 @@ module.exports = {
|
|||||||
return {
|
return {
|
||||||
configured: pco.configured, serviceTypeSet: Boolean(serviceTypeId),
|
configured: pco.configured, serviceTypeSet: Boolean(serviceTypeId),
|
||||||
reachable: false, lastError: '', lastFetched: 0, columns,
|
reachable: false, lastError: '', lastFetched: 0, columns,
|
||||||
plan: null,
|
plan: settings.lastPlan || null, // the last synced plan, so hand placements after a restart stamp right
|
||||||
slots: effectiveSlots().map((label, index) => ({ index, label, person: null })),
|
slots: effectiveSlots().map((label, index) => ({ index, label, person: null })),
|
||||||
library: [], choir: choirOn,
|
library: [], choir: choirOn,
|
||||||
};
|
};
|
||||||
@@ -493,7 +493,8 @@ module.exports = {
|
|||||||
await syncPhotos(); // import the photo source (Drive folder or local path) on every sync
|
await syncPhotos(); // import the photo source (Drive folder or local path) on every sync
|
||||||
if (pco.configured && serviceTypeId) {
|
if (pco.configured && serviceTypeId) {
|
||||||
const plan = pickPlan(await listPlans(serviceTypeId));
|
const plan = pickPlan(await listPlans(serviceTypeId));
|
||||||
latest.plan = plan ? { title: plan.title, dates: plan.dates } : null;
|
latest.plan = plan ? { id: String(plan.id), title: plan.title, dates: plan.dates } : null;
|
||||||
|
if (plan) { settings.lastPlan = latest.plan; saveSettings(); }
|
||||||
if (!plan) { latest.reachable = true; latest.lastError = 'No plan found for that service type.'; }
|
if (!plan) { latest.reachable = true; latest.lastError = 'No plan found for that service type.'; }
|
||||||
else {
|
else {
|
||||||
|
|
||||||
@@ -521,12 +522,15 @@ module.exports = {
|
|||||||
|
|
||||||
const libEntries = Object.entries(library).map(([id, v]) => ({ id, name: v.name, file: v.file }));
|
const libEntries = Object.entries(library).map(([id, v]) => ({ id, name: v.name, file: v.file }));
|
||||||
|
|
||||||
// Slots a person is sitting in by hand — don't fill them, and don't place that same person twice.
|
// Slots a person was placed in by hand FOR THIS PLAN — don't fill them, and don't place that
|
||||||
|
// same person twice. A hand placement made for an earlier plan (last week's lineup, or one
|
||||||
|
// from before placements were stamped) is stale: Sync replaces it like any synced slot.
|
||||||
const eff = effectiveSlots();
|
const eff = effectiveSlots();
|
||||||
|
const planId = String(plan.id);
|
||||||
const openIdx = []; const manualNames = new Set();
|
const openIdx = []; const manualNames = new Set();
|
||||||
for (let i = 0; i < eff.length; i += 1) {
|
for (let i = 0; i < eff.length; i += 1) {
|
||||||
const e = board[String(i)];
|
const e = board[String(i)];
|
||||||
if (e && (e.personId || e.name)) {
|
if (e && (e.personId || e.name) && e.plan === planId) {
|
||||||
const nm = e.personId ? (library[e.personId] && library[e.personId].name) : e.name;
|
const nm = e.personId ? (library[e.personId] && library[e.personId].name) : e.name;
|
||||||
if (nm) manualNames.add(normName(nm));
|
if (nm) manualNames.add(normName(nm));
|
||||||
} else openIdx.push(i);
|
} else openIdx.push(i);
|
||||||
@@ -540,8 +544,8 @@ module.exports = {
|
|||||||
const lib = bestLibraryMatch(m.name, libEntries); // folder photo wins over the PCO headshot
|
const lib = bestLibraryMatch(m.name, libEntries); // folder photo wins over the PCO headshot
|
||||||
const file = lib && lib.file ? lib.file : await cachePcoPhoto(m.personId, m.photoUrl);
|
const file = lib && lib.file ? lib.file : await cachePcoPhoto(m.personId, m.photoUrl);
|
||||||
board[String(i)] = { pco: { name: m.name, file, birthday: m.birthday || '', personId: m.personId } };
|
board[String(i)] = { pco: { name: m.name, file, birthday: m.birthday || '', personId: m.personId } };
|
||||||
} else if (board[String(i)] && board[String(i)].pco) {
|
} else if (board[String(i)]) {
|
||||||
delete board[String(i)]; // was synced, no longer on the plan
|
delete board[String(i)]; // synced or stale, and no longer on the plan
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
saveBoard();
|
saveBoard();
|
||||||
@@ -580,6 +584,7 @@ module.exports = {
|
|||||||
current = {
|
current = {
|
||||||
streams, getLatest: () => latest, pco, listPlans, photoDir,
|
streams, getLatest: () => latest, pco, listPlans, photoDir,
|
||||||
library, board, saveLibrary, saveBoard, rebuildLocal, refresh: () => syncNow(), slots,
|
library, board, saveLibrary, saveBoard, rebuildLocal, refresh: () => syncNow(), slots,
|
||||||
|
planId: () => (latest.plan && latest.plan.id) || '',
|
||||||
photoUrlFor, libraryList,
|
photoUrlFor, libraryList,
|
||||||
setChoir, choirOn: () => choirOn,
|
setChoir, choirOn: () => choirOn,
|
||||||
};
|
};
|
||||||
@@ -684,7 +689,7 @@ module.exports = {
|
|||||||
const personId = String(q.get('personId') || '').trim();
|
const personId = String(q.get('personId') || '').trim();
|
||||||
if (!/^\d+$/.test(slot)) return json(res, 400, { error: 'Bad slot.' });
|
if (!/^\d+$/.test(slot)) return json(res, 400, { error: 'Bad slot.' });
|
||||||
if (personId && !current.library[personId]) return json(res, 404, { error: 'No such library photo.' });
|
if (personId && !current.library[personId]) return json(res, 404, { error: 'No such library photo.' });
|
||||||
if (personId) current.board[slot] = { personId, name: '' };
|
if (personId) current.board[slot] = { personId, name: '', plan: current.planId() };
|
||||||
else delete current.board[slot];
|
else delete current.board[slot];
|
||||||
current.saveBoard(); current.rebuildLocal();
|
current.saveBoard(); current.rebuildLocal();
|
||||||
json(res, 200, { ok: true });
|
json(res, 200, { ok: true });
|
||||||
@@ -702,6 +707,7 @@ module.exports = {
|
|||||||
const name = String(q.get('name') || '').trim();
|
const name = String(q.get('name') || '').trim();
|
||||||
const existing = current.board[index] || { personId: '', name: '' };
|
const existing = current.board[index] || { personId: '', name: '' };
|
||||||
existing.name = name;
|
existing.name = name;
|
||||||
|
existing.plan = current.planId();
|
||||||
if (!existing.personId && !name) delete current.board[index];
|
if (!existing.personId && !name) delete current.board[index];
|
||||||
else current.board[index] = existing;
|
else current.board[index] = existing;
|
||||||
current.saveBoard(); current.rebuildLocal();
|
current.saveBoard(); current.rebuildLocal();
|
||||||
|
|||||||
Reference in New Issue
Block a user