mirror of
https://github.com/nfonteyne/octane-website.git
synced 2026-09-03 23:24:48 +02:00
update: add who refused and who did not give answer yet in ics feed description
This commit is contained in:
parent
3a56ef44c3
commit
b056af78ac
3 changed files with 24 additions and 5 deletions
|
|
@ -40,15 +40,22 @@ function foldLine(line) {
|
||||||
return chunks.map((chunk, i) => (i === 0 ? chunk : ` ${chunk}`)).join('\r\n');
|
return chunks.map((chunk, i) => (i === 0 ? chunk : ` ${chunk}`)).join('\r\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
function rehearsalToEvent(rehearsal, { threshold, baseUrl }) {
|
function rehearsalToEvent(rehearsal, { threshold, baseUrl, allUsers }) {
|
||||||
const status = computeRehearsalStatus(rehearsal.votes, threshold);
|
const status = computeRehearsalStatus(rehearsal.votes, threshold);
|
||||||
const icsStatus = status === 'confirmed' ? 'CONFIRMED' : 'TENTATIVE';
|
const icsStatus = status === 'confirmed' ? 'CONFIRMED' : 'TENTATIVE';
|
||||||
const summary = status === 'confirmed' ? 'Répétition' : 'Répétition (proposition)';
|
const summary = status === 'confirmed' ? 'Répétition' : 'Répétition (proposition)';
|
||||||
const voteUrl = `${baseUrl}/calendar.html?rehearsalId=${rehearsal.id}`;
|
const voteUrl = `${baseUrl}/calendar.html?rehearsalId=${rehearsal.id}`;
|
||||||
|
|
||||||
const accepted = rehearsal.votes.filter((v) => v.vote === 'accept').map((v) => v.name);
|
const accepted = rehearsal.votes.filter((v) => v.vote === 'accept').map((v) => v.name);
|
||||||
|
const refused = rehearsal.votes.filter((v) => v.vote === 'reject').map((v) => v.name);
|
||||||
|
const votedUserIds = new Set(rehearsal.votes.map((v) => v.userId));
|
||||||
|
const pending = allUsers.filter((u) => !votedUserIds.has(u.id)).map((u) => u.name);
|
||||||
|
|
||||||
const description = [
|
const description = [
|
||||||
`Votez ici : ${voteUrl}`,
|
`Votez ici : ${voteUrl}`,
|
||||||
accepted.length ? `Ont accepté : ${accepted.join(', ')}` : "Personne n'a encore accepté.",
|
accepted.length ? `Ont accepté : ${accepted.join(', ')}` : "Personne n'a encore accepté.",
|
||||||
|
refused.length ? `Ont refusé : ${refused.join(', ')}` : "Personne n'a refusé.",
|
||||||
|
pending.length ? `En attente : ${pending.join(', ')}` : "Tout le monde a voté.",
|
||||||
].join('\n');
|
].join('\n');
|
||||||
|
|
||||||
const lines = [
|
const lines = [
|
||||||
|
|
@ -67,7 +74,7 @@ function rehearsalToEvent(rehearsal, { threshold, baseUrl }) {
|
||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildRehearsalsFeed(rehearsals, { threshold, baseUrl }) {
|
function buildRehearsalsFeed(rehearsals, { threshold, baseUrl, allUsers }) {
|
||||||
const lines = [
|
const lines = [
|
||||||
'BEGIN:VCALENDAR',
|
'BEGIN:VCALENDAR',
|
||||||
'VERSION:2.0',
|
'VERSION:2.0',
|
||||||
|
|
@ -75,7 +82,7 @@ function buildRehearsalsFeed(rehearsals, { threshold, baseUrl }) {
|
||||||
'CALSCALE:GREGORIAN',
|
'CALSCALE:GREGORIAN',
|
||||||
'METHOD:PUBLISH',
|
'METHOD:PUBLISH',
|
||||||
'X-WR-CALNAME:Répétitions Octane',
|
'X-WR-CALNAME:Répétitions Octane',
|
||||||
...rehearsals.flatMap((r) => rehearsalToEvent(r, { threshold, baseUrl })),
|
...rehearsals.flatMap((r) => rehearsalToEvent(r, { threshold, baseUrl, allUsers })),
|
||||||
'END:VCALENDAR',
|
'END:VCALENDAR',
|
||||||
];
|
];
|
||||||
return lines.map(foldLine).join('\r\n');
|
return lines.map(foldLine).join('\r\n');
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,13 @@ async function findByIcsToken(token) {
|
||||||
return rows[0] || null;
|
return rows[0] || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Minimal id/name list — used to work out who *hasn't* voted on a rehearsal
|
||||||
|
// yet (the ICS feed's "en attente" list), so no need for the full profile.
|
||||||
|
async function findAllNames() {
|
||||||
|
const { rows } = await pool.query('SELECT id, name FROM users ORDER BY name');
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
findById,
|
findById,
|
||||||
upsertFromClaims,
|
upsertFromClaims,
|
||||||
|
|
@ -100,4 +107,5 @@ module.exports = {
|
||||||
findAllWithActivity,
|
findAllWithActivity,
|
||||||
ensureIcsToken,
|
ensureIcsToken,
|
||||||
findByIcsToken,
|
findByIcsToken,
|
||||||
|
findAllNames,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,16 @@ router.get(
|
||||||
const user = await usersRepo.findByIcsToken(req.params.token);
|
const user = await usersRepo.findByIcsToken(req.params.token);
|
||||||
if (!user) return res.status(404).send('Not found');
|
if (!user) return res.status(404).send('Not found');
|
||||||
|
|
||||||
const [rehearsals, settings] = await Promise.all([rehearsalsRepo.findUpcoming(), calendarRepo.getSlotSettings()]);
|
const [rehearsals, settings, allUsers] = await Promise.all([
|
||||||
|
rehearsalsRepo.findUpcoming(),
|
||||||
|
calendarRepo.getSlotSettings(),
|
||||||
|
usersRepo.findAllNames(),
|
||||||
|
]);
|
||||||
// req.protocol honors X-Forwarded-Proto here — see app.set('trust proxy', 1) in app.js.
|
// req.protocol honors X-Forwarded-Proto here — see app.set('trust proxy', 1) in app.js.
|
||||||
const baseUrl = `${req.protocol}://${req.get('host')}`;
|
const baseUrl = `${req.protocol}://${req.get('host')}`;
|
||||||
res
|
res
|
||||||
.type('text/calendar; charset=utf-8')
|
.type('text/calendar; charset=utf-8')
|
||||||
.send(buildRehearsalsFeed(rehearsals, { threshold: settings.rehearsalConfirmThreshold, baseUrl }));
|
.send(buildRehearsalsFeed(rehearsals, { threshold: settings.rehearsalConfirmThreshold, baseUrl, allUsers }));
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue