This is an automated email from the ASF dual-hosted git repository.

heneveld pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brooklyn-ui.git

commit 88ebac7cdd670d6a8ce5a254b5fdf41a205c0a15
Author: Alex Heneveld <a...@cloudsoft.io>
AuthorDate: Fri Mar 15 23:00:59 2024 +0000

    allow showing nested workflows in expanded workflow
---
 .../components/workflow/workflow-step.directive.js |  49 ++++++--
 .../workflow/workflow-step.template.html           | 124 +++++++++++----------
 .../workflow/workflow-steps.directive.js           |  20 ++--
 .../app/components/workflow/workflow-steps.less    |   7 +-
 .../workflow/workflow-steps.template.html          |   5 +-
 .../inspect/activities/detail/detail.controller.js |   2 +-
 6 files changed, 130 insertions(+), 77 deletions(-)

diff --git 
a/ui-modules/app-inspector/app/components/workflow/workflow-step.directive.js 
b/ui-modules/app-inspector/app/components/workflow/workflow-step.directive.js
index 5ca07ca7..87c200fe 100644
--- 
a/ui-modules/app-inspector/app/components/workflow/workflow-step.directive.js
+++ 
b/ui-modules/app-inspector/app/components/workflow/workflow-step.directive.js
@@ -41,12 +41,19 @@ export function workflowStepDirective() {
             expanded: '=',
             onSizeChange: '=',
         },
-        controller: ['$sce', '$scope', controller],
+        controller: ['$sce', '$scope', 'entityApi', controller],
         controllerAs: 'vm',
     };
 
