diff --git a/awx/ui/client/features/output/index.controller.js b/awx/ui/client/features/output/index.controller.js index 238adc11f4..0b87c47552 100644 --- a/awx/ui/client/features/output/index.controller.js +++ b/awx/ui/client/features/output/index.controller.js @@ -48,13 +48,10 @@ function JobsIndexController (job, JobEventModel, _$sce_, _$timeout_, _$scope_, vm.showHostDetails = showHostDetails; vm.menu = { - expand: menuExpand, - scrollToBottom: menuScrollToBottom, - scrollToTop: menuScrollToTop - }; - - vm.state = { - expand: true + top: { + expand: menuExpand, + isExpanded: false + } }; $timeout(() => { @@ -66,22 +63,9 @@ function JobsIndexController (job, JobEventModel, _$sce_, _$timeout_, _$scope_, } function menuExpand () { - vm.state.expand = !vm.state.expand; vm.toggle(meta.parent); } -function menuScrollToBottom () { - const container = $('.at-Stdout-container')[0]; - - container.scrollTop = container.scrollHeight; -} - -function menuScrollToTop () { - const container = $('.at-Stdout-container')[0]; - - container.scrollTop = 0; -} - function parseEvents (events) { events.sort(orderByLineNumber); diff --git a/awx/ui/client/features/output/index.view.html b/awx/ui/client/features/output/index.view.html index 0d92977ee5..7850adacb3 100644 --- a/awx/ui/client/features/output/index.view.html +++ b/awx/ui/client/features/output/index.view.html @@ -7,17 +7,7 @@
-
-
- -
-
- -
- -
-
+
 
diff --git a/awx/ui/client/lib/components/code/events.directive.js b/awx/ui/client/lib/components/code/events.directive.js new file mode 100644 index 0000000000..8426bf3ae6 --- /dev/null +++ b/awx/ui/client/lib/components/code/events.directive.js @@ -0,0 +1,104 @@ +import Ansi from 'ansi-to-html'; +import hasAnsi from 'has-ansi'; + +const templateUrl = require('~components/code/events.partial.html'); + +let $sce; +let $timeout; +let ansi; + +function atOutputEventLink (scope, element, attrs, controller) { + controller.init(scope, element); +} + +function AtOutputEventController (_$sce_, _$timeout_) { + const vm = this || {}; + + $timeout = _$timeout_; + $sce = _$sce_; + ansi = new Ansi(); + + let scope; + let element; + + vm.init = (_scope_, _element_) => { + scope = _scope_; + element = _element_; + + scope.$watch('state.stdout', curr => { + if (!curr) { + return; + } + + render(scope.state.stdout); + }); + }; + + vm.scroll = position => { + const container = element.find('.at-Stdout-container')[0]; + + if (position === 'bottom') { + container.scrollTop = container.scrollHeight; + } else { + container.scrollTop = 0; + } + }; +} + +AtOutputEventController.$inject = [ + '$sce', + '$timeout', +]; + +function render (stdout) { + const html = $sce.trustAsHtml(parseStdout(stdout)); + + $timeout(() => { + const table = $('#atStdoutTBody'); + + table.html($sce.getTrustedHtml(html)); + }); +} + +function parseStdout (stdout) { + const lines = stdout.split('\r\n'); + + let ln = 0; + + return lines.reduce((html, line) => { + ln++; + + return `${html}${createRow(ln, line)}`; + }, ''); +} + +function createRow (ln, content) { + content = content || ''; + + if (hasAnsi(content)) { + content = ansi.toHtml(content); + } + + return ` + + ${ln} + ${content} + `; +} +function atOutputEvent () { + return { + restrict: 'E', + transclude: true, + replace: true, + require: 'atOutputEvent', + templateUrl, + controller: AtOutputEventController, + controllerAs: 'vm', + link: atOutputEventLink, + scope: { + state: '=', + } + }; +} + +export default atOutputEvent; diff --git a/awx/ui/client/lib/components/code/events.partial.html b/awx/ui/client/lib/components/code/events.partial.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/awx/ui/client/lib/components/code/menu-bottom.directive.js b/awx/ui/client/lib/components/code/menu-bottom.directive.js new file mode 100644 index 0000000000..5b15a7bc10 --- /dev/null +++ b/awx/ui/client/lib/components/code/menu-bottom.directive.js @@ -0,0 +1,41 @@ +const templateUrl = require('~components/code/menu-bottom.partial.html'); + +function atCodeMenuBottomLink (scope, element, attrs, controller) { + controller.init(scope, element); +} + +function AtCodeMenuBottomController () { + const vm = this || {}; + + let element; + + vm.init = (_scope_, _element_) => { + element = _element_; + }; + + vm.scroll = () => { + const container = element.find('.at-Stdout-container')[0]; + + container.scrollTop = container.scrollHeight; + }; +} + +AtCodeMenuBottomController.$inject = []; + +function atCodeMenuBottom () { + return { + restrict: 'E', + transclude: true, + replace: true, + require: 'atCodeMenuBottom', + templateUrl, + controller: AtCodeMenuBottomController, + controllerAs: 'vm', + link: atCodeMenuBottomLink, + scope: { + state: '=', + } + }; +} + +export default atCodeMenuBottom; diff --git a/awx/ui/client/lib/components/code/menu-bottom.partial.html b/awx/ui/client/lib/components/code/menu-bottom.partial.html new file mode 100644 index 0000000000..1a0717a360 --- /dev/null +++ b/awx/ui/client/lib/components/code/menu-bottom.partial.html @@ -0,0 +1,7 @@ +
+
+ +
+ +
+
diff --git a/awx/ui/client/lib/components/code/menu-top.directive.js b/awx/ui/client/lib/components/code/menu-top.directive.js new file mode 100644 index 0000000000..824e24123f --- /dev/null +++ b/awx/ui/client/lib/components/code/menu-top.directive.js @@ -0,0 +1,52 @@ +const templateUrl = require('~components/code/menu-top.partial.html'); + +function atCodeMenuTopLink (scope, element, attrs, controller) { + controller.init(scope, element); +} + +function AtCodeMenuTopController () { + const vm = this || {}; + + let element; + let scope; + + vm.init = (_scope_, _element_) => { + scope = _scope_; + element = _element_; + + scope.state.isExpanded = scope.state.isExpanded || false; + }; + + vm.scroll = () => { + const container = element.parent().find('.at-Stdout-container')[0]; + + console.log(container); + + container.scrollTop = 0; + }; + + vm.expand = () => { + scope.state.isExpanded = !scope.state.isExpanded; + scope.state.expand(); + }; +} + +AtCodeMenuTopController.$inject = []; + +function atCodeMenuTop () { + return { + restrict: 'E', + transclude: true, + replace: true, + require: 'atCodeMenuTop', + templateUrl, + controller: AtCodeMenuTopController, + controllerAs: 'vm', + link: atCodeMenuTopLink, + scope: { + state: '=', + } + }; +} + +export default atCodeMenuTop; diff --git a/awx/ui/client/lib/components/code/menu-top.partial.html b/awx/ui/client/lib/components/code/menu-top.partial.html new file mode 100644 index 0000000000..2e21dc1b8b --- /dev/null +++ b/awx/ui/client/lib/components/code/menu-top.partial.html @@ -0,0 +1,12 @@ +
+
+ +
+ +
+ +
+ +
+
diff --git a/awx/ui/client/lib/components/output/stdout.directive.js b/awx/ui/client/lib/components/code/stdout.directive.js similarity index 95% rename from awx/ui/client/lib/components/output/stdout.directive.js rename to awx/ui/client/lib/components/code/stdout.directive.js index 880e2c6eb6..1f32b5ca7f 100644 --- a/awx/ui/client/lib/components/output/stdout.directive.js +++ b/awx/ui/client/lib/components/code/stdout.directive.js @@ -1,7 +1,7 @@ import Ansi from 'ansi-to-html'; import hasAnsi from 'has-ansi'; -const templateUrl = require('~components/output/stdout.partial.html'); +const templateUrl = require('~components/code/stdout.partial.html'); let $sce; let $timeout; @@ -51,7 +51,6 @@ AtOutputStdoutController.$inject = [ ]; function render (stdout) { - console.log('render'); const html = $sce.trustAsHtml(parseStdout(stdout)); $timeout(() => { diff --git a/awx/ui/client/lib/components/output/stdout.partial.html b/awx/ui/client/lib/components/code/stdout.partial.html similarity index 100% rename from awx/ui/client/lib/components/output/stdout.partial.html rename to awx/ui/client/lib/components/code/stdout.partial.html diff --git a/awx/ui/client/lib/components/index.js b/awx/ui/client/lib/components/index.js index 339747ad67..bf45c63a6d 100644 --- a/awx/ui/client/lib/components/index.js +++ b/awx/ui/client/lib/components/index.js @@ -1,6 +1,10 @@ import atLibServices from '~services'; import actionGroup from '~components/action/action-group.directive'; +import codeMenuBottom from '~components/code/menu-bottom.directive'; +import codeMenuTop from '~components/code/menu-top.directive'; +import codeEvents from '~components/code/events.directive'; +import codeStdout from '~components/code/stdout.directive'; import divider from '~components/utility/divider.directive'; import form from '~components/form/form.directive'; import formAction from '~components/form/action.directive'; @@ -20,7 +24,6 @@ import launchTemplate from '~components/launchTemplateButton/launchTemplateButto import layout from '~components/layout/layout.directive'; import list from '~components/list/list.directive'; import modal from '~components/modal/modal.directive'; -import outputStdout from '~components/output/stdout.directive'; import panel from '~components/panel/panel.directive'; import panelBody from '~components/panel/body.directive'; import panelHeading from '~components/panel/heading.directive'; @@ -46,6 +49,10 @@ angular atLibServices ]) .directive('atActionGroup', actionGroup) + .directive('atCodeEvents', codeEvents) + .directive('atCodeMenuBottom', codeMenuBottom) + .directive('atCodeMenuTop', codeMenuTop) + .directive('atCodeStdout', codeStdout) .directive('atDivider', divider) .directive('atForm', form) .directive('atFormAction', formAction) @@ -69,7 +76,6 @@ angular .directive('atRowItem', rowItem) .directive('atRowAction', rowAction) .directive('atModal', modal) - .directive('atOutputStdout', outputStdout) .directive('atPanel', panel) .directive('atPanelBody', panelBody) .directive('atPanelHeading', panelHeading)