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 8e475be57e5f8787b20a2021143dcda653f03de2
Author: Mykola Mandra <[email protected]>
AuthorDate: Tue Apr 27 14:26:53 2021 +0100

    Support child/parent flip when parent is hosted under child in 
'host_for/hosted_on' relationship
    
    Signed-off-by: Mykola Mandra <[email protected]>
---
 .../app/components/entity-tree/entity-node.html    |   8 +-
 .../entity-tree/entity-tree.directive.js           | 120 ++++++++++++++++-----
 2 files changed, 100 insertions(+), 28 deletions(-)

diff --git 
a/ui-modules/app-inspector/app/components/entity-tree/entity-node.html 
b/ui-modules/app-inspector/app/components/entity-tree/entity-node.html
index 3f11c35..69ccc43 100644
--- a/ui-modules/app-inspector/app/components/entity-tree/entity-node.html
+++ b/ui-modules/app-inspector/app/components/entity-tree/entity-node.html
@@ -25,7 +25,9 @@
             <span class="node-icon"><img ng-src="{{ iconUrl }}"/></span>
         </a>
         <div class="entity-node-toggle-wrapper">
-          <div class="entity-node-toggle" 
ng-if="entitiesInCurrentView(entity.children) > 0 || 
entitiesInCurrentView(entity.members) > 0" ng-click="onToggle($event)" >
+          <div class="entity-node-toggle"
+               ng-if="entitiesInCurrentView(entity.children) > 0 || 
entitiesInCurrentView(entity.members) > 0 || 
entitiesInCurrentView(entity.otherNodes) > 0"
+               ng-click="onToggle($event)" >
             <span class="glyphicon" ng-class="isChildrenOpen ? 
'glyphicon-chevron-up' : 'glyphicon-chevron-down'"></span>
           </div>
         </div>
@@ -39,6 +41,10 @@
         <entity-node ng-repeat="child in entity.members track by child.id"
                      ng-show="child.viewModes.has(viewMode) && 
(!entity.children || entity.children.length === 0)"
                      entity="child" application-id="applicationId" 
view-mode="viewMode"></entity-node>
+        <!-- Other nodes under entity -->
+        <entity-node ng-repeat="child in entity.otherNodes track by child.id"
+                     ng-show="child.viewModes.has(viewMode)"
+                     entity="child" application-id="applicationId" 
view-mode="viewMode"></entity-node>
     </div>
     <script type="text/ng-template" id="EntityNodeInfoTemplate.html">
         <table ng-if="isOpen" class="info-table">
