This now adds validation for invalid characters on the
LetterAddressForm for one off letters. It also adds a validation failed
message for uploaded letters, precompiled letters sent through the API,
and CSV rows with errors.
We recently introduced a form control that lets user choose when a
broadcast ends.
Based on the most recent research participant, we think:
- there is a specific misunderstanding of what this control does
- there is a general low level of understanding of what a ‘broadcast’
means
People will try to understand what a ‘broadcast’ is by using mental
models they have for other kinds of messaging, for example text
messages.
Other kinds of messaging are one-to-one, i.e. they go from a sender to a
recipient. They are not ongoing in any way.
Emails and texts are sent at a time (and for all practicable purposes
are received at that same time). So, when we present the user with
a form that controls time, they might well assume it controls the time
when the message will be sent.
This is a feature we offer for sending messages using a spreadsheet, and
that’s where we’ve borrowed this pattern from.
We reinforce this assumption with the labelling of the form control. By
front-loading it with the word ‘When’ we are playing to the users
confirmation bias, i.e. they are interpreting the meaning of the control
in a way that confirms their prior beliefs about how messaging works.
So this commit does two things:
- re-labels the form to front-load the word ‘End’ not ‘When’
- adds text to the page explaining when the broadcast will start, so
there’s a chance of overriding that confirmation bias
If we can get users to go through this before sending a broadcast for
real, it could help them learn what a broadcast is, and how it differs
from sending text messages.
When sending a letter we check how many pages it has and this number
then determines how many PNG images we ask template preview for. When
calculating the page count, we were getting the page count for the
template as it comes from the database (so without any placeholders
filled in). But filling in placeholders in a letter may cause the number
of pages to change, which was the cause of the 'Letter does not have a
page x' errors we were seeing from template-preview.
Now, when we calculate the letter page count during sending, we take the
placeholders that have already been filled in into account.
It’s an irreversible action if you do click it, so it feels like an ‘Are
you sure?’ step is sensible. Follows the same pattern for deleting
templates, etc.
Different emergencies will need broadcasts to last for a variable amount
of time. We give users some control over this by letting them stop a
broadcast early. But we should also let them set a maximum broadcast
time, for:
- when the duration of the danger is known
- when the broadcast has been live long enough to alert everyone who
needs to know about it
This code re-uses the pattern for scheduling jobs, which has some
constraints that are probably OK for now:
- end time is limited to an hour
- longest duration is 3 whole days (eg if you start broadcasting Friday
you have the choice of Saturday, Sunday and all of Monday, up to
midnight)
If a broadcast definitely shouldn’t go out (for example because it has a
spelling mistake or is going to the wrong areas) then we should have a
way of removing it. Once it’s removed no-one else can approve it, and it
isn’t cluttering up the dashboard.
This is a link (because it’s a secondary action) and red (because it’s
destructive, in that it’s throwing away someone’s work).
Since new broadcasts will go into `pending-approval`, we now need a way
of approving them.
This commit adds a button to this page to start (or approve) the
broadcast. This button is wrapped in a bordered box, to emphasise that
it’s something consequential.
We don’t want one person going full yolo and start broadcasting without
any oversight. This commit changes the flow so that the button on the
‘preview’ page puts the broadcast into `pending-approval`, rather than
directly into `broadcasting`.
When we have an approval flow, `pending-approval` will be the state a
broadcast is in between being a draft and broadcasting.
This means it is the earliest stage at which a broadcast can appear on
the dashboard, so this commit adds a new section at the top of the
dashboard to display these broadcasts (since the dashboard is in a
reverse chronological order).
Rather than displaying the scheduled time, the extra information shown
is the person who drafted the broadcast, since I reckon you’ll be coming
to this page because they’ve asked you to approve their broadcast.
This was broken because current_service doesn’t update itself after
calling the `update` method of the API. So we thought we were changing
the permissions like this:
```
{'email', 'sms', 'letter'}
{'email', 'sms', 'letter', 'broadcast'}
{'sms', 'letter', 'broadcast'}
{'letter', 'broadcast'}
{'broadcast'}
```
But actually we were doing this:
```
{'email', 'sms', 'letter'}
{'email', 'sms', 'letter', 'broadcast'}
{'sms', 'letter'}
{'email', 'letter'}
{'email', 'sms'}
```
This commit changes the code to update the permissions like this:
```
{'email', 'sms', 'letter'}
{'broadcast'}
```
It does so by adding a new method to the service model which changes all
the permissions in one API call, and updates the tests to mock the
underlying API call, not the method on the model.
Same technique as we use for other pages that update via AJAX.
I’ve split the page up into separate chunks because the DiffDOM library
we use finds it easier to work out what’s changed when there are fewer
elements/a shallower tree.
The api returns letter details split by postage, so international
letters are returned with a postage of `europe` or `rest-of-world` not
`international` and these rows need to be added together when the rate
is the same before they are displayed on the usage page.
To do this, we need to replace the postage of `europe` and
`rest-of-world` with `international`. The data then needs to be sorted
by postage and rate before the letter units for rows which are
international and have the same rate are added together.
No functional changes, but this changes the letter details that are
used for the usage page from a tuple to a named tuple since this makes
it easier to understand.
When a service is switched over to broadcast it has the email, text
message and letter permissions removed. And the links to switch these
settings back on are hidden.
This commit ensures that even if the user manually goes to the URLs for
these pages, they still won’t be able to switch the other channels back
on.
The existing macros added data attributes to any
error message displayed which communicated the
error to Google Analytics (if the user had given
consent).
This re-implements that functionality.
Single checkboxes are distinct because:
- they don't need to be wrapped in a `<fieldset>`
- they are a subclass of BooleanField so their
data is either True or False
Nested checkboxes with a single top-level node
will only have one item in their `items` list.
This is because the other choices are children of
that list item.
This means we need to check the `choices`
attribute, which lists all the checkboxes, to see
if they should be marked as a group (by being
wrapped in a `<fieldset>`) or not.
Includes:
1. changes to make NestedFieldMixin work
with new fields and CSS for nested checkboxes
2. adds custom version of GOVUK checkboxes
component to allow us to:
- add classes to elements currently inaccessible
- wrap the checkboxes in a list
- add child checkboxes to each checkbox (making
tree structures possible through recursion
Change 2. should be pushed upstream to the GOVUK
Design System as a proposal for changes to the
GOVUK Checkboxes component.
Allows checkboxes to be collapsed so they take up
less space in the page. The collapsed state
includes a live summary tracking which of them are
selected.
Includes changes to the JS for collapsible
checkboxes to make it work with the GOVUK
Checkboxes component HTML.
govukCheckboxesField subclasses
SelectMultipleField and overwrites how it renders
HTML to let us use the GOVUK Checkboxes component
while retaining all the functionality of WTForms
fields.
Based on work on github.com/richardjpope/recourse:
https://github.com/richardjpope/recourse/blob/master/recourse/forms.py#L6
Since users of broadcast services will always have the view dashboard
permission and never have the API keys permission we can hide these. And
we should re-label the permissions to make sense in the context of
broadcasting.
For services with the broadcast permission this hides:
- the ‘View dashboard’ permission (and defaults it to _checked_) because
all users of broadcast services will need to see the dashboard
- the ‘Manage API keys’ permission (and defaults it to _not checked_)
because we don’t offer an API integration for broadcast services yet
– if we do we won’t want existing users to automatically get the
permission
It relabels:
- the ‘Send’ permission to ‘Prepare and approve’ to match the current,
slightly clunky language on the templates page
- the ‘Manage settings’ label to not refer to ‘usage’ because broadcast
services won’t incur cost
To make the interface as simple as possible we don’t want to mix up
sending other types of communication where services have the broadcast
permission.
This commit removes the other permissions once a service has been given
the broadcast permission by a platform admin user.
This commit adds a page to view a single broadcast. This is important
for two reasons:
- users need an audit of what happened when, and who else was involved
in approving or cancelling a broadcast
- we need a place to put actions (approving, cancelling) on a broadcast
so that you can confirm details of the message and the areas before
performing the action
Currently this is a `get` request from the dashboard. Once we have a page
for viewing an individual broadcast it should probably show there
instead and be a `get`/confirm/`post` loop like for deleting a template.
Shows current and previous broadcasts. Does not add a page for viewing
an individual broadcast.
Broadcasts are split into live and previous.
Draft broadcasts are excluded from the dashboard.
This commit removes the code the puts areas into the session and instead
creates and then updates a draft broadcast in the database.
This is so we can avoid session-related bugs, and potentially having a
large session when we start adding personalisation etc.
Once a broadcast is ready to go it is set to `broadcasting` straight
away with no approval. We’ll revisit this as we learn more about how
users might want to manage who can create and approve broadcasts.
The tests are a bit light in terms of checking what’s on the page, but
clicking through the pages is probably good enough for now.
There are lots of places where we redirect people to the dashboard, for
example after logging in. Rather than add logic to all these places to
check for the broadcast permission, let’s just redirect from the normal
dashboard to the broadcast dashboard.
Other places like the main navigation can still link directly to the
broadcast dashboard, where we do care about speed and not going through
multiple redirect jumps.
There can be lots of areas in a library, for example local councils. So
when there is, let’s allow people to do the find-as-you-type thing we
support in lots of other places.
These are just so we have some pages to click through for now. They
don’t use real templates, or any of the broadcast stuff from the
database.
But I think it’s useful to get some skeleton pages in first so that we
can see the map etc working in production, then build on that, without
having to do it all in one mega PR.
For that reason there are two short term things I’ve done in this commit
which should be revisited soon:
- no tests for the endpoints
- data about which areas are selected is stored in the session