Skip to content

Commit

Permalink
Merge branch 'master' into TP2000-1387-py312-async-bulk-edit
Browse files Browse the repository at this point in the history
  • Loading branch information
LaurenMullally committed Sep 20, 2024
2 parents 54be1ce + 1b0ef4d commit 3a05f91
Show file tree
Hide file tree
Showing 49 changed files with 3,059 additions and 280 deletions.
34 changes: 33 additions & 1 deletion common/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from crispy_forms_gds.layout import Submit
from django import forms
from django.contrib.postgres.forms.ranges import DateRangeField
from django.core.exceptions import NON_FIELD_ERRORS
from django.core.exceptions import ValidationError
from django.forms.renderers import get_default_renderer
from django.forms.utils import ErrorList
Expand Down Expand Up @@ -425,7 +426,7 @@ def __init__(self, *args, **kwargs):

self.fields["end_date"].help_text = (
f"Leave empty if {get_model_indefinite_article(self.instance)} "
f"{self.instance._meta.verbose_name} is needed for an unlimited time."
f"{self.instance._meta.verbose_name} is needed for an unlimited time"
)

if self.instance.valid_between:
Expand Down Expand Up @@ -892,3 +893,34 @@ def deserialize_init_kwargs(cls, form_kwargs: Dict) -> Dict:
representation.
"""
return {}


class ExtraErrorFormMixin:
def add_extra_error(self, field, error):
"""
A modification of Django's add_error method that allows us to add data
to self._errors under custom keys that are not field names or
NON_FIELD_ERRORS.
Used to pass errors to the React form.
"""
if not isinstance(error, ValidationError):
error = ValidationError(error)

if hasattr(error, "error_dict"):
if field is not None:
raise TypeError(
"The argument `field` must be `None` when the `error` "
"argument contains errors for multiple fields.",
)
else:
error = error.error_dict
else:
error = {field or NON_FIELD_ERRORS: error.error_list}

for field, error_list in error.items():
if field not in self.errors:
self._errors[field] = self.error_class()
self._errors[field].extend(error_list)
if field in self.cleaned_data:
del self.cleaned_data[field]
6 changes: 3 additions & 3 deletions common/jinja2/common/app_info.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@
{"text": "Environment variable"},
],
[
{"text": "APP_UPDATED_TIME"},
{"text": APP_UPDATED_TIME},
{"text": "Estimated application deploy time"},
{"text": "UPTIME"},
{"text": UPTIME},
{"text": "Time this instance has been in service"},
],
[
{"text": "LAST_TRANSACTION_TIME"},
Expand Down
10 changes: 3 additions & 7 deletions common/jinja2/layouts/create.jinja
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
{% extends 'layouts/form.jinja' %}

{% block form %}
<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">
{% call django_form() %}
{{ crispy(form) }}
{% endcall %}
</div>
</div>
{% call django_form() %}
{{ crispy(form) }}
{% endcall %}
{% endblock %}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ function QuotaOriginFormset({
groupsWithMembers,
errors,
}) {
const [origins, setOrigins] = useState([...data]);
const emptyOrigin = {
id: "",
pk: "",
Expand All @@ -26,6 +25,10 @@ function QuotaOriginFormset({
end_date_1: "",
end_date_2: "",
};
if (data.length == 0) {
data.push(emptyOrigin);
}
const [origins, setOrigins] = useState([...data]);

const addEmptyOrigin = (e) => {
e.preventDefault();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,239 @@ exports[`QuotaOriginFormset renders empty formset when no initial data 1`] = `
<div
aria-live="polite"
>
<div>
<h3
className="govuk-heading-m"
>
Origin
1
</h3>
<input
name="origins-0-pk"
type="hidden"
value=""
/>
<div
className="govuk-form-group"
>
<div
className="src__StyledContainer-sc-1l2t4xv-0 kSOVkC"
>
<span
className="src__LabelText-sc-1lbxenh-0 jZJbVy"
>
<legend
className="legend__StyledLegend-sc-12rap65-0 deblVS"
size="S"
>
Start date
</legend>
</span>
<div
className="input__StyledList-sc-una33r-1 UBJjX"
>
<label
className="src__Label-sc-iqzvxn-0 input__StyledLabel-sc-una33r-0 eTSPOL bXvZdL"
error={false}
year={false}
>
<span
className="src__LabelText-sc-1lbxenh-0 jZJbVy"
>
Day
</span>
<input
className="src__Input-sc-1ch9crp-0 esEbTY"
defaultValue=""
error={false}
name="origins-0-start_date_0"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
type="text"
/>
</label>
<label
className="src__Label-sc-iqzvxn-0 input__StyledLabel-sc-una33r-0 eTSPOL bXvZdL"
error={false}
year={false}
>
<span
className="src__LabelText-sc-1lbxenh-0 jZJbVy"
>
Month
</span>
<input
className="src__Input-sc-1ch9crp-0 esEbTY"
defaultValue=""
error={false}
name="origins-0-start_date_1"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
type="text"
/>
</label>
<label
className="src__Label-sc-iqzvxn-0 input__StyledLabel-sc-una33r-0 eTSPOL kjRNx"
error={false}
year={true}
>
<span
className="src__LabelText-sc-1lbxenh-0 jZJbVy"
>
Year
</span>
<input
className="src__Input-sc-1ch9crp-0 esEbTY"
defaultValue=""
error={false}
name="origins-0-start_date_2"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
type="text"
/>
</label>
</div>
</div>
</div>
<div
className="govuk-form-group"
>
<div
className="src__StyledContainer-sc-1l2t4xv-0 kSOVkC"
>
<span
className="src__LabelText-sc-1lbxenh-0 jZJbVy"
>
<legend
className="legend__StyledLegend-sc-12rap65-0 deblVS"
size="S"
>
End date
</legend>
</span>
<span
className="src__HintText-sc-tq1z5r-0 hIpBPn"
>
Leave empty if a quota order number origin is needed for an unlimited time
</span>
<div
className="input__StyledList-sc-una33r-1 UBJjX"
>
<label
className="src__Label-sc-iqzvxn-0 input__StyledLabel-sc-una33r-0 eTSPOL bXvZdL"
error={false}
year={false}
>
<span
className="src__LabelText-sc-1lbxenh-0 jZJbVy"
>
Day
</span>
<input
className="src__Input-sc-1ch9crp-0 esEbTY"
defaultValue=""
error={false}
name="origins-0-end_date_0"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
type="text"
/>
</label>
<label
className="src__Label-sc-iqzvxn-0 input__StyledLabel-sc-una33r-0 eTSPOL bXvZdL"
error={false}
year={false}
>
<span
className="src__LabelText-sc-1lbxenh-0 jZJbVy"
>
Month
</span>
<input
className="src__Input-sc-1ch9crp-0 esEbTY"
defaultValue=""
error={false}
name="origins-0-end_date_1"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
type="text"
/>
</label>
<label
className="src__Label-sc-iqzvxn-0 input__StyledLabel-sc-una33r-0 eTSPOL kjRNx"
error={false}
year={true}
>
<span
className="src__LabelText-sc-1lbxenh-0 jZJbVy"
>
Year
</span>
<input
className="src__Input-sc-1ch9crp-0 esEbTY"
defaultValue=""
error={false}
name="origins-0-end_date_2"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
type="text"
/>
</label>
</div>
</div>
</div>
<div
className="govuk-form-group"
>
<legend
className="legend__StyledLegend-sc-12rap65-0 deblVS"
size="S"
>
Geographical area
</legend>
<label
className="src__Label-sc-iqzvxn-0 eTSPOL"
defaultValue=""
error={false}
>
<span
className="src__LabelText-sc-1lbxenh-0 jZJbVy"
/>
<select
className="src__StyledSelect-sc-sgud4a-0 lmpfTQ"
defaultValue=""
error={false}
name="origins-0-geographical_area"
onChange={[Function]}
>
<option
value={1}
/>
<option
value={2}
/>
<option
value={3}
/>
<option
value={4}
/>
<option
value={5}
/>
</select>
</label>
</div>
<hr
className="govuk-!-margin-top-3"
/>
</div>
<button
className="govuk-button govuk-button--secondary"
onClick={[Function]}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ describe("QuotaOriginFormset", () => {
// add an empty origin
fireEvent.click(screen.getByText("Add another origin"));
expect(screen.getByText("Origin 1")).toBeInTheDocument();
expect(screen.queryByText("Origin 2")).not.toBeInTheDocument();
expect(screen.queryByText("Origin 2")).toBeInTheDocument();
expect(screen.queryByText("Origin 3")).not.toBeInTheDocument();
});

it("should remove origin form when delete button is clicked", () => {
Expand Down
Loading

0 comments on commit 3a05f91

Please sign in to comment.