Job detail page refactor / 2.0 style changes

Removed well and index from primary list pages. Job detail page cleanup. Fixed status filter on host summary list. Incresed # rows kept in memory for each list to 100. Showing unreachable host count on the play, mostly to help debugging.
This commit is contained in:
Chris Houseknecht
2014-06-25 22:45:16 -04:00
parent ed9bb6c572
commit 73255eace9
24 changed files with 75 additions and 45 deletions

View File

@@ -25,10 +25,10 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
scope.tasks = []; scope.tasks = [];
scope.hostResults = []; scope.hostResults = [];
scope.hostResultsMaxRows = 15; scope.hostResultsMaxRows = 100;
scope.hostSummariesMaxRows = 15; scope.hostSummariesMaxRows = 100;
scope.tasksMaxRows = 15; scope.tasksMaxRows = 100;
scope.playsMaxRows = 15; scope.playsMaxRows = 100;
scope.liveEventProcessing = true; // control play/pause state of event processing scope.liveEventProcessing = true; // control play/pause state of event processing
@@ -126,7 +126,7 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
$rootScope.jobDetailInterval = setInterval(function() { $rootScope.jobDetailInterval = setInterval(function() {
$log.debug('Updating the DOM...'); $log.debug('Updating the DOM...');
UpdateDOM({ scope: scope }); UpdateDOM({ scope: scope });
}, 5000); }, 2500);
} }
}); });
@@ -149,7 +149,8 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
ok: event.ok, ok: event.ok,
changed: event.changed, changed: event.changed,
unreachable: event.dark, unreachable: event.dark,
failed: event.failures failed: event.failures,
status: (event.failed) ? 'failed' : 'successful'
}; };
}); });
scope.$emit('InitialLoadComplete'); scope.$emit('InitialLoadComplete');
@@ -222,7 +223,7 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
data.results.forEach(function(event, idx) { data.results.forEach(function(event, idx) {
var end, elapsed; var end, elapsed;
if (!play.firstTask) { if (play.firstTask === undefined || play.firstTask === null) {
play.firstTask = event.id; play.firstTask = event.id;
play.hostCount = (event.host_count) ? event.host_count : 0; play.hostCount = (event.host_count) ? event.host_count : 0;
} }
@@ -341,6 +342,8 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
hostCount: 0, hostCount: 0,
fistTask: null, fistTask: null,
playActiveClass: '', playActiveClass: '',
unreachableCount: (data.unreachable_count) ? data.unreachable_count : 0,
status_text: status,
tasks: {} tasks: {}
}; };

View File

@@ -67,6 +67,8 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
elapsed: '00:00:00', elapsed: '00:00:00',
hostCount: 0, hostCount: 0,
fistTask: null, fistTask: null,
unreachableCount: 0,
status_text: (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful',
tasks: {} tasks: {}
}; };
if (scope.activePlay) { if (scope.activePlay) {
@@ -406,7 +408,8 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
ok: (status === 'successful') ? 1 : 0, ok: (status === 'successful') ? 1 : 0,
changed: (status === 'changed') ? 1 : 0, changed: (status === 'changed') ? 1 : 0,
unreachable: (status === 'unreachable') ? 1 : 0, unreachable: (status === 'unreachable') ? 1 : 0,
failed: (status === 'failed') ? 1 : 0 failed: (status === 'failed') ? 1 : 0,
status: (status === 'failed') ? 'failed' : 'successful'
}; };
} }
@@ -454,6 +457,11 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
msg: msg msg: msg
}; };
// increment the unreachable count on the play
if (status === 'unreachable' && scope.jobData.plays[scope.activePlay]) {
scope.jobData.plays[scope.activePlay].unreachableCount++;
}
// update the task status bar // update the task status bar
if (scope.jobData.plays[scope.activePlay].tasks[task_id] !== undefined) { if (scope.jobData.plays[scope.activePlay].tasks[task_id] !== undefined) {
task = scope.jobData.plays[scope.activePlay].tasks[task_id]; task = scope.jobData.plays[scope.activePlay].tasks[task_id];
@@ -464,7 +472,7 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
} }
task.reportedHosts += 1; task.reportedHosts += 1;
task.failedCount += (status === 'failed' || status === 'unreachable') ? 1 : 0; task.failedCount += (status === 'failed') ? 1 : 0;
task.changedCount += (status === 'changed') ? 1 : 0; task.changedCount += (status === 'changed') ? 1 : 0;
task.successfulCount += (status === 'successful') ? 1 : 0; task.successfulCount += (status === 'successful') ? 1 : 0;
task.skippedCount += (status === 'skipped') ? 1 : 0; task.skippedCount += (status === 'skipped') ? 1 : 0;
@@ -745,10 +753,9 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
url = scope.job.related.job_host_summaries + '?'; url = scope.job.related.job_host_summaries + '?';
url += (scope.search_all_hosts_name) ? 'host__name__icontains=' + scope.search_all_hosts_name + '&': ''; url += (scope.search_all_hosts_name) ? 'host__name__icontains=' + scope.search_all_hosts_name + '&': '';
url += (scope.searchAllStatus === 'failed') ? 'failed=true&' : ''; url += (scope.searchAllStatus === 'failed') ? 'failed=true&' : '';
url += 'page_size=' + scope.hostSummaryTableRows + '&order_by=host__name'; url += 'page_size=' + scope.hostSummariesMaxRows + '&order_by=host__name';
scope.hosts = []; scope.hosts = [];
scope.hostsMap = {};
Rest.setUrl(url); Rest.setUrl(url);
Rest.get() Rest.get()
@@ -760,7 +767,8 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
ok: event.ok, ok: event.ok,
changed: event.changed, changed: event.changed,
unreachable: event.dark, unreachable: event.dark,
failed: event.failures failed: event.failures,
status: (event.failed) ? 'failed' : 'successful'
}); });
}); });
$('#hosts-summary-table').mCustomScrollbar("update"); $('#hosts-summary-table').mCustomScrollbar("update");
@@ -790,7 +798,7 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
} }
scope.host_summary.unreachable = 0; scope.host_summary.unreachable = 0;
for (host in data.dark) { for (host in data.dark) {
scope.host_summary.dark += data.dark[host]; scope.host_summary.unreachable += data.dark[host];
} }
scope.host_summary.failed = 0; scope.host_summary.failed = 0;
for (host in data.failures) { for (host in data.failures) {

View File

@@ -19,7 +19,7 @@ angular.module('AdminListDefinition', [])
selectInstructions: '<p>Select existing users by clicking each user or checking the related checkbox. When finished, click the blue ' + selectInstructions: '<p>Select existing users by clicking each user or checking the related checkbox. When finished, click the blue ' +
'<em>Select</em> button, located bottom right.</p>', '<em>Select</em> button, located bottom right.</p>',
base: 'users', base: 'users',
index: true, index: false,
hover: true, hover: true,
fields: { fields: {

View File

@@ -18,7 +18,7 @@ angular.module('CloudCredentialsListDefinition', [])
editTitle: 'Cloud Credentials', editTitle: 'Cloud Credentials',
selectInstructions: '<p>Select existing credentials by clicking each credential or checking the related checkbox. When finished, click the blue ' + selectInstructions: '<p>Select existing credentials by clicking each credential or checking the related checkbox. When finished, click the blue ' +
'<em>Select</em> button, located bottom right.</p> <p>Create a brand new credential by clicking the green <em>Create New</em> button.</p>', '<em>Select</em> button, located bottom right.</p> <p>Create a brand new credential by clicking the green <em>Create New</em> button.</p>',
index: true, index: false,
hover: true, hover: true,
fields: { fields: {

View File

@@ -19,7 +19,7 @@ angular.module('CredentialsListDefinition', [])
selectInstructions: "<p>Select existing credentials by clicking each credential or checking the related checkbox. When " + selectInstructions: "<p>Select existing credentials by clicking each credential or checking the related checkbox. When " +
"finished, click the blue <em>Select</em> button, located bottom right.</p> <p>Create a brand new credential by clicking " + "finished, click the blue <em>Select</em> button, located bottom right.</p> <p>Create a brand new credential by clicking " +
"the green <em>Create New</em> button.</p>", "the green <em>Create New</em> button.</p>",
index: true, index: false,
hover: true, hover: true,
fields: { fields: {

View File

@@ -16,7 +16,7 @@ angular.module('GroupListDefinition', [])
iterator: 'copy_group', iterator: 'copy_group',
selectTitle: 'Copy Groups', selectTitle: 'Copy Groups',
editTitle: 'Groups', editTitle: 'Groups',
index: true, index: false,
well: false, well: false,
fields: { fields: {

View File

@@ -16,7 +16,7 @@ angular.module('HomeGroupListDefinition', [])
name: 'home_groups', name: 'home_groups',
iterator: 'group', iterator: 'group',
editTitle: 'Groups', editTitle: 'Groups',
index: true, index: false,
hover: true, hover: true,
well: true, well: true,

View File

@@ -7,7 +7,7 @@
* on the home tab. * on the home tab.
* *
*/ */
'use strict'; 'use strict';
angular.module('HomeHostListDefinition', []) angular.module('HomeHostListDefinition', [])
@@ -17,7 +17,7 @@ angular.module('HomeHostListDefinition', [])
iterator: 'host', iterator: 'host',
selectTitle: 'Add Existing Hosts', selectTitle: 'Add Existing Hosts',
editTitle: 'Hosts', editTitle: 'Hosts',
index: true, index: false,
hover: true, hover: true,
well: true, well: true,

View File

@@ -16,7 +16,7 @@ angular.module('HostListDefinition', [])
iterator: 'copy_host', iterator: 'copy_host',
selectTitle: 'Add Existing Hosts', selectTitle: 'Add Existing Hosts',
editTitle: 'Hosts', editTitle: 'Hosts',
index: true, index: false,
well: false, well: false,
fields: { fields: {

View File

@@ -17,7 +17,7 @@ angular.module('InventoriesListDefinition', [])
editTitle: 'Inventories', editTitle: 'Inventories',
selectInstructions: "Click on a row to select it, and click Finished when done. Use the green <i class=\"icon-plus\"></i> " + selectInstructions: "Click on a row to select it, and click Finished when done. Use the green <i class=\"icon-plus\"></i> " +
"button to create a new row.", "button to create a new row.",
index: true, index: false,
hover: true, hover: true,
fields: { fields: {

View File

@@ -16,7 +16,7 @@ angular.module('JobHostDefinition', [])
iterator: 'jobhost', iterator: 'jobhost',
editTitle: 'All summaries', editTitle: 'All summaries',
"class": "table-condensed", "class": "table-condensed",
index: true, index: false,
hover: true, hover: true,
navigationLinks: { navigationLinks: {

View File

@@ -18,7 +18,7 @@ angular.module('JobTemplatesListDefinition', [])
editTitle: 'Job Templates', editTitle: 'Job Templates',
selectInstructions: "Click on a row to select it, and click Finished when done. Use the green <i class=\"icon-plus\"></i> " + selectInstructions: "Click on a row to select it, and click Finished when done. Use the green <i class=\"icon-plus\"></i> " +
"button to create a new row.", "button to create a new row.",
index: true, index: false,
hover: true, hover: true,
fields: { fields: {

View File

@@ -17,13 +17,13 @@ angular.module('OrganizationListDefinition', [])
selectTitle: 'Add Organizations', selectTitle: 'Add Organizations',
editTitle: 'Organizations', editTitle: 'Organizations',
hover: true, hover: true,
index: true, index: false,
fields: { fields: {
name: { name: {
key: true, key: true,
label: 'Name', label: 'Name',
columnClass: 'col-sm-8 col-xs-8' columnClass: 'col-lg-4 col-md-6 col-sm-8 col-xs-8'
}, },
description: { description: {
label: 'Description', label: 'Description',

View File

@@ -18,7 +18,7 @@ angular.module('PermissionListDefinition', [])
selectInstructions: "Click on a row to select it, and click Finished when done. Use the green <i class=\"icon-plus\"></i> " + selectInstructions: "Click on a row to select it, and click Finished when done. Use the green <i class=\"icon-plus\"></i> " +
"button to create a new row.", "button to create a new row.",
editTitle: 'Permissions', editTitle: 'Permissions',
index: true, index: false,
well: true, well: true,
fields: { fields: {

View File

@@ -18,7 +18,7 @@ angular.module('ProjectsListDefinition', [])
editTitle: 'Projects', editTitle: 'Projects',
selectInstructions: '<p>Select existing projects by clicking each project or checking the related checkbox. When finished, click the blue ' + selectInstructions: '<p>Select existing projects by clicking each project or checking the related checkbox. When finished, click the blue ' +
'<em>Select</em> button, located bottom right.</p> <p>Create a brand new project by clicking the green <em>Create New</em> button.</p>', '<em>Select</em> button, located bottom right.</p> <p>Create a brand new project by clicking the green <em>Create New</em> button.</p>',
index: true, index: false,
hover: true, hover: true,
fields: { fields: {

View File

@@ -16,7 +16,7 @@ angular.module('SchedulesListDefinition', [])
selectTitle: '', selectTitle: '',
editTitle: 'Schedules', editTitle: 'Schedules',
well: false, well: false,
index: true, index: false,
hover: true, hover: true,
fields: { fields: {

View File

@@ -17,19 +17,19 @@ angular.module('TeamsListDefinition', [])
editTitle: 'Teams', editTitle: 'Teams',
selectInstructions: "Click on a row to select it, and click Finished when done. Use the green <i class=\"icon-plus\"></i> " + selectInstructions: "Click on a row to select it, and click Finished when done. Use the green <i class=\"icon-plus\"></i> " +
"button to create a new row.", "button to create a new row.",
index: true, index: false,
hover: true, hover: true,
fields: { fields: {
name: { name: {
key: true, key: true,
label: 'Name', label: 'Name',
columnClass: 'col-md-4 col-sm-9 col-xs-9', columnClass: 'col-lg-3 col-md-4 col-sm-9 col-xs-9',
modalColumnClass: 'col-md-8' modalColumnClass: 'col-md-8'
}, },
description: { description: {
label: 'Description', label: 'Description',
columnClass: 'col-md-3 hidden-sm hidden-xs', columnClass: 'col-lg-3 col-md-3 hidden-sm hidden-xs',
excludeModal: true excludeModal: true
}, },
organization: { organization: {

View File

@@ -18,7 +18,7 @@ angular.module('UserListDefinition', [])
selectInstructions: '<p>Select existing users by clicking each user or checking the related checkbox. When finished, click the blue ' + selectInstructions: '<p>Select existing users by clicking each user or checking the related checkbox. When finished, click the blue ' +
'<em>Select</em> button, located bottom right.</p> <p>When available, a brand new user can be created by clicking the green ' + '<em>Select</em> button, located bottom right.</p> <p>When available, a brand new user can be created by clicking the green ' +
'<em>Create New</em> button.</p>', '<em>Create New</em> button.</p>',
index: true, index: false,
hover: true, hover: true,
fields: { fields: {

View File

@@ -55,6 +55,7 @@
@import "inventory-edit.less"; @import "inventory-edit.less";
@import "breadcrumbs.less"; @import "breadcrumbs.less";
@import "stdout.less"; @import "stdout.less";
@import "lists.less";
/* Bootstrap fix that's causing a right margin to appear /* Bootstrap fix that's causing a right margin to appear

View File

@@ -16,15 +16,15 @@
.job_summary { .job_summary {
.table { .table {
margin-bottom: 0; margin-bottom: 0;
border: 1px solid @grey; border: 1px solid @well-border;
background-color: @white; background-color: @white;
} }
.table>tbody>tr>td { .table>tbody>tr>td {
border-top-color: @well; border-top-color: @well-border;
padding-bottom: 0; padding-bottom: 0;
} }
.table>thead>tr>th { .table>thead>tr>th {
border-bottom-color: @well; border-bottom-color: @well-border;
padding-bottom: 0; padding-bottom: 0;
height: 22px; height: 22px;
} }
@@ -185,12 +185,12 @@
.table-detail { .table-detail {
overflow-x: hidden; overflow-x: hidden;
overflow-y: auto; overflow-y: auto;
border: 1px solid @grey; border: 1px solid @well-border;
border-radius: 4px; border-radius: 4px;
background-color: @white; background-color: @white;
/*padding-left: 3px; */ /*padding-left: 3px; */
.row { .row {
border-top: 1px solid @grey; border-top: 1px solid @well-border;
} }
.row:first-child { .row:first-child {
border: none; border: none;
@@ -301,8 +301,8 @@ label.small-label {
left: 0; left: 0;
#hosts-table-detail { #hosts-table-detail {
padding: 3px 0 3px 5px; padding: 3px 0 3px 5px;
border: 1px solid @grey; border: 1px solid @well-border;
border-top: 2px solid #ddd; border-top: 2px solid @well-border;
height: 150px; height: 150px;
background-color: @white; background-color: @white;
.col-lg-1, .col-md-1, .col-sm-1, .col-xs-1 { .col-lg-1, .col-md-1, .col-sm-1, .col-xs-1 {

View File

@@ -0,0 +1,16 @@
/*********************************************
* Copyright (c) 2014 AnsibleWorks, Inc.
*
* lists.less
*
* custom styles for generated lists
*
*/
.list-well {
margin-top: 20px;
table >thead >tr >th {
font-weight: normal;
}
}

View File

@@ -729,7 +729,7 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Job
updateOnContentResize: true updateOnContentResize: true
}, },
scrollButtons: { scrollButtons: {
enable: true enable: false
}, },
theme: theme, theme: theme,
mouseWheel: true, mouseWheel: true,

View File

@@ -168,7 +168,7 @@ angular.module('ListGenerator', ['GeneratorHelpers'])
} }
if (options.mode !== 'lookup' && (list.well === undefined || list.well)) { if (options.mode !== 'lookup' && (list.well === undefined || list.well)) {
html += "<div class=\"well\">\n"; html += "<div class=\"list-well\">\n";
} }
if (options.activityStream) { if (options.activityStream) {

View File

@@ -77,8 +77,9 @@
<div class="row"> <div class="row">
<div class="col-lg-1 col-md-1 col-sm-2 hidden-xs">Started</div> <div class="col-lg-1 col-md-1 col-sm-2 hidden-xs">Started</div>
<div class="col-lg-1 col-md-1 hidden-sm hidden-xs">Elapsed</div> <div class="col-lg-1 col-md-1 hidden-sm hidden-xs">Elapsed</div>
<div class="col-lg-8 col-md-8 col-sm-10 col-xs-12">Name</div> <div class="col-lg-6 col-md-6 col-sm-10 col-xs-12">Name</div>
<div class="col-lg-2 col-md-2 hidden-sm hidden-xs text-right">Reporting Hosts</div> <div class="col-lg-2 col-md-2 hidden-sm hidden-xs text-right">Reporting Hosts</div>
<div class="col-lg-2 col-md-2 hidden-sm hidden-xs text-right">Unreachable Hosts</div>
</div> </div>
</div> </div>
<div id="plays-table-detail" aw-custom-scroll class="table-detail"> <div id="plays-table-detail" aw-custom-scroll class="table-detail">
@@ -88,11 +89,12 @@
<div class="col-lg-1 col-md-1 hidden-sm hidden-xs" aw-tool-tip="Completed at {{ play.finished | date:'HH:mm:ss' }}" <div class="col-lg-1 col-md-1 hidden-sm hidden-xs" aw-tool-tip="Completed at {{ play.finished | date:'HH:mm:ss' }}"
data-placement="top">{{ play.elapsed }} data-placement="top">{{ play.elapsed }}
</div> </div>
<div class="col-lg-8 col-md-8 col-sm-10 col-xs-12 status-column" <div class="col-lg-6 col-md-6 col-sm-10 col-xs-12 status-column"
aw-tool-tip="Event Id: {{ play.id }}<br />Status: {{ play.status }}" data-placement="top"> aw-tool-tip="Event Id: {{ play.id }}<br />Status: {{ play.status_text }}" data-placement="top">
<i class="fa icon-job-{{ play.status }}"></i> {{ play.name }}</span> <i class="fa icon-job-{{ play.status }}"></i> {{ play.name }}</span>
</div> </div>
<div class="col-lg-2 col-md-2 hidden-sm hidden-xs text-right">{{ play.hostCount }}</div> <div class="col-lg-2 col-md-2 hidden-sm hidden-xs text-right">{{ play.hostCount }}</div>
<div class="col-lg-2 col-md-2 hidden-sm hidden-xs text-right">{{ play.unreachableCount }}</div>
</div> </div>
<div class="row" ng-show="playList.length == 0"> <div class="row" ng-show="playList.length == 0">
<div class="col-lg-12"> <div class="col-lg-12">