-    function controller($sce, $scope) {
+    function controller($sce, $scope, entityApi) {
         try {
+            let observers = [];
+            $scope.$on('$destroy', ()=> {
+                observers.forEach((observer)=> {
+                    observer.unsubscribe();
+                });
+            });
+
             let vm = this;
 
             let step = $scope.step;
@@ -89,12 +96,12 @@ export function workflowStepDirective() {
                 return "multiline-code multiline-code-resizable 
lines-"+lines.length;
             };
 
-            $scope.json = null;
-            $scope.jsonMode = null;
+            $scope.addlData = null;
+            $scope.addlMode = null;
             vm.showAdditional = (title, mode, obj) => {
-                $scope.jsonTitle = title;
-                $scope.jsonMode = mode;
-                $scope.json = obj==undefined ? null : vm.yamlOrPrimitive(obj);
+                $scope.addlTitle = title;
+                $scope.addlMode = mode;
+                $scope.addlData = obj==undefined ? null : 
vm.yamlOrPrimitive(obj);
             }
 
             $scope.stepTitle = {
@@ -212,6 +219,34 @@ export function workflowStepDirective() {
             $scope.$watch('workflow', updateData);
             updateData();
 
+            $scope.showStepDefinitionInBody = true;
+            function loadUniqueSubworkflow(workflowTag) {
+                if (!workflowTag) return;
+
+                return entityApi.getWorkflow(workflowTag.applicationId, 
workflowTag.entityId, workflowTag.workflowId).then(wResponse => {
+                    if (wResponse.data.status === 'RUNNING') {
+                        wResponse.interval(1000);
+                        observers.push(wResponse.subscribe(() => 
loadUniqueSubworkflow(workflowTag)));
+                    }
+
+                    $scope.uniqueSubworkflow = {
+                        applicationId: workflowTag.applicationId,
+                        entityId: workflowTag.entityId,
+                        workflowTag: workflowTag,
+                        data: wResponse.data,
+                    };
+
+                }).catch(error => {
+                    console.log("Unable to load single unique workflow", 
workflowTag, error);
+                    $scope.showStepDefinitionInBody = false;
+                    $scope.uniqueSubworkflow = undefined;
+                });
+            }
+            if (!$scope.workflow.runIsOld && $scope.stepContext.subWorkflows 
&& $scope.stepContext.subWorkflows.length==1) {
+                $scope.showStepDefinitionInBody = false;
+                loadUniqueSubworkflow($scope.stepContext.subWorkflows[0]);
+            }
+
         } catch (error) {
             console.log("error showing workflow step", error);
             // the ng-repeat seems to swallow and mask any error in the above 
- can't understand why! but log it here in case something breaks.
diff --git 
a/ui-modules/app-inspector/app/components/workflow/workflow-step.template.html 
b/ui-modules/app-inspector/app/components/workflow/workflow-step.template.html
index 1eb67f7d..b504f46d 100644
--- 
a/ui-modules/app-inspector/app/components/workflow/workflow-step.template.html
+++ 
b/ui-modules/app-inspector/app/components/workflow/workflow-step.template.html
@@ -35,7 +35,7 @@
         </span>
     </div>
 
-    <div class="workflow-step" id="workflow-step-{{stepIindex}}" 
ng-class="vm.getWorkflowStepClasses(stepIndex)">
+    <div class="workflow-step workflow-{{workflowId}}" 
id="workflow-step-{{stepIindex}}" 
ng-class="vm.getWorkflowStepClasses(stepIndex)">
         <div class="rhs-icons">
             <div ng-if="isFocusTask" class="workflow-step-pill focus-step 
label-info" title="This step instance is for the task currently selected in the 
activity view.">
                 selected
@@ -183,9 +183,13 @@
                 </div>
 
                 <div class="more-space-above">
+                    <div class="data-row" ng-if="uniqueSubworkflow">
+                        <workflow-steps nested="true" 
workflow="uniqueSubworkflow" style="flex: 1 1 auto; margin-left: -2em; 
margin-top: -24px; margin-right: -1em;"/>
+                    </div>
+
                     <div class="data-row" ng-if="stepContext.error"><div 
class="A">Error</div> <div class="B {{ 
vm.classForCodeMaybeMultiline(stepContext.error) }}">{{ 
vm.yamlOrPrimitive(stepContext.error) }}</div></div>
 
-                    <div class="data-row"><div class="A">Step Definition</div> 
<div class="B {{ vm.classForCodeMaybeMultiline(step) }}">{{ 
vm.yamlOrPrimitive(step) }}</div></div>
+                    <div class="data-row" 
ng-if="showStepDefinitionInBody"><div class="A">Step Definition</div> <div 
class="B {{ vm.classForCodeMaybeMultiline(step) }}">{{ vm.yamlOrPrimitive(step) 
}}</div></div>
 
                     <div ng-if="!isFocusStep || isFocusTask">
                         <div class="data-row" 
ng-if="stepContext.otherMetadata" ng-repeat="(key,value) in 
stepContext.otherMetadata" id="$key">
@@ -199,31 +203,34 @@
             </div>
 
             <div class="more-space-above" ng-if="vm.nonEmpty(stepContext) || 
vm.nonEmpty(step) || vm.nonEmpty(osi)"
-                 style="margin-bottom: {{ jsonTitle ? '9px' : '6px' }};">
+                 style="margin-bottom: {{ addlTitle ? '9px' : '6px' }};">
 
                 <div class="btn-group right" uib-dropdown>
                     <button id="extra-data-button" type="button" class="btn 
btn-sm btn-select-dropdown pull-right" uib-dropdown-toggle
-                            style="padding: 2px 6px; {{ jsonTitle ? 'width: 
100%; ' : '' }} text-align: right;">
-                        {{ jsonTitle ? 'Showing '+jsonTitle : 'More 
Information' }}
-                        <span class="caret" style="{{ jsonTitle ? 'rotate: 
180deg;' : '' }}"></span>
+                            style="padding: 2px 6px; {{ addlTitle ? 'width: 
100%; ' : '' }} text-align: right;">
+                        {{ addlTitle ? 'Showing '+addlTitle : 'More 
Information' }}
+                        <span class="caret" style="{{ addlTitle ? 'rotate: 
180deg;' : '' }}"></span>
                     </button>
                     <ul class="dropdown-menu pull-right 
workflow-dropdown-small" uib-dropdown-menu role="menu" 
aria-labelledby="extra-data-button">
-                        <li role="menuitem" > <a href="" 
ng-click="vm.showAdditional('Context Variables', 'vars', null)" 
ng-class="{'selected' : jsonMode === 'vars'}">
+                        <li role="menuitem" ng-if="!showStepDefinitionInBody"> 
<a href="" ng-click="vm.showAdditional('Step Definition', 'step_defn', 
vm.yamlOrPrimitive(step))" ng-class="{'selected' : addlMode === 'step_defn'}">
+                            <i class="fa fa-check check"></i>
+                            Step Definition</a> </li>
+                        <li role="menuitem" > <a href="" 
ng-click="vm.showAdditional('Context Variables', 'vars', null)" 
ng-class="{'selected' : addlMode === 'vars'}">
                             <i class="fa fa-check check"></i>
                             Context Variables</a> </li>
-                        <li role="menuitem" > <a href="" 
ng-click="vm.showAdditional('Additional Step Info', 'metadata', null)" 
ng-class="{'selected' : jsonMode === 'summary'}">
+                        <li role="menuitem" > <a href="" 
ng-click="vm.showAdditional('Additional Step Info', 'metadata', null)" 
ng-class="{'selected' : addlMode === 'summary'}">
                             <i class="fa fa-check check"></i>
                             Additional Step Info</a> </li>
-                        <li role="menuitem" > <a href="" 
ng-click="vm.showAdditional('Step Record YAML', 'osi', osi)" 
ng-class="{'selected' : jsonMode === 'osi'}">
+                        <li role="menuitem" > <a href="" 
ng-click="vm.showAdditional('Step Record YAML', 'osi', osi)" 
ng-class="{'selected' : addlMode === 'osi'}">
                             <i class="fa fa-check check"></i>
                             Step Record YAML</a> </li>
-                        <li role="menuitem" > <a href="" 
ng-click="vm.showAdditional(null, null)" ng-class="{'selected' : jsonMode === 
null}">
+                        <li role="menuitem" > <a href="" 
ng-click="vm.showAdditional(null, null)" ng-class="{'selected' : addlMode === 
null}">
                             <i class="fa fa-check check"></i>
-                            None</a> </li>
+                            Hide Additional Info</a> </li>
                     </ul>
                 </div>
 
-                <div ng-if="jsonMode === 'vars'">
+                <div ng-if="addlMode === 'vars'">
                     <div class="data-row" 
ng-if="vm.getOutputAndScratchForStep(stepIndex).output">
                         <div class="A">Output of previous</div>
                         <div class="B {{ 
vm.classForCodeMaybeMultiline(vm.getOutputAndScratchForStep(stepIndex).output) 
}}">{{
@@ -239,58 +246,61 @@
                         <div class="B {{ 
