diff --git a/server/vbv_lernwelt/assignment/creators/create_assignments.py b/server/vbv_lernwelt/assignment/creators/create_assignments.py index 9c5e6ebd..6dd46129 100644 --- a/server/vbv_lernwelt/assignment/creators/create_assignments.py +++ b/server/vbv_lernwelt/assignment/creators/create_assignments.py @@ -2,7 +2,7 @@ from wagtail_factories import StreamFieldFactory from vbv_lernwelt.assignment.tests.assignment_factories import ( PerformanceObjectiveBlockFactory, - AssignmentPageFactory, + AssignmentListPageFactory, AssignmentFactory, TaskBlockFactory, ) @@ -12,7 +12,7 @@ from vbv_lernwelt.course.models import CoursePage def create_assignments(): course_page = CoursePage.objects.get(course_id=COURSE_UK) - assignment_page = AssignmentPageFactory( + assignment_page = AssignmentListPageFactory( parent=course_page, ) AssignmentFactory( diff --git a/server/vbv_lernwelt/assignment/migrations/0001_initial.py b/server/vbv_lernwelt/assignment/migrations/0001_initial.py index 0ccccce3..0173e9b8 100644 --- a/server/vbv_lernwelt/assignment/migrations/0001_initial.py +++ b/server/vbv_lernwelt/assignment/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 3.2.13 on 2023-03-30 13:30 +# Generated by Django 3.2.13 on 2023-04-04 11:49 from django.db import migrations, models import django.db.models.deletion @@ -20,11 +20,12 @@ class Migration(migrations.Migration): 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()), - ('performance_objectives', wagtail.fields.StreamField([('performance_objective', wagtail.blocks.StructBlock([('text', wagtail.blocks.TextBlock())]))], use_json_field=True)), - ('effort_required', models.TextField()), - ('assessment_document_url', models.TextField()), - ('tasks', wagtail.fields.StreamField([('task', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock()), ('file_submission_required', wagtail.blocks.BooleanBlock()), ('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())]))], use_json_field=True))]))], use_json_field=True)), + ('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', @@ -32,7 +33,7 @@ class Migration(migrations.Migration): bases=('wagtailcore.page',), ), migrations.CreateModel( - name='AssignmentPage', + 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')), ], @@ -41,11 +42,4 @@ class Migration(migrations.Migration): }, bases=('wagtailcore.page',), ), - migrations.CreateModel( - name='AssignmentSubmission', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created_at', models.DateTimeField(auto_now_add=True)), - ], - ), ] diff --git a/server/vbv_lernwelt/assignment/models.py b/server/vbv_lernwelt/assignment/models.py index 6dc99c17..5530180f 100644 --- a/server/vbv_lernwelt/assignment/models.py +++ b/server/vbv_lernwelt/assignment/models.py @@ -1,14 +1,12 @@ from django.db import models -from django.db.models import Model, TextField from wagtail import blocks from wagtail.admin.panels import FieldPanel -from wagtail.blocks import StreamBlock from wagtail.fields import StreamField from wagtail.models import Page -class AssignmentSubmission(Model): - created_at = models.DateTimeField(auto_now_add=True) +# class AssignmentSubmission(modModel): +# created_at = models.DateTimeField(auto_now_add=True) class ExplanationBlock(blocks.StructBlock): @@ -38,15 +36,15 @@ class UserConfirmationBlock(blocks.StructBlock): class TaskBlock(blocks.StructBlock): - title = blocks.CharBlock() - file_submission_required = blocks.BooleanBlock() - content = StreamBlock( + title = blocks.TextBlock() + file_submission_required = blocks.BooleanBlock(required=False) + content = blocks.StreamBlock( [ ("explanation", ExplanationBlock()), ("user_text_input", UserTextInputBlock()), ("user_confirmation", UserConfirmationBlock()), ], - use_json_field=True, + blank=True, ) class Meta: @@ -55,26 +53,42 @@ class TaskBlock(blocks.StructBlock): class Assignment(Page): - starting_position = TextField() + starting_position = models.TextField(help_text="Erläuterung der Ausgangslage") + effort_required = models.CharField( + max_length=100, help_text="Zeitaufwand als Text", blank=True + ) + performance_objectives = StreamField( [ ("performance_objective", PerformanceObjectiveBlock()), ], use_json_field=True, + blank=True, + help_text="Leistungsziele des Auftrags", ) - effort_required = TextField() - assessment_document_url = TextField() + assessment_description = models.TextField( + blank=True, help_text="Beschreibung der Bewertung" + ) + assessment_document_url = models.CharField( + max_length=255, + blank=True, + help_text="URL zum Beeurteilungsinstrument", + ) + tasks = StreamField( [ ("task", TaskBlock()), ], use_json_field=True, + blank=True, + help_text="Teilaufgaben", ) content_panels = Page.content_panels + [ FieldPanel("starting_position"), - FieldPanel("performance_objectives"), FieldPanel("effort_required"), + FieldPanel("performance_objectives"), + FieldPanel("assessment_description"), FieldPanel("assessment_document_url"), FieldPanel("tasks"), ] @@ -85,6 +99,6 @@ class Assignment(Page): verbose_name = "Auftrag" -class AssignmentPage(Page): +class AssignmentListPage(Page): subpage_types = ["assignment.Assignment"] parent_page_types = ["course.CoursePage"] diff --git a/server/vbv_lernwelt/assignment/tests/assignment_factories.py b/server/vbv_lernwelt/assignment/tests/assignment_factories.py index 69e4130a..6a4e1ad1 100644 --- a/server/vbv_lernwelt/assignment/tests/assignment_factories.py +++ b/server/vbv_lernwelt/assignment/tests/assignment_factories.py @@ -1,6 +1,6 @@ import wagtail_factories -from vbv_lernwelt.assignment.models import AssignmentPage, Assignment, TaskBlock +from vbv_lernwelt.assignment.models import Assignment, TaskBlock, AssignmentListPage from vbv_lernwelt.assignment.models import ( ExplanationBlock, UserConfirmationBlock, @@ -60,8 +60,8 @@ class AssignmentFactory(wagtail_factories.PageFactory): model = Assignment -class AssignmentPageFactory(wagtail_factories.PageFactory): +class AssignmentListPageFactory(wagtail_factories.PageFactory): title = "Aufträge" class Meta: - model = AssignmentPage + model = AssignmentListPage diff --git a/server/vbv_lernwelt/course/models.py b/server/vbv_lernwelt/course/models.py index bed607c4..f4457929 100644 --- a/server/vbv_lernwelt/course/models.py +++ b/server/vbv_lernwelt/course/models.py @@ -121,7 +121,7 @@ class CoursePage(CourseBasePage): "learnpath.LearningPath", "competence.CompetenceProfilePage", "media_library.MediaLibraryPage", - "assignment.AssignmentPage", + "assignment.AssignmentListPage", ] course = models.OneToOneField("course.Course", on_delete=models.PROTECT) 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 6e4cf373..559b4eb2 100644 --- a/server/vbv_lernwelt/learnpath/migrations/0002_alter_learningcontent_contents.py +++ b/server/vbv_lernwelt/learnpath/migrations/0002_alter_learningcontent_contents.py @@ -1,132 +1,20 @@ -# Generated by Django 3.2.13 on 2023-04-03 16:05 +# 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()), - ("url", wagtail.blocks.TextBlock()), - ("text", wagtail.blocks.RichTextBlock(required=False)), - ] - ), - ), - ( - "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), ), ] diff --git a/server/vbv_lernwelt/learnpath/migrations/0013_alter_learningcontent_contents.py b/server/vbv_lernwelt/learnpath/migrations/0013_alter_learningcontent_contents.py deleted file mode 100644 index dc53258c..00000000 --- a/server/vbv_lernwelt/learnpath/migrations/0013_alter_learningcontent_contents.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 3.2.13 on 2023-03-29 13:39 - -from django.db import migrations -import wagtail.blocks -import wagtail.fields - - -class Migration(migrations.Migration): - - dependencies = [ - ('learnpath', '0012_auto_20230309_0711'), - ] - - 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()), ('url', wagtail.blocks.TextBlock())])), ('placeholder', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('feedback', wagtail.blocks.StructBlock([]))], use_json_field=None), - ), - ] diff --git a/server/vbv_lernwelt/learnpath/migrations/0014_alter_learningcontent_contents.py b/server/vbv_lernwelt/learnpath/migrations/0014_alter_learningcontent_contents.py deleted file mode 100644 index bc33968f..00000000 --- a/server/vbv_lernwelt/learnpath/migrations/0014_alter_learningcontent_contents.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 3.2.13 on 2023-03-29 13:44 - -from django.db import migrations -import wagtail.blocks -import wagtail.fields - - -class Migration(migrations.Migration): - - dependencies = [ - ('learnpath', '0013_alter_learningcontent_contents'), - ] - - 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())])), ('placeholder', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('feedback', wagtail.blocks.StructBlock([]))], use_json_field=None), - ), - ] diff --git a/server/vbv_lernwelt/learnpath/migrations/0015_alter_learningcontent_contents.py b/server/vbv_lernwelt/learnpath/migrations/0015_alter_learningcontent_contents.py deleted file mode 100644 index 3d1c1e58..00000000 --- a/server/vbv_lernwelt/learnpath/migrations/0015_alter_learningcontent_contents.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 3.2.13 on 2023-03-30 13:30 - -from django.db import migrations -import wagtail.blocks -import wagtail.fields - - -class Migration(migrations.Migration): - - dependencies = [ - ('learnpath', '0014_alter_learningcontent_contents'), - ] - - 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([('assignment_slug', wagtail.blocks.TextBlock())])), ('placeholder', wagtail.blocks.StructBlock([('description', wagtail.blocks.TextBlock()), ('url', wagtail.blocks.TextBlock())])), ('feedback', wagtail.blocks.StructBlock([]))], use_json_field=None), - ), - ] diff --git a/server/vbv_lernwelt/learnpath/models_learning_unit_content.py b/server/vbv_lernwelt/learnpath/models_learning_unit_content.py index 5efef576..0fb69bd9 100644 --- a/server/vbv_lernwelt/learnpath/models_learning_unit_content.py +++ b/server/vbv_lernwelt/learnpath/models_learning_unit_content.py @@ -1,12 +1,12 @@ from wagtail import blocks +from wagtail.blocks import PageChooserBlock class AssignmentBlock(blocks.StructBlock): - # TODO: Find way to let user select assignment through foreign key - # Wagtail block data is not stored as "true" database objects, - # but only as JSON text stored against the page, so there's no way to define relations such as ForeignKeys. - # A possible solution are InlinePanels: https://docs.wagtail.org/en/stable/reference/pages/panels.html#inlinepanel - assignment_slug = blocks.TextBlock() + description = blocks.TextBlock() + assignment = PageChooserBlock( + required=True, help_text="Choose the corresponding assignment." + ) class Meta: icon = "media"