This commit adds a new model class which can be used by any app to
interact with a broadcast area. A broadcast area is one or more polygons
representing geographical areas.
It also adds some models that make browsing collections of these areas
more straightforward. So the hierarchy looks like:
> **BroadcastAreaLibraries*
> Contains multiple libraries of broadcast area
> > **BroadcastAreaLibrary**
> > A collection of geographic areas, all of the same type, for example
> > counties or electoral wards
> > **BroadcastArea**
> > Contains one or more shapes that make up an area, for example
> > England
> > > **BroadcastArea.polygons[n]**
> > > A single shape, for example the Isle of Wight or Lindisfarne
> > > > **BroadcastArea.polygons[n][o]**
> > > > A single coordinate along a polygons
The classes support iteration, so all the areas in a library can be
looped over, for example if `countries` is an instance of
`BroadcastAreaLibrary` you can do:
```python
for country in countries:
print(country.name)
```
The `BroadcastAreaLibraries` class also provides some useful methods for
quickly getting the polygons for an area or areas, for example to
render them on a map. So if `libraries` is an instance of
`BroadcastAreaLibraries` you can do:
```python
libraries.get_polygons_for_areas_long_lat('england', 'wales')
```
This will give polygons for the Welsh mainland, the Isle of Wight,
Anglesey, etc.
The models load data from GeoJSON files, which is an open standard for
serialising geographic data. I’ve added a few example files taken from
http://geoportal.statistics.gov.uk to show how it works.
At the moment they will get a ‘technical difficulties’ error if they
try.
We probably want to do something around letting people self-approve
broadcasts in trial mode, but for now just telling them they can’t is a
better experience than ‘technical difficulties’ (and will probably be
close to what they should see on a live service as well).
`EmailPreviewTemplate.subject` returns a string of HTML, with any
user-submitted HTML already escaped:
b5a61bfb7b/notifications_utils/template.py (L672)
What won’t be escaped is the HTML needed to redact the placeholders. We
generate this HTML so we know its safe, and doesn’t need to be escaped.
However when we pass it to Jinja, Jinja doesn’t know this, so will try
to escape it. This means users will see the raw HTML.
We can get around this by using Flask’s `Markup` class to tell Jinja
that the string is already sanitised and doesn’t need escaping again.
Text message templates don’t have this problem because they already
return `Markup`: b5a61bfb7b/notifications_utils/template.py (L288)
Letter templates don’t suffer from this problem (because they don’t
support redaction) but without making the same change they would still
double-escape ampersands, greater-than symbols, and so on.
Once you’ve created a broadcast you’re taken back to the dashboard. This
feels too passive, and you might miss that the broadcast still needs
approval.
We should be much more explicit that you now need to find someone to
approve your broadcast. Taking someone directly to the page for a
broadcast lets us give more information about the status of the
broadcast and what the next steps should be.
This is an initial, prototype-quality attempt at introducing some kind
of tour for users new to broadcasting. A lot of the users we’re speaking
to don’t have a good concept of what broadcasting means, which is
causing usability problems down the line.
We did a similar thing in the early days of Notify to explain the
concept of message templates and personalisation.
This should make the pages slightly quicker to load, because Redis will
return the JSON string faster than the API.
The only change that can happen to a broadcast which doesn’t go through
the admin app is a broadcast ending at its scheduled time. So this could
result in a cached broadcast having a status of `broadcasting` when it
had in fact finished. We already account for this here though:
b2b58ec044/app/models/broadcast_message.py (L89-L94)
The fields used for user permissions on
permissions forms were changed as part of the work
converting the checkboxes to GOVUK Frontend.
This removes code added to protect against a
situation where the server-side app was running
this updated code but clients were POSTing from
pages that were not, and so sending the old HTTP
params.
User permissions were handled by a group of
BooleanFields but introducing the new checkboxes
changed this to just one field that stores its
data in a list.
It was mentioned in a comment that there could be
a situation, when the instances roll, where clients
are using the old fields but POSTing to a server
running the new code.
https://github.com/alphagov/notifications-admin/pull/3535#discussion_r460872903
This introduces tests for that situation.
dnspython had been changed from 1.16.0 to 2.0.0 in a previous commit,
but this was not compatible with eventlet 0.25.2. This bumps eventlet to
a later version, which has the effect of downgrading dnspython again.
These fields used to use govukCheckboxesField and
so stored their data in a list. They were since
migrated to govukCheckboxField, which extends
BooleanField and so keeps its data as a boolean
value.
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.
This is what we do on the uploads page now. It makes it more obvious
why your search term has returned a certain result if you can see most
of the address, not just the first line.
We’re now normalising and storing the whole address in the
`normalised_to` field. Previously we were only storing the first line
of the address.
Enough time should now have passed that the field will have been
populated for all letters in the database.
Thus we can now tell users that it’s not just the first line they can
search by.
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.