Skip to content

Commit cdd3cd3

Browse files
Add feedback call to action (#374)
Co-authored-by: Andrew Maddaford <ajmaddaford@gmail.com>
1 parent 2417199 commit cdd3cd3

38 files changed

+593
-144
lines changed

Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ build: load-design-system-templates
1717

1818
lint:
1919
pipenv run ./scripts/run_lint_python.sh
20+
yarn lint
2021

2122
format: format-python
2223
yarn format

app/data_models/session_data.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def __init__(
1919
trad_as=None,
2020
display_address=None,
2121
confirmation_email_count=0,
22-
feedback_sent=False,
22+
feedback_count=0,
2323
**_,
2424
): # pylint: disable=too-many-locals
2525
self.tx_id = tx_id
@@ -40,4 +40,4 @@ def __init__(
4040
self.account_service_log_out_url = account_service_log_out_url
4141
self.display_address = display_address
4242
self.confirmation_email_count = confirmation_email_count
43-
self.feedback_sent = feedback_sent
43+
self.feedback_count = feedback_count

app/helpers/session_helpers.py

+14-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from flask_login import current_user
44

5-
from app.globals import get_questionnaire_store
5+
from app.globals import get_questionnaire_store, get_session_store
66

77

88
def with_questionnaire_store(function):
@@ -19,3 +19,16 @@ def wrapped_function(*args, **kwargs):
1919
return function(questionnaire_store, *args, **kwargs)
2020

2121
return wrapped_function
22+
23+
24+
def with_session_store(function):
25+
"""Adds the `session_store` as an argument.
26+
Use on flask request handlers or methods called by flask request handlers.
27+
"""
28+
29+
@wraps(function)
30+
def wrapped_function(*args, **kwargs):
31+
session_store = get_session_store()
32+
return function(session_store, *args, **kwargs)
33+
34+
return wrapped_function

app/routes/errors.py

+36-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from flask import Blueprint, request
22
from flask import session as cookie_session
33
from flask.helpers import url_for
4+
from flask_babel import lazy_gettext
45
from flask_login import current_user
56
from flask_wtf.csrf import CSRFError
67
from sdc.crypto.exceptions import InvalidTokenException
@@ -15,6 +16,7 @@
1516
from app.helpers.template_helpers import render_template
1617
from app.settings import EQ_SESSION_ID
1718
from app.submitter.submission_failed import SubmissionFailedException
19+
from app.views.handlers.feedback import FeedbackLimitReached
1820
from app.views.handlers.individual_response import (
1921
FulfilmentRequestFailedException,
2022
IndividualResponseLimitReached,
@@ -78,7 +80,39 @@ def method_not_allowed(error=None):
7880
@errors_blueprint.app_errorhandler(IndividualResponseLimitReached)
7981
def too_many_individual_response_requests(error=None):
8082
log_error(error, 429)
81-
return _render_error_page(429, template="429-individual-response")
83+
title = lazy_gettext(
84+
"You have reached the maximum number of individual access codes"
85+
)
86+
contact_us_message = lazy_gettext(
87+
"If you need more individual access codes, please <a href='{url}'>contact us</a>."
88+
)
89+
90+
return _render_error_page(
91+
429,
92+
template="429",
93+
page_title=title,
94+
heading=title,
95+
contact_us_message=contact_us_message,
96+
)
97+
98+
99+
@errors_blueprint.app_errorhandler(FeedbackLimitReached)
100+
def too_many_feedback_requests(error=None):
101+
log_error(error, 429)
102+
title = lazy_gettext(
103+
"You have reached the maximum number of times for submitting feedback"
104+
)
105+
contact_us_message = lazy_gettext(
106+
"If you need to give more feedback, please <a href='{url}'>contact us</a>."
107+
)
108+
109+
return _render_error_page(
110+
429,
111+
template="429",
112+
page_title=title,
113+
heading=title,
114+
contact_us_message=contact_us_message,
115+
)
82116

83117

84118
@errors_blueprint.app_errorhandler(SubmissionFailedException)
@@ -110,7 +144,7 @@ def http_exception(error):
110144

111145

112146
@errors_blueprint.app_errorhandler(FulfilmentRequestFailedException)
113-
def fulfilment_request_failed(error):
147+
def fulfilment_request_failed(_):
114148
logger.exception(
115149
"An individual response fulfilment request failed",
116150
url=request.url,

app/routes/questionnaire.py

+47-23
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from app.globals import get_metadata, get_session_store, get_session_timeout_in_seconds
1313
from app.helpers.language_helper import handle_language
1414
from app.helpers.schema_helpers import with_schema
15-
from app.helpers.session_helpers import with_questionnaire_store
15+
from app.helpers.session_helpers import with_questionnaire_store, with_session_store
1616
from app.helpers.template_helpers import get_census_base_url, render_template
1717
from app.helpers.url_param_serializer import URLParamSerializer
1818
from app.questionnaire.location import InvalidLocationException
@@ -26,7 +26,7 @@
2626
)
2727
from app.views.handlers.feedback import (
2828
Feedback,
29-
FeedbackAlreadySent,
29+
FeedbackLimitReached,
3030
FeedbackNotEnabled,
3131
)
3232
from app.views.handlers.section import SectionHandler
@@ -72,7 +72,10 @@ def before_questionnaire_request():
7272
@post_submission_blueprint.before_request
7373
@login_required
7474
def before_post_submission_request():
75-
session_data = get_session_store().session_data
75+
session_store = get_session_store()
76+
session_data = session_store.session_data
77+
if not session_data.submitted_time:
78+
raise NotFound
7679

7780
handle_language()
7881

@@ -277,9 +280,10 @@ def relationships(
277280

278281

279282
@post_submission_blueprint.route("thank-you/", methods=["GET", "POST"])
283+
@with_session_store
280284
@with_schema
281-
def get_thank_you(schema):
282-
thank_you = ThankYou(schema)
285+
def get_thank_you(schema, session_store):
286+
thank_you = ThankYou(schema, session_store)
283287

284288
if request.method == "POST":
285289
if not thank_you.confirmation_email:
@@ -288,37 +292,48 @@ def get_thank_you(schema):
288292
confirmation_email = thank_you.confirmation_email
289293

290294
if confirmation_email.form.validate():
291-
confirmation_email.handle_post()
295+
confirmation_email.handle_post(session_store)
292296
return redirect(
293297
url_for(
294-
"post_submission.get_confirmation_email_sent",
298+
".get_confirmation_email_sent",
295299
email=confirmation_email.get_url_safe_serialized_email(),
296300
)
297301
)
298302

303+
show_feedback_call_to_action = True
304+
305+
try:
306+
Feedback(schema, session_store, form_data=request.form)
307+
except (FeedbackNotEnabled, FeedbackLimitReached):
308+
show_feedback_call_to_action = False
309+
299310
return render_template(
300311
template=thank_you.template,
301-
content=thank_you.get_context(),
312+
content={
313+
**thank_you.get_context(),
314+
"show_feedback_call_to_action": show_feedback_call_to_action,
315+
},
302316
survey_id=schema.json["survey_id"],
303317
page_title=thank_you.get_page_title(),
304318
)
305319

306320

307321
@post_submission_blueprint.route("confirmation-email/send", methods=["GET", "POST"])
308-
def send_confirmation_email():
309-
if not get_session_store().session_data.confirmation_email_count:
322+
@with_session_store
323+
def send_confirmation_email(session_store):
324+
if not session_store.session_data.confirmation_email_count:
310325
raise NotFound
311326

312327
try:
313328
confirmation_email = ConfirmationEmail()
314329
except ConfirmationEmailLimitReached:
315-
return redirect(url_for("post_submission.get_thank_you"))
330+
return redirect(url_for(".get_thank_you"))
316331

317332
if request.method == "POST" and confirmation_email.form.validate():
318-
confirmation_email.handle_post()
333+
confirmation_email.handle_post(session_store)
319334
return redirect(
320335
url_for(
321-
"post_submission.get_confirmation_email_sent",
336+
".get_confirmation_email_sent",
322337
email=confirmation_email.get_url_safe_serialized_email(),
323338
)
324339
)
@@ -332,12 +347,21 @@ def send_confirmation_email():
332347

333348

334349
@post_submission_blueprint.route("confirmation-email/sent", methods=["GET"])
335-
def get_confirmation_email_sent():
336-
if not get_session_store().session_data.confirmation_email_count:
350+
@with_session_store
351+
@with_schema
352+
def get_confirmation_email_sent(schema, session_store):
353+
if not session_store.session_data.confirmation_email_count:
337354
raise NotFound
338355

339356
email = URLParamSerializer().loads(request.args.get("email"))
340357

358+
show_feedback_call_to_action = True
359+
360+
try:
361+
Feedback(schema, session_store, form_data=request.form)
362+
except (FeedbackNotEnabled, FeedbackLimitReached):
363+
show_feedback_call_to_action = False
364+
341365
return render_template(
342366
template="confirmation-email-sent",
343367
content={
@@ -348,35 +372,35 @@ def get_confirmation_email_sent():
348372
"hide_signout_button": False,
349373
"show_send_another_email_guidance": not ConfirmationEmail.is_limit_reached(),
350374
"sign_out_url": url_for("session.get_sign_out"),
375+
"show_feedback_call_to_action": show_feedback_call_to_action,
351376
},
352377
)
353378

354379

355380
@post_submission_blueprint.route("feedback/send", methods=["GET", "POST"])
381+
@with_session_store
356382
@with_schema
357-
def send_feedback(schema):
383+
def send_feedback(schema, session_store):
358384
try:
359-
feedback = Feedback(schema, form_data=request.form)
385+
feedback = Feedback(schema, session_store, form_data=request.form)
360386
except FeedbackNotEnabled:
361387
raise NotFound
362-
except FeedbackAlreadySent:
363-
return redirect(url_for("post_submission.get_feedback_sent"))
364388

365389
if request.method == "POST" and feedback.form.validate():
366390
feedback.handle_post()
367-
return redirect(url_for("post_submission.get_feedback_sent"))
391+
return redirect(url_for(".get_feedback_sent"))
368392

369393
return render_template(
370394
template="feedback",
371395
content=feedback.get_context(),
372-
previous_location_url=url_for("post_submission.get_thank_you"),
373396
page_title=feedback.get_page_title(),
374397
)
375398

376399

377400
@post_submission_blueprint.route("feedback/sent", methods=["GET"])
378-
def get_feedback_sent():
379-
if not get_session_store().session_data.feedback_sent:
401+
@with_session_store
402+
def get_feedback_sent(session_store):
403+
if not session_store.session_data.feedback_count:
380404
raise NotFound
381405

382406
return render_template(

app/settings.py

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ def get_env_or_fail(key):
5353
EQ_PUBLISHER_BACKEND = os.getenv("EQ_PUBLISHER_BACKEND")
5454
EQ_FULFILMENT_TOPIC_ID = os.getenv("EQ_FULFILMENT_TOPIC_ID", "eq-fulfilment-topic")
5555
EQ_INDIVIDUAL_RESPONSE_LIMIT = int(os.getenv("EQ_INDIVIDUAL_RESPONSE_LIMIT", "1"))
56+
EQ_FEEDBACK_LIMIT = int(os.getenv("EQ_INDIVIDUAL_RESPONSE_LIMIT", "10"))
5657

5758
EQ_SUBMISSION_BACKEND = os.getenv("EQ_SUBMISSION_BACKEND")
5859
EQ_GCS_SUBMISSION_BUCKET_ID = os.getenv("EQ_GCS_SUBMISSION_BUCKET_ID")

0 commit comments

Comments
 (0)