From c6cbb9d1c1b332cedb080f83cb8b419f1f99e427 Mon Sep 17 00:00:00 2001 From: Michael Bauer <michael-bauer@posteo.de> Date: Fri, 10 Jan 2025 20:11:31 +0100 Subject: [PATCH 1/9] Add graphql-backend for periods --- aleksis/apps/alsijil/schema/__init__.py | 35 +++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/aleksis/apps/alsijil/schema/__init__.py b/aleksis/apps/alsijil/schema/__init__.py index 284d8da2d..4be2322de 100644 --- a/aleksis/apps/alsijil/schema/__init__.py +++ b/aleksis/apps/alsijil/schema/__init__.py @@ -1,6 +1,8 @@ from datetime import datetime +from collections import defaultdict from django.db.models import BooleanField, ExpressionWrapper, Q +from django.apps import apps import graphene import graphene_django_optimizer @@ -52,6 +54,17 @@ from .personal_note import ( from .statistics import StatisticsByPersonType +class PeriodType(graphene.ObjectType): + period = graphene.Int() + time_start = graphene.Time() + time_end = graphene.Time() + + +class WeekdayType(graphene.ObjectType): + weekday = graphene.Int() + periods = graphene.List(PeriodType) + + class Query(graphene.ObjectType): documentations_by_course_id = FilterOrderList( DocumentationType, course_id=graphene.ID(required=True) @@ -99,6 +112,8 @@ class Query(graphene.ObjectType): group=graphene.ID(required=True), ) + periods = graphene.List(WeekdayType) + def resolve_documentations_by_course_id(root, info, course_id, **kwargs): documentations = Documentation.objects.filter( pk__in=Documentation.objects.filter(course_id=course_id) @@ -346,6 +361,26 @@ class Query(graphene.ObjectType): annotate_person_statistics_for_school_term(members, school_term, group=group), info ) + @staticmethod + def resolve_periods(root, info): + if apps.is_installed("aleksis.app.lesrooster"): + Slot = apps.get_model("lesrooster", "Slot") + ValidityRange = apps.get_model("lesrooster", "ValidityRange") + slots = Slot.objects.filter(time_grid__validity_range=ValidityRange.current).order_by("weekday").values("weekday", "period", "time_start", "time_end") + # Key by weekday + by_weekday = defaultdict(list) + for slot in slots: + # return nested dicts: {weekday periods { period time_* }} + # sort periods by period + by_weekday[slot["weekday"]].append(slot) + # Nest and sort periods + periods = [] + for weekday, slots in by_weekday.items(): + periods.append({"weekday": weekday, "periods": sorted(slots, key=lambda slot: slot["period"])}) + + return periods + else: + return [] class Mutation(graphene.ObjectType): create_or_update_documentations = DocumentationBatchCreateOrUpdateMutation.Field() -- GitLab From 9f0a8cb43f76029a60e91eb3456c3ee5665e9b3d Mon Sep 17 00:00:00 2001 From: Michael Bauer <michael-bauer@posteo.de> Date: Fri, 10 Jan 2025 20:35:47 +0100 Subject: [PATCH 2/9] Fix naming --- aleksis/apps/alsijil/schema/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aleksis/apps/alsijil/schema/__init__.py b/aleksis/apps/alsijil/schema/__init__.py index 4be2322de..66d5216cc 100644 --- a/aleksis/apps/alsijil/schema/__init__.py +++ b/aleksis/apps/alsijil/schema/__init__.py @@ -363,7 +363,7 @@ class Query(graphene.ObjectType): @staticmethod def resolve_periods(root, info): - if apps.is_installed("aleksis.app.lesrooster"): + if apps.is_installed("aleksis.apps.lesrooster"): Slot = apps.get_model("lesrooster", "Slot") ValidityRange = apps.get_model("lesrooster", "ValidityRange") slots = Slot.objects.filter(time_grid__validity_range=ValidityRange.current).order_by("weekday").values("weekday", "period", "time_start", "time_end") -- GitLab From 2e1bc741f2c0a5ad03483e203eb1bb996279cad1 Mon Sep 17 00:00:00 2001 From: Michael Bauer <michael-bauer@posteo.de> Date: Wed, 15 Jan 2025 20:45:50 +0100 Subject: [PATCH 3/9] Rename periods-query to periods-by-day --- aleksis/apps/alsijil/schema/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aleksis/apps/alsijil/schema/__init__.py b/aleksis/apps/alsijil/schema/__init__.py index 66d5216cc..7798d03d9 100644 --- a/aleksis/apps/alsijil/schema/__init__.py +++ b/aleksis/apps/alsijil/schema/__init__.py @@ -112,7 +112,7 @@ class Query(graphene.ObjectType): group=graphene.ID(required=True), ) - periods = graphene.List(WeekdayType) + periods_by_day = graphene.List(WeekdayType) def resolve_documentations_by_course_id(root, info, course_id, **kwargs): documentations = Documentation.objects.filter( @@ -362,7 +362,7 @@ class Query(graphene.ObjectType): ) @staticmethod - def resolve_periods(root, info): + def resolve_periods_by_day(root, info): if apps.is_installed("aleksis.apps.lesrooster"): Slot = apps.get_model("lesrooster", "Slot") ValidityRange = apps.get_model("lesrooster", "ValidityRange") -- GitLab From c48942a4913dc1d5731d91ce0c3be28b820fa8dc Mon Sep 17 00:00:00 2001 From: Michael Bauer <michael-bauer@posteo.de> Date: Wed, 15 Jan 2025 20:46:19 +0100 Subject: [PATCH 4/9] Adapt longterm-absences-frontend to optionally show periods --- .../absences/AbsenceCreationForm.vue | 169 ++++++++++++------ .../absences/absenceCreation.graphql | 11 ++ 2 files changed, 123 insertions(+), 57 deletions(-) diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue b/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue index 902a33f25..c8f446807 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue +++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue @@ -24,32 +24,46 @@ </div> </v-row> <v-row> - <v-col cols="12" :sm="6" class="pl-0"> + <v-col cols="12" :sm="startPeriods ? 4 : 6" class="pl-0"> <div aria-required="true"> <date-time-field :label="$t('forms.labels.start')" - :max-date="maxStartDate" - :max-time="maxStartTime" - :limit-selectable-range="false" :rules="$rules().required.build()" - :value="startDate" + :value="start.toISO()" @input="handleStartDate" /> </div> </v-col> - <v-col cols="12" :sm="6" class="pr-0"> + <v-col cols="12" :sm="2" v-if="startPeriods" align-self="end"> + <v-select + :label="$t('lesrooster.slot.period')" + :items="startPeriods" + item-text="period" + :value="startSlot" + @input="handleStartSlot" + return-object + /> + </v-col> + <v-col cols="12" :sm="endPeriods ? 4 : 6" class="pr-0"> <div aria-required="true"> <date-time-field :label="$t('forms.labels.end')" - :min-date="minEndDate" - :min-time="minEndTime" - :limit-selectable-range="false" :rules="$rules().required.build()" - :value="endDate" + :value="end.toISO()" @input="handleEndDate" /> </div> </v-col> + <v-col cols="12" :sm="2" v-if="endPeriods" align-self="end"> + <v-select + :label="$t('lesrooster.slot.period')" + :items="endPeriods" + item-text="period" + :value="endSlot" + @input="handleEndSlot" + return-object + /> + </v-col> </v-row> <v-row> <v-text-field @@ -75,7 +89,10 @@ <script> import AbsenceReasonGroupSelect from "aleksis.apps.kolego/components/AbsenceReasonGroupSelect.vue"; import DateTimeField from "aleksis.core/components/generic/forms/DateTimeField.vue"; -import { persons } from "./absenceCreation.graphql"; +import { + periodsByDay, + persons, +} from "./absenceCreation.graphql"; import formRulesMixin from "aleksis.core/mixins/formRulesMixin.js"; import { DateTime } from "luxon"; @@ -96,6 +113,13 @@ export default { ], apollo: { allPersons: persons, + periodsByDay: { + query: periodsByDay, + result({ data: { periodsByDay } }) { + this.handleStartDate(this.start); + this.handleEndDate(this.end); + }, + }, }, props: { persons: { @@ -123,60 +147,91 @@ export default { required: true, }, }, + data() { + return { + startDT: DateTime.fromISO(this.startDate), + endDT: DateTime.fromISO(this.endDate), + startPeriods: false, + endPeriods: false, + startSlot: undefined, + endSlot: undefined, + }; + }, computed: { - maxStartTime() { - // Only if on the same day - const start = DateTime.fromISO(this.startDate); - const end = DateTime.fromISO(this.endDate); - - if (start.day !== end.day) return; - - return end.minus({ minutes: 5 }).toFormat("HH:mm"); + start: { + get() { + return this.startDT; + }, + set(dt) { + this.startDT = dt; + if (dt >= this.end) { + this.end = dt.plus({ minutes: 5 }); + } + this.$emit("start-date", dt.toISO()); + console.log("Set start", this.startDT.toISO()); + }, }, - minEndTime() { - // Only if on the same day - const start = DateTime.fromISO(this.startDate); - const end = DateTime.fromISO(this.endDate); - - if (start.day !== end.day) return; - - return start.plus({ minutes: 5 }).toFormat("HH:mm"); - }, - maxStartDate() { - const end = DateTime.fromISO(this.endDate); - return end.toISODate(); - }, - minEndDate() { - const start = DateTime.fromISO(this.startDate); - return start.toISODate(); + end: { + get() { + return this.endDT; + }, + set(dt) { + this.endDT = dt; + if (dt <= this.start) { + this.start = dt.minus({ minutes: 5 }); + } + this.$emit("end-date", dt.toISO()); + }, }, }, methods: { - handleStartDate(startDate) { - const parsedStart = DateTime.fromISO(startDate); - const parsedEnd = DateTime.fromISO(this.endDate); - if (parsedStart >= parsedEnd) { - this.$emit( - "end-date", - parsedStart.plus({ minutes: 5 }).toISO({ suppressSeconds: true }), - ); + getPeriodsForWeekday(weekday) { + // Adapt from python conventions + const pythonWeekday = weekday - 1; + return this.periodsByDay.find((period) => period.weekday === pythonWeekday).periods; + }, + handleStartDate(date) { + console.log("handleStartDate", date); + this.start = DateTime.fromISO(date); + + if (this.periodsByDay.length > 0) { + // Select periods for day + this.startPeriods = this.getPeriodsForWeekday(this.start.weekday); + // Sync PeriodSelect + const startTime = this.start.toFormat("HH:mm:ss") + console.log("syncing to ", startTime) + this.startSlot = this.startPeriods.find((period) => period.timeStart === startTime) + console.log("startSlot ", this.startSlot) } - this.$emit("start-date", startDate); - this.$refs.form.resetValidation(); - this.$refs.form.validate(); }, - handleEndDate(endDate) { - const parsedStart = DateTime.fromISO(this.startDate); - const parsedEnd = DateTime.fromISO(endDate); - if (parsedEnd <= parsedStart) { - this.$emit( - "start-date", - parsedEnd.minus({ minutes: 5 }).toISO({ suppressSeconds: true }), - ); + handleEndDate(date) { + this.end = DateTime.fromISO(date); + + if (this.periodsByDay.length > 0) { + // Select periods for day + this.endPeriods = this.getPeriodsForWeekday(this.end.weekday); + // Sync PeriodSelect + const endTime = this.end.toFormat("HH:mm:ss") + this.endSlot = this.endPeriods.find((period) => period.endTime === endTime) } - this.$emit("end-date", endDate); - this.$refs.form.resetValidation(); - this.$refs.form.validate(); + }, + handleStartSlot(slot) { + // Sync TimeSelect + const startTime = DateTime.fromISO(slot.timeStart) + this.start = this.start.set({ + hour: startTime.hour, + minute: startTime.minute, + second: startTime.second, + }); + }, + handleEndSlot(slot) { + // Sync TimeSelect + const endTime = DateTime.fromISO(slot.timeEnd) + this.end = this.end.set({ + hour: endTime.hour, + minute: endTime.minute, + second: endTime.second, + }); }, }, }; diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/absenceCreation.graphql b/aleksis/apps/alsijil/frontend/components/coursebook/absences/absenceCreation.graphql index 5a520453f..e164d0868 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/absences/absenceCreation.graphql +++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/absenceCreation.graphql @@ -6,6 +6,17 @@ query persons { } } +query periodsByDay { + periodsByDay: periodsByDay { + weekday + periods { + period + timeStart + timeEnd + } + } +} + query lessonsForPersons($persons: [ID]!, $start: DateTime!, $end: DateTime!) { items: lessonsForPersons(persons: $persons, start: $start, end: $end) { id -- GitLab From 7eca340e093e4c00f06006809347e2791435893c Mon Sep 17 00:00:00 2001 From: Michael Bauer <michael-bauer@posteo.de> Date: Wed, 15 Jan 2025 20:50:23 +0100 Subject: [PATCH 5/9] Reformat --- .../absences/AbsenceCreationForm.vue | 65 ++++++++++--------- aleksis/apps/alsijil/schema/__init__.py | 15 +++-- 2 files changed, 45 insertions(+), 35 deletions(-) diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue b/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue index c8f446807..14a7fad9d 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue +++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue @@ -34,15 +34,15 @@ /> </div> </v-col> - <v-col cols="12" :sm="2" v-if="startPeriods" align-self="end"> - <v-select - :label="$t('lesrooster.slot.period')" - :items="startPeriods" - item-text="period" - :value="startSlot" - @input="handleStartSlot" - return-object - /> + <v-col cols="12" :sm="2" v-if="startPeriods" align-self="end"> + <v-select + :label="$t('lesrooster.slot.period')" + :items="startPeriods" + item-text="period" + :value="startSlot" + @input="handleStartSlot" + return-object + /> </v-col> <v-col cols="12" :sm="endPeriods ? 4 : 6" class="pr-0"> <div aria-required="true"> @@ -55,14 +55,14 @@ </div> </v-col> <v-col cols="12" :sm="2" v-if="endPeriods" align-self="end"> - <v-select - :label="$t('lesrooster.slot.period')" - :items="endPeriods" - item-text="period" - :value="endSlot" - @input="handleEndSlot" - return-object - /> + <v-select + :label="$t('lesrooster.slot.period')" + :items="endPeriods" + item-text="period" + :value="endSlot" + @input="handleEndSlot" + return-object + /> </v-col> </v-row> <v-row> @@ -89,10 +89,7 @@ <script> import AbsenceReasonGroupSelect from "aleksis.apps.kolego/components/AbsenceReasonGroupSelect.vue"; import DateTimeField from "aleksis.core/components/generic/forms/DateTimeField.vue"; -import { - periodsByDay, - persons, -} from "./absenceCreation.graphql"; +import { periodsByDay, persons } from "./absenceCreation.graphql"; import formRulesMixin from "aleksis.core/mixins/formRulesMixin.js"; import { DateTime } from "luxon"; @@ -188,20 +185,24 @@ export default { getPeriodsForWeekday(weekday) { // Adapt from python conventions const pythonWeekday = weekday - 1; - return this.periodsByDay.find((period) => period.weekday === pythonWeekday).periods; + return this.periodsByDay.find( + (period) => period.weekday === pythonWeekday, + ).periods; }, handleStartDate(date) { console.log("handleStartDate", date); this.start = DateTime.fromISO(date); - + if (this.periodsByDay.length > 0) { // Select periods for day this.startPeriods = this.getPeriodsForWeekday(this.start.weekday); // Sync PeriodSelect - const startTime = this.start.toFormat("HH:mm:ss") - console.log("syncing to ", startTime) - this.startSlot = this.startPeriods.find((period) => period.timeStart === startTime) - console.log("startSlot ", this.startSlot) + const startTime = this.start.toFormat("HH:mm:ss"); + console.log("syncing to ", startTime); + this.startSlot = this.startPeriods.find( + (period) => period.timeStart === startTime, + ); + console.log("startSlot ", this.startSlot); } }, handleEndDate(date) { @@ -211,13 +212,15 @@ export default { // Select periods for day this.endPeriods = this.getPeriodsForWeekday(this.end.weekday); // Sync PeriodSelect - const endTime = this.end.toFormat("HH:mm:ss") - this.endSlot = this.endPeriods.find((period) => period.endTime === endTime) + const endTime = this.end.toFormat("HH:mm:ss"); + this.endSlot = this.endPeriods.find( + (period) => period.endTime === endTime, + ); } }, handleStartSlot(slot) { // Sync TimeSelect - const startTime = DateTime.fromISO(slot.timeStart) + const startTime = DateTime.fromISO(slot.timeStart); this.start = this.start.set({ hour: startTime.hour, minute: startTime.minute, @@ -226,7 +229,7 @@ export default { }, handleEndSlot(slot) { // Sync TimeSelect - const endTime = DateTime.fromISO(slot.timeEnd) + const endTime = DateTime.fromISO(slot.timeEnd); this.end = this.end.set({ hour: endTime.hour, minute: endTime.minute, diff --git a/aleksis/apps/alsijil/schema/__init__.py b/aleksis/apps/alsijil/schema/__init__.py index 7798d03d9..a8e830da0 100644 --- a/aleksis/apps/alsijil/schema/__init__.py +++ b/aleksis/apps/alsijil/schema/__init__.py @@ -1,8 +1,8 @@ -from datetime import datetime from collections import defaultdict +from datetime import datetime -from django.db.models import BooleanField, ExpressionWrapper, Q from django.apps import apps +from django.db.models import BooleanField, ExpressionWrapper, Q import graphene import graphene_django_optimizer @@ -366,7 +366,11 @@ class Query(graphene.ObjectType): if apps.is_installed("aleksis.apps.lesrooster"): Slot = apps.get_model("lesrooster", "Slot") ValidityRange = apps.get_model("lesrooster", "ValidityRange") - slots = Slot.objects.filter(time_grid__validity_range=ValidityRange.current).order_by("weekday").values("weekday", "period", "time_start", "time_end") + slots = ( + Slot.objects.filter(time_grid__validity_range=ValidityRange.current) + .order_by("weekday") + .values("weekday", "period", "time_start", "time_end") + ) # Key by weekday by_weekday = defaultdict(list) for slot in slots: @@ -376,12 +380,15 @@ class Query(graphene.ObjectType): # Nest and sort periods periods = [] for weekday, slots in by_weekday.items(): - periods.append({"weekday": weekday, "periods": sorted(slots, key=lambda slot: slot["period"])}) + periods.append( + {"weekday": weekday, "periods": sorted(slots, key=lambda slot: slot["period"])} + ) return periods else: return [] + class Mutation(graphene.ObjectType): create_or_update_documentations = DocumentationBatchCreateOrUpdateMutation.Field() touch_documentation = TouchDocumentationMutation.Field() -- GitLab From 2b77003670ef1e6484c66abced01944902e07e43 Mon Sep 17 00:00:00 2001 From: Michael Bauer <michael-bauer@posteo.de> Date: Wed, 15 Jan 2025 20:52:16 +0100 Subject: [PATCH 6/9] Remove debug-prints --- .../components/coursebook/absences/AbsenceCreationForm.vue | 4 ---- 1 file changed, 4 deletions(-) diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue b/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue index 14a7fad9d..030b07e67 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue +++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue @@ -165,7 +165,6 @@ export default { this.end = dt.plus({ minutes: 5 }); } this.$emit("start-date", dt.toISO()); - console.log("Set start", this.startDT.toISO()); }, }, end: { @@ -190,7 +189,6 @@ export default { ).periods; }, handleStartDate(date) { - console.log("handleStartDate", date); this.start = DateTime.fromISO(date); if (this.periodsByDay.length > 0) { @@ -198,11 +196,9 @@ export default { this.startPeriods = this.getPeriodsForWeekday(this.start.weekday); // Sync PeriodSelect const startTime = this.start.toFormat("HH:mm:ss"); - console.log("syncing to ", startTime); this.startSlot = this.startPeriods.find( (period) => period.timeStart === startTime, ); - console.log("startSlot ", this.startSlot); } }, handleEndDate(date) { -- GitLab From b3e81629cf552bb87ed5767d65fa817c5d6dc527 Mon Sep 17 00:00:00 2001 From: Michael Bauer <michael-bauer@posteo.de> Date: Wed, 15 Jan 2025 21:08:09 +0100 Subject: [PATCH 7/9] Remove unused variable-destructuring --- .../components/coursebook/absences/AbsenceCreationForm.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue b/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue index 030b07e67..bee801bb2 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue +++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue @@ -112,9 +112,9 @@ export default { allPersons: persons, periodsByDay: { query: periodsByDay, - result({ data: { periodsByDay } }) { this.handleStartDate(this.start); this.handleEndDate(this.end); + result(_) { }, }, }, -- GitLab From 304ad9957e575f8f7759de3e3a4fa997e6e05225 Mon Sep 17 00:00:00 2001 From: Michael Bauer <michael-bauer@posteo.de> Date: Wed, 15 Jan 2025 21:08:34 +0100 Subject: [PATCH 8/9] Fix activation of periods Did not make a difference. But now it's proper anyhow. --- .../components/coursebook/absences/AbsenceCreationForm.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue b/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue index bee801bb2..af7d0e86b 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue +++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue @@ -112,9 +112,9 @@ export default { allPersons: persons, periodsByDay: { query: periodsByDay, - this.handleStartDate(this.start); - this.handleEndDate(this.end); result(_) { + this.handleStartDate(this.start.toISO()); + this.handleEndDate(this.end.toISO()); }, }, }, -- GitLab From 59e512903a68f368aee02f4afcfff4f9eee787b5 Mon Sep 17 00:00:00 2001 From: Jonathan Weth <git@jonathanweth.de> Date: Sun, 26 Jan 2025 20:18:39 +0100 Subject: [PATCH 9/9] Add fixes to slot select --- .../coursebook/absences/AbsenceCreationForm.vue | 12 ++++++++---- aleksis/apps/alsijil/schema/__init__.py | 4 +++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue b/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue index 601c2916a..13fcd9ddc 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue +++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/AbsenceCreationForm.vue @@ -186,16 +186,19 @@ export default { getPeriodsForWeekday(weekday) { // Adapt from python conventions const pythonWeekday = weekday - 1; - return this.periodsByDay.find( + let periodsForWeekday = this.periodsByDay.find( (period) => period.weekday === pythonWeekday, - ).periods; + ); + if (!periodsForWeekday) return false; + return periodsForWeekday.periods; }, handleStartDate(date) { this.start = DateTime.fromISO(date); - if (this.periodsByDay.length > 0) { + if (this.periodsByDay && this.periodsByDay.length > 0) { // Select periods for day this.startPeriods = this.getPeriodsForWeekday(this.start.weekday); + if (!this.startPeriods) return; // Sync PeriodSelect const startTime = this.start.toFormat("HH:mm:ss"); this.startSlot = this.startPeriods.find( @@ -206,9 +209,10 @@ export default { handleEndDate(date) { this.end = DateTime.fromISO(date); - if (this.periodsByDay.length > 0) { + if (this.periodsByDay && this.periodsByDay.length > 0) { // Select periods for day this.endPeriods = this.getPeriodsForWeekday(this.end.weekday); + if (!this.endPeriods) return; // Sync PeriodSelect const endTime = this.end.toFormat("HH:mm:ss"); this.endSlot = this.endPeriods.find( diff --git a/aleksis/apps/alsijil/schema/__init__.py b/aleksis/apps/alsijil/schema/__init__.py index 0c75517fd..1614cf0f3 100644 --- a/aleksis/apps/alsijil/schema/__init__.py +++ b/aleksis/apps/alsijil/schema/__init__.py @@ -368,7 +368,9 @@ class Query(graphene.ObjectType): Slot = apps.get_model("lesrooster", "Slot") ValidityRange = apps.get_model("lesrooster", "ValidityRange") slots = ( - Slot.objects.filter(time_grid__validity_range=ValidityRange.current) + Slot.objects.filter( + time_grid__validity_range=ValidityRange.current, period__isnull=False + ) .order_by("weekday") .values("weekday", "period", "time_start", "time_end") ) -- GitLab