vm.classForCodeMaybeMultiline(workflow.data.input) }}">{{
                             vm.yamlOrPrimitive(workflow.data.input) }}</div>
                     </div>
+                    <div class="data-row" 
ng-if="!vm.getOutputAndScratchForStep(stepIndex).output && 
!vm.getOutputAndScratchForStep(stepIndex).workflowScratch && 
!workflow.data.input">
+                        <div class="A">No context variables set</div>
+                    </div>
                 </div>
-                <div ng-if="jsonMode === 'metadata'">
-                        <div class="data-row" ng-if="step.name"><div 
class="A">Name</div> <div class="B">{{ step.name }}</div></div>
-                        <div class="data-row" ng-if="step.id"><div 
class="A">ID</div> <div class="B fixed-width">{{ step.id }}</div></div>
-                        <div class="data-row"><div class="A">Step Number</div> 
<div class="B">{{ stepIndex+1 }}</div></div>
-
-                        <div ng-if="!isFocusStep || isFocusTask">
-                            <!-- only show these if not looking at an earlier 
run of a step -->
-                            <div class="data-row more-space-above" 
ng-if="stepContext.input"><div class="A">All Input</div> <div class="B 
multiline-code">{{ vm.yaml(stepContext.input) }}</div></div>
-                        </div>
+                <div ng-if="addlMode === 'metadata'">
+                    <div class="data-row" ng-if="step.name"><div 
class="A">Name</div> <div class="B">{{ step.name }}</div></div>
+                    <div class="data-row" ng-if="step.id"><div 
class="A">ID</div> <div class="B fixed-width">{{ step.id }}</div></div>
+                    <div class="data-row"><div class="A">Step Number</div> 
<div class="B">{{ stepIndex+1 }}</div></div>
+
+                    <div ng-if="!isFocusStep || isFocusTask">
+                        <!-- only show these if not looking at an earlier run 
of a step -->
+                        <div class="data-row more-space-above" 
ng-if="stepContext.input"><div class="A">All Input</div> <div class="B 
multiline-code">{{ vm.yaml(stepContext.input) }}</div></div>
+                    </div>
 
                     <div class="data-row more-space-above">
