Make list of templates filterable by type

When users are trying to find a template there’s a fair chance that they
know whether or not it’s an email/text message/(letter) that they’re
looking for.

Making them scroll past a whole bunch of templates of a different type
means it will take them longer to find the template they are looking
for.

We already have search on the templates page, but this is only good for
where they can remember the name of the template. This will be
sometimes but not always.

This commit adds some navigation to filter down the list of templates to
only show one type at a time. By default it will show all templates. It
adapts the pattern we use for filtering notifications by
sending/failed/delivered, but without the counts of how many things are
in each bucket (I don’t think there’s any value in knowing you have X
text message templates; on this page you only really care
about the one template you’re looking for).

_Note: required re-arranging the functions in `templates.py`. The route
for `/template/:uuid` needs to come before the route for
`template/:string` otherwise Flask tries to interpret a template’s ID
as its type.
This commit is contained in:
Chris Hill-Scott
2017-06-13 15:28:33 +01:00
parent 114bac7b80
commit 358edf7f20
4 changed files with 100 additions and 24 deletions

View File

@@ -43,26 +43,7 @@ page_headings = {
}
@main.route("/services/<service_id>/templates", methods=['GET'])
@login_required
@user_has_permissions(
'view_activity',
'send_texts',
'send_emails',
'manage_templates',
'manage_api_keys',
admin_override=True,
any_=True,
)
def choose_template(service_id):
return render_template(
'views/templates/choose.html',
templates=service_api_client.get_service_templates(service_id)['data'],
search_form=SearchTemplatesForm(),
)
@main.route("/services/<service_id>/templates/<template_id>")
@main.route("/services/<service_id>/templates/<uuid:template_id>")
@login_required
@user_has_permissions(
'view_activity',
@@ -73,7 +54,7 @@ def choose_template(service_id):
admin_override=True, any_=True
)
def view_template(service_id, template_id):
template = service_api_client.get_service_template(service_id, template_id)['data']
template = service_api_client.get_service_template(service_id, str(template_id))['data']
return render_template(
'views/templates/template.html',
template=get_template(
@@ -92,6 +73,43 @@ def view_template(service_id, template_id):
)
@main.route("/services/<service_id>/templates")
@main.route("/services/<service_id>/templates/<template_type>")
@login_required
@user_has_permissions(
'view_activity',
'send_texts',
'send_emails',
'manage_templates',
'manage_api_keys',
admin_override=True,
any_=True,
)
def choose_template(service_id, template_type='all'):
templates = service_api_client.get_service_templates(service_id)['data']
template_nav_items = [
(label, key, url_for('.choose_template', service_id=current_service['id'], template_type=key), '')
for label, key in filter(None, [
('All', 'all'),
('Text message', 'sms'),
('Email', 'email'),
('Letter', 'letter') if current_service['can_send_letters'] else None,
])
]
return render_template(
'views/templates/choose.html',
templates=[
template for template in templates
if template_type in ['all', template['template_type']]
],
template_nav_items=template_nav_items,
template_type=template_type,
search_form=SearchTemplatesForm(),
)
@main.route("/services/<service_id>/templates/<template_id>.<filetype>")
@login_required
@user_has_permissions('view_activity', admin_override=True)

View File

@@ -3,7 +3,8 @@
{% macro pill(
items=[],
current_value=None,
big_number_args={'smaller': True}
big_number_args={'smaller': True},
show_count=True
) %}
<ul role='tablist' class='pill'>
{% for label, option, link, count in items %}
@@ -14,7 +15,9 @@
<li aria-selected='false' role='tab'>
<a href="{{ link }}">
{% endif %}
{% if show_count %}
{{ big_number(count, **big_number_args) }}
{% endif %}
<div class="pill-label">{{ label }}</div>
{% if current_value == option %}
</div>

View File

@@ -1,3 +1,4 @@
{% from "components/pill.html" import pill %}
{% from "components/message-count-label.html" import message_count_label %}
{% from "components/textbox.html" import textbox %}
@@ -36,7 +37,7 @@
{% else %}
<div class="grid-row bottom-gutter-1-2">
<div class="grid-row bottom-gutter-2-3">
<div class="column-two-thirds">
<h1 class="heading-large">Templates</h1>
</div>
@@ -47,6 +48,10 @@
{% endif %}
</div>
<div class="bottom-gutter-2-3">
{{ pill(template_nav_items, current_value=template_type, show_count=False) }}
</div>
{% if templates|length > 7 %}
<div data-module="autofocus">
<div class="live-search" data-module="live-search" data-targets="#template-list .column-whole">

View File

@@ -7,13 +7,63 @@ from flask import url_for
from freezegun import freeze_time
from notifications_python_client.errors import HTTPError
from tests.conftest import service_one as create_sample_service
from tests.conftest import mock_get_service_email_template, mock_get_service_letter_template
from tests.conftest import mock_get_service_email_template, mock_get_service_letter_template, SERVICE_ONE_ID
from tests import validate_route_permission, template_json, single_notification_json
from tests.app.test_utils import normalize_spaces
from app.main.views.templates import get_last_use_message, get_human_readable_delta
@pytest.mark.parametrize('extra_args, expected_nav_links, expected_templates', [
(
{},
['Text message', 'Email'],
['sms_template_one', 'sms_template_two', 'email_template_one', 'email_template_two']
),
(
{'template_type': 'sms'},
['All', 'Email'],
['sms_template_one', 'sms_template_two'],
),
(
{'template_type': 'email'},
['All', 'Text message'],
['email_template_one', 'email_template_two'],
),
])
def test_should_show_page_for_choosing_a_template(
client_request,
mock_get_service_templates,
extra_args,
expected_nav_links,
expected_templates,
):
page = client_request.get(
'main.choose_template',
service_id=SERVICE_ONE_ID,
**extra_args
)
assert normalize_spaces(page.select('h1')[0].text) == 'Templates'
links_in_page = page.select('.pill a')
assert len(links_in_page) == len(expected_nav_links)
for index, expected_link in enumerate(expected_nav_links):
assert links_in_page[index].text.strip() == expected_link
template_links = page.select('.message-name a')
assert len(template_links) == len(expected_templates)
for index, expected_template in enumerate(expected_templates):
assert template_links[index].text.strip() == expected_template
mock_get_service_templates.assert_called_with(SERVICE_ONE_ID)
def test_should_show_page_for_one_template(
logged_in_client,
mock_get_service_template,