Skip to content

Commit cbbce29

Browse files
committed
add feedback form to answer detail page
1 parent 51a2115 commit cbbce29

File tree

23 files changed

+634
-0
lines changed

23 files changed

+634
-0
lines changed

apps/feedback/__init__.py

Whitespace-only changes.

apps/feedback/admin.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from django.utils.translation import gettext_lazy as _
2+
from wagtail_modeladmin.options import ModelAdmin, modeladmin_register
3+
4+
from apps.feedback.models import Feedback
5+
6+
7+
class FeedbackAdmin(ModelAdmin):
8+
model = Feedback
9+
menu_label = _("Feedback")
10+
menu_icon = "comment"
11+
menu_order = 291
12+
add_to_settings_menu = False
13+
exclude_from_explorer = False
14+
list_display = ("answer", "feedback", "user_email", "date_asked", "status")
15+
search_fields = ("user_email", "answer", "feedback", "status", "date_asked")
16+
17+
18+
modeladmin_register(FeedbackAdmin)

apps/feedback/apps.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from django.apps import AppConfig
2+
3+
from apps.core.utils import check_for_debug_settings_in_production
4+
5+
6+
class FeedbackConfig(AppConfig):
7+
name = "apps.feedback"
8+
9+
def ready(self):
10+
check_for_debug_settings_in_production()

apps/feedback/forms.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from django import forms
2+
from django.utils.translation import gettext_lazy as _
3+
4+
from apps.feedback.models.models import Feedback
5+
6+
7+
class FeedbackForm(forms.ModelForm):
8+
feedback = forms.CharField(
9+
label=_("Have a question or comment? Leave it here!"),
10+
help_text=_("We will forward this response to the expert."),
11+
required=False,
12+
)
13+
14+
grade = forms.IntegerField(
15+
label=_("Do you find this article clearly explained and easy to follow?*"),
16+
help_text=_("(0 = not clear, 5 = very clear)"),
17+
required=True,
18+
)
19+
reliability_grade = forms.IntegerField(
20+
label=_("Do you find this KlimaatHelpdesk article reliable?*"),
21+
help_text=_("(0 = not reliable, 5 = very reliable)"),
22+
required=True,
23+
)
24+
25+
user_name = forms.CharField(
26+
label=_("What is your name?"),
27+
required=False,
28+
)
29+
user_email = forms.CharField(
30+
label=_("Email"),
31+
help_text=_("We will forward the expert's response when we receive it."),
32+
required=False,
33+
)
34+
user_age = forms.IntegerField(label=_("What is your age?"), required=False)
35+
36+
class Meta:
37+
model = Feedback
38+
fields = [
39+
"feedback",
40+
"grade",
41+
"reliability_grade",
42+
"user_name",
43+
"user_email",
44+
"user_age",
45+
]
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# Generated by Django 4.2.11 on 2024-04-30 09:22
2+
3+
from django.db import migrations, models
4+
import django.db.models.deletion
5+
import wagtail.contrib.routable_page.models
6+
import wagtail.fields
7+
8+
9+
class Migration(migrations.Migration):
10+
11+
initial = True
12+
13+
dependencies = [
14+
("cms", "0003_alter_answertag_tag"),
15+
("wagtailcore", "0089_log_entry_data_json_null_to_object"),
16+
]
17+
18+
operations = [
19+
migrations.CreateModel(
20+
name="FeedbackFormPage",
21+
fields=[
22+
(
23+
"page_ptr",
24+
models.OneToOneField(
25+
auto_created=True,
26+
on_delete=django.db.models.deletion.CASCADE,
27+
parent_link=True,
28+
primary_key=True,
29+
serialize=False,
30+
to="wagtailcore.page",
31+
),
32+
),
33+
("intro", wagtail.fields.RichTextField(verbose_name="Intro")),
34+
(
35+
"thank_you_text",
36+
wagtail.fields.RichTextField(
37+
default="<p>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.</p>",
38+
verbose_name="Tekst",
39+
),
40+
),
41+
],
42+
options={
43+
"verbose_name": "Feedback formulier pagina",
44+
"verbose_name_plural": "Feedback formulier pagina's",
45+
},
46+
bases=(
47+
wagtail.contrib.routable_page.models.RoutablePageMixin,
48+
"wagtailcore.page",
49+
),
50+
),
51+
migrations.CreateModel(
52+
name="Feedback",
53+
fields=[
54+
(
55+
"id",
56+
models.AutoField(
57+
auto_created=True,
58+
primary_key=True,
59+
serialize=False,
60+
verbose_name="ID",
61+
),
62+
),
63+
(
64+
"feedback",
65+
models.TextField(
66+
help_text="We will forward this response to the expert.",
67+
verbose_name="Have a question or comment? Leave it here!",
68+
),
69+
),
70+
(
71+
"grade",
72+
models.PositiveSmallIntegerField(
73+
blank=True,
74+
help_text="(0 = not clear, 5 = very clear)",
75+
null=True,
76+
verbose_name="Do you find this article clearly explained and easy to follow?",
77+
),
78+
),
79+
(
80+
"reliability_grade",
81+
models.PositiveSmallIntegerField(
82+
help_text="(0 = not reliable, 5 = very reliable)",
83+
verbose_name="Do you find this KlimaatHelpdesk article reliable?",
84+
),
85+
),
86+
(
87+
"user_name",
88+
models.TextField(
89+
blank=True, null=True, verbose_name="What is your name?"
90+
),
91+
),
92+
(
93+
"user_email",
94+
models.EmailField(
95+
blank=True,
96+
help_text="We will forward the expert's response when we receive it.",
97+
max_length=254,
98+
null=True,
99+
verbose_name="Email",
100+
),
101+
),
102+
(
103+
"user_age",
104+
models.PositiveSmallIntegerField(
105+
blank=True, null=True, verbose_name="What is your age?"
106+
),
107+
),
108+
("feedback_by_ip", models.GenericIPAddressField(blank=True, null=True)),
109+
("date_asked", models.DateTimeField(auto_now_add=True)),
110+
(
111+
"status",
112+
models.IntegerField(
113+
choices=[
114+
(0, "Undecided"),
115+
(1, "Approved"),
116+
(2, "Answered"),
117+
(3, "Rejected"),
118+
],
119+
default=0,
120+
),
121+
),
122+
(
123+
"answer",
124+
models.ForeignKey(
125+
null=True,
126+
on_delete=django.db.models.deletion.SET_NULL,
127+
to="cms.answer",
128+
),
129+
),
130+
],
131+
),
132+
]