-                            <div class="A"><span 
ng-if="isCurrentAndActive">CURRENTLY EXECUTING</span><span 
ng-if="!isCurrentAndActive"><span ng-if="osi.countStarted > 1">LAST 
</span>EXECUTED</span> IN</div>
-                            <div class="B">
-                                            <span ng-if="isFocusTask">
-                                                task <span 
class="monospace">{{ stepContext.taskId }}</span>
-                                            </span>
-                                <span ng-if="!isFocusTask">
-                                                 <a 
ui-sref="main.inspect.activities.detail({applicationId: workflow.applicationId, 
entityId: workflow.entityId, activityId: stepContext.taskId, workflowId })"
-                                                 >task <span 
class="monospace">{{ stepContext.taskId }}</span></a>
-                                            </span>
-                            </div>
-                        </div>
-                        <div ng-if="!isFocusStep || isFocusTask">
-                            <!-- only show these if not looking at an earlier 
run of a step -->
-                            <div class="data-row"><div class="A">Preceeded 
by</div> <div class="B">
-                                <span ng-if="osi.previousTaskId">
-                                    Step {{ osi.previous[0]+1 }}
-                                    (<a 
ui-sref="main.inspect.activities.detail({applicationId: workflow.applicationId, 
entityId: workflow.entityId, activityId: osi.previousTaskId, workflowId })"
-                                >task <span class="monospace">{{ 
osi.previousTaskId }}</span></a>)
-                                </span>
-                                <span ng-if="!osi.previousTaskId">(workflow 
start)</span>
-                            </div></div>
-
-                            <div class="data-row" 
ng-if="!isCurrentMaybeInactive"><div class="A">Followed by</div> <div class="B">
-                                <span ng-if="osi.nextTaskId">
-                                    Step {{ osi.next[0]+1 }}
-                                    (<a 
ui-sref="main.inspect.activities.detail({applicationId: workflow.applicationId, 
entityId: workflow.entityId, activityId: osi.nextTaskId, workflowId })"
-                                >task <span class="monospace">{{ 
osi.nextTaskId }}</span></a>)
-                                </span>
-                                <span ng-if="!osi.nextTaskId">(workflow 
end)</span>
-                            </div></div>
+                        <div class="A"><span 
ng-if="isCurrentAndActive">CURRENTLY EXECUTING</span><span 
ng-if="!isCurrentAndActive"><span ng-if="osi.countStarted > 1">LAST 
</span>EXECUTED</span> IN</div>
+                        <div class="B">
+                                        <span ng-if="isFocusTask">
+                                            task <span class="monospace">{{ 
stepContext.taskId }}</span>
+                                        </span>
+                            <span ng-if="!isFocusTask">
+                                             <a 
ui-sref="main.inspect.activities.detail({applicationId: workflow.applicationId, 
entityId: workflow.entityId, activityId: stepContext.taskId, workflowId })"
+                                             >task <span class="monospace">{{ 
stepContext.taskId }}</span></a>
+                                        </span>
                         </div>
+                    </div>
+                    <div ng-if="!isFocusStep || isFocusTask">
+                        <!-- only show these if not looking at an earlier run 
of a step -->
+                        <div class="data-row"><div class="A">Preceeded 
by</div> <div class="B">
+                            <span ng-if="osi.previousTaskId">
+                                Step {{ osi.previous[0]+1 }}
+                                (<a 
ui-sref="main.inspect.activities.detail({applicationId: workflow.applicationId, 
entityId: workflow.entityId, activityId: osi.previousTaskId, workflowId })"
+                            >task <span class="monospace">{{ 
osi.previousTaskId }}</span></a>)
+                            </span>
+                            <span ng-if="!osi.previousTaskId">(workflow 
start)</span>
+                        </div></div>
 
