diff --git a/prepare_server.sh b/prepare_server.sh index 8fd54393..ad375e5b 100755 --- a/prepare_server.sh +++ b/prepare_server.sh @@ -97,7 +97,6 @@ if [ "$SKIP_SETUP" = false ]; then echo "python server/manage.py create_default_courses $course_param" python server/manage.py create_default_courses $course_param python server/manage.py create_default_notifications - python server/manage.py create_default_assignments # make django translations (cd server && python manage.py compilemessages) diff --git a/server/vbv_lernwelt/assignment/creators/create_assignments.py b/server/vbv_lernwelt/assignment/creators/create_assignments.py index 4e2a415e..62b196e6 100644 --- a/server/vbv_lernwelt/assignment/creators/create_assignments.py +++ b/server/vbv_lernwelt/assignment/creators/create_assignments.py @@ -1,23 +1,20 @@ -from wagtail.blocks import StreamValue - -from vbv_lernwelt.assignment.models import ( - TaskContentStreamBlock, -) +from vbv_lernwelt.assignment.models import TaskContentStreamBlock from vbv_lernwelt.assignment.tests.assignment_factories import ( - PerformanceObjectiveBlockFactory, - AssignmentListPageFactory, AssignmentFactory, - TaskBlockFactory, + AssignmentListPageFactory, ExplanationBlockFactory, + PerformanceObjectiveBlockFactory, + TaskBlockFactory, UserTextInputBlockFactory, ) from vbv_lernwelt.core.utils import replace_whitespace from vbv_lernwelt.course.consts import COURSE_UK from vbv_lernwelt.course.models import CoursePage +from wagtail.blocks import StreamValue -def create_assignments(): - course_page = CoursePage.objects.get(course_id=COURSE_UK) +def create_uk_assignments(course_id=COURSE_UK): + course_page = CoursePage.objects.get(course_id=course_id) assignment_page = AssignmentListPageFactory( parent=course_page, ) diff --git a/server/vbv_lernwelt/assignment/management/commands/create_default_assignments.py b/server/vbv_lernwelt/assignment/management/commands/create_default_assignments.py deleted file mode 100644 index 1e2d6fc6..00000000 --- a/server/vbv_lernwelt/assignment/management/commands/create_default_assignments.py +++ /dev/null @@ -1,9 +0,0 @@ -import djclick as click - -from vbv_lernwelt.assignment.creators.create_assignments import create_assignments - - -@click.command() -def command(): - print("Creating default assignments") - create_assignments() diff --git a/server/vbv_lernwelt/assignment/migrations/0001_initial.py b/server/vbv_lernwelt/assignment/migrations/0001_initial.py index 0173e9b8..f4adc435 100644 --- a/server/vbv_lernwelt/assignment/migrations/0001_initial.py +++ b/server/vbv_lernwelt/assignment/migrations/0001_initial.py @@ -1,10 +1,11 @@ # Generated by Django 3.2.13 on 2023-04-04 11:49 -from django.db import migrations, models import django.db.models.deletion -import vbv_lernwelt.assignment.models import wagtail.blocks import wagtail.fields +from django.db import migrations, models + +import vbv_lernwelt.assignment.models class Migration(migrations.Migration): @@ -12,34 +13,144 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('wagtailcore', '0069_log_entry_jsonfield'), + ("wagtailcore", "0069_log_entry_jsonfield"), ] operations = [ migrations.CreateModel( - name='Assignment', + name="Assignment", fields=[ - ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')), - ('starting_position', models.TextField(help_text='Erläuterung der Ausgangslage')), - ('effort_required', models.CharField(blank=True, help_text='Zeitaufwand als Text', max_length=100)), - ('performance_objectives', wagtail.fields.StreamField([('performance_objective', wagtail.blocks.StructBlock([('text', wagtail.blocks.TextBlock())]))], blank=True, help_text='Leistungsziele des Auftrags', use_json_field=True)), - ('assessment_description', models.TextField(blank=True, help_text='Beschreibung der Bewertung')), - ('assessment_document_url', models.CharField(blank=True, help_text='URL zum Beeurteilungsinstrument', max_length=255)), - ('tasks', 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.TextBlock())])), ('user_text_input', vbv_lernwelt.assignment.models.UserTextInputBlock()), ('user_confirmation', wagtail.blocks.StructBlock([('text', wagtail.blocks.TextBlock())]))], blank=True))]))], blank=True, help_text='Teilaufgaben', use_json_field=True)), + ( + "page_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to="wagtailcore.page", + ), + ), + ( + "starting_position", + models.TextField(help_text="Erläuterung der Ausgangslage"), + ), + ( + "effort_required", + models.CharField( + blank=True, help_text="Zeitaufwand als Text", max_length=100 + ), + ), + ( + "performance_objectives", + wagtail.fields.StreamField( + [ + ( + "performance_objective", + wagtail.blocks.StructBlock( + [("text", wagtail.blocks.TextBlock())] + ), + ) + ], + blank=True, + help_text="Leistungsziele des Auftrags", + use_json_field=True, + ), + ), + ( + "assessment_description", + models.TextField( + blank=True, help_text="Beschreibung der Bewertung" + ), + ), + ( + "assessment_document_url", + models.CharField( + blank=True, + help_text="URL zum Beeurteilungsinstrument", + max_length=255, + ), + ), + ( + "tasks", + 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.TextBlock(), + ) + ] + ), + ), + ( + "user_text_input", + vbv_lernwelt.assignment.models.UserTextInputBlock(), + ), + ( + "user_confirmation", + wagtail.blocks.StructBlock( + [ + ( + "text", + wagtail.blocks.TextBlock(), + ) + ] + ), + ), + ], + blank=True, + ), + ), + ] + ), + ) + ], + blank=True, + help_text="Teilaufgaben", + use_json_field=True, + ), + ), ], options={ - 'verbose_name': 'Auftrag', + "verbose_name": "Auftrag", }, - bases=('wagtailcore.page',), + bases=("wagtailcore.page",), ), migrations.CreateModel( - name='AssignmentListPage', + name="AssignmentListPage", fields=[ - ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')), + ( + "page_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to="wagtailcore.page", + ), + ), ], options={ - 'abstract': False, + "abstract": False, }, - bases=('wagtailcore.page',), + bases=("wagtailcore.page",), ), ] diff --git a/server/vbv_lernwelt/assignment/models.py b/server/vbv_lernwelt/assignment/models.py index 4c74134f..c7366719 100644 --- a/server/vbv_lernwelt/assignment/models.py +++ b/server/vbv_lernwelt/assignment/models.py @@ -1,9 +1,27 @@ from django.db import models +from slugify import slugify from wagtail import blocks from wagtail.admin.panels import FieldPanel from wagtail.fields import StreamField from wagtail.models import Page +from vbv_lernwelt.core.model_utils import find_available_slug +from vbv_lernwelt.course.models import CourseBasePage + + +class AssignmentListPage(CourseBasePage): + subpage_types = ["assignment.Assignment"] + parent_page_types = ["course.CoursePage"] + + def save(self, clean=True, user=None, log_action=False, **kwargs): + self.slug = find_available_slug( + slugify(f"{self.get_parent().slug}-assignment", allow_unicode=True) + ) + super(AssignmentListPage, self).save(clean, user, log_action, **kwargs) + + def __str__(self): + return f"{self.title}" + # class AssignmentSubmission(modModel): # created_at = models.DateTimeField(auto_now_add=True) @@ -55,7 +73,7 @@ class TaskBlock(blocks.StructBlock): label = "Teilauftrag" -class Assignment(Page): +class Assignment(CourseBasePage): starting_position = models.TextField(help_text="Erläuterung der Ausgangslage") effort_required = models.CharField( max_length=100, help_text="Zeitaufwand als Text", blank=True @@ -101,7 +119,8 @@ class Assignment(Page): class Meta: verbose_name = "Auftrag" - -class AssignmentListPage(Page): - subpage_types = ["assignment.Assignment"] - parent_page_types = ["course.CoursePage"] + def save(self, clean=True, user=None, log_action=False, **kwargs): + self.slug = find_available_slug( + slugify(f"{self.get_parent().slug}-{self.title}", allow_unicode=True) + ) + super(Assignment, self).save(clean, user, log_action, **kwargs) diff --git a/server/vbv_lernwelt/assignment/tests/assignment_factories.py b/server/vbv_lernwelt/assignment/tests/assignment_factories.py index 4326b2e5..c152422d 100644 --- a/server/vbv_lernwelt/assignment/tests/assignment_factories.py +++ b/server/vbv_lernwelt/assignment/tests/assignment_factories.py @@ -3,15 +3,13 @@ from factory import SubFactory from vbv_lernwelt.assignment.models import ( Assignment, - TaskBlock, AssignmentListPage, - TaskContentStreamBlock, - UserTextInputBlock, -) -from vbv_lernwelt.assignment.models import ( ExplanationBlock, - UserConfirmationBlock, PerformanceObjectiveBlock, + TaskBlock, + TaskContentStreamBlock, + UserConfirmationBlock, + UserTextInputBlock, ) from vbv_lernwelt.core.utils import replace_whitespace diff --git a/server/vbv_lernwelt/course/management/commands/create_default_courses.py b/server/vbv_lernwelt/course/management/commands/create_default_courses.py index 3f6931f9..e8dcc94c 100644 --- a/server/vbv_lernwelt/course/management/commands/create_default_courses.py +++ b/server/vbv_lernwelt/course/management/commands/create_default_courses.py @@ -1,6 +1,7 @@ import djclick as click from wagtail.models import Page +from vbv_lernwelt.assignment.creators.create_assignments import create_uk_assignments from vbv_lernwelt.competence.create_uk_competence_profile import ( create_uk_competence_profile, create_uk_fr_competence_profile, @@ -137,6 +138,7 @@ def create_course_uk_de(): create_versicherungsvermittlerin_with_categories( course_id=COURSE_UK, title="Überbetriebliche Kurse" ) + create_uk_assignments(course_id=COURSE_UK) create_uk_learning_path(course_id=COURSE_UK) create_uk_competence_profile(course_id=COURSE_UK) create_default_media_library(course_id=COURSE_UK) diff --git a/server/vbv_lernwelt/course/management/commands/create_uk_course.py b/server/vbv_lernwelt/course/management/commands/create_uk_course.py index 0eb08b49..9899333a 100644 --- a/server/vbv_lernwelt/course/management/commands/create_uk_course.py +++ b/server/vbv_lernwelt/course/management/commands/create_uk_course.py @@ -5,6 +5,7 @@ from slugify import slugify from wagtail.models import Locale, Page, Site from wagtail_localize.models import LocaleSynchronization +from vbv_lernwelt.assignment.models import Assignment from vbv_lernwelt.core.admin import User from vbv_lernwelt.course.consts import COURSE_UK, COURSE_UK_FR from vbv_lernwelt.course.models import CoursePage @@ -18,6 +19,7 @@ from vbv_lernwelt.learnpath.tests.learning_path_factories import ( LearningUnitFactory, MediaLibraryBlockFactory, TopicFactory, + AssignmentBlockFactory, ) @@ -282,6 +284,20 @@ damit du erfolgreich mit deinem Lernpfad (durch-)starten kannst. title="Reflexion", parent=circle, ) + LearningContentFactory( + title="Überprüfen einer Motorfahrzeug-Versicherungspolice", + parent=circle, + contents=[ + ( + "assignment", + AssignmentBlockFactory( + assignment=Assignment.objects.get( + slug__startswith="überbetriebliche-kurse-assignment-überprüfen-einer-motorfahrzeugs" + ) + ), + ) + ], + ) LearningContentFactory( title="Feedback", parent=circle, diff --git a/server/vbv_lernwelt/learnpath/migrations/0002_alter_learningcontent_contents.py b/server/vbv_lernwelt/learnpath/migrations/0002_alter_learningcontent_contents.py index 559b4eb2..70d70f10 100644 --- a/server/vbv_lernwelt/learnpath/migrations/0002_alter_learningcontent_contents.py +++ b/server/vbv_lernwelt/learnpath/migrations/0002_alter_learningcontent_contents.py @@ -1,20 +1,137 @@ # Generated by Django 3.2.13 on 2023-04-04 08:28 -from django.db import migrations import wagtail.blocks import wagtail.fields +from django.db import migrations class Migration(migrations.Migration): dependencies = [ - ('learnpath', '0001_initial'), + ("learnpath", "0001_initial"), ] operations = [ migrations.AlterField( - model_name='learningcontent', - name='contents', - field=wagtail.fields.StreamField([('video', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('resource', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock()), ('text', wagtail.blocks.RichTextBlock(required=False))])), ('exercise', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('learningmodule', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('online_training', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('media_library', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('document', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('test', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('book', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('assignment', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('assignment', wagtail.blocks.PageChooserBlock(help_text='Choose the corresponding assignment.', required=True))])), ('placeholder', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('feedback', wagtail.blocks.StructBlock([])), ('attendance_day', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock())]))], use_json_field=None), + model_name="learningcontent", + name="contents", + field=wagtail.fields.StreamField( + [ + ( + "video", + wagtail.blocks.StructBlock( + [ + ("description", wagtail.blocks.TextBlock()), + ("url", wagtail.blocks.TextBlock()), + ] + ), + ), + ( + "resource", + wagtail.blocks.StructBlock( + [ + ("description", wagtail.blocks.TextBlock()), + ("url", wagtail.blocks.TextBlock()), + ("text", wagtail.blocks.RichTextBlock(required=False)), + ] + ), + ), + ( + "exercise", + wagtail.blocks.StructBlock( + [ + ("description", wagtail.blocks.TextBlock()), + ("url", wagtail.blocks.TextBlock()), + ] + ), + ), + ( + "learningmodule", + wagtail.blocks.StructBlock( + [ + ("description", wagtail.blocks.TextBlock()), + ("url", wagtail.blocks.TextBlock()), + ] + ), + ), + ( + "online_training", + wagtail.blocks.StructBlock( + [ + ("description", wagtail.blocks.TextBlock()), + ("url", wagtail.blocks.TextBlock()), + ] + ), + ), + ( + "media_library", + wagtail.blocks.StructBlock( + [ + ("description", wagtail.blocks.TextBlock()), + ("url", wagtail.blocks.TextBlock()), + ] + ), + ), + ( + "document", + wagtail.blocks.StructBlock( + [ + ("description", wagtail.blocks.TextBlock()), + ("url", wagtail.blocks.TextBlock()), + ] + ), + ), + ( + "test", + wagtail.blocks.StructBlock( + [ + ("description", wagtail.blocks.TextBlock()), + ("url", wagtail.blocks.TextBlock()), + ] + ), + ), + ( + "book", + wagtail.blocks.StructBlock( + [ + ("description", wagtail.blocks.TextBlock()), + ("url", wagtail.blocks.TextBlock()), + ] + ), + ), + ( + "assignment", + wagtail.blocks.StructBlock( + [ + ("description", wagtail.blocks.TextBlock()), + ( + "assignment", + wagtail.blocks.PageChooserBlock( + help_text="Choose the corresponding assignment.", + required=True, + ), + ), + ] + ), + ), + ( + "placeholder", + wagtail.blocks.StructBlock( + [ + ("description", wagtail.blocks.TextBlock()), + ("url", wagtail.blocks.TextBlock()), + ] + ), + ), + ("feedback", wagtail.blocks.StructBlock([])), + ( + "attendance_day", + wagtail.blocks.StructBlock( + [("description", wagtail.blocks.TextBlock())] + ), + ), + ], + use_json_field=None, + ), ), ]