diff --git a/apps/feedback/__init__.py b/apps/feedback/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/feedback/admin.py b/apps/feedback/admin.py new file mode 100644 index 0000000..25646d3 --- /dev/null +++ b/apps/feedback/admin.py @@ -0,0 +1,18 @@ +from django.utils.translation import gettext_lazy as _ +from wagtail_modeladmin.options import ModelAdmin, modeladmin_register + +from apps.feedback.models import Feedback + + +class FeedbackAdmin(ModelAdmin): + model = Feedback + menu_label = _("Feedback") + menu_icon = "comment" + menu_order = 291 + add_to_settings_menu = False + exclude_from_explorer = False + list_display = ("answer", "feedback", "user_email", "date_asked", "status") + search_fields = ("user_email", "answer", "feedback", "status", "date_asked") + + +modeladmin_register(FeedbackAdmin) diff --git a/apps/feedback/apps.py b/apps/feedback/apps.py new file mode 100644 index 0000000..bd32c7e --- /dev/null +++ b/apps/feedback/apps.py @@ -0,0 +1,10 @@ +from django.apps import AppConfig + +from apps.core.utils import check_for_debug_settings_in_production + + +class FeedbackConfig(AppConfig): + name = "apps.feedback" + + def ready(self): + check_for_debug_settings_in_production() diff --git a/apps/feedback/forms.py b/apps/feedback/forms.py new file mode 100644 index 0000000..38b7fa6 --- /dev/null +++ b/apps/feedback/forms.py @@ -0,0 +1,45 @@ +from django import forms +from django.utils.translation import gettext_lazy as _ + +from apps.feedback.models.models import Feedback + + +class FeedbackForm(forms.ModelForm): + feedback = forms.CharField( + label=_("Have a question or comment? Leave it here!"), + help_text=_("We will forward this response to the expert."), + required=False, + ) + + grade = forms.IntegerField( + label=_("Do you find this article clearly explained and easy to follow?*"), + help_text=_("(0 = not clear, 5 = very clear)"), + required=True, + ) + reliability_grade = forms.IntegerField( + label=_("Do you find this AI-Helpdesk article reliable?*"), + help_text=_("(0 = not reliable, 5 = very reliable)"), + required=True, + ) + + user_name = forms.CharField( + label=_("What is your name?"), + required=False, + ) + user_email = forms.CharField( + label=_("Email"), + help_text=_("We will forward the expert's response when we receive it."), + required=False, + ) + user_age = forms.IntegerField(label=_("What is your age?"), required=False) + + class Meta: + model = Feedback + fields = [ + "feedback", + "grade", + "reliability_grade", + "user_name", + "user_email", + "user_age", + ] diff --git a/apps/feedback/migrations/0001_initial.py b/apps/feedback/migrations/0001_initial.py new file mode 100644 index 0000000..a0cc514 --- /dev/null +++ b/apps/feedback/migrations/0001_initial.py @@ -0,0 +1,132 @@ +# Generated by Django 4.2.11 on 2024-04-30 09:22 + +from django.db import migrations, models +import django.db.models.deletion +import wagtail.contrib.routable_page.models +import wagtail.fields + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ("cms", "0003_alter_answertag_tag"), + ("wagtailcore", "0089_log_entry_data_json_null_to_object"), + ] + + operations = [ + migrations.CreateModel( + name="FeedbackFormPage", + 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", + ), + ), + ("intro", wagtail.fields.RichTextField(verbose_name="Intro")), + ( + "thank_you_text", + wagtail.fields.RichTextField( + default="
Bedankt voor het stellen van je vraag. We nemen je vraag in behandeling en proberen zo snel mogelijk een expert te vinden die je vraag kan beantwoorden.
", + verbose_name="Tekst", + ), + ), + ], + options={ + "verbose_name": "Feedback formulier pagina", + "verbose_name_plural": "Feedback formulier pagina's", + }, + bases=( + wagtail.contrib.routable_page.models.RoutablePageMixin, + "wagtailcore.page", + ), + ), + migrations.CreateModel( + name="Feedback", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "feedback", + models.TextField( + help_text="We will forward this response to the expert.", + verbose_name="Have a question or comment? Leave it here!", + ), + ), + ( + "grade", + models.PositiveSmallIntegerField( + blank=True, + help_text="(0 = not clear, 5 = very clear)", + null=True, + verbose_name="Do you find this article clearly explained and easy to follow?", + ), + ), + ( + "reliability_grade", + models.PositiveSmallIntegerField( + help_text="(0 = not reliable, 5 = very reliable)", + verbose_name="Do you find this KlimaatHelpdesk article reliable?", + ), + ), + ( + "user_name", + models.TextField( + blank=True, null=True, verbose_name="What is your name?" + ), + ), + ( + "user_email", + models.EmailField( + blank=True, + help_text="We will forward the expert's response when we receive it.", + max_length=254, + null=True, + verbose_name="Email", + ), + ), + ( + "user_age", + models.PositiveSmallIntegerField( + blank=True, null=True, verbose_name="What is your age?" + ), + ), + ("feedback_by_ip", models.GenericIPAddressField(blank=True, null=True)), + ("date_asked", models.DateTimeField(auto_now_add=True)), + ( + "status", + models.IntegerField( + choices=[ + (0, "Undecided"), + (1, "Approved"), + (2, "Answered"), + (3, "Rejected"), + ], + default=0, + ), + ), + ( + "answer", + models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.SET_NULL, + to="cms.answer", + ), + ), + ], + ), + ] diff --git a/apps/feedback/migrations/0002_alter_feedback_grade_and_more.py b/apps/feedback/migrations/0002_alter_feedback_grade_and_more.py new file mode 100644 index 0000000..128bb79 --- /dev/null +++ b/apps/feedback/migrations/0002_alter_feedback_grade_and_more.py @@ -0,0 +1,52 @@ +# Generated by Django 4.2.11 on 2024-05-06 08:00 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("feedback", "0001_initial"), + ] + + operations = [ + migrations.AlterField( + model_name="feedback", + name="grade", + field=models.PositiveSmallIntegerField( + blank=True, + help_text="(0 = not clear, 5 = very clear)", + verbose_name="Do you find this article clearly explained and easy to follow?", + ), + ), + migrations.AlterField( + model_name="feedback", + name="reliability_grade", + field=models.PositiveSmallIntegerField( + help_text="(0 = not reliable, 5 = very reliable)", + verbose_name="Do you find this AIHelpdesk article reliable?", + ), + ), + migrations.AlterField( + model_name="feedback", + name="user_age", + field=models.PositiveSmallIntegerField( + blank=True, verbose_name="What is your age?" + ), + ), + migrations.AlterField( + model_name="feedback", + name="user_email", + field=models.EmailField( + blank=True, + help_text="We will forward the expert's response when we receive it.", + max_length=254, + verbose_name="Email", + ), + ), + migrations.AlterField( + model_name="feedback", + name="user_name", + field=models.TextField(blank=True, verbose_name="What is your name?"), + ), + ] diff --git a/apps/feedback/migrations/0003_alter_feedback_user_age.py b/apps/feedback/migrations/0003_alter_feedback_user_age.py new file mode 100644 index 0000000..bacc93a --- /dev/null +++ b/apps/feedback/migrations/0003_alter_feedback_user_age.py @@ -0,0 +1,20 @@ +# Generated by Django 4.2.11 on 2024-05-06 08:02 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("feedback", "0002_alter_feedback_grade_and_more"), + ] + + operations = [ + migrations.AlterField( + model_name="feedback", + name="user_age", + field=models.PositiveSmallIntegerField( + blank=True, null=True, verbose_name="What is your age?" + ), + ), + ] diff --git a/apps/feedback/migrations/__init__.py b/apps/feedback/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/feedback/models/__init__.py b/apps/feedback/models/__init__.py new file mode 100644 index 0000000..327332a --- /dev/null +++ b/apps/feedback/models/__init__.py @@ -0,0 +1,2 @@ +from .models import * # noqa +from .pages import * # noqa diff --git a/apps/feedback/models/models.py b/apps/feedback/models/models.py new file mode 100644 index 0000000..df62bfb --- /dev/null +++ b/apps/feedback/models/models.py @@ -0,0 +1,83 @@ +from django.db import models +from django.utils.translation import gettext_lazy as _ +from wagtail.admin.panels import FieldPanel, MultiFieldPanel, HelpPanel, \ + TitleFieldPanel, InlinePanel + + +class Feedback(models.Model): + UNDECIDED = 0 + APPROVED = 1 + ANSWERED = 2 + REJECTED = 3 + + STATUS_CHOICES = ( + (UNDECIDED, _("Undecided")), + (APPROVED, _("Approved")), + (ANSWERED, _("Answered")), + (REJECTED, _("Rejected")), + ) + answer = models.ForeignKey( + to="cms.Answer", + on_delete=models.SET_NULL, + null=True, + ) + + feedback = models.TextField( + verbose_name=_("Have a question or comment? Leave it here!"), + help_text=_("We will forward this response to the expert."), + + ) + + grade = models.PositiveSmallIntegerField( + verbose_name=_( + "Do you find this article clearly explained and easy to follow?" + ), + help_text=_("(0 = not clear, 5 = very clear)"), blank=True + ) + reliability_grade = models.PositiveSmallIntegerField( + verbose_name=_("Do you find this AI-Helpdesk article reliable?"), + help_text=_("(0 = not reliable, 5 = very reliable)"), + ) + + user_name = models.TextField(verbose_name=_("What is your name?"), + blank=True) + user_email = models.EmailField( + verbose_name=_("Email"), + help_text=_("We will forward the expert's response when we receive it."), + blank=True, + ) + user_age = models.PositiveSmallIntegerField(verbose_name=_("What is your age?"), + null=True, blank=True) + + feedback_by_ip = models.GenericIPAddressField(null=True, blank=True) + date_asked = models.DateTimeField(auto_now_add=True) + status = models.IntegerField(choices=STATUS_CHOICES, default=UNDECIDED) + + panels = [ + MultiFieldPanel( + [ + FieldPanel("answer", read_only=True), + ], + heading=_("Answer"), + ), + MultiFieldPanel( + [ + FieldPanel("status"), + FieldPanel("feedback", read_only=True), + FieldPanel("grade", read_only=True), + FieldPanel("reliability_grade", read_only=True), + ], + heading=_("Feedback"), + ), + MultiFieldPanel( + [ + + FieldPanel("user_name", read_only=True), + FieldPanel("user_email", read_only=True), + FieldPanel("user_age", read_only=True), + FieldPanel("feedback_by_ip", read_only=True), + + ], + heading=_("User information"), + ), + ] diff --git a/apps/feedback/models/pages.py b/apps/feedback/models/pages.py new file mode 100644 index 0000000..0db49e6 --- /dev/null +++ b/apps/feedback/models/pages.py @@ -0,0 +1,66 @@ +from django.apps import apps +from django.http import HttpResponseRedirect +from django.shortcuts import render +from wagtail.admin.panels import FieldPanel, MultiFieldPanel +from wagtail.contrib.routable_page.models import RoutablePageMixin, path, re_path, route +from wagtail.fields import RichTextField +from wagtail.models import Page +from wagtail_helpdesk.cms.models import Answer + +from apps.feedback.forms import FeedbackForm + + +class FeedbackFormPage(RoutablePageMixin, Page): + intro = RichTextField( + verbose_name="Intro", + ) + thank_you_text = RichTextField( + verbose_name="Tekst", + default="Bedankt voor het stellen van je vraag. " + "We nemen je vraag in behandeling en proberen zo snel mogelijk een " + "expert te vinden die je vraag kan beantwoorden.
", + ) + + content_panels = Page.content_panels + [ + MultiFieldPanel( + [ + FieldPanel("intro"), + FieldPanel("thank_you_text"), + ], + heading="Formulier tekst", + ), + ] + + @path("+ {% trans "What did you think of this answer?" %} {% trans "Give us your opinion" %} +
+