-                        <div ng-if="osi.countStarted > 1 && osi.countStarted > 
osi.countCompleted" class="space-above">
-                            <div class="data-row more-space-above"><div 
class="A">Runs</div> <div class="B"><b>{{ osi.countStarted }}</b></div></div>
-                            <div class="data-row"><div 
class="A">Succeeded</div> <div class="B">{{ osi.countCompleted }}</div></div>
-                            <div class="data-row"><div class="A">Failed</div> 
<div class="B">{{ osi.countStarted - osi.countCompleted - (isCurrentAndActive ? 
1 : 0) }}</div></div>
-                        </div>
+                        <div class="data-row" 
ng-if="!isCurrentMaybeInactive"><div class="A">Followed by</div> <div class="B">
+                            <span ng-if="osi.nextTaskId">
+                                Step {{ osi.next[0]+1 }}
+                                (<a 
ui-sref="main.inspect.activities.detail({applicationId: workflow.applicationId, 
entityId: workflow.entityId, activityId: osi.nextTaskId, workflowId })"
+                            >task <span class="monospace">{{ osi.nextTaskId 
}}</span></a>)
+                            </span>
+                            <span ng-if="!osi.nextTaskId">(workflow end)</span>
+                        </div></div>
+                    </div>
+
+                    <div ng-if="osi.countStarted > 1 && osi.countStarted > 
osi.countCompleted" class="space-above">
+                        <div class="data-row more-space-above"><div 
class="A">Runs</div> <div class="B"><b>{{ osi.countStarted }}</b></div></div>
+                        <div class="data-row"><div class="A">Succeeded</div> 
<div class="B">{{ osi.countCompleted }}</div></div>
+                        <div class="data-row"><div class="A">Failed</div> <div 
class="B">{{ osi.countStarted - osi.countCompleted - (isCurrentAndActive ? 1 : 
0) }}</div></div>
                     </div>
+                </div>
 
-                <pre ng-if="json" class="more-space-above">{{ json }}</pre>
+                <pre ng-if="addlData" class="more-space-above">{{ addlData 
}}</pre>
             </div>
         </div>
 
