re base code
[sdc.git] / catalog-ui / src / app / directives / graphs-v2 / deployment-graph / deployment-graph.directive.ts
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 import * as _ from "lodash";
22 import { Component, Module, NodesFactory, ComponentInstance } from "app/models";
23 import { ComponentInstanceFactory } from "app/utils";
24 import { DeploymentGraphGeneralUtils } from "./deployment-utils/deployment-graph-general-utils";
25 import { CommonGraphUtils } from "../common/common-graph-utils";
26 import { ComponentInstanceNodesStyle } from "../common/style/component-instances-nodes-style";
27 import { ModulesNodesStyle } from "../common/style/module-node-style";
28 import { GRAPH_EVENTS } from "app/utils";
29 import { EventListenerService } from "app/services";
30 import '@bardit/cytoscape-expand-collapse';
31 import {AngularJSBridge} from "../../../services/angular-js-bridge-service";
32
33 interface IDeploymentGraphScope extends ng.IScope {
34     component: Component;
35 }
36
37 export class DeploymentGraph implements ng.IDirective {
38     private _cy: Cy.Instance;
39
40     constructor(private NodesFactory: NodesFactory,
41         private commonGraphUtils: CommonGraphUtils,
42         private deploymentGraphGeneralUtils: DeploymentGraphGeneralUtils,
43         private ComponentInstanceFactory: ComponentInstanceFactory,
44         private eventListenerService: EventListenerService) {
45     }
46
47     restrict = 'E';
48     template = require('./deployment-graph.html');
49     scope = {
50         component: '=',
51         isViewOnly: '='
52     };
53
54     link = (scope: IDeploymentGraphScope, el: JQuery) => {
55
56         if (scope.component.isResource()) {
57             if (scope.component.componentInstances && scope.component.componentInstancesRelations && scope.component.modules) {
58                 this.loadGraph(scope, el);
59             } else {
60                 this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_DEPLOYMENT_GRAPH_DATA_LOADED, () => {
61                     this.loadGraph(scope, el);
62                 });
63             }
64         }
65     };
66
67     public initGraphNodes = (cy: Cy.Instance, component: Component): void => {
68         if (component.modules) { // Init module nodes
69             _.each(component.modules, (groupModule: Module) => {
70                 let moduleNode = this.NodesFactory.createModuleNode(groupModule);
71                 this.commonGraphUtils.addNodeToGraph(cy, moduleNode);
72
73             });
74         }
75         _.each(component.componentInstances, (instance: ComponentInstance) => { // Init component instance nodes
76             let componentInstanceNode = this.NodesFactory.createNode(instance);
77             componentInstanceNode.parent = this.deploymentGraphGeneralUtils.findInstanceModule(component.modules, instance.uniqueId);
78             if (componentInstanceNode.parent) { // we are not drawing instances that are not a part of a module
79                 this.commonGraphUtils.addComponentInstanceNodeToGraph(cy, componentInstanceNode);
80             }
81         });
82
83         // This is a special functionality to pass the cytoscape default behavior - we can't create Parent module node without children's
84         // so we must add an empty dummy child node
85         _.each(this._cy.nodes('[?isGroup]'), (moduleNode: Cy.CollectionFirstNode) => {
86             if (!moduleNode.isParent()) {
87                 let dummyInstance = this.ComponentInstanceFactory.createEmptyComponentInstance();
88                 let componentInstanceNode = this.NodesFactory.createNode(dummyInstance);
89                 componentInstanceNode.parent = moduleNode.id();
90                 let dummyNode = this.commonGraphUtils.addNodeToGraph(cy, componentInstanceNode, moduleNode.position());
91                 dummyNode.addClass('dummy-node');
92             }
93         })
94     };
95
96     private registerGraphEvents() {
97
98         this._cy.on('afterExpand', (event) => {
99             event.cyTarget.qtip({});
100         });
101
102         this._cy.on('afterCollapse', (event) => {
103             this.commonGraphUtils.initNodeTooltip(event.cyTarget);
104         });
105     }
106
107     private loadGraph = (scope: IDeploymentGraphScope, el: JQuery) => {
108
109         let graphEl = el.find('.sdc-deployment-graph-wrapper');
110         const imagePath = AngularJSBridge.getAngularConfig().imagesPath;
111         this._cy = cytoscape({
112             container: graphEl,
113             style: ComponentInstanceNodesStyle.getCompositionGraphStyle().concat(ModulesNodesStyle.getModuleGraphStyle()),
114             zoomingEnabled: false,
115             selectionType: 'single',
116
117         });
118
119         //adding expand collapse extension
120         this._cy.expandCollapse({
121             layoutBy: {
122                 name: "grid",
123                 animate: true,
124                 randomize: false,
125                 fit: true
126             },
127             fisheye: false,
128             undoable: false,
129             expandCollapseCueSize: 18,
130             expandCueImage: imagePath + '/assets/styles/images/resource-icons/' + 'closeModule.png',
131             collapseCueImage: imagePath + '/assets/styles/images/resource-icons/' + 'openModule.png',
132             expandCollapseCueSensitivity: 2,
133             cueOffset: -20
134         });
135
136         this.initGraphNodes(this._cy, scope.component); //creating instances nodes
137         this.commonGraphUtils.initGraphLinks(this._cy, scope.component.componentInstancesRelations, scope.component.getRelationRequirementCapability.bind(scope.component));
138         this._cy.collapseAll();
139         this.registerGraphEvents();
140
141         scope.$on('$destroy', () => {
142             this._cy.destroy();
143             _.forEach(GRAPH_EVENTS, (event) => {
144                 this.eventListenerService.unRegisterObserver(event);
145             });
146         });
147
148     };
149
150     public static factory = (NodesFactory: NodesFactory, CommonGraphUtils: CommonGraphUtils, DeploymentGraphGeneralUtils: DeploymentGraphGeneralUtils, ComponentInstanceFactory: ComponentInstanceFactory, EventListenerService: EventListenerService) => {
151         return new DeploymentGraph(NodesFactory, CommonGraphUtils, DeploymentGraphGeneralUtils, ComponentInstanceFactory, EventListenerService)
152     }
153 }
154
155 DeploymentGraph.factory.$inject = ['NodesFactory', 'CommonGraphUtils', 'DeploymentGraphGeneralUtils', 'ComponentInstanceFactory', 'EventListenerService'];