mirror of
https://github.com/ansible/awx.git
synced 2026-03-06 19:21:06 -03:30
Job details -play button
Pause live events by clicking on a task or play. Restart live events by clicking the play button. Fixed issues with event viewer and host viewer dialogs.
This commit is contained in:
@@ -31,8 +31,8 @@ function JobDetailController ($location, $rootScope, $scope, $compile, $routePar
|
||||
scope.tasksMaxRows = 200;
|
||||
scope.playsMaxRows = 200;
|
||||
|
||||
scope.liveEventProcessing = true; // control play/pause state of event processing
|
||||
scope.pauseLiveEvents = false;
|
||||
scope.liveEventProcessing = true; // true while job is active and live events are arriving
|
||||
scope.pauseLiveEvents = false; // control play/pause state of event processing
|
||||
|
||||
scope.job_status = {};
|
||||
scope.job_id = job_id;
|
||||
@@ -105,7 +105,9 @@ function JobDetailController ($location, $rootScope, $scope, $compile, $routePar
|
||||
if ($rootScope.jobDetailInterval) {
|
||||
window.clearInterval($rootScope.jobDetailInterval);
|
||||
}
|
||||
$scope.$emit('LoadJob'); //this is what is used for the refresh
|
||||
if (!scope.pauseLiveEvents) {
|
||||
$scope.$emit('LoadJob'); //this is what is used for the refresh
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -118,8 +120,8 @@ function JobDetailController ($location, $rootScope, $scope, $compile, $routePar
|
||||
var url;
|
||||
Wait('stop');
|
||||
if (JobIsFinished(scope)) {
|
||||
$scope.liveEventProcessing = false; // signal that event processing is over and endless scroll
|
||||
// should be enabled
|
||||
scope.liveEventProcessing = false; // signal that event processing is over and endless scroll
|
||||
scope.pauseLiveEvents = false; // should be enabled
|
||||
url = scope.job.related.job_events + '?event=playbook_on_stats';
|
||||
Rest.setUrl(url);
|
||||
Rest.get()
|
||||
@@ -143,7 +145,6 @@ function JobDetailController ($location, $rootScope, $scope, $compile, $routePar
|
||||
else {
|
||||
api_complete = true; //trigger events to start processing
|
||||
$rootScope.jobDetailInterval = setInterval(function() {
|
||||
$log.debug('Updating the DOM...');
|
||||
UpdateDOM({ scope: scope });
|
||||
}, 2000);
|
||||
}
|
||||
@@ -291,6 +292,7 @@ function JobDetailController ($location, $rootScope, $scope, $compile, $routePar
|
||||
else {
|
||||
scope.activeTask = data.results[0].id;
|
||||
}
|
||||
scope.selectedTask = scope.activeTask;
|
||||
}
|
||||
data.results.forEach(function(event, idx) {
|
||||
var end, elapsed, status, status_text;
|
||||
@@ -352,7 +354,7 @@ function JobDetailController ($location, $rootScope, $scope, $compile, $routePar
|
||||
task: play.tasks[event.id]
|
||||
});
|
||||
});
|
||||
if (scope.activeTask) {
|
||||
if (scope.activeTask && scope.jobData.plays[scope.activePlay] && scope.jobData.plays[scope.activePlay].tasks[scope.activeTask]) {
|
||||
scope.jobData.plays[scope.activePlay].tasks[scope.activeTask].taskActiveClass = 'active';
|
||||
}
|
||||
scope.$emit('LoadHosts');
|
||||
@@ -395,6 +397,7 @@ function JobDetailController ($location, $rootScope, $scope, $compile, $routePar
|
||||
else {
|
||||
scope.activePlay = data.results[0].id;
|
||||
}
|
||||
scope.selectedPlay = scope.activePlay;
|
||||
}
|
||||
data.results.forEach(function(event, idx) {
|
||||
var status, status_text, start, end, elapsed, ok, changed, failed, skipped;
|
||||
@@ -457,7 +460,7 @@ function JobDetailController ($location, $rootScope, $scope, $compile, $routePar
|
||||
scope.host_summary.total = scope.host_summary.ok + scope.host_summary.changed + scope.host_summary.unreachable +
|
||||
scope.host_summary.failed;
|
||||
});
|
||||
if (scope.activePlay) {
|
||||
if (scope.activePlay && scope.jobData.plays[scope.activePlay]) {
|
||||
scope.jobData.plays[scope.activePlay].playActiveClass = 'active';
|
||||
}
|
||||
scope.$emit('LoadTasks', events_url);
|
||||
@@ -507,6 +510,7 @@ function JobDetailController ($location, $rootScope, $scope, $compile, $routePar
|
||||
}
|
||||
scope.removeLoadJobRow = scope.$on('LoadJob', function() {
|
||||
Wait('start');
|
||||
scope.job_status = {};
|
||||
// Load the job record
|
||||
Rest.setUrl(GetBasePath('jobs') + job_id + '/');
|
||||
Rest.get()
|
||||
@@ -552,6 +556,7 @@ function JobDetailController ($location, $rootScope, $scope, $compile, $routePar
|
||||
if (data.status === 'successful' || data.status === 'failed' || data.status === 'error' || data.status === 'canceled') {
|
||||
scope.job_status.finished = data.finsished;
|
||||
scope.liveEventProcessing = false;
|
||||
scope.pauseLiveEvents = false;
|
||||
}
|
||||
else {
|
||||
scope.job_status.finished = null;
|
||||
@@ -653,9 +658,19 @@ function JobDetailController ($location, $rootScope, $scope, $compile, $routePar
|
||||
scope.adjustSize();
|
||||
}, 500));
|
||||
|
||||
function flashPlayTip() {
|
||||
setTimeout(function(){
|
||||
$('#play-help').popover('show');
|
||||
},500);
|
||||
setTimeout(function() {
|
||||
$('#play-help').popover('hide');
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
scope.selectPlay = function(id) {
|
||||
if (scope.liveEventProcessing) {
|
||||
if (scope.liveEventProcessing && !scope.pauseLiveEvents) {
|
||||
scope.pauseLiveEvents = true;
|
||||
flashPlayTip();
|
||||
}
|
||||
SelectPlay({
|
||||
scope: scope,
|
||||
@@ -664,8 +679,9 @@ function JobDetailController ($location, $rootScope, $scope, $compile, $routePar
|
||||
};
|
||||
|
||||
scope.selectTask = function(id) {
|
||||
if (scope.liveEventProcessing) {
|
||||
if (scope.liveEventProcessing && !scope.pauseLiveEvents) {
|
||||
scope.pauseLiveEvents = true;
|
||||
flashPlayTip();
|
||||
}
|
||||
SelectTask({
|
||||
scope: scope,
|
||||
@@ -673,6 +689,13 @@ function JobDetailController ($location, $rootScope, $scope, $compile, $routePar
|
||||
});
|
||||
};
|
||||
|
||||
scope.togglePlayButton = function() {
|
||||
if (scope.pauseLiveEvents) {
|
||||
scope.pauseLiveEvents = false;
|
||||
scope.$emit('LoadJob');
|
||||
}
|
||||
};
|
||||
|
||||
scope.toggleSummary = function(hide) {
|
||||
var docw, doch, height = $('#job-detail-container').height(), slide_width;
|
||||
if (!hide) {
|
||||
@@ -739,7 +762,7 @@ function JobDetailController ($location, $rootScope, $scope, $compile, $routePar
|
||||
|
||||
scope.filterPlayStatus = function() {
|
||||
scope.search_play_status = (scope.search_play_status === 'all') ? 'failed' : 'all';
|
||||
if (!scope.liveEventProcessing) {
|
||||
if (!scope.liveEventProcessing || scope.pauseLiveEvents) {
|
||||
LoadPlays({
|
||||
scope: scope
|
||||
});
|
||||
@@ -753,7 +776,7 @@ function JobDetailController ($location, $rootScope, $scope, $compile, $routePar
|
||||
else {
|
||||
scope.searchPlaysEnabled = true;
|
||||
}
|
||||
if (!scope.liveEventProcessing) {
|
||||
if (!scope.liveEventProcessing || scope.pauseLiveEvents) {
|
||||
LoadPlays({
|
||||
scope: scope
|
||||
});
|
||||
@@ -774,7 +797,7 @@ function JobDetailController ($location, $rootScope, $scope, $compile, $routePar
|
||||
else {
|
||||
scope.searchTasksEnabled = true;
|
||||
}
|
||||
if (!scope.liveEventProcessing) {
|
||||
if (!scope.liveEventProcessing || scope.pauseLiveEvents) {
|
||||
LoadTasks({
|
||||
scope: scope
|
||||
});
|
||||
@@ -795,7 +818,7 @@ function JobDetailController ($location, $rootScope, $scope, $compile, $routePar
|
||||
else {
|
||||
scope.searchHostsEnabled = true;
|
||||
}
|
||||
if (!scope.liveEventProcessing) {
|
||||
if (!scope.liveEventProcessing || scope.pauseLiveEvents) {
|
||||
LoadHosts({
|
||||
scope: scope
|
||||
});
|
||||
@@ -816,7 +839,7 @@ function JobDetailController ($location, $rootScope, $scope, $compile, $routePar
|
||||
else {
|
||||
scope.searchHostSummaryEnabled = true;
|
||||
}
|
||||
if (!scope.liveEventProcessing) {
|
||||
if (!scope.liveEventProcessing || scope.pauseLiveEvents) {
|
||||
ReloadHostSummaryList({
|
||||
scope: scope
|
||||
});
|
||||
@@ -832,7 +855,7 @@ function JobDetailController ($location, $rootScope, $scope, $compile, $routePar
|
||||
|
||||
scope.filterTaskStatus = function() {
|
||||
scope.search_task_status = (scope.search_task_status === 'all') ? 'failed' : 'all';
|
||||
if (!scope.liveEventProcessing) {
|
||||
if (!scope.liveEventProcessing || scope.pauseLiveEvents) {
|
||||
LoadTasks({
|
||||
scope: scope
|
||||
});
|
||||
@@ -841,7 +864,7 @@ function JobDetailController ($location, $rootScope, $scope, $compile, $routePar
|
||||
|
||||
scope.filterHostStatus = function() {
|
||||
scope.search_host_status = (scope.search_host_status === 'all') ? 'failed' : 'all';
|
||||
if (!scope.liveEventProcessing) {
|
||||
if (!scope.liveEventProcessing || scope.pauseLiveEvents) {
|
||||
LoadHosts({
|
||||
scope: scope
|
||||
});
|
||||
@@ -850,7 +873,7 @@ function JobDetailController ($location, $rootScope, $scope, $compile, $routePar
|
||||
|
||||
scope.filterHostSummaryStatus = function() {
|
||||
scope.search_host_summary_status = (scope.search_host_summary_status === 'all') ? 'failed' : 'all';
|
||||
if (!scope.liveEventProcessing) {
|
||||
if (!scope.liveEventProcessing || scope.pauseLiveEvents) {
|
||||
ReloadHostSummaryList({
|
||||
scope: scope
|
||||
});
|
||||
@@ -861,7 +884,7 @@ function JobDetailController ($location, $rootScope, $scope, $compile, $routePar
|
||||
EventViewer({
|
||||
scope: scope,
|
||||
url: scope.job.related.job_events,
|
||||
parent_id: scope.activeTask,
|
||||
parent_id: scope.selectedTask,
|
||||
event_id: id,
|
||||
title: 'Host Events'
|
||||
});
|
||||
@@ -975,7 +998,7 @@ function JobDetailController ($location, $rootScope, $scope, $compile, $routePar
|
||||
else {
|
||||
// no next event (task), get the end time of the play
|
||||
scope.plays.every(function(p, j) {
|
||||
if (p.id === scope.activePlay) {
|
||||
if (p.id === scope.selectedPlay) {
|
||||
end = scope.plays[j].finished;
|
||||
return false;
|
||||
}
|
||||
@@ -997,7 +1020,7 @@ function JobDetailController ($location, $rootScope, $scope, $compile, $routePar
|
||||
|
||||
scope.tasks.push({
|
||||
id: event.id,
|
||||
play_id: scope.activePlay,
|
||||
play_id: scope.selectedPlay,
|
||||
name: event.name,
|
||||
status: status,
|
||||
status_text: status_text,
|
||||
|
||||
@@ -116,9 +116,9 @@ angular.module('HostEventsViewerHelper', ['ModalDialog', 'Utilities', 'EventView
|
||||
var html = '';
|
||||
html += "<tr>\n";
|
||||
html += "<td class=\"col-md-3\"><a href=\"\" ng-click=\"showDetails(" + res.id + ")\" aw-tool-tip=\"Click to view details\" data-placement=\"top\"><i class=\"fa icon-job-" + res.status + "\"></i> " + res.status_text + "</a></td>\n";
|
||||
html += "<td class=\"col-md=3\">" + res.host_name + "</td>\n";
|
||||
html += "<td class=\"col-md-3\">" + res.play + "</td>\n";
|
||||
html += "<td class=\"col-md-3\">" + res.task + "</td>\n";
|
||||
html += "<td class=\"col-md=3\" ng-non-bindable>" + res.host_name + "</td>\n";
|
||||
html += "<td class=\"col-md-3\" ng-non-bindable>" + res.play + "</td>\n";
|
||||
html += "<td class=\"col-md-3\" ng-non-bindable>" + res.task + "</td>\n";
|
||||
html += "</tr>";
|
||||
return html;
|
||||
};
|
||||
|
||||
@@ -725,16 +725,16 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
|
||||
};
|
||||
}])
|
||||
|
||||
// Call SelectPlay whenever the the activePlay needs to change
|
||||
.factory('SelectPlay', ['SelectTask', 'LoadTasks', function(SelectTask, LoadTasks) {
|
||||
// Call when the selected Play needs to change
|
||||
.factory('SelectPlay', ['LoadTasks', function(LoadTasks) {
|
||||
return function(params) {
|
||||
var scope = params.scope,
|
||||
id = params.id,
|
||||
callback = params.callback;
|
||||
|
||||
scope.activePlay = id;
|
||||
scope.selectedPlay = id;
|
||||
scope.plays.forEach(function(play, idx) {
|
||||
if (play.id === scope.activePlay) {
|
||||
if (play.id === scope.selectedPlay) {
|
||||
scope.plays[idx].playActiveClass = 'active';
|
||||
}
|
||||
else {
|
||||
@@ -760,14 +760,14 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
|
||||
scope.tasks = [];
|
||||
scope.tasksMap = {};
|
||||
|
||||
if (scope.activePlay) {
|
||||
url = scope.job.url + 'job_tasks/?event_id=' + scope.activePlay;
|
||||
if (scope.selectedPlay) {
|
||||
url = scope.job.url + 'job_tasks/?event_id=' + scope.selectedPlay;
|
||||
url += (scope.search_task_name) ? '&task__icontains=' + scope.search_task_name : '';
|
||||
url += (scope.search_task_status === 'failed') ? '&failed=true' : '';
|
||||
url += '&page_size=' + scope.tasksMaxRows + '&order_by=id';
|
||||
|
||||
scope.plays.every(function(p, idx) {
|
||||
if (p.id === scope.activePlay) {
|
||||
if (p.id === scope.selectedPlay) {
|
||||
play = scope.plays[idx];
|
||||
return false;
|
||||
}
|
||||
@@ -793,7 +793,7 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
|
||||
else {
|
||||
// no next event (task), get the end time of the play
|
||||
scope.plays.every(function(play) {
|
||||
if (play.id === scope.activePlay) {
|
||||
if (play.id === scope.selectedPlay) {
|
||||
end = play.finished;
|
||||
return false;
|
||||
}
|
||||
@@ -816,7 +816,7 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
|
||||
|
||||
scope.tasks.push({
|
||||
id: event.id,
|
||||
play_id: scope.activePlay,
|
||||
play_id: scope.selectedPlay,
|
||||
name: event.name,
|
||||
status: status,
|
||||
status_text: status_text,
|
||||
@@ -859,7 +859,6 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
|
||||
});
|
||||
}
|
||||
else {
|
||||
//$('#tasks-table-detail').mCustomScrollbar("update");
|
||||
SelectTask({
|
||||
scope: scope,
|
||||
id: null,
|
||||
@@ -869,16 +868,16 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
|
||||
};
|
||||
}])
|
||||
|
||||
// Call SelectTask whenever the activeTask needs to change
|
||||
// Call when the selected task needs to change
|
||||
.factory('SelectTask', ['LoadHosts', function(LoadHosts) {
|
||||
return function(params) {
|
||||
var scope = params.scope,
|
||||
id = params.id,
|
||||
callback = params.callback;
|
||||
|
||||
scope.activeTask = id;
|
||||
scope.selectedTask = id;
|
||||
scope.tasks.forEach(function(task, idx) {
|
||||
if (task.id === scope.activeTask) {
|
||||
if (task.id === scope.selectedTask) {
|
||||
scope.tasks[idx].taskActiveClass = 'active';
|
||||
}
|
||||
else {
|
||||
@@ -904,9 +903,9 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
|
||||
scope.hostResults = [];
|
||||
scope.hostResultsMap = {};
|
||||
|
||||
if (scope.activeTask) {
|
||||
if (scope.selectedTask) {
|
||||
// If we have a selected task, then get the list of hosts
|
||||
url = scope.job.related.job_events + '?parent=' + scope.activeTask + '&';
|
||||
url = scope.job.related.job_events + '?parent=' + scope.selectedTask + '&';
|
||||
url += (scope.search_host_name) ? 'host__name__icontains=' + scope.search_host_name + '&' : '';
|
||||
url += (scope.search_host_status === 'failed') ? 'failed=true&' : '';
|
||||
url += 'event__startswith=runner&page_size=' + scope.hostResultsMaxRows + '&order_by=host__name';
|
||||
@@ -1178,6 +1177,7 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
|
||||
setTimeout( function() {
|
||||
scope.$apply( function() {
|
||||
scope.plays = result;
|
||||
scope.selectedPlay = scope.activePlay;
|
||||
if (scope.liveEventProcessing) {
|
||||
$('#plays-table-detail').scrollTop($('#plays-table-detail').prop("scrollHeight"));
|
||||
}
|
||||
@@ -1203,7 +1203,7 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (scope.activePlay) {
|
||||
if (scope.activePlay && scope.jobData.plays[scope.activePlay]) {
|
||||
|
||||
tasks = JSON.parse(JSON.stringify(scope.jobData.plays[scope.activePlay].tasks));
|
||||
|
||||
@@ -1253,6 +1253,7 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
|
||||
setTimeout( function() {
|
||||
scope.$apply( function() {
|
||||
scope.tasks = result;
|
||||
scope.selectedTask = scope.activeTask;
|
||||
if (scope.liveEventProcessing) {
|
||||
$('#tasks-table-detail').scrollTop($('#tasks-table-detail').prop("scrollHeight"));
|
||||
}
|
||||
@@ -1273,7 +1274,8 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
|
||||
key,
|
||||
keys;
|
||||
|
||||
if (scope.activePlay && scope.activeTask) {
|
||||
if (scope.activePlay && scope.activeTask && scope.jobData.plays[scope.activePlay] &&
|
||||
scope.jobData.plays[scope.activePlay].tasks[scope.activeTask]) {
|
||||
|
||||
hostResults = JSON.parse(JSON.stringify(scope.jobData.plays[scope.activePlay].tasks[scope.activeTask].hostResults));
|
||||
|
||||
|
||||
@@ -80,6 +80,12 @@
|
||||
|
||||
#jobs-detail {
|
||||
|
||||
#play-help {
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.job_summary {
|
||||
.table {
|
||||
margin-bottom: 0;
|
||||
|
||||
@@ -229,7 +229,7 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Job
|
||||
* aw-tool-tip="<< tooltip text here >>"
|
||||
*
|
||||
* Include the standard TB data-XXX attributes to controll a tooltip's appearance. We will
|
||||
* default placement to the left and delay to 2 seconds.
|
||||
* default placement to the left and delay to the config setting.
|
||||
*/
|
||||
.directive('awToolTip', function() {
|
||||
return function(scope, element, attrs) {
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
<div class="job_well">
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-right">
|
||||
<a href="" id="play-help" aw-pop-over="Live event processing is now paused. Click here to resume." id="play-button-help" data-placement="left" ng-show="pauseLiveEvents" ><i class="fa fa-question"></i></a>
|
||||
<a href="" ng-click="togglePlayButton()" id="play-button" class="btn btn-primary btn-xs" aw-tool-tip="Resume viewing live events" data-placement="top" ng-show="pauseLiveEvents" style="margin-right:25px;"><i class="fa fa-play"></i></a>
|
||||
<a href="/#/jobs/{{ job_id }}/stdout" id="view-stdout-button" target="_blank" type="button" class="btn btn-primary btn-xs" aw-tool-tip="View standard out. Opens in new tab or window." data-placement="top"><i class="fa fa-external-link"></i></a>
|
||||
<button type="button" class="btn btn-xs btn-primary ng-hide" ng-click="refresh()" id="refresh_btn" aw-tool-tip="Refresh the page" data-placement="top" ng-show="socketStatus == 'error'"
|
||||
data-original-title="" title=""><i class="fa fa-refresh"></i></button>
|
||||
|
||||
Reference in New Issue
Block a user