From 1237fe66016abdf5f42f3168d29aa01da31e563b Mon Sep 17 00:00:00 2001 From: chouseknecht Date: Fri, 16 May 2014 01:00:22 -0400 Subject: [PATCH] Fixed graph rendering and auto-resizing. Removed use of job_host_summaries, making things much faster. Fixed real-time updating so that it now refreshes smoothly as tasks complete. --- awx/ui/static/js/controllers/JobDetail.js | 15 ++- awx/ui/static/js/helpers/JobDetail.js | 144 ++++++++++------------ awx/ui/static/less/job-details.less | 12 +- awx/ui/static/partials/job_detail.html | 4 +- 4 files changed, 89 insertions(+), 86 deletions(-) diff --git a/awx/ui/static/js/controllers/JobDetail.js b/awx/ui/static/js/controllers/JobDetail.js index c5415d7c9a..fed7c0be2c 100644 --- a/awx/ui/static/js/controllers/JobDetail.js +++ b/awx/ui/static/js/controllers/JobDetail.js @@ -35,6 +35,13 @@ function JobDetailController ($scope, $compile, $routeParams, ClearScope, Breadc scope.hostSummaryTableRows = 300; scope.searchAllHostsEnabled = true; + scope.host_summary = {}; + scope.host_summary.ok = 0; + scope.host_summary.changed = 0; + scope.host_summary.unreachable = 0; + scope.host_summary.failed = 0; + scope.host_summary.total = 0; + scope.eventsHelpText = "

Successful

\n" + "

Changed

\n" + "

Unreachable

\n" + @@ -253,7 +260,7 @@ function JobDetailController ($scope, $compile, $routeParams, ClearScope, Breadc } else { // Check if we need to redraw the group - setTimeout(function() { DrawGraph({ scope: scope }); }, 500); + setTimeout(function() { DrawGraph({ scope: scope, resize: true }); }, 500); } }); @@ -279,7 +286,7 @@ function JobDetailController ($scope, $compile, $routeParams, ClearScope, Breadc "padding-right": "15px", "z-index": 0 }); - setTimeout(function() { $('#job-summary-container .job_well').height($('#job-detail-container').height() - 17); }, 500); + setTimeout(function() { $('#job-summary-container .job_well').height($('#job-detail-container').height() - 19); }, 500); $('#job-summary-container').show(); } // Detail table height adjusting. First, put page height back to 'normal'. @@ -356,7 +363,7 @@ function JobDetailController ($scope, $compile, $routeParams, ClearScope, Breadc }).show(); // Adjust the summary table height - $('#job-summary-container .job_well').height(height - 18).css({ + $('#job-summary-container .job_well').height(height - 19).css({ 'box-shadow': '-3px 3px 5px 0 #ccc' }); height = Math.floor($('#job-detail-container').height() * 0.5) - @@ -380,7 +387,7 @@ function JobDetailController ($scope, $compile, $routeParams, ClearScope, Breadc 'padding-left': '15px' }).show('slide', {'direction': 'right'}); - setTimeout(function() { DrawGraph({ scope: scope }); }, 500); + setTimeout(function() { DrawGraph({ scope: scope, resize: true }); }, 500); } else { $('.overlay').hide(); diff --git a/awx/ui/static/js/helpers/JobDetail.js b/awx/ui/static/js/helpers/JobDetail.js index 4fe4812041..c70338aa05 100644 --- a/awx/ui/static/js/helpers/JobDetail.js +++ b/awx/ui/static/js/helpers/JobDetail.js @@ -40,9 +40,9 @@ angular.module('JobDetailHelper', ['Utilities', 'RestServices']) .factory('DigestEvents', ['UpdatePlayStatus', 'UpdateHostStatus', 'UpdatePlayChild', 'AddHostResult', 'SelectPlay', 'SelectTask', - 'GetHostCount', 'GetElapsed', 'UpdateTaskStatus', 'DrawGraph', + 'GetHostCount', 'GetElapsed', 'UpdateTaskStatus', 'DrawGraph', 'LoadHostSummary', function(UpdatePlayStatus, UpdateHostStatus, UpdatePlayChild, AddHostResult, SelectPlay, SelectTask, GetHostCount, GetElapsed, - UpdateTaskStatus, DrawGraph) { + UpdateTaskStatus, DrawGraph, LoadHostSummary) { return function(params) { var scope = params.scope, @@ -230,6 +230,8 @@ function(UpdatePlayStatus, UpdateHostStatus, UpdatePlayChild, AddHostResult, Sel }); scope.job_status.status = (event.failed) ? 'failed' : 'successful'; scope.job_status.status_class = ""; + scope.host_summary = {}; + LoadHostSummary({ scope: scope, data: event.event_data }); DrawGraph({ scope: scope }); } }); @@ -468,7 +470,8 @@ function(UpdatePlayStatus, UpdateHostStatus, UpdatePlayChild, AddHostResult, Sel }]) // Update host summary totals and update the task -.factory('UpdateHostStatus', ['UpdateTaskStatus', 'AddHostResult', function(UpdateTaskStatus, AddHostResult) { +.factory('UpdateHostStatus', ['UpdateTaskStatus', 'AddHostResult', + function(UpdateTaskStatus, AddHostResult) { return function(params) { var scope = params.scope, status = params.status, // successful, changed, unreachable, failed, skipped @@ -494,6 +497,12 @@ function(UpdatePlayStatus, UpdateHostStatus, UpdatePlayChild, AddHostResult, Sel }); if (!host_found) { + // keep totalls for the summary graph + scope.host_summary.total += 1; + scope.host_summary.ok += (status === 'successful') ? 1 : 0; + scope.host_summary.changed += (status === 'changed') ? 1 : 0; + scope.host_summary.unreachable += (status === 'unreachable') ? 1 : 0; + scope.host_summary.failed += (status === 'failed') ? 1 : 0; scope.hosts.push({ id: host_id, name: name, @@ -766,81 +775,75 @@ function(UpdatePlayStatus, UpdateHostStatus, UpdatePlayChild, AddHostResult, Sel }; }]) -.factory('DrawGraph', ['Rest', 'GetBasePath', 'ProcessErrors', function(Rest, GetBasePath, ProcessErrors) { +.factory('LoadHostSummary', [ function() { return function(params) { var scope = params.scope, - dark = 0, failed = 0, changed = 0, ok = 0, - width, height, svg_height, svg_width, svg_radius, svg, url; + data = params.data; + scope.host_summary.ok = Object.keys(data.ok).length; + scope.host_summary.changed = Object.keys(data.changed).length; + scope.host_summary.unreachable = Object.keys(data.dark).length; + scope.host_summary.failed = Object.keys(data.failures).length; + scope.host_summary.total = scope.host_summary.ok + scope.host_summary.changed + + scope.host_summary.unreachable + scope.host_summary.failed; + }; +}]) +.factory('DrawGraph', [ function() { + return function(params) { + var scope = params.scope, + resize = params.resize, + width, height, svg_height, svg_width, svg_radius, svg, graph_data = []; + + // Ready the data + if (scope.host_summary.ok) { + graph_data.push({ + label: 'OK', + value: (scope.host_summary.ok === scope.host_summary.total) ? 1 : scope.host_summary.ok, + color: '#5bb75b' + }); + } + if (scope.host_summary.changed) { + graph_data.push({ + label: 'Changed', + value: (scope.host_summary.changed === scope.host_summary.total) ? 1 : scope.host_summary.changed, + color: '#FF9900' + }); + } + if (scope.host_summary.unreachable) { + graph_data.push({ + label: 'Unreachable', + value: (scope.host_summary.unreachable === scope.host_summary.total) ? 1 : scope.host_summary.unreachable, + color: '#A9A9A9' + }); + } + if (scope.host_summary.failed) { + graph_data.push({ + label: 'Failed', + value: (scope.host_summary.failed === scope.host_summary.total) ? 1 : scope.host_summary.failed, + color: '#DA4D49' + }); + } + + // Adjust the size width = $('#job-summary-container .job_well').width(); height = $('#job-summary-container .job_well').height() - $('#summary-well-top-section').height() - $('#graph-section .header').outerHeight() - 15; svg_radius = Math.min(width, height); svg_width = width; svg_height = height; - if (svg_height > 0 && svg_width > 0) { - if ($('#graph-section svg').length > 0) { - $("#completedHostsDonut").attr('id', 'completedHostsDonut_old'); - svg = d3.select("#graph-section svg").attr("width", svg_width).attr("height", svg_height); - $('#completedHostsDonut').remove(); - svg.append("g").attr("id","completedHostsDonut"); - $('#completedHostsDonut').hide(); - scope.$emit('GraphLoadData'); + if (svg_height > 0 && svg_width > 0) { + if (!resize && $('#graph-section svg').length > 0) { + Donut3D.transition("completedHostsDonut", graph_data, Math.floor(svg_radius * 0.50), Math.floor(svg_radius * 0.25), 18, 0.4); } else { + if ($('#graph-section svg').length > 0) { + $('#graph-section svg').remove(); + } svg = d3.select("#graph-section").append("svg").attr("width", svg_width).attr("height", svg_height); svg.append("g").attr("id","completedHostsDonut"); - scope.$emit('GraphLoadData'); + Donut3D.draw("completedHostsDonut", graph_data, Math.floor(svg_width / 2), Math.floor(svg_height / 2), Math.floor(svg_radius * 0.50), Math.floor(svg_radius * 0.25), 18, 0.4); + $('#graph-section .header .legend').show(); } } - - if (scope.removeRenderGraph) { - scope.removeRenderGraph(); - } - scope.removeRenderGraph = scope.$on('RenderGraph', function(e, graph_data) { - Donut3D.draw("completedHostsDonut", graph_data, Math.floor(svg_width / 2), Math.floor(svg_height / 2), Math.floor(svg_radius * 0.50), Math.floor(svg_radius * 0.25), 18, 0.4); - $('#completedHostsDonut_old').remove(); - $('#completedHostsDonut').show(); - $('#graph-section .legend').show(); - }); - - if (scope.removeGraphLoadData) { - scope.removeGraphLoadData(); - } - scope.removeGraphLoadData = scope.$on('GraphLoadData', function() { - url = GetBasePath('jobs') + scope.job_id + '/job_host_summaries/'; - Rest.setUrl(url); - Rest.get() - .success(function(data) { - var graph_data; - if (data.count) { - data.results.forEach(function(row) { - if (row.dark) { - dark ++; - } - else if (row.failures) { - failed++; - } - else if (row.changed) { - changed++; - } - else if (row.ok) { - ok++; - } - }); - graph_data = [ - { label: 'OK', value: ok, color: '#9ED89E' }, - { label: 'Changed', value: changed, color: '#FFC773' }, - { label: 'Failed', value: failed, color: '#DA4D49' }, - { label: 'Unreachable', value: dark, color: '#A9A9A9' } - ]; - scope.$emit('RenderGraph', graph_data); - } - }) - .error(function(data, status) { - ProcessErrors(scope, data, status, null, { hdr: 'Error!', - msg: 'Call to ' + url + '. GET returned: ' + status }); - }); - }); }; }]) @@ -921,15 +924,4 @@ function(UpdatePlayStatus, UpdateHostStatus, UpdatePlayChild, AddHostResult, Sel msg: 'Call to ' + url + '. GET returned: ' + status }); }); }; -}]); - - - - - - - - - - - +}]); \ No newline at end of file diff --git a/awx/ui/static/less/job-details.less b/awx/ui/static/less/job-details.less index 14d7f794a3..bb77bb06ec 100644 --- a/awx/ui/static/less/job-details.less +++ b/awx/ui/static/less/job-details.less @@ -8,8 +8,10 @@ */ @failed-hosts-color: #DA4D49; -@successful-hosts-color: #9ED89E; -@changed-hosts-color: #FFC773; +@successful-hosts-color: #5bb75b; +@changed-hosts-color: #FF9900; +@skipped-hosts-color: #00BFFF; +@unreachable-hosts-color: #A9A9A9; #jobs-detail { @@ -72,10 +74,10 @@ color: @changed-hosts-color; } .skipped-hosts, .no-matching-hosts { - background-color: #D4D4D4; + background-color: @skipped-hosts-color; } .unreachable-hosts { - background-color: @grey; + background-color: @unreachable-hosts-color; } .unreachable-hosts-color { color: @grey; @@ -309,6 +311,7 @@ label.small-label { .legend { font-size: 12px; i { + font-size: 10px; margin-left: 5px; } i:first-child { @@ -321,6 +324,7 @@ label.small-label { } #graph-section { + position: relative; width: 100%; .header { margin-top: 20px; diff --git a/awx/ui/static/partials/job_detail.html b/awx/ui/static/partials/job_detail.html index 670abba5b5..e64dab2649 100644 --- a/awx/ui/static/partials/job_detail.html +++ b/awx/ui/static/partials/job_detail.html @@ -159,7 +159,7 @@
- +
@@ -209,7 +209,7 @@
-
Host Status Overview
+
Host Status Summary