aboutsummaryrefslogtreecommitdiffstats
path: root/catalog-ui/src/app/ng2/pages/composition/graph/common
diff options
context:
space:
mode:
Diffstat (limited to 'catalog-ui/src/app/ng2/pages/composition/graph/common')
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/graph/common/common-graph-utils.ts304
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/graph/common/image-creator.service.ts92
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/graph/common/style/component-instances-nodes-style.spec.ts37
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/graph/common/style/component-instances-nodes-style.ts362
-rw-r--r--catalog-ui/src/app/ng2/pages/composition/graph/common/style/module-node-style.ts103
5 files changed, 898 insertions, 0 deletions
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/common/common-graph-utils.ts b/catalog-ui/src/app/ng2/pages/composition/graph/common/common-graph-utils.ts
new file mode 100644
index 0000000000..bfc540e97e
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/common/common-graph-utils.ts
@@ -0,0 +1,304 @@
+/*-
+ * ============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=========================================================
+ */
+
+import * as _ from "lodash";
+import {
+ CommonNodeBase,
+ Relationship,
+ CompositionCiNodeBase
+} from "app/models";
+import {CompositionCiServicePathLink} from "app/models/graph/graph-links/composition-graph-links/composition-ci-service-path-link";
+import {Requirement, Capability} from "app/models";
+import {Injectable} from "@angular/core";
+
+
+
+@Injectable()
+export class CommonGraphUtils {
+
+ constructor() {
+
+ }
+
+ 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:CommonNodeBase, position?:Cy.Position):Cy.CollectionElements {
+
+ let node = cy.add(<Cy.ElementDefinition> {
+ group: 'nodes',
+ position: position,
+ data: compositionGraphNode,
+ classes: compositionGraphNode.classes
+ });
+
+ 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:CompositionCiNodeBase):Cy.CollectionElements {
+
+ let nodePosition = {
+ x: +compositionGraphNode.componentInstance.posX,
+ y: +compositionGraphNode.componentInstance.posY
+ };
+
+ let node = this.addNodeToGraph(cy, compositionGraphNode, nodePosition);
+ return node;
+ };
+
+ /**
+ * Add service path link to graph - only draw the link
+ * @param cy
+ * @param link
+ */
+ public insertServicePathLinkToGraph = (cy:Cy.Instance, link:CompositionCiServicePathLink) => {
+ let linkElement = cy.add({
+ group: 'edges',
+ data: link,
+ classes: link.classes
+ });
+ this.initServicePathTooltip(linkElement, link);
+ };
+
+ /**
+ * Returns function for the link tooltip content
+ * @param {Relationship} linkRelation
+ * @param {Requirement} requirement
+ * @param {Capability} capability
+ * @returns {() => string}
+ * @private
+ */
+ private _getLinkTooltipContent(linkRelation:Relationship, requirement?:Requirement, capability?:Capability):string {
+ return '<div class="line">' +
+ '<span class="req-cap-label">R: </span>' +
+ '<span>' + (requirement ? requirement.getTitle() : linkRelation.relation.requirement) + '</span>' +
+ '</div>' +
+ '<div class="line">' +
+ '<div class="sprite-new link-tooltip-arrow"></div>' +
+ '<span class="req-cap-label">C: </span>' +
+ '<span>' + (capability ? capability.getTitle() : linkRelation.relation.capability) + '</span>' +
+ '</div>';
+ }
+
+ /**
+ * This function will init qtip tooltip on the link
+ * @param linkElement - the link we want the tooltip to apply on,
+ * @param link
+ * @param getLinkRequirementCapability
+ * link - the link obj
+ */
+ public initLinkTooltip(linkElement:Cy.CollectionElements, link:Relationship, getLinkRequirementCapability:Function) {
+ const content = () => this._getLinkTooltipContent(link); // base tooltip content without owner names
+ const render = (event, api) => {
+ // on render (called once at first show), get the link requirement and capability and change to full tooltip content (with owner names)
+ getLinkRequirementCapability().then((linkReqCap) => {
+ const fullContent = () => this._getLinkTooltipContent(link, linkReqCap.requirement, linkReqCap.capability);
+ api.set('content.text', fullContent);
+ });
+ };
+ linkElement.qtip(this.prepareInitTooltipData({content, events: {render}}));
+ };
+
+ /**
+ *
+ * @param linkElement
+ * @param link
+ */
+ public initServicePathTooltip(linkElement:Cy.CollectionElements, link:CompositionCiServicePathLink) {
+ let content = function () {
+ return '<div class="line">' +
+ '<div>' + link.pathName + '</div>' +
+ '</div>';
+ };
+ linkElement.qtip(this.prepareInitTooltipData({content}));
+ };
+
+ private prepareInitTooltipData(options?:Object) {
+ return _.merge({
+ position: {
+ my: 'top center',
+ at: 'bottom center',
+ adjust: {x: 0, y: 0},
+ effect: false
+ },
+ style: {
+ classes: 'qtip-dark qtip-rounded qtip-custom link-qtip',
+ tip: {
+ width: 16,
+ height: 8
+ }
+ },
+ show: {
+ event: 'mouseover',
+ delay: 1000
+ },
+ hide: {event: 'mouseout mousedown'},
+ includeLabels: true,
+ events: {}
+ }, options);
+ }
+
+ 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:DragEvent | MouseEvent):Cy.Position => {
+ let targetOffset = $(event.target).offset();
+ if(event instanceof DragEvent) {
+ targetOffset = $('canvas').offset();
+ }
+
+ let x = (event.pageX - targetOffset.left) / cy.zoom();
+ let y = (event.pageY - targetOffset.top) / cy.zoom();
+
+ 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;
+ }
+
+ /**
+ * Generic function that can be used for any html elements overlaid on canvas
+ * Returns the html position of a node on canvas, including left palette and header offsets. Option to pass in additional offset to add to return position.
+ * @param node
+ * @param additionalOffset
+ * @returns {Cy.Position}
+
+ public getNodePositionWithOffset = (node:Cy.CollectionFirstNode, additionalOffset?:Cy.Position): Cy.Position => {
+ if(!additionalOffset) additionalOffset = {x: 0, y:0};
+
+ let nodePosition = node.renderedPosition();
+ let posWithOffset:Cy.Position = {
+ x: nodePosition.x + GraphUIObjects.DIAGRAM_PALETTE_WIDTH_OFFSET + additionalOffset.x,
+ y: nodePosition.y + GraphUIObjects.COMPOSITION_HEADER_OFFSET + additionalOffset.y
+ };
+ return posWithOffset;
+ };*/
+
+ /**
+ * 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;
+
+ };
+
+ /**
+ *
+ * @param cy
+ * @param node
+ * @returns {Array}
+ */
+ public getLinkableNodes(cy:Cy.Instance, node:Cy.CollectionFirstNode):Array<CompositionCiNodeBase> {
+ let compatibleNodes = [];
+ _.each(cy.nodes(), (tempNode)=> {
+ if (this.nodeLocationsCompatible(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(node1:Cy.CollectionFirstNode, node2:Cy.CollectionFirstNode) {
+ return (this.isFirstBoxContainsInSecondBox(node1.boundingbox(), node2.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);
+ };
+}
+
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/common/image-creator.service.ts b/catalog-ui/src/app/ng2/pages/composition/graph/common/image-creator.service.ts
new file mode 100644
index 0000000000..2be92c782b
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/common/image-creator.service.ts
@@ -0,0 +1,92 @@
+/*-
+ * ============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 {Injectable} from "@angular/core";
+
+export interface ICanvasImage {
+ src: string;
+ width: number
+ height: number;
+ x: number;
+ y: number;
+}
+
+@Injectable()
+export class ImageCreatorService {
+
+ private _canvas:HTMLCanvasElement;
+
+ constructor() {
+ this._canvas = <HTMLCanvasElement>$('<canvas>')[0];
+ this._canvas.setAttribute('style', 'display:none');
+
+ let body = document.getElementsByTagName('body')[0];
+ body.appendChild(this._canvas);
+ }
+
+ /**
+ * Create an image composed of different image layers
+ * @param canvasImages
+ * @param canvasWidth
+ * @param canvasHeight
+ * returns a PROMISE
+ */
+ getMultiLayerBase64Image(canvasImages: ICanvasImage[], canvasWidth?:number, canvasHeight?:number):Promise<string> {
+
+ var promise = new Promise<string>((resolve, reject) => {
+ if(canvasImages && canvasImages.length === 0){
+ return null;
+ }
+
+ //If only width was set, use it for height, otherwise use first canvasImage height
+ canvasHeight = canvasHeight || canvasImages[0].height;
+ canvasWidth = canvasWidth || canvasImages[0].width;
+
+ const images = [];
+ let imagesLoaded = 0;
+ const onImageLoaded = () => {
+ imagesLoaded++;
+ if(imagesLoaded < canvasImages.length){
+ return;
+ }
+ this._canvas.setAttribute('width', (canvasWidth * 4).toString());
+ this._canvas.setAttribute('height', (canvasHeight * 4).toString());
+ const canvasCtx = this._canvas.getContext('2d');
+ canvasCtx.scale(4,4);
+ canvasCtx.clearRect(0, 0, this._canvas.width, this._canvas.height);
+ images.forEach((image, index) => {
+ const canvasImage = canvasImages[index];
+ canvasCtx.drawImage(image, canvasImage.x, canvasImage.y, canvasImage.width, canvasImage.height);
+ });
+
+ let base64Image = this._canvas.toDataURL();
+ resolve(base64Image)
+ };
+ canvasImages.forEach(canvasImage => {
+ let image = new Image();
+ image.onload = onImageLoaded;
+ image.src = canvasImage.src;
+ images.push(image);
+ });
+ });
+
+ return promise;
+ }
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/common/style/component-instances-nodes-style.spec.ts b/catalog-ui/src/app/ng2/pages/composition/graph/common/style/component-instances-nodes-style.spec.ts
new file mode 100644
index 0000000000..54b3dbed24
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/common/style/component-instances-nodes-style.spec.ts
@@ -0,0 +1,37 @@
+import {async} from "@angular/core/testing";
+import {ComponentInstanceNodesStyle} from "./component-instances-nodes-style";
+
+
+describe('component instance nodes style component', () => {
+
+ beforeEach(
+ async(() => {
+ const createElement = document.createElement.bind(document);
+ document.createElement = (tagName) => {
+ if (tagName === 'canvas') {
+ return {
+ getContext: () => ({
+ font: "",
+ measureText: (x) => ({width: x.length})
+ }),
+ };
+ }
+ return createElement(tagName);
+ };
+ })
+ );
+
+ it('verify getGraphDisplayName for String.length smaller than 67 chars', () => {
+ let inputString = 'SomeText';
+ let expectedRes = inputString;
+ let res = ComponentInstanceNodesStyle.getGraphDisplayName(inputString);
+ expect(res).toBe(expectedRes);
+ });
+
+ it('verify getGraphDisplayName for String.length greater than 67 chars', () => {
+ let inputString = 'AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDDEEEEEEEEEEFFFFFFFFFFGGGGGGGGGG12345678';
+ let expectedRes = 'AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDDEEEEEEEEEEFFFFFFFFF...';
+ let res = ComponentInstanceNodesStyle.getGraphDisplayName(inputString);
+ expect(res).toBe(expectedRes);
+ });
+} \ No newline at end of file
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/common/style/component-instances-nodes-style.ts b/catalog-ui/src/app/ng2/pages/composition/graph/common/style/component-instances-nodes-style.ts
new file mode 100644
index 0000000000..cc9cac16e6
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/common/style/component-instances-nodes-style.ts
@@ -0,0 +1,362 @@
+/*-
+ * ============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=========================================================
+ */
+
+import { GraphColors, GraphUIObjects} from "app/utils/constants";
+import constant = require("lodash/constant");
+import {ImagesUrl} from "app/utils/constants";
+import {AngularJSBridge} from "app/services/angular-js-bridge-service";
+import { CanvasHandleTypes } from "app/utils";
+/**
+ * Created by obarda on 12/18/2016.
+ */
+export class ComponentInstanceNodesStyle {
+
+ public static 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': 'OpenSans-Regular,sans-serif',
+
+ 'font-size': 14,
+ 'events': 'yes',
+ 'text-events': 'yes',
+ 'text-border-width': 15,
+ 'text-border-color': GraphColors.NODE_UCPE,
+ 'text-margin-y': 5
+ }
+ },
+ {
+ selector: '.vf-node',
+ css: {
+ 'background-color': 'transparent',
+ 'shape': 'rectangle',
+ 'label': 'data(displayName)',
+ 'background-image': 'data(img)',
+ 'width': GraphUIObjects.DEFAULT_RESOURCE_WIDTH,
+ 'height': GraphUIObjects.DEFAULT_RESOURCE_WIDTH,
+ 'background-opacity': 0,
+ "background-width": GraphUIObjects.DEFAULT_RESOURCE_WIDTH,
+ "background-height": GraphUIObjects.DEFAULT_RESOURCE_WIDTH,
+ 'text-valign': 'bottom',
+ 'text-halign': 'center',
+ 'background-fit': 'cover',
+ 'background-clip': 'node',
+ 'overlay-color': 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': 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': GraphUIObjects.SMALL_RESOURCE_WIDTH,
+ 'background-height': GraphUIObjects.SMALL_RESOURCE_WIDTH,
+ 'width': GraphUIObjects.SMALL_RESOURCE_WIDTH + GraphUIObjects.HANDLE_SIZE,
+ 'height': GraphUIObjects.SMALL_RESOURCE_WIDTH + GraphUIObjects.HANDLE_SIZE/2,
+ 'background-position-x': GraphUIObjects.HANDLE_SIZE / 2,
+ 'background-position-y': GraphUIObjects.HANDLE_SIZE / 2,
+ 'text-valign': 'bottom',
+ 'text-halign': 'center',
+ 'background-opacity': 0,
+ 'overlay-color': 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': GraphUIObjects.SMALL_RESOURCE_WIDTH,
+ 'background-height': GraphUIObjects.SMALL_RESOURCE_WIDTH,
+ 'background-position-x': GraphUIObjects.HANDLE_SIZE / 2,
+ 'background-position-y': GraphUIObjects.HANDLE_SIZE / 2,
+ 'width': GraphUIObjects.SMALL_RESOURCE_WIDTH + GraphUIObjects.HANDLE_SIZE,
+ 'height': GraphUIObjects.SMALL_RESOURCE_WIDTH + GraphUIObjects.HANDLE_SIZE / 2,
+ 'text-valign': 'bottom',
+ 'text-halign': 'center',
+ 'background-opacity': 0,
+ 'overlay-color': GraphColors.NODE_BACKGROUND_COLOR,
+ 'overlay-opacity': 0
+ }
+ },
+ {
+ selector: '.ucpe-cp',
+ css: {
+ 'background-color': 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': 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': GraphColors.VL_LINK,
+ 'curve-style': 'bezier',
+ 'control-point-step-size': 30
+ }
+ },
+ {
+ selector: '.vl-link-1',
+ css: {
+ 'width': 3,
+ 'line-color': GraphColors.ACTIVE_LINK,
+ 'curve-style': 'unbundled-bezier',
+ 'target-arrow-color': '#3b7b9b',
+ 'target-arrow-shape': 'triangle',
+ 'control-point-step-size': 30
+ }
+ },
+ {
+ selector: '.ucpe-host-link',
+ css: {
+ 'width': 0
+ }
+ },
+ {
+ selector: '.not-certified-link',
+ css: {
+ 'width': 1,
+ 'line-color': GraphColors.NOT_CERTIFIED_LINK,
+ 'curve-style': 'bezier',
+ 'control-point-step-size': 30,
+ 'line-style': 'dashed',
+ 'target-arrow-color': '#3b7b9b',
+ 'target-arrow-shape': 'triangle'
+
+ }
+ },
+
+ {
+ selector: '.service-path-link',
+ css: {
+ 'width': 2,
+ 'line-color': GraphColors.SERVICE_PATH_LINK,
+ 'target-arrow-color': GraphColors.SERVICE_PATH_LINK,
+ 'target-arrow-shape': 'triangle',
+ 'curve-style': 'bezier',
+ 'control-point-step-size': 30
+ }
+ },
+ {
+ selector: '.not-certified',
+ css: {
+ 'shape': 'rectangle',
+ 'background-image': (ele:Cy.Collection) => {
+ // return ele.data().setUncertifiedImageBgStyle(ele, GraphUIObjects.NODE_OVERLAP_MIN_SIZE);//Change name to setUncertifiedImageBgStyle??
+ return ele.data().initUncertifiedImage(ele, GraphUIObjects.NODE_OVERLAP_MIN_SIZE);
+ },
+ 'border-width': 0
+ }
+ },
+ {
+ selector: '.dependent',
+ css: {
+ 'shape': 'rectangle',
+ 'background-image': (ele:Cy.Collection) => {
+ return ele.data().initDependentImage(ele, GraphUIObjects.NODE_OVERLAP_MIN_SIZE)
+ },
+ 'border-width': 0
+ }
+ },
+ {
+ selector: '.dependent.not-certified',
+ css: {
+ 'shape': 'rectangle',
+ 'background-image': (ele:Cy.Collection) => {
+ return ele.data().initUncertifiedDependentImage(ele, GraphUIObjects.NODE_OVERLAP_MIN_SIZE)
+ },
+ 'border-width': 0
+ }
+ },
+ {
+ selector: 'node:selected',
+ css: {
+ "border-width": 2,
+ "border-color": GraphColors.NODE_SELECTED_BORDER_COLOR,
+ 'shape': 'rectangle'
+ }
+ },
+ {
+ selector: 'edge:selected',
+ css: {
+ 'line-color': GraphColors.ACTIVE_LINK
+
+ }
+ },
+ {
+ selector: 'edge:active',
+ css: {
+ 'overlay-opacity': 0
+ }
+ }, {
+ selector: '.configuration-node',
+ css: {
+ 'background-color': 'rgb(255,255,255)',
+ 'shape': 'rectangle',
+ 'label': 'data(displayName)',
+ 'background-image': 'data(img)',
+ 'background-width': GraphUIObjects.SMALL_RESOURCE_WIDTH,
+ 'background-height': GraphUIObjects.SMALL_RESOURCE_WIDTH,
+ 'background-position-x': GraphUIObjects.HANDLE_SIZE / 2,
+ 'background-position-y': GraphUIObjects.HANDLE_SIZE / 2,
+ 'width': GraphUIObjects.SMALL_RESOURCE_WIDTH + GraphUIObjects.HANDLE_SIZE,
+ 'height': GraphUIObjects.SMALL_RESOURCE_WIDTH + GraphUIObjects.HANDLE_SIZE/2,
+ 'text-valign': 'bottom',
+ 'text-halign': 'center',
+ 'background-opacity': 0,
+ 'overlay-color': GraphColors.NODE_BACKGROUND_COLOR,
+ 'overlay-opacity': 0
+ }
+ },
+ {
+ selector: '.archived',
+ css: {
+ 'shape': 'rectangle',
+ 'background-image': (ele:Cy.Collection) => {
+ return ele.data().setArchivedImageBgStyle(ele, GraphUIObjects.NODE_OVERLAP_MIN_SIZE); //Change name to setArchivedImageBgStyle ??
+ },
+ "border-width": 0
+ }
+ }
+ ]
+ }
+
+ public static getAddEdgeHandle = () => {
+ return {
+
+ single: false,
+ type: CanvasHandleTypes.ADD_EDGE,
+ imageUrl: AngularJSBridge.getAngularConfig().imagesPath + ImagesUrl.CANVAS_PLUS_ICON,
+ lineColor: '#27a337',
+ lineWidth: 2,
+ lineStyle: 'dashed'
+
+ }
+ }
+
+ public static getTagHandle = () => {
+ return {
+ single: false,
+ type: CanvasHandleTypes.TAG_AVAILABLE,
+ imageUrl: AngularJSBridge.getAngularConfig().imagesPath + ImagesUrl.CANVAS_TAG_ICON,
+ }
+ }
+
+ public static getTaggedPolicyHandle = () => {
+ return {
+ single: false,
+ type: CanvasHandleTypes.TAGGED_POLICY,
+ imageUrl: AngularJSBridge.getAngularConfig().imagesPath + ImagesUrl.CANVAS_POLICY_TAGGED_ICON,
+ }
+ }
+
+ public static getTaggedGroupHandle = () => {
+ return {
+ single: false,
+ type: CanvasHandleTypes.TAGGED_GROUP,
+ imageUrl: AngularJSBridge.getAngularConfig().imagesPath + ImagesUrl.CANVAS_GROUP_TAGGED_ICON,
+ }
+ }
+
+ public static getGraphDisplayName(name:string):string {
+ let context = document.createElement("canvas").getContext("2d");
+ context.font = "13px Arial";
+
+ if (67 < context.measureText(name).width) {
+ let newLen = name.length - 3;
+ let newName = name.substring(0, newLen);
+
+ while (59 < (context.measureText(newName).width)) {
+ newName = newName.substring(0, (--newLen));
+ }
+ return newName + '...';
+ }
+ return name;
+ }
+
+}
diff --git a/catalog-ui/src/app/ng2/pages/composition/graph/common/style/module-node-style.ts b/catalog-ui/src/app/ng2/pages/composition/graph/common/style/module-node-style.ts
new file mode 100644
index 0000000000..bf71e1c868
--- /dev/null
+++ b/catalog-ui/src/app/ng2/pages/composition/graph/common/style/module-node-style.ts
@@ -0,0 +1,103 @@
+/*-
+ * ============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=========================================================
+ */
+
+import {GraphColors} from "app/utils";
+export class ModulesNodesStyle {
+
+ public static 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": 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': GraphColors.BASE_LINK,
+ }
+ },
+ {
+ selector: '.vl-link:selected',
+ css: {
+ 'line-color': GraphColors.VL_LINK,
+ }
+ },
+ {
+ selector: '.cy-expand-collapse-collapsed-node:selected',
+ css: {
+ "border-color": GraphColors.NODE_SELECTED_BORDER_COLOR,
+ 'border-opacity': 1,
+ 'border-style': 'solid',
+ 'border-width': 2
+ }
+ },
+ {
+ selector: '.module-node:selected',
+ css: {
+ "border-color": GraphColors.NODE_SELECTED_BORDER_COLOR,
+ 'border-opacity': 1
+ }
+ },
+ {
+ selector: '.dummy-node',
+ css: {
+ 'width': 20,
+ 'height': 20
+ }
+ },
+ ]
+ }
+}