mirror of
https://github.com/ansible/awx.git
synced 2026-01-13 02:50:02 -03:30
all things scroll following and anchoring
This commit is contained in:
parent
1c907a1f07
commit
c94d86206d
@ -85,6 +85,24 @@
|
||||
color: @default-interface-txt;
|
||||
}
|
||||
|
||||
.JobResultsStdOut-followButton.is-engaged {
|
||||
background-color: @default-link;
|
||||
color: @default-bg;
|
||||
}
|
||||
|
||||
.JobResultsStdOut-followButton.is-engaged .JobResultsStdOut-followIcon {
|
||||
color: @default-bg;
|
||||
}
|
||||
|
||||
.JobResultsStdOut-followButton.is-engaged:hover {
|
||||
background-color: @default-icon;
|
||||
}
|
||||
|
||||
.JobResultsStdOut-followButton.is-engaged:hover .JobResultsStdOut-followIcon,
|
||||
.JobResultsStdOut-followButton.is-engaged .JobResultsStdOut-followIcon:hover {
|
||||
color: @default-border;
|
||||
}
|
||||
|
||||
.JobResultsStdOut-stdoutContainer {
|
||||
height: ~"calc(100% - 48px)";
|
||||
background-color: @default-no-items-bord;
|
||||
@ -167,3 +185,10 @@
|
||||
width: 70px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.foo {
|
||||
margin-right: auto;
|
||||
margin-top: 8px;
|
||||
margin-left: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@ -5,14 +5,132 @@
|
||||
*************************************************/
|
||||
|
||||
// import hostStatusBarController from './host-status-bar.controller';
|
||||
export default [ 'templateUrl', '$timeout',
|
||||
function(templateUrl, $timeout) {
|
||||
export default [ 'templateUrl', '$timeout', '$location', '$anchorScroll', '$log',
|
||||
function(templateUrl, $timeout, $location, $anchorScroll, $log) {
|
||||
return {
|
||||
scope: false,
|
||||
templateUrl: templateUrl('job-results/job-results-stdout/job-results-stdout'),
|
||||
restrict: 'E',
|
||||
link: function(scope, element, attrs) {
|
||||
link: function(scope, element) {
|
||||
|
||||
var findTopLines = function() {
|
||||
scope.visibleItems = "";
|
||||
var $container = $('.JobResultsStdOut-stdoutContainer');
|
||||
var visItem,
|
||||
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,
|
||||
classList,
|
||||
header;
|
||||
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);
|
||||
}
|
||||
parentItem = parseInt($($head.children()[0]).text());
|
||||
return false;
|
||||
}
|
||||
});
|
||||
scope.visLine = visItem;
|
||||
scope.parentVisLine = parentItem;
|
||||
scope.visibleItems = "First visible line: " + visItem + ", Parent line: " + parentItem;
|
||||
};
|
||||
|
||||
var lastScrollTop = 0;
|
||||
$(".JobResultsStdOut-stdoutContainer").on('scroll', function() {
|
||||
var st = $(this).scrollTop();
|
||||
if (st < lastScrollTop){
|
||||
// user up scrolled, so disengage follow
|
||||
scope.followEngaged = false;
|
||||
}
|
||||
|
||||
if($(this).scrollTop() + $(this).innerHeight() >=
|
||||
$(this)[0].scrollHeight) {
|
||||
// user scrolled all the way to bottom, so engage
|
||||
// follow
|
||||
scope.followEngaged = true;
|
||||
}
|
||||
|
||||
lastScrollTop = st;
|
||||
});
|
||||
|
||||
scope.followScroll = function() {
|
||||
$(".JobResultsStdOut-followAnchor")
|
||||
.appendTo(".JobResultsStdOut-stdoutContainer");
|
||||
|
||||
$location.hash('followAnchor');
|
||||
$anchorScroll();
|
||||
};
|
||||
|
||||
scope.topLineAnchor = function() {
|
||||
$location.hash('topLineAnchor');
|
||||
$anchorScroll();
|
||||
}
|
||||
|
||||
// follow button for completed job should specify that the
|
||||
// button will jump to the bottom of the standard out pane,
|
||||
// not follow lines as they come in
|
||||
if (scope.jobFinished) {
|
||||
scope.followTooltip = "Jump to last line";
|
||||
}
|
||||
|
||||
// if following becomes active, go ahead and get to the bottom
|
||||
// of the standard out pane
|
||||
scope.$watch('followEngaged', function(val) {
|
||||
if (val) {
|
||||
scope.followScroll();
|
||||
}
|
||||
|
||||
if (!scope.jobFinished) {
|
||||
if (val) {
|
||||
scope.followTooltip = "Follow standard out";
|
||||
} else {
|
||||
scope.followTooltip = "Unfollow standard out";
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
scope.followToggleClicked = function() {
|
||||
if (scope.jobFinished) {
|
||||
scope.followScroll();
|
||||
} else {
|
||||
scope.followEngaged = !scope.followEngaged;
|
||||
}
|
||||
};
|
||||
|
||||
scope.toggleAllStdout = function(type) {
|
||||
findTopLines();
|
||||
|
||||
if (type === 'expand') {
|
||||
$(".line_num_" + scope.visLine)
|
||||
.prepend($("#topLineAnchor"));
|
||||
} else {
|
||||
$(".line_num_" + scope.parentVisLine)
|
||||
.prepend($("#topLineAnchor"));
|
||||
}
|
||||
|
||||
var expandClass;
|
||||
if (type === 'expand') {
|
||||
expandClass = "fa-caret-right";
|
||||
@ -24,6 +142,7 @@ export default [ 'templateUrl', '$timeout',
|
||||
.each((i, val) => {
|
||||
$timeout(function(){
|
||||
angular.element(val).trigger('click');
|
||||
scope.topLineAnchor();
|
||||
});
|
||||
});
|
||||
|
||||
@ -38,6 +157,7 @@ export default [ 'templateUrl', '$timeout',
|
||||
$timeout(function(){
|
||||
angular.element(val)
|
||||
.trigger('click');
|
||||
scope.topLineAnchor();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@ -17,16 +17,32 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="JobResultsStdOut-toolbarStdoutColumn">
|
||||
<!-- <span class="foo">{{ visibleItems }}</span> -->
|
||||
<div class="JobResultsStdOut-followButton"
|
||||
aw-tool-tip="Follow standard out."
|
||||
data-placement="left">
|
||||
ng-class="{'is-engaged': followEngaged && !jobFinished}"
|
||||
aw-tool-tip="Follow standard out"
|
||||
data-placement="left"
|
||||
ng-click="followToggleClicked()">
|
||||
<i class="JobResultsStdOut-followIcon fa fa-arrow-down">
|
||||
</i>
|
||||
</div>
|
||||
<!-- TODO: get followTooltip watch working
|
||||
<div class="JobResultsStdOut-followButton"
|
||||
aw-tool-tip="{{followTooltip}}"
|
||||
data-tip-watch="followTooltip"
|
||||
data-placement="left"
|
||||
ng-click="followToggleClicked()">
|
||||
<i class="JobResultsStdOut-followIcon fa fa-arrow-down">
|
||||
</i>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="JobResultsStdOut-stdoutContainer">
|
||||
<div class="JobResultsStdOut-numberColumnPreload"></div>
|
||||
<div id='topLineAnchor'></div>
|
||||
<div id="followAnchor"
|
||||
class="JobResultsStdOut-followAnchor">
|
||||
</div>
|
||||
</div>
|
||||
<div class="JobResultsStdOut-footer">
|
||||
<div class="JobResultsStdOut-footerNumberColumn"></div>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
export default ['jobData', 'jobDataOptions', 'jobLabels', 'count', '$scope', 'ParseTypeChange', 'ParseVariableString', 'jobResultsService', '$rootScope', 'eventQueue', '$compile', function(jobData, jobDataOptions, jobLabels, count, $scope, ParseTypeChange, ParseVariableString, jobResultsService, $rootScope, eventQueue, $compile) {
|
||||
export default ['jobData', 'jobDataOptions', 'jobLabels', 'jobFinished', 'count', '$scope', 'ParseTypeChange', 'ParseVariableString', 'jobResultsService', '$rootScope', 'eventQueue', '$compile', function(jobData, jobDataOptions, jobLabels, jobFinished, count, $scope, ParseTypeChange, ParseVariableString, jobResultsService, $rootScope, eventQueue, $compile) {
|
||||
var getTowerLinks = function() {
|
||||
var getTowerLink = function(key) {
|
||||
if ($scope.job.related[key]) {
|
||||
@ -81,6 +81,11 @@ export default ['jobData', 'jobDataOptions', 'jobLabels', 'count', '$scope', 'Pa
|
||||
$scope.countFinished = count.countFinished;
|
||||
$scope.stdoutArr = [];
|
||||
|
||||
// if the job is still running engage following of the last line in the
|
||||
// standard out pane
|
||||
$scope.jobFinished = jobFinished;
|
||||
$scope.followEngaged = !$scope.jobFinished;
|
||||
|
||||
// EVENT STUFF BELOW
|
||||
|
||||
// just putting the event queue on scope so it can be inspected in the
|
||||
@ -121,6 +126,7 @@ export default ['jobData', 'jobDataOptions', 'jobLabels', 'count', '$scope', 'Pa
|
||||
|
||||
if (change === 'finishedTime' && !$scope.job.finished) {
|
||||
$scope.job.finished = mungedEvent.finishedTime;
|
||||
$scope.jobFinished = true;
|
||||
}
|
||||
|
||||
if (change === 'countFinished') {
|
||||
@ -136,6 +142,10 @@ export default ['jobData', 'jobDataOptions', 'jobLabels', 'count', '$scope', 'Pa
|
||||
.element(".JobResultsStdOut-stdoutContainer")
|
||||
.append($compile(mungedEvent
|
||||
.stdout)($scope));
|
||||
|
||||
if ($scope.followEngaged) {
|
||||
$scope.followScroll();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -44,6 +44,14 @@ export default {
|
||||
});
|
||||
return val.promise;
|
||||
}],
|
||||
// used to signify if job is completed or still running
|
||||
jobFinished: ['jobData', function(jobData) {
|
||||
if (jobData.finished) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}],
|
||||
// after the GET for the job, this helps us keep the status bar from
|
||||
// flashing as rest data comes in. If the job is finished and
|
||||
// there's a playbook_on_stats event, go ahead and resolve the count
|
||||
|
||||
@ -31,15 +31,23 @@ export default [function(){
|
||||
line = line.replace(/\[0m/g, '</span>');
|
||||
return line;
|
||||
},
|
||||
getCollapseClasses: function(event) {
|
||||
getCollapseClasses: function(event, line, lineNum) {
|
||||
var string = "";
|
||||
if (event.event_name === "playbook_on_play_start") {
|
||||
string += " header_play";
|
||||
string += " header_play_" + event.event_data.play_uuid;
|
||||
if (line) {
|
||||
string += " actual_header";
|
||||
}
|
||||
} else if (event.event_name === "playbook_on_task_start") {
|
||||
string += " header_task";
|
||||
string += " header_task_" + event.event_data.task_uuid;
|
||||
if (event.event_data.play_uuid) {
|
||||
string += " play_" + event.event_data.play_uuid;
|
||||
}
|
||||
if (line) {
|
||||
string += " actual_header";
|
||||
}
|
||||
} else {
|
||||
if (event.event_data.play_uuid) {
|
||||
string += " play_" + event.event_data.play_uuid;
|
||||
@ -48,7 +56,7 @@ export default [function(){
|
||||
string += " task_" + event.event_data.task_uuid;
|
||||
}
|
||||
}
|
||||
|
||||
string += " line_num_" + lineNum;
|
||||
return string;
|
||||
},
|
||||
getCollapseIcon: function(event, line) {
|
||||
@ -94,7 +102,7 @@ export default [function(){
|
||||
event.stdout.split("\r\n").slice(0, -1))
|
||||
.map(lineArr => {
|
||||
return `
|
||||
<div class="JobResultsStdOut-aLineOfStdOut${this.getCollapseClasses(event)}">
|
||||
<div class="JobResultsStdOut-aLineOfStdOut${this.getCollapseClasses(event, lineArr[1], lineArr[0])}">
|
||||
<div class="JobResultsStdOut-lineNumberColumn">${this.getCollapseIcon(event, lineArr[1])}${lineArr[0]}</div>
|
||||
<div class="JobResultsStdOut-stdoutColumn">${this.prettify(lineArr[1])}</div>
|
||||
</div>`;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user