From ca35eb39d2e77082974642ea4c770d856326b88a Mon Sep 17 00:00:00 2001 From: Jake McDermott Date: Wed, 15 Aug 2018 21:04:36 -0400 Subject: [PATCH] make line expand / collapse work for paginated scrollup --- .../features/output/index.controller.js | 143 ++++++++++++------ awx/ui/client/features/output/index.view.html | 4 +- .../client/features/output/render.service.js | 27 +++- 3 files changed, 128 insertions(+), 46 deletions(-) diff --git a/awx/ui/client/features/output/index.controller.js b/awx/ui/client/features/output/index.controller.js index 7d2acdc8ea..18e0357ed1 100644 --- a/awx/ui/client/features/output/index.controller.js +++ b/awx/ui/client/features/output/index.controller.js @@ -273,64 +273,121 @@ function togglePanelExpand () { vm.isPanelExpanded = !vm.isPanelExpanded; } -function toggleMenuExpand () { +const iconCollapsed = 'fa-angle-right'; +const iconExpanded = 'fa-angle-down'; +const iconSelector = '.at-Stdout-toggle > i'; +const lineCollapsed = 'hidden'; + +function toggleCollapseAll () { if (scroll.isPaused()) return; - const recordList = Object.keys(render.record).map(key => render.record[key]); - const playRecords = recordList.filter(({ name }) => name === EVENT_START_PLAY); - const playIds = playRecords.map(({ uuid }) => uuid); + const records = Object.keys(render.record).map(key => render.record[key]); + const plays = records.filter(({ name }) => name === EVENT_START_PLAY); + const tasks = records.filter(({ name }) => name === EVENT_START_TASK); - // get any task record that does not have a parent play record - const orphanTaskRecords = recordList - .filter(({ name }) => name === EVENT_START_TASK) - .filter(({ parents }) => !parents.some(uuid => playIds.indexOf(uuid) >= 0)); + const orphanLines = records + .filter(({ level }) => level === 3) + .filter(({ parents }) => !records[parents[0]]); - const toggled = playRecords.concat(orphanTaskRecords) - .map(({ uuid }) => getToggleElements(uuid)) - .filter(({ icon }) => icon.length > 0) - .map(({ icon, lines }) => setExpanded(icon, lines, !vm.isMenuExpanded)); + const orphanLineParents = orphanLines + .map(({ parents }) => ({ uuid: parents[0] })); - if (toggled.length > 0) { - vm.isMenuExpanded = !vm.isMenuExpanded; + plays.concat(tasks).forEach(({ uuid }) => { + const icon = $(`#${uuid} ${iconSelector}`); + + if (vm.isMenuCollapsed) { + icon.removeClass(iconCollapsed); + icon.addClass(iconExpanded); + } else { + icon.removeClass(iconExpanded); + icon.addClass(iconCollapsed); + } + }); + + tasks.concat(orphanLineParents).forEach(({ uuid }) => { + const lines = $(`.child-of-${uuid}`); + + if (vm.isMenuCollapsed) { + lines.removeClass(lineCollapsed); + } else { + lines.addClass(lineCollapsed); + } + }); + + vm.isMenuCollapsed = !vm.isMenuCollapsed; + render.setCollapseAll(vm.isMenuCollapsed); +} + +function toggleCollapse (uuid) { + if (scroll.isPaused()) return; + + const record = render.record[uuid]; + + if (record.name === EVENT_START_PLAY) { + togglePlayCollapse(uuid); + } + + if (record.name === EVENT_START_TASK) { + toggleTaskCollapse(uuid); } } -function toggleLineExpand (uuid) { - if (scroll.isPaused()) return; +function togglePlayCollapse (uuid) { + const record = render.record[uuid]; + const descendants = record.children || []; - const { icon, lines } = getToggleElements(uuid); - const isExpanded = icon.hasClass('fa-angle-down'); + const icon = $(`#${uuid} ${iconSelector}`); + const lines = $(`.child-of-${uuid}`); + const taskIcons = $(`#${descendants.join(', #')}`).find(iconSelector); - setExpanded(icon, lines, !isExpanded); + const isCollapsed = icon.hasClass(iconCollapsed); - vm.isMenuExpanded = !isExpanded; + if (isCollapsed) { + icon.removeClass(iconCollapsed); + icon.addClass(iconExpanded); + + taskIcons.removeClass(iconExpanded); + taskIcons.addClass(iconCollapsed); + lines.removeClass(lineCollapsed); + + descendants + .map(item => $(`.child-of-${item}`)) + .forEach(line => line.addClass(lineCollapsed)); + } else { + icon.removeClass(iconExpanded); + icon.addClass(iconCollapsed); + + taskIcons.removeClass(iconExpanded); + taskIcons.addClass(iconCollapsed); + + lines.addClass(lineCollapsed); + } + + descendants + .map(item => render.record[item]) + .filter(({ name }) => name === EVENT_START_TASK) + .forEach(rec => { render.record[rec.uuid].isCollapsed = true; }); + + render.record[uuid].isCollapsed = !isCollapsed; } -function getToggleElements (uuid) { - const record = render.record[uuid]; +function toggleTaskCollapse (uuid) { + const icon = $(`#${uuid} ${iconSelector}`); const lines = $(`.child-of-${uuid}`); - const iconSelector = '.at-Stdout-toggle > i'; - const additionalSelector = `#${(record.children || []).join(', #')}`; + const isCollapsed = icon.hasClass(iconCollapsed); - let icon = $(`#${uuid} ${iconSelector}`); - if (additionalSelector) { - icon = icon.add($(additionalSelector).find(iconSelector)); - } - - return { icon, lines }; -} - -function setExpanded (icon, lines, expanded) { - if (expanded) { - icon.removeClass('fa-angle-right'); - icon.addClass('fa-angle-down'); - lines.removeClass('hidden'); + if (isCollapsed) { + icon.removeClass(iconCollapsed); + icon.addClass(iconExpanded); + lines.removeClass(lineCollapsed); } else { - icon.removeClass('fa-angle-down'); - icon.addClass('fa-angle-right'); - lines.addClass('hidden'); + icon.removeClass(iconExpanded); + icon.addClass(iconCollapsed); + lines.addClass(lineCollapsed); } + + render.record[uuid].isCollapsed = !isCollapsed; } function compile (html) { @@ -476,10 +533,10 @@ function OutputIndexController ( // Stdout Navigation vm.menu = { last: menuLast, first, down, up, clear }; - vm.isMenuExpanded = true; + vm.isMenuCollapsed = false; vm.isFollowing = false; - vm.toggleMenuExpand = toggleMenuExpand; - vm.toggleLineExpand = toggleLineExpand; + vm.toggleCollapseAll = toggleCollapseAll; + vm.toggleCollapse = toggleCollapse; vm.showHostDetails = showHostDetails; vm.toggleLineEnabled = resource.model.get('type') === 'job'; vm.followTooltip = vm.strings.get('tooltips.MENU_LAST'); diff --git a/awx/ui/client/features/output/index.view.html b/awx/ui/client/features/output/index.view.html index d6fae167f5..ea6c31c2fc 100644 --- a/awx/ui/client/features/output/index.view.html +++ b/awx/ui/client/features/output/index.view.html @@ -21,9 +21,9 @@ reload="vm.reloadState">
-
+
+ ng-class="{ 'fa-minus': !vm.isMenuCollapsed, 'fa-plus': vm.isMenuCollapsed }">
{ + this.state.collapseAll = value; }; this.sortByLineNumber = (a, b) => { @@ -133,10 +140,14 @@ function JobRenderService ($q, $sce, $window) { isTruncated: (event.end_line - event.start_line) > lines.length, lineCount: lines.length, isHost: this.isHostEvent(event), + isCollapsed: this.state.collapseAll, }; if (event.parent_uuid) { info.parents = this.getParentEvents(event.parent_uuid); + if (this.record[event.parent_uuid]) { + info.isCollapsed = this.record[event.parent_uuid].isCollapsed; + } } if (info.isTruncated) { @@ -192,6 +203,7 @@ function JobRenderService ($q, $sce, $window) { this.createRow = (current, ln, content) => { let id = ''; + let icon = ''; let timestamp = ''; let tdToggle = ''; let tdEvent = ''; @@ -206,7 +218,14 @@ function JobRenderService ($q, $sce, $window) { if (current) { if (this.createToggles && current.isParent && current.line === ln) { id = current.uuid; - tdToggle = `
`; + + if (current.isCollapsed) { + icon = 'fa-angle-right'; + } else { + icon = 'fa-angle-down'; + } + + tdToggle = `
`; } if (current.isHost) { @@ -234,6 +253,12 @@ function JobRenderService ($q, $sce, $window) { ln = '...'; } + if (current && current.isCollapsed) { + if (current.level === 3 || current.level === 0) { + classList += ' hidden'; + } + } + return `
${tdToggle}