Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce Address answer type #261

Merged
merged 25 commits into from
Sep 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
94b9f9d
Spike Address Lookup
MebinAbraham Aug 17, 2020
b01c10b
Merge spike
MebinAbraham Aug 27, 2020
81e6960
Tidy up
MebinAbraham Aug 27, 2020
9796d18
Add tests
MebinAbraham Aug 27, 2020
9340169
Point to address validator branch
MebinAbraham Aug 27, 2020
e67e94b
Merge branch 'master' into address-answer-type
MebinAbraham Aug 27, 2020
61f80ea
Update messages.pot
MebinAbraham Aug 27, 2020
162bb9b
Revert unnecessary changes
MebinAbraham Aug 27, 2020
1e0dbbd
Address comments
MebinAbraham Sep 1, 2020
05b8f1a
Merge master and resolve conflicts
MebinAbraham Sep 1, 2020
35ceb4f
Fix mypy lint
MebinAbraham Sep 1, 2020
b3322fe
Merge branch 'master' into address-answer-type
MebinAbraham Sep 1, 2020
cf21b93
Merge remote-tracking branch 'origin/master' into address-answer-type
MebinAbraham Sep 1, 2020
35dd9bd
Address comments
MebinAbraham Sep 1, 2020
cfaa712
Merge branch 'address-answer-type' of github.com:ONSdigital/eq-questi…
MebinAbraham Sep 1, 2020
b5c92e1
Fix grammar
MebinAbraham Sep 1, 2020
a8a1590
Remove AddressField and use FormField directly
MebinAbraham Sep 2, 2020
58b9388
Remove custom address validator class
MebinAbraham Sep 2, 2020
67f4efa
Merge master and resolve conflicts
MebinAbraham Sep 2, 2020
1168a47
Address comment
MebinAbraham Sep 3, 2020
4417f38
Merge remote-tracking branch 'origin/master' into address-answer-type
MebinAbraham Sep 3, 2020
47f71b1
Revert scripts/run_validator.sh
MebinAbraham Sep 3, 2020
05d9b2e
Add optional address answer
MebinAbraham Sep 3, 2020
8d95d89
Merge branch 'address-answer-type' of github.com:ONSdigital/eq-questi…
MebinAbraham Sep 3, 2020
6fd61b4
Merge master and resolve conflicts
MebinAbraham Sep 3, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/data_model/answer.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
from __future__ import annotations

from dataclasses import asdict, dataclass, field
from typing import Dict, List, Optional, Union
from typing import Dict, List, Mapping, Optional, Union


@dataclass
class Answer:
answer_id: str
value: Union[str, int, float, List]
value: Union[str, int, float, List, Mapping]
list_item_id: Optional[str] = field(default=None)

@classmethod
Expand Down
20 changes: 20 additions & 0 deletions app/forms/address_form.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import logging
from functools import cached_property

from wtforms import Form, StringField

logger = logging.getLogger(__name__)


def get_address_form(validators):
class AddressForm(Form):
line1 = StringField(validators=validators)
line2 = StringField()
town = StringField()
postcode = StringField()

@cached_property
def data(self):
return super().data

return AddressForm
1 change: 1 addition & 0 deletions app/forms/error_messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
'Select at least one answer <span class="u-vh">to ‘%(question_title)s’</span>'
),
"MANDATORY_DATE": lazy_gettext("Enter a date to continue"),
"MANDATORY_ADDRESS": lazy_gettext("Enter an address to continue"),
"MANDATORY_DURATION": lazy_gettext("Enter a duration to continue"),
"NUMBER_TOO_SMALL": lazy_gettext("Enter an answer more than or equal to %(min)s"),
"NUMBER_TOO_LARGE": lazy_gettext("Enter an answer less than or equal to %(max)s"),
Expand Down
2 changes: 2 additions & 0 deletions app/forms/field_handlers/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .address_handler import AddressHandler
from .date_handlers import DateHandler, MonthYearDateHandler, YearDateHandler
from .dropdown_handler import DropdownHandler
from .duration_handler import DurationHandler
Expand All @@ -21,6 +22,7 @@
"MonthYearDate": MonthYearDateHandler,
"YearDate": YearDateHandler,
"Duration": DurationHandler,
"Address": AddressHandler,
}


Expand Down
37 changes: 37 additions & 0 deletions app/forms/field_handlers/address_handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from functools import cached_property
from typing import List

from wtforms import FormField
from wtforms.validators import InputRequired

from app.forms.address_form import get_address_form
from app.forms.field_handlers.field_handler import FieldHandler
from app.forms.validators import format_message_with_title


class AddressHandler(FieldHandler):
MANDATORY_MESSAGE_KEY = "MANDATORY_ADDRESS"

@cached_property
def validators(self) -> List:
validate_with: List = []

