From 279b6c1dd5424f54411348116fa0a5b44ce48b16 Mon Sep 17 00:00:00 2001 From: Daniel Egger Date: Wed, 23 Aug 2023 11:08:34 +0200 Subject: [PATCH] Refactor some fields in `DueDate` --- client/src/locales/de/translation.json | 7 +- .../assignment/AssignmentIntroductionView.vue | 2 +- .../migrations/0006_auto_20230823_1127.py | 25 +++ server/vbv_lernwelt/course_session/models.py | 146 +++++++++--------- server/vbv_lernwelt/duedate/admin.py | 24 ++- .../migrations/0003_auto_20230823_1126.py | 65 ++++++++ server/vbv_lernwelt/duedate/models.py | 61 ++++++-- 7 files changed, 241 insertions(+), 89 deletions(-) create mode 100644 server/vbv_lernwelt/assignment/migrations/0006_auto_20230823_1127.py create mode 100644 server/vbv_lernwelt/duedate/migrations/0003_auto_20230823_1126.py diff --git a/client/src/locales/de/translation.json b/client/src/locales/de/translation.json index f0ba3370..bc831c6e 100644 --- a/client/src/locales/de/translation.json +++ b/client/src/locales/de/translation.json @@ -23,9 +23,9 @@ "confirmSubmitPerson": "Hiermit bestätige ich, dass die folgende Person meine Ergebnisse bewerten soll.", "confirmSubmitResults": "Hiermit bestätige ich, dass ich die Zusammenfassung meiner Ergebnisse überprüft habe und so abgeben will.", "dueDateIntroduction": "Reiche deine Ergebnisse pünktlich ein bis am: ", + "dueDateEvaluation": "Freigabetermin Bewertung", "dueDateNotSet": "Keine Abgabedaten wurden erfasst für diese Durchführung", "dueDateSubmission": "Abgabetermin", - "dueDateTitle": "Abgabetermin", "edit": "Bearbeiten", "effortTitle": "Zeitaufwand", "initialSituationTitle": "Ausgangslage", @@ -107,7 +107,7 @@ "showAllDueDates": "Alle Termine anzeigen" }, "edoniqTest": { - "qualifiesForExtendedTime": "edoniqTest.qualifiesForExtendedTime" + "qualifiesForExtendedTime": "Ich habe Anrecht auf einen Nachteilsausgleich." }, "feedback": { "answers": "Antworten", @@ -250,7 +250,6 @@ "titel": "Lernmedien" }, "overview": "Übersicht", - "show": "Mediathek anzeigen", "title": "Mediathek" }, "messages": { @@ -273,7 +272,7 @@ "selfEvaluationNo": "@:selfEvaluation: Muss ich nochmals anschauen.", "selfEvaluationYes": "@:selfEvaluation: Ich kann das.", "steps": "Schritt {{current}} von {{max}}", - "title": "@:selfEvaluation.selfEvaluation {{title}}", + "title": "Selbsteinschätzung {{title}}", "yes": "Ja, ich kann das" }, "settings": { diff --git a/client/src/pages/learningPath/learningContentPage/assignment/AssignmentIntroductionView.vue b/client/src/pages/learningPath/learningContentPage/assignment/AssignmentIntroductionView.vue index f9fd2d61..0603eea5 100644 --- a/client/src/pages/learningPath/learningContentPage/assignment/AssignmentIntroductionView.vue +++ b/client/src/pages/learningPath/learningContentPage/assignment/AssignmentIntroductionView.vue @@ -41,7 +41,7 @@ const step = useRouteQuery("step"); -

{{ $t("assignment.dueDateTitle") }}asdf

+

{{ $t("assignment.dueDateSubmission") }}

{{ $t("assignment.dueDateIntroduction") }} diff --git a/server/vbv_lernwelt/assignment/migrations/0006_auto_20230823_1127.py b/server/vbv_lernwelt/assignment/migrations/0006_auto_20230823_1127.py new file mode 100644 index 00000000..5f243e68 --- /dev/null +++ b/server/vbv_lernwelt/assignment/migrations/0006_auto_20230823_1127.py @@ -0,0 +1,25 @@ +# Generated by Django 3.2.20 on 2023-08-23 09:27 + +from django.db import migrations +import wagtail.blocks +import wagtail.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('assignment', '0005_alter_assignment_assignment_type'), + ] + + operations = [ + migrations.AlterField( + model_name='assignment', + name='evaluation_tasks', + field=wagtail.fields.StreamField([('task', wagtail.blocks.StructBlock([('title', wagtail.blocks.TextBlock()), ('description', wagtail.blocks.RichTextBlock(blank=True, features=['ul', 'bold', 'italic', 'link'], required=False)), ('max_points', wagtail.blocks.IntegerBlock()), ('sub_tasks', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('title', wagtail.blocks.TextBlock()), ('description', wagtail.blocks.RichTextBlock(blank=True, features=['ul', 'bold', 'italic', 'link'], required=False)), ('points', wagtail.blocks.IntegerBlock())]), blank=True, use_json_field=True))]))], blank=True, help_text='Beurteilungsschritte', use_json_field=True), + ), + migrations.AlterField( + model_name='assignment', + name='tasks', + field=wagtail.fields.StreamField([('task', wagtail.blocks.StructBlock([('title', wagtail.blocks.TextBlock()), ('file_submission_required', wagtail.blocks.BooleanBlock(required=False)), ('content', wagtail.blocks.StreamBlock([('explanation', wagtail.blocks.StructBlock([('text', wagtail.blocks.RichTextBlock(features=['ul', 'bold', 'italic', 'link']))])), ('user_text_input', wagtail.blocks.StructBlock([('text', wagtail.blocks.RichTextBlock(blank=True, features=['ul', 'bold', 'italic', 'link'], required=False))])), ('user_confirmation', wagtail.blocks.StructBlock([('text', wagtail.blocks.RichTextBlock(features=['ul', 'bold', 'italic', 'link']))]))], blank=True))]))], blank=True, help_text='Teilaufgaben', use_json_field=True), + ), + ] diff --git a/server/vbv_lernwelt/course_session/models.py b/server/vbv_lernwelt/course_session/models.py index 0b2f636c..56ad1541 100644 --- a/server/vbv_lernwelt/course_session/models.py +++ b/server/vbv_lernwelt/course_session/models.py @@ -1,5 +1,4 @@ from django.db import models -from django.utils.translation import gettext_lazy as _ from django_jsonform.models.fields import JSONField as JSONSchemaField from vbv_lernwelt.assignment.models import AssignmentType @@ -53,23 +52,22 @@ class CourseSessionAttendanceCourse(models.Model): ) def save(self, *args, **kwargs): - if not self.pk: - title = "" - url = "" - page = None - if self.learning_content_id: - title = self.learning_content.title - page = self.learning_content.page_ptr - url = self.learning_content.get_frontend_url() + if self.learning_content_id: + if not self.due_date_id: + self.due_date = DueDate.objects.create( + course_session=self.course_session, + ) + + if not self.due_date.manual_override_fields: + self.due_date.url = self.learning_content.get_frontend_url() + self.due_date.title = self.learning_content.title + self.due_date.page = self.learning_content.page_ptr + self.due_date.assignment_type_translation_key = ( + "learningContentTypes.attendanceCourse" + ) + + self.due_date.save() - self.due_date = DueDate.objects.create( - url=url, - title=f"{title}", - learning_content_description=f"{_('Präsenzkurs')}", - description="", - course_session=self.course_session, - page=page, - ) super().save(*args, **kwargs) def __str__(self): @@ -106,47 +104,57 @@ class CourseSessionAssignment(models.Model): ) def save(self, *args, **kwargs): - if not self.pk: - title = "" - url = "" - page = None - assignment_type_description = "" - if self.learning_content_id: - title = self.learning_content.title - page = self.learning_content.page_ptr - url = self.learning_content.get_frontend_url() - assignment_type = self.learning_content.assignment_type - assignment_type_descriptions = { - AssignmentType.CASEWORK.name: _("Geleitete Fallarbeit"), - AssignmentType.PREP_ASSIGNMENT.name: _("Vorbereitungsauftrag"), - AssignmentType.REFLECTION.name: _("Reflexion"), - } - assignment_type_description = assignment_type_descriptions.get( - assignment_type, "" - ) + if self.learning_content_id: + title = self.learning_content.title + page = self.learning_content.page_ptr + url = self.learning_content.get_frontend_url() + assignment_type = self.learning_content.assignment_type + assignment_type_translation_keys = { + AssignmentType.CASEWORK.value: "learningContentTypes.casework", + AssignmentType.PREP_ASSIGNMENT.value: "learningContentTypes.prepAssignment", + AssignmentType.REFLECTION.value: "learningContentTypes.reflection", + } - if assignment_type in { + if assignment_type in ( AssignmentType.CASEWORK.value, AssignmentType.PREP_ASSIGNMENT.value, - }: # Reflexion - self.submission_deadline = DueDate.objects.create( - url=url, - title=f"{title}", - learning_content_description=assignment_type_description, - description=f"{_('Abgabe Termin')}", - course_session=self.course_session, - page=page, - ) + ): + if not self.submission_deadline_id: + self.submission_deadline = DueDate.objects.create( + course_session=self.course_session, + ) + + if not self.submission_deadline.manual_override_fields: + self.submission_deadline.url = url + self.submission_deadline.title = title + self.submission_deadline.assignment_type_translation_key = ( + assignment_type_translation_keys[assignment_type] + ) + self.submission_deadline.date_type_translation_key = ( + "assignment.dueDateSubmission" + ) + self.submission_deadline.page = page + + self.submission_deadline.save() if assignment_type == AssignmentType.CASEWORK.value: - self.evaluation_deadline = DueDate.objects.create( - url=url, - title=f"{title}", - learning_content_description=assignment_type_description, - description=f"{_('Freigabe Termin Bewertungen')}", - course_session=self.course_session, - page=page, - ) + if not self.evaluation_deadline_id: + self.evaluation_deadline = DueDate.objects.create( + course_session=self.course_session, + ) + + if not self.evaluation_deadline.manual_override_fields: + self.evaluation_deadline.url = url + self.evaluation_deadline.title = title + self.evaluation_deadline.assignment_type_translation_key = ( + assignment_type_translation_keys[assignment_type] + ) + self.evaluation_deadline.date_type_translation_key = ( + "assignment.dueDateEvaluation" + ) + self.evaluation_deadline.page = page + + self.evaluation_deadline.save() super().save(*args, **kwargs) @@ -174,23 +182,21 @@ class CourseSessionEdoniqTest(models.Model): return f"{self.course_session} - {self.learning_content}" def save(self, *args, **kwargs): - if not self.pk: - title = "" - url = "" - page = None - edoniq_test_type_description = _("Wissens und Verständnisfragen") - if self.learning_content_id: - title = self.learning_content.title - page = self.learning_content.page_ptr - url = self.learning_content.get_frontend_url() + if self.learning_content_id: + if not self.deadline_id: + self.deadline = DueDate.objects.create( + course_session=self.course_session, + ) - self.deadline = DueDate.objects.create( - url=url, - title=f"{title}", - learning_content_description=edoniq_test_type_description, - description=f"{_('Abgabe Termin')}", - course_session=self.course_session, - page=page, - ) + if not self.deadline.manual_override_fields: + self.deadline.url = self.learning_content.get_frontend_url() + self.deadline.title = self.learning_content.title + self.deadline.page = self.learning_content.page_ptr + self.deadline.assignment_type_translation_key = ( + "learningContentTypes.edoniqTest" + ) + self.deadline.date_type_translation_key = "assignment.dueDateSubmission" + + self.deadline.save() super().save(*args, **kwargs) diff --git a/server/vbv_lernwelt/duedate/admin.py b/server/vbv_lernwelt/duedate/admin.py index 83268d4f..12fd4052 100644 --- a/server/vbv_lernwelt/duedate/admin.py +++ b/server/vbv_lernwelt/duedate/admin.py @@ -11,18 +11,34 @@ from vbv_lernwelt.learnpath.models import ( # Register your models here. @admin.register(DueDate) class DueDateAdmin(admin.ModelAdmin): - date_hierarchy = "end" + date_hierarchy = "start" list_display = [ - "title", "course_session", - "learning_content_description", + "title", + "display_subtitle", "start", "end", - "is_undefined", ] list_filter = ["course_session"] readonly_fields = ["course_session", "page"] + def get_readonly_fields(self, request, obj=None): + default_readonly = super(DueDateAdmin, self).get_readonly_fields(request, obj) + + if obj is None: + return default_readonly + + if not obj.manual_override_fields: + return default_readonly + [ + "title", + "subtitle", + "assignment_type_translation_key", + "date_type_translation_key", + "url", + ] + + return default_readonly + def formfield_for_foreignkey(self, db_field, request, **kwargs): if db_field.name == "page": if request.resolver_match.kwargs.get("object_id"): diff --git a/server/vbv_lernwelt/duedate/migrations/0003_auto_20230823_1126.py b/server/vbv_lernwelt/duedate/migrations/0003_auto_20230823_1126.py new file mode 100644 index 00000000..f1fd2c66 --- /dev/null +++ b/server/vbv_lernwelt/duedate/migrations/0003_auto_20230823_1126.py @@ -0,0 +1,65 @@ +# Generated by Django 3.2.20 on 2023-08-23 09:26 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('duedate', '0002_alter_duedate_start'), + ] + + operations = [ + migrations.AlterModelOptions( + name='duedate', + options={'ordering': ['start', 'end']}, + ), + migrations.RemoveField( + model_name='duedate', + name='description', + ), + migrations.RemoveField( + model_name='duedate', + name='learning_content_description', + ), + migrations.AddField( + model_name='duedate', + name='assignment_type_translation_key', + field=models.CharField(blank=True, default='', help_text='Translation Key aus dem Frontend', max_length=1024), + ), + migrations.AddField( + model_name='duedate', + name='date_type_translation_key', + field=models.CharField(blank=True, default='', help_text='Translation Key aus dem Frontend', max_length=1024), + ), + migrations.AddField( + model_name='duedate', + name='manual_override_fields', + field=models.BooleanField(default=False, help_text='Nur aktivieren, wenn man die Felder manuell überschreiben will'), + ), + migrations.AddField( + model_name='duedate', + name='subtitle', + field=models.TextField(blank=True, default='', help_text='Überschreibt den Untertitel bei `assignment_type_translation_key` und `date_type_translation_key`'), + ), + migrations.AlterField( + model_name='duedate', + name='end', + field=models.DateTimeField(blank=True, db_index=True, help_text='Enddatum ist optional', null=True), + ), + migrations.AlterField( + model_name='duedate', + name='start', + field=models.DateTimeField(blank=True, db_index=True, help_text='Startdatum ist Pflicht', null=True), + ), + migrations.AlterField( + model_name='duedate', + name='title', + field=models.CharField(default='', help_text='Title wird standarmässig vom LearningContent übernommen', max_length=1024), + ), + migrations.AlterField( + model_name='duedate', + name='url', + field=models.CharField(blank=True, default='', help_text='URL wird vom LearningContent übernommen', max_length=1024), + ), + ] diff --git a/server/vbv_lernwelt/duedate/models.py b/server/vbv_lernwelt/duedate/models.py index 154a193b..3cf6b8e6 100644 --- a/server/vbv_lernwelt/duedate/models.py +++ b/server/vbv_lernwelt/duedate/models.py @@ -10,14 +10,44 @@ from vbv_lernwelt.course.models import CourseSession class DueDate(models.Model): - start = models.DateTimeField(null=True, db_index=True, blank=True) - end = models.DateTimeField(null=True, blank=True, db_index=True) - title = models.CharField(default="", max_length=1024) - learning_content_description = models.CharField( - default="", blank=True, max_length=1024 + start = models.DateTimeField( + null=True, blank=True, db_index=True, help_text="Startdatum ist Pflicht" + ) + end = models.DateTimeField( + null=True, blank=True, db_index=True, help_text="Enddatum ist optional" + ) + manual_override_fields = models.BooleanField( + default=False, + help_text="Nur aktivieren, wenn man die Felder manuell überschreiben will", + ) + title = models.CharField( + default="", + max_length=1024, + help_text="Title wird standarmässig vom LearningContent übernommen", + ) + assignment_type_translation_key = models.CharField( + default="", + blank=True, + max_length=1024, + help_text="Translation Key aus dem Frontend", + ) + date_type_translation_key = models.CharField( + default="", + blank=True, + max_length=1024, + help_text="Translation Key aus dem Frontend", + ) + subtitle = models.TextField( + default="", + blank=True, + help_text="Überschreibt den Untertitel bei `assignment_type_translation_key` und `date_type_translation_key`", + ) + url = models.CharField( + default="", + blank=True, + max_length=1024, + help_text="URL wird vom LearningContent übernommen", ) - description = models.CharField(default="", blank=True, max_length=1024) - url = models.CharField(default="", blank=True, max_length=1024) course_session = models.ForeignKey( "course.CourseSession", on_delete=models.CASCADE, @@ -26,10 +56,8 @@ class DueDate(models.Model): page = models.ForeignKey(Page, on_delete=models.SET_NULL, null=True, blank=True) - def Meta(self): + class Meta: ordering = ["start", "end"] - verbose_name = _("Termin") - help = "The start date is mandatory. You can set the end date if you want to have a deadline with a duration." def __str__(self): if self.is_undefined: @@ -43,6 +71,19 @@ class DueDate(models.Model): return result + @property + def display_subtitle(self): + result = "" + if self.subtitle and self.manual_override_fields: + result = self.subtitle + + result = self.assignment_type_translation_key + + if self.date_type_translation_key: + result += ": " + self.date_type_translation_key + + return result + @property def is_undefined(self): return self.start is None