Skip to content

Commit

Permalink
ECIL-325 Fix error summary links for several form fields.
Browse files Browse the repository at this point in the history
Changes:
  - Fix error summary link for GovUKDateInputField.
  - Fix error summary link for GovUKCheckboxesField.
  - Fix error summary link for GovUKRadioInputField.
  - Add test for error_summary_kwargs.
  - Rename GDSMixin to GDSFieldMixin.
  • Loading branch information
MattHolmes123 committed Dec 5, 2024
1 parent e9a03d9 commit 6789c28
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 57 deletions.
3 changes: 3 additions & 0 deletions pii-ner-exclude.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5200,3 +5200,6 @@ MultiValueField
dict[str
HTML
{{ application_field(process.manufacturing_process
# Conditional
GovUKSelectField
id_text_input_field
50 changes: 28 additions & 22 deletions web/ecil/gds/forms/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from .validators import MaxWordsValidator


class GDSMixin:
class GDSFieldMixin:
# Field template name
template_name: ClassVar[str | None] = None
# BoundField class that defines Nunjucks context
Expand Down Expand Up @@ -65,7 +65,7 @@ def _get_errors(self) -> serializers.ErrorMessage | None:
return serializers.ErrorMessage(text=" ".join(self.errors))


class GovUKCharacterCountField(GDSMixin, forms.CharField):
class GovUKCharacterCountField(GDSFieldMixin, forms.CharField):
def __init__(
self, *args: Any, max_length: int | None = None, max_words: int | None = None, **kwargs: Any
) -> None:
Expand Down Expand Up @@ -110,7 +110,7 @@ def get_context(self) -> dict[str, Any]:
return context


class GovUKCheckboxesField(GDSMixin, forms.MultipleChoiceField):
class GovUKCheckboxesField(GDSFieldMixin, forms.MultipleChoiceField):
class BF(GDSBoundField):
def get_context(self) -> dict[str, Any]:
context = super().get_context()
Expand All @@ -126,8 +126,8 @@ def get_context(self) -> dict[str, Any]:
),
hint=self._get_hint(),
items=[
serializers.CheckboxItem(value=value, text=label)
for value, label in self.field.choices
serializers.CheckboxItem(id=f"{self.auto_id}_{i}", value=value, text=label)
for i, (value, label) in enumerate(self.field.choices)
],
values=self.data or self.initial or [],
errorMessage=self._get_errors(),
Expand Down Expand Up @@ -163,7 +163,7 @@ def decompress(self, value):
return None, None, None


class GovUKDateInputField(GDSMixin, forms.MultiValueField):
class GovUKDateInputField(GDSFieldMixin, forms.MultiValueField):
widget = DateMultiWidget

default_error_messages = {
Expand Down Expand Up @@ -206,9 +206,15 @@ def get_context(self) -> dict[str, Any]:
),
hint=self._get_hint(),
items=[
serializers.DateItem(label="Day", name=f"{self.name}_0", value=value[0]),
serializers.DateItem(label="Month", name=f"{self.name}_1", value=value[1]),
serializers.DateItem(label="Year", name=f"{self.name}_2", value=value[2]),
serializers.DateItem(
label="Day", name=f"{self.name}_0", value=value[0], id=f"{self.auto_id}_0"
),
serializers.DateItem(
label="Month", name=f"{self.name}_1", value=value[1], id=f"{self.auto_id}_1"
),
serializers.DateItem(
label="Year", name=f"{self.name}_2", value=value[2], id=f"{self.auto_id}_2"
),
],
errorMessage=self._get_errors(),
attributes=self.field.widget.attrs,
Expand Down Expand Up @@ -289,7 +295,7 @@ def compress(self, data_list: list[str | None]) -> dt.date | None:
return None


class GovUKDecimalField(GDSMixin, forms.DecimalField):
class GovUKDecimalField(GDSFieldMixin, forms.DecimalField):
class BF(GDSBoundField):
def get_context(self) -> dict[str, Any]:
context = super().get_context()
Expand All @@ -316,7 +322,7 @@ def get_context(self) -> dict[str, Any]:
return context


class GovUKEmailField(GDSMixin, forms.EmailField):
class GovUKEmailField(GDSFieldMixin, forms.EmailField):
class BF(GDSBoundField):
def get_context(self) -> dict[str, Any]:
context = super().get_context()
Expand All @@ -338,7 +344,7 @@ def get_context(self) -> dict[str, Any]:
return context


class GovUKFileUploadField(GDSMixin, ICMSFileField):
class GovUKFileUploadField(GDSFieldMixin, ICMSFileField):
class BF(GDSBoundField):
def get_context(self) -> dict[str, Any]:
context = super().get_context()
Expand All @@ -363,7 +369,7 @@ def get_context(self) -> dict[str, Any]:
return context


class GovUKFloatField(GDSMixin, forms.FloatField):
class GovUKFloatField(GDSFieldMixin, forms.FloatField):
class BF(GDSBoundField):
def get_context(self) -> dict[str, Any]:
context = super().get_context()
Expand All @@ -385,7 +391,7 @@ def get_context(self) -> dict[str, Any]:
return context


class GovUKIntegerField(GDSMixin, forms.IntegerField):
class GovUKIntegerField(GDSFieldMixin, forms.IntegerField):
"""Custom field using django IntegerField validation and rendering a gds text-input."""

class BF(GDSBoundField):
Expand All @@ -409,7 +415,7 @@ def get_context(self) -> dict[str, Any]:
return context


class GovUKPasswordInputField(GDSMixin, forms.CharField):
class GovUKPasswordInputField(GDSFieldMixin, forms.CharField):
class BF(GDSBoundField):
def get_context(self) -> dict[str, Any]:
context = super().get_context()
Expand All @@ -430,14 +436,14 @@ def get_context(self) -> dict[str, Any]:
return context


class GovUKRadioInputField(GDSMixin, forms.ChoiceField):
class GovUKRadioInputField(GDSFieldMixin, forms.ChoiceField):
class BF(GDSBoundField):
def get_context(self) -> dict[str, Any]:
context = super().get_context()

items = []
for value, label in self.field.choices:
item = {"value": value, "text": label}
for i, (value, label) in enumerate(self.field.choices):
item = {"id": f"{self.auto_id}_{i}", "value": value, "text": label}
if value in self.form.gds_radio_conditional_fields:
item["conditional"] = {"html": self.form.gds_radio_conditional_fields[value]}

Expand All @@ -462,7 +468,7 @@ def get_context(self) -> dict[str, Any]:
return context


class GovUKSelectField(GDSMixin, forms.ChoiceField):
class GovUKSelectField(GDSFieldMixin, forms.ChoiceField):
class BF(GDSBoundField):
def get_context(self) -> dict[str, Any]:
context = super().get_context()
Expand All @@ -487,7 +493,7 @@ def get_context(self) -> dict[str, Any]:
return context


class GovUKSlugField(GDSMixin, forms.SlugField):
class GovUKSlugField(GDSFieldMixin, forms.SlugField):
class BF(GDSBoundField):
def get_context(self) -> dict[str, Any]:
context = super().get_context()
Expand All @@ -508,7 +514,7 @@ def get_context(self) -> dict[str, Any]:
return context


class GovUKTextareaField(GDSMixin, forms.CharField):
class GovUKTextareaField(GDSFieldMixin, forms.CharField):
class BF(GDSBoundField):
def get_context(self) -> dict[str, Any]:
context = super().get_context()
Expand All @@ -530,7 +536,7 @@ def get_context(self) -> dict[str, Any]:
return context


class GovUKTextInputField(GDSMixin, forms.CharField):
class GovUKTextInputField(GDSFieldMixin, forms.CharField):
class BF(GDSBoundField):
def get_context(self) -> dict[str, Any]:
context = super().get_context()
Expand Down
24 changes: 19 additions & 5 deletions web/ecil/gds/forms/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,27 @@ def error_summary_kwargs(self) -> dict[str, Any]:
if not self.errors:
return {}

# TODO: Revisit in ECIL-325 to fix checkbox, date and radio input fields.
error_list = []

for field_name, error in self.errors.items():
match self.fields[field_name]:
case gds_fields.GovUKDateInputField():
# Default the date input link to the first field.
href = f"#id_{field_name}_0"
case gds_fields.GovUKCheckboxesField():
# Default to the first checkbox item
href = f"#id_{field_name}_0"
case gds_fields.GovUKRadioInputField():
# Default to the first radio item
href = f"#id_{field_name}_0"
case _:
href = f"#id_{field_name}"

error_list.append({"text": error, "href": href})

return {
"titleText": "There is a problem",
"errorList": [
{"text": error, "href": f"#id_{field_name}"}
for field_name, error in self.errors.items()
],
"errorList": error_list,
}


Expand Down
61 changes: 31 additions & 30 deletions web/tests/ecil/gds/forms/test_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,20 +172,20 @@ def test_template(self):
</div>
<div class="govuk-checkboxes" data-module="govuk-checkboxes">
<div class="govuk-checkboxes__item">
<input class="govuk-checkboxes__input" id="field" name="field" type="checkbox" value="one" checked>
<label class="govuk-label govuk-checkboxes__label" for="field">
<input class="govuk-checkboxes__input" id="id_field_0" name="field" type="checkbox" value="one" checked>
<label class="govuk-label govuk-checkboxes__label" for="id_field_0">
One
</label>
</div>
<div class="govuk-checkboxes__item">
<input class="govuk-checkboxes__input" id="field-2" name="field" type="checkbox" value="two">
<label class="govuk-label govuk-checkboxes__label" for="field-2">
<input class="govuk-checkboxes__input" id="id_field_1" name="field" type="checkbox" value="two">
<label class="govuk-label govuk-checkboxes__label" for="id_field_1">
Two
</label>
</div>
<div class="govuk-checkboxes__item">
<input class="govuk-checkboxes__input" id="field-3" name="field" type="checkbox" value="three">
<label class="govuk-label govuk-checkboxes__label" for="field-3">
<input class="govuk-checkboxes__input" id="id_field_2" name="field" type="checkbox" value="three">
<label class="govuk-label govuk-checkboxes__label" for="id_field_2">
Three
</label>
</div>
Expand Down Expand Up @@ -286,30 +286,29 @@ def test_template(self):
<div id="id_field-hint" class="govuk-hint">
Test help_text
</div>
<div class="govuk-date-input"
id="id_field">
<div class="govuk-date-input" id="id_field">
<div class="govuk-date-input__item">
<div class="govuk-form-group">
<label class="govuk-label govuk-date-input__label" for="id_field-field_0">
<label class="govuk-label govuk-date-input__label" for="id_field_0">
Day
</label>
<input class="govuk-input govuk-date-input__input " id="id_field-field_0" name="field_0" type="text" value="23" inputmode="numeric">
<input class="govuk-input govuk-date-input__input " id="id_field_0" name="field_0" type="text" value="23" inputmode="numeric">
</div>
</div>
<div class="govuk-date-input__item">
<div class="govuk-form-group">
<label class="govuk-label govuk-date-input__label" for="id_field-field_1">
<label class="govuk-label govuk-date-input__label" for="id_field_1">
Month
</label>
<input class="govuk-input govuk-date-input__input " id="id_field-field_1" name="field_1" type="text" value="7" inputmode="numeric">
<input class="govuk-input govuk-date-input__input " id="id_field_1" name="field_1" type="text" value="7" inputmode="numeric">
</div>
</div>
<div class="govuk-date-input__item">
<div class="govuk-form-group">
<label class="govuk-label govuk-date-input__label" for="id_field-field_2">
<label class="govuk-label govuk-date-input__label" for="id_field_2">
Year
</label>
<input class="govuk-input govuk-date-input__input " id="id_field-field_2" name="field_2" type="text" value="2022" inputmode="numeric">
<input class="govuk-input govuk-date-input__input " id="id_field_2" name="field_2" type="text" value="2022" inputmode="numeric">
</div>
</div>
</div>
Expand Down Expand Up @@ -726,21 +725,20 @@ def test_template(self):
</div>
<div class="govuk-radios" data-module="govuk-radios">
<div class="govuk-radios__item">
<input class="govuk-radios__input" id="field" name="field" type="radio" value="one"
checked>
<label class="govuk-label govuk-radios__label" for="field">
<input class="govuk-radios__input" id="id_field_0" name="field" type="radio" value="one" checked>
<label class="govuk-label govuk-radios__label" for="id_field_0">
One
</label>
</div>
<div class="govuk-radios__item">
<input class="govuk-radios__input" id="field-2" name="field" type="radio" value="two">
<label class="govuk-label govuk-radios__label" for="field-2">
<input class="govuk-radios__input" id="id_field_1" name="field" type="radio" value="two">
<label class="govuk-label govuk-radios__label" for="id_field_1">
Two
</label>
</div>
<div class="govuk-radios__item">
<input class="govuk-radios__input" id="field-3" name="field" type="radio" value="three">
<label class="govuk-label govuk-radios__label" for="field-3">
<input class="govuk-radios__input" id="id_field_2" name="field" type="radio" value="three">
<label class="govuk-label govuk-radios__label" for="id_field_2">
Three
</label>
</div>
Expand Down Expand Up @@ -790,12 +788,12 @@ def test_conditional_template(self):
</div>
<div class="govuk-radios" data-module="govuk-radios">
<div class="govuk-radios__item">
<input class="govuk-radios__input" id="field" name="field" type="radio" value="one" data-aria-controls="conditional-field">
<label class="govuk-label govuk-radios__label" for="field">
<input class="govuk-radios__input" id="id_field_0" name="field" type="radio" value="one" data-aria-controls="conditional-id_field_0">
<label class="govuk-label govuk-radios__label" for="id_field_0">
One
</label>
</div>
<div class="govuk-radios__conditional govuk-radios__conditional--hidden" id="conditional-field">
<div class="govuk-radios__conditional govuk-radios__conditional--hidden" id="conditional-id_field_0">
<div class="govuk-form-group">
<h1 class="govuk-label-wrapper">
<label class="govuk-label govuk-label--l" for="id_one">
Expand All @@ -809,12 +807,15 @@ def test_conditional_template(self):
</div>
</div>
<div class="govuk-radios__item">
<input class="govuk-radios__input" id="field-2" name="field" type="radio" value="two" checked data-aria-controls="conditional-field-2">
<label class="govuk-label govuk-radios__label" for="field-2">
<input
class="govuk-radios__input" id="id_field_1" name="field" type="radio" value="two" checked
data-aria-controls="conditional-id_field_1"
>
<label class="govuk-label govuk-radios__label" for="id_field_1">
Two
</label>
</div>
<div class="govuk-radios__conditional" id="conditional-field-2">
<div class="govuk-radios__conditional" id="conditional-id_field_1">
<div class="govuk-form-group">
<h1 class="govuk-label-wrapper">
<label class="govuk-label govuk-label--l" for="id_two">
Expand All @@ -828,12 +829,12 @@ def test_conditional_template(self):
</div>
</div>
<div class="govuk-radios__item">
<input class="govuk-radios__input" id="field-3" name="field" type="radio" value="three" data-aria-controls="conditional-field-3">
<label class="govuk-label govuk-radios__label" for="field-3">
<input class="govuk-radios__input" id="id_field_2" name="field" type="radio" value="three" data-aria-controls="conditional-id_field_2">
<label class="govuk-label govuk-radios__label" for="id_field_2">
Three
</label>
</div>
<div class="govuk-radios__conditional govuk-radios__conditional--hidden" id="conditional-field-3">
<div class="govuk-radios__conditional govuk-radios__conditional--hidden" id="conditional-id_field_2">
<div class="govuk-form-group">
<h1 class="govuk-label-wrapper">
<label class="govuk-label govuk-label--l" for="id_three">
Expand Down
Loading

0 comments on commit 6789c28

Please sign in to comment.