It would be quite easy to dissociate the search box from the things its
supposed to be searching.
This commit adds assertions to make sure that the things the search box
is targeting are on the page
When adding a new folder it is created inside the currently active
one. The user is returned to the previously active folder page,
which shows the added folder.
This adds a new route to the add template/folder views. Thankfully,
`url_for` recognizes when `template_folder_id` is `None` and will use
the URL without `/folders/...`, so users without folder permissions
should be unaffected by this change.
When a folder is selected the full path is displayed in page title
and header (for example `Templates / Folder1 / Folder2`). Elements
of the path link to the corresponding folder. Current folder is not
linked.
Clicking on template folder navigates to a page that displays that
folder's contents.
This reuses the existing choose template view by adding a filter
based on optional `template_folder_id` argument.
Service model methods are rewritten to match `all_templates` and
`get_template`. New `get_template_folder_path` method returns a
list of folders (from root to the current one) that the selected
folder is nested inside.
With the addition of template folders we need to filter templates
based on a combination of type and parent folder ID.
This replaces the existing `templates_by_type` method with
`get_templates`, which supports both type and parent folder filters,
avoiding a need to create specific methods for each use case.
We still need the templates property to exist in some way in order
to cache it, but it needs to be clear that it's different from
`.get_templates`. One option was to make it "private" (i.e. `_templates`),
and always use `.get_templates` in the rest of the code, but this requires
adding "include all folders" to `.get_templates`, which doesn't have an
obvious interface since `parent_folder_id=None` already means "top-level
only".
This will probably come up again when we need to look into adding
templates from nested folders into the page for live search, but
for now renaming `Service.templates` to `.all_templates` makes it
clear what the property contains.
The add new templates page now has option to add template folders.
Tweaked wording of other options and h1 to clarify options since it's
not all about templates any more.
Added api client and stuff for it
When you land on the page it’s good to be able to quickly see what the
currently-set value is, before you change it.
This is unnecessarily hard if the selected item is buried half way down
the page. This commit moves it to the top.
Currently the brandings have non-deterministic sorting, which means
the order changes from page load to page load. This makes it hard to
find the item you’re looking for.
This commit sorts them by the name of the branding, same as for email
brandings.
These helper functions for modifying a service permission were just
floating around loose in the view code.
A much better home for them is on the model. This will also make it
easy to reuse them in other views if we ever need to.
In trial mode you can’t send letters. But it’s still useful to be able
to build up a letter to see how it work.
Best place to put this error is before someone tries to send a letter
for real.
We didn’t used to allow this because it wasn’t really possible with the
old DVLA set up and we didn’t think there’s a need.
We think it’s possible now because, even though it’s cumbersome, it’s
better than the manual process.
There’s a lot of code in service settings which:
- talks to the API directly through the clients
- passes that information through to the Jinja template
By encapsulating this logic in the service model:
- the Jinja template can access the data directly
- the logic can be reused across multiple methods
This commit is the first step to disentangling the models from the API
clients. With the models in the same folder as the API clients it makes
it hard to import the API clients within the model without getting a
circular import.
After this commit the user API clients still has this problem, but at
least the service API client doesn’t.
Making people use a property is a sure way to make sure they’re spelling
the name of the property correctly, and allows us to easily swap out
properties that call through to the underlying JSON, and properties
which are implemented as methods.
This means we can have a method on the service model which hits the API
(or Redis) but can be called multiple times (within the context of a
request) without making multiple network requests.
It does this by storing the results of the method on the object’s
internal `__dict__` the first time the method is called.
We do a lot of logic around choosing which templates to show. This logic
is all inside one view method.
It makes it cleaner to break this logic up into functions. But this
would mean passing around variables from one function to another.
Putting these methods onto a class (the service model) means that
there’s a place to store this data (rather than having to pass it around
a lot).
Making this code more manageable is important so that when we have
templates and folders it’s easy to encapsulate the logic around
combining the two.
`_get_current_service` is a function which gets called every time
`current_service` is referenced in a view method or Jinja template.
Because the service model was getting initialised inside this function
it was being reconstructed many times in one request. On the service
settings page, for example, it was getting initialised 43 times, adding
about 200ms to the response time.
This commit moves its initialisation to the point where we’re getting
the data from the API, which only happens once per request.
We already have tests for the
/services/<service_id>/notifications/<notification_type> page, but these
were not testing the page when there were failed notifications, so this
adds a test for the page in this situation.
Once all our users have upgraded to the latest clients they won’t need
this. The latest clients only use the combined key and service ID.
Discuss: when can we safely remove it?
At the moment we show precompiled letters that have failed the
validation as having been sent. This is confusing.
We should communicate it as having been cancelled (rather than failed),
with the implication being that Notify has come along and cancelled the
letter before printing it. I think this is conceptually what makes the
most sense.
From the user’s point of view any letters that show up as cancelled
probably need to be fixed and resent, so it makes sense to group them
with the same name.
At the moment we are manually cancelling letters for people when they
ask us to. Once’s we’ve done this there is no indication that it’s
happened except for the date going red on the list of letters.
This commit adds some error messaging and styling to show when a letter
is cancelled.
Letting people cancel their own letters will be a future enhancement.
We were passing both dvla_org_id and filename to template-preview
temporarily while we switch to only using filename. Now that
template-preview is set up to use filename, we can stop sending the
dvla_org_id too.
One of the changes this pulls in is encoding of
periods in the token used for new password
requests.
In real-life the resulting URL is build by
concatenating the base url with the token so it
isn't processed further.
The test for new password requests builds the URL
with url_for. This encodes the result returned so
the periods are encoded twice.
We now pass through `filename` to the Template Preview `/preview.<filetype>'
endpoint in addition to the `dvla_org_id`. Template Preview will be
changed to only use `filename`, and once this has been done, we can change
the code to only pass through `dvla_org_id` instead of passing through
both pieces of information.
- add get/post view
- create a pdf upload form
- add a template where user can upload the file
- check boundaries of the letter by calling template-preview
- display banner messages with boundaries validation result
- display pages of the document, with visible boundaries overlay
if the document did not pass validation, and without overlay
if they do pass validation