diff --git a/server/vbv_lernwelt/feedback/admin.py b/server/vbv_lernwelt/feedback/admin.py index 15e3f383..e69de29b 100644 --- a/server/vbv_lernwelt/feedback/admin.py +++ b/server/vbv_lernwelt/feedback/admin.py @@ -1,7 +0,0 @@ -from vbv_lernwelt.feedback.models import Motivation -from django.contrib.admin import ModelAdmin, register - - -@register(Motivation) -class MotivationAdmin(ModelAdmin): - pass diff --git a/server/vbv_lernwelt/feedback/forms.py b/server/vbv_lernwelt/feedback/forms.py index a0e7732f..aab783e2 100644 --- a/server/vbv_lernwelt/feedback/forms.py +++ b/server/vbv_lernwelt/feedback/forms.py @@ -1,13 +1,9 @@ from django import forms -from vbv_lernwelt.feedback.models import Feedback +from vbv_lernwelt.feedback.models import FeedbackResponse class FeedbackForm(forms.ModelForm): class Meta: - model = Feedback + model = FeedbackResponse fields = "__all__" - - -class NameForm(forms.Form): - your_name = forms.CharField(label="Your name", max_length=100) diff --git a/server/vbv_lernwelt/feedback/graphql/mutations.py b/server/vbv_lernwelt/feedback/graphql/mutations.py index dd27c58b..daf2713b 100644 --- a/server/vbv_lernwelt/feedback/graphql/mutations.py +++ b/server/vbv_lernwelt/feedback/graphql/mutations.py @@ -1,14 +1,13 @@ from graphene_django.rest_framework.mutation import SerializerMutation +import graphene -from vbv_lernwelt.feedback.serializers import FeedbackSerializer +from vbv_lernwelt.feedback.serializers import FeedbackResponseSerializer class SendFeedback(SerializerMutation): - # feedback = graphene.Field(FeedbackType) - class Meta: - # form_class = FeedbackForm - serializer_class = FeedbackSerializer + serializer_class = FeedbackResponseSerializer + model_operations = ["create"] class Mutation(object): diff --git a/server/vbv_lernwelt/feedback/migrations/0001_initial.py b/server/vbv_lernwelt/feedback/migrations/0001_initial.py index 9fe2b6bf..6cb7e6c8 100644 --- a/server/vbv_lernwelt/feedback/migrations/0001_initial.py +++ b/server/vbv_lernwelt/feedback/migrations/0001_initial.py @@ -1,7 +1,8 @@ -# Generated by Django 3.2.13 on 2022-11-17 16:13 +# Generated by Django 3.2.13 on 2022-12-08 11:22 import django.core.validators from django.db import migrations, models +import django.db.models.deletion import vbv_lernwelt.feedback.models @@ -10,33 +11,26 @@ class Migration(migrations.Migration): initial = True dependencies = [ + ('learnpath', '0009_alter_learningcontent_contents'), ] operations = [ migrations.CreateModel( - name='Motivation', + name='FeedbackResponse', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('title', models.CharField(max_length=50)), - ], - ), - migrations.CreateModel( - name='Feedback', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('satisfaction', vbv_lernwelt.feedback.models.FeedbackIntegerField(validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4), django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4)])), - ('goal_attainment', vbv_lernwelt.feedback.models.FeedbackIntegerField(validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4), django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4)])), - ('proficiency', models.IntegerField(validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(5)])), - ('received_materials', models.BooleanField()), - ('materials_rating', vbv_lernwelt.feedback.models.FeedbackIntegerField(blank=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4), django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4)])), - ('instructor_competence', vbv_lernwelt.feedback.models.FeedbackIntegerField(validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4), django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4)])), - ('instructor_respect', vbv_lernwelt.feedback.models.FeedbackIntegerField(validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4), django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4)])), - ('instructor_open_feedback', models.TextField()), - ('would_recommend', models.BooleanField()), - ('course_positive_feedback', models.TextField()), - ('course_negative_feedback', models.TextField()), - ('how_discovered', models.CharField(choices=[('I', 'Internet'), ('L', 'Leaflet'), ('N', 'Newspaper'), ('R', 'Personal recommendation'), ('E', 'Public event'), ('O', 'Other')], max_length=1)), - ('motivation', models.ManyToManyField(to='feedback.Motivation')), + ('satisfaction', vbv_lernwelt.feedback.models.FeedbackIntegerField(null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4), django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4)])), + ('goal_attainment', vbv_lernwelt.feedback.models.FeedbackIntegerField(null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4), django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4)])), + ('proficiency', models.IntegerField(null=True)), + ('received_materials', models.NullBooleanField()), + ('materials_rating', vbv_lernwelt.feedback.models.FeedbackIntegerField(null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4), django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4)])), + ('instructor_competence', vbv_lernwelt.feedback.models.FeedbackIntegerField(null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4), django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4)])), + ('instructor_respect', vbv_lernwelt.feedback.models.FeedbackIntegerField(null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4), django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4)])), + ('instructor_open_feedback', models.TextField(blank=True)), + ('would_recommend', models.NullBooleanField()), + ('course_positive_feedback', models.TextField(blank=True)), + ('course_negative_feedback', models.TextField(blank=True)), + ('circle', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='learnpath.circle')), ], ), ] diff --git a/server/vbv_lernwelt/feedback/models.py b/server/vbv_lernwelt/feedback/models.py index f87ac77f..d647c168 100644 --- a/server/vbv_lernwelt/feedback/models.py +++ b/server/vbv_lernwelt/feedback/models.py @@ -7,20 +7,15 @@ from django.utils.translation import gettext_lazy as _ class FeedbackIntegerField(models.IntegerField): def __init__(self, **kwargs): validators = kwargs.pop("validators", []) + nullable = kwargs.pop("null", True) super().__init__( validators=validators + [MinValueValidator(1), MaxValueValidator(4)], + null=nullable, **kwargs ) -class Motivation(models.Model): - title = models.CharField(max_length=50) - - def __str__(self): - return self.title - - -class Feedback(models.Model): +class FeedbackResponse(models.Model): class DiscoveredChoices(models.TextChoices): INTERNET = "I", _("Internet") LEAFLET = "L", _("Leaflet") @@ -44,14 +39,14 @@ class Feedback(models.Model): satisfaction = FeedbackIntegerField() goal_attainment = FeedbackIntegerField() - proficiency = models.IntegerField() - received_materials = models.BooleanField() - materials_rating = FeedbackIntegerField(blank=True) + proficiency = models.IntegerField(null=True) + received_materials = models.NullBooleanField() + materials_rating = FeedbackIntegerField() instructor_competence = FeedbackIntegerField() instructor_respect = FeedbackIntegerField() - instructor_open_feedback = models.TextField() - would_recommend = models.BooleanField() - course_positive_feedback = models.TextField() - course_negative_feedback = models.TextField() - how_discovered = models.CharField(max_length=1) - motivation = models.ManyToManyField(Motivation) + instructor_open_feedback = models.TextField(blank=True) + would_recommend = models.NullBooleanField() + course_positive_feedback = models.TextField(blank=True) + course_negative_feedback = models.TextField(blank=True) + + circle = models.ForeignKey("learnpath.Circle", models.PROTECT) diff --git a/server/vbv_lernwelt/feedback/serializers.py b/server/vbv_lernwelt/feedback/serializers.py index 6e5152f3..127d8561 100644 --- a/server/vbv_lernwelt/feedback/serializers.py +++ b/server/vbv_lernwelt/feedback/serializers.py @@ -1,9 +1,26 @@ +import structlog from rest_framework import serializers +from wagtail.models import Page -from vbv_lernwelt.feedback.models import Feedback +from vbv_lernwelt.feedback.models import FeedbackResponse + +logger = structlog.get_logger(__name__) -class FeedbackSerializer(serializers.ModelSerializer): +class FeedbackResponseSerializer(serializers.ModelSerializer): + page = serializers.CharField(write_only=True) + class Meta: - model = Feedback - fields = "__all__" + model = FeedbackResponse + exclude = ["circle"] + # extra_kwargs = {"course", {"read_only": True}} + + def create(self, validated_data): + logger.info("creating feedback") + page_key = validated_data.pop("page") + + learning_content = Page.objects.get( + translation_key=page_key, locale__language_code="de-CH" + ) + circle = learning_content.get_parent().specific + return FeedbackResponse.objects.create(**validated_data, circle=circle) diff --git a/server/vbv_lernwelt/learnpath/migrations/0009_alter_learningcontent_contents.py b/server/vbv_lernwelt/learnpath/migrations/0009_alter_learningcontent_contents.py new file mode 100644 index 00000000..8e15731d --- /dev/null +++ b/server/vbv_lernwelt/learnpath/migrations/0009_alter_learningcontent_contents.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.13 on 2022-12-08 09:55 + +from django.db import migrations +import wagtail.blocks +import wagtail.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('learnpath', '0008_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()), ('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([]))], use_json_field=None), + ), + ] diff --git a/server/vbv_lernwelt/learnpath/models.py b/server/vbv_lernwelt/learnpath/models.py index ac2db8c8..6d85877c 100644 --- a/server/vbv_lernwelt/learnpath/models.py +++ b/server/vbv_lernwelt/learnpath/models.py @@ -14,7 +14,7 @@ from vbv_lernwelt.learnpath.models_learning_unit_content import ( BookBlock, DocumentBlock, ExerciseBlock, - LearningModuleBlock, + FeedbackBlock, LearningModuleBlock, MediaLibraryBlock, OnlineTrainingBlock, PlaceholderBlock, @@ -267,6 +267,7 @@ class LearningContent(CourseBasePage): ("book", BookBlock()), ("assignment", AssignmentBlock()), ("placeholder", PlaceholderBlock()), + ("feedback", FeedbackBlock()), ] contents = StreamField( diff --git a/server/vbv_lernwelt/learnpath/models_learning_unit_content.py b/server/vbv_lernwelt/learnpath/models_learning_unit_content.py index 721bf242..9bf81961 100644 --- a/server/vbv_lernwelt/learnpath/models_learning_unit_content.py +++ b/server/vbv_lernwelt/learnpath/models_learning_unit_content.py @@ -90,3 +90,8 @@ class PlaceholderBlock(blocks.StructBlock): class Meta: icon = "media" + + +class FeedbackBlock(blocks.StructBlock): + class Meta: + icon = "media"