Add a form to filter notifications by recipient

Because manually editing the URL isn’t a great user interface, this
commit adds a search field to do this on the user’s behalf.

For this pass at the story it doesn’t do any validation – the user will
just get no results if they search by something which isn’t a phone
number or email address.

If the user navigates to a different ‘bucket’ of notifications (eg
delivered, failed) then the search term is reset, because they’ve
changed the filter which is at a level above the search term.
This commit is contained in:
Chris Hill-Scott
2017-05-30 13:51:25 +01:00
parent f41830e5d3
commit b9bf18b936
5 changed files with 97 additions and 3 deletions

View File

@@ -59,3 +59,21 @@
}
}
.align-button-with-textbox {
.button {
@include media(desktop) {
position: relative;
top: 32px;
left: -30px;
width: 100%;
margin-right: -30px;
padding-top: 8px;
box-sizing: content-box;
}
}
}

View File

@@ -625,6 +625,11 @@ class SearchTemplatesForm(Form):
search = SearchField('Search by name')
class SearchNotificationsForm(Form):
to = SearchField('Search by phone number or email address')
class PlaceholderForm(Form):
pass

View File

@@ -26,6 +26,7 @@ from app import (
current_service,
format_datetime_short)
from app.main import main
from app.main.forms import SearchNotificationsForm
from app.utils import (
get_page_from_request,
generate_next_dict,
@@ -197,9 +198,10 @@ def view_notifications(service_id, message_type):
'views/notifications.html',
partials=get_notifications(service_id, message_type),
message_type=message_type,
status=request.args.get('status'),
status=request.args.get('status') or 'sending,delivered,failed',
page=request.args.get('page', 1),
to=request.args.get('to'),
search_form=SearchNotificationsForm(to=request.args.get('to')),
)
@@ -252,11 +254,11 @@ def get_notifications(service_id, message_type, status_override=None):
}
prev_page = None
if notifications['links'].get('prev', None):
if 'links' in notifications and notifications['links'].get('prev', None):
prev_page = generate_previous_dict('main.view_notifications', service_id, page, url_args=url_args)
next_page = None
if notifications['links'].get('next', None):
if 'links' in notifications and notifications['links'].get('next', None):
next_page = generate_next_dict('main.view_notifications', service_id, page, url_args)
return {

View File

@@ -1,6 +1,8 @@
{% extends "withnav_template.html" %}
{% from "components/ajax-block.html" import ajax_block %}
{% from "components/message-count-label.html" import message_count_label, recipient_count_label %}
{% from "components/page-footer.html" import page_footer %}
{% from "components/textbox.html" import textbox %}
{% block service_page_title %}
{{ message_count_label(99, message_type, suffix='') | capitalize }}
@@ -18,6 +20,24 @@
'counts'
) }}
<form
method="get"
action="{{ url_for('.view_notifications', service_id=current_service.id, message_type=message_type) }}"
class="grid-row"
>
<div class="column-three-quarters">
<input type="hidden" name="status" value="{{ status }}">
{{ textbox(
search_form.to,
width='1-1',
label='Search by {}'.format('email address' if message_type == 'email' else 'phone number')
) }}
</div>
<div class="column-one-quarter align-button-with-textbox">
<input type="submit" class="button" value="Search">
</div>
</form>
{{ ajax_block(
partials,
url_for('.get_notifications_as_json', service_id=current_service.id, message_type=message_type, status=status, page=page, to=to),

View File

@@ -8,6 +8,7 @@ from bs4 import BeautifulSoup
from app.main.views.jobs import get_time_left, get_status_filters
from tests import notification_json
from tests.conftest import SERVICE_ONE_ID
from freezegun import freeze_time
@@ -381,6 +382,54 @@ def test_can_show_notifications(
assert json_content.keys() == {'counts', 'notifications'}
@pytest.mark.parametrize("initial_query_arguments, expected_status_field_value, expected_search_box_contents", [
(
{
'message_type': 'sms',
},
'sending,delivered,failed',
'',
),
(
{
'status': 'failed',
'message_type': 'email',
'page': '99',
'to': 'test@example.com',
},
'failed',
'test@example.com',
),
])
def test_search_recipient_form(
logged_in_client,
mock_get_notifications,
mock_get_detailed_service,
initial_query_arguments,
expected_status_field_value,
expected_search_box_contents,
):
response = logged_in_client.get(url_for(
'main.view_notifications',
service_id=SERVICE_ONE_ID,
**initial_query_arguments
))
assert response.status_code == 200
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
action_url = page.find("form")['action']
url = urlparse(action_url)
assert url.path == '/services/{}/notifications/{}'.format(
SERVICE_ONE_ID,
initial_query_arguments['message_type']
)
query_dict = parse_qs(url.query)
assert query_dict == {}
assert page.find("input", {'name': 'status'})['value'] == expected_status_field_value
assert page.find("input", {'name': 'to'})['value'] == expected_search_box_contents
def test_should_show_notifications_for_a_service_with_next_previous(
logged_in_client,
service_one,