apps/feedback/migrations/__init__.py

Whitespace-only changes.

apps/feedback/models/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from .models import * # noqa
2+
from .pages import * # noqa

apps/feedback/models/models.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
from django.db import models
2+
from django.utils.translation import gettext_lazy as _
3+
from wagtail.admin.panels import FieldPanel, MultiFieldPanel, HelpPanel, \
4+
TitleFieldPanel, InlinePanel
5+
6+
7+
class Feedback(models.Model):
8+
UNDECIDED = 0
9+
APPROVED = 1
10+
ANSWERED = 2
11+
REJECTED = 3
12+
13+
STATUS_CHOICES = (
14+
(UNDECIDED, _("Undecided")),
15+
(APPROVED, _("Approved")),
16+
(ANSWERED, _("Answered")),
17+
(REJECTED, _("Rejected")),
18+
)
19+
answer = models.ForeignKey(
20+
to="cms.Answer",
21+
on_delete=models.SET_NULL,
22+
null=True,
23+
)
24+
25+
feedback = models.TextField(
26+
verbose_name=_("Have a question or comment? Leave it here!"),
27+
help_text=_("We will forward this response to the expert."),
28+
29+
)
30+
31+
grade = models.PositiveSmallIntegerField(
32+
verbose_name=_(
33+
"Do you find this article clearly explained and easy to follow?"
34+
),
35+
help_text=_("(0 = not clear, 5 = very clear)"), null=True, blank=True
36+
)
37+
reliability_grade = models.PositiveSmallIntegerField(
38+
verbose_name=_("Do you find this KlimaatHelpdesk article reliable?"),
39+
help_text=_("(0 = not reliable, 5 = very reliable)"),
40+
)
41+
42+
user_name = models.TextField(verbose_name=_("What is your name?"), null=True,
43+
blank=True)
44+
user_email = models.EmailField(
45+
verbose_name=_("Email"),
46+
help_text=_("We will forward the expert's response when we receive it."),
47+
null=True,
48+
blank=True,
49+
)
50+
user_age = models.PositiveSmallIntegerField(verbose_name=_("What is your age?"),
51+
null=True, blank=True)
52+
53+
feedback_by_ip = models.GenericIPAddressField(null=True, blank=True)
54+
date_asked = models.DateTimeField(auto_now_add=True)
55+
status = models.IntegerField(choices=STATUS_CHOICES, default=UNDECIDED)
56+
57+
panels = [
58+
MultiFieldPanel(
59+
[
60+
FieldPanel("answer", read_only=True),
61+
],
62+
heading=_("Answer"),
63+
),
64+
MultiFieldPanel(
65+
[
66+
FieldPanel("status"),
67+
FieldPanel("feedback", read_only=True),
68+
FieldPanel("grade", read_only=True),
69+
FieldPanel("reliability_grade", read_only=True),
70+
],
71+
heading=_("Feedback"),
72+
),
73+
MultiFieldPanel(
74+
[
75+
76+
FieldPanel("user_name", read_only=True),
77+
FieldPanel("user_email", read_only=True),
78+
FieldPanel("user_age", read_only=True),
79+
FieldPanel("feedback_by_ip", read_only=True),
80+
81+
],
82+
heading=_("User information"),
83+
),
84+
]

