diff --git a/client/src/components/dueDates/DueDatesList.vue b/client/src/components/dueDates/DueDatesList.vue
index 48aae0cc..35094f4f 100644
--- a/client/src/components/dueDates/DueDatesList.vue
+++ b/client/src/components/dueDates/DueDatesList.vue
@@ -10,11 +10,11 @@
- {{ $t("duedates.noDueDatesAvailable") }}
+ {{ $t("dueDates.noDueDatesAvailable") }}
diff --git a/client/src/components/dueDates/DueDatesShortList.vue b/client/src/components/dueDates/DueDatesShortList.vue
index 98b908bd..752206e6 100644
--- a/client/src/components/dueDates/DueDatesShortList.vue
+++ b/client/src/components/dueDates/DueDatesShortList.vue
@@ -18,5 +18,5 @@ const props = defineProps<{
}>();
const courseSession = useCurrentCourseSession();
-const allDueDates = courseSession.value.duedates;
+const allDueDates = courseSession.value.due_dates;
diff --git a/client/src/locales/de/translation.json b/client/src/locales/de/translation.json
index e1dbac5b..e391e89d 100644
--- a/client/src/locales/de/translation.json
+++ b/client/src/locales/de/translation.json
@@ -90,9 +90,7 @@
"welcome": "Willkommen, {{name}}"
},
"dueDates": {
- "nextDueDates": "Nächste Termine"
- },
- "duedates": {
+ "nextDueDates": "Nächste Termine",
"noDueDatesAvailable": "Keine Termine vorhanden",
"showAllDueDates": "Alle Termine anzeigen"
},
diff --git a/client/src/stores/courseSessions.ts b/client/src/stores/courseSessions.ts
index d1cb8d8f..ada625f0 100644
--- a/client/src/stores/courseSessions.ts
+++ b/client/src/stores/courseSessions.ts
@@ -40,7 +40,7 @@ export const useCourseSessionsStore = defineStore("courseSessions", () => {
reload: reload,
})) as CourseSessionUser[];
cs.users = users;
- cs.duedates.forEach((dueDate) => {
+ cs.due_dates.forEach((dueDate) => {
dueDate.start = dayjs(dueDate.start);
dueDate.end = dayjs(dueDate.end);
});
@@ -199,7 +199,7 @@ export const useCourseSessionsStore = defineStore("courseSessions", () => {
const allDueDatesReturn: DueDate[] = [];
allCourseSessions.value?.forEach((cs) => {
- allDueDatesReturn.push(...cs.duedates);
+ allDueDatesReturn.push(...cs.due_dates);
});
allDueDatesReturn.sort((a, b) => dayjs(a.end).diff(dayjs(b.end)));
return allDueDatesReturn;
diff --git a/client/src/types.ts b/client/src/types.ts
index bcb7763f..ab0f521d 100644
--- a/client/src/types.ts
+++ b/client/src/types.ts
@@ -450,7 +450,7 @@ export interface CourseSession {
assignments: CourseSessionAssignment[];
documents: CircleDocument[];
users: CourseSessionUser[];
- duedates: DueDate[];
+ due_dates: DueDate[];
}
export type Role = "MEMBER" | "EXPERT" | "TUTOR";
diff --git a/server/vbv_lernwelt/core/management/commands/reset_schema.py b/server/vbv_lernwelt/core/management/commands/reset_schema.py
index d0f8a469..4d9c153a 100644
--- a/server/vbv_lernwelt/core/management/commands/reset_schema.py
+++ b/server/vbv_lernwelt/core/management/commands/reset_schema.py
@@ -29,4 +29,3 @@ def command():
call_command("migrate")
call_command("create_default_users")
call_command("create_default_courses")
- # call_command("create_default_duedates")
diff --git a/server/vbv_lernwelt/course/serializers.py b/server/vbv_lernwelt/course/serializers.py
index a30eea17..7ce71f0a 100644
--- a/server/vbv_lernwelt/course/serializers.py
+++ b/server/vbv_lernwelt/course/serializers.py
@@ -62,7 +62,7 @@ class CourseSessionSerializer(serializers.ModelSerializer):
documents = serializers.SerializerMethodField()
attendance_courses = serializers.SerializerMethodField()
assignments = serializers.SerializerMethodField()
- duedates = serializers.SerializerMethodField()
+ due_dates = serializers.SerializerMethodField()
def get_course(self, obj):
return CourseSerializer(obj.course).data
@@ -98,10 +98,9 @@ class CourseSessionSerializer(serializers.ModelSerializer):
CourseSessionAssignment.objects.filter(course_session=obj), many=True
).data
- def get_duedates(self, obj):
- # TODO: Filter by user / userrole
- duedates = DueDate.objects.filter(course_session=obj)
- return DueDateSerializer(duedates, many=True).data
+ def get_due_dates(self, obj):
+ due_dates = DueDate.objects.filter(course_session=obj)
+ return DueDateSerializer(due_dates, many=True).data
class Meta:
model = CourseSession
@@ -122,7 +121,7 @@ class CourseSessionSerializer(serializers.ModelSerializer):
"media_library_url",
"course_url",
"documents",
- "duedates",
+ "due_dates",
]
diff --git a/server/vbv_lernwelt/duedate/factories.py b/server/vbv_lernwelt/duedate/factories.py
index 724f9fc8..af848ef0 100644
--- a/server/vbv_lernwelt/duedate/factories.py
+++ b/server/vbv_lernwelt/duedate/factories.py
@@ -2,11 +2,8 @@ import datetime
import structlog
from django.utils import timezone
-from factory import SubFactory
from factory.django import DjangoModelFactory
-from ..course_session.factories import CourseSessionFactory
-
from .models import DueDate
logger = structlog.get_logger(__name__)
@@ -25,28 +22,3 @@ class DueDateFactory(DjangoModelFactory):
title = "Prüfung Versicherungsvermittler/-in"
end = get_date("Jan 01 2021")
-
-
-def generate_events(start=timezone.now()):
- for i in range(20):
- DueDateFactory(
- title=f"{i}",
- start=start + datetime.timedelta(days=i),
- end=start + datetime.timedelta(days=i, hours=1),
- )
-
-
-def hour_rounder(t):
- # Rounds to nearest hour by adding a timedelta hour if minute >= 30
- return t.replace(
- second=0, microsecond=0, minute=0, hour=t.hour
- ) + datetime.timedelta(hours=t.minute // 30)
-
-
-def set_default_times_for_duedates():
- now = hour_rounder(timezone.now())
-
- for i, event in enumerate(DueDate.objects.filter(end__isnull=True)):
- event.start = now + datetime.timedelta(days=i)
- event.end = event.start + datetime.timedelta(hours=3)
- event.save()
diff --git a/server/vbv_lernwelt/duedate/migrations/0009_alter_duedate_course_session.py b/server/vbv_lernwelt/duedate/migrations/0009_alter_duedate_course_session.py
new file mode 100644
index 00000000..4b149840
--- /dev/null
+++ b/server/vbv_lernwelt/duedate/migrations/0009_alter_duedate_course_session.py
@@ -0,0 +1,24 @@
+# Generated by Django 3.2.13 on 2023-07-12 07:05
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("course", "0006_remove_coursesession_assignment_details_list"),
+ ("duedate", "0008_auto_20230711_1116"),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name="duedate",
+ name="course_session",
+ field=models.ForeignKey(
+ blank=True,
+ on_delete=django.db.models.deletion.CASCADE,
+ to="course.coursesession",
+ ),
+ ),
+ ]
diff --git a/server/vbv_lernwelt/duedate/models.py b/server/vbv_lernwelt/duedate/models.py
index 32484c39..c584d49d 100644
--- a/server/vbv_lernwelt/duedate/models.py
+++ b/server/vbv_lernwelt/duedate/models.py
@@ -20,7 +20,6 @@ class DueDate(models.Model):
course_session = models.ForeignKey(
"course.CourseSession",
on_delete=models.CASCADE,
- related_name="duedates",
blank=True,
)
@@ -51,12 +50,12 @@ class DueDate(models.Model):
cls, user: User, course_session: CourseSession = None, limit=10
):
"""
- Returns a queryset of all duedates that are relevant for the given user. Ordered nearest start date first.
- If course_session is given, only duedates for that course_session are returned.
+ Returns a queryset of all due dates that are relevant for the given user.
+ If course_session is given, only due dates for that course_session are returned.
The user is determined by via a course session user of a course_assignment.
"""
- qs = cls.get_next_duedates_qs()
+ qs = cls.get_next_due_dates_qs()
if course_session:
qs = qs.filter(
@@ -66,12 +65,12 @@ class DueDate(models.Model):
else:
qs = qs.filter(course_session__course_assignment__user=user)
- qs = qs.order_by("start")[:limit]
+ qs = qs.order_by("end")[:limit]
return qs
@classmethod
- def get_next_duedates_qs(cls):
+ def get_next_due_dates_qs(cls):
now = timezone.now()
qs = cls.objects.filter(end__gte=now)
return qs
diff --git a/server/vbv_lernwelt/notify/migrations/0002_auto_20230712_0905.py b/server/vbv_lernwelt/notify/migrations/0002_auto_20230712_0905.py
new file mode 100644
index 00000000..cbc4d336
--- /dev/null
+++ b/server/vbv_lernwelt/notify/migrations/0002_auto_20230712_0905.py
@@ -0,0 +1,162 @@
+# Generated by Django 3.2.13 on 2023-07-12 07:05
+
+import django.db.models.deletion
+import django.utils.timezone
+import jsonfield.fields
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("contenttypes", "0002_remove_content_type_name"),
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ("notify", "0001_initial"),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name="notification",
+ options={
+ "ordering": ["-timestamp"],
+ "verbose_name": "Notification",
+ "verbose_name_plural": "Notifications",
+ },
+ ),
+ migrations.AlterField(
+ model_name="notification",
+ name="action_object_content_type",
+ field=models.ForeignKey(
+ blank=True,
+ null=True,
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="notify_action_object",
+ to="contenttypes.contenttype",
+ verbose_name="action object content type",
+ ),
+ ),
+ migrations.AlterField(
+ model_name="notification",
+ name="action_object_object_id",
+ field=models.CharField(
+ blank=True,
+ max_length=255,
+ null=True,
+ verbose_name="action object object id",
+ ),
+ ),
+ migrations.AlterField(
+ model_name="notification",
+ name="actor_content_type",
+ field=models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="notify_actor",
+ to="contenttypes.contenttype",
+ verbose_name="actor content type",
+ ),
+ ),
+ migrations.AlterField(
+ model_name="notification",
+ name="actor_object_id",
+ field=models.CharField(max_length=255, verbose_name="actor object id"),
+ ),
+ migrations.AlterField(
+ model_name="notification",
+ name="data",
+ field=jsonfield.fields.JSONField(
+ blank=True, null=True, verbose_name="data"
+ ),
+ ),
+ migrations.AlterField(
+ model_name="notification",
+ name="deleted",
+ field=models.BooleanField(
+ db_index=True, default=False, verbose_name="deleted"
+ ),
+ ),
+ migrations.AlterField(
+ model_name="notification",
+ name="description",
+ field=models.TextField(blank=True, null=True, verbose_name="description"),
+ ),
+ migrations.AlterField(
+ model_name="notification",
+ name="emailed",
+ field=models.BooleanField(
+ db_index=True, default=False, verbose_name="emailed"
+ ),
+ ),
+ migrations.AlterField(
+ model_name="notification",
+ name="level",
+ field=models.CharField(
+ choices=[
+ ("success", "success"),
+ ("info", "info"),
+ ("warning", "warning"),
+ ("error", "error"),
+ ],
+ default="info",
+ max_length=20,
+ verbose_name="level",
+ ),
+ ),
+ migrations.AlterField(
+ model_name="notification",
+ name="public",
+ field=models.BooleanField(
+ db_index=True, default=True, verbose_name="public"
+ ),
+ ),
+ migrations.AlterField(
+ model_name="notification",
+ name="recipient",
+ field=models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="notifications",
+ to=settings.AUTH_USER_MODEL,
+ verbose_name="recipient",
+ ),
+ ),
+ migrations.AlterField(
+ model_name="notification",
+ name="target_content_type",
+ field=models.ForeignKey(
+ blank=True,
+ null=True,
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name="notify_target",
+ to="contenttypes.contenttype",
+ verbose_name="target content type",
+ ),
+ ),
+ migrations.AlterField(
+ model_name="notification",
+ name="target_object_id",
+ field=models.CharField(
+ blank=True, max_length=255, null=True, verbose_name="target object id"
+ ),
+ ),
+ migrations.AlterField(
+ model_name="notification",
+ name="timestamp",
+ field=models.DateTimeField(
+ db_index=True,
+ default=django.utils.timezone.now,
+ verbose_name="timestamp",
+ ),
+ ),
+ migrations.AlterField(
+ model_name="notification",
+ name="unread",
+ field=models.BooleanField(
+ db_index=True, default=True, verbose_name="unread"
+ ),
+ ),
+ migrations.AlterField(
+ model_name="notification",
+ name="verb",
+ field=models.CharField(max_length=255, verbose_name="verb"),
+ ),
+ ]