From 3b7dc05dd65c9b3feb3d12e33233aa41156de0f1 Mon Sep 17 00:00:00 2001 From: Chris Hill-Scott Date: Tue, 31 Dec 2019 13:27:27 +0000 Subject: [PATCH] Add a page for each report MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It’s useful to get some kind of preview of the report before you download it. And if there’s only a few letters in there then you might not even need to download it at all. For teams with lots of letters we don’t want the page to load too slowly so let’s cap the number of displayed items to 50, same as previewing a spreadsheet. --- app/assets/stylesheets/views/dashboard.scss | 4 + app/main/views/returned_letters.py | 18 ++++ app/navigation.py | 4 + .../views/returned-letter-summary.html | 4 +- app/templates/views/returned-letters.html | 57 +++++++++++ tests/app/main/views/test_returned_letters.py | 98 ++++++++++++++++++- 6 files changed, 180 insertions(+), 5 deletions(-) create mode 100644 app/templates/views/returned-letters.html diff --git a/app/assets/stylesheets/views/dashboard.scss b/app/assets/stylesheets/views/dashboard.scss index 39d8e82ee..76a5e834c 100644 --- a/app/assets/stylesheets/views/dashboard.scss +++ b/app/assets/stylesheets/views/dashboard.scss @@ -62,6 +62,10 @@ margin-top: -10px; } + &-filename-unlinked { + @include core-19; + } + &-hint { @include core-16; display: block; diff --git a/app/main/views/returned_letters.py b/app/main/views/returned_letters.py index 09f3db4ab..a381b1312 100644 --- a/app/main/views/returned_letters.py +++ b/app/main/views/returned_letters.py @@ -17,6 +17,24 @@ def returned_letter_summary(service_id): ) +@main.route("/services//returned-letters/", methods=["GET"]) +@user_has_permissions('view_activity') +def returned_letters(service_id, reported_at): + + page_size = 50 + returned_letters = service_api_client.get_returned_letters(service_id, reported_at) + count_of_returned_letters = len(returned_letters) + + return render_template( + 'views/returned-letters.html', + returned_letters=returned_letters[:page_size], + reported_at=reported_at, + more_than_one_page=(count_of_returned_letters > page_size), + page_size=page_size, + count_of_returned_letters=count_of_returned_letters, + ) + + @main.route("/services//returned-letters/.csv", methods=["GET"]) @user_has_permissions('view_activity') def returned_letters_report(service_id, reported_at): diff --git a/app/navigation.py b/app/navigation.py index fe2f2092b..354483c7d 100644 --- a/app/navigation.py +++ b/app/navigation.py @@ -243,6 +243,7 @@ class HeaderNavigation(Navigation): 'resend_email_verification', 'resume_service', 'returned_letter_summary', + 'returned_letters', 'returned_letters_report', 'revoke_api_key', 'robots', @@ -567,6 +568,7 @@ class MainNavigation(Navigation): 'resend_email_verification', 'resume_service', 'returned_letter_summary', + 'returned_letters', 'returned_letters_report', 'roadmap', 'robots', @@ -806,6 +808,7 @@ class CaseworkNavigation(Navigation): 'resend_email_verification', 'resume_service', 'returned_letter_summary', + 'returned_letters', 'returned_letters_report', 'revoke_api_key', 'roadmap', @@ -1084,6 +1087,7 @@ class OrgNavigation(Navigation): 'resend_email_verification', 'resume_service', 'returned_letter_summary', + 'returned_letters', 'returned_letters_report', 'revoke_api_key', 'roadmap', diff --git a/app/templates/views/returned-letter-summary.html b/app/templates/views/returned-letter-summary.html index 38106526f..4071b30c3 100644 --- a/app/templates/views/returned-letter-summary.html +++ b/app/templates/views/returned-letter-summary.html @@ -20,8 +20,8 @@ field_headings_visible=False ) %} {% call field() %} - {{ item.reported_at | format_date_normal }} + {{ item.reported_at | format_date_normal }}

{{ item.returned_letter_count}} {{ message_count_label(item.returned_letter_count, 'letter', suffix='')}}

diff --git a/app/templates/views/returned-letters.html b/app/templates/views/returned-letters.html new file mode 100644 index 000000000..98e71e94c --- /dev/null +++ b/app/templates/views/returned-letters.html @@ -0,0 +1,57 @@ +{% from "components/table.html" import list_table, field %} +{% from "components/message-count-label.html" import message_count_label %} +{% from "components/page-header.html" import page_header %} +{% extends "withnav_template.html" %} + +{% block service_page_title %} + Returned letters for {{ reported_at|format_date_normal }} +{% endblock %} + +{% block maincolumn_content %} + +{{ page_header( + 'Returned letters for {}'.format(reported_at|format_date_normal), + back_link=url_for('main.returned_letter_summary', service_id=current_service.id) +) }} + +