diff --git 
a/ui-modules/app-inspector/app/components/workflow/workflow-steps.directive.js 
b/ui-modules/app-inspector/app/components/workflow/workflow-steps.directive.js
index b48cf7e6..f82d9216 100644
--- 
a/ui-modules/app-inspector/app/components/workflow/workflow-steps.directive.js
+++ 
b/ui-modules/app-inspector/app/components/workflow/workflow-steps.directive.js
@@ -33,6 +33,7 @@ export function workflowStepsDirective() {
         scope: {
             workflow: '=',
             task: '=?',
+            nested: '=?',
         },
         controller: ['$sce', '$timeout', '$scope', '$element', controller],
         controllerAs: 'vm',
@@ -42,6 +43,7 @@ export function workflowStepsDirective() {
         let vm = this;
 
         vm.stringify = stringify;
+        $scope.workflowId = $scope.workflow.data.workflowId;
 
         vm.getWorkflowStepsClasses = () => {
             const c = [];
@@ -60,22 +62,23 @@ export function workflowStepsDirective() {
         vm.onSizeChange = () => $timeout(()=>recompute($scope, $element));
 
         $scope.$watch('workflow', vm.onSizeChange);
+        $scope.$watch(() => $element[0].offsetHeight, (newVal, oldVal) => {
+            if (oldVal!=newVal) vm.onSizeChange();
+        });
         vm.onSizeChange();
     }
 
     function recompute($scope, $element) {
-        let svg = $element[0].querySelector('#workflow-step-arrows');
-
-        let steps = $element[0].querySelectorAll('div');
-        // let steps = $element[0].querySelectorAll('.workflow-steps-main');
-        steps = $element[0].querySelectorAll('.workflow-step');
-        let arrows = makeArrows($scope.workflow, steps);
+        let svg = 
$element[0].querySelector('#workflow-step-arrows.workflow-'+$scope.workflowId);
+        let steps = 
$element[0].querySelectorAll('.workflow-'+$scope.workflowId+'.workflow-step');
+        let arrows = makeArrows($scope.workflow, steps, { width: $scope.nested 
? 32 : 56 });
 
         svg.innerHTML = arrows.join('\n');
     }
 }
 
-function makeArrows(workflow, steps) {
+function makeArrows(workflow, steps, options) {
+    const sectionWidth = ((options || {}).width) || 56;
     workflow = workflow || {};
     workflow.data = workflow.data || {};
 
@@ -105,7 +108,7 @@ function makeArrows(workflow, steps) {
             if (!opts) opts = {};
             const color = opts.class ? '' : opts.color || (opts.colorEnd && 
opts.colorEnd==opts.colorStart ? opts.colorEnd : '#000');
 
-            const rightFarEdge = 56;
+            const rightFarEdge = sectionWidth;
             const rightArrowheadStart = rightFarEdge - arrowheadLength;
             const leftFarEdge = 10;
             const leftActive = rightArrowheadStart + (leftFarEdge - 
rightArrowheadStart) * (opts.width || 1);
@@ -250,6 +253,7 @@ function makeArrows(workflow, steps) {
         var indexOfId = {};
         for (var i = 0; i < steps.length; i++) {
             const s = workflow.data.stepsDefinition[i];
+            if (!s) console.log("XXX missing step", i, workflow.data, steps);
             if (s.id) indexOfId[s.id] = i;
         }
 
diff --git 
a/ui-modules/app-inspector/app/components/workflow/workflow-steps.less 
b/ui-modules/app-inspector/app/components/workflow/workflow-steps.less
index 643135bd..a2d73e0e 100644
--- a/ui-modules/app-inspector/app/components/workflow/workflow-steps.less
+++ b/ui-modules/app-inspector/app/components/workflow/workflow-steps.less
@@ -35,6 +35,11 @@
     padding-top: 5px;
     padding-bottom: 5px;
 
+    .workflow-steps .workflow-step {
+      // when nested, smaller right margin
+      margin-right: 36px;
+    }
+
     border: solid @gray-light-lighter 1px;
 
     .rhs-icons {
@@ -78,7 +83,7 @@
       visibility: hidden;
       //display: none;
     }
-    &:hover .step-id.hover-only {
+    &:hover > .rhs-icons > .step-id.hover-only {
       visibility: visible;
       display: inherit;
     }
diff --git 
a/ui-modules/app-inspector/app/components/workflow/workflow-steps.template.html 
b/ui-modules/app-inspector/app/components/workflow/workflow-steps.template.html
index b571686e..fcddb1bf 100644
--- 
a/ui-modules/app-inspector/app/components/workflow/workflow-steps.template.html
+++ 
b/ui-modules/app-inspector/app/components/workflow/workflow-steps.template.html
@@ -17,15 +17,14 @@
   under the License.
 -->
 <div class="workflow-steps" ng-class="vm.getWorkflowStepsClasses()">
-
     <svg width="100%" height="100%" style="position: absolute;" 
class="workflow-arrows">
-        <g transform="scale(-1,1)" transform-origin="center" 
id="workflow-step-arrows">
+        <g transform="scale(-1,1)" transform-origin="center" 
class="workflow-{{workflowId}}" id="workflow-step-arrows">
         </g>
     </svg>
 
     <div style="position: relative;">
         <div ng-if="workflow.data.stepsDefinition" class="workflow-steps-main">
-            <div ng-repeat="step in workflow.data.stepsDefinition track by 
$index" id="workflow-step-outer-{{$index}}">
+            <div ng-repeat="step in workflow.data.stepsDefinition track by 
$index" id="workflow-{{workflowId}}-step-outer-{{$index}}">
                 <workflow-step workflow="workflow" task="task" step="step" 
step-index="$index" expanded="expandStates[$index]" 
on-size-change="vm.onSizeChange"></workflow-step>
             </div>
         </div>
diff --git 
a/ui-modules/app-inspector/app/views/main/inspect/activities/detail/detail.controller.js
 
b/ui-modules/app-inspector/app/views/main/inspect/activities/detail/detail.controller.js
index b6c870ee..11b46ec0 100644
--- 
a/ui-modules/app-inspector/app/views/main/inspect/activities/detail/detail.controller.js
+++ 
b/ui-modules/app-inspector/app/views/main/inspect/activities/detail/detail.controller.js
@@ -159,7 +159,7 @@ function DetailController($scope, $state, $stateParams, 
$location, $log, $uibMod
                     let osi = vm.model.workflow.data.oldStepInfo;
                     vm.model.workflow.finishedWithNoSteps = ((osi["-2"] || 
{}).previous || [])[0] == -1;
 
-                        $scope.actions.workflowReplays = [];
+                    $scope.actions.workflowReplays = [];
                     if (vm.model.workflow.data.status !== 'RUNNING') {
 
                         $scope.actions.workflowReplays = [];

Reply via email to