AC-1294 reworked standard out page to support custom scroll bar. Removed use of <pre> elment by parsing the inbound HTML and isolating the style sheet and the job output. Those are now inserted into styled <div> elements, giving the UI better control. The page now listens to the web socket server and refreshes whenver an event happens for the job. On an event the <div> element refreshes and automatically scrolls to the bottom.

This commit is contained in:
chouseknecht
2014-05-21 17:29:03 -04:00
parent 35521cbdc8
commit e5ee7e5383
12 changed files with 103 additions and 46 deletions

View File

@@ -46,6 +46,8 @@ var $AnsibleConfig = {
gutters: ["CodeMirror-lint-markers"], gutters: ["CodeMirror-lint-markers"],
lint: true lint: true
} }
} },
websocket_port: 8090
}; };

View File

@@ -7,23 +7,44 @@
'use strict'; 'use strict';
function JobStdoutController ($scope, $compile, $routeParams, ClearScope, GetBasePath, Wait, Rest, ProcessErrors) { function JobStdoutController ($scope, $compile, $routeParams, ClearScope, GetBasePath, Wait, Rest, ProcessErrors, Socket) {
ClearScope(); ClearScope();
var available_height, job_id = $routeParams.id; var available_height, job_id = $routeParams.id,
api_complete = false,
stdout_url,
event_socket = Socket({
scope: $scope,
endpoint: "job_events"
});
Wait('start'); Wait('start');
event_socket.init();
event_socket.on("job_events-" + job_id, function() {
if (api_complete) {
$scope.$emit('LoadStdout');
}
});
if ($scope.removeLoadStdout) { if ($scope.removeLoadStdout) {
$scope.removeLoadStdout(); $scope.removeLoadStdout();
} }
$scope.removeLoadStdout = $scope.$on('LoadStdout', function(e, url) { $scope.removeLoadStdout = $scope.$on('LoadStdout', function() {
Rest.setUrl(url + '?format=html'); Rest.setUrl(stdout_url + '?format=html');
Rest.get() Rest.get()
.success(function(data) { .success(function(data) {
api_complete = true;
Wait('stop'); Wait('stop');
$('#stdout-iframe').attr('srcdoc', data); var doc, style, pre, parser = new DOMParser();
doc = parser.parseFromString(data, "text/html");
pre = doc.getElementsByTagName('pre');
style = doc.getElementsByTagName('style');
$('#style-sheet-container').empty().html(style[0]);
$('#pre-container-content').empty().html($(pre[0]).html());
setTimeout(function() { $('#pre-container').mCustomScrollbar("scrollTo", 'bottom'); }, 1000);
}) })
.error(function(data, status) { .error(function(data, status) {
ProcessErrors($scope, data, status, null, { hdr: 'Error!', ProcessErrors($scope, data, status, null, { hdr: 'Error!',
@@ -33,15 +54,15 @@ function JobStdoutController ($scope, $compile, $routeParams, ClearScope, GetBas
function resizeToFit() { function resizeToFit() {
available_height = $(window).height() - $('.main-menu').outerHeight() - $('#main_tabs').outerHeight() - available_height = $(window).height() - $('.main-menu').outerHeight() - $('#main_tabs').outerHeight() -
$('#breadcrumb-container').outerHeight() - $('.site-footer').outerHeight(); $('#breadcrumb-container').outerHeight() - $('.site-footer').outerHeight() * 2;
if ($(window).width() < 768) { if ($(window).width() < 768) {
available_height += 55; available_height += 55;
} }
else { else if ($(window).width() > 1240) {
available_height += 5; available_height += 5;
} }
$('#stdout-iframe').height(available_height); $('#pre-container').height(available_height);
//$('#stdout-container').mCustomScrollbar("update"); $('#pre-container').mCustomScrollbar("update");
} }
resizeToFit(); resizeToFit();
@@ -53,7 +74,8 @@ function JobStdoutController ($scope, $compile, $routeParams, ClearScope, GetBas
Rest.get() Rest.get()
.success(function(data) { .success(function(data) {
$scope.job = data; $scope.job = data;
$scope.$emit('LoadStdout', data.related.stdout); stdout_url = data.related.stdout;
$scope.$emit('LoadStdout');
}) })
.error(function(data, status) { .error(function(data, status) {
ProcessErrors($scope, data, status, null, { hdr: 'Error!', ProcessErrors($scope, data, status, null, { hdr: 'Error!',
@@ -61,4 +83,4 @@ function JobStdoutController ($scope, $compile, $routeParams, ClearScope, GetBas
}); });
} }
JobStdoutController.$inject = [ '$scope', '$compile', '$routeParams', 'ClearScope', 'GetBasePath', 'Wait', 'Rest', 'ProcessErrors' ]; JobStdoutController.$inject = [ '$scope', '$compile', '$routeParams', 'ClearScope', 'GetBasePath', 'Wait', 'Rest', 'ProcessErrors', 'Socket' ];

View File

@@ -348,6 +348,12 @@ td.actions {
font-family: Fixed, monospace; font-family: Fixed, monospace;
} }
/* Make a div or any element behave like pre. Use in conjunction with .mono-space */
.pre {
white-space: pre;
}
dd { dd {
margin-left: 15px; margin-left: 15px;
} }
@@ -1658,7 +1664,8 @@ tr td button i {
/* job stdout */ /* job stdout */
#stdout-iframe { #pre-container {
overflow: auto;
width: 100%; width: 100%;
border-radius: 4px; border-radius: 4px;
margin: 0; margin: 0;

View File

@@ -18,7 +18,7 @@ angular.module('SocketIO', ['AuthService', 'Utilities'])
host = $location.host(), host = $location.host(),
endpoint = params.endpoint, endpoint = params.endpoint,
protocol = $location.protocol(), protocol = $location.protocol(),
url = protocol + '://' + host + ':8080/socket.io/' + endpoint; url = protocol + '://' + host + ':' + $AnsibleConfig.websocket_port + '/socket.io/' + endpoint;
function getSocketTip(status) { function getSocketTip(status) {
var result = ''; var result = '';

View File

@@ -722,6 +722,7 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Job
.directive('awCustomScroll', [ function() { .directive('awCustomScroll', [ function() {
return function(scope, element, attrs) { return function(scope, element, attrs) {
var theme = (attrs.scrollTheme) ? attrs.scrollTheme : 'dark-thin';
$(element).mCustomScrollbar({ $(element).mCustomScrollbar({
advanced:{ advanced:{
updateOnContentResize: true updateOnContentResize: true
@@ -729,7 +730,7 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Job
scrollButtons: { scrollButtons: {
enable: true enable: true
}, },
theme: 'dark-thin', theme: theme,
mouseWheel: true, mouseWheel: true,
scrollInertia: 300, scrollInertia: 300,
callbacks: { callbacks: {

View File

@@ -1,6 +1,6 @@
{ {
"name": "malihu-custom-scrollbar-plugin", "name": "malihu-custom-scrollbar-plugin",
"version": "2.8.3", "version": "2.8.4",
"title": "malihu custom scrollbar plugin", "title": "malihu custom scrollbar plugin",
"description": "Custom scrollbar jQuery plugin that's fully customizable with CSS. Features vertical/horizontal scrolling, mouse-wheel support, scroll easing, adjustable scrollbar height/width, nested scrollbars, user defined callbacks etc.", "description": "Custom scrollbar jQuery plugin that's fully customizable with CSS. Features vertical/horizontal scrolling, mouse-wheel support, scroll easing, adjustable scrollbar height/width, nested scrollbars, user defined callbacks etc.",
"main": "./jquery.mCustomScrollbar.js", "main": "./jquery.mCustomScrollbar.js",
@@ -37,13 +37,13 @@
"/source_files", "/source_files",
"/js" "/js"
], ],
"_release": "2.8.3", "_release": "2.8.4",
"_resolution": { "_resolution": {
"type": "version", "type": "version",
"tag": "2.8.3", "tag": "2.8.4",
"commit": "179ced37ef972b2c44bb4b71d20a6310fa317867" "commit": "7f5be74468063f39e5f9bf0a8e2db380486c6e0e"
}, },
"_source": "git://github.com/malihu/malihu-custom-scrollbar-plugin.git", "_source": "git://github.com/malihu/malihu-custom-scrollbar-plugin.git",
"_target": "2.8.3", "_target": "2.8.4",
"_originalSource": "malihu-custom-scrollbar-plugin" "_originalSource": "malihu-custom-scrollbar-plugin"
} }

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
/* /*
== malihu jquery custom scrollbars plugin == == malihu jquery custom scrollbars plugin ==
version: 2.8.3 version: 2.8.4
author: malihu (http://manos.malihu.gr) author: malihu (http://manos.malihu.gr)
plugin home: http://manos.malihu.gr/jquery-custom-content-scroller plugin home: http://manos.malihu.gr/jquery-custom-content-scroller
*/ */
@@ -176,8 +176,9 @@ along with this program. If not, see http://www.gnu.org/licenses/lgpl.html.
percentage=maxHeight, percentage=maxHeight,
maxHeight=$this.parent().height()*percentage/100; maxHeight=$this.parent().height()*percentage/100;
} }
var paddingY=($this.innerHeight()-$this.height());
$this.css("overflow","hidden"); $this.css("overflow","hidden");
mCustomScrollBox.css("max-height",maxHeight); mCustomScrollBox.css("max-height",maxHeight-paddingY);
} }
} }
$this.mCustomScrollbar("update"); $this.mCustomScrollbar("update");
@@ -192,8 +193,12 @@ along with this program. If not, see http://www.gnu.org/licenses/lgpl.html.
if(!$this.is(".mCS_disabled") && !$this.is(".mCS_destroyed")){ if(!$this.is(".mCS_disabled") && !$this.is(".mCS_destroyed")){
var winWidth=$(window).width(),winHeight=$(window).height(); var winWidth=$(window).width(),winHeight=$(window).height();
if(currWinWidth!==winWidth || currWinHeight!==winHeight){ /*ie8 fix*/ if(currWinWidth!==winWidth || currWinHeight!==winHeight){ /*ie8 fix*/
if($this.css("max-height")!=="none" && percentage){ if($this.css("max-height")!=="none"){
mCustomScrollBox.css("max-height",$this.parent().height()*percentage/100); if(percentage){
mCustomScrollBox.css("max-height",($this.parent().height()*percentage/100)-paddingY);
}else{
mCustomScrollBox.css("max-height",(parseInt($this.css("max-height"))-paddingY));
}
} }
$this.mCustomScrollbar("update"); $this.mCustomScrollbar("update");
currWinWidth=winWidth; currWinHeight=winHeight; currWinWidth=winWidth; currWinHeight=winHeight;
@@ -206,22 +211,23 @@ along with this program. If not, see http://www.gnu.org/licenses/lgpl.html.
if(options.advanced.updateOnContentResize){ if(options.advanced.updateOnContentResize){
var mCSB_onContentResize; var mCSB_onContentResize;
if(options.horizontalScroll){ if(options.horizontalScroll){
var mCSB_containerOldSize=mCSB_container.outerWidth(); var mCSB_containerOldSize=mCSB_container.outerWidth(),mCSB_contentOldSize=mCSB_container.innerWidth();
}else{ }else{
var mCSB_containerOldSize=mCSB_container.outerHeight(); var mCSB_containerOldSize=mCSB_container.outerHeight(),mCSB_contentOldSize=mCSB_container.innerHeight();
} }
mCSB_onContentResize=setInterval(function(){ mCSB_onContentResize=setInterval(function(){
if(options.horizontalScroll){ if(options.horizontalScroll){
if(options.advanced.autoExpandHorizontalScroll){ if(options.advanced.autoExpandHorizontalScroll){
mCSB_container.css({"position":"absolute","width":"auto"}).wrap("<div class='mCSB_h_wrapper' style='position:relative; left:0; width:999999px;' />").css({"width":mCSB_container.outerWidth(),"position":"relative"}).unwrap(); mCSB_container.css({"position":"absolute","width":"auto"}).wrap("<div class='mCSB_h_wrapper' style='position:relative; left:0; width:999999px;' />").css({"width":mCSB_container.outerWidth(),"position":"relative"}).unwrap();
} }
var mCSB_containerNewSize=mCSB_container.outerWidth(); var mCSB_containerNewSize=mCSB_container.outerWidth(),mCSB_contentNewSize=mCSB_container.innerWidth();
}else{ }else{
var mCSB_containerNewSize=mCSB_container.outerHeight(); var mCSB_containerNewSize=mCSB_container.outerHeight(),mCSB_contentNewSize=mCSB_container.innerHeight();
} }
if(mCSB_containerNewSize!=mCSB_containerOldSize){ if(mCSB_containerNewSize!=mCSB_containerOldSize || mCSB_contentNewSize!=mCSB_contentOldSize){
$this.mCustomScrollbar("update"); $this.mCustomScrollbar("update");
mCSB_containerOldSize=mCSB_containerNewSize; mCSB_containerOldSize=mCSB_containerNewSize;
mCSB_contentOldSize=mCSB_contentNewSize;
} }
},300); },300);
} }
@@ -681,6 +687,18 @@ along with this program. If not, see http://www.gnu.org/licenses/lgpl.html.
}else{ }else{
draggerScrollTo=scrollTo=target; draggerScrollTo=scrollTo=target;
} }
}else if(typeof(scrollTo)==="object"){ /*if object, scroll by element position*/
var target=$(scrollTo);
if(target.length===1){ /*if such unique element exists, scroll to it*/
if($this.data("horizontalScroll")){
scrollTo=target.position().left;
}else{
scrollTo=target.position().top;
}
draggerScrollTo=scrollTo/$this.data("scrollAmount");
}else{
draggerScrollTo=scrollTo=target;
}
} }
/*scroll to*/ /*scroll to*/
if($this.data("horizontalScroll")){ if($this.data("horizontalScroll")){
@@ -767,7 +785,7 @@ along with this program. If not, see http://www.gnu.org/licenses/lgpl.html.
} }
/*callbacks*/ /*callbacks*/
function callbacks(cb){ function callbacks(cb){
if ($this.data("mCustomScrollbarIndex")) { if($this.data("mCustomScrollbarIndex")){
this.mcs = { this.mcs = {
top: mCSB_container.position().top, left: mCSB_container.position().left, top: mCSB_container.position().top, left: mCSB_container.position().left,
draggerTop: mCSB_dragger.position().top, draggerLeft: mCSB_dragger.position().left, draggerTop: mCSB_dragger.position().top, draggerLeft: mCSB_dragger.position().left,
@@ -831,7 +849,9 @@ along with this program. If not, see http://www.gnu.org/licenses/lgpl.html.
functions={ functions={
/*hide/show scrollbar*/ /*hide/show scrollbar*/
showScrollbar:function(){ showScrollbar:function(){
this.stop().animate({opacity:1},"fast"); if($(this).css("opacity")==0){
this.stop().animate({opacity:1},"fast");
}
}, },
hideScrollbar:function(){ hideScrollbar:function(){
this.stop().animate({opacity:0},"fast"); this.stop().animate({opacity:0},"fast");
@@ -955,7 +975,7 @@ along with this program. If not, see http://www.gnu.org/licenses/lgpl.html.
$.support.msPointer=window.navigator.msPointerEnabled; /*MSPointer support*/ $.support.msPointer=window.navigator.msPointerEnabled; /*MSPointer support*/
/*plugin dependencies*/ /*plugin dependencies*/
var _dlp=("https:"==document.location.protocol) ? "https:" : "http:"; var _dlp=("https:"==document.location.protocol) ? "https:" : "http:";
$.event.special.mousewheel || document.write('<script src="'+_dlp+'//cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.0.6/jquery.mousewheel.min.js"><\/script>'); $.event.special.mousewheel || $("<script>",{src:_dlp+"//cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.6/jquery.mousewheel.min.js"}).appendTo("body");
/*plugin fn*/ /*plugin fn*/
$.fn.mCustomScrollbar=function(method){ $.fn.mCustomScrollbar=function(method){
if(methods[method]){ if(methods[method]){

File diff suppressed because one or more lines are too long

View File

@@ -16,7 +16,10 @@
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<iframe id="stdout-iframe"></iframe> <div id="style-sheet-container"></div>
<div id="pre-container" class="body_background body_foreground pre mono-space" aw-custom-scroll data-scroll-theme="light-thin">
<div id="pre-container-content"></div>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -402,7 +402,8 @@
<script src="{{ STATIC_URL }}lib/codemirror/addon/selection/active-line.js"></script> <script src="{{ STATIC_URL }}lib/codemirror/addon/selection/active-line.js"></script>
<script src="{{ STATIC_URL }}lib/scrollto/lib/jquery-scrollto.js"></script> <script src="{{ STATIC_URL }}lib/scrollto/lib/jquery-scrollto.js"></script>
<script src="{{ STATIC_URL }}lib/socket.io-client/dist/socket.io.min.js"></script> <script src="{{ STATIC_URL }}lib/socket.io-client/dist/socket.io.min.js"></script>
<script src="{{ STATIC_URL }}lib/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.concat.min.js"></script> <script src="{{ STATIC_URL }}lib/jquery-mousewheel/jquery.mousewheel.min.js"></script>
<script src="{{ STATIC_URL }}lib/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.min.js"></script>
<script scr="{{ STATIC_URL }}lib/lib/jQuery.dotdotdot/src/js/jquery.dotdotdot.min.js"></script> <script scr="{{ STATIC_URL }}lib/lib/jQuery.dotdotdot/src/js/jquery.dotdotdot.min.js"></script>
<script src="{{ STATIC_URL }}lib/d3js/build/d3.v3.min.js"></script> <script src="{{ STATIC_URL }}lib/d3js/build/d3.v3.min.js"></script>
<script src="{{ STATIC_URL }}lib/d3Donut/d3Donut.js"></script> <script src="{{ STATIC_URL }}lib/d3Donut/d3Donut.js"></script>

View File

@@ -23,7 +23,7 @@
"sizzle": "1.10.16", "sizzle": "1.10.16",
"d3js": "*", "d3js": "*",
"angular-tz-extensions": "~0.3.10", "angular-tz-extensions": "~0.3.10",
"malihu-custom-scrollbar-plugin": "2.8.3", "malihu-custom-scrollbar-plugin": "2.8.4",
"jQuery.dotdotdot": "~1.6.14" "jQuery.dotdotdot": "~1.6.14"
}, },
"resolutions": { "resolutions": {