Refactor slot editing to use searchable selections
Instead of having to type in exactly the name of events or shifts and then hope you remembered it right, replace these interactions with the custom select component that gives a complete list of the available choices and allows quickly searching for the right one.
This commit is contained in:
parent
da65103e05
commit
b0d5cdf791
4 changed files with 125 additions and 215 deletions
|
@ -7,7 +7,6 @@
|
||||||
<th>end</th>
|
<th>end</th>
|
||||||
<th>duration</th>
|
<th>duration</th>
|
||||||
<th>event</th>
|
<th>event</th>
|
||||||
<th>s</th>
|
|
||||||
<th>location</th>
|
<th>location</th>
|
||||||
<th>assigned</th>
|
<th>assigned</th>
|
||||||
<th v-if="edit"></th>
|
<th v-if="edit"></th>
|
||||||
|
@ -19,7 +18,7 @@
|
||||||
v-for="es in eventSlots"
|
v-for="es in eventSlots"
|
||||||
:key='es.slot?.id ?? es.start.toMillis()'
|
:key='es.slot?.id ?? es.start.toMillis()'
|
||||||
:class='{
|
:class='{
|
||||||
removed: es.type === "slot" && es.deleted,
|
removed: es.type === "slot" && es.slot.deleted,
|
||||||
gap: es.type === "gap",
|
gap: es.type === "gap",
|
||||||
}'
|
}'
|
||||||
>
|
>
|
||||||
|
@ -35,23 +34,16 @@
|
||||||
>
|
>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input
|
<SelectSingleEntity
|
||||||
type="text"
|
:entities="schedule.events"
|
||||||
v-model="newEventName"
|
v-model="newEventId"
|
||||||
>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
|
||||||
<td>
|
<td>
|
||||||
<select
|
<SelectMultiEntity
|
||||||
v-model="newEventLocation"
|
:entities="schedule.locations"
|
||||||
>
|
v-model="newEventLocationIds"
|
||||||
<option
|
/>
|
||||||
v-for="location in schedule.locations.values()"
|
|
||||||
:key="location.id"
|
|
||||||
:value="location.id"
|
|
||||||
:selected="location.id === newEventLocation"
|
|
||||||
>{{ location.name }}</option>
|
|
||||||
</select>
|
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -89,34 +81,27 @@
|
||||||
>
|
>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input
|
<SelectSingleEntity
|
||||||
type="text"
|
:entities="schedule.events"
|
||||||
v-model="es.event.name"
|
:modelValue="es.slot.eventId"
|
||||||
>
|
@update:modelValue="es.slot.setEventId($event)"
|
||||||
</td>
|
/>
|
||||||
<td>{{ status(es) }}</td>
|
|
||||||
<td>
|
|
||||||
<select
|
|
||||||
:value="es.locationId"
|
|
||||||
@change="editEventSlot(es, { locationId: parseInt(($event as any).target.value) })"
|
|
||||||
>
|
|
||||||
<option
|
|
||||||
v-for="location in schedule.locations.values()"
|
|
||||||
:key="location.id"
|
|
||||||
:value="location.id"
|
|
||||||
:selected="location.id === es.locationId"
|
|
||||||
>{{ location.name }}</option>
|
|
||||||
</select>
|
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<AssignedCrew
|
<SelectMultiEntity
|
||||||
:edit="true"
|
:entities="schedule.locations"
|
||||||
|
v-model="es.slot.locationIds"
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<SelectMultiEntity
|
||||||
|
:entities="usersStore.users"
|
||||||
v-model="es.slot.assigned"
|
v-model="es.slot.assigned"
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<button
|
<button
|
||||||
:disabled="es.deleted"
|
:disabled="es.slot.deleted"
|
||||||
type="button"
|
type="button"
|
||||||
@click="es.slot.deleted = true"
|
@click="es.slot.deleted = true"
|
||||||
>Remove</button>
|
>Remove</button>
|
||||||
|
@ -148,12 +133,17 @@
|
||||||
>
|
>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input
|
<SelectSingleEntity
|
||||||
type="text"
|
:entities="schedule.events"
|
||||||
v-model="newEventName"
|
v-model="newEventId"
|
||||||
>
|
/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<SelectMultiEntity
|
||||||
|
:entities="schedule.locations"
|
||||||
|
v-model="newEventLocationIds"
|
||||||
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
|
||||||
<td></td>
|
<td></td>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<button
|
<button
|
||||||
|
@ -181,10 +171,9 @@
|
||||||
<td>{{ es.start.toFormat("yyyy-LL-dd HH:mm") }}</td>
|
<td>{{ es.start.toFormat("yyyy-LL-dd HH:mm") }}</td>
|
||||||
<td>{{ es.end.toFormat("HH:mm") }}</td>
|
<td>{{ es.end.toFormat("HH:mm") }}</td>
|
||||||
<td>{{ es.end.diff(es.start).toFormat('hh:mm') }}</td>
|
<td>{{ es.end.diff(es.start).toFormat('hh:mm') }}</td>
|
||||||
<td>{{ es.name }}</td>
|
<td>{{ es.event?.name }}</td>
|
||||||
<td>{{ status(es) }}</td>
|
<td></td>
|
||||||
<td>{{ es.locationId }}</td>
|
<td><AssignedCrew :modelValue="es.slot.assigned" :edit="false" /></td>
|
||||||
<td><AssignedCrew :modelValue="es.assigned" :edit="false" /></td>
|
|
||||||
</template>
|
</template>
|
||||||
</tr>
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
|
@ -206,40 +195,23 @@ const props = defineProps<{
|
||||||
|
|
||||||
interface EventSlot {
|
interface EventSlot {
|
||||||
type: "slot",
|
type: "slot",
|
||||||
id: Id,
|
event?: ClientScheduleEvent,
|
||||||
deleted?: boolean,
|
|
||||||
event: ClientScheduleEvent,
|
|
||||||
slot: ClientScheduleEventSlot,
|
slot: ClientScheduleEventSlot,
|
||||||
name: string,
|
|
||||||
locationId: Id,
|
|
||||||
assigned: Set<Id>,
|
|
||||||
start: DateTime,
|
start: DateTime,
|
||||||
end: DateTime,
|
end: DateTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Gap {
|
interface Gap {
|
||||||
type: "gap",
|
type: "gap",
|
||||||
id?: undefined,
|
|
||||||
event?: undefined,
|
event?: undefined,
|
||||||
slot?: undefined,
|
slot?: undefined,
|
||||||
name?: undefined,
|
|
||||||
locationId?: number,
|
|
||||||
start: DateTime,
|
start: DateTime,
|
||||||
end: DateTime,
|
end: DateTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
function status(eventSlot: EventSlot) {
|
|
||||||
if (
|
|
||||||
!eventSlot.event
|
|
||||||
|| eventSlot.event.name !== eventSlot.name
|
|
||||||
) {
|
|
||||||
const event = [...schedule.value.events.values()].find(event => event.name === eventSlot.name);
|
|
||||||
return event ? "L" : "N";
|
|
||||||
}
|
|
||||||
return eventSlot.event.slots.size === 1 ? "" : eventSlot.event.slots.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
const accountStore = useAccountStore();
|
const accountStore = useAccountStore();
|
||||||
|
const usersStore = useUsersStore();
|
||||||
|
await usersStore.fetch();
|
||||||
const schedule = await useSchedule();
|
const schedule = await useSchedule();
|
||||||
|
|
||||||
const oneDayMs = 24 * 60 * 60 * 1000;
|
const oneDayMs = 24 * 60 * 60 * 1000;
|
||||||
|
@ -268,9 +240,9 @@ const newEventEnd = computed({
|
||||||
newEventDuration.value = dropDay(end.diff(start)).toFormat("hh:mm");
|
newEventDuration.value = dropDay(end.diff(start)).toFormat("hh:mm");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const newEventLocation = ref(props.locationId);
|
const newEventLocationIds = ref(new Set(props.locationId === undefined ? undefined : [props.locationId]));
|
||||||
watch(() => props.locationId, () => {
|
watch(() => props.locationId, () => {
|
||||||
newEventLocation.value = props.locationId;
|
newEventLocationIds.value = new Set(props.locationId === undefined ? undefined : [props.locationId]);
|
||||||
});
|
});
|
||||||
|
|
||||||
function endFromTime(start: DateTime, time: string) {
|
function endFromTime(start: DateTime, time: string) {
|
||||||
|
@ -287,7 +259,7 @@ function durationFromTime(time: string) {
|
||||||
}
|
}
|
||||||
return duration;
|
return duration;
|
||||||
}
|
}
|
||||||
const newEventName = ref("");
|
const newEventId = ref<Id>();
|
||||||
|
|
||||||
function editEventSlot(
|
function editEventSlot(
|
||||||
eventSlot: EventSlot,
|
eventSlot: EventSlot,
|
||||||
|
@ -295,7 +267,6 @@ function editEventSlot(
|
||||||
start?: string,
|
start?: string,
|
||||||
end?: string,
|
end?: string,
|
||||||
duration?: string,
|
duration?: string,
|
||||||
locationId?: Id,
|
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
if (edits.start) {
|
if (edits.start) {
|
||||||
|
@ -309,22 +280,13 @@ function editEventSlot(
|
||||||
if (edits.duration !== undefined) {
|
if (edits.duration !== undefined) {
|
||||||
eventSlot.slot.end = eventSlot.start.plus(durationFromTime(edits.duration));
|
eventSlot.slot.end = eventSlot.start.plus(durationFromTime(edits.duration));
|
||||||
}
|
}
|
||||||
if (edits.locationId !== undefined) {
|
|
||||||
eventSlot.slot.locationIds = new Set([edits.locationId]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
function newEventSlot(options: { start?: DateTime, end?: DateTime } = {}) {
|
function newEventSlot(options: { start?: DateTime, end?: DateTime } = {}) {
|
||||||
const name = newEventName.value;
|
const event = schedule.value.events.get(newEventId.value!);
|
||||||
const nameId = toId(name);
|
|
||||||
const event = [...schedule.value.events.values()].find(event => toId(event.name) === nameId);
|
|
||||||
if (!event) {
|
if (!event) {
|
||||||
alert("Invalid event");
|
alert("Invalid event");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (newEventLocation.value === undefined) {
|
|
||||||
alert("Invalid location");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let start;
|
let start;
|
||||||
let end;
|
let end;
|
||||||
const duration = durationFromTime(newEventDuration.value);
|
const duration = durationFromTime(newEventDuration.value);
|
||||||
|
@ -352,13 +314,13 @@ function newEventSlot(options: { start?: DateTime, end?: DateTime } = {}) {
|
||||||
event.id,
|
event.id,
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
new Set([newEventLocation.value]),
|
new Set(newEventLocationIds.value),
|
||||||
new Set(),
|
new Set(),
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
schedule.value.eventSlots.set(slot.id, slot);
|
schedule.value.eventSlots.set(slot.id, slot);
|
||||||
event.slotIds.add(slot.id);
|
event.slotIds.add(slot.id);
|
||||||
newEventName.value = "";
|
newEventId.value = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const oneHourMs = 60 * 60 * 1000;
|
const oneHourMs = 60 * 60 * 1000;
|
||||||
|
@ -373,29 +335,21 @@ function gapFormat(gap: Gap) {
|
||||||
|
|
||||||
const eventSlots = computed(() => {
|
const eventSlots = computed(() => {
|
||||||
const data: (EventSlot | Gap)[] = [];
|
const data: (EventSlot | Gap)[] = [];
|
||||||
for (const event of schedule.value.events.values()) {
|
for (const slot of schedule.value.eventSlots.values()) {
|
||||||
if (event.deleted)
|
const event = schedule.value.events.get(slot.eventId!);
|
||||||
|
if (event?.deleted)
|
||||||
continue;
|
continue;
|
||||||
for (const slot of event.slots.values()) {
|
if (props.eventSlotFilter && !props.eventSlotFilter(slot))
|
||||||
if (props.eventSlotFilter && !props.eventSlotFilter(slot))
|
continue;
|
||||||
continue;
|
if (props.locationId !== undefined && !slot.locationIds.has(props.locationId))
|
||||||
for (const locationId of slot.locationIds) {
|
continue;
|
||||||
if (props.locationId !== undefined && locationId !== props.locationId)
|
data.push({
|
||||||
continue;
|
type: "slot",
|
||||||
data.push({
|
event,
|
||||||
type: "slot",
|
slot,
|
||||||
id: slot.id,
|
start: slot.start,
|
||||||
deleted: slot.deleted || event.deleted,
|
end: slot.end,
|
||||||
event,
|
});
|
||||||
slot,
|
|
||||||
name: event.name,
|
|
||||||
locationId,
|
|
||||||
assigned: slot.assigned ?? [],
|
|
||||||
start: slot.start,
|
|
||||||
end: slot.end,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
data.sort((a, b) => a.start.toMillis() - b.start.toMillis() || a.end.toMillis() - b.end.toMillis());
|
data.sort((a, b) => a.start.toMillis() - b.start.toMillis() || a.end.toMillis() - b.end.toMillis());
|
||||||
|
|
||||||
|
@ -407,7 +361,6 @@ const eventSlots = computed(() => {
|
||||||
if (maxEnd < second.start.toMillis()) {
|
if (maxEnd < second.start.toMillis()) {
|
||||||
gaps.push([index, {
|
gaps.push([index, {
|
||||||
type: "gap",
|
type: "gap",
|
||||||
locationId: props.locationId,
|
|
||||||
start: DateTime.fromMillis(maxEnd, { locale: accountStore.activeLocale }),
|
start: DateTime.fromMillis(maxEnd, { locale: accountStore.activeLocale }),
|
||||||
end: second.start,
|
end: second.start,
|
||||||
}]);
|
}]);
|
||||||
|
|
|
@ -37,9 +37,8 @@
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
:disabled="!accountStore.canEditPublic"
|
:disabled="!accountStore.canEditPublic"
|
||||||
:value="!event.crew"
|
|
||||||
:checked="!event.crew"
|
:checked="!event.crew"
|
||||||
@change="event.crew = !($event.target as HTMLInputElement).value"
|
@change="event.crew = !event.crew"
|
||||||
>
|
>
|
||||||
</td>
|
</td>
|
||||||
<td>{{ event.slots.size ? event.slots.size : "" }}</td>
|
<td>{{ event.slots.size ? event.slots.size : "" }}</td>
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
<th>end</th>
|
<th>end</th>
|
||||||
<th>duration</th>
|
<th>duration</th>
|
||||||
<th>shift</th>
|
<th>shift</th>
|
||||||
<th>s</th>
|
|
||||||
<th>role</th>
|
<th>role</th>
|
||||||
<th>assigned</th>
|
<th>assigned</th>
|
||||||
<th v-if="edit"></th>
|
<th v-if="edit"></th>
|
||||||
|
@ -35,24 +34,16 @@
|
||||||
>
|
>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input
|
<SelectSingleEntity
|
||||||
type="text"
|
:entities="schedule.shifts"
|
||||||
v-model="newShiftName"
|
v-model="newShiftId"
|
||||||
>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
|
||||||
<td>
|
<td>
|
||||||
<select
|
<SelectSingleEntity
|
||||||
|
:entities="schedule.roles"
|
||||||
v-model="newShiftRoleId"
|
v-model="newShiftRoleId"
|
||||||
>
|
/>
|
||||||
<option
|
|
||||||
v-for="role in schedule.roles.values()"
|
|
||||||
:key="role.id"
|
|
||||||
:value="role.id"
|
|
||||||
:disabled="role.deleted"
|
|
||||||
:selected="role.id === newShiftRoleId"
|
|
||||||
>{{ role.name }}</option>
|
|
||||||
</select>
|
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -90,34 +81,28 @@
|
||||||
>
|
>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input
|
<SelectSingleEntity
|
||||||
type="text"
|
:entities="schedule.shifts"
|
||||||
v-model="ss.name"
|
:modelValue="ss.slot.shiftId"
|
||||||
>
|
@update:modelValue="ss.slot.setShiftId($event)"
|
||||||
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td>{{ status(ss) }}</td>
|
|
||||||
<td>
|
<td>
|
||||||
<select
|
<SelectSingleEntity
|
||||||
|
v-if="ss.shift"
|
||||||
|
:entities="schedule.roles"
|
||||||
v-model="ss.shift.roleId"
|
v-model="ss.shift.roleId"
|
||||||
>
|
/>
|
||||||
<option
|
|
||||||
v-for="role in schedule.roles.values()"
|
|
||||||
:key="role.id"
|
|
||||||
:value="role.id"
|
|
||||||
:disabled="role.deleted"
|
|
||||||
:selected="role.id === ss.shift.roleId"
|
|
||||||
>{{ role.name }}</option>
|
|
||||||
</select>
|
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<AssignedCrew
|
<SelectMultiEntity
|
||||||
:edit="true"
|
:entities="usersStore.users"
|
||||||
v-model="ss.slot.assigned"
|
v-model="ss.slot.assigned"
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<button
|
<button
|
||||||
:disabled="ss.deleted"
|
:disabled="ss.slot.deleted"
|
||||||
type="button"
|
type="button"
|
||||||
@click="ss.slot.deleted = true"
|
@click="ss.slot.deleted = true"
|
||||||
>Remove</button>
|
>Remove</button>
|
||||||
|
@ -149,12 +134,18 @@
|
||||||
>
|
>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input
|
<SelectSingleEntity
|
||||||
type="text"
|
:entities="schedule.shifts"
|
||||||
v-model="newShiftName"
|
v-model="newShiftId"
|
||||||
>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td colspan="3">
|
<td>
|
||||||
|
<SelectSingleEntity
|
||||||
|
:entities="schedule.roles"
|
||||||
|
v-model="newShiftRoleId"
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
<td colspan="2">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@click="newShiftSlot()"
|
@click="newShiftSlot()"
|
||||||
|
@ -180,10 +171,11 @@
|
||||||
<td>{{ ss.start.toFormat("yyyy-LL-dd HH:mm") }}</td>
|
<td>{{ ss.start.toFormat("yyyy-LL-dd HH:mm") }}</td>
|
||||||
<td>{{ ss.end.toFormat("HH:mm") }}</td>
|
<td>{{ ss.end.toFormat("HH:mm") }}</td>
|
||||||
<td>{{ ss.end.diff(ss.start).toFormat('hh:mm') }}</td>
|
<td>{{ ss.end.diff(ss.start).toFormat('hh:mm') }}</td>
|
||||||
<td>{{ ss.name }}</td>
|
<td>{{ ss.shift?.name }}</td>
|
||||||
<td>{{ status(ss) }}</td>
|
<td>{{ ss.shift?.roleId }}</td>
|
||||||
<td>{{ ss.roleId }}</td>
|
<td>
|
||||||
<td><AssignedCrew :modelValue="ss.assigned" :edit="false" /></td>
|
<AssignedCrew :modelValue="ss.slot.assigned" :edit="false" />
|
||||||
|
</td>
|
||||||
</template>
|
</template>
|
||||||
</tr>
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
|
@ -206,12 +198,8 @@ const props = defineProps<{
|
||||||
interface ShiftSlot {
|
interface ShiftSlot {
|
||||||
type: "slot",
|
type: "slot",
|
||||||
id: Id,
|
id: Id,
|
||||||
deleted: boolean,
|
shift?: ClientScheduleShift,
|
||||||
shift: ClientScheduleShift,
|
|
||||||
slot: ClientScheduleShiftSlot,
|
slot: ClientScheduleShiftSlot,
|
||||||
name: string,
|
|
||||||
roleId: Id,
|
|
||||||
assigned: Set<Id>,
|
|
||||||
start: DateTime,
|
start: DateTime,
|
||||||
end: DateTime,
|
end: DateTime,
|
||||||
}
|
}
|
||||||
|
@ -221,24 +209,13 @@ interface Gap {
|
||||||
id?: undefined,
|
id?: undefined,
|
||||||
shift?: undefined,
|
shift?: undefined,
|
||||||
slot?: undefined,
|
slot?: undefined,
|
||||||
name?: undefined,
|
|
||||||
role?: undefined,
|
|
||||||
start: DateTime,
|
start: DateTime,
|
||||||
end: DateTime,
|
end: DateTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
function status(shiftSlot: ShiftSlot) {
|
|
||||||
if (
|
|
||||||
!shiftSlot.shift
|
|
||||||
|| shiftSlot.shift.name !== shiftSlot.name
|
|
||||||
) {
|
|
||||||
const shift = [...schedule.value.shifts.values()].find(shift => !shift.deleted && shift.name === shiftSlot.name);
|
|
||||||
return shift ? "L" : "N";
|
|
||||||
}
|
|
||||||
return shiftSlot.shift.slots.size === 1 ? "" : shiftSlot.shift.slots.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
const accountStore = useAccountStore();
|
const accountStore = useAccountStore();
|
||||||
|
const usersStore = useUsersStore();
|
||||||
|
await usersStore.fetch();
|
||||||
const schedule = await useSchedule();
|
const schedule = await useSchedule();
|
||||||
|
|
||||||
const oneDayMs = 24 * 60 * 60 * 1000;
|
const oneDayMs = 24 * 60 * 60 * 1000;
|
||||||
|
@ -286,7 +263,7 @@ function durationFromTime(time: string) {
|
||||||
}
|
}
|
||||||
return duration;
|
return duration;
|
||||||
}
|
}
|
||||||
const newShiftName = ref("");
|
const newShiftId = ref<Id>();
|
||||||
|
|
||||||
function editShiftSlot(
|
function editShiftSlot(
|
||||||
shiftSlot: ShiftSlot,
|
shiftSlot: ShiftSlot,
|
||||||
|
@ -298,20 +275,18 @@ function editShiftSlot(
|
||||||
) {
|
) {
|
||||||
if (edits.start) {
|
if (edits.start) {
|
||||||
const start = DateTime.fromISO(edits.start, { zone: accountStore.activeTimezone, locale: accountStore.activeLocale });
|
const start = DateTime.fromISO(edits.start, { zone: accountStore.activeTimezone, locale: accountStore.activeLocale });
|
||||||
shiftSlot.start = start;
|
shiftSlot.slot.start = start;
|
||||||
shiftSlot.end = start.plus(shiftSlot.slot.end.diff(shiftSlot.slot.start));
|
shiftSlot.slot.end = start.plus(shiftSlot.slot.end.diff(shiftSlot.slot.start));
|
||||||
}
|
}
|
||||||
if (edits.end !== undefined) {
|
if (edits.end !== undefined) {
|
||||||
shiftSlot.end = endFromTime(shiftSlot.start, edits.end);
|
shiftSlot.slot.end = endFromTime(shiftSlot.slot.start, edits.end);
|
||||||
}
|
}
|
||||||
if (edits.duration !== undefined) {
|
if (edits.duration !== undefined) {
|
||||||
shiftSlot.end = shiftSlot.start.plus(durationFromTime(edits.duration));
|
shiftSlot.slot.end = shiftSlot.slot.start.plus(durationFromTime(edits.duration));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function newShiftSlot(options: { start?: DateTime, end?: DateTime } = {}) {
|
function newShiftSlot(options: { start?: DateTime, end?: DateTime } = {}) {
|
||||||
const name = newShiftName.value;
|
const shift = schedule.value.shifts.get(newShiftId.value!);
|
||||||
const nameId = toId(name);
|
|
||||||
const shift = [...schedule.value.shifts.values()].find(shift => toId(shift.name) === nameId);
|
|
||||||
if (!shift) {
|
if (!shift) {
|
||||||
alert("Invalid shift");
|
alert("Invalid shift");
|
||||||
return;
|
return;
|
||||||
|
@ -352,7 +327,7 @@ function newShiftSlot(options: { start?: DateTime, end?: DateTime } = {}) {
|
||||||
);
|
);
|
||||||
schedule.value.shiftSlots.set(slot.id, slot);
|
schedule.value.shiftSlots.set(slot.id, slot);
|
||||||
shift.slotIds.add(slot.id);
|
shift.slotIds.add(slot.id);
|
||||||
newShiftName.value = "";
|
newShiftId.value = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const oneHourMs = 60 * 60 * 1000;
|
const oneHourMs = 60 * 60 * 1000;
|
||||||
|
@ -367,25 +342,20 @@ function gapFormat(gap: Gap) {
|
||||||
|
|
||||||
const shiftSlots = computed(() => {
|
const shiftSlots = computed(() => {
|
||||||
const data: (ShiftSlot | Gap)[] = [];
|
const data: (ShiftSlot | Gap)[] = [];
|
||||||
for (const shift of schedule.value.shifts.values()) {
|
for (const slot of schedule.value.shiftSlots.values()) {
|
||||||
if (props.roleId !== undefined && shift.roleId !== props.roleId)
|
const shift = schedule.value.shifts.get(slot.shiftId!);
|
||||||
|
if (shift && props.roleId !== undefined && shift.roleId !== props.roleId)
|
||||||
continue;
|
continue;
|
||||||
for (const slot of shift.slots.values()) {
|
if (props.shiftSlotFilter && !props.shiftSlotFilter(slot))
|
||||||
if (props.shiftSlotFilter && !props.shiftSlotFilter(slot))
|
continue;
|
||||||
continue;
|
data.push({
|
||||||
data.push({
|
type: "slot",
|
||||||
type: "slot",
|
id: slot.id,
|
||||||
id: slot.id,
|
shift,
|
||||||
deleted: slot.deleted || shift.deleted,
|
slot,
|
||||||
shift,
|
start: slot.start,
|
||||||
slot,
|
end: slot.end,
|
||||||
name: shift.name,
|
});
|
||||||
roleId: shift.roleId,
|
|
||||||
assigned: slot.assigned,
|
|
||||||
start: slot.start,
|
|
||||||
end: slot.end,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const byTime = (a: DateTime, b: DateTime) => a.toMillis() - b.toMillis();
|
const byTime = (a: DateTime, b: DateTime) => a.toMillis() - b.toMillis();
|
||||||
data.sort((a, b) => byTime(a.start, b.start) || byTime(a.end, b.end));
|
data.sort((a, b) => byTime(a.start, b.start) || byTime(a.end, b.end));
|
||||||
|
|
|
@ -26,17 +26,10 @@
|
||||||
>
|
>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select
|
<SelectSingleEntity
|
||||||
|
:entities="schedule.roles"
|
||||||
v-model="shift.roleId"
|
v-model="shift.roleId"
|
||||||
>
|
/>
|
||||||
<option
|
|
||||||
v-for="role in schedule.roles.values()"
|
|
||||||
:key="role.id"
|
|
||||||
:value="role.id"
|
|
||||||
:disabled="shift.deleted"
|
|
||||||
:selected="shift.roleId === role.id"
|
|
||||||
>{{ role.name }}</option>
|
|
||||||
</select>
|
|
||||||
</td>
|
</td>
|
||||||
<td>{{ shift.slots.size ? shift.slots.size : "" }}</td>
|
<td>{{ shift.slots.size ? shift.slots.size : "" }}</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -67,15 +60,10 @@
|
||||||
>
|
>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select v-model="newShiftRoleId">
|
<SelectSingleEntity
|
||||||
<option
|
:entities="schedule.roles"
|
||||||
v-for="role in schedule.roles.values()"
|
v-model="newShiftRoleId"
|
||||||
:key="role.id"
|
/>
|
||||||
:value="role.id"
|
|
||||||
:disabled="role.deleted"
|
|
||||||
:selected="role.id === newShiftRoleId"
|
|
||||||
>{{ role.name }}</option>
|
|
||||||
</select>
|
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td>
|
<td>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue