aboutsummaryrefslogtreecommitdiffstats
path: root/catalog-ui/app/scripts/directives/graphs-v2/common
diff options
context:
space:
mode:
Diffstat (limited to 'catalog-ui/app/scripts/directives/graphs-v2/common')
-rw-r--r--catalog-ui/app/scripts/directives/graphs-v2/common/common-graph-utils.ts361
-rw-r--r--catalog-ui/app/scripts/directives/graphs-v2/common/style/component-instances-nodes-style.ts259
-rw-r--r--catalog-ui/app/scripts/directives/graphs-v2/common/style/module-node-style.ts92
3 files changed, 712 insertions, 0 deletions
diff --git a/catalog-ui/app/scripts/directives/graphs-v2/common/common-graph-utils.ts b/catalog-ui/app/scripts/directives/graphs-v2/common/common-graph-utils.ts
new file mode 100644
index 0000000000..e01e455e93
--- /dev/null
+++ b/catalog-ui/app/scripts/directives/graphs-v2/common/common-graph-utils.ts
@@ -0,0 +1,361 @@
+/**
+ * Created by obarda on 12/21/2016.
+ */
+/**
+ * Created by obarda on 12/13/2016.
+ */
+/// <reference path="../../../references"/>
+module Sdc.Graph.Utils {
+
+ export class CommonGraphUtils {
+
+ constructor(private NodesFactory:Sdc.Utils.NodesFactory, private LinksFactory:Sdc.Utils.LinksFactory) {
+
+ }
+
+ public safeApply = (scope:ng.IScope, fn:any) => { //todo remove to general utils
+ let phase = scope.$root.$$phase;
+ if (phase == '$apply' || phase == '$digest') {
+ if (fn && (typeof(fn) === 'function')) {
+ fn();
+ }
+ } else {
+ scope.$apply(fn);
+ }
+ };
+
+ /**
+ * Draw node on the graph
+ * @param cy
+ * @param compositionGraphNode
+ * @param position
+ * @returns {CollectionElements}
+ */
+ public addNodeToGraph(cy:Cy.Instance, compositionGraphNode:Models.Graph.CommonNodeBase, position?:Cy.Position):Cy.CollectionElements {
+
+ var node = cy.add(<Cy.ElementDefinition> {
+ group: 'nodes',
+ position: position,
+ data: compositionGraphNode,
+ classes: compositionGraphNode.classes
+ });
+
+ if(!node.data().isUcpe) { //ucpe should not have tooltip
+ this.initNodeTooltip(node);
+ }
+ return node;
+ };
+
+ /**
+ * The function will create a component instance node by the componentInstance position.
+ * If the node is UCPE the function will create all cp lan&wan for the ucpe
+ * @param cy
+ * @param compositionGraphNode
+ * @returns {Cy.CollectionElements}
+ */
+ public addComponentInstanceNodeToGraph(cy:Cy.Instance, compositionGraphNode:Models.Graph.CompositionCiNodeBase):Cy.CollectionElements {
+
+ let nodePosition = {
+ x: +compositionGraphNode.componentInstance.posX,
+ y: +compositionGraphNode.componentInstance.posY
+ };
+
+ let node = this.addNodeToGraph(cy, compositionGraphNode, nodePosition);
+ if (compositionGraphNode.isUcpe) {
+ this.createUcpeCpNodes(cy, node);
+ }
+ return node;
+ };
+
+ /**
+ * This function will create CP_WAN & CP_LAN for the UCPE. this is a special node on the group that will behave like ports on the ucpe
+ * @param cy
+ * @param ucpeGraphNode
+ */
+ private createUcpeCpNodes(cy:Cy.Instance, ucpeGraphNode:Cy.CollectionNodes):void {
+
+ let requirementsArray:Array<any> = ucpeGraphNode.data().componentInstance.requirements["tosca.capabilities.Node"];
+ //show only LAN or WAN requirements
+ requirementsArray = _.reject(requirementsArray, (requirement:any) => {
+ let name:string = requirement.ownerName.toLowerCase();
+ return name.indexOf('lan') === -1 && name.indexOf('wan') === -1;
+ });
+ requirementsArray.sort(function (a, b) {
+ let nameA = a.ownerName.toLowerCase().match(/[^ ]+/)[0];
+ let nameB = b.ownerName.toLowerCase().match(/[^ ]+/)[0];
+ let numA = _.last(a.ownerName.toLowerCase().split(' '));
+ let numB = _.last(b.ownerName.toLowerCase().split(' '));
+
+ if (nameA === nameB) return numA > numB ? 1 : -1;
+ return nameA < nameB ? 1 : -1;
+ });
+ let position = angular.copy(ucpeGraphNode.boundingbox());
+ //add CP nodes to group
+ let topCps:number = 0;
+ for (let i = 0; i < requirementsArray.length; i++) {
+
+ let cpNode = this.NodesFactory.createUcpeCpNode(angular.copy(ucpeGraphNode.data().componentInstance));
+ cpNode.componentInstance.capabilities = requirementsArray[i];
+ cpNode.id = requirementsArray[i].ownerId;
+ cpNode.group = ucpeGraphNode.data().componentInstance.uniqueId;
+ cpNode.name = requirementsArray[i].ownerName; //for tooltip
+ cpNode.displayName = requirementsArray[i].ownerName;
+ cpNode.displayName = cpNode.displayName.length > 5 ? cpNode.displayName.substring(0, 5) + '...' : cpNode.displayName;
+
+
+ if (cpNode.name.toLowerCase().indexOf('lan') > -1) {
+ cpNode.textPosition = "top";
+ cpNode.componentInstance.posX = position.x1 + (i * 90) - (topCps * 90) + 53;
+ cpNode.componentInstance.posY = position.y1 + 400 + 27;
+ } else {
+ cpNode.textPosition = "bottom";
+ cpNode.componentInstance.posX = position.x1 + (topCps * 90) + 53;
+ cpNode.componentInstance.posY = position.y1 + 27;
+ topCps++;
+ }
+ let cyCpNode = this.addComponentInstanceNodeToGraph(cy, cpNode);
+ cyCpNode.lock();
+ }
+ };
+
+ /**
+ *
+ * @param nodes - all nodes in graph in order to find the edge connecting the two nodes
+ * @param fromNodeId
+ * @param toNodeId
+ * @returns {boolean} true/false if the edge is certified (from node and to node are certified)
+ */
+ public isRelationCertified(nodes:Cy.CollectionNodes, fromNodeId:string, toNodeId:string):boolean {
+ let resourceTemp = _.filter(nodes, function (node:Cy.CollectionFirst) {
+ return node.data().id === fromNodeId || node.data().id === toNodeId;
+ });
+ let certified:boolean = true;
+
+ _.forEach(resourceTemp, (item) => {
+ certified = certified && item.data().certified;
+ });
+
+ return certified;
+ }
+
+ /**
+ * Add link to graph - only draw the link
+ * @param cy
+ * @param link
+ */
+ public insertLinkToGraph = (cy:Cy.Instance, link:Models.CompositionCiLinkBase) => {
+
+ if (!this.isRelationCertified(cy.nodes(), link.source, link.target)) {
+ link.classes = 'not-certified-link';
+ }
+ cy.add({
+ group: 'edges',
+ data: link,
+ classes: link.classes
+ });
+
+ };
+
+ /**
+ * go over the relations and draw links on the graph
+ * @param cy
+ * @param instancesRelations
+ */
+ public initGraphLinks(cy:Cy.Instance, instancesRelations:Array<Models.RelationshipModel>) {
+
+ if (instancesRelations) {
+ _.forEach(instancesRelations, (relationshipModel:Models.RelationshipModel) => {
+ _.forEach(relationshipModel.relationships, (relationship:Models.Relationship) => {
+ let linkToCreate = this.LinksFactory.createGraphLink(cy, relationshipModel, relationship);
+ this.insertLinkToGraph(cy, linkToCreate);
+ });
+ });
+ }
+ }
+
+ /**
+ * Determine which nodes are in the UCPE and set child data for them.
+ * @param cy
+ */
+ public initUcpeChildren(cy:Cy.Instance){
+ let ucpe:Cy.CollectionNodes = cy.nodes('[?isUcpe]'); // Get ucpe on graph if exist
+ _.each(cy.edges('.ucpe-host-link'), (link)=>{
+
+ let ucpeChild:Cy.CollectionNodes = (link.source().id() == ucpe.id())? link.target() : link.source();
+ this.initUcpeChildData(ucpeChild, ucpe);
+
+ //vls dont have ucpe-host-link connection, so need to find them and iterate separately
+ let connectedVLs = ucpeChild.connectedEdges().connectedNodes('.vl-node');
+ _.forEach(connectedVLs, (vl)=>{ //all connected vls must be UCPE children because not allowed to connect to a VL outside of the UCPE
+ this.initUcpeChildData(vl, ucpe);
+ });
+ });
+ }
+
+ /**
+ * Set properties for nodes contained by the UCPE
+ * @param childNode- node contained in UCPE
+ * @param ucpe- ucpe container node
+ */
+ public initUcpeChildData(childNode:Cy.CollectionNodes, ucpe:Cy.CollectionNodes){
+
+ if(!childNode.data('isInsideGroup')){
+ this.updateUcpeChildPosition(childNode, ucpe);
+ childNode.data({isInsideGroup: true});
+ }
+
+ }
+
+ /**
+ * Updates UCPE child node offset, which allows child nodes to be dragged in synchronization with ucpe
+ * @param childNode- node contained in UCPE
+ * @param ucpe- ucpe container node
+ */
+ public updateUcpeChildPosition(childNode:Cy.CollectionNodes, ucpe:Cy.CollectionNodes){
+ let childPos:Cy.Position = childNode.relativePosition();
+ let ucpePos:Cy.Position = ucpe.relativePosition();
+ let offset:Cy.Position = {
+ x: childPos.x - ucpePos.x,
+ y: childPos.y - ucpePos.y
+ };
+ childNode.data("ucpeOffset", offset);
+ }
+
+ /**
+ * Removes ucpe-child properties from the node
+ * @param childNode- node being removed from UCPE
+ */
+ public removeUcpeChildData(childNode:Cy.CollectionNodes){
+ childNode.removeData("ucpeOffset");
+ childNode.data({isInsideGroup: false});
+
+ }
+
+
+ public HTMLCoordsToCytoscapeCoords(cytoscapeBoundingBox:Cy.Extent, mousePos:Cy.Position):Cy.Position {
+ return {x: mousePos.x + cytoscapeBoundingBox.x1, y: mousePos.y + cytoscapeBoundingBox.y1}
+ };
+
+
+ public getCytoscapeNodePosition = (cy: Cy.Instance, event:IDragDropEvent):Cy.Position => {
+ let targetOffset = $(event.target).offset();
+ let x = event.pageX - targetOffset.left;
+ let y = event.pageY - targetOffset.top;
+
+ return this.HTMLCoordsToCytoscapeCoords(cy.extent(), {
+ x: x,
+ y: y
+ });
+ };
+
+
+ public getNodePosition(node:Cy.CollectionFirstNode):Cy.Position{
+ let nodePosition = node.relativePoint();
+ if(node.data().isUcpe){ //UCPEs use bounding box and not relative point.
+ nodePosition = {x: node.boundingbox().x1, y: node.boundingbox().y1};
+ }
+
+ return nodePosition;
+ }
+
+ /**
+ * return true/false if first node contains in second - this used in order to verify is node is entirely inside ucpe
+ * @param firstBox
+ * @param secondBox
+ * @returns {boolean}
+ */
+ public isFirstBoxContainsInSecondBox(firstBox:Cy.BoundingBox, secondBox:Cy.BoundingBox) {
+
+ return firstBox.x1 > secondBox.x1 && firstBox.x2 < secondBox.x2 && firstBox.y1 > secondBox.y1 && firstBox.y2 < secondBox.y2;
+
+ };
+
+
+ /**
+ * Check if node node bounds position is inside any ucpe on graph, and return the ucpe
+ * @param {diagram} the diagram.
+ * @param {nodeActualBounds} the actual bound position of the node.
+ * @return the ucpe if found else return null
+ */
+ public isInUcpe = (cy: Cy.Instance, nodeBounds: Cy.BoundingBox): Cy.CollectionElements => {
+
+ let ucpeNodes = cy.nodes('[?isUcpe]').filterFn((ucpeNode) => {
+ return this.isFirstBoxContainsInSecondBox(nodeBounds, ucpeNode.boundingbox());
+ });
+ return ucpeNodes;
+ };
+
+ /**
+ *
+ * @param cy
+ * @param node
+ * @returns {Array}
+ */
+ public getLinkableNodes(cy:Cy.Instance, node:Cy.CollectionFirstNode):Array<Models.Graph.CompositionCiNodeBase>{
+ let compatibleNodes = [];
+ _.each(cy.nodes(), (tempNode)=>{
+ if(this.nodeLocationsCompatible(cy, node, tempNode)){
+ compatibleNodes.push(tempNode.data());
+ }
+ });
+ return compatibleNodes;
+ }
+
+ /**
+ * Checks whether node locations are compatible in reference to UCPEs.
+ * Returns true if both nodes are in UCPE or both nodes out, or one node is UCPEpart.
+ * @param node1
+ * @param node2
+ */
+ public nodeLocationsCompatible(cy:Cy.Instance, node1:Cy.CollectionFirstNode, node2:Cy.CollectionFirstNode){
+
+ let ucpe = cy.nodes('[?isUcpe]');
+ if(!ucpe.length){ return true; }
+ if(node1.data().isUcpePart || node2.data().isUcpePart) { return true; }
+
+ return (this.isFirstBoxContainsInSecondBox(node1.boundingbox(), ucpe.boundingbox()) == this.isFirstBoxContainsInSecondBox(node2.boundingbox(), ucpe.boundingbox()));
+
+ }
+
+ /**
+ * This function will init qtip tooltip on the node
+ * @param node - the node we want the tooltip to apply on
+ */
+ public initNodeTooltip(node:Cy.CollectionNodes) {
+
+ let opts = {
+ content: function () {
+ return this.data('name');
+ },
+ position: {
+ my: 'top center',
+ at: 'bottom center',
+ adjust: {x:0, y:-5}
+ },
+ style: {
+ classes: 'qtip-dark qtip-rounded qtip-custom',
+ tip: {
+ width: 16,
+ height: 8
+ }
+ },
+ show: {
+ event: 'mouseover',
+ delay: 1000
+ },
+ hide: {event: 'mouseout mousedown'},
+ includeLabels: true
+ };
+
+ if (node.data().isUcpePart){ //fix tooltip positioning for UCPE-cps
+ opts.position.adjust = {x:0, y:20};
+ }
+
+ node.qtip(opts);
+ };
+ };
+
+
+
+ CommonGraphUtils.$inject = ['NodesFactory', 'LinksFactory'];
+} \ No newline at end of file
diff --git a/catalog-ui/app/scripts/directives/graphs-v2/common/style/component-instances-nodes-style.ts b/catalog-ui/app/scripts/directives/graphs-v2/common/style/component-instances-nodes-style.ts
new file mode 100644
index 0000000000..2ec0174aa9
--- /dev/null
+++ b/catalog-ui/app/scripts/directives/graphs-v2/common/style/component-instances-nodes-style.ts
@@ -0,0 +1,259 @@
+/**
+ * Created by obarda on 12/18/2016.
+ */
+/**
+ * Created by obarda on 12/13/2016.
+ */
+/// <reference path="../../../../references"/>
+module Sdc.Graph.Utils.ComponentIntanceNodesStyle {
+
+ export function getCompositionGraphStyle():Array<Cy.Stylesheet> {
+ return [
+ {
+ selector: 'core',
+ css: {
+ 'shape': 'rectangle',
+ 'active-bg-size': 0,
+ 'selection-box-color': 'rgb(0, 159, 219)',
+ 'selection-box-opacity': 0.2,
+ 'selection-box-border-color': '#009fdb',
+ 'selection-box-border-width': 1
+
+ }
+ },
+ {
+ selector: 'node',
+ css: {
+ 'font-family': 'omnes-regular,sans-serif',
+ 'font-size': 14,
+ 'events': 'yes',
+ 'text-events': 'yes',
+ 'text-border-width': 15,
+ 'text-border-color': Sdc.Utils.Constants.GraphColors.NODE_UCPE,
+ 'text-margin-y': 5
+ }
+ },
+ {
+ selector: '.vf-node',
+ css: {
+ 'background-color': 'transparent',
+ 'shape': 'rectangle',
+ 'label': 'data(displayName)',
+ 'background-image': 'data(img)',
+ 'width': 65,
+ 'height': 65,
+ 'background-opacity': 0,
+ "background-width": 65,
+ "background-height": 65,
+ 'text-valign': 'bottom',
+ 'text-halign': 'center',
+ 'background-fit': 'cover',
+ 'background-clip': 'node',
+ 'overlay-color': Sdc.Utils.Constants.GraphColors.NODE_BACKGROUND_COLOR,
+ 'overlay-opacity': 0
+ }
+ },
+
+ {
+ selector: '.service-node',
+ css: {
+ 'background-color': 'transparent',
+ 'label': 'data(displayName)',
+ 'events': 'yes',
+ 'text-events': 'yes',
+ 'background-image': 'data(img)',
+ 'width': 64,
+ 'height': 64,
+ "border-width": 0,
+ 'text-valign': 'bottom',
+ 'text-halign': 'center',
+ 'background-opacity': 0,
+ 'overlay-color': Sdc.Utils.Constants.GraphColors.NODE_BACKGROUND_COLOR,
+ 'overlay-opacity': 0
+ }
+ },
+ {
+ selector: '.cp-node',
+ css: {
+ 'background-color': 'rgb(255,255,255)',
+ 'shape': 'rectangle',
+ 'label': 'data(displayName)',
+ 'background-image': 'data(img)',
+ 'background-width': 21,
+ 'background-height': 21,
+ 'width': 21,
+ 'height': 21,
+ 'text-valign': 'bottom',
+ 'text-halign': 'center',
+ 'background-opacity': 0,
+ 'overlay-color': Sdc.Utils.Constants.GraphColors.NODE_BACKGROUND_COLOR,
+ 'overlay-opacity': 0
+ }
+ },
+ {
+ selector: '.vl-node',
+ css: {
+ 'background-color': 'rgb(255,255,255)',
+ 'shape': 'rectangle',
+ 'label': 'data(displayName)',
+ 'background-image': 'data(img)',
+ 'background-width': 21,
+ 'background-height': 21,
+ 'width': 21,
+ 'height': 21,
+ 'text-valign': 'bottom',
+ 'text-halign': 'center',
+ 'background-opacity': 0,
+ 'overlay-color': Sdc.Utils.Constants.GraphColors.NODE_BACKGROUND_COLOR,
+ 'overlay-opacity': 0
+ }
+ },
+ {
+ selector: '.ucpe-cp',
+ css: {
+ 'background-color': Sdc.Utils.Constants.GraphColors.NODE_UCPE_CP,
+ 'background-width': 15,
+ 'background-height': 15,
+ 'width': 15,
+ 'height': 15,
+ 'text-halign': 'center',
+ 'overlay-opacity': 0,
+ 'label': 'data(displayName)',
+ 'text-valign': 'data(textPosition)',
+ 'text-margin-y': (ele:Cy.Collection) => {
+ return (ele.data('textPosition') == 'top')? -5 : 5;
+ },
+ 'font-size': 12
+ }
+ },
+ {
+ selector: '.ucpe-node',
+ css: {
+ 'background-fit': 'cover',
+ 'padding-bottom': 0,
+ 'padding-top': 0
+ }
+ },
+ {
+ selector: '.simple-link',
+ css: {
+ 'width': 1,
+ 'line-color': Sdc.Utils.Constants.GraphColors.BASE_LINK,
+ 'target-arrow-color': '#3b7b9b',
+ 'target-arrow-shape': 'triangle',
+ 'curve-style': 'bezier',
+ 'control-point-step-size': 30
+ }
+ },
+ {
+ selector: '.vl-link',
+ css: {
+ 'width': 3,
+ 'line-color': Sdc.Utils.Constants.GraphColors.VL_LINK,
+ 'curve-style': 'bezier',
+ 'control-point-step-size': 30
+ }
+ },
+ {
+ selector: '.ucpe-host-link',
+ css: {
+ 'width': 0
+ }
+ },
+ {
+ selector: '.not-certified-link',
+ css: {
+ 'width': 1,
+ 'line-color': Sdc.Utils.Constants.GraphColors.NOT_CERTIFIED_LINK,
+ 'curve-style': 'bezier',
+ 'control-point-step-size': 30,
+ 'line-style': 'dashed',
+ 'target-arrow-color': '#3b7b9b',
+ 'target-arrow-shape': 'triangle'
+
+ }
+ },
+
+ {
+ selector: '.not-certified',
+ css: {
+ 'shape': 'rectangle',
+ 'background-image': (ele:Cy.Collection) => {
+ return ele.data().initImage(ele)
+ },
+ "border-width": 0
+ }
+ },
+ {
+ selector: 'node:selected',
+ css: {
+ "border-width": 2,
+ "border-color": Sdc.Utils.Constants.GraphColors.NODE_SELECTED_BORDER_COLOR,
+ 'shape': 'rectangle'
+ }
+ },
+ {
+ selector: 'edge:selected',
+ css: {
+ 'line-color': Sdc.Utils.Constants.GraphColors.ACTIVE_LINK
+
+ }
+ },
+ {
+ selector: 'edge:active',
+ css: {
+ 'overlay-opacity': 0
+ }
+ }
+ ]
+ }
+
+ export function getBasicNodeHanlde() {
+ return {
+ positionX: "center",
+ positionY: "top",
+ offsetX: 15,
+ offsetY: -20,
+ color: "#27a337",
+ type: "default",
+ single: false,
+ nodeTypeNames: ["basic-node"],
+ imageUrl: Sdc.Utils.Constants.IMAGE_PATH + '/styles/images/resource-icons/' + 'canvasPlusIcon.png',
+ lineWidth: 2,
+ lineStyle: 'dashed'
+
+ }
+ }
+
+ export function getBasicSmallNodeHandle() {
+ return {
+ positionX: "center",
+ positionY: "top",
+ offsetX: 3,
+ offsetY: -25,
+ color: "#27a337",
+ type: "default",
+ single: false,
+ nodeTypeNames: ["basic-small-node"],
+ imageUrl: Sdc.Utils.Constants.IMAGE_PATH + '/styles/images/resource-icons/' + 'canvasPlusIcon.png',
+ lineWidth: 2,
+ lineStyle: 'dashed'
+ }
+ }
+
+ export function getUcpeCpNodeHandle() {
+ return {
+ positionX: "center",
+ positionY: "center",
+ offsetX: -8,
+ offsetY: -10,
+ color: "#27a337",
+ type: "default",
+ single: false,
+ nodeTypeNames: ["ucpe-cp-node"],
+ imageUrl: Sdc.Utils.Constants.IMAGE_PATH + '/styles/images/resource-icons/' + 'canvasPlusIcon.png',
+ lineWidth: 2,
+ lineStyle: 'dashed'
+ }
+ }
+} \ No newline at end of file
diff --git a/catalog-ui/app/scripts/directives/graphs-v2/common/style/module-node-style.ts b/catalog-ui/app/scripts/directives/graphs-v2/common/style/module-node-style.ts
new file mode 100644
index 0000000000..62436fbf74
--- /dev/null
+++ b/catalog-ui/app/scripts/directives/graphs-v2/common/style/module-node-style.ts
@@ -0,0 +1,92 @@
+/**
+ * Created by obarda on 1/1/2017.
+ */
+/**
+ * Created by obarda on 12/18/2016.
+ */
+/**
+ * Created by obarda on 12/13/2016.
+ */
+/// <reference path="../../../../references"/>
+module Sdc.Graph.Utils.ModulesNodesStyle {
+
+ export function getModuleGraphStyle():Array<Cy.Stylesheet> {
+
+ return [
+ {
+ selector: '.cy-expand-collapse-collapsed-node',
+ css: {
+ 'background-image': 'data(img)',
+ 'width': 34,
+ 'height': 32,
+ 'background-opacity': 0,
+ 'shape': 'rectangle',
+ 'label': 'data(displayName)',
+ 'events': 'yes',
+ 'text-events': 'yes',
+ 'text-valign': 'bottom',
+ 'text-halign': 'center',
+ 'text-margin-y': 5,
+ 'border-opacity': 0
+ }
+ },
+ {
+ selector: '.module-node',
+ css: {
+ 'background-color': 'transparent',
+ 'background-opacity': 0,
+ "border-width": 2,
+ "border-color": Sdc.Utils.Constants.GraphColors.NODE_SELECTED_BORDER_COLOR,
+ 'border-style': 'dashed',
+ 'label': 'data(displayName)',
+ 'events': 'yes',
+ 'text-events': 'yes',
+ 'text-valign': 'bottom',
+ 'text-halign': 'center',
+ 'text-margin-y': 8
+ }
+ },
+ {
+ selector: 'node:selected',
+ css: {
+ "border-opacity": 0
+ }
+ },
+ {
+ selector: '.simple-link:selected',
+ css: {
+ 'line-color': Sdc.Utils.Constants.GraphColors.BASE_LINK,
+ }
+ },
+ {
+ selector: '.vl-link:selected',
+ css: {
+ 'line-color': Sdc.Utils.Constants.GraphColors.VL_LINK,
+ }
+ },
+ {
+ selector: '.cy-expand-collapse-collapsed-node:selected',
+ css: {
+ "border-color": Sdc.Utils.Constants.GraphColors.NODE_SELECTED_BORDER_COLOR,
+ 'border-opacity': 1,
+ 'border-style': 'solid',
+ 'border-width': 2
+ }
+ },
+ {
+ selector: '.module-node:selected',
+ css: {
+ "border-color": Sdc.Utils.Constants.GraphColors.NODE_SELECTED_BORDER_COLOR,
+ 'border-opacity': 1
+ }
+ },
+ {
+ selector: '.dummy-node',
+ css: {
+ 'width': 20,
+ 'height': 20
+ }
+ },
+ ]
+ }
+} \ No newline at end of file