diff --git 
a/ui-modules/app-inspector/app/components/entity-tree/entity-tree.directive.js 
b/ui-modules/app-inspector/app/components/entity-tree/entity-tree.directive.js
index 07ba97d..eeec3c6 100644
--- 
a/ui-modules/app-inspector/app/components/entity-tree/entity-tree.directive.js
+++ 
b/ui-modules/app-inspector/app/components/entity-tree/entity-tree.directive.js
@@ -120,6 +120,7 @@ export function entityTreeDirective() {
                 if ($scope.viewModes.has(VIEW_HOST_FOR_HOSTED_ON)) {
                     addHostForHostedOnView(entities, relationships);
                 }
+                console.log('-------------THE END-------------------------');
             }
 
             /**
@@ -129,16 +130,15 @@ export function entityTreeDirective() {
              * @returns {Array.<Object>} The array of all entities found in 
the tree.
              */
             function entityTreeToArray(entities) {
-                let children = [];
+                let nodes = [];
                 if (!Array.isArray(entities) || entities.length === 0) {
-                    return children;
+                    return nodes;
                 }
                 entities.forEach(entity => {
-                    children = 
children.concat(entityTreeToArray(entity.children));
-                    children = 
children.concat(entityTreeToArray(entity.members));
-                })
-
-                return entities.concat(children);
+                    nodes = nodes.concat(entityTreeToArray(entity.children));
+                    nodes = nodes.concat(entityTreeToArray(entity.members));
+                });
+                return entities.concat(nodes);
             }
 
             /**
@@ -149,46 +149,100 @@ export function entityTreeDirective() {
              * @param {Array.<Object>} relationships The relationships of 
entities.
              */
             function addHostForHostedOnView(entities, relationships) {
+
+                // Look through all entities found in the entity tree
                 entities.forEach(entity => {
+
+                    // Check if entity has 'host_for/hosted_on' relationship.
                     let relationship = relationships.find(r => r.id === 
entity.id);
                     if (relationship && relationship.name === 
RELATIONSHIP_HOST_FOR) {
+
+                        // Label every 'host_for' entity to display and 
highlight in 'host_for/hosted_on' view mode.
                         displayEntityInView(entity, VIEW_HOST_FOR_HOSTED_ON);
                         highlightEntityInView(entity, VIEW_HOST_FOR_HOSTED_ON);
 
+                        // Look for 'hosted_on' entities under 'host_for', 
flip of move them and label to display in
+                        // 'host_for/hosted_on' view mode respectively.
                         relationship.targets.forEach(target => {
-                            let child = entities.find(e => e.id === target);
-                            if (child) {
-                                highlightEntityInView(child, 
VIEW_HOST_FOR_HOSTED_ON);
-                                if (child.parentId !== entity.id) { // Move 
(copy) child under 'hosted_on' entity.
-                                    let childCopy = Object.assign({}, child); 
// Copy entity
-
-                                    // Display in 'host_for/hosted_on' view 
only.
-                                    childCopy.viewModes = null;
-                                    displayEntityInView(childCopy, 
VIEW_HOST_FOR_HOSTED_ON);
-
-                                    let parent = findEntity(entities, 
child.parentId);
-                                    if (parent) {
-                                        childCopy.name += ' (' + parent.name + 
')';
-                                    }
+                            let relatedEntity = entities.find(e => e.id === 
target);
+                            if (relatedEntity) {
+                                highlightEntityInView(relatedEntity, 
VIEW_HOST_FOR_HOSTED_ON);
+                                displayParentsInView(entities, 
relatedEntity.parentId, VIEW_HOST_FOR_HOSTED_ON);
+
+                                // Re-arrange the tree if related 'hosted_on' 
entity is not a child of 'host_for'.
+                                if (relatedEntity.parentId !== entity.id) {
 
-                                    if (!entity.children) {
-                                        entity.children = [childCopy];
+                                    if (relatedEntity.id === entity.parentId) {
+                                        // 4.1. Flip 'hosted_on' parent with a 
'host_for' child.
+                                        flipParentAndChild(relatedEntity, 
entity, entities, VIEW_HOST_FOR_HOSTED_ON);
                                     } else {
-                                        entity.children.push(childCopy);
+                                        // 4.2. Move 'hosted_on' entity to a 
new 'host_for' parent.
+                                        moveEntityToParent(relatedEntity, 
entity, entities, VIEW_HOST_FOR_HOSTED_ON);
                                     }
                                 }
-                                displayParentsInView(entities, child.parentId, 
VIEW_HOST_FOR_HOSTED_ON);
                             }
                         });
                     } else if (!relationship || relationship.name !== 
RELATIONSHIP_HOSTED_ON) {
-                        // Display original position for any other entity 
under 'host_for/hosted_on' view.
+
+                        // Display original position for any other entity 
under 'host_for/hosted_on' view. Do no highlight
+                        // entities that are required to be displayed but do 
not belong to this view.
                         displayEntityInView(entity, VIEW_HOST_FOR_HOSTED_ON);
-                        // Spotlight will never be on entities that are 
required to be displayed but do not belong to this view.
                     }
                 });
             }
 
             /**
+             * Flips parent entity with its child.
+             *
+             * @param parent The parent entity to flip with its child.
+             * @param child The child entity to flip with its parent.
+             * @param {Array.<Object>} entities The entity tree converted to 
array.
+             * @param {string} viewMode The view mode to display copy of the 
entity in only.
+             */
+            function flipParentAndChild(parent, child, entities, viewMode) {
+                console.log('Flip parent with a child!', parent, child);
+                let parentOfTheParent = findEntity(entities, parent.parentId);
+                if (parentOfTheParent) {
+                    hideEntityInView(child, viewMode);
+                    let childCopy = moveEntityToParent(child, 
parentOfTheParent, entities, viewMode);
+                    moveEntityToParent(parent, childCopy, entities, viewMode);
+                }
+            }
+
+            /**
+             * Moves entity to a new parent, creates copy of the entity under 
parent.otherNodes.
+             *
+             * @param {Object} entity The entity to move.
+             * @param {Object} parent The parent to move entity to.
+             * @param {Array.<Object>} entities The entity tree converted to 
array.
+             * @param {string} viewMode The view mode to display copy of the 
entity in only.
+             * @returns {Object} The copy of the entity under 
parent.otherNodes.
+             */
+            function moveEntityToParent(entity, parent, entities, viewMode) {
+                // 1. Create a copy.
+                let entityCopy = Object.assign({}, entity);
+
+                // 2. Include the name of the original parent.
+                let parentOfEntity = findEntity(entities, entityCopy.parentId);
+                if (parentOfEntity) {
+                    entityCopy.name += ' (' + parentOfEntity.name + ')';
+                }
+
+                // 3. Label it to display in a view mode specified only.
+                entityCopy.viewModes = null;
+                displayEntityInView(entityCopy, viewMode);
+
+                // 4. Add copy under otherNodes.
+                if (!parent.otherNodes) {
+                    parent.otherNodes = [entityCopy];
+                } else {
+                    parent.otherNodes.push(entityCopy);
+                }
+
+                return entityCopy;
+            }
+
+            /**
              * Labels all parents to display for a particular view mode 
starting from a specified ID, traverses the node
              * tree recursively, bottom-up.
              *
@@ -216,6 +270,18 @@ export function entityTreeDirective() {
             }
 
             /**
+             * Labels entity to not display in particular view mode.
+             *
+             * @param {Object} entity The entity to label.
+             * @param {string} viewMode The view mode to not display entity in.
+             */
+            function hideEntityInView(entity, viewMode) {
+                if (entity.viewModes) {
+                    entity.viewModes.delete(viewMode);
+                }
+            }
+
+            /**
              * Labels entity to display in particular view mode.
              *
              * @param {Object} entity The entity to label.

Reply via email to