Commit Graph

270 Commits

Author SHA1 Message Date
Toby Lorne
698e9816ec models: use broadcast areas from admin package
Signed-off-by: Toby Lorne <toby.lornewelch-richards@digital.cabinet-office.gov.uk>
2020-08-10 12:50:22 +01:00
Chris Hill-Scott
479406c02d Don’t let users self-approve broadcasts
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).
2020-08-05 16:01:21 +01:00
Chris Hill-Scott
4f859a69a6 Merge pull request #3527 from alphagov/broadcast-end-time
Let users choose when to end a broadcast
2020-07-17 10:43:10 +01:00
Chris Hill-Scott
2d7d800c64 Merge pull request #3528 from alphagov/fix-set-broadcast-permission
Fix setting of broadcast permission
2020-07-17 10:40:26 +01:00
Chris Hill-Scott
83156bd16e Let users choose when to end a broadcast
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)
2020-07-17 08:23:10 +01:00
Chris Hill-Scott
03b4aabf5f Add a link to reject a broadcast
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).
2020-07-17 08:07:44 +01:00
Chris Hill-Scott
a99b40304b Add button to approve broadcast
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.
2020-07-17 08:07:44 +01:00
Chris Hill-Scott
5b83db9768 Don’t start broadcasts immediately
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`.
2020-07-17 08:07:43 +01:00
Chris Hill-Scott
4b1e3ec504 Refactor broadcast message model
There was a lot of duplicate code here for updating the status and other
properties of a broadcast.

This commit abstracts them into reusable methods. They’re named with an
underscore to suggest that they shouldn’t be used externally.
2020-07-17 08:07:42 +01:00
Chris Hill-Scott
e29a477eb1 Fix setting of broadcast permission
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.
2020-07-16 19:44:20 +01:00
Chris Hill-Scott
414e4b5834 Merge pull request #3520 from alphagov/broadcast-user-permissions
Make user permissions make sense for services with the broadcast permission
2020-07-16 14:59:57 +01:00
Chris Hill-Scott
72c1b3d8a1 Only show relevant user permissions for broadcast services
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
2020-07-14 09:45:42 +01:00
Chris Hill-Scott
7d6dffc098 Add a page to view a single broadcast
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
2020-07-10 15:55:05 +01:00
Chris Hill-Scott
3136d1a33b Implement sorting
Shows the broadcasts with the longest time still to live at the top. At
the moment this will be the same as the newest broadcasts, so we may
want to revisit this sort order when we have broadcasts of variable
duration.

For no-longer-live broadcasts we show the most-recently-finished at the
top, whether it finished naturally or was cancelled.
2020-07-10 09:57:06 +01:00
Chris Hill-Scott
44e177b402 Allow broadcasts to be cancelled
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.
2020-07-10 09:57:06 +01:00
Chris Hill-Scott
6b822f9fde Add broadcasts to the dashboard
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.
2020-07-09 16:32:15 +01:00
Chris Hill-Scott
effe24893e Make the broadcast flow talk to the API
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.
2020-07-09 14:31:12 +01:00
Chris Hill-Scott
c4458efa21 Bump utils to 40.2.1
Brings in:
- re-usable `SerialisedModel`
- speed improvements to processing CSVs against email templates

I chose not to rename `JSONModel` or `ModelList` to keep the diff nice
and small.
2020-07-06 09:39:54 +01:00
Chris Hill-Scott
01ec2ad9c7 Add template type hint on choose page 2020-07-03 15:47:29 +01:00
Chris Hill-Scott
154d4bdb85 Allow adding broadcast templates
At the moment the page is the same as for text message templates,
except:
- different H1
- no guidance about personalisation, links, etc (until we decide how
  these should work)

For now you won’t be able to really create a broadcast template, because
the API doesn’t support it (the API will respond with a 400). But that’s
OK because no real services have the broadcast permission yet.

This required a bit of refactoring of how we check which template types
a service can use, because there were some hard-coded assumptions about
emails and text messages.
2020-07-01 17:17:46 +01:00
Leo Hemsted
8b3aa43101 add broadcast service permission 2020-06-30 13:06:26 +01:00
Chris Hill-Scott
45697aac43 Stop expecting letter contact block in service JSON
We’re removing it for performance reasons.

This means removing the old pages that edited the letter contact block
when it was stored directly on the service, rather than the current
model where a service can have multiple contact blocks.
2020-06-23 08:13:52 +01:00
Chris Hill-Scott
e089de74ee Refactor to not need custom constructor
All the constructor of the service model is doing is setting a default
value of a property, this is more idiomatically expressed with a custom
property, and means we can get rid of the custom constructor entirely.
2020-06-03 15:34:55 +01:00
Chris Hill-Scott
a95d9b5152 Enforce service permissions
This should catch typos more quickly and obviously.
2020-06-03 15:34:55 +01:00
Katie Smith
313d39415d Catch errors when user register from invite
API gives an error if it tries to add a user to a service and that user is
already a member of the service. This situation shouldn't occur - admin checks
if an invited user is a member of a service before calling API, but we
have seen this error occurring when there are two requests processing at
the same time.

This change catches the errors from API if a user is already a member of
a service and redirects the user to the service dashboard so that they
don't see an error page.
2020-05-19 13:49:17 +01:00
Chris Hill-Scott
34f5417844 Group uploaded letters by day of printing
Some teams have started uploading quite a lot of letters (in the
hundreds per week). They’re also uploading CSVs of emails. This means
the uploads page ends up quite jumbled.

This is because:
- there’s just a lot of items to scan through
- conceptually it’s a bit odd to have batches of things displayed
  alongside individual things on the same page

So instead we’re going to start grouping together uploaded letters. This
will be by the date on which we ‘start’ printing them, or in other
words the time at which they can no longer be cancelled.

This feels like a natural grouping, and it matches what we know about
people’s mental models of ‘batches’ and ‘runs’ when talking about
printing.

This grouping will be done in the API, so all this commit need to do is:
- be ready to display this new type of pseudo-job
- link to the page that displays all the uploaded letters for a given
  print day
2020-05-11 14:29:03 +01:00
Chris Hill-Scott
06108de0f7 Allow international addresses in spreadsheets
For services with permission, they can now put international addresses
into their spreadsheets without getting a postcode error.

This also means they can start using address line 7 instead of postcode,
since it doesn’t make sense to put a country in a field called
‘postcode’. But this will be undocumented to start with, because we’re
not giving any real users the permission.

It does now mean that the number of possible placeholders (7 + postcode)
is greater than the number of allowed placeholders (7), so we have to
account for that in the one-off address flow where we’re populating the
placeholders automatically. We’re sticking with 6 + postcode here for
backwards compatibility.
2020-04-29 16:19:57 +01:00
Chris Hill-Scott
f5649d72c9 Explain 3 required address columns
Our rules about address columns are relaxing, so that none of them are
mandatory any more. Instead you just need any 3 of the 7 to make a valid
address.

This commit updates our error messaging to reflect that.
2020-04-27 16:47:49 +01:00
Chris Hill-Scott
23e1682260 Make dynamic attributes of model introspectable
`dir(object)` is a useful Python function that tells you what attributes
and methods an object has. It’s also used by tools like iPython and IDEs
for code completion.

Some of the attributes of a `JSONModel` are dynamic, based on what
fields we expect in the underlying JSON. Therefore they don’t
automatically end up in the result of calling `dir`. To get around this
we can implement our own `__dir__` method, which also returns the names
of the fields we’re expecting the the JSON.

Inspired by this Raymond Hettinger tweet:

> #python tip:  If you add attributes to an API with __getattr__() or
> __getattribute__(), remember to update __dir__() to make the extension
> introspectable.

— https://twitter.com/raymondh/status/1249860863525146624
2020-04-14 09:44:38 +01:00
Chris Hill-Scott
047ca8a48c Fix unnecessary call to organisation API endpoint
We’re caching the organisation name, but still talking to the API
to see if the organisation exists.

`Service().organisation_id` only goes to the JSON for the service.

`Service().organisation` makes a separate API call.

We only need the former to know if a service belongs to an organisation.
2020-04-02 15:24:02 +01:00
Chris Hill-Scott
cc5701e870 Cache organisation name in Redis
A lot of pages in the admin app are now generated entirely from Redis,
without touching the API.

The one remaining API call that a lot of pages make, when the user is
platform admin or a member of an organisation, is to get the name of
the current service’s organisation.

This commit adds some code to start caching that as well, which should
speed up page load times for when we’re clicking around the admin app
(it’s typically 100ms just to get the organisation, and more than that
when the API is under load).

This means changing the service model to get the organisation from the
API by ID, not by service ID. Otherwise it would be very hard to clear
the cache if the name of the organisation ever changed.

We can’t cache the whole organisation because it has a
`count_of_live_services` field which can change at any time, without an
update being made.
2020-04-02 12:07:19 +01:00
Chris Hill-Scott
3895794208 Merge branch 'master' into flask-login-again 2020-04-01 14:29:16 +01:00
Chris Hill-Scott
7fb8e1de92 Use statistics for returned letters on dashboard
This should be faster and more accurate than querying all the reports.
2020-04-01 10:18:55 +01:00
Chris Hill-Scott
57ec58ab4e Merge pull request #3377 from alphagov/delete-contact-list
Let users delete a contact list
2020-03-27 16:13:32 +00:00
Chris Hill-Scott
481c9dba17 Remove unused model property 2020-03-25 13:58:23 +00:00
Chris Hill-Scott
697803a10c Add a ‘general’ ticket type
This is for tickets coming from non-logged-in users. It’s effectively
the same as reporting a problem, but doesn’t have the banner about
the status page (because we can’t tell if they’re actually reporting a
problem now we’re not asking).

It also gives a more generic page title.
2020-03-24 17:56:11 +00:00
Chris Hill-Scott
30a3418473 Refactor so constants are used everywhere 2020-03-24 17:48:13 +00:00
Chris Hill-Scott
8f15eee5e0 Let users delete a contact list
Follows our standard pattern of confirming with a red banner for actions
that are destructive.
2020-03-19 15:17:01 +00:00
Chris Hill-Scott
82634f79de Use new API endpoint to get single contact list
When we first built the contact list feature this endpoint didn’t exist.
Now it does we can remove the slightly cludgy looping-through-all-the-lists
code.
2020-03-17 11:30:27 +00:00
Chris Hill-Scott
93f862621c Pass original file name when sending contact list
Otherwise the new file doesn’t get a name, which is very confusing.
2020-03-16 13:09:32 +00:00
Chris Hill-Scott
b99216173e Sort contact lists appropriately
On the uploads page this should be newest first, same as the scheduled
and immediate jobs on this page.

On the _choose_ page this should be alphabetical, same as choosing a
template.
2020-03-16 13:09:23 +00:00
Chris Hill-Scott
050f98fea6 Show contact lists on the uploads page
Uploads page is where all the stuff you’ve uploaded lives. Now you can
upload contact lists they should live here too.

They always come first because they’re the most-removed from stuff
you’ve sent.
2020-03-16 13:09:16 +00:00
Chris Hill-Scott
31d2fd9b58 Only show the link to use list if service has lists
Most services won’t be interested in the contact list feature, so we
shouldn’t clutter up the interface with the extra link.
2020-03-16 13:09:01 +00:00
Chris Hill-Scott
6c2021aeb2 Only show contact lists relevant to template
You can’t send an email message template to a list of phone numbers. So
we shouldn’t show you the lists of phone numbers when you’ve chosen an
email template.
2020-03-16 13:08:53 +00:00
Chris Hill-Scott
b598af1eca Add an endpoint to download a contact list
In case you need to download it, modify it, and re-upload it when you
don’t have access to the existing list.
2020-03-16 13:08:46 +00:00
Chris Hill-Scott
e24083ce9d Add a page to choose a contact list
You’ll be able to use a contact list by first choosing a template, then
choosing the list you want to use.

At the moment this shows all lists, not just the ones that are
compatible with your template.
2020-03-16 13:08:07 +00:00
Chris Hill-Scott
aa85870ee1 Add a page to view a single contact list 2020-03-16 13:08:00 +00:00
Chris Hill-Scott
460b779d11 Add endpoint to redirect from contact list to send
In order to use a contact list we’re going to put you in the normal
upload a spreadsheet journey. Except without having to upload again.

So this commit adds an endpoint that takes the file from the contact
list bucket, puts it in the same place it would have gone if you’d
uploaded it, then sends you on your way.
2020-03-16 13:07:46 +00:00
Chris Hill-Scott
03f2368deb Use the correct bucket for storing contact lists
We don’t want to muddy them up with the normal CSV uploads.

I’ve tried to reuse the existing S3 code where possible because it’s
well tested.

Buckets have already been created.
2020-03-16 13:07:39 +00:00
Chris Hill-Scott
1c02476ee7 Let users upload a contact list to use later
We increasingly have teams wanting to do business-continuity type
messaging. They might be without access to their normal systems, which
is where they would otherwise go to get the list of email addresses or
phone numbers.

So we want to give them a place in Notify where they can store their
spreadsheets and use them at a later date.

For the initial pass we’re going to scope this to only allowing
spreadsheets with one column, ie just phone numbers/email addresses.
This is because:
- it minimises the amount of personal info we’re storing
- it reduces the chance of getting a placeholder error when you go to
  send the message, which is probably a high-stress situation where you
  might not be able to re-generate the file

The code for this is mostly copied from the existing upload CSV journey.
It’s quite duplicative, but that’s what I needed to do to get this out
quickly. There are opportunities for refactoring later.

Similarly, I would have liked to split this up into better commit
messages, but it really was a case of just bashing code out until it
worked 😳

This commit does not:
- implement the ‘view a contact list page’ (it just has a placeholder
  because the API isn’t ready at the moment)
- link to this page (because it’s not ready to use yet)
2020-03-16 13:07:28 +00:00