mirror of
https://github.com/ansible/awx.git
synced 2026-03-03 17:51:06 -03:30
job results cleanup 2 of 2
Clean up of standard out directive code
This commit is contained in:
committed by
jaredevantabor
parent
96952e7841
commit
93f5b19685
@@ -13,60 +13,139 @@ export default [ 'templateUrl', '$timeout', '$location', '$anchorScroll',
|
|||||||
restrict: 'E',
|
restrict: 'E',
|
||||||
link: function(scope, element) {
|
link: function(scope, element) {
|
||||||
|
|
||||||
|
// utility function used to find the top visible line and
|
||||||
|
// parent header in the pane
|
||||||
|
//
|
||||||
|
// note that while this function is called when in mobile width
|
||||||
|
// the line anchor is not displayed in the css so calls
|
||||||
|
// to lineAnchor do nothing
|
||||||
var findTopLines = function() {
|
var findTopLines = function() {
|
||||||
scope.visibleItems = "";
|
|
||||||
var $container = $('.JobResultsStdOut-stdoutContainer');
|
var $container = $('.JobResultsStdOut-stdoutContainer');
|
||||||
|
|
||||||
|
// get the first visible line's head element
|
||||||
|
var getHeadElement = function (line) {
|
||||||
|
var lineHasHeaderClass = !!(line
|
||||||
|
.hasClass("header_play") ||
|
||||||
|
line.hasClass("header_task"));
|
||||||
|
var lineClassList;
|
||||||
|
var lineUUIDClass;
|
||||||
|
|
||||||
|
if (lineHasHeaderClass) {
|
||||||
|
// find head element when the first visible
|
||||||
|
// line is a header
|
||||||
|
|
||||||
|
lineClassList = line.attr("class")
|
||||||
|
.split(" ");
|
||||||
|
|
||||||
|
// get the header class w task uuid...
|
||||||
|
lineUUIDClass = lineClassList
|
||||||
|
.filter(n => n
|
||||||
|
.indexOf("header_task_") > -1)[0];
|
||||||
|
|
||||||
|
// ...if that doesn't exist get the one
|
||||||
|
// w play uuid
|
||||||
|
if (!lineUUIDClass) {
|
||||||
|
lineUUIDClass = lineClassList
|
||||||
|
.filter(n => n.
|
||||||
|
indexOf("header_play_") > -1)[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the header line (not their might
|
||||||
|
// be more than one, so get the one with
|
||||||
|
// the actual header class)
|
||||||
|
//
|
||||||
|
// TODO it might be better in this case to just
|
||||||
|
// return `line` (less jumping with a cowsay
|
||||||
|
// case)
|
||||||
|
return $(".actual_header." +
|
||||||
|
lineUUIDClass);
|
||||||
|
} else {
|
||||||
|
// find head element when the first visible
|
||||||
|
// line is not a header
|
||||||
|
|
||||||
|
lineClassList = line.attr("class")
|
||||||
|
.split(" ");
|
||||||
|
|
||||||
|
// get the class w task uuid...
|
||||||
|
lineUUIDClass = lineClassList
|
||||||
|
.filter(n => n
|
||||||
|
.indexOf("task_") > -1)[0];
|
||||||
|
|
||||||
|
// ...if that doesn't exist get the one
|
||||||
|
// w play uuid
|
||||||
|
if (!lineUUIDClass) {
|
||||||
|
lineUUIDClass = lineClassList
|
||||||
|
.filter(n => n
|
||||||
|
.indexOf("play_") > -1)[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the header line (not their might
|
||||||
|
// be more than one, so get the one with
|
||||||
|
// the actual header class)
|
||||||
|
return $(".actual_header.header_" +
|
||||||
|
lineUUIDClass);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
var visItem,
|
var visItem,
|
||||||
parentItem;
|
parentItem;
|
||||||
$container.find('.JobResultsStdOut-aLineOfStdOut').each( function () {
|
|
||||||
var $this = $(this);
|
|
||||||
if ( $this.position().top + $this.height() > $container.position().top &&
|
|
||||||
$this.position().top < ($container.height() + $container.position().top) ) {
|
|
||||||
visItem = parseInt($($this.children()[0]).text());
|
|
||||||
|
|
||||||
var $head,
|
var containerHeight = $container.height();
|
||||||
classList,
|
var containerTop = $container.position().top;
|
||||||
header;
|
var containerNetHeight = containerHeight + containerTop;
|
||||||
if ($this.hasClass("header_play") || $this.hasClass("header_task")) {
|
|
||||||
classList = $this.attr("class")
|
|
||||||
.split(" ");
|
|
||||||
header = classList
|
|
||||||
.filter(n => n.indexOf("header_task_") > -1)[0];
|
|
||||||
if (!header) {
|
|
||||||
header = classList
|
|
||||||
.filter(n => n.indexOf("header_play_") > -1)[0];
|
|
||||||
}
|
|
||||||
$head = $(".actual_header." + header);
|
|
||||||
} else {
|
|
||||||
classList = $this.attr("class")
|
|
||||||
.split(" ");
|
|
||||||
header = classList
|
|
||||||
.filter(n => n.indexOf("task_") > -1)[0];
|
|
||||||
if (!header) {
|
|
||||||
header = classList
|
|
||||||
.filter(n => n.indexOf("play_") > -1)[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
$head = $(".actual_header.header_" + header);
|
// iterate through each line of standard out
|
||||||
}
|
$container.find('.JobResultsStdOut-aLineOfStdOut')
|
||||||
parentItem = parseInt($($head.children()[0]).text());
|
.each( function () {
|
||||||
return false;
|
var $this = $(this);
|
||||||
|
|
||||||
|
var lineHeight = $this.height();
|
||||||
|
var lineTop = $this.position().top;
|
||||||
|
var lineNetHeight = lineHeight + lineTop;
|
||||||
|
|
||||||
|
// check to see if the line is the first visible
|
||||||
|
// line in the viewport...
|
||||||
|
if (lineNetHeight > containerTop &&
|
||||||
|
lineTop < containerNetHeight) {
|
||||||
|
|
||||||
|
// ...if it is, return the line number
|
||||||
|
// for this line
|
||||||
|
visItem = parseInt($($this
|
||||||
|
.children()[0])
|
||||||
|
.text());
|
||||||
|
|
||||||
|
// as well as the line number for it's
|
||||||
|
// closest parent header line
|
||||||
|
var $head = getHeadElement($this);
|
||||||
|
parentItem = parseInt($($head
|
||||||
|
.children()[0])
|
||||||
|
.text());
|
||||||
|
|
||||||
|
// stop iterating over the standard out
|
||||||
|
// lines once the first one has been
|
||||||
|
// found
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
scope.visLine = visItem;
|
|
||||||
scope.parentVisLine = parentItem;
|
return {
|
||||||
|
visLine: visItem,
|
||||||
|
parentVisLine: parentItem
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// find when window changes from mobile to desktop width
|
// find if window is initially mobile or desktop width
|
||||||
if (window.innerWidth < 1200) {
|
if (window.innerWidth <= 1200) {
|
||||||
scope.isMobile = true;
|
scope.isMobile = true;
|
||||||
} else {
|
} else {
|
||||||
scope.isMobile = false;
|
scope.isMobile = false;
|
||||||
}
|
}
|
||||||
$( window ).resize(function() {
|
// watch changes to the window size
|
||||||
if (window.innerWidth < 1200 && !scope.isMobile) {
|
$(window).resize(function() {
|
||||||
|
// and update the isMobile var accordingly
|
||||||
|
if (window.innerWidth <= 1200 && !scope.isMobile) {
|
||||||
scope.isMobile = true;
|
scope.isMobile = true;
|
||||||
} else if (window.innerWidth >= 1200 & scope.isMobile) {
|
} else if (window.innerWidth > 1200 & scope.isMobile) {
|
||||||
scope.isMobile = false;
|
scope.isMobile = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -75,55 +154,71 @@ export default [ 'templateUrl', '$timeout', '$location', '$anchorScroll',
|
|||||||
|
|
||||||
var initScrollTop = function() {
|
var initScrollTop = function() {
|
||||||
lastScrollTop = 0;
|
lastScrollTop = 0;
|
||||||
}
|
};
|
||||||
var scrollWatcher = function() {
|
var scrollWatcher = function() {
|
||||||
var st = $(this).scrollTop(),
|
var st = $(this).scrollTop();
|
||||||
fullHeight;
|
var netScroll = st + $(this).innerHeight();
|
||||||
|
var fullHeight;
|
||||||
|
|
||||||
if (st < lastScrollTop){
|
if (st < lastScrollTop){
|
||||||
// user up scrolled, so disengage follow
|
// user up scrolled, so disengage follow
|
||||||
scope.followEngaged = false;
|
scope.followEngaged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scope.isMobile) {
|
if (scope.isMobile) {
|
||||||
|
// for mobile the height is the body of the entire
|
||||||
|
// page
|
||||||
fullHeight = $("body").height();
|
fullHeight = $("body").height();
|
||||||
} else {
|
} else {
|
||||||
|
// for desktop the height is the body of the
|
||||||
|
// stdoutContainer, minus the "^ TOP" indicator
|
||||||
fullHeight = $(this)[0].scrollHeight - 25;
|
fullHeight = $(this)[0].scrollHeight - 25;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($(this).scrollTop() + $(this).innerHeight() >=
|
if(netScroll >= fullHeight) {
|
||||||
fullHeight) {
|
|
||||||
// user scrolled all the way to bottom, so engage
|
// user scrolled all the way to bottom, so engage
|
||||||
// follow
|
// follow
|
||||||
scope.followEngaged = true;
|
scope.followEngaged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// pane is now overflowed, show top indicator
|
// pane is now overflowed, show top indicator.
|
||||||
if (st > 0 && !scope.isMobile) {
|
if (st > 0) {
|
||||||
scope.stdoutOverflowed = true;
|
scope.stdoutOverflowed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastScrollTop = st;
|
lastScrollTop = st;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
// update scroll watchers when isMobile changes based on
|
||||||
|
// window resize
|
||||||
scope.$watch('isMobile', function(val) {
|
scope.$watch('isMobile', function(val) {
|
||||||
if (val === true) {
|
if (val === true) {
|
||||||
// make sure ^ TOP always shown
|
// make sure ^ TOP always shown for mobile
|
||||||
scope.stdoutOverflowed = true;
|
scope.stdoutOverflowed = true;
|
||||||
|
|
||||||
initScrollTop();
|
// unbind scroll watcher on standard out container
|
||||||
$(".JobResultsStdOut-stdoutContainer")
|
$(".JobResultsStdOut-stdoutContainer")
|
||||||
.unbind('scroll');
|
.unbind('scroll');
|
||||||
|
|
||||||
|
// init scroll watcher on window
|
||||||
|
initScrollTop();
|
||||||
$(window).on('scroll', scrollWatcher);
|
$(window).on('scroll', scrollWatcher);
|
||||||
|
|
||||||
} else if (val === false) {
|
} else if (val === false) {
|
||||||
initScrollTop();
|
// unbind scroll watcher on window
|
||||||
$(window).unbind('scroll');
|
$(window).unbind('scroll');
|
||||||
|
|
||||||
|
// init scroll watcher on standard out container
|
||||||
|
initScrollTop();
|
||||||
$(".JobResultsStdOut-stdoutContainer").on('scroll',
|
$(".JobResultsStdOut-stdoutContainer").on('scroll',
|
||||||
scrollWatcher);
|
scrollWatcher);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// called to scroll to follow anchor
|
||||||
scope.followScroll = function() {
|
scope.followScroll = function() {
|
||||||
|
// a double-check to make sure the follow anchor is at
|
||||||
|
// the bottom of the standard out container
|
||||||
$(".JobResultsStdOut-followAnchor")
|
$(".JobResultsStdOut-followAnchor")
|
||||||
.appendTo(".JobResultsStdOut-stdoutContainer");
|
.appendTo(".JobResultsStdOut-stdoutContainer");
|
||||||
|
|
||||||
@@ -131,11 +226,19 @@ export default [ 'templateUrl', '$timeout', '$location', '$anchorScroll',
|
|||||||
$anchorScroll();
|
$anchorScroll();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// called to scroll to top of standard out (when "^ TOP" is
|
||||||
|
// clicked)
|
||||||
scope.toTop = function() {
|
scope.toTop = function() {
|
||||||
$location.hash('topAnchor');
|
$location.hash('topAnchor');
|
||||||
$anchorScroll();
|
$anchorScroll();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// called to scroll to the current line anchor
|
||||||
|
// when expand all/collapse all/filtering is engaged
|
||||||
|
//
|
||||||
|
// note that while this function can be called when in mobile
|
||||||
|
// width the line anchor is not displayed in the css so those
|
||||||
|
// calls do nothing
|
||||||
scope.lineAnchor = function() {
|
scope.lineAnchor = function() {
|
||||||
$location.hash('lineAnchor');
|
$location.hash('lineAnchor');
|
||||||
$anchorScroll();
|
$anchorScroll();
|
||||||
@@ -144,10 +247,12 @@ export default [ 'templateUrl', '$timeout', '$location', '$anchorScroll',
|
|||||||
// if following becomes active, go ahead and get to the bottom
|
// if following becomes active, go ahead and get to the bottom
|
||||||
// of the standard out pane
|
// of the standard out pane
|
||||||
scope.$watch('followEngaged', function(val) {
|
scope.$watch('followEngaged', function(val) {
|
||||||
|
// scroll to follow point if followEngaged is true
|
||||||
if (val) {
|
if (val) {
|
||||||
scope.followScroll();
|
scope.followScroll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set up tooltip changes for not finsihed job
|
||||||
if (!scope.jobFinished) {
|
if (!scope.jobFinished) {
|
||||||
if (val) {
|
if (val) {
|
||||||
scope.followTooltip = "Currently following standard out as it comes in. Click to unfollow.";
|
scope.followTooltip = "Currently following standard out as it comes in. Click to unfollow.";
|
||||||
@@ -157,73 +262,121 @@ export default [ 'templateUrl', '$timeout', '$location', '$anchorScroll',
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// follow button ng-click function
|
||||||
scope.followToggleClicked = function() {
|
scope.followToggleClicked = function() {
|
||||||
if (scope.jobFinished) {
|
if (scope.jobFinished) {
|
||||||
|
// when the job is finished engage followScroll
|
||||||
scope.followScroll();
|
scope.followScroll();
|
||||||
} else {
|
} else {
|
||||||
|
// when the job is not finished toggle followEngaged
|
||||||
|
// which is watched above
|
||||||
scope.followEngaged = !scope.followEngaged;
|
scope.followEngaged = !scope.followEngaged;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// expand all/collapse all ng-click function
|
||||||
scope.toggleAllStdout = function(type) {
|
scope.toggleAllStdout = function(type) {
|
||||||
findTopLines();
|
// find the top visible line in the container currently,
|
||||||
|
// as well as the header parent of that line
|
||||||
|
var topLines = findTopLines();
|
||||||
|
|
||||||
if (type === 'expand') {
|
if (type === 'expand') {
|
||||||
$(".line_num_" + scope.visLine)
|
// for expand prepend the lineAnchor to the visible
|
||||||
|
// line
|
||||||
|
$(".line_num_" + topLines.visLine)
|
||||||
.prepend($("#lineAnchor"));
|
.prepend($("#lineAnchor"));
|
||||||
} else {
|
} else {
|
||||||
$(".line_num_" + scope.parentVisLine)
|
// for collapse prepent the lineAnchor to the
|
||||||
|
// visible line's parent header
|
||||||
|
$(".line_num_" + topLines.parentVisLine)
|
||||||
.prepend($("#lineAnchor"));
|
.prepend($("#lineAnchor"));
|
||||||
}
|
}
|
||||||
|
|
||||||
var expandClass;
|
var expandClass;
|
||||||
if (type === 'expand') {
|
if (type === 'expand') {
|
||||||
|
// for expand all, you'll need to find all the
|
||||||
|
// collapsed headers to expand them
|
||||||
expandClass = "fa-caret-right";
|
expandClass = "fa-caret-right";
|
||||||
} else {
|
} else {
|
||||||
|
// for collapse all, you'll need to find all the
|
||||||
|
// expanded headers to collapse them
|
||||||
expandClass = "fa-caret-down";
|
expandClass = "fa-caret-down";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// find all applicable task headers that need to be
|
||||||
|
// toggled
|
||||||
element.find(".expanderizer--task."+expandClass)
|
element.find(".expanderizer--task."+expandClass)
|
||||||
.each((i, val) => {
|
.each((i, val) => {
|
||||||
|
// and trigger their expansion/collapsing
|
||||||
$timeout(function(){
|
$timeout(function(){
|
||||||
|
// TODO change to a direct call of the
|
||||||
|
// toggleLine function
|
||||||
angular.element(val).trigger('click');
|
angular.element(val).trigger('click');
|
||||||
|
// TODO only call lineAnchor for those
|
||||||
|
// that are above the first visible line
|
||||||
scope.lineAnchor();
|
scope.lineAnchor();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// find all applicable play headers that need to be
|
||||||
|
// toggled
|
||||||
element.find(".expanderizer--play."+expandClass)
|
element.find(".expanderizer--play."+expandClass)
|
||||||
.each((i, val) => {
|
.each((i, val) => {
|
||||||
|
// for collapse all, only collapse play
|
||||||
|
// headers that do not have children task
|
||||||
|
// headers
|
||||||
if(angular.element("." +
|
if(angular.element("." +
|
||||||
angular.element(val).attr("data-uuid"))
|
angular.element(val).attr("data-uuid"))
|
||||||
.find(".expanderizer--task")
|
.find(".expanderizer--task")
|
||||||
.length === 0 ||
|
.length === 0 ||
|
||||||
type !== 'collapse') {
|
type !== 'collapse') {
|
||||||
|
|
||||||
|
// trigger their expansion/
|
||||||
|
// collapsing
|
||||||
$timeout(function(){
|
$timeout(function(){
|
||||||
|
// TODO change to a direct
|
||||||
|
// call of the
|
||||||
|
// toggleLine function
|
||||||
angular.element(val)
|
angular.element(val)
|
||||||
.trigger('click');
|
.trigger('click');
|
||||||
|
// TODO only call lineAnchor
|
||||||
|
// for those that are above
|
||||||
|
// the first visible line
|
||||||
scope.lineAnchor();
|
scope.lineAnchor();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// expand/collapse triangle ng-click function
|
||||||
scope.toggleLine = function($event, id) {
|
scope.toggleLine = function($event, id) {
|
||||||
|
// if the section is currently expanded
|
||||||
if ($($event.currentTarget).hasClass("fa-caret-down")) {
|
if ($($event.currentTarget).hasClass("fa-caret-down")) {
|
||||||
|
// hide all the children lines
|
||||||
$(id).hide();
|
$(id).hide();
|
||||||
|
|
||||||
|
// and change the triangle for the header to collapse
|
||||||
$($event.currentTarget)
|
$($event.currentTarget)
|
||||||
.removeClass("fa-caret-down");
|
.removeClass("fa-caret-down");
|
||||||
$($event.currentTarget)
|
$($event.currentTarget)
|
||||||
.addClass("fa-caret-right");
|
.addClass("fa-caret-right");
|
||||||
} else {
|
} else {
|
||||||
|
// if the section is currently collapsed
|
||||||
|
|
||||||
|
// show all the children lines
|
||||||
$(id).show();
|
$(id).show();
|
||||||
|
|
||||||
|
// and change the triangle for the header to expanded
|
||||||
$($event.currentTarget)
|
$($event.currentTarget)
|
||||||
.removeClass("fa-caret-right");
|
.removeClass("fa-caret-right");
|
||||||
$($event.currentTarget)
|
$($event.currentTarget)
|
||||||
.addClass("fa-caret-down");
|
.addClass("fa-caret-down");
|
||||||
|
|
||||||
|
// if the section you expanded is a play
|
||||||
if ($($event.currentTarget)
|
if ($($event.currentTarget)
|
||||||
.hasClass("expanderizer--play")) {
|
.hasClass("expanderizer--play")) {
|
||||||
|
// find all children task headers and
|
||||||
|
// expand them too
|
||||||
$("." + $($event.currentTarget)
|
$("." + $($event.currentTarget)
|
||||||
.attr("data-uuid"))
|
.attr("data-uuid"))
|
||||||
.find(".expanderizer--task")
|
.find(".expanderizer--task")
|
||||||
@@ -231,6 +384,9 @@ export default [ 'templateUrl', '$timeout', '$location', '$anchorScroll',
|
|||||||
if ($(val)
|
if ($(val)
|
||||||
.hasClass("fa-caret-right")) {
|
.hasClass("fa-caret-right")) {
|
||||||
$timeout(function(){
|
$timeout(function(){
|
||||||
|
// TODO change to a
|
||||||
|
// direct call of the
|
||||||
|
// toggleLine function
|
||||||
angular.element(val)
|
angular.element(val)
|
||||||
.trigger('click');
|
.trigger('click');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -82,14 +82,21 @@ export default ['$log', function($log){
|
|||||||
// play header classes
|
// play header classes
|
||||||
string += " header_play";
|
string += " header_play";
|
||||||
string += " header_play_" + event.event_data.play_uuid;
|
string += " header_play_" + event.event_data.play_uuid;
|
||||||
if (line) {
|
|
||||||
|
// give the actual header class to the line with the
|
||||||
|
// actual header info (think cowsay)
|
||||||
|
if (line.indexOf("PLAY") > -1) {
|
||||||
string += " actual_header";
|
string += " actual_header";
|
||||||
}
|
}
|
||||||
} else if (event.event_name === "playbook_on_task_start") {
|
} else if (event.event_name === "playbook_on_task_start") {
|
||||||
// task header classes
|
// task header classes
|
||||||
string += " header_task";
|
string += " header_task";
|
||||||
string += " header_task_" + event.event_data.task_uuid;
|
string += " header_task_" + event.event_data.task_uuid;
|
||||||
if (line) {
|
|
||||||
|
// give the actual header class to the line with the
|
||||||
|
// actual header info (think cowsay)
|
||||||
|
if (line.indexOf("TASK") > -1 ||
|
||||||
|
line.indexOf("RUNNING HANDLER") > -1) {
|
||||||
string += " actual_header";
|
string += " actual_header";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user