diff --git a/app/assets/stylesheets/components/table.scss b/app/assets/stylesheets/components/table.scss
index c748bdbcc..8f908ddde 100644
--- a/app/assets/stylesheets/components/table.scss
+++ b/app/assets/stylesheets/components/table.scss
@@ -118,6 +118,10 @@
}
+ &-noborder {
+ border: 0px;
+ }
+
&-index {
width: 15px;
}
@@ -159,6 +163,12 @@
text-align: right;
}
+
+.table-row-group {
+ border-top: 1px solid $border-colour;
+ border-bottom: 1px solid $border-colour;
+}
+
.table-empty-message {
@include core-16;
color: $secondary-text-colour;
diff --git a/app/main/views/platform_admin.py b/app/main/views/platform_admin.py
index 7c883d7e9..46bb030d8 100644
--- a/app/main/views/platform_admin.py
+++ b/app/main/views/platform_admin.py
@@ -1,7 +1,5 @@
import itertools
-from datetime import datetime
-import pytz
from flask import render_template
from flask_login import login_required
@@ -63,13 +61,10 @@ def create_global_stats(services):
def format_stats_by_service(services):
for service in services:
- stats = service['statistics'].values()
yield {
'id': service['id'],
'name': service['name'],
- 'sending': sum((stat['requested'] - stat['delivered'] - stat['failed']) for stat in stats),
- 'delivered': sum(stat['delivered'] for stat in stats),
- 'failed': sum(stat['failed'] for stat in stats),
+ 'stats': service['statistics'],
'restricted': service['restricted'],
'research_mode': service['research_mode'],
'created_at': service['created_at']
diff --git a/app/templates/components/table.html b/app/templates/components/table.html
index 97783ff93..9b0eaf8bc 100644
--- a/app/templates/components/table.html
+++ b/app/templates/components/table.html
@@ -49,10 +49,20 @@
{%- endmacro %}
-{% macro field(align='left', status='') -%}
-
- {{ caller() }}
- |
+{% macro row_group(id=None) %}
+
+ {{ caller() }}
+
+{%- endmacro %}
+
+{% macro field(align='left', status='', border=True) -%}
+
+ {% set field_alignment = 'table-field-right-aligned' if align == 'right' else 'table-field-center-aligned' %}
+ {% set border = '' if border else 'table-field-noborder' %}
+
+
+ {{ caller() }}
+ |
{%- endmacro %}
{% macro row_heading() -%}
diff --git a/app/templates/views/platform-admin.html b/app/templates/views/platform-admin.html
index 38902bc7d..d8b8e6569 100644
--- a/app/templates/views/platform-admin.html
+++ b/app/templates/views/platform-admin.html
@@ -2,49 +2,76 @@
{% from "components/big-number.html" import big_number, big_number_with_status %}
{% from "components/message-count-label.html" import message_count_label %}
{% from "components/browse-list.html" import browse_list %}
-{% from "components/table.html" import list_table, field, right_aligned_field_heading, hidden_field_heading, text_field %}
+{% from "components/table.html" import mapping_table, field, stats_fields, row_group, row, right_aligned_field_heading, hidden_field_heading, text_field %}
+
+{% macro stats_fields(channel, data) -%}
+
+ {% call field(border=False) %}
+ {{ channel.title() }}
+ {% endcall %}
+
+ {% call field(align='right', border=False) %}
+ {{ big_number(data[channel]['requested'], smaller=True) }}
+ {% endcall %}
+
+ {% call field(align='right', border=False) %}
+ {{ big_number(data[channel]['delivered'], smaller=True) }}
+ {% endcall %}
+
+ {% call field(align='right', status='error' if data[channel]['failed'], border=False) %}
+ {{ big_number(data[channel]['failed'], smaller=True) }}
+ {% endcall %}
+
+{%- endmacro %}
{% macro services_table(services, caption) %}
- {% call(item, row_number) list_table(
- services,
+ {% call(item, row_number) mapping_table(
caption=caption,
caption_visible=True,
field_headings=[
- 'Service',
- hidden_field_heading('Status'),
- right_aligned_field_heading('Sending'),
- right_aligned_field_heading('Delivered'),
- right_aligned_field_heading('Failed')
+ 'Service',
+ hidden_field_heading('Type'),
+ right_aligned_field_heading('Sending'),
+ right_aligned_field_heading('Delivered'),
+ right_aligned_field_heading('Failed')
],
field_headings_visible=True
) %}
- {% call field() %}
-
- {% endcall %}
- {% if item['research_mode'] %}
- {% call field() %}
- research mode
+
+ {% for service in services %}
+
+ {% call row_group() %}
+
+ {% call row() %}
+ {% call field(border=False) %}
+ {{ service['name'] }}
+ {% endcall %}
+
+ {{ stats_fields('email', service['stats']) }}
+ {% endcall %}
+
+ {% call row() %}
+ {% if service['research_mode'] %}
+ {% call field(border=False) %}
+ research mode
+ {% endcall %}
+ {% elif not service['restricted'] %}
+ {% call field(status='error') %}
+
+ Live
+
+ {% endcall %}
+ {% else %}
+ {{ text_field('') }}
+ {% endif %}
+
+ {{ stats_fields('sms', service['stats']) }}
+ {% endcall %}
+
{% endcall %}
- {% elif not item['restricted'] %}
- {% call field(status='error') %}
-
- Live
-
- {% endcall %}
- {% else %}
- {{ text_field('') }}
- {% endif %}
- {% call field(align='right') %}
- {{ big_number(item['sending'], smaller=True) }}
- {% endcall %}
- {% call field(align='right') %}
- {{ big_number(item['delivered'], smaller=True) }}
- {% endcall %}
- {% call field(align='right', status='error' if 0 else '') %}
- {{ big_number(item['failed'], smaller=True) }}
- {% endcall %}
+
+ {% endfor %}
+
{% endcall %}
{% endmacro %}
diff --git a/tests/app/main/views/test_platform_admin.py b/tests/app/main/views/test_platform_admin.py
index ca95d704a..74ba43a35 100644
--- a/tests/app/main/views/test_platform_admin.py
+++ b/tests/app/main/views/test_platform_admin.py
@@ -60,8 +60,10 @@ def test_should_show_research_and_restricted_mode(
assert response.status_code == 200
mock_get_detailed_services.assert_called_once_with({'detailed': True})
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
- # get second column, which contains flags as text.
- assert page.find_all('tbody')[table_index].find_all('td')[1].text.strip() == displayed
+ # get first column in second row, which contains flags as text.
+ table_body = page.find_all('table')[table_index].find_all('tbody')[0]
+ service_mode = table_body.find_all('tbody')[0].find_all('tr')[1].find_all('td')[0].text.strip()
+ assert service_mode == displayed
def test_should_render_platform_admin_page(
@@ -141,7 +143,7 @@ def create_stats(
}
-def test_format_stats_by_service_sums_values_for_sending(fake_uuid):
+def test_format_stats_by_service_returns_correct_values(fake_uuid):
services = [service_json(fake_uuid, 'a', [])]
services[0]['statistics'] = create_stats(
emails_requested=10,
@@ -153,8 +155,62 @@ def test_format_stats_by_service_sums_values_for_sending(fake_uuid):
)
ret = list(format_stats_by_service(services))
-
assert len(ret) == 1
- assert ret[0]['sending'] == 34
- assert ret[0]['delivered'] == 10
- assert ret[0]['failed'] == 16
+ assert ret[0]['stats']['email']['requested'] == 10
+ assert ret[0]['stats']['email']['delivered'] == 3
+ assert ret[0]['stats']['email']['failed'] == 5
+
+ assert ret[0]['stats']['sms']['requested'] == 50
+ assert ret[0]['stats']['sms']['delivered'] == 7
+ assert ret[0]['stats']['sms']['failed'] == 11
+
+
+@pytest.mark.parametrize('restricted, table_index, research_mode', [
+ (True, 1, False),
+ (False, 0, False)
+])
+def test_should_show_email_and_sms_stats_for_all_service_types(
+ restricted,
+ table_index,
+ research_mode,
+ app_,
+ platform_admin_user,
+ mocker,
+ mock_get_detailed_services,
+ fake_uuid
+):
+ services = [service_json(fake_uuid, 'My Service', [], restricted=restricted, research_mode=research_mode)]
+ services[0]['statistics'] = create_stats(
+ emails_requested=10,
+ emails_delivered=3,
+ emails_failed=5,
+ sms_requested=50,
+ sms_delivered=7,
+ sms_failed=11
+ )
+
+ mock_get_detailed_services.return_value = {'data': services}
+ with app_.test_request_context():
+ with app_.test_client() as client:
+ mock_get_user(mocker, user=platform_admin_user)
+ client.login(platform_admin_user)
+ response = client.get(url_for('main.platform_admin'))
+
+ assert response.status_code == 200
+ mock_get_detailed_services.assert_called_once_with({'detailed': True})
+ page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
+
+ table_body = page.find_all('table')[table_index].find_all('tbody')[0]
+ service_row_group = table_body.find_all('tbody')[0].find_all('tr')
+ email_stats = service_row_group[0].find_all('td')[2:]
+ sms_stats = service_row_group[1].find_all('td')[2:]
+
+ email_sending, email_delivered, email_failed = [int(stat.text.split()[0]) for stat in email_stats]
+ sms_sending, sms_delivered, sms_failed = [int(stat.text.split()[0]) for stat in sms_stats]
+
+ assert email_sending == 10
+ assert email_delivered == 3
+ assert email_failed == 5
+ assert sms_sending == 50
+ assert sms_delivered == 7
+ assert sms_failed == 11