From 5c57f5b5884083d2ccf2954a1315c05579dc78bb Mon Sep 17 00:00:00 2001 From: Chris Hill-Scott Date: Wed, 23 Mar 2016 08:43:45 +0000 Subject: [PATCH 1/3] Make dashboard stats update dynamically https://www.pivotaltracker.com/story/show/115874485 This uses the same component as on the jobs page to make a partial section of the page update itself periodically. --- app/main/views/dashboard.py | 17 ++++++++++++++++- app/templates/views/dashboard/dashboard.html | 10 +++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/app/main/views/dashboard.py b/app/main/views/dashboard.py index 6fc17c49c..8cec638b4 100644 --- a/app/main/views/dashboard.py +++ b/app/main/views/dashboard.py @@ -1,7 +1,8 @@ from flask import ( render_template, session, - flash + flash, + jsonify ) from flask_login import login_required @@ -41,6 +42,20 @@ def service_dashboard(service_id): service_id=str(service_id)) +@main.route("/services//dashboard.json") +@login_required +def service_dashboard_updates(service_id): + + statistics = statistics_api_client.get_statistics_for_service(service_id)['data'] + + return jsonify(**{ + 'today': render_template( + 'views/dashboard/today.html', + statistics=expand_statistics(statistics), + ) + }) + + def expand_statistics(statistics, danger_zone=25): if not statistics or not statistics[0]: diff --git a/app/templates/views/dashboard/dashboard.html b/app/templates/views/dashboard/dashboard.html index 67fb31a53..d41e85f4d 100644 --- a/app/templates/views/dashboard/dashboard.html +++ b/app/templates/views/dashboard/dashboard.html @@ -13,7 +13,15 @@ {% if not jobs %} {% include 'views/dashboard/get-started.html' %} {% else %} - {% include 'views/dashboard/today.html' %} + +
+ {% include 'views/dashboard/today.html' %} +
+ {% include 'views/dashboard/jobs.html' %} {% endif %} From 4411f8cb37d1f0b17dacbfe3c02b84aea0940034 Mon Sep 17 00:00:00 2001 From: Chris Hill-Scott Date: Wed, 23 Mar 2016 08:54:48 +0000 Subject: [PATCH 2/3] Allow custom interval on AJAX sections of page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some pages with AJAX should update quickly, because the data is likely to be changing quickly, and be finished changing sooner. Other pages we want to have tick over a bit slower. This commit adds an optional ‘interval’ parameter to the updateContent modules, which sets how often the page should ping the server for an update. It then sets the interval for the dashboard page to be 10 seconds, rather than the default 1.5 seconds. --- app/assets/javascripts/updateContent.js | 11 +++++------ app/templates/views/dashboard/dashboard.html | 1 + 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/updateContent.js b/app/assets/javascripts/updateContent.js index 64cfc7325..4c78d4473 100644 --- a/app/assets/javascripts/updateContent.js +++ b/app/assets/javascripts/updateContent.js @@ -1,12 +1,10 @@ (function(GOVUK, Modules) { "use strict"; - const interval = 1500; // milliseconds - GOVUK.timeCache = {}; GOVUK.resultCache = {}; - let getter = function(resource, render) { + let getter = function(resource, interval, render) { if ( GOVUK.resultCache[resource] && @@ -23,8 +21,8 @@ }; - let poller = (resource, key, component) => () => getter( - resource, response => component.html(response[key]) + let poller = (resource, key, component, interval) => () => getter( + resource, interval, response => component.html(response[key]) ); Modules.UpdateContent = function() { @@ -32,9 +30,10 @@ this.start = function(component) { const $component = $(component); + interval = ($(component).data("interval-seconds") * 1000) || 1500; setInterval( - poller($component.data('resource'), $component.data('key'), $component), + poller($component.data('resource'), $component.data('key'), $component, interval), interval / 5 ); diff --git a/app/templates/views/dashboard/dashboard.html b/app/templates/views/dashboard/dashboard.html index d41e85f4d..411642b04 100644 --- a/app/templates/views/dashboard/dashboard.html +++ b/app/templates/views/dashboard/dashboard.html @@ -18,6 +18,7 @@ data-module="update-content" data-resource="{{url_for(".service_dashboard_updates", service_id=service_id)}}" data-key="today" + data-interval-seconds="10" > {% include 'views/dashboard/today.html' %} From 45ea12e13f575e45971a315d05870d8584d04e0a Mon Sep 17 00:00:00 2001 From: Chris Hill-Scott Date: Wed, 23 Mar 2016 09:21:35 +0000 Subject: [PATCH 3/3] Improve display of failure rates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://www.pivotaltracker.com/story/show/116052359 - add absolute numbers for failures - make percentages accurate to 1 decimal place (50.0%) - make error colour appear if failures go above 3.0% - make error colour boolean (don’t interpolate between the colours) --- .../stylesheets/components/big-number.scss | 27 +++++-------------- app/main/views/dashboard.py | 27 +++++++++---------- app/templates/components/big-number.html | 11 +++++--- app/templates/views/dashboard/today.html | 12 ++++----- 4 files changed, 33 insertions(+), 44 deletions(-) diff --git a/app/assets/stylesheets/components/big-number.scss b/app/assets/stylesheets/components/big-number.scss index a14f30d9b..ab656c2bf 100644 --- a/app/assets/stylesheets/components/big-number.scss +++ b/app/assets/stylesheets/components/big-number.scss @@ -25,21 +25,13 @@ padding-bottom: 0; } + %big-number-status, .big-number-status { + @include core-19; display: block; background: $green; - position: relative; - - &-error-percentage { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: $error-colour; - z-index: 1; - } + padding: 15px; a { @@ -52,16 +44,11 @@ } - .big-number { - @include bold-19; - position: relative; - z-index: 2; - } - - .big-number-label { - display: inline; - } + } + .big-number-status-failing { + @extend %big-number-status; + background: $error-colour; } } diff --git a/app/main/views/dashboard.py b/app/main/views/dashboard.py index 8cec638b4..f05e15a42 100644 --- a/app/main/views/dashboard.py +++ b/app/main/views/dashboard.py @@ -37,7 +37,7 @@ def service_dashboard(service_id): free_text_messages_remaining='250,000', spent_this_month='0.00', service=service['data'], - statistics=expand_statistics(statistics), + statistics=add_rates_to(statistics), templates=templates, service_id=str(service_id)) @@ -51,28 +51,27 @@ def service_dashboard_updates(service_id): return jsonify(**{ 'today': render_template( 'views/dashboard/today.html', - statistics=expand_statistics(statistics), + statistics=add_rates_to(statistics), ) }) -def expand_statistics(statistics, danger_zone=25): +def add_rates_to(delivery_statistics): - if not statistics or not statistics[0]: + if not delivery_statistics or not delivery_statistics[0]: return {} - today = statistics[0] + today = delivery_statistics[0] today.update({ - 'emails_failure_rate': - int(today['emails_error'] / today['emails_requested'] * 100) if today['emails_requested'] else 0, - 'sms_failure_rate': - int(today['sms_error'] / today['sms_requested'] * 100) if today['sms_requested'] else 0 - }) - - today.update({ - 'emails_percentage_of_danger_zone': min(today['emails_failure_rate'] / (danger_zone / 100), 100), - 'sms_percentage_of_danger_zone': min(today['sms_failure_rate'] / (danger_zone / 100), 100) + 'emails_failure_rate': ( + "{0:.1f}".format((today['emails_error'] / today['emails_requested'] * 100)) + if today['emails_requested'] else 0 + ), + 'sms_failure_rate': ( + "{0:.1f}".format((today['sms_error'] / today['sms_requested'] * 100)) + if today['sms_requested'] else 0 + ) }) return today diff --git a/app/templates/components/big-number.html b/app/templates/components/big-number.html index 9ee6affb9..403228219 100644 --- a/app/templates/components/big-number.html +++ b/app/templates/components/big-number.html @@ -6,12 +6,15 @@ {% endmacro %} -{% macro big_number_with_status(number, label, status_number, status_label, percentage_bad=0) %} +{% macro big_number_with_status(number, label, failures, failure_percentage, danger_zone=False) %}
{{ big_number(number, label) }} -
-
- {{ big_number(status_number, status_label) }} +
+ {% if failures %} + {{ failures }} failed – {{ failure_percentage }}% + {% else %} + No failures + {% endif %}
{% endmacro %} diff --git a/app/templates/views/dashboard/today.html b/app/templates/views/dashboard/today.html index bc1d13abf..2dc3e5f6f 100644 --- a/app/templates/views/dashboard/today.html +++ b/app/templates/views/dashboard/today.html @@ -8,18 +8,18 @@ {{ big_number_with_status( statistics.get('emails_requested', 0), 'email' if statistics.get('emails_requested') == 1 else 'emails', - '{}%'.format(statistics.get('emails_failure_rate', 0)), - 'failed', - statistics.get('emails_percentage_of_danger_zone', 0) + statistics.get('emails_error'), + statistics.get('emails_failure_rate', 0.0), + statistics.get('emails_failure_rate', 0)|float > 3 ) }}
{{ big_number_with_status( statistics.get('sms_requested', 0), 'text message' if statistics.get('sms_requested') == 1 else 'text messages', - '{}%'.format(statistics.get('sms_failure_rate', 0)), - 'failed', - statistics.get('sms_percentage_of_danger_zone', 0) + statistics.get('sms_error'), + statistics.get('sms_failure_rate', 0.0), + statistics.get('sms_failure_rate', 0)|float > 3 ) }}