Rename accounts to users to be consistent with the new naming scheme where account only referes to the logged in user of the session and implement live updates of users via a user store which listens for updates from the event stream.
96 lines
2.5 KiB
TypeScript
96 lines
2.5 KiB
TypeScript
import { readSchedule, ServerUser, writeSchedule } from '~/server/database';
|
|
import { broadcastEvent } from '~/server/streams';
|
|
import type { ApiAccount, ApiSchedule } from '~/shared/types/api';
|
|
|
|
export async function updateScheduleInterestedCounts(users: ServerUser[]) {
|
|
const eventCounts = new Map<number, number>();
|
|
const eventSlotCounts = new Map<number, number>();
|
|
for (const user of users) {
|
|
if (user.deleted)
|
|
continue;
|
|
if (user.interestedEventIds)
|
|
for (const id of user.interestedEventIds)
|
|
eventCounts.set(id, (eventCounts.get(id) ?? 0) + 1);
|
|
if (user.interestedEventSlotIds)
|
|
for (const id of user.interestedEventSlotIds)
|
|
eventSlotCounts.set(id, (eventSlotCounts.get(id) ?? 0) + 1);
|
|
}
|
|
|
|
const schedule = await readSchedule();
|
|
if (schedule.deleted) {
|
|
throw new Error("Deleted schedule not implemented");
|
|
}
|
|
const update: ApiSchedule = {
|
|
id: schedule.id,
|
|
updatedAt: new Date().toISOString(),
|
|
events: [],
|
|
};
|
|
const updatedFrom = schedule.updatedAt;
|
|
for (const event of schedule.events ?? []) {
|
|
let modified = false;
|
|
if (event.deleted)
|
|
continue;
|
|
|
|
let count = eventCounts.get(event.id);
|
|
if (count !== event.interested) {
|
|
event.interested = eventCounts.get(event.id);
|
|
modified = true;
|
|
}
|
|
for (const slot of event.slots) {
|
|
let slotCount = eventSlotCounts.get(slot.id);
|
|
if (slotCount !== slot.interested) {
|
|
slot.interested = slotCount;
|
|
modified = true;
|
|
}
|
|
}
|
|
if (modified) {
|
|
event.updatedAt = update.updatedAt;
|
|
update.events!.push(event);
|
|
}
|
|
}
|
|
if (!update.events!.length) {
|
|
return; // No changes
|
|
}
|
|
schedule.updatedAt = updatedFrom;
|
|
await writeSchedule(schedule);
|
|
await broadcastEvent({
|
|
type: "schedule-update",
|
|
updatedFrom,
|
|
data: update,
|
|
});
|
|
}
|
|
|
|
export function canSeeAnonymous(userType: string | undefined) {
|
|
return userType === "admin";
|
|
}
|
|
|
|
export function canSeeCrew(userType: string | undefined) {
|
|
return userType === "crew" || userType === "admin";
|
|
}
|
|
|
|
/** Filters out crew visible only parts of schedule */
|
|
export function filterSchedule(schedule: ApiSchedule): ApiSchedule {
|
|
if (schedule.deleted) {
|
|
return schedule;
|
|
}
|
|
return {
|
|
id: schedule.id,
|
|
updatedAt: schedule.updatedAt,
|
|
locations: schedule.locations,
|
|
events: (schedule.events ?? [])
|
|
.map(event => (
|
|
event.deleted
|
|
? event
|
|
: event.crew
|
|
// Pretend crew events are deleted.
|
|
? { id: event.id, deleted: true, updatedAt: event.updatedAt }
|
|
: {
|
|
...event,
|
|
slots: event.slots.map(slot => ({
|
|
...slot,
|
|
assigned: undefined,
|
|
}
|
|
)),
|
|
})),
|
|
}
|
|
}
|