Fix loading of DueDates

This commit is contained in:
Daniel Egger 2023-10-10 15:20:48 +02:00
parent dcf450339d
commit 227e9f317d
12 changed files with 80 additions and 32 deletions

View File

@ -17,7 +17,7 @@ const assignmentType = t(props.dueDate.assignment_type_translation_key);
const courseSessionsStore = useCourseSessionsStore(); const courseSessionsStore = useCourseSessionsStore();
const courseSession = courseSessionsStore.allCourseSessions.find( const courseSession = courseSessionsStore.allCourseSessions.find(
(cs: CourseSession) => cs.id === props.dueDate.course_session (cs: CourseSession) => cs.id === props.dueDate.course_session_id
); );
if (!courseSession) { if (!courseSession) {
@ -28,10 +28,10 @@ const isExpert = courseSessionsStore.hasCockpit(courseSession);
const url = isExpert ? props.dueDate.url_expert : props.dueDate.url; const url = isExpert ? props.dueDate.url_expert : props.dueDate.url;
const courseSessionTitle = computed(() => { const courseSessionTitle = computed(() => {
if (props.dueDate.course_session) { if (props.dueDate.course_session_id) {
return ( return (
courseSessionsStore.getCourseSessionById(props.dueDate.course_session)?.title ?? courseSessionsStore.getCourseSessionById(props.dueDate.course_session_id)
"" ?.title ?? ""
); );
} }
return ""; return "";

View File

@ -135,7 +135,7 @@ onMounted(() => {
<template v-if="courseSessionsStore.currentCourseSessionHasCockpit"> <template v-if="courseSessionsStore.currentCourseSessionHasCockpit">
<router-link <router-link
data-cy="navigation-cockpit-link" data-cy="navigation-cockpit-link"
:to="`${courseSessionsStore.currentCourseSession.course_url}/cockpit`" :to="`${courseSessionsStore.currentCourseSession.course.slug}/cockpit`"
class="nav-item" class="nav-item"
:class="{ 'nav-item--active': inCockpit() }" :class="{ 'nav-item--active': inCockpit() }"
> >

View File

@ -64,7 +64,7 @@ const courseSessionsStore = useCourseSessionsStore();
<li class="mb-6"> <li class="mb-6">
<button <button
data-cy="navigation-mobile-cockpit-link" data-cy="navigation-mobile-cockpit-link"
@click="clickLink(`${courseSession.course_url}/cockpit`)" @click="clickLink(`${courseSession.course.slug}/cockpit`)"
> >
{{ $t("cockpit.title") }} {{ $t("cockpit.title") }}
</button> </button>

View File

@ -101,14 +101,14 @@ const appointments = computed(() => {
const isMatchingSession = (dueDate: DueDate) => const isMatchingSession = (dueDate: DueDate) =>
selectedSession.value.id === UNFILTERED || selectedSession.value.id === UNFILTERED ||
dueDate.course_session === selectedSession.value.id; dueDate.course_session_id === selectedSession.value.id;
const isMatchingCircle = (dueDate: DueDate) => const isMatchingCircle = (dueDate: DueDate) =>
selectedCircle.value.id === UNFILTERED || selectedCircle.value.id === UNFILTERED ||
dueDate.circle?.id === selectedCircle.value.id; dueDate.circle?.id === selectedCircle.value.id;
const isMatchingCourse = (dueDate: DueDate) => const isMatchingCourse = (dueDate: DueDate) =>
courseSessions.value.map((cs) => cs.id).includes(dueDate.course_session); courseSessions.value.map((cs) => cs.id).includes(dueDate.course_session_id);
const numAppointmentsToShow = ref(7); const numAppointmentsToShow = ref(7);
const canLoadMore = computed(() => { const canLoadMore = computed(() => {

View File

@ -21,7 +21,7 @@ const allDueDates = courseSessionsStore.allDueDates();
const getNextStepLink = (courseSession: CourseSession) => { const getNextStepLink = (courseSession: CourseSession) => {
return computed(() => { return computed(() => {
if (courseSessionsStore.hasCockpit(courseSession)) { if (courseSessionsStore.hasCockpit(courseSession)) {
return `${courseSession.course_url}/cockpit`; return `${courseSession.course.slug}/cockpit`;
} }
return getLearningPathUrl(courseSession.course.slug); return getLearningPathUrl(courseSession.course.slug);
}); });

View File

@ -518,7 +518,6 @@ export interface CourseSession {
title: string; title: string;
start_date: string; start_date: string;
end_date: string; end_date: string;
course_url: string;
due_dates: DueDate[]; due_dates: DueDate[];
} }
@ -672,5 +671,6 @@ export type DueDate = SimpleDueDate & {
subtitle: string; subtitle: string;
url: string; url: string;
url_expert: string; url_expert: string;
course_session_id: string;
circle: CircleLight | null; circle: CircleLight | null;
}; };

View File

@ -53,20 +53,14 @@ class CourseSessionSerializer(serializers.ModelSerializer):
id = StringIDField() id = StringIDField()
course = serializers.SerializerMethodField() course = serializers.SerializerMethodField()
course_url = serializers.SerializerMethodField() # course_url = serializers.SerializerMethodField()
due_dates = serializers.SerializerMethodField() due_dates = serializers.SerializerMethodField()
def get_course(self, obj): def get_course(self, obj):
return CourseSerializer(obj.course).data return CourseSerializer(obj.course).data
def get_course_url(self, obj): # def get_course_url(self, obj):
return obj.course.get_course_url() # return obj.course.get_course_url()
def get_documents(self, obj):
documents = CircleDocument.objects.filter(
course_session=obj, file__upload_finished_at__isnull=False
)
return CircleDocumentSerializer(documents, many=True).data
def get_due_dates(self, obj): def get_due_dates(self, obj):
due_dates = DueDate.objects.filter(course_session=obj) due_dates = DueDate.objects.filter(course_session=obj)
@ -82,7 +76,6 @@ class CourseSessionSerializer(serializers.ModelSerializer):
"title", "title",
"start_date", "start_date",
"end_date", "end_date",
"course_url",
"due_dates", "due_dates",
] ]

View File

@ -0,0 +1,17 @@
# Generated by Django 3.2.20 on 2023-10-10 13:05
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("duedate", "0005_auto_20230925_1648"),
]
operations = [
migrations.AddField(
model_name="duedate",
name="circle_data",
field=models.JSONField(blank=True, default=dict),
),
]

View File

@ -0,0 +1,21 @@
# Generated by Django 3.2.20 on 2023-10-10 13:05
from django.db import migrations
from django.db.migrations import RunPython
def trigger_due_date_save(apps, schema_editor):
# need to load concrete model, so that wagtail page has `specific` instance method...
from vbv_lernwelt.duedate.models import DueDate
for due_date in DueDate.objects.all():
# trigger save to prefetch circle data
due_date.save()
class Migration(migrations.Migration):
dependencies = [
("duedate", "0006_duedate_circle_data"),
]
operations = [RunPython(trigger_due_date_save)]

View File

@ -60,6 +60,7 @@ class DueDate(models.Model):
) )
page = models.ForeignKey(Page, on_delete=models.SET_NULL, null=True, blank=True) page = models.ForeignKey(Page, on_delete=models.SET_NULL, null=True, blank=True)
circle_data = models.JSONField(default=dict, blank=True)
class Meta: class Meta:
ordering = ["start", "end"] ordering = ["start", "end"]
@ -80,6 +81,21 @@ class DueDate(models.Model):
return result return result
def save(self, *args, **kwargs):
try:
circle = self.get_circle()
# prefetch circle data, because loading it dynamically is too slow
if circle:
self.circle_data = {
"id": str(circle.id),
"title": circle.title,
"slug": circle.slug,
}
except Exception:
# noop
pass
super().save(*args, **kwargs)
@property @property
def display_subtitle(self): def display_subtitle(self):
result = "" result = ""

View File

@ -6,11 +6,9 @@ from vbv_lernwelt.duedate.models import DueDate
class DueDateSerializer(serializers.ModelSerializer): class DueDateSerializer(serializers.ModelSerializer):
id = StringIDField() id = StringIDField()
course_session_id = serializers.SerializerMethodField()
circle = serializers.SerializerMethodField() circle = serializers.SerializerMethodField()
# course_session = StringIDField()
# page = StringIDField()
class Meta: class Meta:
model = DueDate model = DueDate
fields = [ fields = [
@ -24,18 +22,18 @@ class DueDateSerializer(serializers.ModelSerializer):
"subtitle", "subtitle",
"url", "url",
"url_expert", "url_expert",
"course_session", "course_session_id",
"page",
"circle", "circle",
] ]
def get_circle(self, obj): def get_course_session_id(self, obj):
circle = obj.get_circle() return str(obj.course_session.id)
if circle: def get_circle(self, obj):
if obj.circle_data:
return { return {
"id": str(circle.id), "id": obj.circle_data.get("id"),
"title": circle.title, "title": obj.circle_data.get("title"),
"translation_key": circle.translation_key, "slug": obj.circle_data.get("slug"),
} }
return None return None

View File

@ -6,7 +6,10 @@ from django.db import migrations
def init_user_notification_emails(apps=None, schema_editor=None): def init_user_notification_emails(apps=None, schema_editor=None):
User = apps.get_model("core", "User") User = apps.get_model("core", "User")
for u in User.objects.all(): for u in User.objects.all():
u.additional_json_data["email_notification_categories"] = ["NOTIFICATION"] u.additional_json_data["email_notification_categories"] = [
"INFORMATION",
"USER_INTERACTION",
]
u.save() u.save()