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