From 5229373341cc7e1a08bd3d712a22bc297ce66292 Mon Sep 17 00:00:00 2001 From: Chris Hill-Scott Date: Tue, 14 Jul 2020 13:39:29 +0100 Subject: [PATCH] Make the broadcast dashboard update via AJAX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same technique as we use for other pages that update via AJAX. I’ve split the page up into separate chunks because the DiffDOM library we use finds it easier to work out what’s changed when there are fewer elements/a shallower tree. --- app/main/views/broadcast.py | 29 ++++++++-- app/navigation.py | 4 ++ app/templates/views/broadcast/dashboard.html | 54 ++++--------------- .../broadcast/partials/dashboard-table.html | 39 ++++++++++++++ tests/app/main/views/test_broadcast.py | 25 +++++++++ 5 files changed, 104 insertions(+), 47 deletions(-) create mode 100644 app/templates/views/broadcast/partials/dashboard-table.html diff --git a/app/main/views/broadcast.py b/app/main/views/broadcast.py index c9ca2b645..0c30ef0df 100644 --- a/app/main/views/broadcast.py +++ b/app/main/views/broadcast.py @@ -1,4 +1,4 @@ -from flask import abort, redirect, render_template, request, url_for +from flask import abort, jsonify, redirect, render_template, request, url_for from app import current_service from app.main import main @@ -11,11 +11,32 @@ from app.utils import service_has_permission, user_has_permissions @user_has_permissions() @service_has_permission('broadcast') def broadcast_dashboard(service_id): - broadcast_messages = BroadcastMessages(service_id) return render_template( 'views/broadcast/dashboard.html', - live_broadcasts=broadcast_messages.with_status('broadcasting'), - previous_broadcasts=broadcast_messages.with_status('cancelled', 'completed'), + partials=get_broadcast_dashboard_partials(current_service.id) + ) + + +@main.route('/services//broadcast-dashboard.json') +@user_has_permissions() +@service_has_permission('broadcast') +def broadcast_dashboard_updates(service_id): + return jsonify(get_broadcast_dashboard_partials(current_service.id)) + + +def get_broadcast_dashboard_partials(service_id): + broadcast_messages = BroadcastMessages(service_id) + return dict( + live_broadcasts=render_template( + 'views/broadcast/partials/dashboard-table.html', + broadcasts=broadcast_messages.with_status('broadcasting'), + empty_message='You do not have any live broadcasts at the moment', + ), + previous_broadcasts=render_template( + 'views/broadcast/partials/dashboard-table.html', + broadcasts=broadcast_messages.with_status('cancelled', 'completed'), + empty_message='You do not have any previous broadcasts', + ), ) diff --git a/app/navigation.py b/app/navigation.py index 2ea2b77c9..4442829f6 100644 --- a/app/navigation.py +++ b/app/navigation.py @@ -353,6 +353,7 @@ class HeaderNavigation(Navigation): 'who_can_use_notify', 'who_its_for', 'broadcast_dashboard', + 'broadcast_dashboard_updates', 'broadcast', 'preview_broadcast_areas', 'choose_broadcast_library', @@ -373,6 +374,7 @@ class MainNavigation(Navigation): mapping = { 'dashboard': { 'broadcast_dashboard', + 'broadcast_dashboard_updates', 'conversation', 'inbox', 'monthly', @@ -697,6 +699,7 @@ class CaseworkNavigation(Navigation): mapping = { 'dashboard': { 'broadcast_dashboard', + 'broadcast_dashboard_updates', }, 'send-one-off': { 'choose_from_contact_list', @@ -1322,6 +1325,7 @@ class OrgNavigation(Navigation): 'who_can_use_notify', 'who_its_for', 'broadcast_dashboard', + 'broadcast_dashboard_updates', 'broadcast', 'preview_broadcast_areas', 'choose_broadcast_library', diff --git a/app/templates/views/broadcast/dashboard.html b/app/templates/views/broadcast/dashboard.html index a7b31722e..3e35af6ec 100644 --- a/app/templates/views/broadcast/dashboard.html +++ b/app/templates/views/broadcast/dashboard.html @@ -1,47 +1,7 @@ -{% from "components/table.html" import list_table, field, right_aligned_field_heading, row_heading %} +{% from 'components/ajax-block.html' import ajax_block %} {% extends "withnav_template.html" %} -{% macro broadcast_table(broadcasts, empty_message) %} -
- {% call(item, row_number) list_table( - broadcasts|sort|reverse|list, - caption="Live broadcasts", - caption_visible=False, - empty_message=empty_message, - field_headings=[ - 'Template name', - 'Status' - ], - field_headings_visible=False - ) %} - {% call row_heading() %} -
- {{ item.template_name }} - - To {{ item.initial_area_names|formatted_list(before_each='', after_each='') }} - -
- {% endcall %} - {% call field(align='right') %} - {% if item.status == 'broadcasting' %} -

- Live until {{ item.finishes_at|format_datetime_relative }} -

- {% elif item.status == 'cancelled' %} -

- Stopped {{ item.cancelled_at|format_datetime_relative }} -

- {% else %} -

- Finished {{ item.finishes_at|format_datetime_relative }} -

- {% endif %} - {% endcall %} - {% endcall %} -
-{% endmacro %} - {% block service_page_title %} Dashboard {% endblock %} @@ -52,10 +12,18 @@

Live broadcasts

- {{ broadcast_table(live_broadcasts, 'You do not have any live broadcasts at the moment') }} + {{ ajax_block( + partials, + url_for('.broadcast_dashboard_updates', service_id=current_service.id), + 'live_broadcasts' + ) }}

Previous broadcasts

- {{ broadcast_table(previous_broadcasts, 'You do not have any previous broadcasts') }} + {{ ajax_block( + partials, + url_for('.broadcast_dashboard_updates', service_id=current_service.id), + 'previous_broadcasts' + ) }} {% endblock %} diff --git a/app/templates/views/broadcast/partials/dashboard-table.html b/app/templates/views/broadcast/partials/dashboard-table.html new file mode 100644 index 000000000..615326b0b --- /dev/null +++ b/app/templates/views/broadcast/partials/dashboard-table.html @@ -0,0 +1,39 @@ +{% from "components/table.html" import list_table, field, right_aligned_field_heading, row_heading %} + +
+ {% call(item, row_number) list_table( + broadcasts|sort|reverse|list, + caption="Live broadcasts", + caption_visible=False, + empty_message=empty_message, + field_headings=[ + 'Template name', + 'Status' + ], + field_headings_visible=False + ) %} + {% call row_heading() %} +
+ {{ item.template_name }} + + To {{ item.initial_area_names|formatted_list(before_each='', after_each='') }} + +
+ {% endcall %} + {% call field(align='right') %} + {% if item.status == 'broadcasting' %} +

+ Live until {{ item.finishes_at|format_datetime_relative }} +

+ {% elif item.status == 'cancelled' %} +

+ Stopped {{ item.cancelled_at|format_datetime_relative }} +

+ {% else %} +

+ Finished {{ item.finishes_at|format_datetime_relative }} +

+ {% endif %} + {% endcall %} + {% endcall %} +
diff --git a/tests/app/main/views/test_broadcast.py b/tests/app/main/views/test_broadcast.py index 8d5ca9cf8..f379717cf 100644 --- a/tests/app/main/views/test_broadcast.py +++ b/tests/app/main/views/test_broadcast.py @@ -1,3 +1,5 @@ +import json + import pytest from flask import url_for from freezegun import freeze_time @@ -10,6 +12,7 @@ sample_uuid = sample_uuid() @pytest.mark.parametrize('endpoint, extra_args', ( ('.broadcast_dashboard', {}), + ('.broadcast_dashboard_updates', {}), ('.broadcast', {'template_id': sample_uuid}), ('.preview_broadcast_areas', {'broadcast_message_id': sample_uuid}), ('.choose_broadcast_library', {'broadcast_message_id': sample_uuid}), @@ -88,6 +91,28 @@ def test_broadcast_dashboard( ] +@freeze_time('2020-02-20 02:20') +def test_broadcast_dashboard_json( + logged_in_client, + service_one, + mock_get_broadcast_messages, +): + service_one['permissions'] += ['broadcast'] + response = logged_in_client.get(url_for( + '.broadcast_dashboard_updates', + service_id=SERVICE_ONE_ID, + )) + + assert response.status_code == 200 + + json_response = json.loads(response.get_data(as_text=True)) + + assert json_response.keys() == {'live_broadcasts', 'previous_broadcasts'} + + assert 'Live until tomorrow at 2:20am' in json_response['live_broadcasts'] + assert 'Finished yesterday at 8:20pm' in json_response['previous_broadcasts'] + + def test_broadcast_page( client_request, service_one,