aboutsummaryrefslogtreecommitdiffstats
path: root/catalog-ui/src/app/directives/graphs-v2/deployment-graph/deployment-graph.directive.ts
blob: 5ad6570013c412ab47af6d5c17ff27f4067862d4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import {Component, Module, NodesFactory, ComponentInstance} from "app/models";
import {ComponentInstanceFactory} from "app/utils";
import {DeploymentGraphGeneralUtils} from "./deployment-utils/deployment-graph-general-utils";
import {CommonGraphUtils} from "../common/common-graph-utils";
import {ComponentInstanceNodesStyle} from "../common/style/component-instances-nodes-style";
import {ModulesNodesStyle} from "../common/style/module-node-style";
import {GRAPH_EVENTS} from "app/utils";
import {EventListenerService} from "app/services";
import 'cytoscape-expand-collapse';

interface IDeploymentGraphScope extends ng.IScope {
    component:Component;
}

export class DeploymentGraph implements ng.IDirective {
    private _cy:Cy.Instance;

    constructor(private NodesFactory:NodesFactory, private commonGraphUtils:CommonGraphUtils,
                private deploymentGraphGeneralUtils:DeploymentGraphGeneralUtils, private ComponentInstanceFactory:ComponentInstanceFactory, private eventListenerService:EventListenerService) {
    }

    restrict = 'E';
    template = require('./deployment-graph.html');
    scope = {
        component: '=',
        isViewOnly: '='
    };

    link = (scope:IDeploymentGraphScope, el:JQuery) => {

        if (scope.component.isResource()) {
            if (scope.component.componentInstances && scope.component.componentInstancesRelations && scope.component.groups) {
                this.loadGraph(scope, el);
            } else {
                this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_DEPLOYMENT_GRAPH_DATA_LOADED, () => {
                    this.loadGraph(scope, el);
                });
            }
        }
    };


    public initGraphNodes = (cy:Cy.Instance, component:Component):void => {
        if (component.groups) { // Init module nodes
            _.each(component.groups, (groupModule:Module) => {
                let moduleNode = this.NodesFactory.createModuleNode(groupModule);
                this.commonGraphUtils.addNodeToGraph(cy, moduleNode);

            });
        }
        _.each(component.componentInstances, (instance:ComponentInstance) => { // Init component instance nodes
            let componentInstanceNode = this.NodesFactory.createNode(instance);
            componentInstanceNode.parent = this.deploymentGraphGeneralUtils.findInstanceModule(component.groups, instance.uniqueId);
            if (componentInstanceNode.parent) { // we are not drawing instances that are not a part of a module
                this.commonGraphUtils.addComponentInstanceNodeToGraph(cy, componentInstanceNode);
            }
        });

        // This is a special functionality to pass the cytoscape default behavior - we can't create Parent module node without children's
        // so we must add an empty dummy child node
        _.each(this._cy.nodes('[?isGroup]'), (moduleNode:Cy.CollectionFirstNode) => {
            if (!moduleNode.isParent()) {
                let dummyInstance = this.ComponentInstanceFactory.createEmptyComponentInstance();
                let componentInstanceNode = this.NodesFactory.createNode(dummyInstance);
                componentInstanceNode.parent = moduleNode.id();
                let dummyNode = this.commonGraphUtils.addNodeToGraph(cy, componentInstanceNode, moduleNode.position());
                dummyNode.addClass('dummy-node');
            }
        })
    };

    private registerGraphEvents() {

        this._cy.on('afterExpand', (event) => {
            event.cyTarget.qtip({});
        });

        this._cy.on('afterCollapse', (event) => {
            this.commonGraphUtils.initNodeTooltip(event.cyTarget);
        });
    }

    private loadGraph = (scope:IDeploymentGraphScope, el:JQuery) => {

        let graphEl = el.find('.sdc-deployment-graph-wrapper');
        this._cy = cytoscape({
            container: graphEl,
            style: ComponentInstanceNodesStyle.getCompositionGraphStyle().concat(ModulesNodesStyle.getModuleGraphStyle()),
            zoomingEnabled: false,
            selectionType: 'single',

        });

        //adding expand collapse extension
        this._cy.expandCollapse({
            layoutBy: {
                name: "grid",
                animate: true,
                randomize: false,
                fit: true
            },
            fisheye: false,
            undoable: false,
            expandCollapseCueSize: 18,
            expandCueImage: '/assets/styles/images/resource-icons/' + 'closeModule.png',
            collapseCueImage: '/assets/styles/images/resource-icons/' + 'openModule.png',
            expandCollapseCueSensitivity: 2,
            cueOffset: -20
        });

        this.initGraphNodes(this._cy, scope.component); //creating instances nodes
        this.commonGraphUtils.initGraphLinks(this._cy, scope.component.componentInstancesRelations);
        this._cy.collapseAll();
        this.registerGraphEvents();
    };

    public static factory = (NodesFactory:NodesFactory, CommonGraphUtils:CommonGraphUtils, DeploymentGraphGeneralUtils:DeploymentGraphGeneralUtils, ComponentInstanceFactory:ComponentInstanceFactory, EventListenerService:EventListenerService) => {
        return new DeploymentGraph(NodesFactory, CommonGraphUtils, DeploymentGraphGeneralUtils, ComponentInstanceFactory, EventListenerService)
    }
}

DeploymentGraph.factory.$inject = ['NodesFactory', 'CommonGraphUtils', 'DeploymentGraphGeneralUtils', 'ComponentInstanceFactory', 'EventListenerService'];