if self.answer_schema["mandatory"]:
validate_with = [
InputRequired(
message=self.get_validation_message(
format_message_with_title(
self.MANDATORY_MESSAGE_KEY, self.question_title
)
)
)
]

return validate_with

def get_field(self) -> FormField:
return FormField(
get_address_form(self.validators),
label=self.label,
description=self.guidance,
)
MebinAbraham marked this conversation as resolved.
Show resolved Hide resolved
6 changes: 6 additions & 0 deletions app/jinja_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ def format_number(value):
return ""


def get_formatted_address(address_fields):
return "<br>".join(address_field for address_field in address_fields.values())


def get_formatted_currency(value, currency="GBP"):
if value or value == 0:
return numbers.format_currency(
Expand Down Expand Up @@ -432,6 +436,8 @@ def __init__( # noqa: C901, R0912 pylint: disable=too-complex, too-many-branche

if value is None or value == "":
self.valueList = [SummaryRowItemValue(no_answer_provided)]
elif answer_type == "address":
self.valueList = [SummaryRowItemValue(get_formatted_address(value))]
elif answer_type == "checkbox":
self.valueList = [
SummaryRowItemValue(option["label"], option["detail_answer_value"])
Expand Down
20 changes: 15 additions & 5 deletions app/questionnaire/questionnaire_store_updater.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
class QuestionnaireStoreUpdater:
"""Component responsible for any actions that need to happen as a result of updating the questionnaire_store"""

EMPTY_ANSWER_VALUES: Tuple = (None, [], "")
EMPTY_ANSWER_VALUES: Tuple = (None, [], "", {})

def __init__(self, current_location, schema, questionnaire_store, current_question):
self._current_location = current_location
Expand Down Expand Up @@ -215,13 +215,23 @@ def update_answers(self, form_data, list_item_id=None):
for answer_id, answer_value in form_data.items():

if answer_id in answer_ids_for_question:
if answer_value not in self.EMPTY_ANSWER_VALUES:
answer_value_to_store = (
Copy link
Contributor

@LJBabbage LJBabbage Sep 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not 100% sure what this is doing, looks to me if answer_value is a dict make another dict with all the empties removed. Then check it's not completely empty at a later stage?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just filtering out any EMPTY_ANSWER_VALUES when the answer is a dict i.e address since we don't store any answers that match EMPTY_ANSWER_VALUES.

{
key: value
for key, value in answer_value.items()
if value not in self.EMPTY_ANSWER_VALUES
}
if isinstance(answer_value, dict)
else answer_value
)

if answer_value_to_store in self.EMPTY_ANSWER_VALUES:
self._answer_store.remove_answer(answer_id, list_item_id)
else:
answer = Answer(
answer_id=answer_id,
list_item_id=list_item_id,
value=answer_value,
value=answer_value_to_store,
)

self._answer_store.add_or_update(answer)
else:
self._answer_store.remove_answer(answer_id, list_item_id)
84 changes: 58 additions & 26 deletions app/translations/messages.pot
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2020-09-01 10:21+0100\n"
"POT-Creation-Date: 2020-09-02 10:39+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email protected]>\n"
Expand All @@ -17,26 +17,26 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.8.0\n"

#: app/forms/validators.py:341 app/jinja_filters.py:81
#: app/forms/validators.py:341 app/jinja_filters.py:85
#, python-format
msgid "%(num)s year"
msgid_plural "%(num)s years"
msgstr[0] ""
msgstr[1] ""

#: app/forms/validators.py:345 app/jinja_filters.py:89
#: app/forms/validators.py:345 app/jinja_filters.py:93
#, python-format
msgid "%(num)s month"
msgid_plural "%(num)s months"
msgstr[0] ""
msgstr[1] ""

#: app/jinja_filters.py:132
#: app/jinja_filters.py:136
#, python-format
msgid "%(date)s at %(time)s"
msgstr ""

#: app/jinja_filters.py:143
#: app/jinja_filters.py:147
#, python-format
msgid "%(from_date)s to %(to_date)s"
msgstr ""
Expand Down Expand Up @@ -67,105 +67,109 @@ msgid "Enter a date to continue"
msgstr ""

#: app/forms/error_messages.py:23
msgid "Enter a duration to continue"
msgid "Enter an address to continue"
msgstr ""

#: app/forms/error_messages.py:24
msgid "Enter a duration to continue"
msgstr ""

#: app/forms/error_messages.py:25
#, python-format
msgid "Enter an answer more than or equal to %(min)s"
msgstr ""

#: app/forms/error_messages.py:25
#: app/forms/error_messages.py:26
#, python-format
msgid "Enter an answer less than or equal to %(max)s"
msgstr ""

#: app/forms/error_messages.py:26
#: app/forms/error_messages.py:27
#, python-format
msgid "Enter an answer more than %(min)s"
msgstr ""

#: app/forms/error_messages.py:27
#: app/forms/error_messages.py:28
#, python-format
msgid "Enter an answer less than %(max)s"
msgstr ""

#: app/forms/error_messages.py:28
#: app/forms/error_messages.py:29
#, python-format
msgid "Enter answers that add up to %(total)s"
msgstr ""

#: app/forms/error_messages.py:29
#: app/forms/error_messages.py:30
#, python-format
msgid "Enter answers that add up to or are less than %(total)s"
msgstr ""

#: app/forms/error_messages.py:32
#: app/forms/error_messages.py:33
#, python-format
msgid "Enter answers that add up to less than %(total)s"
msgstr ""

#: app/forms/error_messages.py:35
#: app/forms/error_messages.py:36
#, python-format
msgid "Enter answers that add up to greater than %(total)s"
msgstr ""

#: app/forms/error_messages.py:38
#: app/forms/error_messages.py:39
#, python-format
msgid "Enter answers that add up to or are greater than %(total)s"
msgstr ""

#: app/forms/error_messages.py:41
#: app/forms/error_messages.py:42
msgid "Enter a number"
msgstr ""

#: app/forms/error_messages.py:42
#: app/forms/error_messages.py:43
msgid "Enter a whole number"
msgstr ""

#: app/forms/error_messages.py:43
#: app/forms/error_messages.py:44
#, python-format
msgid "Enter a number rounded to %(max)d decimal places"
msgstr ""

#: app/forms/error_messages.py:44
#: app/forms/error_messages.py:45
#, python-format
msgid "You have entered too many characters. Enter up to %(max)d characters"
msgstr ""

#: app/forms/error_messages.py:47
#: app/forms/error_messages.py:48
msgid "Enter a valid date"
msgstr ""

#: app/forms/error_messages.py:48
#: app/forms/error_messages.py:49
msgid "Enter a 'period to' date later than the 'period from' date"
msgstr ""

#: app/forms/error_messages.py:51
#: app/forms/error_messages.py:52
msgid "Enter a valid duration"
msgstr ""

#: app/forms/error_messages.py:52
#: app/forms/error_messages.py:53
#, python-format
msgid "Enter a reporting period greater than or equal to %(min)s"
msgstr ""

#: app/forms/error_messages.py:55
#: app/forms/error_messages.py:56
#, python-format
msgid "Enter a reporting period less than or equal to %(max)s"
msgstr ""

#: app/forms/error_messages.py:58
#: app/forms/error_messages.py:59
#, python-format
msgid "Enter a date after %(min)s"
msgstr ""

#: app/forms/error_messages.py:59
#: app/forms/error_messages.py:60
#, python-format
msgid "Enter a date before %(max)s"
msgstr ""

#: app/forms/error_messages.py:60
#: app/forms/error_messages.py:61
msgid "Remove an answer to continue"
msgstr ""

Expand Down Expand Up @@ -795,6 +799,34 @@ msgstr ""
msgid "Or"
msgstr ""

#: templates/partials/answers/address.html:11
msgid "Enter address or postcode and select from results"
msgstr ""

#: templates/partials/answers/address.html:15
msgid "Address line 1"
msgstr ""

#: templates/partials/answers/address.html:20
msgid "Address line 2"
msgstr ""

#: templates/partials/answers/address.html:24
msgid "Town or city"
msgstr ""

#: templates/partials/answers/address.html:28
msgid "Postcode"
msgstr ""

#: templates/partials/answers/address.html:31
msgid "Search for an address"
msgstr ""

#: templates/partials/answers/address.html:32
msgid "Manually enter address"
msgstr ""

#: templates/partials/answers/checkbox.html:8
msgid "Select all that apply"
msgstr ""
Expand Down
35 changes: 35 additions & 0 deletions templates/partials/answers/address.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{% from "components/address/_macro.njk" import onsAddressInput %}

{% set address_form = form.fields[answer.id] %}

{% set config = {
"id": answer.id,
"legend": question.title,
"legendClasses": "u-vh",
"autosuggest":{
"label": {
"text": _("Enter address or postcode and select from results")
},
},
Comment on lines +9 to +13
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was added because the DS component requires this at the moment. This bug will be fixed in the DS soon.

"line1": {
"label": _("Address line 1"),
"value": address_form.line1._value() | e,
"error": error
},
"line2": {
"label": _("Address line 2"),
"value": address_form.line2._value() | e
},
"town": {
"label": _("Town or city"),
"value": address_form.town._value() | e
},
"postcode": {
"label": _("Postcode"),
"value": address_form.postcode._value() | e
},
"searchButton": _("Search for an address"),
"manualButton": _("Manually enter address")
} %}

{{ onsAddressInput(config) }}
Loading