mirror of
https://github.com/ansible/awx.git
synced 2026-03-03 01:38:50 -03:30
Merge pull request #1084 from mabashian/stdout-log-directive
Moved standard out log to directive
This commit is contained in:
@@ -32,6 +32,7 @@
|
|||||||
#pre-container {
|
#pre-container {
|
||||||
overflow-x: scroll;
|
overflow-x: scroll;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -881,9 +881,9 @@ var tower = angular.module('Tower', [
|
|||||||
}]);
|
}]);
|
||||||
}])
|
}])
|
||||||
|
|
||||||
.run(['$q', '$compile', '$cookieStore', '$rootScope', '$log', 'CheckLicense', '$location', 'Authorization', 'LoadBasePaths', 'Timer', 'ClearScope', 'Socket',
|
.run(['$q', '$compile', '$cookieStore', '$rootScope', '$log', '$state', 'CheckLicense', '$location', 'Authorization', 'LoadBasePaths', 'Timer', 'ClearScope', 'Socket',
|
||||||
'LoadConfig', 'Store', 'ShowSocketHelp', 'AboutAnsibleHelp', 'pendoService',
|
'LoadConfig', 'Store', 'ShowSocketHelp', 'AboutAnsibleHelp', 'pendoService',
|
||||||
function ($q, $compile, $cookieStore, $rootScope, $log, CheckLicense, $location, Authorization, LoadBasePaths, Timer, ClearScope, Socket,
|
function ($q, $compile, $cookieStore, $rootScope, $log, $state, CheckLicense, $location, Authorization, LoadBasePaths, Timer, ClearScope, Socket,
|
||||||
LoadConfig, Store, ShowSocketHelp, AboutAnsibleHelp, pendoService) {
|
LoadConfig, Store, ShowSocketHelp, AboutAnsibleHelp, pendoService) {
|
||||||
|
|
||||||
|
|
||||||
@@ -959,32 +959,28 @@ var tower = angular.module('Tower', [
|
|||||||
' status changed to ' + data.status +
|
' status changed to ' + data.status +
|
||||||
' send to ' + $location.$$url);
|
' send to ' + $location.$$url);
|
||||||
|
|
||||||
var urlToCheck = $location.$$url;
|
|
||||||
if (urlToCheck.indexOf("?") !== -1) {
|
|
||||||
urlToCheck = urlToCheck.substr(0, urlToCheck.indexOf("?"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// this acts as a router...it emits the proper
|
// this acts as a router...it emits the proper
|
||||||
// value based on what URL the user is currently
|
// value based on what URL the user is currently
|
||||||
// accessing.
|
// accessing.
|
||||||
if (urlToCheck === '/jobs') {
|
if ($state.is('jobs')) {
|
||||||
$rootScope.$emit('JobStatusChange-jobs', data);
|
$rootScope.$emit('JobStatusChange-jobs', data);
|
||||||
} else if (/\/jobs\/(\d)+\/stdout/.test(urlToCheck) ||
|
} else if ($state.is('jobDetail') ||
|
||||||
/\/ad_hoc_commands\/(\d)+/.test(urlToCheck)) {
|
$state.is('adHocJobStdout') ||
|
||||||
|
$state.is('inventorySyncStdout') ||
|
||||||
// TODO: something will need to change here for stdout
|
$state.is('managementJobStdout') ||
|
||||||
|
$state.is('scmUpdateStdout')) {
|
||||||
|
|
||||||
$log.debug("sending status to standard out");
|
$log.debug("sending status to standard out");
|
||||||
$rootScope.$emit('JobStatusChange-jobStdout', data);
|
$rootScope.$emit('JobStatusChange-jobStdout', data);
|
||||||
} else if (/\/jobs\/(\d)+/.test(urlToCheck)) {
|
} else if ($state.is('jobDetail')) {
|
||||||
$rootScope.$emit('JobStatusChange-jobDetails', data);
|
$rootScope.$emit('JobStatusChange-jobDetails', data);
|
||||||
} else if (urlToCheck === '/home') {
|
} else if ($state.is('dashboard')) {
|
||||||
$rootScope.$emit('JobStatusChange-home', data);
|
$rootScope.$emit('JobStatusChange-home', data);
|
||||||
} else if (urlToCheck === '/portal') {
|
} else if ($state.is('portal')) {
|
||||||
$rootScope.$emit('JobStatusChange-portal', data);
|
$rootScope.$emit('JobStatusChange-portal', data);
|
||||||
} else if (urlToCheck === '/projects') {
|
} else if ($state.is('projects')) {
|
||||||
$rootScope.$emit('JobStatusChange-projects', data);
|
$rootScope.$emit('JobStatusChange-projects', data);
|
||||||
} else if (/\/inventories\/(\d)+\/manage/.test(urlToCheck)) {
|
} else if ($state.is('inventoryManage')) {
|
||||||
$rootScope.$emit('JobStatusChange-inventory', data);
|
$rootScope.$emit('JobStatusChange-inventory', data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<div class="tab-pane" id="jobs-stdout">
|
<div class="tab-pane" id="jobs-stdout">
|
||||||
<div ng-cloak id="htmlTemplate">
|
<div ng-cloak id="htmlTemplate">
|
||||||
<div class="StandardOut">
|
<div class="StandardOut">
|
||||||
<div class="StandardOut-leftPanel">
|
<div class="StandardOut-leftPanel" ng-show="!stdoutFullScreen">
|
||||||
<div class="Panel">
|
<div class="Panel">
|
||||||
<div class="StandardOut-panelHeader">
|
<div class="StandardOut-panelHeader">
|
||||||
RESULTS
|
RESULTS
|
||||||
@@ -98,17 +98,19 @@
|
|||||||
<div class="StandardOut-rightPanel">
|
<div class="StandardOut-rightPanel">
|
||||||
<div class="Panel">
|
<div class="Panel">
|
||||||
<div class="StandardOut-panelHeader">
|
<div class="StandardOut-panelHeader">
|
||||||
STANDARD OUT
|
<div class="StandardOut-panelHeaderText">STANDARD OUT</div>
|
||||||
</div>
|
<div class="StandardOut-panelHeaderActions">
|
||||||
<div class="StandardOut-consoleOutput">
|
<button class="StandardOut-actionButton" aw-tool-tip="Toggle Output" data-placement="top" ng-class="{'StandardOut-actionButton--active': stdoutFullScreen}"ng-click="toggleStdoutFullscreen()">
|
||||||
<div id="pre-container" class="body_background body_foreground pre mono-space StandardOut-preContainer"
|
<i class="fa fa-arrows-alt"></i>
|
||||||
lr-infinite-scroll="stdOutScrollToTop" scroll-threshold="300" data-direction="up" time-threshold="500">
|
</button>
|
||||||
<div id="pre-container-content" class="StandardOut-preContent"></div>
|
<a href="/api/v1/ad_hoc_commands/{{ job.id }}/stdout?format=txt_download&token={{ token }}">
|
||||||
</div>
|
<button class="StandardOut-actionButton" aw-tool-tip="Download Output" data-placement="top">
|
||||||
<div class="scroll-spinner" id="stdoutMoreRowsBottom">
|
<i class="fa fa-download"></i>
|
||||||
<i class="fa fa-cog fa-spin"></i>
|
</button>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<standard-out-log stdout-endpoint="job.related.stdout"></standard-out-log>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -23,18 +23,16 @@ export default {
|
|||||||
return FeaturesService.get();
|
return FeaturesService.get();
|
||||||
}],
|
}],
|
||||||
adhocEventsSocket: ['Socket', '$rootScope', function(Socket, $rootScope) {
|
adhocEventsSocket: ['Socket', '$rootScope', function(Socket, $rootScope) {
|
||||||
// if (!$rootScope.adhoc_event_socket) {
|
if (!$rootScope.adhoc_event_socket) {
|
||||||
// $rootScope.adhoc_event_socket = Socket({
|
$rootScope.adhoc_event_socket = Socket({
|
||||||
// scope: $rootScope,
|
scope: $rootScope,
|
||||||
// endpoint: "ad_hoc_command_events"
|
endpoint: "ad_hoc_command_events"
|
||||||
// });
|
});
|
||||||
// $rootScope.adhoc_event_socket.init();
|
$rootScope.adhoc_event_socket.init();
|
||||||
// return true;
|
return true;
|
||||||
// } else {
|
} else {
|
||||||
// return true;
|
return true;
|
||||||
// }
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<div class="tab-pane" id="jobs-stdout">
|
<div class="tab-pane" id="jobs-stdout">
|
||||||
<div ng-cloak id="htmlTemplate">
|
<div ng-cloak id="htmlTemplate">
|
||||||
<div class="StandardOut">
|
<div class="StandardOut">
|
||||||
<div class="StandardOut-leftPanel">
|
<div class="StandardOut-leftPanel" ng-show="!stdoutFullScreen">
|
||||||
<div class="Panel">
|
<div class="Panel">
|
||||||
<div class="StandardOut-panelHeader">
|
<div class="StandardOut-panelHeader">
|
||||||
RESULTS
|
RESULTS
|
||||||
@@ -112,17 +112,19 @@
|
|||||||
<div class="StandardOut-rightPanel">
|
<div class="StandardOut-rightPanel">
|
||||||
<div class="Panel">
|
<div class="Panel">
|
||||||
<div class="StandardOut-panelHeader">
|
<div class="StandardOut-panelHeader">
|
||||||
STANDARD OUT
|
<div class="StandardOut-panelHeaderText">STANDARD OUT</div>
|
||||||
</div>
|
<div class="StandardOut-panelHeaderActions">
|
||||||
<div class="StandardOut-consoleOutput">
|
<button class="StandardOut-actionButton" aw-tool-tip="Toggle Output" data-placement="top" ng-class="{'StandardOut-actionButton--active': stdoutFullScreen}"ng-click="toggleStdoutFullscreen()">
|
||||||
<div id="pre-container" class="body_background body_foreground pre mono-space StandardOut-preContainer"
|
<i class="fa fa-arrows-alt"></i>
|
||||||
lr-infinite-scroll="stdOutScrollToTop" scroll-threshold="300" data-direction="up" time-threshold="500">
|
</button>
|
||||||
<div id="pre-container-content" class="StandardOut-preContent"></div>
|
<a href="/api/v1/inventory_updates/{{ job.id }}/stdout?format=txt_download&token={{ token }}">
|
||||||
</div>
|
<button class="StandardOut-actionButton" aw-tool-tip="Download Output" data-placement="top">
|
||||||
<div class="scroll-spinner" id="stdoutMoreRowsBottom">
|
<i class="fa fa-download"></i>
|
||||||
<i class="fa fa-cog fa-spin"></i>
|
</button>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<standard-out-log stdout-endpoint="job.related.stdout"></standard-out-log>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -24,18 +24,8 @@ export default {
|
|||||||
features: ['FeaturesService', function(FeaturesService) {
|
features: ['FeaturesService', function(FeaturesService) {
|
||||||
return FeaturesService.get();
|
return FeaturesService.get();
|
||||||
}],
|
}],
|
||||||
adhocEventsSocket: ['Socket', '$rootScope', function(Socket, $rootScope) {
|
inventorySyncSocket: ['Socket', '$rootScope', function(Socket, $rootScope) {
|
||||||
// if (!$rootScope.adhoc_event_socket) {
|
// TODO: determine whether or not we have socket support for inventory sync standard out
|
||||||
// $rootScope.adhoc_event_socket = Socket({
|
|
||||||
// scope: $rootScope,
|
|
||||||
// endpoint: "ad_hoc_command_events"
|
|
||||||
// });
|
|
||||||
// $rootScope.adhoc_event_socket.init();
|
|
||||||
// return true;
|
|
||||||
// } else {
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|||||||
10
awx/ui/client/src/standard-out/log/main.js
Normal file
10
awx/ui/client/src/standard-out/log/main.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
/*************************************************
|
||||||
|
* Copyright (c) 2015 Ansible, Inc.
|
||||||
|
*
|
||||||
|
* All Rights Reserved
|
||||||
|
*************************************************/
|
||||||
|
|
||||||
|
import standardOutLog from './standard-out-log.directive';
|
||||||
|
export default
|
||||||
|
angular.module('standardOutLogDirective', [])
|
||||||
|
.directive('standardOutLog', standardOutLog);
|
||||||
@@ -0,0 +1,206 @@
|
|||||||
|
/*************************************************
|
||||||
|
* Copyright (c) 2016 Ansible, Inc.
|
||||||
|
*
|
||||||
|
* All Rights Reserved
|
||||||
|
*************************************************/
|
||||||
|
|
||||||
|
export default ['$log', '$rootScope', '$scope', '$state', '$stateParams', 'ProcessErrors', 'Rest', 'Wait',
|
||||||
|
function ($log, $rootScope, $scope, $state, $stateParams, ProcessErrors, Rest, Wait) {
|
||||||
|
|
||||||
|
var api_complete = false,
|
||||||
|
stdout_url,
|
||||||
|
current_range,
|
||||||
|
loaded_sections = [],
|
||||||
|
event_queue = 0,
|
||||||
|
auto_scroll_down=true, // programmatic scroll to bottom
|
||||||
|
live_event_processing = true,
|
||||||
|
page_size = 500,
|
||||||
|
job_id = $stateParams.id;
|
||||||
|
|
||||||
|
$scope.should_apply_live_events = true;
|
||||||
|
|
||||||
|
// Open up a socket for events depending on the type of job
|
||||||
|
function openSockets() {
|
||||||
|
if ($state.current.name == 'adHocJobStdout') {
|
||||||
|
$log.debug("socket watching on ad_hoc_command_events-" + job_id);
|
||||||
|
$rootScope.adhoc_event_socket.on("ad_hoc_command_events-" + job_id, function() {
|
||||||
|
$log.debug("socket fired on ad_hoc_command_events-" + job_id);
|
||||||
|
if (api_complete) {
|
||||||
|
event_queue++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// TODO: do we need to add socket listeners for scmUpdateStdout, inventorySyncStdout, managementJobStdout?
|
||||||
|
}
|
||||||
|
|
||||||
|
openSockets();
|
||||||
|
|
||||||
|
// This is a trigger for loading up the standard out
|
||||||
|
if ($scope.removeLoadStdout) {
|
||||||
|
$scope.removeLoadStdout();
|
||||||
|
}
|
||||||
|
$scope.removeLoadStdout = $scope.$on('LoadStdout', function() {
|
||||||
|
if (loaded_sections.length === 0) {
|
||||||
|
loadStdout()
|
||||||
|
}
|
||||||
|
else if (live_event_processing) {
|
||||||
|
getNextSection();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// This interval checks to see whether or not we've gotten a new
|
||||||
|
// event via sockets. If so, go out and update the standard out
|
||||||
|
// log.
|
||||||
|
$rootScope.jobStdOutInterval = setInterval( function() {
|
||||||
|
if (event_queue > 0) {
|
||||||
|
// events happened since the last check
|
||||||
|
$log.debug('checking for stdout...');
|
||||||
|
if (loaded_sections.length === 0) { ////this if statement for refresh
|
||||||
|
$log.debug('calling LoadStdout');
|
||||||
|
loadStdout();
|
||||||
|
}
|
||||||
|
else if (live_event_processing) {
|
||||||
|
$log.debug('calling getNextSection');
|
||||||
|
getNextSection();
|
||||||
|
}
|
||||||
|
event_queue = 0;
|
||||||
|
}
|
||||||
|
}, 2000);
|
||||||
|
|
||||||
|
// stdoutEndpoint gets passed through in the directive declaration.
|
||||||
|
// This watcher fires off loadStdout() when the endpoint becomes
|
||||||
|
// available.
|
||||||
|
$scope.$watch('stdoutEndpoint', function(newVal, oldVal) {
|
||||||
|
if(newVal && newVal != oldVal) {
|
||||||
|
// Fire off the server call
|
||||||
|
loadStdout();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function loadStdout() {
|
||||||
|
Rest.setUrl($scope.stdoutEndpoint + '?format=json&start_line=-' + page_size);
|
||||||
|
Rest.get()
|
||||||
|
.success(function(data) {
|
||||||
|
Wait('stop');
|
||||||
|
if (data.content) {
|
||||||
|
api_complete = true;
|
||||||
|
$('#pre-container-content').html(data.content);
|
||||||
|
current_range = data.range;
|
||||||
|
if (data.content !== "Waiting for results...") {
|
||||||
|
loaded_sections.push({
|
||||||
|
start: (data.range.start < 0) ? 0 : data.range.start,
|
||||||
|
end: data.range.end
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#pre-container').scrollTop($('#pre-container').prop("scrollHeight"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
api_complete = true;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.error(function(data, status) {
|
||||||
|
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
|
||||||
|
msg: 'Failed to retrieve stdout for job: ' + job_id + '. GET returned: ' + status });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function getNextSection() {
|
||||||
|
// get the next range of data from the API
|
||||||
|
var start = loaded_sections[loaded_sections.length - 1].end, url;
|
||||||
|
url = stdout_url + '?format=json&start_line=' + start + '&end_line=' + (start + page_size);
|
||||||
|
$('#stdoutMoreRowsBottom').fadeIn();
|
||||||
|
Rest.setUrl(url);
|
||||||
|
Rest.get()
|
||||||
|
.success( function(data) {
|
||||||
|
if ($('#pre-container-content').html() === "Waiting for results...") {
|
||||||
|
$('#pre-container-content').html(data.content);
|
||||||
|
} else {
|
||||||
|
$('#pre-container-content').append(data.content);
|
||||||
|
}
|
||||||
|
loaded_sections.push({
|
||||||
|
start: (data.range.start < 0) ? 0 : data.range.start,
|
||||||
|
end: data.range.end
|
||||||
|
});
|
||||||
|
//console.log('loaded start: ' + data.range.start + ' end: ' + data.range.end);
|
||||||
|
//console.log(data.content);
|
||||||
|
if ($scope.should_apply_live_events) {
|
||||||
|
// if user has not disabled live event view by scrolling upward, then scroll down to the new content
|
||||||
|
current_range = data.range;
|
||||||
|
auto_scroll_down = true; // prevent auto load from happening
|
||||||
|
$('#pre-container').scrollTop($('#pre-container').prop("scrollHeight"));
|
||||||
|
}
|
||||||
|
$('#stdoutMoreRowsBottom').fadeOut(400);
|
||||||
|
})
|
||||||
|
.error(function(data, status) {
|
||||||
|
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
|
||||||
|
msg: 'Failed to retrieve stdout for job: ' + job_id + '. GET returned: ' + status });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.stdOutScrollToTop = function() {
|
||||||
|
// scroll up or back in time toward the beginning of the file
|
||||||
|
var start, end, url;
|
||||||
|
if (loaded_sections.length > 0 && loaded_sections[0].start > 0) {
|
||||||
|
start = (loaded_sections[0].start - page_size > 0) ? loaded_sections[0].start - page_size : 0;
|
||||||
|
end = loaded_sections[0].start - 1;
|
||||||
|
}
|
||||||
|
else if (loaded_sections.length === 0) {
|
||||||
|
start = 0;
|
||||||
|
end = page_size;
|
||||||
|
}
|
||||||
|
if (start !== undefined && end !== undefined) {
|
||||||
|
$('#stdoutMoreRowsTop').fadeIn();
|
||||||
|
url = stdout_url + '?format=json&start_line=' + start + '&end_line=' + end;
|
||||||
|
Rest.setUrl(url);
|
||||||
|
Rest.get()
|
||||||
|
.success( function(data) {
|
||||||
|
//var currentPos = $('#pre-container').scrollTop();
|
||||||
|
var newSH, oldSH = $('#pre-container').prop('scrollHeight'),
|
||||||
|
st = $('#pre-container').scrollTop();
|
||||||
|
|
||||||
|
$('#pre-container-content').prepend(data.content);
|
||||||
|
|
||||||
|
newSH = $('#pre-container').prop('scrollHeight');
|
||||||
|
$('#pre-container').scrollTop(newSH - oldSH + st);
|
||||||
|
|
||||||
|
loaded_sections.unshift({
|
||||||
|
start: (data.range.start < 0) ? 0 : data.range.start,
|
||||||
|
end: data.range.end
|
||||||
|
});
|
||||||
|
current_range = data.range;
|
||||||
|
$('#stdoutMoreRowsTop').fadeOut(400);
|
||||||
|
})
|
||||||
|
.error(function(data, status) {
|
||||||
|
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
|
||||||
|
msg: 'Failed to retrieve stdout for job: ' + job_id + '. GET returned: ' + status });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// We watch for job status changes here. If the job completes we want to clear out the
|
||||||
|
// stdout interval and kill the live_event_processing flag.
|
||||||
|
if ($scope.removeJobStatusChange) {
|
||||||
|
$scope.removeJobStatusChange();
|
||||||
|
}
|
||||||
|
$scope.removeJobStatusChange = $rootScope.$on('JobStatusChange-jobStdout', function(e, data) {
|
||||||
|
if (parseInt(data.unified_job_id, 10) === parseInt(job_id,10)) {
|
||||||
|
if (data.status === 'failed' || data.status === 'canceled' ||
|
||||||
|
data.status === 'error' || data.status === 'successful') {
|
||||||
|
if ($rootScope.jobStdOutInterval) {
|
||||||
|
window.clearInterval($rootScope.jobStdOutInterval);
|
||||||
|
}
|
||||||
|
if (live_event_processing) {
|
||||||
|
if (loaded_sections.length === 0) {
|
||||||
|
loadStdout();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
getNextSection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
live_event_processing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}];
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*************************************************
|
||||||
|
* Copyright (c) 2016 Ansible, Inc.
|
||||||
|
*
|
||||||
|
* All Rights Reserved
|
||||||
|
*************************************************/
|
||||||
|
|
||||||
|
import standardOutLogController from './standard-out-log.controller';
|
||||||
|
export default [ 'templateUrl',
|
||||||
|
function(templateUrl) {
|
||||||
|
return {
|
||||||
|
scope: {
|
||||||
|
stdoutEndpoint: '=',
|
||||||
|
jobId: '='
|
||||||
|
},
|
||||||
|
templateUrl: templateUrl('standard-out/log/standard-out-log'),
|
||||||
|
restrict: 'E',
|
||||||
|
controller: standardOutLogController,
|
||||||
|
link: function(scope) {
|
||||||
|
// All of our DOM related stuff will go in here
|
||||||
|
|
||||||
|
var lastScrollTop,
|
||||||
|
direction;
|
||||||
|
|
||||||
|
function detectDirection() {
|
||||||
|
var st = $('#pre-container').scrollTop();
|
||||||
|
if (st > lastScrollTop) {
|
||||||
|
direction = "down";
|
||||||
|
} else {
|
||||||
|
direction = "up";
|
||||||
|
}
|
||||||
|
lastScrollTop = st;
|
||||||
|
return direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#pre-container').bind('scroll', function() {
|
||||||
|
if (detectDirection() === "up") {
|
||||||
|
scope.should_apply_live_events = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($(this).scrollTop() + $(this).height() === $(this).prop("scrollHeight")) {
|
||||||
|
scope.should_apply_live_events = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}];
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<div class="StandardOut-consoleOutput">
|
||||||
|
<div id="pre-container" class="body_background body_foreground pre mono-space StandardOut-preContainer"
|
||||||
|
lr-infinite-scroll="stdOutScrollToTop" scroll-threshold="300" data-direction="up" time-threshold="500">
|
||||||
|
<div id="pre-container-content" class="StandardOut-preContent"></div>
|
||||||
|
</div>
|
||||||
|
<div class="scroll-spinner" id="stdoutMoreRowsBottom">
|
||||||
|
<i class="fa fa-cog fa-spin"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -10,8 +10,9 @@ import stdoutInventorySyncRoute from './inventory-sync/standard-out-inventory-sy
|
|||||||
import stdoutScmUpdateRoute from './scm-update/standard-out-scm-update.route';
|
import stdoutScmUpdateRoute from './scm-update/standard-out-scm-update.route';
|
||||||
import {JobStdoutController} from './standard-out.controller';
|
import {JobStdoutController} from './standard-out.controller';
|
||||||
import StandardOutHelper from './standard-out-factories/main';
|
import StandardOutHelper from './standard-out-factories/main';
|
||||||
|
import standardOutLogDirective from './log/main';
|
||||||
|
|
||||||
export default angular.module('standardOut', [StandardOutHelper.name])
|
export default angular.module('standardOut', [StandardOutHelper.name, standardOutLogDirective.name])
|
||||||
.controller('JobStdoutController', JobStdoutController)
|
.controller('JobStdoutController', JobStdoutController)
|
||||||
.run(['$stateExtender', function($stateExtender) {
|
.run(['$stateExtender', function($stateExtender) {
|
||||||
$stateExtender.addState(stdoutAdhocRoute);
|
$stateExtender.addState(stdoutAdhocRoute);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<div class="tab-pane" id="jobs-stdout">
|
<div class="tab-pane" id="jobs-stdout">
|
||||||
<div ng-cloak id="htmlTemplate">
|
<div ng-cloak id="htmlTemplate">
|
||||||
<div class="StandardOut">
|
<div class="StandardOut">
|
||||||
<div class="StandardOut-leftPanel">
|
<div class="StandardOut-leftPanel" ng-show="!stdoutFullScreen">
|
||||||
<div class="Panel">
|
<div class="Panel">
|
||||||
<div class="StandardOut-panelHeader">
|
<div class="StandardOut-panelHeader">
|
||||||
RESULTS
|
RESULTS
|
||||||
@@ -64,17 +64,14 @@
|
|||||||
<div class="StandardOut-rightPanel">
|
<div class="StandardOut-rightPanel">
|
||||||
<div class="Panel">
|
<div class="Panel">
|
||||||
<div class="StandardOut-panelHeader">
|
<div class="StandardOut-panelHeader">
|
||||||
STANDARD OUT
|
<div class="StandardOut-panelHeaderText">STANDARD OUT</div>
|
||||||
</div>
|
<div class="StandardOut-panelHeaderActions">
|
||||||
<div class="StandardOut-consoleOutput">
|
<button class="StandardOut-actionButton" aw-tool-tip="Toggle Output" data-placement="top" ng-class="{'StandardOut-actionButton--active': stdoutFullScreen}"ng-click="toggleStdoutFullscreen()">
|
||||||
<div id="pre-container" class="body_background body_foreground pre mono-space StandardOut-preContainer"
|
<i class="fa fa-arrows-alt"></i>
|
||||||
lr-infinite-scroll="stdOutScrollToTop" scroll-threshold="300" data-direction="up" time-threshold="500">
|
</button>
|
||||||
<div id="pre-container-content" class="StandardOut-preContent"></div>
|
|
||||||
</div>
|
|
||||||
<div class="scroll-spinner" id="stdoutMoreRowsBottom">
|
|
||||||
<i class="fa fa-cog fa-spin"></i>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<standard-out-log stdout-endpoint="job.related.stdout"></standard-out-log>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -22,18 +22,8 @@ export default {
|
|||||||
features: ['FeaturesService', function(FeaturesService) {
|
features: ['FeaturesService', function(FeaturesService) {
|
||||||
return FeaturesService.get();
|
return FeaturesService.get();
|
||||||
}],
|
}],
|
||||||
adhocEventsSocket: ['Socket', '$rootScope', function(Socket, $rootScope) {
|
managementJobSocket: ['Socket', '$rootScope', function(Socket, $rootScope) {
|
||||||
// if (!$rootScope.adhoc_event_socket) {
|
// TODO: determine whether or not we have socket support for management job standard out
|
||||||
// $rootScope.adhoc_event_socket = Socket({
|
|
||||||
// scope: $rootScope,
|
|
||||||
// endpoint: "ad_hoc_command_events"
|
|
||||||
// });
|
|
||||||
// $rootScope.adhoc_event_socket.init();
|
|
||||||
// return true;
|
|
||||||
// } else {
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<div class="tab-pane" id="jobs-stdout">
|
<div class="tab-pane" id="jobs-stdout">
|
||||||
<div ng-cloak id="htmlTemplate">
|
<div ng-cloak id="htmlTemplate">
|
||||||
<div class="StandardOut">
|
<div class="StandardOut">
|
||||||
<div class="StandardOut-leftPanel">
|
<div class="StandardOut-leftPanel" ng-show="!stdoutFullScreen">
|
||||||
<div class="Panel">
|
<div class="Panel">
|
||||||
<div class="StandardOut-panelHeader">
|
<div class="StandardOut-panelHeader">
|
||||||
RESULTS
|
RESULTS
|
||||||
@@ -77,17 +77,19 @@
|
|||||||
<div class="StandardOut-rightPanel">
|
<div class="StandardOut-rightPanel">
|
||||||
<div class="Panel">
|
<div class="Panel">
|
||||||
<div class="StandardOut-panelHeader">
|
<div class="StandardOut-panelHeader">
|
||||||
STANDARD OUT
|
<div class="StandardOut-panelHeaderText">STANDARD OUT</div>
|
||||||
</div>
|
<div class="StandardOut-panelHeaderActions">
|
||||||
<div class="StandardOut-consoleOutput">
|
<button class="StandardOut-actionButton" aw-tool-tip="Toggle Output" data-placement="top" ng-class="{'StandardOut-actionButton--active': stdoutFullScreen}"ng-click="toggleStdoutFullscreen()">
|
||||||
<div id="pre-container" class="body_background body_foreground pre mono-space StandardOut-preContainer"
|
<i class="fa fa-arrows-alt"></i>
|
||||||
lr-infinite-scroll="stdOutScrollToTop" scroll-threshold="300" data-direction="up" time-threshold="500">
|
</button>
|
||||||
<div id="pre-container-content" class="StandardOut-preContent"></div>
|
<a href="/api/v1/project_updates/{{ job.id }}/stdout?format=txt_download&token={{ token }}">
|
||||||
</div>
|
<button class="StandardOut-actionButton" aw-tool-tip="Download Output" data-placement="top">
|
||||||
<div class="scroll-spinner" id="stdoutMoreRowsBottom">
|
<i class="fa fa-download"></i>
|
||||||
<i class="fa fa-cog fa-spin"></i>
|
</button>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<standard-out-log stdout-endpoint="job.related.stdout"></standard-out-log>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -24,18 +24,8 @@ export default {
|
|||||||
features: ['FeaturesService', function(FeaturesService) {
|
features: ['FeaturesService', function(FeaturesService) {
|
||||||
return FeaturesService.get();
|
return FeaturesService.get();
|
||||||
}],
|
}],
|
||||||
adhocEventsSocket: ['Socket', '$rootScope', function(Socket, $rootScope) {
|
scmUpdateSocket: ['Socket', '$rootScope', function(Socket, $rootScope) {
|
||||||
// if (!$rootScope.adhoc_event_socket) {
|
// TODO: determine whether or not we have socket support for scm update standard out
|
||||||
// $rootScope.adhoc_event_socket = Socket({
|
|
||||||
// scope: $rootScope,
|
|
||||||
// endpoint: "ad_hoc_command_events"
|
|
||||||
// });
|
|
||||||
// $rootScope.adhoc_event_socket.init();
|
|
||||||
// return true;
|
|
||||||
// } else {
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,19 +10,19 @@
|
|||||||
|
|
||||||
.StandardOut-leftPanel {
|
.StandardOut-leftPanel {
|
||||||
flex: 0 0 400px;
|
flex: 0 0 400px;
|
||||||
|
margin-right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.StandardOut-rightPanel {
|
.StandardOut-rightPanel {
|
||||||
flex: 1 0;
|
flex: 1 0;
|
||||||
margin-left: 20px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.StandardOut-panelHeader {
|
.StandardOut-panelHeader {
|
||||||
color: @default-interface-txt;
|
color: @default-interface-txt;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-right: 10px;
|
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.StandardOut-consoleOutput {
|
.StandardOut-consoleOutput {
|
||||||
@@ -30,6 +30,8 @@
|
|||||||
min-height: 200px;
|
min-height: 200px;
|
||||||
background-color: @default-secondary-bg;
|
background-color: @default-secondary-bg;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
height: 300px;
|
||||||
|
overflow: scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
.StandardOut-details {
|
.StandardOut-details {
|
||||||
@@ -63,13 +65,54 @@
|
|||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.StandardOut-preContainer {
|
||||||
|
height: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.StandardOut-panelHeaderText {
|
||||||
|
align-items: center;
|
||||||
|
flex: 1 0 auto;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.StandardOut-panelHeaderActions {
|
||||||
|
justify-content: flex-end;
|
||||||
|
display: flex;
|
||||||
|
margin-left: 10px;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.StandardOut-actionButton {
|
||||||
|
font-size: 16px;
|
||||||
|
height: 30px;
|
||||||
|
min-width: 30px;
|
||||||
|
color: #b7b7b7;
|
||||||
|
background-color: inherit;
|
||||||
|
border: none;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.StandardOut-actionButton:hover {
|
||||||
|
background-color: @list-actn-bg-hov !important;
|
||||||
|
color: @list-actn-icn-hov;
|
||||||
|
}
|
||||||
|
|
||||||
|
.StandardOut-actionButton--active {
|
||||||
|
background-color: @list-actn-bg-hov !important;
|
||||||
|
color: @list-actn-icn-hov;
|
||||||
|
}
|
||||||
|
|
||||||
|
.StandardOut-actionButton + a {
|
||||||
|
margin-left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
@standardout-breakpoint: 900px;
|
@standardout-breakpoint: 900px;
|
||||||
|
|
||||||
@media screen and (max-width: @standardout-breakpoint) {
|
@media screen and (max-width: @standardout-breakpoint) {
|
||||||
.StandardOut {
|
.StandardOut {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
.StandardOut-rightPanel {
|
.StandardOut-leftPanel {
|
||||||
margin-left: 0px;
|
margin-right: 0px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,153 +11,34 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
export function JobStdoutController ($location, $log, $rootScope, $scope, $compile, $state, $stateParams, ClearScope, GetBasePath, Wait, Rest, ProcessErrors, ModelToBasePathKey, Empty, GetChoices, LookUpName) {
|
export function JobStdoutController ($rootScope, $scope, $state, $stateParams, ClearScope, GetBasePath, Rest, ProcessErrors, Empty, GetChoices, LookUpName) {
|
||||||
|
|
||||||
ClearScope();
|
ClearScope();
|
||||||
|
|
||||||
var job_id = $stateParams.id,
|
var job_id = $stateParams.id,
|
||||||
jobType = $state.current.data.jobType,
|
jobType = $state.current.data.jobType;
|
||||||
api_complete = false,
|
|
||||||
stdout_url,
|
|
||||||
current_range,
|
|
||||||
loaded_sections = [],
|
|
||||||
event_queue = 0,
|
|
||||||
auto_scroll_down=true, // programmatic scroll to bottom
|
|
||||||
live_event_processing = true,
|
|
||||||
should_apply_live_events = true,
|
|
||||||
page_size = 500,
|
|
||||||
lastScrollTop = 0,
|
|
||||||
st,
|
|
||||||
direction;
|
|
||||||
|
|
||||||
$scope.isClosed = true;
|
// This scope variable controls whether or not the left panel is shown and the right panel
|
||||||
|
// is expanded to take up the full screen
|
||||||
|
$scope.stdoutFullScreen = false;
|
||||||
|
|
||||||
|
// Listen for job status updates that may come across via sockets. We need to check the payload
|
||||||
// function openSockets() {
|
// to see whethere the updated job is the one that we're currently looking at.
|
||||||
// if (/\/jobs\/(\d)+\/stdout/.test($location.$$url)) {
|
if ($scope.removeJobStatusChange) {
|
||||||
// $log.debug("socket watching on job_events-" + job_id);
|
$scope.removeJobStatusChange();
|
||||||
// $rootScope.event_socket.on("job_events-" + job_id, function() {
|
|
||||||
// $log.debug("socket fired on job_events-" + job_id);
|
|
||||||
// if (api_complete) {
|
|
||||||
// event_queue++;
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// } else if (/\/ad_hoc_commands\/(\d)+/.test($location.$$url)) {
|
|
||||||
// $log.debug("socket watching on ad_hoc_command_events-" + job_id);
|
|
||||||
// $rootScope.adhoc_event_socket.on("ad_hoc_command_events-" + job_id, function() {
|
|
||||||
// $log.debug("socket fired on ad_hoc_command_events-" + job_id);
|
|
||||||
// if (api_complete) {
|
|
||||||
// event_queue++;
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// openSockets();
|
|
||||||
|
|
||||||
if ($rootScope.removeJobStatusChange) {
|
|
||||||
$rootScope.removeJobStatusChange();
|
|
||||||
}
|
}
|
||||||
$rootScope.removeJobStatusChange = $rootScope.$on('JobStatusChange-jobStdout', function(e, data) {
|
$scope.removeJobStatusChange = $rootScope.$on('JobStatusChange-jobStdout', function(e, data) {
|
||||||
if (parseInt(data.unified_job_id, 10) === parseInt(job_id,10) && $scope.job) {
|
if (parseInt(data.unified_job_id, 10) === parseInt(job_id,10) && $scope.job) {
|
||||||
$scope.job.status = data.status;
|
$scope.job.status = data.status;
|
||||||
if (data.status === 'failed' || data.status === 'canceled' ||
|
|
||||||
data.status === 'error' || data.status === 'successful') {
|
|
||||||
if ($rootScope.jobStdOutInterval) {
|
|
||||||
window.clearInterval($rootScope.jobStdOutInterval);
|
|
||||||
}
|
|
||||||
if (live_event_processing) {
|
|
||||||
if (loaded_sections.length === 0) {
|
|
||||||
$scope.$emit('LoadStdout');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
getNextSection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
live_event_processing = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: when the job completes we should refresh the job data so that we pull in the finish
|
||||||
|
// timestamp as well as the run time.
|
||||||
});
|
});
|
||||||
|
|
||||||
$rootScope.jobStdOutInterval = setInterval( function() {
|
// Go out and get the job details based on the job type. jobType gets defined
|
||||||
if (event_queue > 0) {
|
// in the data block of the route declaration for each of the different types
|
||||||
// events happened since the last check
|
// of stdout jobs.
|
||||||
$log.debug('checking for stdout...');
|
|
||||||
if (loaded_sections.length === 0) { ////this if statement for refresh
|
|
||||||
$log.debug('calling LoadStdout');
|
|
||||||
$scope.$emit('LoadStdout');
|
|
||||||
}
|
|
||||||
else if (live_event_processing) {
|
|
||||||
$log.debug('calling getNextSection');
|
|
||||||
getNextSection();
|
|
||||||
}
|
|
||||||
event_queue = 0;
|
|
||||||
}
|
|
||||||
}, 2000);
|
|
||||||
|
|
||||||
if ($scope.removeLoadStdout) {
|
|
||||||
$scope.removeLoadStdout();
|
|
||||||
}
|
|
||||||
$scope.removeLoadStdout = $scope.$on('LoadStdout', function() {
|
|
||||||
Rest.setUrl(stdout_url + '?format=json&start_line=-' + page_size);
|
|
||||||
Rest.get()
|
|
||||||
.success(function(data) {
|
|
||||||
Wait('stop');
|
|
||||||
if (data.content) {
|
|
||||||
api_complete = true;
|
|
||||||
$('#pre-container-content').html(data.content);
|
|
||||||
current_range = data.range;
|
|
||||||
if (data.content !== "Waiting for results...") {
|
|
||||||
loaded_sections.push({
|
|
||||||
start: (data.range.start < 0) ? 0 : data.range.start,
|
|
||||||
end: data.range.end
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#pre-container').scrollTop($('#pre-container').prop("scrollHeight"));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
api_complete = true;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.error(function(data, status) {
|
|
||||||
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
|
|
||||||
msg: 'Failed to retrieve stdout for job: ' + job_id + '. GET returned: ' + status });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
function detectDirection() {
|
|
||||||
st = $('#pre-container').scrollTop();
|
|
||||||
if (st > lastScrollTop) {
|
|
||||||
direction = "down";
|
|
||||||
} else {
|
|
||||||
direction = "up";
|
|
||||||
}
|
|
||||||
lastScrollTop = st;
|
|
||||||
return direction;
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#pre-container').bind('scroll', function() {
|
|
||||||
if (detectDirection() === "up") {
|
|
||||||
should_apply_live_events = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($(this).scrollTop() + $(this).height() === $(this).prop("scrollHeight")) {
|
|
||||||
should_apply_live_events = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$scope.toggleClosedStatus = function() {
|
|
||||||
if (!$scope.isClosed) {
|
|
||||||
$('.StandardOutDetails-detailRow--closable').slideUp(200);
|
|
||||||
$scope.isClosed = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$('.StandardOutDetails-detailRow--closable').slideDown(200);
|
|
||||||
$scope.isClosed = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Rest.setUrl(GetBasePath('base') + jobType + '/' + job_id + '/');
|
Rest.setUrl(GetBasePath('base') + jobType + '/' + job_id + '/');
|
||||||
Rest.get()
|
Rest.get()
|
||||||
.success(function(data) {
|
.success(function(data) {
|
||||||
@@ -179,7 +60,6 @@ export function JobStdoutController ($location, $log, $rootScope, $scope, $compi
|
|||||||
$scope.limit = data.limit;
|
$scope.limit = data.limit;
|
||||||
$scope.verbosity = data.verbosity;
|
$scope.verbosity = data.verbosity;
|
||||||
$scope.job_tags = data.job_tags;
|
$scope.job_tags = data.job_tags;
|
||||||
stdout_url = data.related.stdout;
|
|
||||||
|
|
||||||
// If we have a source then we have to go get the source choices from the server
|
// If we have a source then we have to go get the source choices from the server
|
||||||
if (!Empty(data.source)) {
|
if (!Empty(data.source)) {
|
||||||
@@ -252,14 +132,12 @@ export function JobStdoutController ($location, $log, $rootScope, $scope, $compi
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (data.status === 'successful' || data.status === 'failed' || data.status === 'error' || data.status === 'canceled') {
|
// If the job isn't running we want to clear out the interval that goes out and checks for stdout updates.
|
||||||
// live_event_processing = false;
|
// This interval is defined in the standard out log directive controller.
|
||||||
// if ($rootScope.jobStdOutInterval) {
|
if (data.status === 'successful' || data.status === 'failed' || data.status === 'error' || data.status === 'canceled') {
|
||||||
// window.clearInterval($rootScope.jobStdOutInterval);
|
if ($rootScope.jobStdOutInterval) {
|
||||||
// }
|
window.clearInterval($rootScope.jobStdOutInterval);
|
||||||
// }
|
}
|
||||||
if(stdout_url) {
|
|
||||||
$scope.$emit('LoadStdout');
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.error(function(data, status) {
|
.error(function(data, status) {
|
||||||
@@ -267,88 +145,17 @@ export function JobStdoutController ($location, $log, $rootScope, $scope, $compi
|
|||||||
msg: 'Failed to retrieve job: ' + job_id + '. GET returned: ' + status });
|
msg: 'Failed to retrieve job: ' + job_id + '. GET returned: ' + status });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO: this is currently not used but is necessary for cases where sockets
|
||||||
|
// are not available and a manual refresh trigger is needed.
|
||||||
$scope.refresh = function(){
|
$scope.refresh = function(){
|
||||||
if (loaded_sections.length === 0) { ////this if statement for refresh
|
$scope.$emit('LoadStdout');
|
||||||
$scope.$emit('LoadStdout');
|
|
||||||
}
|
|
||||||
else if (live_event_processing) {
|
|
||||||
getNextSection();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.stdOutScrollToTop = function() {
|
// Click binding for the expand/collapse button on the standard out log
|
||||||
// scroll up or back in time toward the beginning of the file
|
$scope.toggleStdoutFullscreen = function() {
|
||||||
var start, end, url;
|
$scope.stdoutFullScreen = !$scope.stdoutFullScreen;
|
||||||
if (loaded_sections.length > 0 && loaded_sections[0].start > 0) {
|
|
||||||
start = (loaded_sections[0].start - page_size > 0) ? loaded_sections[0].start - page_size : 0;
|
|
||||||
end = loaded_sections[0].start - 1;
|
|
||||||
}
|
|
||||||
else if (loaded_sections.length === 0) {
|
|
||||||
start = 0;
|
|
||||||
end = page_size;
|
|
||||||
}
|
|
||||||
if (start !== undefined && end !== undefined) {
|
|
||||||
$('#stdoutMoreRowsTop').fadeIn();
|
|
||||||
url = stdout_url + '?format=json&start_line=' + start + '&end_line=' + end;
|
|
||||||
Rest.setUrl(url);
|
|
||||||
Rest.get()
|
|
||||||
.success( function(data) {
|
|
||||||
//var currentPos = $('#pre-container').scrollTop();
|
|
||||||
var newSH, oldSH = $('#pre-container').prop('scrollHeight'),
|
|
||||||
st = $('#pre-container').scrollTop();
|
|
||||||
|
|
||||||
$('#pre-container-content').prepend(data.content);
|
|
||||||
|
|
||||||
newSH = $('#pre-container').prop('scrollHeight');
|
|
||||||
$('#pre-container').scrollTop(newSH - oldSH + st);
|
|
||||||
|
|
||||||
loaded_sections.unshift({
|
|
||||||
start: (data.range.start < 0) ? 0 : data.range.start,
|
|
||||||
end: data.range.end
|
|
||||||
});
|
|
||||||
current_range = data.range;
|
|
||||||
$('#stdoutMoreRowsTop').fadeOut(400);
|
|
||||||
})
|
|
||||||
.error(function(data, status) {
|
|
||||||
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
|
|
||||||
msg: 'Failed to retrieve stdout for job: ' + job_id + '. GET returned: ' + status });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function getNextSection() {
|
|
||||||
// get the next range of data from the API
|
|
||||||
var start = loaded_sections[loaded_sections.length - 1].end, url;
|
|
||||||
url = stdout_url + '?format=json&start_line=' + start + '&end_line=' + (start + page_size);
|
|
||||||
$('#stdoutMoreRowsBottom').fadeIn();
|
|
||||||
Rest.setUrl(url);
|
|
||||||
Rest.get()
|
|
||||||
.success( function(data) {
|
|
||||||
if ($('#pre-container-content').html() === "Waiting for results...") {
|
|
||||||
$('#pre-container-content').html(data.content);
|
|
||||||
} else {
|
|
||||||
$('#pre-container-content').append(data.content);
|
|
||||||
}
|
|
||||||
loaded_sections.push({
|
|
||||||
start: (data.range.start < 0) ? 0 : data.range.start,
|
|
||||||
end: data.range.end
|
|
||||||
});
|
|
||||||
//console.log('loaded start: ' + data.range.start + ' end: ' + data.range.end);
|
|
||||||
//console.log(data.content);
|
|
||||||
if (should_apply_live_events) {
|
|
||||||
// if user has not disabled live event view by scrolling upward, then scroll down to the new content
|
|
||||||
current_range = data.range;
|
|
||||||
auto_scroll_down = true; // prevent auto load from happening
|
|
||||||
$('#pre-container').scrollTop($('#pre-container').prop("scrollHeight"));
|
|
||||||
}
|
|
||||||
$('#stdoutMoreRowsBottom').fadeOut(400);
|
|
||||||
})
|
|
||||||
.error(function(data, status) {
|
|
||||||
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
|
|
||||||
msg: 'Failed to retrieve stdout for job: ' + job_id + '. GET returned: ' + status });
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JobStdoutController.$inject = [ '$location', '$log', '$rootScope', '$scope', '$compile', '$state', '$stateParams', 'ClearScope', 'GetBasePath', 'Wait', 'Rest', 'ProcessErrors', 'ModelToBasePathKey', 'Empty', 'GetChoices', 'LookUpName'];
|
JobStdoutController.$inject = [ '$rootScope', '$scope', '$state', '$stateParams', 'ClearScope', 'GetBasePath', 'Rest', 'ProcessErrors', 'Empty', 'GetChoices', 'LookUpName'];
|
||||||
|
|||||||
Reference in New Issue
Block a user