apps/feedback/models/pages.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
from django.apps import apps
2+
from django.http import HttpResponseRedirect
3+
from django.shortcuts import render
4+
from wagtail.admin.panels import FieldPanel, MultiFieldPanel
5+
from wagtail.contrib.routable_page.models import RoutablePageMixin, path, re_path, route
6+
from wagtail.fields import RichTextField
7+
from wagtail.models import Page
8+
9+
from apps.feedback.forms import FeedbackForm
10+
11+
12+
class FeedbackFormPage(RoutablePageMixin, Page):
13+
intro = RichTextField(
14+
verbose_name="Intro",
15+
)
16+
thank_you_text = RichTextField(
17+
verbose_name="Tekst",
18+
default="<p>Bedankt voor het stellen van je vraag. "
19+
"We nemen je vraag in behandeling en proberen zo snel mogelijk een "
20+
"expert te vinden die je vraag kan beantwoorden.</p>",
21+
)
22+
23+
content_panels = Page.content_panels + [
24+
MultiFieldPanel(
25+
[
26+
FieldPanel("intro"),
27+
FieldPanel("thank_you_text"),
28+
],
29+
heading="Formulier tekst",
30+
),
31+
]
32+
33+
@path("<int:answer_id>/")
34+
def form(self, request, answer_id):
35+
"""
36+
Index page, the form is spread over two steps using JavaScript.
37+
"""
38+
if request.method == "POST":
39+
form = FeedbackForm(request.POST)
40+
if form.is_valid():
41+
obj = form.save(commit=False)
42+
obj.answer_id = answer_id
43+
obj.asked_by_ip = request.META.get("REMOTE_ADDR", "")
44+
obj.save()
45+
return HttpResponseRedirect(
46+
self.url + self.reverse_subpage("thank-you")
47+
)
48+
else:
49+
form = FeedbackForm()
50+
51+
template = "feedback/feedback_form_page.html"
52+
context = self.get_context(request)
53+
Answer = apps.get_model(app_label='cms', model_name='Answer')
54+
context.update({"answer": Answer.objects.get(id=answer_id)})
55+
context.update({"form": form})
56+
return render(request, template, context)
57+
58+
@re_path(r"^dank/", name="thank-you")
59+
def thank_you(self, request):
60+
template = "wagtail_helpdesk/cms/ask_question_page_thank_you.html"
61+
context = self.get_context(request)
62+
return render(request, template, context)
63+
64+
class Meta:
65+
verbose_name = "Feedback formulier pagina"
66+
verbose_name_plural = "Feedback formulier pagina's"
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from django import template
2+
3+
from apps.feedback.models import FeedbackFormPage
4+
5+
register = template.Library()
6+
7+
8+
@register.simple_tag
9+
def get_feedback_page():
10+
return FeedbackFormPage.objects.live().first()

0 commit comments

Comments
 (0)