aboutsummaryrefslogtreecommitdiffstats
path: root/catalog-ui/src/app/directives/structure-tree
diff options
context:
space:
mode:
Diffstat (limited to 'catalog-ui/src/app/directives/structure-tree')
-rw-r--r--catalog-ui/src/app/directives/structure-tree/structure-tree-directive.html54
-rw-r--r--catalog-ui/src/app/directives/structure-tree/structure-tree-directive.less68
-rw-r--r--catalog-ui/src/app/directives/structure-tree/structure-tree-directive.ts195
3 files changed, 317 insertions, 0 deletions
diff --git a/catalog-ui/src/app/directives/structure-tree/structure-tree-directive.html b/catalog-ui/src/app/directives/structure-tree/structure-tree-directive.html
new file mode 100644
index 0000000000..7d8a883b33
--- /dev/null
+++ b/catalog-ui/src/app/directives/structure-tree/structure-tree-directive.html
@@ -0,0 +1,54 @@
+<div class="structure-tree">
+ <div class="component-container">
+ <div class="{{component.iconSprite}} small" ng-class="structureTree.serviceRoot.icon"></div>
+ <div class="component-container-text" tooltip-class="tooltip-custom break-word-tooltip" tooltips tooltip-content="&#8203;{{structureTree.serviceRoot.name}}"> {{structureTree.serviceRoot.name}}</div>
+ </div>
+ <ul>
+ <li data-ng-repeat="firstLevelResourcesInstances in structureTree.serviceRoot.resourceInstancesList">
+ <div class="component-container">
+ <div class="small {{firstLevelResourcesInstances.icon}}" ng-class="{'sprite-resource-icons': !component.isProduct(), 'sprite-services-icons': component.isProduct()}">
+ <div data-ng-class="{'non-certified':!firstLevelResourcesInstances.certified}"
+ tooltips tooltip-side="top" tooltip-content="Not certified">
+ </div>
+ </div>
+ <div class="component-container-text" tooltips tooltip-content="{{firstLevelResourcesInstances.name}}" > {{firstLevelResourcesInstances.name}} </div>
+ </div>
+ <ul>
+ <li data-ng-repeat="secondLevelResourcesInstances in firstLevelResourcesInstances.resourceInstancesList">
+ <div class="component-container">
+ <div class="sprite-resource-icons small" ng-class="secondLevelResourcesInstances.icon">
+ <div data-ng-class="{'non-certified':!secondLevelResourcesInstances.certified}"
+ tooltips tooltip-side="top" tooltip-content="Not certified">
+ </div>
+ </div>
+ <div class="component-container-text" tooltips tooltip-content="{{secondLevelResourcesInstances.name}}"> {{secondLevelResourcesInstances.name}} </div>
+ </div>
+ <ul>
+ <li data-ng-repeat="thirdLevelResourcesInstances in secondLevelResourcesInstances.resourceInstancesList">
+ <div class="component-container">
+ <div class="sprite-resource-icons small" ng-class="thirdLevelResourcesInstances.icon">
+ <div data-ng-class="{'non-certified':!thirdLevelResourcesInstances.certified}"
+ tooltips tooltip-side="top" tooltip-content="Not certified">
+ </div>
+ </div>
+ <div class="component-container-text" tooltips tooltip-content="{{thirdLevelResourcesInstances.name}}" > {{thirdLevelResourcesInstances.name}} </div>
+ </div>
+ <ul>
+ <li data-ng-repeat="forthLevelResourcesInstances in thirdLevelResourcesInstances.resourceInstancesList">
+ <div class="component-container">
+ <div class="sprite-resource-icons small" ng-class="forthLevelResourcesInstances.icon">
+ <div data-ng-class="{'non-certified':!forthLevelResourcesInstances.certified}"
+ tooltips tooltip-side="top" tooltip-content="Not certified">
+ </div>
+ </div>
+ <div class="component-container-text" tooltips tooltip-content="{{forthLevelResourcesInstances.name}}"> {{forthLevelResourcesInstances.name}} </div>
+ </div>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ </ul>
+</div>
diff --git a/catalog-ui/src/app/directives/structure-tree/structure-tree-directive.less b/catalog-ui/src/app/directives/structure-tree/structure-tree-directive.less
new file mode 100644
index 0000000000..094c3f70ba
--- /dev/null
+++ b/catalog-ui/src/app/directives/structure-tree/structure-tree-directive.less
@@ -0,0 +1,68 @@
+.structure-tree{
+ padding: 9px 0px 10px 30px;
+ position: relative;
+ ul{
+ position: relative;
+ list-style: none;
+ padding-left:25px;
+ ::before{
+ content: "";
+ position: absolute;
+ left: -27px;
+ }
+ ::after{
+ content: "";
+ position: absolute;
+ left: -27px;
+ }
+ li{
+ position: relative;
+ &::before{
+ border-top: 1px solid #666666;
+ top: 20px;
+ width: 10px;
+ height: 0;
+ }
+ &::after{
+ border-left: 1px solid #666666;
+ height: 100%;
+ width: 0px;
+ top: -2px;
+ }
+ &:last-child::after{
+ height: 23px
+ }
+ }
+ }
+ .component-container{
+ display: inline-block;
+ margin: 6px 0px 0px -16px;
+ }
+ .component-container-icon{
+ display: inline-block;
+ }
+ .component-container-text{
+ padding-left: 8px;
+ float: right;
+
+ text-overflow: ellipsis;
+ max-width:120px;
+ display: inline-block;
+ white-space: nowrap;
+ font-size: 13px;
+ color: #666666;;
+ overflow: hidden;
+ line-height: 28px;
+ float: none;
+ }
+
+ .non-certified{
+ position: relative;
+ left: 18px;
+ bottom: 8px;
+ .sprite;
+ .s-sdc-state-non-certified;
+ display:block;
+ }
+
+}
diff --git a/catalog-ui/src/app/directives/structure-tree/structure-tree-directive.ts b/catalog-ui/src/app/directives/structure-tree/structure-tree-directive.ts
new file mode 100644
index 0000000000..4d6fbee4db
--- /dev/null
+++ b/catalog-ui/src/app/directives/structure-tree/structure-tree-directive.ts
@@ -0,0 +1,195 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+'use strict';
+import {RelationshipModel, Component, ComponentInstance} from "app/models";
+import {Dictionary} from "app/utils";
+
+
+export interface IStructureTreeScope extends ng.IScope {
+
+ component:Component;
+ structureTree:StructureTree;
+}
+
+class StructureTree {
+
+ serviceRoot:ResourceInstanceNode;
+
+ constructor(private uniqueId:string, private resourceInstanceName:string, private resourceInstanceIcon:string, private certified:boolean) {
+ this.serviceRoot = new ResourceInstanceNode(uniqueId, resourceInstanceName, resourceInstanceIcon, certified);
+ }
+
+}
+
+class ResourceInstanceNode {
+ id:string;
+ icon:string;
+ name:string;
+ resourceInstancesList:Array<ResourceInstanceNode>;
+ isAlreadyInTree:boolean;
+ certified:boolean;
+
+
+ constructor(private uniqueId:string, private resourceInstanceName:string, private resourceInstanceIcon:string, certified:boolean) {
+ this.id = uniqueId;
+ this.name = resourceInstanceName;
+ this.icon = resourceInstanceIcon;
+ this.resourceInstancesList = [];
+ this.isAlreadyInTree = false;
+ this.certified = certified;
+ }
+}
+
+export class StructureTreeDirective implements ng.IDirective {
+
+
+ constructor() {
+ }
+
+ scope = {
+ component: '=',
+ };
+ restrict = 'E';
+ template = ():string => {
+ return require('./structure-tree-directive.html');
+ };
+
+ link = (scope:IStructureTreeScope, $elem:any) => {
+
+ let RESOURCE_INSTANCE_LIST:string = "resourceInstancesChildesList";
+ let resourceInstanceMap:Dictionary<string, ResourceInstanceNode>;
+ let relations:Array<RelationshipModel>;
+ //************* Start Building Tree Functions *******************//
+
+ //remove unnecessary instances
+ let initResourceInstanceMap = ():void => {
+
+ resourceInstanceMap = new Dictionary<string, ResourceInstanceNode>();
+
+ _.forEach(scope.component.componentInstances, (resourceInstance:ComponentInstance)=> {
+ if (_.some(Object.keys(resourceInstance.capabilities), (key:string)=> {
+ return 'tosca.capabilities.container' == key.toLowerCase();
+ }) || _.some(Object.keys(resourceInstance.requirements), (key:string)=> {
+ return 'tosca.capabilities.container' == key.toLowerCase();
+ })) {
+
+ let isCertified = 0 === (parseFloat(resourceInstance.componentVersion) % 1);
+ let node:ResourceInstanceNode = new ResourceInstanceNode(resourceInstance.uniqueId,
+ resourceInstance.name,
+ resourceInstance.icon,
+ isCertified);
+ resourceInstanceMap.setValue(resourceInstance.uniqueId, node);
+ }
+ });
+ };
+
+ //remove unnecessary relations
+ let initRelations = ():void => {
+ relations = _.filter(scope.component.componentInstancesRelations, (relation:RelationshipModel)=> {
+ return resourceInstanceMap.containsKey(relation.fromNode) && resourceInstanceMap.containsKey(relation.toNode);
+ });
+ };
+
+ let buildTree = ():void => {
+ if (scope.component) {
+ scope.structureTree = new StructureTree(scope.component.uniqueId, scope.component.name, scope.component.icon, 'CERTIFIED' === scope.component.lifecycleState);
+ initResourceInstanceMap();
+ initRelations();
+
+ let parentNodesList = _.groupBy(relations, (node:any)=> {
+ return node.fromNode;
+ });
+
+ for (let parent in parentNodesList) {
+ _.forEach(parentNodesList[parent], (childNode)=> {
+ parentNodesList[parent][RESOURCE_INSTANCE_LIST] = [];
+ parentNodesList[parent][RESOURCE_INSTANCE_LIST].push(mergeAllSubtrees(childNode, parentNodesList));
+ });
+ }
+
+ //add the resourceInstanceList for the service root node
+ for (let parent in parentNodesList) {
+ let resourceInstanceNode:ResourceInstanceNode = resourceInstanceMap.getValue(parent);
+ resourceInstanceNode.resourceInstancesList = parentNodesList[parent];
+ resourceInstanceNode.resourceInstancesList = parentNodesList[parent][RESOURCE_INSTANCE_LIST];
+ resourceInstanceNode.isAlreadyInTree = true;
+ scope.structureTree.serviceRoot.resourceInstancesList.push(resourceInstanceNode);
+ }
+
+ // Add all node that have no connection to the rootNode
+ resourceInstanceMap.forEach((key:string, value:ResourceInstanceNode) => {
+ if (!value.isAlreadyInTree) {
+ scope.structureTree.serviceRoot.resourceInstancesList.push(value);
+ }
+ });
+ }
+ };
+
+ //this recursion is merging all the subtrees
+ let mergeAllSubtrees = (connectionData:any, parentNodesList:any):ResourceInstanceNode => {
+ let resourceInstanceNode:ResourceInstanceNode = resourceInstanceMap.getValue(connectionData.toNode);
+ resourceInstanceNode.isAlreadyInTree = true;
+ if (parentNodesList[resourceInstanceNode.id]) {
+ if (parentNodesList[resourceInstanceNode.id][RESOURCE_INSTANCE_LIST]) {
+ resourceInstanceNode.resourceInstancesList = parentNodesList[resourceInstanceNode.id][RESOURCE_INSTANCE_LIST];
+ }
+ else {
+ _.forEach(parentNodesList[resourceInstanceNode.id], (children)=> {
+ resourceInstanceNode.resourceInstancesList.push(mergeAllSubtrees(children, parentNodesList));
+ });
+ }
+ delete parentNodesList[resourceInstanceNode.id];
+ }
+ return resourceInstanceNode;
+ };
+ //************* End Building Tree Functions *******************//
+
+ //************* Start Watchers *******************//
+ scope.$watch('component.name', ():void => {
+ if (scope.structureTree)
+ scope.structureTree.serviceRoot.name = scope.component.name;
+ });
+
+ scope.$watch('component.icon', ():void => {
+ if (scope.structureTree)
+ scope.structureTree.serviceRoot.icon = scope.component.icon;
+ });
+
+ scope.$watchCollection('component.componentInstancesRelations', ():void => {
+ buildTree();
+ });
+
+ scope.$watchCollection('component.componentInstances', ():void => {
+ buildTree();
+ });
+
+ //************* End Watchers *******************//
+
+ buildTree();
+
+ };
+
+
+ public static factory = () => {
+ return new StructureTreeDirective();
+ };
+}
+
+StructureTreeDirective.factory.$inject = [];