+ Download this report +

+ +
+ {% call(item, row_number) list_table( + returned_letters, + caption="Returned letters for {}".format(today), + caption_visible=False, + empty_message='If you have returned letter reports they will be listed here', + field_headings=['Template name', 'Originally sent'], + field_headings_visible=False + ) %} + {% call field() %} + {{ item.template_name or item.uploaded_letter_file_name }} + + {% if item.client_reference %} + Reference {{ item.client_reference }} + {% elif item.original_file_name %} + Sent from {{ item.original_file_name }} + {% else %} + No reference provided + {% endif %} + + {% endcall %} + {% call field(align='right') %} + + + Originally sent {{ item.created_at|format_date_normal }} + + + {% endcall %} + {% endcall %} + {% if more_than_one_page %} + + {% endif %} +
+ +{% endblock %} diff --git a/tests/app/main/views/test_returned_letters.py b/tests/app/main/views/test_returned_letters.py index 1b205f1be..d1039a833 100644 --- a/tests/app/main/views/test_returned_letters.py +++ b/tests/app/main/views/test_returned_letters.py @@ -1,3 +1,5 @@ +import uuid + from flask import url_for from tests.conftest import SERVICE_ONE_ID, normalize_spaces @@ -22,9 +24,11 @@ def test_returned_letter_summary( '24 December 2019 ' '30 letters' ) - assert page.select_one('.table-field-left-aligned a')['href'] == url_for('.returned_letters_report', - service_id=SERVICE_ONE_ID, - reported_at='2019-12-24') + assert page.select_one('.table-field-left-aligned a')['href'] == url_for( + '.returned_letters', + service_id=SERVICE_ONE_ID, + reported_at='2019-12-24', + ) def test_returned_letter_summary_with_one_letter( @@ -48,6 +52,94 @@ def test_returned_letter_summary_with_one_letter( ) +def test_returned_letters_page( + client_request, + mocker +): + data = [ + { + 'notification_id': uuid.uuid4(), + 'client_reference': client_reference, + 'created_at': '2019-12-24 13:30', + 'email_address': 'test@gov.uk', + 'template_name': template_name, + 'template_id': uuid.uuid4(), + 'template_version': None, + 'original_file_name': original_file_name, + 'job_row_number': None, + 'uploaded_letter_file_name': 'test_letter.pdf', + } + for client_reference, template_name, original_file_name, uploaded_letter_file_name in ( + ('ABC123', 'Example template', None, None), + (None, 'Example template', 'Example spreadsheet.xlsx', None), + (None, 'Example template', None, None), + ('DEF456', None, None, 'Example precompiled.pdf'), + (None, None, None, 'Example one-off.pdf'), + ) + ] + mocker.patch('app.service_api_client.get_returned_letters', return_value=data) + + page = client_request.get( + 'main.returned_letters', + service_id=SERVICE_ONE_ID, + reported_at='2019-12-24', + ) + + assert [ + 'Template name Originally sent', + 'Example template Reference ABC123 Originally sent 24 December 2019', + 'Example template Sent from Example spreadsheet.xlsx Originally sent 24 December 2019', + 'Example template No reference provided Originally sent 24 December 2019', + 'test_letter.pdf Reference DEF456 Originally sent 24 December 2019', + 'test_letter.pdf No reference provided Originally sent 24 December 2019', + ] == [ + normalize_spaces(row.text) for row in page.select('tr') + ] + + +def test_returned_letters_page_with_many_letters( + client_request, + mocker +): + data = [ + { + 'notification_id': uuid.uuid4(), + 'client_reference': None, + 'created_at': '2019-12-24 13:30', + 'email_address': 'test@gov.uk', + 'template_name': 'Example template', + 'template_id': uuid.uuid4(), + 'template_version': None, + 'original_file_name': None, + 'job_row_number': None, + 'uploaded_letter_file_name': None, + } + ] * 51 + mocker.patch('app.service_api_client.get_returned_letters', return_value=data) + + page = client_request.get( + 'main.returned_letters', + service_id=SERVICE_ONE_ID, + reported_at='2019-12-24', + ) + + assert len(data) == 51 + assert len(page.select('tbody tr')) == 50 + assert normalize_spaces( + page.select_one('.table-show-more-link').text + ) == ( + 'Only showing the first 50 of 51 rows' + ) + assert page.select_one('a[download]').text == ( + 'Download this report' + ) + assert page.select_one('a[download]')['href'] == url_for( + '.returned_letters_report', + service_id=SERVICE_ONE_ID, + reported_at='2019-12-24', + ) + + def test_returned_letters_reports( client_request, mocker