Improvements to job detail page graph rendering and auto-resizing.

This commit is contained in:
chouseknecht
2014-05-15 13:49:52 -04:00
parent 70e42aff36
commit 200a528391
4 changed files with 201 additions and 244 deletions

View File

@@ -8,7 +8,7 @@
'use strict'; 'use strict';
function JobDetailController ($scope, $compile, $routeParams, ClearScope, Breadcrumbs, LoadBreadCrumbs, GetBasePath, Wait, Rest, ProcessErrors, DigestEvents, function JobDetailController ($scope, $compile, $routeParams, ClearScope, Breadcrumbs, LoadBreadCrumbs, GetBasePath, Wait, Rest, ProcessErrors, DigestEvents,
SelectPlay, SelectTask, Socket, GetElapsed, SelectHost, FilterAllByHostName) { SelectPlay, SelectTask, Socket, GetElapsed, SelectHost, FilterAllByHostName, DrawGraph) {
ClearScope(); ClearScope();
@@ -251,6 +251,10 @@ function JobDetailController ($scope, $compile, $routeParams, ClearScope, Breadc
// First time. User just loaded page. // First time. User just loaded page.
scope.$emit('LoadJob'); scope.$emit('LoadJob');
} }
else {
// Check if we need to redraw the group
setTimeout(function() { DrawGraph({ scope: scope }); }, 500);
}
}); });
scope.adjustSize = function() { scope.adjustSize = function() {
@@ -275,7 +279,7 @@ function JobDetailController ($scope, $compile, $routeParams, ClearScope, Breadc
"padding-right": "15px", "padding-right": "15px",
"z-index": 0 "z-index": 0
}); });
setTimeout(function() { $('#job-summary-container .job_well').height($('#job-detail-container').height() - 18); }, 500); setTimeout(function() { $('#job-summary-container .job_well').height($('#job-detail-container').height() - 17); }, 500);
$('#job-summary-container').show(); $('#job-summary-container').show();
} }
// Detail table height adjusting. First, put page height back to 'normal'. // Detail table height adjusting. First, put page height back to 'normal'.
@@ -304,99 +308,6 @@ function JobDetailController ($scope, $compile, $routeParams, ClearScope, Breadc
scope.$emit('RefreshCompleted'); scope.$emit('RefreshCompleted');
}; };
/*function refreshHostRows() {
var url;
if (scope.activeTask) {
scope.hostResults = [];
scope.auto_scroll = true;
url = GetBasePath('jobs') + job_id + '/job_events/?parent=' + scope.activeTask + '&';
url += (scope.task_host_name) ? 'host__name__icontains=' + scope.task_host_name + '&' : '';
url += 'host__isnull=false&page_size=' + scope.hostTableRows + '&order_by=host__name';
Wait('start');
Rest.setUrl(url);
Rest.get()
.success(function(data) {
data.results.forEach(function(row) {
scope.hostResults.push({
id: row.id,
status: ( (row.failed) ? 'failed': (row.changed) ? 'changed' : 'successful' ),
host_id: row.host,
task_id: row.parent,
name: row.event_data.host,
created: row.created,
msg: ( (row.event_data && row.event_data.res) ? row.event_data.res.msg : '' )
});
});
$('#hosts-table-detail').mCustomScrollbar("update");
setTimeout( function() { $('#hosts-table-detail').mCustomScrollbar("scrollTo", "bottom"); }, 700);
Wait('stop');
scope.$emit('RefreshCompleted');
})
.error(function(data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + '. GET returned: ' + status });
});
}
else {
$('#hosts-table-detail').mCustomScrollbar("update");
scope.$emit('RefreshCompleted');
}
}
function refreshSummaryHostRows() {
if (scope.hosts.length < scope.hostSummaryTableRows) {
var url = GetBasePath('jobs') + job_id + '/job_host_summaries/?';
url += (scope.summary_host_name) ? 'host__name__icontains=' + scope.summary_host_name + '&': '';
url += '&page_size=' + scope.hostSummaryTableRows + '&order_by=host__name';
Wait('start');
Rest.setUrl(url);
Rest.get()
.success(function(data) {
data.results.forEach(function(row) {
var found = false;
scope.hosts.every(function(host) {
if (host.id === row.host) {
found = true;
return false;
}
return true;
});
if (!found) {
scope.hosts.push({
id: row.host,
name: row.summary_fields.host.name,
ok: row.ok,
changed: row.changed,
unreachable: row.dark,
failed: row.failures
});
}
});
scope.hosts.sort(function(a,b) {
if (a.name < b.name) {
return -1;
}
if (a.name > b.name) {
return 1;
}
return 0;
});
$('#hosts-summary-table').mCustomScrollbar("update");
setTimeout( function() { $('#hosts-summary-table').mCustomScrollbar("scrollTo", "bottom"); }, 700);
Wait('stop');
scope.$emit('RefreshCompleted');
})
.error(function(data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + '. GET returned: ' + status });
});
}
else {
$('#hosts-table-detail').mCustomScrollbar("update");
scope.$emit('RefreshCompleted');
}
}*/
setTimeout(function() { scope.adjustSize(); }, 500); setTimeout(function() { scope.adjustSize(); }, 500);
// Use debounce for the underscore library to adjust after user resizes window. // Use debounce for the underscore library to adjust after user resizes window.
@@ -443,10 +354,23 @@ function JobDetailController ($scope, $compile, $routeParams, ClearScope, Breadc
width: $(document).width(), width: $(document).width(),
height: $(document).height() height: $(document).height()
}).show(); }).show();
// Adjust the summary table height
$('#job-summary-container .job_well').height(height - 18).css({ $('#job-summary-container .job_well').height(height - 18).css({
'box-shadow': '-3px 3px 5px 0 #ccc' 'box-shadow': '-3px 3px 5px 0 #ccc'
}); });
height = Math.floor($('#job-detail-container').height() * 0.5) -
$('#hosts-summary-section .header').outerHeight() -
$('#hosts-summary-section .table-header').outerHeight() -
$('#hide-summary-button').outerHeight() -
$('#summary-search-section').outerHeight() -
$('#hosts-summary-section .header').outerHeight() -
$('#hosts-summary-section .legend').outerHeight();
$('#hosts-summary-table').height(height - 50);
$('#hosts-summary-table').mCustomScrollbar("update");
$('#hide-summary-button').show(); $('#hide-summary-button').show();
$('#job-summary-container').css({ $('#job-summary-container').css({
top: 0, top: 0,
right: 0, right: 0,
@@ -455,6 +379,8 @@ function JobDetailController ($scope, $compile, $routeParams, ClearScope, Breadc
'padding-right': '15px', 'padding-right': '15px',
'padding-left': '15px' 'padding-left': '15px'
}).show('slide', {'direction': 'right'}); }).show('slide', {'direction': 'right'});
setTimeout(function() { DrawGraph({ scope: scope }); }, 500);
} }
else { else {
$('.overlay').hide(); $('.overlay').hide();
@@ -754,5 +680,5 @@ function JobDetailController ($scope, $compile, $routeParams, ClearScope, Breadc
} }
JobDetailController.$inject = [ '$scope', '$compile', '$routeParams', 'ClearScope', 'Breadcrumbs', 'LoadBreadCrumbs', 'GetBasePath', 'Wait', JobDetailController.$inject = [ '$scope', '$compile', '$routeParams', 'ClearScope', 'Breadcrumbs', 'LoadBreadCrumbs', 'GetBasePath', 'Wait',
'Rest', 'ProcessErrors', 'DigestEvents', 'SelectPlay', 'SelectTask', 'Socket', 'GetElapsed', 'SelectHost', 'FilterAllByHostName' 'Rest', 'ProcessErrors', 'DigestEvents', 'SelectPlay', 'SelectTask', 'Socket', 'GetElapsed', 'SelectHost', 'FilterAllByHostName', 'DrawGraph'
]; ];

View File

@@ -494,8 +494,6 @@ function(UpdatePlayStatus, UpdateHostStatus, UpdatePlayChild, AddHostResult, Sel
}); });
if (!host_found) { if (!host_found) {
if (scope.hosts.length < 10 || name > scope.hosts[0].name) {
// This is a new host we want added to the list
scope.hosts.push({ scope.hosts.push({
id: host_id, id: host_id,
name: name, name: name,
@@ -513,16 +511,14 @@ function(UpdatePlayStatus, UpdateHostStatus, UpdatePlayChild, AddHostResult, Sel
} }
return 0; return 0;
}); });
// Only keep 10 hosts
if (scope.hosts.length > scope.hostSummaryTableRows) { if (scope.hosts.length > scope.hostSummaryTableRows) {
scope.hosts.splice(0,1); scope.hosts.pop();
} }
$('#tasks-table-detail').mCustomScrollbar("update"); $('#tasks-table-detail').mCustomScrollbar("update");
setTimeout( function() { /*setTimeout( function() {
scope.auto_scroll = true; scope.auto_scroll = true;
$('#hosts-summary-table').mCustomScrollbar("scrollTo", "bottom"); $('#hosts-summary-table').mCustomScrollbar("scrollTo", "bottom");
}, 700); }, 700);*/
}
} }
UpdateTaskStatus({ UpdateTaskStatus({
@@ -774,33 +770,48 @@ function(UpdatePlayStatus, UpdateHostStatus, UpdatePlayChild, AddHostResult, Sel
return function(params) { return function(params) {
var scope = params.scope, var scope = params.scope,
dark = 0, failed = 0, changed = 0, ok = 0, dark = 0, failed = 0, changed = 0, ok = 0,
svg_height, svg_width, graph_data, svg, url; width, height, svg_height, svg_width, svg_radius, svg, url;
svg_width = $('#graph-section').width(); width = $('#job-summary-container .job_well').width();
svg_height = 300; height = $('#job-summary-container .job_well').height() - $('#summary-well-top-section').height() - $('#graph-section .header').outerHeight() - 15;
if ($('#graph-section svg').length === 0) { svg_radius = Math.min(width, height);
svg = d3.select("#graph-section").append("svg").attr("width", svg_width).attr("height", svg_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');
} }
else { else {
svg = d3.select("#graph-section svg"); svg = d3.select("#graph-section").append("svg").attr("width", svg_width).attr("height", svg_height);
svg.append("g").attr("id","completedHostsDonut");
scope.$emit('GraphLoadData');
}
} }
svg.append("g").attr("id","completedHostsDonutNew");
$('#completedHostsDonutNew').hide();
if (scope.removeRenderGraph) { if (scope.removeRenderGraph) {
scope.removeRenderGraph(); scope.removeRenderGraph();
} }
scope.removeRenderGraph = scope.$on('RenderGraph', function() { scope.removeRenderGraph = scope.$on('RenderGraph', function(e, graph_data) {
Donut3D.draw("completedHostsDonutNew", graph_data, Math.floor(svg_width / 2), 150, 130, 100, 15, 0.4); 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').remove(); $('#completedHostsDonut_old').remove();
$('#completedHostsDonutNew').attr('id','completedHostsDonut');
$('#completedHostsDonut').show(); $('#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/'; url = GetBasePath('jobs') + scope.job_id + '/job_host_summaries/';
Rest.setUrl(url); Rest.setUrl(url);
Rest.get() Rest.get()
.success(function(data) { .success(function(data) {
var graph_data;
if (data.count) { if (data.count) {
data.results.forEach(function(row) { data.results.forEach(function(row) {
if (row.dark) { if (row.dark) {
@@ -822,13 +833,14 @@ function(UpdatePlayStatus, UpdateHostStatus, UpdatePlayChild, AddHostResult, Sel
{ label: 'Failed', value: failed, color: '#DA4D49' }, { label: 'Failed', value: failed, color: '#DA4D49' },
{ label: 'Unreachable', value: dark, color: '#A9A9A9' } { label: 'Unreachable', value: dark, color: '#A9A9A9' }
]; ];
scope.$emit('RenderGraph'); scope.$emit('RenderGraph', graph_data);
} }
}) })
.error(function(data, status) { .error(function(data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!', ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + '. GET returned: ' + status }); msg: 'Call to ' + url + '. GET returned: ' + status });
}); });
});
}; };
}]) }])

View File

@@ -301,26 +301,41 @@ label.small-label {
.badge-column a { .badge-column a {
width: 20%; width: 20%;
} }
.legend {
margin: 8px 0;
}
}
.legend {
font-size: 12px;
i {
margin-left: 5px;
}
i:first-child {
margin-left: 0;
}
} }
.mCSB_container { .mCSB_container {
margin-right: 18px; margin-right: 18px;
} }
#graph-section { #graph-section {
position: relative; width: 100%;
.header {
margin-top: 20px;
.legend { .legend {
font-size: 12px; text-align: center;
margin-top: 10px; margin: 15px 0 0 0;
}
i { i {
margin-left: 5px; margin-left: 10px
} }
i:first-child { i:first-child {
margin-left: 0; margin-left: 0;
} }
} }
}
}
path.slice{ path.slice{
stroke-width:2px; stroke-width:2px;

View File

@@ -135,6 +135,7 @@
<div id="job-summary-container"> <div id="job-summary-container">
<div class="job_well"> <div class="job_well">
<div id="summary-well-top-section">
<div id="hide-summary-button" style="display: hidden;"> <div id="hide-summary-button" style="display: hidden;">
<a href="" class="btn btn-xs btn-default" ng-click="toggleSummary('hide')" aw-tool-tip="Hide summary" data-placement="top"><i class="fa fa-arrow-circle-right fa-lg"></i></a> <a href="" class="btn btn-xs btn-default" ng-click="toggleSummary('hide')" aw-tool-tip="Hide summary" data-placement="top"><i class="fa fa-arrow-circle-right fa-lg"></i></a>
</div> </div>
@@ -174,11 +175,13 @@
<a class="search-icon" ng-show="!searchSummaryHostsEnabled" ng-click="summary_host_name=''; searchSummaryHosts()"><i class="fa fa-times"></i></a> <a class="search-icon" ng-show="!searchSummaryHostsEnabled" ng-click="summary_host_name=''; searchSummaryHosts()"><i class="fa fa-times"></i></a>
</div> </div>
</div> </div>
<div class="legend"><i class="fa fa-circle successful-hosts-color"></i> Successful <i class="fa fa-circle changed-hosts-color"></i> Changed
<i class="fa fa-circle unreachable-hosts-color"></i> Unreachable <i class="fa fa-circle failed-hosts-color"></i> Failed</div>
<div class="table-header"> <div class="table-header">
<div class="row"> <div class="row">
<div class="col-lg-6 col-md-6 col-sm-6 col-xs-6">Host</div> <div class="col-lg-6 col-md-6 col-sm-6 col-xs-6">Host</div>
<div class="col-lg-6 col-md-6 col-sm-6 col-xs-6">Events <div class="col-lg-6 col-md-6 col-sm-6 col-xs-6">Completed Tasks
<a href="" id="event-help-link" aw-pop-over="{{ eventsHelpText }}" aw-tool-tip="Click for help" aw-pop-over-watch="eventsHelpText" data-placement="top" data-container="body" data-title="Event Legend" class="help-link"><i class="fa fa-question-circle"></i></a> <!-- <a href="" id="event-help-link" aw-pop-over="{{ eventsHelpText }}" aw-tool-tip="Click for help" aw-pop-over-watch="eventsHelpText" data-placement="top" data-container="body" data-title="Event Legend" class="help-link"><i class="fa fa-question-circle"></i></a> -->
</div> </div>
</div> </div>
</div> </div>
@@ -202,11 +205,12 @@
</div> </div>
</div> </div>
</div><!-- section --> </div><!-- section -->
</div><!-- summary-well-top-section -->
<div id="graph-section"> <div id="graph-section" class="section">
<div class="header"> <div class="header">
<div class="title">Host Status Overview</div> <div class="title">Host Status Overview</div>
<div class="legend"><i class="fa fa-circle successful-hosts-color"></i> Successful <i class="fa fa-circle changed-hosts-color"></i> Changed <div class="legend" style="display: none;"><i class="fa fa-circle successful-hosts-color"></i> Successful <i class="fa fa-circle changed-hosts-color"></i> Changed
<i class="fa fa-circle unreachable-hosts-color"></i> Unreachable <i class="fa fa-circle failed-hosts-color"></i> Failed</div> <i class="fa fa-circle unreachable-hosts-color"></i> Unreachable <i class="fa fa-circle failed-hosts-color"></i> Failed</div>
</div> </div>
</div><!-- graph section --> </div><!-- graph section -->