Allow orphaned event and shit slots

When editing the slots of events and shifts there are certain situations
where the event or shift a slot should belong to becomes unclear or
difficult to reliably assign.  For example when adding a new slot in the
UI it may be desirable to do so before the user has input the event
or shift the slot should belong to.

In these cases, not being able to store the slot into the schedule makes
the UI logic needlessly complicated.  Allow slots to be added that do
not have its assiated relation linked up to make editing and handling
such scenarios easier.
This commit is contained in:
Hornwitser 2025-06-27 18:34:37 +02:00
parent d49ed38185
commit 73b28834a1
3 changed files with 45 additions and 38 deletions

View file

@ -123,7 +123,7 @@
<button
v-if="es.slot.isModified()"
type="button"
@click="es.event.discardSlot(es.slot.id)"
@click="schedule.discardEventSlot(es.slot.id)"
>Revert</button>
</td>
</template>

View file

@ -124,7 +124,7 @@
<button
v-if="ss.slot.isModified()"
type="button"
@click="ss.shift.discardSlot(ss.slot.id)"
@click="schedule.discardShiftSlot(ss.slot.id)"
>Revert</button>
</td>
</template>

View file

@ -197,19 +197,6 @@ export class ClientScheduleEvent extends ClientEntity<ApiScheduleEvent> {
}
}
discardSlot(id: Id) {
if (!this.slotIds.has(id)) {
throw new Error("ClientScheduleEvent.discardSlot: slot does not exist");
}
const slot = this.schedule.eventSlots.get(id)!;
if (slot.isNewEntity) {
this.slotIds.delete(id);
this.schedule.eventSlots.delete(id);
} else {
slot.discard();
}
}
static create(
schedule: ClientSchedule,
id: Id,
@ -300,7 +287,7 @@ export class ClientScheduleEvent extends ClientEntity<ApiScheduleEvent> {
export class ClientScheduleEventSlot {
schedule!: ClientSchedule;
serverDeleted: boolean;
serverEventId: Id;
serverEventId: Id | undefined;
serverStart: DateTime;
serverEnd: DateTime;
serverLocationIds: Set<Id>;
@ -311,7 +298,7 @@ export class ClientScheduleEventSlot {
public id: Id,
public isNewEntity: boolean,
public deleted: boolean,
public eventId: Id,
public eventId: Id | undefined,
public start: DateTime,
public end: DateTime,
public locationIds: Set<Id>,
@ -341,11 +328,11 @@ export class ClientScheduleEventSlot {
);
}
setEventId(newEventId: Id) {
setEventId(newEventId: Id | undefined) {
if (this.eventId === newEventId)
return;
this.schedule.events.get(newEventId)!.slotIds.add(this.id);
this.schedule.events.get(this.eventId)!.slotIds.delete(this.id);
this.schedule.events.get(newEventId!)?.slotIds.add(this.id);
this.schedule.events.get(this.eventId!)?.slotIds.delete(this.id);
this.eventId = newEventId;
}
@ -582,19 +569,6 @@ export class ClientScheduleShift extends ClientEntity<ApiScheduleShift> {
}
}
discardSlot(id: Id) {
if (!this.slotIds.has(id)) {
throw new Error("ClientScheduleShift.discardSlot: slot does not exist");
}
const slot = this.schedule.shiftSlots.get(id)!;
if (slot.isNewEntity) {
this.slotIds.delete(id);
this.schedule.shiftSlots.delete(id);
} else {
slot.discard();
}
}
static create(
schedule: ClientSchedule,
id: Id,
@ -670,7 +644,7 @@ export class ClientScheduleShift extends ClientEntity<ApiScheduleShift> {
export class ClientScheduleShiftSlot {
schedule!: ClientSchedule;
serverDeleted: boolean;
serverShiftId: Id;
serverShiftId: Id | undefined;
serverStart: DateTime;
serverEnd: DateTime;
serverAssigned: Set<Id>;
@ -679,7 +653,7 @@ export class ClientScheduleShiftSlot {
public id: Id,
public isNewEntity: boolean,
public deleted: boolean,
public shiftId: Id,
public shiftId: Id | undefined,
public start: DateTime,
public end: DateTime,
public assigned: Set<Id>,
@ -703,11 +677,11 @@ export class ClientScheduleShiftSlot {
);
}
setShiftId(newShiftId: Id) {
setShiftId(newShiftId: Id | undefined) {
if (this.shiftId === newShiftId)
return;
this.schedule.shifts.get(newShiftId)!.slotIds.add(this.id);
this.schedule.shifts.get(this.shiftId)!.slotIds.delete(this.id);
this.schedule.shifts.get(newShiftId!)?.slotIds.add(this.id);
this.schedule.shifts.get(this.shiftId!)?.slotIds.delete(this.id);
this.shiftId = newShiftId;
}
@ -823,6 +797,39 @@ export class ClientSchedule extends ClientEntity<ApiSchedule> {
this.shifts.discard();
}
discardEventSlot(id: Id) {
const eventSlot = this.eventSlots.get(id);
if (!eventSlot) {
throw new Error("ClientSchedule.discardEventSlot: slot does not exist");
}
if (eventSlot.isNewEntity) {
this.eventSlots.delete(id);
if (eventSlot.eventId !== undefined)
this.events.get(eventSlot.eventId)?.slotIds.delete(id);
if (eventSlot.serverEventId !== undefined && eventSlot.serverEventId !== eventSlot.eventId)
this.events.get(eventSlot.serverEventId)?.schedule.eventSlots.delete(id);
} else {
eventSlot.discard();
}
}
discardShiftSlot(id: Id) {
const shiftSlot = this.shiftSlots.get(id);
if (!shiftSlot) {
throw new Error("ClientSchedule.discardShiftSlot: slot does not exist");
}
if (shiftSlot.isNewEntity) {
this.shiftSlots.delete(id);
if (shiftSlot.shiftId !== undefined)
this.shifts.get(shiftSlot.shiftId)?.slotIds.delete(id);
if (shiftSlot.serverShiftId !== undefined && shiftSlot.serverShiftId !== shiftSlot.shiftId)
this.shifts.get(shiftSlot.serverShiftId)?.schedule.shiftSlots.delete(id);
} else {
shiftSlot.discard();
}
}
override isModified() {
return (
super.isModified()