Render events without a location
All checks were successful
/ build (push) Successful in 1m31s
/ deploy (push) Successful in 16s

Show events that have no locations set. This is useful when drafting a
schedule and having events who's location have yet to be decided.
This commit is contained in:
Hornwitser 2025-06-30 16:39:51 +02:00
parent 5144bf2b37
commit 344b9acbf8

View file

@ -82,17 +82,16 @@
</div> </div>
</td> </td>
</tr> </tr>
<template v-for="location in schedule.locations.values()" :key="location.id"> <template v-for="[id, locationGroup] in locationGroups" :key="id">
<tr <tr
v-if="locationGroups.has(location.id)" v-for="row, index in locationGroup"
v-for="row, index in locationGroups.get(location.id)"
:key="index" :key="index"
> >
<th <th
v-if="index === 0" v-if="index === 0"
:rowSpan="locationGroups.get(location.id)!.length" :rowSpan="locationGroup.length"
> >
{{ location.name }} {{ schedule.locations.get(id!)?.name }}
</th> </th>
<td <td
v-for="cell, index in row" v-for="cell, index in row"
@ -161,7 +160,7 @@ type Junction = { ts: number, edges: Edge[] };
type Span = { type Span = {
start: Junction; start: Junction;
end: Junction, end: Junction,
locations: Map<number, Set<ClientScheduleEventSlot>>, locations: Map<number | undefined, Set<ClientScheduleEventSlot>>,
roles: Map<number | undefined, Set<ClientScheduleShiftSlot>>, roles: Map<number | undefined, Set<ClientScheduleShiftSlot>>,
}; };
@ -234,9 +233,10 @@ function* spansFromJunctions(
locations: ClientMap<ClientScheduleLocation>, locations: ClientMap<ClientScheduleLocation>,
roles: ClientMap<ClientScheduleRole>, roles: ClientMap<ClientScheduleRole>,
): Generator<Span> { ): Generator<Span> {
const activeLocations = new Map( const activeLocations = new Map<number | undefined, Set<ClientScheduleEventSlot>>(
[...locations.keys()].map(id => [id, new Set<ClientScheduleEventSlot>()]) [...locations.keys()].map(id => [id, new Set()])
); );
activeLocations.set(undefined, new Set());
const activeRoles = new Map<number | undefined, Set<ClientScheduleShiftSlot>>( const activeRoles = new Map<number | undefined, Set<ClientScheduleShiftSlot>>(
[...roles.keys()].map(id => [id, new Set()]), [...roles.keys()].map(id => [id, new Set()]),
); );
@ -246,7 +246,10 @@ function* spansFromJunctions(
if (edge.type === "start") { if (edge.type === "start") {
if (edge.source === "event") { if (edge.source === "event") {
for (const locationId of edge.slot.locationIds) { for (const locationId of edge.slot.locationIds) {
activeLocations.get(locationId)?.add(edge.slot) activeLocations.get(locationId)?.add(edge.slot);
}
if (edge.slot.locationIds.size === 0) {
activeLocations.get(undefined)?.add(edge.slot);
} }
} else if (edge.source === "shift") { } else if (edge.source === "shift") {
activeRoles.get(edge.roleId)?.add(edge.slot); activeRoles.get(edge.roleId)?.add(edge.slot);
@ -271,7 +274,10 @@ function* spansFromJunctions(
if (edge.type === "end") { if (edge.type === "end") {
if (edge.source === "event") { if (edge.source === "event") {
for (const locationId of edge.slot.locationIds) { for (const locationId of edge.slot.locationIds) {
activeLocations.get(locationId)?.delete(edge.slot) activeLocations.get(locationId)?.delete(edge.slot);
}
if (edge.slot.locationIds.size === 0) {
activeLocations.get(undefined)?.delete(edge.slot);
} }
} else if (edge.source === "shift") { } else if (edge.source === "shift") {
activeRoles.get(edge.roleId)?.delete(edge.slot); activeRoles.get(edge.roleId)?.delete(edge.slot);
@ -402,7 +408,8 @@ function tableElementsFromStretches(
const columnGroups: ColumnGroup[] = []; const columnGroups: ColumnGroup[] = [];
const dayHeaders: DayHead[] = []; const dayHeaders: DayHead[] = [];
const hourHeaders: HourHead[]= []; const hourHeaders: HourHead[]= [];
const locationGroups = new Map<number, LocationRow[]>([...locations.keys()].map(id => [id, []])); const locationGroups = new Map<number | undefined, LocationRow[]>([...locations.keys()].map(id => [id, []]));
locationGroups.set(undefined, []);
const roleGroups = new Map<number | undefined, RoleRow[]>([...roles.keys()].map(id => [id, []])); const roleGroups = new Map<number | undefined, RoleRow[]>([...roles.keys()].map(id => [id, []]));
roleGroups.set(undefined, []); roleGroups.set(undefined, []);
const eventBySlotId = new Map([...events.values()].flatMap(event => [...event.slots.values()].map(slot => [slot.id, event]))); const eventBySlotId = new Map([...events.values()].flatMap(event => [...event.slots.values()].map(slot => [slot.id, event])));
@ -418,7 +425,7 @@ function tableElementsFromStretches(
function startHour(isBreak: boolean, content?: string, isDayShift = false) { function startHour(isBreak: boolean, content?: string, isDayShift = false) {
hourHeaders.push({ span: 0, isBreak, isDayShift, content }) hourHeaders.push({ span: 0, isBreak, isDayShift, content })
} }
function startLocation(id: number, isBreak: boolean, newSlots = new Set<ClientScheduleEventSlot>()) { function startLocation(id: number | undefined, isBreak: boolean, newSlots = new Set<ClientScheduleEventSlot>()) {
const group = locationGroups.get(id)!; const group = locationGroups.get(id)!;
// Remove all slots that are no longer in the new slots. // Remove all slots that are no longer in the new slots.
for (const row of group) { for (const row of group) {
@ -476,9 +483,8 @@ function tableElementsFromStretches(
columnGroups[columnGroups.length - 1].cols.push({ minutes }) columnGroups[columnGroups.length - 1].cols.push({ minutes })
dayHeaders[dayHeaders.length - 1].span += 1; dayHeaders[dayHeaders.length - 1].span += 1;
hourHeaders[hourHeaders.length - 1].span += 1; hourHeaders[hourHeaders.length - 1].span += 1;
for(const location of locations.values()) { for (const locationGroup of locationGroups.values()) {
const group = locationGroups.get(location.id)!; for (const row of locationGroup) {
for (const row of group) {
row[row.length - 1].span += 1; row[row.length - 1].span += 1;
} }
} }
@ -497,8 +503,8 @@ function tableElementsFromStretches(
startColumnGroup(stretch.start, stretch.end, (stretch.end - stretch.start) / oneHourMs, false); startColumnGroup(stretch.start, stretch.end, (stretch.end - stretch.start) / oneHourMs, false);
startDay(false, startDate.toFormat("yyyy-LL-dd")); startDay(false, startDate.toFormat("yyyy-LL-dd"));
startHour(false, startDate.toFormat("HH:mm")); startHour(false, startDate.toFormat("HH:mm"));
for (const location of locations.values()) { for (const locationId of locationGroups.keys()) {
startLocation(location.id, false); startLocation(locationId, false);
} }
for (const roleId of roleGroups.keys()) { for (const roleId of roleGroups.keys()) {
startRole(roleId, false); startRole(roleId, false);
@ -511,8 +517,8 @@ function tableElementsFromStretches(
if (!sameDay) if (!sameDay)
startDay(true); startDay(true);
startHour(true, "break"); startHour(true, "break");
for(const location of locations.values()) { for (const locationId of locationGroups.keys()) {
startLocation(location.id, true); startLocation(locationId, true);
} }
for (const roleId of roleGroups.keys()) { for (const roleId of roleGroups.keys()) {
startRole(roleId, true); startRole(roleId, true);
@ -523,8 +529,8 @@ function tableElementsFromStretches(
if (!sameDay) if (!sameDay)
startDay(false, dayName); startDay(false, dayName);
startHour(false, startDate.toFormat("HH:mm")); startHour(false, startDate.toFormat("HH:mm"));
for(const location of locations.values()) { for (const locationId of locationGroups.keys()) {
startLocation(location.id, false); startLocation(locationId, false);
} }
for (const roleId of roleGroups.keys()) { for (const roleId of roleGroups.keys()) {
startRole(roleId, false); startRole(roleId, false);
@ -536,12 +542,12 @@ function tableElementsFromStretches(
const end = cutSpan.end.ts; const end = cutSpan.end.ts;
const durationMs = end - cutSpan.start.ts; const durationMs = end - cutSpan.start.ts;
for (const location of locations.values()) { for (const locationId of locationGroups.keys()) {
const slots = cutSpan.locations.get(location.id) ?? new Set(); const slots = cutSpan.locations.get(locationId) ?? new Set();
const group = locationGroups.get(location.id)!; const group = locationGroups.get(locationId)!;
const existing = new Set(group.map(row => row[row.length - 1].slot).filter(slot => slot)); const existing = new Set(group.map(row => row[row.length - 1].slot).filter(slot => slot));
if (!setEquals(slots, existing)) { if (!setEquals(slots, existing)) {
startLocation(location.id, false, slots) startLocation(locationId, false, slots);
} }
} }
for (const roleId of roleGroups.keys()) { for (const roleId of roleGroups.keys()) {