Job detail page refactor

Added custom scrollbar to task list and made it do the endless scroll thing. Switched tasks and plays from objects back to arrays, in support of endless scroll.  Still need to apply scrollbar to play list and enable endless scroll. Modified calls to job_tasks endpoint to use the 'paginated' structure. Will need to do the same to plays. None of this is tested yet.
This commit is contained in:
Chris Houseknecht
2014-06-17 18:21:18 -04:00
committed by Luke Sneeringer
parent ea2bb5e201
commit 8c393c6efd
3 changed files with 384 additions and 230 deletions

View File

@@ -9,7 +9,7 @@
function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log, ClearScope, Breadcrumbs, LoadBreadCrumbs, GetBasePath, Wait, Rest, function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log, ClearScope, Breadcrumbs, LoadBreadCrumbs, GetBasePath, Wait, Rest,
ProcessErrors, ProcessEventQueue, SelectPlay, SelectTask, Socket, GetElapsed, SelectHost, FilterAllByHostName, DrawGraph, LoadHostSummary, ReloadHostSummaryList, ProcessErrors, ProcessEventQueue, SelectPlay, SelectTask, Socket, GetElapsed, SelectHost, FilterAllByHostName, DrawGraph, LoadHostSummary, ReloadHostSummaryList,
JobIsFinished) { JobIsFinished, SetTaskStyles) {
ClearScope(); ClearScope();
@@ -21,14 +21,21 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
lastEventId = 0, lastEventId = 0,
queue = []; queue = [];
scope.plays = {}; scope.plays = [];
scope.playsMap = {};
scope.hosts = []; scope.hosts = [];
scope.hostsMap = {}; scope.hostsMap = {};
scope.tasks = {}; scope.tasks = [];
scope.tasksMap = {};
scope.hostResults = []; scope.hostResults = [];
scope.hostResultsMap = {}; scope.hostResultsMap = {};
api_complete = false; api_complete = false;
scope.hostTableRows = 150;
scope.hostSummaryTableRows = 150;
scope.tasksMaxRows = 150;
scope.playsMaxRows = 150;
scope.search_all_tasks = []; scope.search_all_tasks = [];
scope.search_all_plays = []; scope.search_all_plays = [];
scope.job_status = {}; scope.job_status = {};
@@ -36,8 +43,6 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
scope.auto_scroll = false; scope.auto_scroll = false;
scope.searchTaskHostsEnabled = true; scope.searchTaskHostsEnabled = true;
scope.searchSummaryHostsEnabled = true; scope.searchSummaryHostsEnabled = true;
scope.hostTableRows = 150;
scope.hostSummaryTableRows = 150;
scope.searchAllHostsEnabled = true; scope.searchAllHostsEnabled = true;
scope.haltEventQueue = false; scope.haltEventQueue = false;
@@ -202,8 +207,8 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
data.forEach(function(event, idx) { data.forEach(function(event, idx) {
var status = (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful', var status = (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful',
start = event.started, start = event.started,
end, end, elapsed, play;
elapsed;
if (idx < data.length - 1) { if (idx < data.length - 1) {
// end date = starting date of the next event // end date = starting date of the next event
end = data[idx + 1].started; end = data[idx + 1].started;
@@ -221,15 +226,25 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
else { else {
elapsed = '00:00:00'; elapsed = '00:00:00';
} }
scope.plays[event.id] = { if (scope.playsMap[event.id]) {
id: event.id, play = scope.plays[scope.playsMapp[event.id]];
name: event.play, play.finished = end;
created: start, play.elapsed = elapsed;
finished: end, play.status = status;
status: status, play.playActiveClass = '';
elapsed: elapsed, }
playActiveClass: '' else {
}; scope.plays.push({
id: event.id,
name: event.play,
created: start,
finished: end,
status: status,
elapsed: elapsed,
playActiveClass: ''
});
scope.playsMap[event.id] = scope.plays.length - 1;
}
scope.host_summary.ok += (data.ok_count) ? data.ok_count : 0; scope.host_summary.ok += (data.ok_count) ? data.ok_count : 0;
scope.host_summary.changed += (data.changed_count) ? data.changed_count : 0; scope.host_summary.changed += (data.changed_count) ? data.changed_count : 0;
scope.host_summary.unreachable += (data.unreachable_count) ? data.unreachable_count : 0; scope.host_summary.unreachable += (data.unreachable_count) ? data.unreachable_count : 0;
@@ -487,9 +502,23 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
return true; return true;
}; };
/*
function rebuildHostResultsMap() {
scope.hostResultsMap = {};
scope.hostResults.forEach(function(result, idx) {
scope.hostResultsMap[result.id] = idx;
});
}
function rebuildTasksMap() {
scope.tasksMap = {};
scope.tasks.forEach(function(task, idx) {
scope.tasksMap[task.id] = idx;
});
}
scope.HostDetailOnTotalScroll = _.debounce(function() { scope.HostDetailOnTotalScroll = _.debounce(function() {
// Called when user scrolls down (or forward in time). Using _.debounce // Called when user scrolls down (or forward in time)
var url, mcs = arguments[0]; var url, mcs = arguments[0];
scope.$apply(function() { scope.$apply(function() {
if (!scope.auto_scroll && scope.activeTask && scope.hostResults.length) { if (!scope.auto_scroll && scope.activeTask && scope.hostResults.length) {
@@ -513,7 +542,7 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
msg: ( (row.event_data && row.event_data.res) ? row.event_data.res.msg : '' ) msg: ( (row.event_data && row.event_data.res) ? row.event_data.res.msg : '' )
}); });
if (scope.hostResults.length > scope.hostTableRows) { if (scope.hostResults.length > scope.hostTableRows) {
scope.hostResults.splice(0,1); scope.hostResults.shift();
} }
}); });
if (data.next) { if (data.next) {
@@ -521,6 +550,7 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
setTimeout(function() { $('#hosts-table-detail .mCSB_dragger').css({ top: (mcs.draggerTop - 15) + 'px'}); }, 700); setTimeout(function() { $('#hosts-table-detail .mCSB_dragger').css({ top: (mcs.draggerTop - 15) + 'px'}); }, 700);
} }
scope.auto_scroll = false; scope.auto_scroll = false;
rebuildHostResultsMap();
Wait('stop'); Wait('stop');
}) })
.error(function(data, status) { .error(function(data, status) {
@@ -566,6 +596,7 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
// there are more rows. move dragger down, letting user know. // there are more rows. move dragger down, letting user know.
setTimeout(function() { $('#hosts-table-detail .mCSB_dragger').css({ top: (mcs.draggerTop + 15) + 'px' }); }, 700); setTimeout(function() { $('#hosts-table-detail .mCSB_dragger').css({ top: (mcs.draggerTop + 15) + 'px' }); }, 700);
} }
rebuildHostResultsMap();
Wait('stop'); Wait('stop');
scope.auto_scroll = false; scope.auto_scroll = false;
}) })
@@ -580,6 +611,162 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
}); });
}, 300); }, 300);
scope.TasksOnTotalScroll = _.debounce(function() {
// Called when user scrolls down (or forward in time)
var url, mcs = arguments[0];
scope.$apply(function() {
if (!scope.auto_scroll && scope.activePlay && scope.tasks.length) {
scope.auto_scroll = true;
url = scope.job.url + 'job_tasks/?event_id=' + scope.activePlay;
url += (scope.search_all_tasks.length > 0) ? '&id__in=' + scope.search_all_tasks.join() : '';
url += (scope.searchAllStatus === 'failed') ? '&failed=true' : '';
url += 'id__gt=' + scope.tasks[scope.tasks.length - 1].id + '&page_size=' + (scope.tasksMaxRows / 3) + '&order_by=id';
Wait('start');
Rest.setUrl(url);
Rest.get()
.success(function(data) {
data.results.forEach(function(event, idx) {
var end, elapsed;
if (idx < data.length - 1) {
// end date = starting date of the next event
end = data[idx + 1].created;
}
else {
// no next event (task), get the end time of the play
end = scope.plays[scope.activePlay].finished;
}
if (end) {
elapsed = GetElapsed({
start: event.created,
end: end
});
}
else {
elapsed = '00:00:00';
}
scope.tasks.push({
id: event.id,
play_id: scope.activePlay,
name: event.name,
status: ( (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful' ),
created: event.created,
modified: event.modified,
finished: end,
elapsed: elapsed,
hostCount: event.host_count, // hostCount,
reportedHosts: event.reported_hosts,
successfulCount: event.successful_count,
failedCount: event.failed_count,
changedCount: event.changed_count,
skippedCount: event.skipped_count,
taskActiveClass: ''
});
scope.tasksMap[event.id] = scope.tasks.length - 1;
SetTaskStyles({
scope: scope,
task_id: event.id
});
if (scope.tasks.length > scope.tasksMaxRows) {
scope.tasks.shift();
}
});
if (data.next) {
// there are more rows. move dragger up, letting user know.
setTimeout(function() { $('#tasks-table-detail .mCSB_dragger').css({ top: (mcs.draggerTop - 15) + 'px'}); }, 700);
}
scope.auto_scroll = false;
rebuildTasksMap();
Wait('stop');
})
.error(function(data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + '. GET returned: ' + status });
});
}
else {
scope.auto_scroll = false;
}
});
}, 300);
scope.TasksOnTotalScrollBack = _.debounce(function() {
// Called when user scrolls up (or back in time)
var url, mcs = arguments[0];
scope.$apply(function() {
if (!scope.auto_scroll && scope.activePlay && scope.tasks.length) {
scope.auto_scroll = true;
url = scope.job.url + 'job_tasks/?event_id=' + scope.activePlay;
url += (scope.search_all_tasks.length > 0) ? '&id__in=' + scope.search_all_tasks.join() : '';
url += (scope.searchAllStatus === 'failed') ? '&failed=true' : '';
url += 'id__lt=' + scope.tasks[scope.tasks[0]].name + '&page_size=' + (scope.tasksMaxRows / 3) + '&order_by=id';
Wait('start');
Rest.setUrl(url);
Rest.get()
.success(function(data) {
data.results.forEach(function(event, idx) {
var end, elapsed;
if (idx < data.length - 1) {
// end date = starting date of the next event
end = data[idx + 1].created;
}
else {
// no next event (task), get the end time of the play
end = scope.plays[scope.activePlay].finished;
}
if (end) {
elapsed = GetElapsed({
start: event.created,
end: end
});
}
else {
elapsed = '00:00:00';
}
scope.tasks.unshift({
id: event.id,
play_id: scope.activePlay,
name: event.name,
status: ( (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful' ),
created: event.created,
modified: event.modified,
finished: end,
elapsed: elapsed,
hostCount: event.host_count, // hostCount,
reportedHosts: event.reported_hosts,
successfulCount: event.successful_count,
failedCount: event.failed_count,
changedCount: event.changed_count,
skippedCount: event.skipped_count,
taskActiveClass: ''
});
scope.tasksMap[event.id] = scope.tasks.length - 1;
SetTaskStyles({
scope: scope,
task_id: event.id
});
if (scope.tasks.length > scope.tasksMaxRows) {
scope.tasks.pop();
}
});
if (data.next) {
// there are more rows. move dragger up, letting user know.
setTimeout(function() { $('#tasks-table-detail .mCSB_dragger').css({ top: (mcs.draggerTop + 15) + 'px'}); }, 700);
}
scope.auto_scroll = false;
rebuildTasksMap();
Wait('stop');
})
.error(function(data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + '. GET returned: ' + status });
});
}
else {
scope.auto_scroll = false;
}
});
}, 300);
scope.HostSummaryOnTotalScroll = function(mcs) { scope.HostSummaryOnTotalScroll = function(mcs) {
var url; var url;
if (!scope.auto_scroll && scope.hosts) { if (!scope.auto_scroll && scope.hosts) {
@@ -603,7 +790,7 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
failed: row.failures failed: row.failures
}); });
if (scope.hosts.length > scope.hostSummaryTableRows) { if (scope.hosts.length > scope.hostSummaryTableRows) {
scope.hosts.splice(0,1); scope.hosts.shift();
} }
}); });
if (data.next) { if (data.next) {
@@ -667,7 +854,6 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
scope.auto_scroll = false; scope.auto_scroll = false;
} }
}; };
*/
scope.searchAllByHost = function() { scope.searchAllByHost = function() {
var keys, nxtPlay; var keys, nxtPlay;
@@ -723,9 +909,6 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
ReloadHostSummaryList({ ReloadHostSummaryList({
scope: scope scope: scope
}); });
//setTimeout(function() {
// SelectPlay({ scope: scope, id: scope.activePlay });
//}, 2000);
}; };
scope.viewEvent = function(event_id) { scope.viewEvent = function(event_id) {
@@ -736,5 +919,5 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
JobDetailController.$inject = [ '$rootScope', '$scope', '$compile', '$routeParams', '$log', 'ClearScope', 'Breadcrumbs', 'LoadBreadCrumbs', 'GetBasePath', JobDetailController.$inject = [ '$rootScope', '$scope', '$compile', '$routeParams', '$log', 'ClearScope', 'Breadcrumbs', 'LoadBreadCrumbs', 'GetBasePath',
'Wait', 'Rest', 'ProcessErrors', 'ProcessEventQueue', 'SelectPlay', 'SelectTask', 'Socket', 'GetElapsed', 'SelectHost', 'FilterAllByHostName', 'DrawGraph', 'Wait', 'Rest', 'ProcessErrors', 'ProcessEventQueue', 'SelectPlay', 'SelectTask', 'Socket', 'GetElapsed', 'SelectHost', 'FilterAllByHostName', 'DrawGraph',
'LoadHostSummary', 'ReloadHostSummaryList', 'JobIsFinished' 'LoadHostSummary', 'ReloadHostSummaryList', 'JobIsFinished', 'SetTaskStyles'
]; ];

View File

@@ -61,14 +61,13 @@ angular.module('JobDetailHelper', ['Utilities', 'RestServices'])
}]) }])
.factory('DigestEvent', ['$rootScope', '$log', 'UpdatePlayStatus', 'UpdateHostStatus', 'AddHostResult', 'SelectPlay', 'SelectTask', .factory('DigestEvent', ['$rootScope', '$log', 'UpdatePlayStatus', 'UpdateHostStatus', 'AddHostResult', 'SelectPlay', 'SelectTask',
'GetHostCount', 'GetElapsed', 'UpdateTaskStatus', 'DrawGraph', 'LoadHostSummary', 'JobIsFinished', 'GetHostCount', 'GetElapsed', 'UpdateTaskStatus', 'DrawGraph', 'LoadHostSummary', 'JobIsFinished', 'AddNewTask',
function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, SelectPlay, SelectTask, GetHostCount, GetElapsed, function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, SelectPlay, SelectTask, GetHostCount, GetElapsed,
UpdateTaskStatus, DrawGraph, LoadHostSummary, JobIsFinished) { UpdateTaskStatus, DrawGraph, LoadHostSummary, JobIsFinished, AddNewTask) {
return function(params) { return function(params) {
var scope = params.scope, var scope = params.scope,
event = params.event, event = params.event;
hostCount;
switch (event.event) { switch (event.event) {
case 'playbook_on_start': case 'playbook_on_start':
@@ -79,94 +78,29 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Se
break; break;
case 'playbook_on_play_start': case 'playbook_on_play_start':
scope.plays[event.id] = { scope.plays.push({
id: event.id, id: event.id,
name: event.play, name: event.play,
created: event.created, created: event.created,
status: (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful', status: (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful',
elapsed: '00:00:00' elapsed: '00:00:00',
}; hostCount: 0,
scope.tasks = {}; fistTask: null
});
scope.playsMap[event.id] = scope.plays.length -1;
scope.tasks = [];
scope.tasksMap = {};
scope.hostResults = []; scope.hostResults = [];
scope.hostResultsMap = {}; scope.hostResultsMap = {};
scope.activePlay = event.id; scope.activePlay = event.id;
break; break;
case 'playbook_on_setup': case 'playbook_on_setup':
if (scope.activePlay === event.parent) { AddNewTask({ scope: scope, event: event });
scope.tasks[event.id] = {
id: event.id,
play_id: event.parent,
name: event.event_display,
status: ( (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful' ),
created: event.created,
modified: event.modified,
hostCount: 0,
reportedHosts: 0,
successfulCount: 0,
failedCount: 0,
changedCount: 0,
skippedCount: 0,
successfulStyle: { display: 'none'},
failedStyle: { display: 'none' },
changedStyle: { display: 'none' },
skippedStyle: { display: 'none' }
};
scope.hostResults = [];
scope.hostResultsMap = {};
scope.activeTask = event.id;
}
UpdatePlayStatus({
scope: scope,
play_id: event.parent,
failed: event.failed,
changed: event.changed,
modified: event.modified
});
if (scope.host_summary.total > 0) {
DrawGraph({ scope: scope, resize: true });
}
break; break;
case 'playbook_on_task_start': case 'playbook_on_task_start':
if (scope.activePlay === event.parent) { AddNewTask({ scope: scope, event: event });
hostCount = GetHostCount({ scope: scope });
scope.tasks[event.id] = {
id: event.id,
name: event.task,
play_id: event.parent,
status: ( (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful' ),
role: event.role,
created: event.created,
modified: event.modified,
hostCount: hostCount,
reportedHosts: 0,
successfulCount: 0,
failedCount: 0,
changedCount: 0,
skippedCount: 0,
successfulStyle: { display: 'none'},
failedStyle: { display: 'none' },
changedStyle: { display: 'none' },
skippedStyle: { display: 'none' }
};
scope.hostResults = [];
scope.hostResultsMap = {};
scope.activeTask = event.id;
}
if (event.role) {
scope.hasRoles = true;
}
UpdatePlayStatus({
scope: scope,
play_id: event.parent,
failed: event.failed,
changed: event.changed,
modified: event.modified
});
if (scope.host_summary.total > 0) {
DrawGraph({ scope: scope, resize: true });
}
break; break;
case 'runner_on_ok': case 'runner_on_ok':
@@ -271,28 +205,6 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Se
}; };
}]) }])
//Get the # of expected hosts for a task by looking at the number
//on the very first task for a play
.factory('GetHostCount', [ 'FindFirstTaskofPlay', function(FindFirstTaskofPlay) {
return function(params) {
var scope = params.scope,
task_id = FindFirstTaskofPlay({ scope: scope });
if (task_id) {
return scope.tasks[task_id].hostCount;
}
return 0;
};
}])
.factory('FindFirstTaskofPlay', function() {
return function(params) {
var scope = params.scope,
taskIds;
taskIds = Object.keys(scope.tasks);
return (taskIds.length > 0) ? scope.tasks[taskIds[0]].id : null;
};
})
.factory('GetElapsed', [ function() { .factory('GetElapsed', [ function() {
return function(params) { return function(params) {
var start = params.start, var start = params.start,
@@ -319,6 +231,60 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Se
}; };
}]) }])
.factory('AddNewTask', ['DrawGraph', 'UpdatePlayStatus', function(DrawGraph, UpdatePlayStatus) {
return function(params) {
var scope = params.scope,
event = params.event;
scope.tasks.push({
id: event.id,
play_id: event.parent,
name: event.event_display,
status: ( (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful' ),
created: event.created,
modified: event.modified,
hostCount: scope.plays[scope.playsMap[scope.activePlay]].hostCount,
reportedHosts: 0,
successfulCount: 0,
failedCount: 0,
changedCount: 0,
skippedCount: 0,
successfulStyle: { display: 'none'},
failedStyle: { display: 'none' },
changedStyle: { display: 'none' },
skippedStyle: { display: 'none' }
});
if (scope.tasks.length > scope.tasksMaxRows) {
scope.tasks.shift();
}
if (!scope.playsMap[scope.activePlay].firstTask) {
scope.playsMap[scope.activePlay].firstTask = event.id;
}
scope.hostResults = [];
scope.hostResultsMap = {};
scope.activeTask = event.id;
// Not sure if this still works
scope.hasRoles = (event.role) ? true : false;
// Record the first task id
UpdatePlayStatus({
scope: scope,
play_id: event.parent,
failed: event.failed,
changed: event.changed,
modified: event.modified
});
if (scope.host_summary.total > 0) {
DrawGraph({ scope: scope, resize: true });
}
};
}])
.factory('UpdateJobStatus', ['GetElapsed', 'Empty', function(GetElapsed, Empty) { .factory('UpdateJobStatus', ['GetElapsed', 'Empty', function(GetElapsed, Empty) {
return function(params) { return function(params) {
var scope = params.scope, var scope = params.scope,
@@ -355,27 +321,28 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Se
modified = params.modified, modified = params.modified,
no_hosts = params.no_hosts, no_hosts = params.no_hosts,
status_text = params.status_text, status_text = params.status_text,
play = scope.plays[id]; play;
if (scope.plays[id]) { if (scope.playsMap[id]) {
play = scope.plays[scope.playsMap[id]];
if (failed) { if (failed) {
scope.plays[id].status = 'failed'; play.status = 'failed';
} }
else if (play.status !== 'changed' && play.status !== 'failed') { else if (play.status !== 'changed' && play.status !== 'failed') {
// once the status becomes 'changed' or 'failed' don't modify it // once the status becomes 'changed' or 'failed' don't modify it
if (no_hosts) { if (no_hosts) {
scope.plays[id].status = 'no-matching-hosts'; play.status = 'no-matching-hosts';
} }
else { else {
scope.plays[id].status = (changed) ? 'changed' : (failed) ? 'failed' : 'successful'; play.status = (changed) ? 'changed' : (failed) ? 'failed' : 'successful';
} }
} }
scope.plays[id].finished = modified; play.finished = modified;
scope.plays[id].elapsed = GetElapsed({ play.elapsed = GetElapsed({
start: play.created, start: play.created,
end: modified end: modified
}); });
scope.plays[id].status_text = (status_text) ? status_text : scope.plays[id].status; play.status_text = (status_text) ? status_text : play.status;
} }
UpdateJobStatus({ UpdateJobStatus({
@@ -394,9 +361,10 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Se
id = params.task_id, id = params.task_id,
modified = params.modified, modified = params.modified,
no_hosts = params.no_hosts, no_hosts = params.no_hosts,
task = scope.tasks[id]; task;
if (scope.tasks[id]) { if (scope.tasksMap[id]) {
task = scope.tasks[scope.tasksMap[id]];
if (no_hosts){ if (no_hosts){
task.status = 'no-matching-hosts'; task.status = 'no-matching-hosts';
} }
@@ -509,7 +477,7 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Se
created = params.created, created = params.created,
name = params.name, name = params.name,
msg = params.message, msg = params.message,
play_id, first; task;
if (!scope.hostResultsMap[host_id] && scope.hostResults.length < scope.hostTableRows) { if (!scope.hostResultsMap[host_id] && scope.hostResults.length < scope.hostTableRows) {
scope.hostResults.push({ scope.hostResults.push({
@@ -538,20 +506,17 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Se
} }
// update the task status bar // update the task status bar
if (scope.tasks[task_id]) { if (scope.tasksMap[task_id]) {
play_id = scope.tasks[task_id].play_id; task = scope.tasks[scope.tasksMap[task_id]];
first = FindFirstTaskofPlay({ if (task_id === scope.plays[scope.playsMap[scope.activePlays]].firstPlay) {
scope: scope, scope.plays[scope.playsMap[scope.activePlay]].hostCount++;
play_id: play_id task.hostCount++;
});
if (task_id === first) {
scope.tasks[task_id].hostCount += 1;
} }
scope.tasks[task_id].reportedHosts += 1; task.reportedHosts += 1;
scope.tasks[task_id].failedCount += (status === 'failed' || status === 'unreachable') ? 1 : 0; task.failedCount += (status === 'failed' || status === 'unreachable') ? 1 : 0;
scope.tasks[task_id].changedCount += (status === 'changed') ? 1 : 0; task.changedCount += (status === 'changed') ? 1 : 0;
scope.tasks[task_id].successfulCount += (status === 'successful') ? 1 : 0; task.successfulCount += (status === 'successful') ? 1 : 0;
scope.tasks[task_id].skippedCount += (status === 'skipped') ? 1 : 0; task.skippedCount += (status === 'skipped') ? 1 : 0;
SetTaskStyles({ SetTaskStyles({
scope: scope, scope: scope,
task_id: task_id task_id: task_id
@@ -564,31 +529,33 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Se
return function(params) { return function(params) {
var task_id = params.task_id, var task_id = params.task_id,
scope = params.scope, scope = params.scope,
diff; diff, task;
scope.tasks[task_id].failedPct = (scope.tasks[task_id].hostCount > 0) ? Math.ceil((100 * (scope.tasks[task_id].failedCount / scope.tasks[task_id].hostCount))) : 0;
scope.tasks[task_id].changedPct = (scope.tasks[task_id].hostCount > 0) ? Math.ceil((100 * (scope.tasks[task_id].changedCount / scope.tasks[task_id].hostCount))) : 0;
scope.tasks[task_id].skippedPct = (scope.tasks[task_id].hostCount > 0) ? Math.ceil((100 * (scope.tasks[task_id].skippedCount / scope.tasks[task_id].hostCount))) : 0;
scope.tasks[task_id].successfulPct = (scope.tasks[task_id].hostCount > 0) ? Math.ceil((100 * (scope.tasks[task_id].successfulCount / scope.tasks[task_id].hostCount))) : 0;
diff = (scope.tasks[task_id].failedPct + scope.tasks[task_id].changedPct + scope.tasks[task_id].skippedPct + scope.tasks[task_id].successfulPct) - 100; task = scope.tasks[scope.tasksMap[task_id]];
task.failedPct = (task.hostCount > 0) ? Math.ceil((100 * (task.failedCount / task.hostCount))) : 0;
task.changedPct = (task.hostCount > 0) ? Math.ceil((100 * (task.changedCount / task.hostCount))) : 0;
task.skippedPct = (task.hostCount > 0) ? Math.ceil((100 * (task.skippedCount / task.hostCount))) : 0;
task.successfulPct = (task.hostCount > 0) ? Math.ceil((100 * (task.successfulCount / task.hostCount))) : 0;
diff = (task.failedPct + task.changedPct + task.skippedPct + task.successfulPct) - 100;
if (diff > 0) { if (diff > 0) {
if (scope.tasks[task_id].failedPct > diff) { if (task.failedPct > diff) {
scope.tasks[task_id].failedPct = scope.tasks[task_id].failedPct - diff; task.failedPct = task.failedPct - diff;
} }
else if (scope.tasks[task_id].changedPct > diff) { else if (task.changedPct > diff) {
scope.tasks[task_id].changedPct = scope.tasks[task_id].changedPct - diff; task.changedPct = task.changedPct - diff;
} }
else if (scope.tasks[task_id].skippedPct > diff) { else if (task.skippedPct > diff) {
scope.tasks[task_id].skippedPct = scope.tasks[task_id].skippedPct - diff; task.skippedPct = task.skippedPct - diff;
} }
else if (scope.tasks[task_id].successfulPct > diff) { else if (task.successfulPct > diff) {
scope.tasks[task_id].successfulPct = scope.tasks[task_id].successfulPct - diff; task.successfulPct = task.successfulPct - diff;
} }
} }
scope.tasks[task_id].successfulStyle = (scope.tasks[task_id].successfulPct > 0) ? { 'display': 'inline-block', 'width': scope.tasks[task_id].successfulPct + "%" } : { 'display': 'none' }; task.successfulStyle = (task.successfulPct > 0) ? { 'display': 'inline-block', 'width': task.successfulPct + "%" } : { 'display': 'none' };
scope.tasks[task_id].changedStyle = (scope.tasks[task_id].changedPct > 0) ? { 'display': 'inline-block', 'width': scope.tasks[task_id].changedPct + "%" } : { 'display': 'none' }; task.changedStyle = (task.changedPct > 0) ? { 'display': 'inline-block', 'width': task.changedPct + "%" } : { 'display': 'none' };
scope.tasks[task_id].skippedStyle = (scope.tasks[task_id].skippedPct > 0) ? { 'display': 'inline-block', 'width': scope.tasks[task_id].skippedPct + "%" } : { 'display': 'none' }; task.skippedStyle = (task.skippedPct > 0) ? { 'display': 'inline-block', 'width': task.skippedPct + "%" } : { 'display': 'none' };
scope.tasks[task_id].failedStyle = (scope.tasks[task_id].failedPct > 0) ? { 'display': 'inline-block', 'width': scope.tasks[task_id].failedPct + "%" } : { 'display': 'none' }; task.failedStyle = (task.failedPct > 0) ? { 'display': 'inline-block', 'width': task.failedPct + "%" } : { 'display': 'none' };
}; };
}]) }])
@@ -608,11 +575,11 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Se
clear = (scope.activePlay === id) ? false : true; //are we moving to a new play? clear = (scope.activePlay === id) ? false : true; //are we moving to a new play?
} }
if (scope.plays[scope.activePlay]) { if (scope.playsMap[scope.activePlay]) {
scope.plays[scope.activePlay].playActiveClass = ''; scope.plays[scope.playsMap[scope.activePlay]].playActiveClass = '';
} }
if (id) { if (id) {
scope.plays[id].playActiveClass = 'active'; scope.plays[scope.playsMap[id]].playActiveClass = 'active';
} }
scope.activePlay = id; scope.activePlay = id;
@@ -634,48 +601,59 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Se
var scope = params.scope, var scope = params.scope,
callback = params.callback, callback = params.callback,
clear = params.clear, clear = params.clear,
url, tIds, lastId; url;
if (clear) { if (clear) {
scope.tasks = {}; scope.tasks = [];
scope.tasksMap = {};
} }
if (scope.activePlay) { if (scope.activePlay) {
url = scope.job.url + 'job_tasks/?event_id=' + scope.activePlay; url = scope.job.url + 'job_tasks/?event_id=' + scope.activePlay;
// job_tasks seems to ignore all query predicates other than event_id url += (scope.search_all_tasks.length > 0) ? '&id__in=' + scope.search_all_tasks.join() : '';
//+ '&'; url += (scope.searchAllStatus === 'failed') ? '&failed=true' : '';
//url += (scope.search_all_plays.length > 0) ? 'event_id__in=' + scope.search_all_plays.join() + '&' : ''; url += '&page_size=' + scope.tasksMaxRows;
//url += (scope.searchAllStatus === 'failed') ? 'failed=true&' : '';
//url += 'order_by=id';
Rest.setUrl(url); Rest.setUrl(url);
Rest.get() Rest.get()
.success(function(data) { .success(function(data) {
data.forEach(function(event, idx) { data.results.forEach(function(event, idx) {
var end, elapsed; var end, elapsed, task;
if ((!scope.searchAllStatus) || (scope.searchAllStatus === 'failed' && event.failed) &&
((!scope.search_all_hosts_name) || (scope.search_all_hosts_name && scope.search_all_tasks.indexOf(event.id)))) {
if (idx < data.length - 1) { if (idx < data.length - 1) {
// end date = starting date of the next event // end date = starting date of the next event
end = data[idx + 1].created; end = data[idx + 1].created;
} }
else { else {
// no next event (task), get the end time of the play // no next event (task), get the end time of the play
end = scope.plays[scope.activePlay].finished; end = scope.plays[scope.activePlay].finished;
} }
if (end) { if (end) {
elapsed = GetElapsed({ elapsed = GetElapsed({
start: event.created, start: event.created,
end: end end: end
}); });
} }
else { else {
elapsed = '00:00:00'; elapsed = '00:00:00';
} }
scope.tasks[event.id] = { if (scope.tasksMap[event.id]) {
task = scope.tasks[scope.tasksMap[event.id]];
task.status = (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful';
task.finished = end;
task.elapsed = elapsed;
task.hostCount = (event.host_count) ? event.host_count : 0;
task.reportedHosts = (event.reported_hosts) ? event.reported_hosts : 0;
task.successfulCount = (event.successful_count) ? event.successful_count : 0;
task.failedCount = (event.failed_count) ? event.failed_count : 0;
task.changedCount = (event.changed_count) ? event.changed_count : 0;
task.skippedCount = (event.skipped_count) ? event.skipped_count : 0;
task.taskActiveClass = '';
}
else {
scope.tasks.push({
id: event.id, id: event.id,
play_id: scope.activePlay, play_id: scope.activePlay,
name: event.name, name: event.name,
@@ -684,28 +662,26 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Se
modified: event.modified, modified: event.modified,
finished: end, finished: end,
elapsed: elapsed, elapsed: elapsed,
hostCount: event.host_count, // hostCount, hostCount: (event.host_count) ? event.host_count : 0,
reportedHosts: event.reported_hosts, reportedHosts: (event.reported_hosts) ? event.reported_hosts : 0,
successfulCount: event.successful_count, successfulCount: (event.successful_count) ? event.successful_count : 0,
failedCount: event.failed_count, failedCount: (event.failed_count) ? event.failed_count : 0,
changedCount: event.changed_count, changedCount: (event.changed_count) ? event.changed_count : 0,
skippedCount: event.skipped_count, skippedCount: (event.skipped_count) ? event.skipped_count : 0,
taskActiveClass: '' taskActiveClass: ''
};
SetTaskStyles({
scope: scope,
task_id: event.id
}); });
scope.tasksMap[event.id] = scope.tasks.length - 1;
} }
SetTaskStyles({
scope: scope,
task_id: event.id
});
}); });
// set the active task // set the active task
tIds = Object.keys(scope.tasks);
lastId = (tIds.length > 0) ? tIds[tIds.length - 1] : null;
SelectTask({ SelectTask({
scope: scope, scope: scope,
id: lastId, id: (scope.tasks.length > 0) ? scope.tasks[scope.tasks.length - 1].id : null,
callback: callback callback: callback
}); });
}) })
@@ -715,13 +691,8 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Se
}); });
} }
else { else {
// set the active task scope.tasks = [];
//tIds = Object.keys(scope.tasks); scope.tasksMap = {};
//lastId = (tIds.length > 0) ? tIds[tIds.length - 1] : null;
//console.log('selecting task: ' + lastId);
//console.log('tasks: ');
//console.log(scope.tasks);
scope.tasks = {};
SelectTask({ SelectTask({
scope: scope, scope: scope,
id: null, id: null,
@@ -746,12 +717,11 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Se
clear = (scope.activeTask === id) ? false : true; clear = (scope.activeTask === id) ? false : true;
} }
if (scope.activeTask && scope.tasks[scope.activeTask]) { if (scope.activeTask && scope.tasksMap[scope.activeTask]) {
scope.tasks[scope.activeTask].taskActiveClass = ''; scope.tasks[scope.tasksMap[scope.activeTask]].taskActiveClass = '';
} }
if (id) { if (id) {
scope.tasks[id].taskActiveClass = 'active'; scope.tasks[scope.tasksMap[id]].taskActiveClass = 'active';
scope.activeTaskName = scope.tasks[id].name;
} }
scope.activeTask = id; scope.activeTask = id;

View File

@@ -67,7 +67,7 @@
</div> </div>
<div class="row" ng-show="objectIsEmpty(playList)"> <div class="row" ng-show="objectIsEmpty(playList)">
<div class="col-lg-12"> <div class="col-lg-12">
<div class="loading-info">No plays matched</div> <div class="loading-info">No matching plays</div>
</div> </div>
</div> </div>
</div> </div>
@@ -83,7 +83,8 @@
<div class="col-lg-5 col-md-5 hidden-xs hidden-sm">Host Status</div> <div class="col-lg-5 col-md-5 hidden-xs hidden-sm">Host Status</div>
</div> </div>
</div> </div>
<div id="tasks-table-detail" aw-custom-scroll class="table-detail"> <div id="tasks-table-detail" class="table-detail" aw-custom-scroll data-on-total-scroll="TasksOnTotalScroll"
data-on-total-scroll-back="TasksOnTotalScrollBack">
<div class="row cursor-pointer" <div class="row cursor-pointer"
ng-repeat="(task_id, task) in tasks track by task_id" ng-repeat="(task_id, task) in tasks track by task_id"
ng-class="task.taskActiveClass" ng-click="selectTask(task.id)"> ng-class="task.taskActiveClass" ng-click="selectTask(task.id)">
@@ -102,7 +103,7 @@
</div> </div>
<div class="row" ng-show="objectIsEmpty(tasks)"> <div class="row" ng-show="objectIsEmpty(tasks)">
<div class="col-lg-12"> <div class="col-lg-12">
<div class="loading-info">No tasks matched</div> <div class="loading-info">No matching tasks</div>
</div> </div>
</div> </div>
</div> </div>
@@ -131,7 +132,7 @@
</div> </div>
<div class="row" ng-show="hostResults.length == 0"> <div class="row" ng-show="hostResults.length == 0">
<div class="col-lg-12"> <div class="col-lg-12">
<div class="loading-info">No hosts matched</div> <div class="loading-info">No matching hosts</div>
</div> </div>
</div> </div>
</div> </div>
@@ -205,7 +206,7 @@
</div> </div>
<div class="row" ng-show="hosts.length === 0"> <div class="row" ng-show="hosts.length === 0">
<div class="col-lg-12"> <div class="col-lg-12">
<div class="loading-info">No hosts matched</div> <div class="loading-info">No matching hosts</div>
</div> </div>
</div> </div>
</div> </div>