From 540f10bfbcf5876ea1b670ed87320619bed438e1 Mon Sep 17 00:00:00 2001 From: Chris Houseknecht Date: Tue, 24 Jun 2014 11:32:45 -0400 Subject: [PATCH] Job stdout refactor More infinite scrolling. Mostly seems to be working. However, we're not removing content, just continually adding as user scrolls back up. --- awx/ui/static/js/app.js | 4 + awx/ui/static/js/controllers/JobStdout.js | 126 +++++++++++++++++++--- awx/ui/static/less/stdout.less | 9 ++ awx/ui/static/partials/job_stdout.html | 1 + 4 files changed, 126 insertions(+), 14 deletions(-) diff --git a/awx/ui/static/js/app.js b/awx/ui/static/js/app.js index dff0feb89d..da01f3308e 100644 --- a/awx/ui/static/js/app.js +++ b/awx/ui/static/js/app.js @@ -474,6 +474,10 @@ angular.module('Tower', [ window.clearInterval($rootScope.jobDetailInterval); } + if ($rootScope.jobStdOutInterval) { + window.clearInterval($rootScope.jobStdOutInterval); + } + // On each navigation request, check that the user is logged in if (!/^\/(login|logout)/.test($location.path())) { // capture most recent URL, excluding login/logout diff --git a/awx/ui/static/js/controllers/JobStdout.js b/awx/ui/static/js/controllers/JobStdout.js index 084af3ea3a..a61b578d2d 100644 --- a/awx/ui/static/js/controllers/JobStdout.js +++ b/awx/ui/static/js/controllers/JobStdout.js @@ -16,7 +16,12 @@ function JobStdoutController ($log, $rootScope, $scope, $compile, $routeParams, stdout_url, current_range, event_socket, - first_time=0; + first_time=0, + loaded_sections = [], + event_queue = 0, + auto_scroll_down=true, + live_event_processing = true, + page_size = 500; event_socket = Socket({ scope: $scope, @@ -29,25 +34,67 @@ function JobStdoutController ($log, $rootScope, $scope, $compile, $routeParams, event_socket.on("job_events-" + job_id, function() { if (api_complete) { - $scope.$emit('LoadStdout'); + event_queue++; } }); + if ($rootScope.removeJobStatusChange) { + $rootScope.removeJobStatusChange(); + } + $rootScope.removeJobStatusChange = $rootScope.$on('JobStatusChange', function(e, data) { + // if we receive a status change event for the current job indicating the job + // is finished, stop event queue processing and reload + if (parseInt(data.unified_job_id, 10) === parseInt(job_id,10)) { + $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) { + getNextSection(); + } + live_event_processing = false; + } + } + }); + + $rootScope.jobStdOutInterval = setInterval( function() { + // limit the scrolling to every 5 seconds + $log.debug('checking for stdout...'); + if (event_queue > 15) { + if (loaded_sections.length === 0) { + $log.debug('calling LoadStdout'); + $scope.$emit('LoadStdout'); + } + else { + $log.debug('calling getNextSection'); + getNextSection(); + } + event_queue = 0; + } + }, 5000); + if ($scope.removeLoadStdout) { $scope.removeLoadStdout(); } $scope.removeLoadStdout = $scope.$on('LoadStdout', function() { - Rest.setUrl(stdout_url + '?format=json&start_line=-500'); + Rest.setUrl(stdout_url + '?format=json&start_line=-' + page_size); Rest.get() .success(function(data) { - api_complete = true; Wait('stop'); - $('#pre-container-content').html(data.content); - current_range = data.range; - //$('#pre-container').mCustomScrollbar("update"); - setTimeout(function() { - $('#pre-container').mCustomScrollbar("scrollTo", 'bottom'); - }, 300); + if (data.content) { + api_complete = true; + $('#pre-container-content').html(data.content); + current_range = data.range; + loaded_sections.push(data.range.start); + setTimeout(function() { + $('#pre-container').mCustomScrollbar("scrollTo", "bottom"); + }, 300); + } + else { + api_complete = true; + } }) .error(function(data, status) { ProcessErrors($scope, data, status, null, { hdr: 'Error!', @@ -56,7 +103,7 @@ function JobStdoutController ($log, $rootScope, $scope, $compile, $routeParams, }); function resizeToFit() { - available_height = $(window).height() - $('#main-menu-container .navbar').outerHeight() - + available_height = $(window).height() - $('#main-menu-container .navbar').outerHeight() - $('#job-status').outerHeight() - $('#breadcrumb-container').outerHeight() - 20; $('#pre-container').height(available_height); $('#pre-container').mCustomScrollbar("update"); @@ -72,6 +119,9 @@ function JobStdoutController ($log, $rootScope, $scope, $compile, $routeParams, .success(function(data) { $scope.job = data; stdout_url = data.related.stdout; + if (data.status === 'successful' || data.status === 'failed' || data.status === 'error' || data.status === 'canceled') { + live_event_processing = false; + } $scope.$emit('LoadStdout'); }) .error(function(data, status) { @@ -81,14 +131,39 @@ function JobStdoutController ($log, $rootScope, $scope, $compile, $routeParams, $scope.onTotalScroll = function() { - $log.debug('Total scroll!'); + // scroll forward or into the future toward the end of the file + var start = current_range.end + 1, url; + if ((!live_event_processing) && (!auto_scroll_down) && loaded_sections.indexOf(start) < 0) { + url = stdout_url + '?format=json&start_line=' + start + '&end_line=' + (current_range.start + page_size); + first_time++; + Wait('start'); + Rest.setUrl(url); + Rest.get() + .success( function(data) { + Wait('stop'); + if (data.content) { + $('#pre-container-content').append(data.content); + loaded_sections.push(data.range.start); + current_range = data.range; + } + //$("#pre-container").mCustomScrollbar("scrollTo", "bottom", {scrollInertia:0}); + //$('#pre-container').mCustomScrollbar("update"); + }) + .error(function(data, status) { + ProcessErrors($scope, data, status, null, { hdr: 'Error!', + msg: 'Failed to retrieve stdout for job: ' + job_id + '. GET returned: ' + status }); + }); + } + else { + auto_scroll_down = false; + } }; $scope.onTotalScrollBack = function() { // scroll up or back in time toward the beginning of the file - if (current_range.start > 0) { + if ((!live_event_processing) && current_range.start > 0) { //we haven't hit the top yet - var start = (current_range.start < 500) ? 0 : current_range.start - 500, + var start = (current_range.start < page_size) ? 0 : current_range.start - page_size, url = stdout_url + '?format=json&start_line=' + start + '&end_line=' + (current_range.start - 1); first_time++; Wait('start'); @@ -99,6 +174,7 @@ function JobStdoutController ($log, $rootScope, $scope, $compile, $routeParams, var oldContentHeight, heightDiff; oldContentHeight=$("#pre-container .mCSB_container").innerHeight(); $('#pre-container-content').prepend(data.content); + loaded_sections.unshift(data.range.start); current_range = data.range; heightDiff=$("#pre-container .mCSB_container").innerHeight() - oldContentHeight; if (first_time === 1) { @@ -113,6 +189,28 @@ function JobStdoutController ($log, $rootScope, $scope, $compile, $routeParams, }); } }; + + function getNextSection() { + var start = current_range.end + 1, url; + if (loaded_sections.indexOf(start) < 0) { + url = stdout_url + '?format=json&start_line=' + start + '&end_line=' + (current_range.start + page_size); + Wait('start'); + Rest.setUrl(url); + Rest.get() + .success( function(data) { + Wait('stop'); + $('#pre-container-content').append(data.content); + loaded_sections.push(data.range.start); + current_range = data.range; + $("#pre-container").mCustomScrollbar("scrollTo", "bottom", {scrollInertia:0}); + }) + .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 = [ '$log', '$rootScope', '$scope', '$compile', '$routeParams', 'ClearScope', 'GetBasePath', 'Wait', 'Rest', 'ProcessErrors', diff --git a/awx/ui/static/less/stdout.less b/awx/ui/static/less/stdout.less index 5e80a84392..a2f7ff1b46 100644 --- a/awx/ui/static/less/stdout.less +++ b/awx/ui/static/less/stdout.less @@ -5,6 +5,15 @@ * */ + #jobs-stdout { + #job-status { + label { + margin-right: 15px; + } + margin-bottom: 15px; + } + } + .body_foreground { color: #AAAAAA; } .body_background { background-color: @black; } diff --git a/awx/ui/static/partials/job_stdout.html b/awx/ui/static/partials/job_stdout.html index 0cef385aad..c0275c8455 100644 --- a/awx/ui/static/partials/job_stdout.html +++ b/awx/ui/static/partials/job_stdout.html @@ -14,6 +14,7 @@
+
{{ job.status }}