summaryrefslogtreecommitdiffstats
path: root/catalog-ui/src/app/directives/graphs-v2
diff options
context:
space:
mode:
Diffstat (limited to 'catalog-ui/src/app/directives/graphs-v2')
-rw-r--r--catalog-ui/src/app/directives/graphs-v2/common/style/component-instances-nodes-style.ts100
-rw-r--r--catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.directive.ts455
-rw-r--r--catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.html27
-rw-r--r--catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.less16
-rw-r--r--catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-general-utils.ts54
-rw-r--r--catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-nodes-utils.ts2
-rw-r--r--catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-service-path-utils.ts10
-rw-r--r--catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-zone-utils.ts198
-rw-r--r--catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/match-capability-requierment-utils.ts20
-rw-r--r--catalog-ui/src/app/directives/graphs-v2/deployment-graph/deployment-graph.directive.ts8
-rw-r--r--catalog-ui/src/app/directives/graphs-v2/deployment-graph/deployment-utils/deployment-graph-general-utils.ts2
-rw-r--r--catalog-ui/src/app/directives/graphs-v2/image-creator/image-creator.service.ts62
-rw-r--r--catalog-ui/src/app/directives/graphs-v2/palette/palette.directive.ts8
-rw-r--r--catalog-ui/src/app/directives/graphs-v2/palette/palette.html2
-rw-r--r--catalog-ui/src/app/directives/graphs-v2/relation-menu/relation-menu.html63
-rw-r--r--catalog-ui/src/app/directives/graphs-v2/relation-menu/relation-menu.less118
-rw-r--r--catalog-ui/src/app/directives/graphs-v2/relation-menu/relation-menu.ts104
17 files changed, 665 insertions, 584 deletions
diff --git a/catalog-ui/src/app/directives/graphs-v2/common/style/component-instances-nodes-style.ts b/catalog-ui/src/app/directives/graphs-v2/common/style/component-instances-nodes-style.ts
index 596dcecc13..194845c238 100644
--- a/catalog-ui/src/app/directives/graphs-v2/common/style/component-instances-nodes-style.ts
+++ b/catalog-ui/src/app/directives/graphs-v2/common/style/component-instances-nodes-style.ts
@@ -22,6 +22,7 @@ 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.
*/
@@ -102,8 +103,10 @@ export class ComponentInstanceNodesStyle {
'background-image': 'data(img)',
'background-width': GraphUIObjects.SMALL_RESOURCE_WIDTH,
'background-height': GraphUIObjects.SMALL_RESOURCE_WIDTH,
- 'width': GraphUIObjects.SMALL_RESOURCE_WIDTH,
- '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,
@@ -120,8 +123,10 @@ export class ComponentInstanceNodesStyle {
'background-image': 'data(img)',
'background-width': GraphUIObjects.SMALL_RESOURCE_WIDTH,
'background-height': GraphUIObjects.SMALL_RESOURCE_WIDTH,
- 'width': GraphUIObjects.SMALL_RESOURCE_WIDTH,
- '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,
@@ -167,6 +172,16 @@ export class ComponentInstanceNodesStyle {
}
},
{
+ 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
+ }
+ },
+ {
selector: '.vl-link',
css: {
'width': 3,
@@ -222,7 +237,7 @@ export class ComponentInstanceNodesStyle {
css: {
'shape': 'rectangle',
'background-image': (ele:Cy.Collection) => {
- return ele.data().initUncertifiedImage(ele, GraphUIObjects.NODE_OVERLAP_MIN_SIZE)
+ return ele.data().setUncertifiedImageBgStyle(ele, GraphUIObjects.NODE_OVERLAP_MIN_SIZE);//Change name to setUncertifiedImageBgStyle??
},
"border-width": 0
}
@@ -256,8 +271,10 @@ export class ComponentInstanceNodesStyle {
'background-image': 'data(img)',
'background-width': GraphUIObjects.SMALL_RESOURCE_WIDTH,
'background-height': GraphUIObjects.SMALL_RESOURCE_WIDTH,
- 'width': GraphUIObjects.SMALL_RESOURCE_WIDTH,
- '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,
@@ -268,52 +285,57 @@ export class ComponentInstanceNodesStyle {
]
}
- public static getBasicNodeHanlde = () => {
+ public static getAddEdgeHandle = () => {
return {
- positionX: "right",
- positionY: "top",
- offsetX: 15,
- offsetY: -20,
- color: "#27a337",
- type: "default",
+
single: false,
- nodeTypeNames: ["basic-node"],
+ type: CanvasHandleTypes.ADD_EDGE,
imageUrl: AngularJSBridge.getAngularConfig().imagesPath + ImagesUrl.CANVAS_PLUS_ICON,
+ lineColor: '#27a337',
lineWidth: 2,
lineStyle: 'dashed'
}
}
- public static getBasicSmallNodeHandle = () => {
+ public static getTagHandle = () => {
return {
- positionX: "right",
- positionY: "top",
- offsetX: 3,
- offsetY: -25,
- color: "#27a337",
- type: "default",
single: false,
- nodeTypeNames: ["basic-small-node"],
- imageUrl: AngularJSBridge.getAngularConfig().imagesPath + ImagesUrl.CANVAS_PLUS_ICON,
- lineWidth: 2,
- lineStyle: 'dashed'
- }
+ type: CanvasHandleTypes.TAG_AVAILABLE,
+ imageUrl: AngularJSBridge.getAngularConfig().imagesPath + ImagesUrl.CANVAS_TAG_ICON,
+ }
}
- public static getUcpeCpNodeHandle = () => {
+ public static getTaggedPolicyHandle = () => {
return {
- positionX: "center",
- positionY: "center",
- offsetX: -8,
- offsetY: -10,
- color: "#27a337",
- type: "default",
single: false,
- nodeTypeNames: ["ucpe-cp-node"],
- imageUrl: AngularJSBridge.getAngularConfig().imagesPath + ImagesUrl.CANVAS_PLUS_ICON,
- lineWidth: 2,
- lineStyle: 'dashed'
- }
+ 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 getUcpeCpNodeHandle = () => {
+ // return {
+ // positionX: "center",
+ // positionY: "center",
+ // offsetX: -8,
+ // offsetY: -10,
+ // color: "#27a337",
+ // type: "default",
+ // single: false,
+ // nodeTypeNames: ["ucpe-cp-node"],
+ // imageUrl: AngularJSBridge.getAngularConfig().imagesPath + ImagesUrl.CANVAS_PLUS_ICON,
+ // lineWidth: 2,
+ // lineStyle: 'dashed'
+ // }
+ // }
}
diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.directive.ts b/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.directive.ts
index 2144ecfbfa..e40792dc7e 100644
--- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.directive.ts
+++ b/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.directive.ts
@@ -24,10 +24,7 @@ import {
LinkMenu,
ComponentInstance,
LeftPaletteComponent,
- Capability,
- Requirement,
Relationship,
- PropertyModel,
Component,
Service,
ConnectRelationModel,
@@ -35,8 +32,7 @@ import {
CompositionCiNodeVl,
ModalModel,
ButtonModel,
- NodesFactory/*,
- AssetPopoverObj*/,
+ NodesFactory,
Point
} from "app/models";
import {ComponentInstanceFactory, ComponentFactory, GRAPH_EVENTS, GraphColors} from "app/utils";
@@ -52,7 +48,6 @@ import {CytoscapeEdgeEditation} from 'third-party/cytoscape.js-edge-editation/Cy
import {ComponentServiceNg2} from "../../../ng2/services/component-services/component.service";
import {ComponentGenericResponse} from "../../../ng2/services/responses/component-generic-response";
import {ModalService} from "../../../ng2/services/modal.service";
-
import {ConnectionWizardService} from "../../../ng2/pages/connection-wizard/connection-wizard.service";
import {StepModel} from "../../../models/wizard-step";
import {FromNodeStepComponent} from "app/ng2/pages/connection-wizard/from-node-step/from-node-step.component";
@@ -63,31 +58,40 @@ import {ConnectionPropertiesViewComponent} from "../../../ng2/pages/connection-w
import {ComponentInstanceServiceNg2} from "../../../ng2/services/component-instance-services/component-instance.service";
import {EVENTS} from "../../../utils/constants";
import {PropertyBEModel} from "../../../models/properties-inputs/property-be-model";
-import {ComponentType} from "app/utils";
import {ForwardingPath} from "app/models/forwarding-path";
import {ServicePathGraphUtils} from "./utils/composition-graph-service-path-utils";
import {CompositionCiServicePathLink} from "app/models/graph/graph-links/composition-graph-links/composition-ci-service-path-link";
-import { ZoneConfig, ZoneInstanceConfig, ZoneInstanceMode } from "app/models/graph/zones/zone-child";
-import { PoliciesService } from "app/ng2/services/policies.service";
-import { PaletteAnimationComponent } from "app/ng2/components/ui/palette-animation/palette-animation.component";
-import { CompositionGraphZoneUtils } from "./utils/composition-graph-zone-utils";
-import {LeftPaletteMetadataTypes} from "../../../models/components/displayComponent";
+import {
+ ZoneInstance, ZoneInstanceMode, ZoneInstanceType,
+ ZoneInstanceAssignmentType
+} from "app/models/graph/zones/zone-instance";
+
+import {Zone} from "app/models/graph/zones/zone";
+import {CompositionGraphZoneUtils} from "./utils/composition-graph-zone-utils";
+import {UIZoneInstanceObject} from "../../../models/ui-models/ui-zone-instance-object";
+import {GroupInstance} from "../../../models/graph/zones/group-instance";
+import {PolicyInstance} from "../../../models/graph/zones/policy-instance";
export interface ICompositionGraphScope extends ng.IScope {
component:Component;
- isLoading: boolean;
- isViewOnly: boolean;
- withSidebar: boolean;
+ isLoading:boolean;
+ isViewOnly:boolean;
+ withSidebar:boolean;
//zones
newZoneInstance;
zoneTagMode:string;
- activeZoneInstance:ZoneInstanceConfig;
- zones:any;
- zoneInstanceModeChanged(newMode:ZoneInstanceMode, instance:ZoneInstanceConfig, zoneId:string);
+ activeZoneInstance:ZoneInstance;
+ zones:Array<Zone>;
+ zoneMinimizeToggle(zoneType:ZoneInstanceType):void;
+ zoneInstanceTagged(taggedInstance:ZoneInstance):void;
+ zoneInstanceModeChanged(newMode:ZoneInstanceMode, instance:ZoneInstance, zoneId:ZoneInstanceType);
+ unsetActiveZoneInstance():void;
clickOutsideZoneInstance():void;
+ zoneAssignmentSaveStart():void;
+ zoneAssignmentSaveComplete(success:boolean):void;
// Link menu - create link menu
relationMenuDirectiveObj:ConnectRelationModel;
@@ -98,7 +102,7 @@ export interface ICompositionGraphScope extends ng.IScope {
//modify link menu - for now only delete menu
relationMenuTimeout:ng.IPromise<any>;
linkMenuObject:LinkMenu;
- isOnDrag: boolean;
+ isOnDrag:boolean;
//left palette functions callbacks
dropCallback(event:JQueryEventObject, ui:any):void;
@@ -111,24 +115,24 @@ export interface ICompositionGraphScope extends ng.IScope {
hideRelationMenu();
//search,zoom in/out/all
- componentInstanceNames: Array<string>; //id, name
- zoom(zoomIn: boolean): void;
- zoomAll(nodes?:Cy.CollectionNodes): void;
- getAutoCompleteValues(searchTerm: string):void;
- highlightSearchMatches(searchTerm: string): void;
+ componentInstanceNames:Array<string>; //id, name
+ zoom(zoomIn:boolean):void;
+ zoomAllWithoutSidebar():void;
+ getAutoCompleteValues(searchTerm:string):void;
+ highlightSearchMatches(searchTerm:string):void;
canvasMenuProps:any;
- createOrUpdateServicePath(data: any):void;
+ createOrUpdateServicePath(data:any):void;
deletePathsOnCy():void;
- drawPathOnCy(data: ForwardingPath):void;
- selectedPathId: string;
+ drawPathOnCy(data:ForwardingPath):void;
+ selectedPathId:string;
/*//asset popover menu
- assetPopoverObj:AssetPopoverObj;
- assetPopoverOpen:boolean;
- hideAssetPopover():void;
- deleteNode(nodeId:string):void;*/
+ assetPopoverObj:AssetPopoverObj;
+ assetPopoverOpen:boolean;
+ hideAssetPopover():void;
+ deleteNode(nodeId:string):void;*/
}
export class CompositionGraph implements ng.IDirective {
@@ -153,12 +157,11 @@ export class CompositionGraph implements ng.IDirective {
private matchCapabilitiesRequirementsUtils:MatchCapabilitiesRequirementsUtils,
private CompositionGraphPaletteUtils:CompositionGraphPaletteUtils,
private compositionGraphZoneUtils:CompositionGraphZoneUtils,
- private ComponentServiceNg2: ComponentServiceNg2,
- private ModalServiceNg2: ModalService,
- private ConnectionWizardServiceNg2: ConnectionWizardService,
- private ComponentInstanceServiceNg2: ComponentInstanceServiceNg2,
- private servicePathGraphUtils: ServicePathGraphUtils,
- private policiesService:PoliciesService) {
+ private ComponentServiceNg2:ComponentServiceNg2,
+ private ModalServiceNg2:ModalService,
+ private ConnectionWizardServiceNg2:ConnectionWizardService,
+ private ComponentInstanceServiceNg2:ComponentInstanceServiceNg2,
+ private servicePathGraphUtils:ServicePathGraphUtils) {
}
@@ -173,14 +176,15 @@ export class CompositionGraph implements ng.IDirective {
link = (scope:ICompositionGraphScope, el:JQuery) => {
this.loadGraph(scope, el);
- if(scope.component.componentInstances && scope.component.componentInstancesRelations) {
- this.loadGraphData(scope);
- } else {
- //when we don't have the data we register to on graph load event
+ if (!scope.component.groupInstances || !scope.component.policies) {
this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_COMPOSITION_GRAPH_DATA_LOADED, () => {
this.loadGraphData(scope);
});
+ } else {
+ this.loadGraphData(scope);
}
+
+
scope.$on('$destroy', () => {
this._cy.destroy();
_.forEach(GRAPH_EVENTS, (event) => {
@@ -196,7 +200,10 @@ export class CompositionGraph implements ng.IDirective {
this.initGraphNodes(scope.component.componentInstances, scope.isViewOnly);
this.commonGraphUtils.initGraphLinks(this._cy, scope.component.componentInstancesRelations, scope.component.getRelationRequirementCapability.bind(scope.component));
this.commonGraphUtils.initUcpeChildren(this._cy);
- this.compositionGraphZoneUtils.initPolicyInstances(scope.zones.policy, scope.component.policies);
+ this.compositionGraphZoneUtils.initZoneInstances(scope.zones, scope.component);
+ setTimeout(() => {//Need settimeout so that angular canvas changes will take effect before resize & center
+ this.GeneralGraphUtils.zoomAllWithMax(this._cy, 1);
+ });
}
private loadGraph = (scope:ICompositionGraphScope, el:JQuery) => {
@@ -207,7 +214,6 @@ export class CompositionGraph implements ng.IDirective {
this.registerCytoscapeGraphEvents(scope);
this.registerCustomEvents(scope, el);
this.initViewMode(scope.isViewOnly);
-
};
private initGraph(graphEl:JQuery, isViewOnly:boolean) {
@@ -234,16 +240,26 @@ export class CompositionGraph implements ng.IDirective {
this._cy.off('drag');
this._cy.off('handlemouseout');
this._cy.off('handlemouseover');
+ this._cy.off('canvasredraw');
+ this._cy.off('handletagclick')
this._cy.edges().unselectify();
}
};
private registerCustomEvents(scope:ICompositionGraphScope, el:JQuery) {
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_GROUP_INSTANCE_UPDATE, (groupInstance:GroupInstance) => {
+ this.compositionGraphZoneUtils.findAndUpdateZoneInstanceData(scope.zones, groupInstance);
+ this.GeneralGraphUtils.showGroupUpdateSuccess();
+ });
+
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_POLICY_INSTANCE_UPDATE, (policyInstance: PolicyInstance) => {
+ this.compositionGraphZoneUtils.findAndUpdateZoneInstanceData(scope.zones, policyInstance);
+ this.GeneralGraphUtils.showPolicyUpdateSuccess();
+ });
+
this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HOVER_IN, (leftPaletteComponent:LeftPaletteComponent) => {
- if(scope.isOnDrag ||
- leftPaletteComponent.categoryType === LeftPaletteMetadataTypes.Group ||
- leftPaletteComponent.categoryType === LeftPaletteMetadataTypes.Policy) {
+ if (scope.isOnDrag) {
return;
}
@@ -264,47 +280,33 @@ export class CompositionGraph implements ng.IDirective {
//----------------------- ORIT TO FIX------------------------//
- this.ComponentServiceNg2.getCapabilitiesAndRequirements(leftPaletteComponent.componentType, leftPaletteComponent.uniqueId).subscribe((response: ComponentGenericResponse) => {
+ this.ComponentServiceNg2.getCapabilitiesAndRequirements(leftPaletteComponent.componentType, leftPaletteComponent.uniqueId).subscribe((response:ComponentGenericResponse) => {
- let component = this.ComponentFactory.createEmptyComponent(leftPaletteComponent.componentType);
- component.uniqueId = component.uniqueId;
- component.capabilities = response.capabilities;
- component.requirements = response.requirements;
- this.GeneralGraphUtils.componentRequirementsAndCapabilitiesCaching.setValue(leftPaletteComponent.uniqueId, component);
- let filteredNodesData = this.matchCapabilitiesRequirementsUtils.findMatchingNodes(component, nodesData, nodesLinks);
- this.matchCapabilitiesRequirementsUtils.fadeNonMachingComponents(filteredNodesData, nodesData, this._cy);
- this.matchCapabilitiesRequirementsUtils.highlightMatchingComponents(filteredNodesData, this._cy)
- });
+ let component = this.ComponentFactory.createEmptyComponent(leftPaletteComponent.componentType);
+ component.uniqueId = component.uniqueId;
+ component.capabilities = response.capabilities;
+ component.requirements = response.requirements;
+ this.GeneralGraphUtils.componentRequirementsAndCapabilitiesCaching.setValue(leftPaletteComponent.uniqueId, component);
+ });
});
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_ADD_COMPONENT_INSTANCE_ZONE_START, (component:Component, paletteComponent:LeftPaletteComponent, startPosition:Point) => {
- this.LoaderService.showLoader('composition-graph');
-
- let zoneType:string = LeftPaletteMetadataTypes[paletteComponent.categoryType].toLowerCase();
- scope.zones[zoneType].showZone = true;
- if(scope.minifyZone) scope.minifyZone = false;
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_ADD_ZONE_INSTANCE_FROM_PALETTE, (component:Component, paletteComponent:LeftPaletteComponent, startPosition:Point) => {
- this.policiesService.createPolicyInstance(component.componentType, component.uniqueId, paletteComponent.type).subscribe((newInstance)=>{
+ let zoneType:ZoneInstanceType = this.compositionGraphZoneUtils.getZoneTypeForPaletteComponent(paletteComponent.categoryType);
+ this.compositionGraphZoneUtils.showZone(scope.zones[zoneType]);
+ this.LoaderService.showLoader('composition-graph');
+ this.compositionGraphZoneUtils.createZoneInstanceFromLeftPalette(zoneType, component, paletteComponent.type).subscribe((zoneInstance:ZoneInstance) => {
this.LoaderService.hideLoader('composition-graph');
- scope.newZoneInstance = newInstance;
- this.compositionGraphZoneUtils.showAnimationToZone(startPosition, zoneType);
- }, (error) => {
+ this.compositionGraphZoneUtils.addInstanceToZone(scope.zones[zoneInstance.type], zoneInstance, true);
+ this.compositionGraphZoneUtils.createPaletteToZoneAnimation(startPosition, zoneType, zoneInstance);
+ }, (error)=> {
this.LoaderService.hideLoader('composition-graph');
});
});
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_FINISH_ANIMATION_ZONE, () => {
- if(scope.newZoneInstance){
- this.compositionGraphZoneUtils.addInstanceToZone(scope.zones['policy'], scope.newZoneInstance);
- }
- })
-
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_ZONE_SIZE_CHANGE, () => {
- scope.minifyZone = true;
- })
-
this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HOVER_OUT, () => {
+
this._cy.emit('hidehandles');
this.matchCapabilitiesRequirementsUtils.resetFadedNodes(this._cy);
});
@@ -334,13 +336,34 @@ export class CompositionGraph implements ng.IDirective {
this.NodesGraphUtils.deleteNode(this._cy, scope.component, nodeToDelete);
});
- this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_DELETE_MULTIPLE_COMPONENTS, () => {
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_DELETE_ZONE_INSTANCE, (deletedInstance:UIZoneInstanceObject) => {
- this._cy.$('node:selected').each((i:number, node:Cy.CollectionNodes) => {
- this.NodesGraphUtils.deleteNode(this._cy, scope.component, node);
- });
+ if(deletedInstance.type === ZoneInstanceType.POLICY){
+ scope.component.policies = scope.component.policies.filter(policy => policy.uniqueId !== deletedInstance.uniqueId);
+ } else if (deletedInstance.type === ZoneInstanceType.GROUP) {
+ scope.component.groupInstances = scope.component.groupInstances.filter(group => group.uniqueId !== deletedInstance.uniqueId);
+ }
+ //remove it from zones
+ scope.zones[deletedInstance.type].removeInstance(deletedInstance.uniqueId);
+ if (deletedInstance.type === ZoneInstanceType.GROUP && !_.isEmpty(scope.zones[ZoneInstanceType.POLICY])) {
+ this.compositionGraphZoneUtils.updateTargetsOrMembersOnCanvasDelete(deletedInstance.uniqueId, [scope.zones[ZoneInstanceType.POLICY]], ZoneInstanceAssignmentType.GROUPS);
+ }
+ this.eventListenerService.notifyObservers(EVENTS.UPDATE_PANEL);
+ });
+ this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_DELETE_COMPONENT_INSTANCE_SUCCESS, (componentInstanceId:string)=> {
+ if (!_.isEmpty(scope.zones)) {
+ this.compositionGraphZoneUtils.updateTargetsOrMembersOnCanvasDelete(componentInstanceId, scope.zones, ZoneInstanceAssignmentType.COMPONENT_INSTANCES);
+ }
});
+ // not in use; commenting out
+ // this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_DELETE_MULTIPLE_COMPONENTS, () => {
+
+ // this._cy.$('node:selected').each((i:number, node:Cy.CollectionNodes) => {
+ // this.NodesGraphUtils.deleteNode(this._cy, scope.component, node);
+ // });
+
+ // });
this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_DELETE_EDGE, (releaseLoading:boolean, linksToDelete:Cy.CollectionEdges) => {
this.CompositionGraphLinkUtils.deleteLink(this._cy, scope.component, releaseLoading, linksToDelete);
@@ -375,8 +398,9 @@ export class CompositionGraph implements ng.IDirective {
this.loadGraphData(scope);
});
- scope.zoom = (zoomIn: boolean):void => {
- let currentZoom: number = this._cy.zoom();
+
+ scope.zoom = (zoomIn:boolean):void => {
+ let currentZoom:number = this._cy.zoom();
if (zoomIn) {
this.GeneralGraphUtils.zoomGraphTo(this._cy, currentZoom + .1);
} else {
@@ -384,37 +408,32 @@ export class CompositionGraph implements ng.IDirective {
}
}
- //Zooms to fit all of the nodes in the collection passed in. If no nodes are passed in, will zoom to fit all nodes on graph
- scope.zoomAll = (nodes?:Cy.CollectionNodes) => {
- if (!nodes || !nodes.length) {
- nodes = this._cy.nodes();
- }
-
+
+ scope.zoomAllWithoutSidebar = () => {
scope.withSidebar = false;
- this._cy.animate({
- fit: { eles: nodes, padding: 20 },
- center: { eles: nodes }
- }, { duration: 400 });
+ setTimeout(() => { //wait for sidebar changes to take effect before zooming
+ this.GeneralGraphUtils.zoomAll(this._cy);
+ });
};
- scope.getAutoCompleteValues = (searchTerm: string) => {
+ scope.getAutoCompleteValues = (searchTerm:string) => {
if (searchTerm.length > 1) { //US requirement: only display search results after 2nd letter typed.
- let nodes: Cy.CollectionNodes = this.NodesGraphUtils.getMatchingNodesByName(this._cy, searchTerm);
+ let nodes:Cy.CollectionNodes = this.NodesGraphUtils.getMatchingNodesByName(this._cy, searchTerm);
scope.componentInstanceNames = _.map(nodes, node => node.data('name'));
} else {
scope.componentInstanceNames = [];
}
};
- scope.highlightSearchMatches = (searchTerm: string) => {
+ scope.highlightSearchMatches = (searchTerm:string) => {
this.NodesGraphUtils.highlightMatchingNodesByName(this._cy, searchTerm);
- let matchingNodes: Cy.CollectionNodes = this.NodesGraphUtils.getMatchingNodesByName(this._cy, searchTerm);
- scope.zoomAll(matchingNodes);
+ let matchingNodes:Cy.CollectionNodes = this.NodesGraphUtils.getMatchingNodesByName(this._cy, searchTerm);
+ this.GeneralGraphUtils.zoomAll(this._cy, matchingNodes);
};
scope.saveChangedCapabilityProperties = ():Promise<PropertyBEModel[]> => {
return new Promise<PropertyBEModel[]>((resolve) => {
- const capabilityPropertiesBE: PropertyBEModel[] = this.ConnectionWizardServiceNg2.changedCapabilityProperties.map((prop) => {
+ const capabilityPropertiesBE:PropertyBEModel[] = this.ConnectionWizardServiceNg2.changedCapabilityProperties.map((prop) => {
prop.value = prop.getJSONValue();
const propBE = new PropertyBEModel(prop);
propBE.parentUniqueId = this.ConnectionWizardServiceNg2.selectedMatch.relationship.relation.capabilityOwnerId;
@@ -464,7 +483,7 @@ export class CompositionGraph implements ng.IDirective {
scope.deletePathsOnCy = () => {
this.servicePathGraphUtils.deletePathsFromGraph(this._cy, <Service> scope.component);
};
- scope.drawPathOnCy = (data: ForwardingPath) => {
+ scope.drawPathOnCy = (data:ForwardingPath) => {
this.servicePathGraphUtils.drawPath(this._cy, data, <Service> scope.component);
};
@@ -486,10 +505,14 @@ export class CompositionGraph implements ng.IDirective {
this.ConnectionWizardServiceNg2.selectedMatch.relationship = relationship;
const title = `Connection Properties`;
- const saveButton: ButtonModel = new ButtonModel('Save', 'blue', () => {
- scope.saveChangedCapabilityProperties().then(() => { this.ModalServiceNg2.closeCurrentModal(); })
+ const saveButton:ButtonModel = new ButtonModel('Save', 'blue', () => {
+ scope.saveChangedCapabilityProperties().then(() => {
+ this.ModalServiceNg2.closeCurrentModal();
+ })
+ });
+ const cancelButton:ButtonModel = new ButtonModel('Cancel', 'white', () => {
+ this.ModalServiceNg2.closeCurrentModal();
});
- const cancelButton: ButtonModel = new ButtonModel('Cancel', 'white', () => { this.ModalServiceNg2.closeCurrentModal(); });
const modal = new ModalModel('xl', title, '', [saveButton, cancelButton]);
const modalInstance = this.ModalServiceNg2.createCustomModal(modal);
this.ModalServiceNg2.addDynamicContentToModal(modalInstance, ConnectionPropertiesViewComponent);
@@ -500,7 +523,8 @@ export class CompositionGraph implements ng.IDirective {
this.ComponentInstanceServiceNg2.getInstanceCapabilityProperties(scope.component, linkData.target, capability)
.subscribe(() => {
resolve();
- }, (error) => {});
+ }, (error) => {
+ });
} else {
resolve();
}
@@ -508,7 +532,8 @@ export class CompositionGraph implements ng.IDirective {
this.ModalServiceNg2.addDynamicContentToModal(modalInstance, ConnectionPropertiesViewComponent);
})
- }, (error) => {});
+ }, (error) => {
+ });
};
scope.deleteRelation = (link:Cy.CollectionEdges) => {
@@ -523,20 +548,20 @@ export class CompositionGraph implements ng.IDirective {
};
/*
- scope.hideAssetPopover = ():void => {
-
- this.commonGraphUtils.safeApply(scope, () => {
- scope.assetPopoverOpen = false;
- scope.assetPopoverObj = null;
- });
- };
-
- scope.deleteNode = (nodeId:string):void => {
- if (!scope.isViewOnly) {
- this.NodesGraphUtils.confirmDeleteNode(nodeId, this._cy, scope.component);
- //scope.hideAssetPopover();
- }
- };*/
+ scope.hideAssetPopover = ():void => {
+
+ this.commonGraphUtils.safeApply(scope, () => {
+ scope.assetPopoverOpen = false;
+ scope.assetPopoverObj = null;
+ });
+ };
+
+ scope.deleteNode = (nodeId:string):void => {
+ if (!scope.isViewOnly) {
+ this.NodesGraphUtils.confirmDeleteNode(nodeId, this._cy, scope.component);
+ //scope.hideAssetPopover();
+ }
+ };*/
}
private registerCytoscapeGraphEvents(scope:ICompositionGraphScope) {
@@ -599,22 +624,30 @@ export class CompositionGraph implements ng.IDirective {
}
});
- /* this._cy.on('mouseover', 'node', (event:Cy.EventObject) => {
- if (!this._cy.scratch('_edge_editation_highlights')) {
- this.commonGraphUtils.safeApply(scope, () => {
- this.showNodePopoverMenu(scope, event.cyTarget[0]);
- });
- }
- });
+ /* this._cy.on('mouseover', 'node', (event:Cy.EventObject) => {
+ if (!this._cy.scratch('_edge_editation_highlights')) {
+ this.commonGraphUtils.safeApply(scope, () => {
+ this.showNodePopoverMenu(scope, event.cyTarget[0]);
+ });
+ }
+ });
+
+ this._cy.on('mouseout', 'node', (event:Cy.EventObject) => {
+ scope.hideAssetPopover();
+ });*/
+
- this._cy.on('mouseout', 'node', (event:Cy.EventObject) => {
- scope.hideAssetPopover();
- });*/
this._cy.on('handlemouseover', (event, payload) => {
if (payload.node.grabbed() || this._cy.scratch('_edge_editation_highlights') === true) { //no need to add opacity while we are dragging and hovering othe nodes- or if opacity was already calculated for these nodes
return;
}
+
+ if (scope.zoneTagMode) {
+ scope.zoneTagMode = scope.zones[scope.activeZoneInstance.type].getHoverTagModeId();
+ return;
+ }
+
let nodesData = this.NodesGraphUtils.getAllNodesData(this._cy.nodes());
let nodesLinks = this.GeneralGraphUtils.getAllCompositionCiLinks(this._cy);
@@ -622,12 +655,16 @@ export class CompositionGraph implements ng.IDirective {
let filteredNodesData = this.matchCapabilitiesRequirementsUtils.findMatchingNodes(payload.node.data().componentInstance, linkableNodes, nodesLinks);
this.matchCapabilitiesRequirementsUtils.highlightMatchingComponents(filteredNodesData, this._cy);
this.matchCapabilitiesRequirementsUtils.fadeNonMachingComponents(filteredNodesData, nodesData, this._cy, payload.node.data());
-
+
this._cy.scratch()._edge_editation_highlights = true;
/*scope.hideAssetPopover();*/
});
this._cy.on('handlemouseout', () => {
+ if (scope.zoneTagMode) {
+ scope.zoneTagMode = scope.zones[scope.activeZoneInstance.type].getTagModeId();
+ return;
+ }
if (this._cy.scratch('_edge_editation_highlights') === true) {
this._cy.removeScratch('_edge_editation_highlights');
this._cy.emit('hidehandles');
@@ -638,15 +675,20 @@ export class CompositionGraph implements ng.IDirective {
this._cy.on('tapend', (event:Cy.EventObject) => {
scope.isOnDrag = false;
+ if (scope.zoneTagMode) {
+ return;
+ }
if (event.cyTarget === this._cy) { //On Background clicked
if (this._cy.$('node:selected').length === 0) { //if the background click but not dragged
+ if (scope.activeZoneInstance) {
+ scope.unsetActiveZoneInstance();
+ }
this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_GRAPH_BACKGROUND_CLICKED);
}
scope.hideRelationMenu();
}
else if (event.cyTarget.isEdge()) { //On Edge clicked
- if (scope.isViewOnly) return;
this.CompositionGraphLinkUtils.handleLinkClick(this._cy, event);
if (event.cyTarget.data().type === CompositionCiServicePathLink.LINK_TYPE) {
return;
@@ -655,6 +697,7 @@ export class CompositionGraph implements ng.IDirective {
}
else { //On Node clicked
+
this._cy.nodes(':grabbed').style({'overlay-opacity': 0});
let isUcpe:boolean = event.cyTarget.data().isUcpe;
@@ -668,6 +711,9 @@ export class CompositionGraph implements ng.IDirective {
this.NodesGraphUtils.onNodesPositionChanged(this._cy, scope.component, nodesMoved);
} else {
this.$log.debug('composition-graph::onNodeSelectedEvent:: fired');
+ if (scope.activeZoneInstance) {
+ scope.unsetActiveZoneInstance();
+ }
scope.$apply(() => {
this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_NODE_SELECTED, event.cyTarget.data().componentInstance);
//open node popover menu
@@ -684,8 +730,21 @@ export class CompositionGraph implements ng.IDirective {
});
this._cy.on('boxselect', 'node', (event:Cy.EventObject) => {
+ scope.unsetActiveZoneInstance();
this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_NODE_SELECTED, event.cyTarget.data().componentInstance);
});
+
+ this._cy.on('canvasredraw', (event:Cy.EventObject) => {
+ if (scope.zoneTagMode) {
+ this.compositionGraphZoneUtils.showZoneTagIndications(this._cy, scope.activeZoneInstance);
+ }
+ });
+
+ this._cy.on('handletagclick', (event:Cy.EventObject, eventData:any) => {
+ this.compositionGraphZoneUtils.handleTagClick(this._cy, scope.activeZoneInstance, eventData.nodeId);
+
+
+ });
}
private openModifyLinkMenu = (scope:ICompositionGraphScope, linkMenuObject:LinkMenu, timeOutInMilliseconds?:number) => {
@@ -710,14 +769,15 @@ export class CompositionGraph implements ng.IDirective {
}
});
}
- scope.canvasMenuProps.items.push({
- contents: 'Delete',
- styleClass: 'w-sdc-canvas-menu-item-delete',
- action: () => {
- scope.deleteRelation(<Cy.CollectionEdges>linkMenuObject.link);
- }
- });
-
+ if(!scope.isViewOnly){
+ scope.canvasMenuProps.items.push({
+ contents: 'Delete',
+ styleClass: 'w-sdc-canvas-menu-item-delete',
+ action: () => {
+ scope.deleteRelation(<Cy.CollectionEdges>linkMenuObject.link);
+ }
+ });
+ }
scope.relationMenuTimeout = this.$timeout(() => {
scope.hideRelationMenu();
}, timeOutInMilliseconds ? timeOutInMilliseconds : 6000);
@@ -726,15 +786,19 @@ export class CompositionGraph implements ng.IDirective {
private initGraphNodes(componentInstances:ComponentInstance[], isViewOnly:boolean) {
- if (!isViewOnly) { //Init nodes handle extension - enable dynamic links
- setTimeout(()=> {
- let handles = new CytoscapeEdgeEditation;
- handles.init(this._cy, 18);
- handles.registerHandle(ComponentInstanceNodesStyle.getBasicNodeHanlde());
- handles.registerHandle(ComponentInstanceNodesStyle.getBasicSmallNodeHandle());
- handles.registerHandle(ComponentInstanceNodesStyle.getUcpeCpNodeHandle());
- }, 0);
- }
+
+ setTimeout(()=> {
+ let handles = new CytoscapeEdgeEditation;
+ handles.init(this._cy);
+ if (!isViewOnly) { //Init nodes handle extension - enable dynamic links
+ handles.initNodeEvents();
+ handles.registerHandle(ComponentInstanceNodesStyle.getAddEdgeHandle());
+ }
+ handles.registerHandle(ComponentInstanceNodesStyle.getTagHandle());
+ handles.registerHandle(ComponentInstanceNodesStyle.getTaggedPolicyHandle());
+ handles.registerHandle(ComponentInstanceNodesStyle.getTaggedGroupHandle());
+ }, 0);
+
_.each(componentInstances, (instance) => {
let compositionGraphNode:CompositionCiNodeBase = this.NodesFactory.createNode(instance);
@@ -755,7 +819,7 @@ export class CompositionGraph implements ng.IDirective {
scope.verifyDrop = (event:JQueryEventObject) => {
- if (this.dragElement.hasClass('red')) {
+ if (!this.dragElement || this.dragElement.hasClass('red')) {
return false;
}
return true;
@@ -777,43 +841,85 @@ export class CompositionGraph implements ng.IDirective {
private initZones = (scope:ICompositionGraphScope):void => {
scope.zones = this.compositionGraphZoneUtils.createCompositionZones();
- scope.zoneInstanceModeChanged = (newMode:ZoneInstanceMode, instance:ZoneInstanceConfig, zoneId:string):void => {
- if(scope.zoneTagMode) { //we're in tag mode.
- if(instance == scope.activeZoneInstance && newMode == ZoneInstanceMode.TAG){ //we want to toggle tag mode off.
- scope.unsetActiveZoneInstance();
+
+ scope.zoneMinimizeToggle = (zoneType:ZoneInstanceType):void => {
+ scope.zones[zoneType].minimized = !scope.zones[zoneType].minimized;
+ };
+
+ scope.zoneInstanceModeChanged = (newMode:ZoneInstanceMode, instance:ZoneInstance, zoneId:ZoneInstanceType):void => {
+ if (scope.zoneTagMode) { //we're in tag mode.
+ if (instance == scope.activeZoneInstance && newMode == ZoneInstanceMode.NONE) { //we want to turn tag mode off.
+ scope.zoneTagMode = null;
+ scope.activeZoneInstance.mode = ZoneInstanceMode.SELECTED;
+ this.compositionGraphZoneUtils.endCyTagMode(this._cy);
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_CANVAS_TAG_END, instance);
+
}
} else {
- scope.setZoneInstanceMode(newMode, instance, zoneId);
- }
- };
+ if (instance != scope.activeZoneInstance || (instance == scope.activeZoneInstance && newMode > ZoneInstanceMode.HOVER)) { //when active zone instance gets hover/none,dont actually change mode, just show/hide indications
+ instance.mode = newMode;
+ }
- scope.setZoneInstanceMode = (newMode:ZoneInstanceMode, instance:ZoneInstanceConfig, zoneId:string):void => {
- instance.mode = newMode;
- switch(newMode){
- case ZoneInstanceMode.TAG: {
- scope.zoneTagMode = zoneId + "-tagging";
+ if (newMode == ZoneInstanceMode.NONE) {
+ this.compositionGraphZoneUtils.hideZoneTagIndications(this._cy);
+ if (scope.zones[ZoneInstanceType.GROUP]) {
+ this.compositionGraphZoneUtils.hideGroupZoneIndications(scope.zones[ZoneInstanceType.GROUP].instances);
+ }
+ }
+ if (newMode >= ZoneInstanceMode.HOVER) {
+ this.compositionGraphZoneUtils.showZoneTagIndications(this._cy, instance);
+ if (instance.type == ZoneInstanceType.POLICY && scope.zones[ZoneInstanceType.GROUP]) {
+ this.compositionGraphZoneUtils.showGroupZoneIndications(scope.zones[ZoneInstanceType.GROUP].instances, instance);
+ }
}
- case ZoneInstanceMode.SELECTED: { //case TAG flows into here as well
+ if (newMode >= ZoneInstanceMode.SELECTED) {
+ this._cy.$('node:selected').unselect();
+ if (scope.activeZoneInstance && scope.activeZoneInstance != instance && newMode >= ZoneInstanceMode.SELECTED) {
+ scope.activeZoneInstance.mode = ZoneInstanceMode.NONE;
+ }
scope.activeZoneInstance = instance;
- break;
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_ZONE_INSTANCE_SELECTED, instance);
+ }
+ if (newMode == ZoneInstanceMode.TAG) {
+ this.compositionGraphZoneUtils.startCyTagMode(this._cy);
+ scope.zoneTagMode = scope.zones[zoneId].getTagModeId();
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_CANVAS_TAG_START, zoneId);
}
}
};
- scope.unsetActiveZoneInstance = ():void => {
- scope.activeZoneInstance.mode = ZoneInstanceMode.NONE;
- scope.activeZoneInstance = null;
- scope.zoneTagMode = null;
- };
+ scope.zoneInstanceTagged = (taggedInstance:ZoneInstance) => {
+ scope.activeZoneInstance.addOrRemoveAssignment(taggedInstance.instanceData.uniqueId, ZoneInstanceAssignmentType.GROUPS);
+ let newHandle:string = this.compositionGraphZoneUtils.getCorrectHandleForNode(taggedInstance.instanceData.uniqueId, scope.activeZoneInstance);
+ taggedInstance.showHandle(newHandle);
+ }
- scope.clickOutsideZoneInstance = ():void => {
- if(!scope.zoneTagMode)
+ scope.zoneBackgroundClicked = ():void => {
+ if (!scope.zoneTagMode && scope.activeZoneInstance) {
scope.unsetActiveZoneInstance();
+ }
};
- };
+ scope.zoneAssignmentSaveStart = () => {
+ this.LoaderService.showLoader('composition-graph');
+ }
+ scope.zoneAssignmentSaveComplete = (success:boolean) => {
+ this.LoaderService.hideLoader('composition-graph');
+ if (!success) {
+ this.GeneralGraphUtils.showUpdateFailure();
+ }
+ };
+ scope.unsetActiveZoneInstance = ():void => {
+ if(scope.activeZoneInstance){
+ scope.activeZoneInstance.mode = ZoneInstanceMode.NONE;
+ scope.activeZoneInstance = null;
+ scope.zoneTagMode = null;
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_GRAPH_BACKGROUND_CLICKED);
+ }
+ };
+ };
public static factory = ($q,
@@ -835,8 +941,7 @@ export class CompositionGraph implements ng.IDirective {
ModalService,
ConnectionWizardService,
ComponentInstanceServiceNg2,
- ServicePathGraphUtils,
- PoliciesService) => {
+ ServicePathGraphUtils) => {
return new CompositionGraph(
$q,
$log,
@@ -857,8 +962,7 @@ export class CompositionGraph implements ng.IDirective {
ModalService,
ConnectionWizardService,
ComponentInstanceServiceNg2,
- ServicePathGraphUtils,
- PoliciesService);
+ ServicePathGraphUtils);
}
}
@@ -882,6 +986,5 @@ CompositionGraph.factory.$inject = [
'ModalServiceNg2',
'ConnectionWizardServiceNg2',
'ComponentInstanceServiceNg2',
- 'ServicePathGraphUtils',
- 'PoliciesServiceNg2'
+ 'ServicePathGraphUtils'
];
diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.html b/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.html
index 487e4cb65a..2d8145f81e 100644
--- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.html
+++ b/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.html
@@ -1,12 +1,12 @@
<loader display="isLoading" loader-type="composition-graph"></loader>
-<div class="sdc-composition-graph-wrapper {{zoneTagMode}}" ng-class="{'view-only':isViewOnly}"
- data-drop="true"
+<div class="sdc-composition-graph-wrapper {{zoneTagMode}}" ng-class="{'with-sidebar': withSidebar, 'view-only':isViewOnly}"
+ data-drop="!zoneTagMode"
data-jqyoui-options="{accept: verifyDrop}"
data-jqyoui-droppable="{onDrop:'dropCallback', beforeDrop: 'beforeDropCallback'}">
</div>
-<relation-menu relation-menu-directive-obj="relationMenuDirectiveObj" is-link-menu-open="isLinkMenuOpen"
- create-relation="createLinkFromMenu" cancel="cancelRelationMenu()"></relation-menu>
+<!-- <relation-menu relation-menu-directive-obj="relationMenuDirectiveObj" is-link-menu-open="isLinkMenuOpen"
+ create-relation="createLinkFromMenu" cancel="cancelRelationMenu()"></relation-menu> -->
<menu-list-ng2 [props]="canvasMenuProps"></menu-list-ng2>
@@ -19,10 +19,11 @@
[delete-paths]="deletePathsOnCy"
[selected-path-id]="selectedPathId">
</ng2-service-path-selector>
- <ng2-service-path
+ <ng2-service-path
ng-if="component.isService()"
[service]="component"
- [on-create]="createOrUpdateServicePath">
+ [on-create]="createOrUpdateServicePath"
+ [is-view-only]="isViewOnly">
</ng2-service-path>
<ng2-search-with-autocomplete
[search-placeholder]="'Type to search'"
@@ -31,17 +32,19 @@
(search-button-clicked)="highlightSearchMatches($event)"
[search-bar-class]="'composition-search'">
</ng2-search-with-autocomplete>
- <div class="zoom-icons sprite-new canvas-fit-all" data-ng-click="zoomAll()"></div>
+ <div class="zoom-icons sprite-new canvas-fit-all" data-ng-click="zoomAllWithoutSidebar()"></div>
<div class="zoom-icons sprite-new zoom-plus" data-ng-click="zoom(true)"></div>
<div class="zoom-icons sprite-new zoom-minus" data-ng-click="zoom(false)"></div>
</div>
<!--<asset-popover ng-if="assetPopoverOpen" asset-popover-obj="assetPopoverObj" delete-asset="deleteNode(assetPopoverObj.nodeId)"></asset-popover>-->
<div class="sdc-canvas-zones__wrapper {{zoneTagMode}}" data-ng-class="{'with-sidebar': withSidebar}">
- <ng2-zone-container data-ng-repeat="zoneConfig in zones" [title]="zoneConfig.title" [class]="zoneConfig.type" [count]="zoneConfig.instances.length" [show-zone] = "zoneConfig.showZone" [minify-zone] = "minifyZone">
+ <ng2-zone-container data-ng-repeat="zone in zones" [title]="zone.title" [type]="zone.type" [count]="zone.instances.length"
+ [visible]="zone.visible" [minimized]="zone.minimized" (minimize)="zoneMinimizeToggle(zone.type)" (background-click)="zoneBackgroundClicked()">
<ng2-zone-instance
- data-ng-repeat="instance in zoneConfig.instances" clicked-outside="{onClickedOutside: 'clickOutsideZoneInstance()', clickedOutsideEnable: 'activeZoneInstance == instance'}"
- [config]="instance" [default-icon-text]="zoneConfig.defaultIconText" [is-active]="activeZoneInstance == instance" [active-instance-mode]="activeZoneInstance && activeZoneInstance.mode"
- (mode-change)="zoneInstanceModeChanged($event.newMode, $event.instance, zoneConfig.type)">
+ data-ng-repeat="instance in zone.instances" [hidden]="instance.hidden"
+ [zone-instance]="instance" [default-icon-text]="zone.defaultIconText" [is-active]="activeZoneInstance == instance" [active-instance-mode]="activeZoneInstance && activeZoneInstance.mode"
+ [is-view-only]="isViewOnly" [force-save]="instance.forceSave" (mode-change)="zoneInstanceModeChanged($event.newMode, $event.instance, zone.type)" (tag-handle-click)="zoneInstanceTagged($event)"
+ (assignment-save-start)="zoneAssignmentSaveStart()" (assignment-save-complete)="zoneAssignmentSaveComplete($event)">
</ng2-zone-instance>
</ng2-zone-container>
-</div>
+</div> \ No newline at end of file
diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.less b/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.less
index 5a6a104670..7124a4b5a6 100644
--- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.less
+++ b/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.less
@@ -6,6 +6,10 @@ composition-graph {
.sdc-composition-graph-wrapper{
height:100%;
width: 100%;
+
+ &.with-sidebar {
+ width: calc(~'100% - 300px');
+ }
}
.view-only{
@@ -29,10 +33,18 @@ composition-graph {
}
}
+
.group-tagging {
- cursor: url("/assets/styles/images/canvas-tagging-icons/adding_group.svg"), pointer;
+ cursor: url("../../../../assets/styles/images/canvas-tagging-icons/group_1.svg"), pointer;
+ }
+ .group-tagging-hover {
+ cursor: url("../../../../assets/styles/images/canvas-tagging-icons/group_2.svg"), pointer;
}
.policy-tagging {
- cursor: url("/assets/styles/images/canvas-tagging-icons/adding_policy.svg"), pointer;
+ cursor: url("../../../../assets/styles/images/canvas-tagging-icons/policy_1.svg"), pointer;
+ }
+ .policy-tagging-hover {
+ cursor: url("../../../../assets/styles/images/canvas-tagging-icons/policy_2.svg"), pointer;
}
+
}
diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-general-utils.ts b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-general-utils.ts
index 73e03e954d..329af56e87 100644
--- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-general-utils.ts
+++ b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-general-utils.ts
@@ -34,7 +34,8 @@ export class CompositionGraphGeneralUtils {
constructor(private $q:ng.IQService,
private LoaderService:LoaderService,
private commonGraphUtils:CommonGraphUtils,
- private matchCapabilitiesRequirementsUtils:MatchCapabilitiesRequirementsUtils) {
+ private matchCapabilitiesRequirementsUtils:MatchCapabilitiesRequirementsUtils,
+ private Notification:any) {
CompositionGraphGeneralUtils.graphUtilsUpdateQueue = new QueueUtils(this.$q);
}
@@ -73,6 +74,34 @@ export class CompositionGraphGeneralUtils {
renderedPosition: { x: zx, y: zy }
});
}
+
+
+ //saves the current zoom, and then sets a temporary maximum zoom for zoomAll, and then reverts to old value
+ public zoomAllWithMax = (cy:Cy.Instance, maxZoom:number):void => {
+
+ let oldMaxZoom:number = cy.maxZoom();
+
+ cy.maxZoom(maxZoom);
+ this.zoomAll(cy);
+ cy.maxZoom(oldMaxZoom);
+
+ };
+
+
+ //Zooms to fit all of the nodes in the collection passed in. If no nodes are passed in, will zoom to fit all nodes on graph
+ public zoomAll = (cy:Cy.Instance, nodes?:Cy.CollectionNodes):void => {
+
+ if (!nodes || !nodes.length) {
+ nodes = cy.nodes();
+ }
+
+ cy.resize();
+ cy.animate({
+ fit: { eles: nodes, padding: 20 },
+ center: { eles: nodes }
+ }, { duration: 400 });
+ };
+
/**
* will return true/false if two nodes overlapping
*
@@ -223,6 +252,27 @@ export class CompositionGraphGeneralUtils {
};
+ public showPolicyUpdateSuccess = () => {
+ this.Notification.success({
+ message: "Policy Updated",
+ title: "Success"
+ });
+ }
+
+ public showGroupUpdateSuccess = () => {
+ this.Notification.success({
+ message: "Group Updated",
+ title: "Success"
+ });
+ }
+
+ public showUpdateFailure = () => {
+ this.Notification.error({
+ message: "Update Failed",
+ title: "Error"
+ });
+ };
+
/**
* Get Graph Utils server queue
* @returns {QueueUtils}
@@ -270,4 +320,4 @@ export class CompositionGraphGeneralUtils {
};
}
-CompositionGraphGeneralUtils.$inject = ['$q', 'LoaderService', 'CommonGraphUtils', 'MatchCapabilitiesRequirementsUtils'];
+CompositionGraphGeneralUtils.$inject = ['$q', 'LoaderService', 'CommonGraphUtils', 'MatchCapabilitiesRequirementsUtils', 'Notification'];
diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-nodes-utils.ts b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-nodes-utils.ts
index fb1e6650bd..cfec49267a 100644
--- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-nodes-utils.ts
+++ b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-nodes-utils.ts
@@ -105,6 +105,8 @@ export class CompositionGraphNodesUtils {
(<Service>component).forwardingPaths = response.forwardingPaths;
});
+ this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_DELETE_COMPONENT_INSTANCE_SUCCESS, nodeId);
+
//update UI
cy.remove(nodeToDelete);
};
diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-service-path-utils.ts b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-service-path-utils.ts
index ef047d7dd3..1a348912fc 100644
--- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-service-path-utils.ts
+++ b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-service-path-utils.ts
@@ -47,8 +47,14 @@ export class ServicePathGraphUtils {
_.forEach(pathElements, (link: ForwardingPathLink) => {
let data:CompositionCiServicePathLink = new CompositionCiServicePathLink(link);
- data.source = data.forwardingPathLink.fromNode;
- data.target = data.forwardingPathLink.toNode;
+ data.source = _.find(
+ service.componentInstances,
+ instance => instance.name === data.forwardingPathLink.fromNode
+ ).uniqueId;
+ data.target = _.find(
+ service.componentInstances,
+ instance => instance.name === data.forwardingPathLink.toNode
+ ).uniqueId;
data.pathId = forwardingPath.uniqueId;
data.pathName = forwardingPath.name;
this.commonGraphUtils.insertServicePathLinkToGraph(cy, data);
diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-zone-utils.ts b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-zone-utils.ts
index 28f2dc85d2..bcf0cb7bb9 100644
--- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-zone-utils.ts
+++ b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-zone-utils.ts
@@ -1,55 +1,195 @@
-import { PolicyInstance } from "app/models/graph/zones/policy-instance";
-import { ZoneConfig, ZoneInstanceConfig } from "app/models/graph/zones/zone-child";
-import { DynamicComponentService } from "app/ng2/services/dynamic-component.service";
-import { PaletteAnimationComponent } from "app/ng2/components/ui/palette-animation/palette-animation.component";
-import { Point } from "../../../../models";
+import {PolicyInstance} from "app/models/graph/zones/policy-instance";
+import {ZoneInstance, ZoneInstanceType, ZoneInstanceAssignmentType} from "app/models/graph/zones/zone-instance";
+import {Zone} from "app/models/graph/zones/zone";
+import {DynamicComponentService} from "app/ng2/services/dynamic-component.service";
+import {PaletteAnimationComponent} from "app/ng2/components/ui/palette-animation/palette-animation.component";
+import {Point, LeftPaletteMetadataTypes, Component} from "../../../../models";
+import {CanvasHandleTypes} from "app/utils";
+import {PoliciesService} from "../../../../ng2/services/policies.service";
+import {Observable} from "rxjs";
+import {GroupsService} from "../../../../ng2/services/groups.service";
+import {GroupInstance} from "app/models/graph/zones/group-instance";
+
export class CompositionGraphZoneUtils {
- constructor(private dynamicComponentService: DynamicComponentService) {}
+ constructor(private dynamicComponentService:DynamicComponentService,
+ private policiesService:PoliciesService,
+ private groupsService:GroupsService) {
+ }
+
+
+ public createCompositionZones = ():Array<Zone> => {
+ let zones:Array<Zone> = [];
+
+ zones[ZoneInstanceType.POLICY] = new Zone('Policies', 'P', ZoneInstanceType.POLICY);
+ zones[ZoneInstanceType.GROUP] = new Zone('Groups', 'G', ZoneInstanceType.GROUP);
- public createCompositionZones(){
- let zones = {
- 'policy': new ZoneConfig('Policies', 'P', 'policy', false),
- 'group': new ZoneConfig('Groups', 'G', 'group', false)
- };
return zones;
}
- public initPolicyInstances(policyZone:ZoneConfig, policies:Array<PolicyInstance>) {
- if(policies && policies.length){
- policyZone.showZone = true;
+ public showZone = (zone:Zone):void => {
+ zone.visible = true;
+ zone.minimized = false;
+ }
+
+ public getZoneTypeForPaletteComponent = (componentCategory:LeftPaletteMetadataTypes) => {
+ if (componentCategory == LeftPaletteMetadataTypes.Group) {
+ return ZoneInstanceType.GROUP;
+ } else if (componentCategory == LeftPaletteMetadataTypes.Policy) {
+ return ZoneInstanceType.POLICY;
+ }
+ };
+
+ public initZoneInstances(zones:Array<Zone>, component:Component) {
+ if (component.groupInstances && component.groupInstances.length) {
+ this.showZone(zones[ZoneInstanceType.GROUP]);
+ _.forEach(component.groupInstances, (group:GroupInstance) => {
+ let newInstance = new ZoneInstance(group, component);
+ this.addInstanceToZone(zones[ZoneInstanceType.GROUP], newInstance);
+ });
+ }
+
+ if (component.policies && component.policies.length) {
+ this.showZone(zones[ZoneInstanceType.POLICY]);
+ _.forEach(component.policies, (policy:PolicyInstance) => {
+ let newInstance = new ZoneInstance(policy, component);
+ this.addInstanceToZone(zones[ZoneInstanceType.POLICY], newInstance);
+
+ });
}
- _.forEach(policies, (policy:PolicyInstance) => {
- policyZone.instances.push(new ZoneInstanceConfig(policy));
+ }
+
+ public findAndUpdateZoneInstanceData (zones: Array<Zone>, instanceData:PolicyInstance | GroupInstance) {
+ _.forEach(zones, (zone:Zone) => {
+ _.forEach(zone.instances, (zoneInstance:ZoneInstance) => {
+ if(zoneInstance.instanceData.uniqueId === instanceData.uniqueId){
+ zoneInstance.updateInstanceData(instanceData);
+ }
+ });
});
}
- public addInstanceToZone(zone:ZoneConfig, instance:PolicyInstance){
- zone.instances.push(new ZoneInstanceConfig(instance));
+ public updateTargetsOrMembersOnCanvasDelete = (canvasNodeID:string, zones:Array<Zone>, type:ZoneInstanceAssignmentType):void => {
+ _.forEach(zones, (zone) => {
+ _.forEach(zone.instances, (zoneInstance:ZoneInstance) => {
+ if (zoneInstance.isAlreadyAssigned(canvasNodeID)) {
+ zoneInstance.addOrRemoveAssignment(canvasNodeID, type);
+ //remove it from our list of BE targets and members as well (so that it will not be sent in future calls to BE).
+ zoneInstance.instanceData.setSavedAssignments(zoneInstance.assignments);
+ }
+ });
+ });
+ };
+
+ public createZoneInstanceFromLeftPalette = (zoneType:ZoneInstanceType, component:Component, paletteComponentType:string):Observable<ZoneInstance> => {
+ if (zoneType === ZoneInstanceType.POLICY) {
+ return this.policiesService.createPolicyInstance(component.componentType, component.uniqueId, paletteComponentType).map(response => {
+ let newInstance = new PolicyInstance(response);
+ component.policies.push(newInstance);
+ return new ZoneInstance(newInstance, component);
+ });
+ } else if (zoneType === ZoneInstanceType.GROUP) {
+ return this.groupsService.createGroupInstance(component.componentType, component.uniqueId, paletteComponentType).map(response => {
+ let newInstance = new GroupInstance(response);
+ component.groupInstances.push(newInstance);
+ return new ZoneInstance(newInstance, component);
+ });
+ }
+ }
+
+ public addInstanceToZone(zone:Zone, instance:ZoneInstance, hide?:boolean) {
+ if(hide){
+ instance.hidden = true;
+ }
+ zone.instances.push(instance);
+
};
- private findZoneCoordinates(zoneType):Point{
- let point:Point = new Point(0,0);
+ private findZoneCoordinates(zoneType):Point {
+ let point:Point = new Point(0, 0);
let zone = angular.element(document.querySelector('.' + zoneType + '-zone'));
- let wrapperZone = zone.offsetParent();
- point.x = zone.prop('offsetLeft') + wrapperZone.prop('offsetLeft');
- point.y = zone.prop('offsetTop') + wrapperZone.prop('offsetTop');
+ let wrapperZone = zone.offsetParent();
+ point.x = zone.prop('offsetLeft') + wrapperZone.prop('offsetLeft');
+ point.y = zone.prop('offsetTop') + wrapperZone.prop('offsetTop');
return point;
}
- public showAnimationToZone = (startPoint:Point, zoneType:string) => {
-
+ public createPaletteToZoneAnimation = (startPoint:Point, zoneType:ZoneInstanceType, newInstance:ZoneInstance) => {
+ let zoneTypeName = ZoneInstanceType[zoneType].toLowerCase();
let paletteToZoneAnimation = this.dynamicComponentService.createDynamicComponent(PaletteAnimationComponent);
paletteToZoneAnimation.instance.from = startPoint;
- paletteToZoneAnimation.instance.to = this.findZoneCoordinates(zoneType);
- paletteToZoneAnimation.instance.iconName = zoneType;
+ paletteToZoneAnimation.instance.type = zoneType;
+ paletteToZoneAnimation.instance.to = this.findZoneCoordinates(zoneTypeName);
+ paletteToZoneAnimation.instance.zoneInstance = newInstance;
+ paletteToZoneAnimation.instance.iconName = zoneTypeName;
paletteToZoneAnimation.instance.runAnimation();
}
-
+ public startCyTagMode = (cy:Cy.Instance) => {
+ cy.autolock(true);
+ cy.nodes().unselectify();
+ cy.emit('tagstart'); //dont need to show handles because they're already visible bcz of hover event
+
+ };
+
+ public endCyTagMode = (cy:Cy.Instance) => {
+ cy.emit('tagend');
+ cy.nodes().selectify();
+ cy.autolock(false);
+ };
+
+ public handleTagClick = (cy:Cy.Instance, zoneInstance:ZoneInstance, nodeId:string) => {
+ zoneInstance.addOrRemoveAssignment(nodeId, ZoneInstanceAssignmentType.COMPONENT_INSTANCES);
+ this.showZoneTagIndicationForNode(nodeId, zoneInstance, cy);
+ };
+
+ public showGroupZoneIndications = (groupInstances:Array<ZoneInstance>, policyInstance:ZoneInstance) => {
+ groupInstances.forEach((groupInstance:ZoneInstance)=> {
+ let handle:string = this.getCorrectHandleForNode(groupInstance.instanceData.uniqueId, policyInstance);
+ groupInstance.showHandle(handle);
+ })
+ };
+
+ public hideGroupZoneIndications = (instances:Array<ZoneInstance>) => {
+ instances.forEach((instance) => {
+ instance.hideHandle();
+ })
+ }
+
+ public showZoneTagIndications = (cy:Cy.Instance, zoneInstance:ZoneInstance) => {
+
+ cy.nodes().forEach(node => {
+ let handleType:string = this.getCorrectHandleForNode(node.id(), zoneInstance);
+ cy.emit('showhandle', [node, handleType]);
+ });
+ };
+
+ public showZoneTagIndicationForNode = (nodeId:string, zoneInstance:ZoneInstance, cy:Cy.Instance) => {
+ let node = cy.getElementById(nodeId);
+ let handleType:string = this.getCorrectHandleForNode(nodeId, zoneInstance);
+ cy.emit('showhandle', [node, handleType]);
+ }
+
+ public hideZoneTagIndications = (cy:Cy.Instance) => {
+ cy.emit('hidehandles');
+ };
+
+ public getCorrectHandleForNode = (nodeId:string, zoneInstance:ZoneInstance):string => {
+ if (zoneInstance.isAlreadyAssigned(nodeId)) {
+ if (zoneInstance.type == ZoneInstanceType.POLICY) {
+ return CanvasHandleTypes.TAGGED_POLICY;
+ } else {
+ return CanvasHandleTypes.TAGGED_GROUP;
+ }
+ } else {
+ return CanvasHandleTypes.TAG_AVAILABLE;
+ }
+ };
}
CompositionGraphZoneUtils.$inject = [
- 'DynamicComponentService'
+ 'DynamicComponentService',
+ 'PoliciesServiceNg2',
+ 'GroupsServiceNg2'
]; \ No newline at end of file
diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/match-capability-requierment-utils.ts b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/match-capability-requierment-utils.ts
index 3a05ce901f..eac907a9b2 100644
--- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/match-capability-requierment-utils.ts
+++ b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/match-capability-requierment-utils.ts
@@ -74,19 +74,25 @@ export class MatchCapabilitiesRequirementsUtils {
}
private static isRequirementFulfilled(fromNodeId:string, requirement:any, links:Array<CompositionCiLinkBase>):boolean {
- return _.some(links, {
+ if(requirement.maxOccurrences === 'UNBOUNDED'){
+ return false;
+ }
+ let linksWithThisReq:Array<CompositionCiLinkBase> = _.filter(links, {
'relation': {
'fromNode': fromNodeId,
'relationships': [{
- 'requirementOwnerId': requirement.ownerId,
- 'requirement': requirement.name,
- 'relationship': {
- 'type': requirement.relationship
+ 'relation':{
+ 'requirementOwnerId': requirement.ownerId,
+ 'requirement': requirement.name,
+ 'relationship': {
+ 'type': requirement.capability
+ }
+
}
- }
- ]
+ }]
}
});
+ return linksWithThisReq.length == requirement.maxOccurrences;
};
private static isMatch(requirement:Requirement, capability:Capability):boolean {
diff --git a/catalog-ui/src/app/directives/graphs-v2/deployment-graph/deployment-graph.directive.ts b/catalog-ui/src/app/directives/graphs-v2/deployment-graph/deployment-graph.directive.ts
index c542e9fc95..f335ea02d9 100644
--- a/catalog-ui/src/app/directives/graphs-v2/deployment-graph/deployment-graph.directive.ts
+++ b/catalog-ui/src/app/directives/graphs-v2/deployment-graph/deployment-graph.directive.ts
@@ -54,7 +54,7 @@ export class DeploymentGraph implements ng.IDirective {
link = (scope: IDeploymentGraphScope, el: JQuery) => {
if (scope.component.isResource()) {
- if (scope.component.componentInstances && scope.component.componentInstancesRelations && scope.component.groups) {
+ if (scope.component.componentInstances && scope.component.componentInstancesRelations && scope.component.modules) {
this.loadGraph(scope, el);
} else {
this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_DEPLOYMENT_GRAPH_DATA_LOADED, () => {
@@ -65,8 +65,8 @@ export class DeploymentGraph implements ng.IDirective {
};
public initGraphNodes = (cy: Cy.Instance, component: Component): void => {
- if (component.groups) { // Init module nodes
- _.each(component.groups, (groupModule: Module) => {
+ if (component.modules) { // Init module nodes
+ _.each(component.modules, (groupModule: Module) => {
let moduleNode = this.NodesFactory.createModuleNode(groupModule);
this.commonGraphUtils.addNodeToGraph(cy, moduleNode);
@@ -74,7 +74,7 @@ export class DeploymentGraph implements ng.IDirective {
}
_.each(component.componentInstances, (instance: ComponentInstance) => { // Init component instance nodes
let componentInstanceNode = this.NodesFactory.createNode(instance);
- componentInstanceNode.parent = this.deploymentGraphGeneralUtils.findInstanceModule(component.groups, instance.uniqueId);
+ componentInstanceNode.parent = this.deploymentGraphGeneralUtils.findInstanceModule(component.modules, instance.uniqueId);
if (componentInstanceNode.parent) { // we are not drawing instances that are not a part of a module
this.commonGraphUtils.addComponentInstanceNodeToGraph(cy, componentInstanceNode);
}
diff --git a/catalog-ui/src/app/directives/graphs-v2/deployment-graph/deployment-utils/deployment-graph-general-utils.ts b/catalog-ui/src/app/directives/graphs-v2/deployment-graph/deployment-utils/deployment-graph-general-utils.ts
index 3a90115179..ebd1f5b205 100644
--- a/catalog-ui/src/app/directives/graphs-v2/deployment-graph/deployment-utils/deployment-graph-general-utils.ts
+++ b/catalog-ui/src/app/directives/graphs-v2/deployment-graph/deployment-utils/deployment-graph-general-utils.ts
@@ -32,7 +32,7 @@ export class DeploymentGraphGeneralUtils {
public findInstanceModule = (groupsArray:Array<Module>, componentInstanceId:string):string => {
let parentGroup:Module = _.find(groupsArray, (group:Module) => {
- return _.find(group.members, (member) => {
+ return _.find((<any>Object).values(group.members), (member: string) => {
return member === componentInstanceId;
});
});
diff --git a/catalog-ui/src/app/directives/graphs-v2/image-creator/image-creator.service.ts b/catalog-ui/src/app/directives/graphs-v2/image-creator/image-creator.service.ts
index 6d6291d900..68c9e9a459 100644
--- a/catalog-ui/src/app/directives/graphs-v2/image-creator/image-creator.service.ts
+++ b/catalog-ui/src/app/directives/graphs-v2/image-creator/image-creator.service.ts
@@ -18,6 +18,14 @@
* ============LICENSE_END=========================================================
*/
+export interface ICanvasImage {
+ src: string;
+ width: number
+ height: number;
+ x: number;
+ y: number;
+}
+
'use strict';
export class ImageCreatorService {
static '$inject' = ['$q'];
@@ -31,36 +39,48 @@ export class ImageCreatorService {
body.appendChild(this._canvas);
}
- getImageBase64(imageBaseUri:string, imageLayerUri:string, nodeWidth:number, canvasWidth:number, handleSize:number):ng.IPromise<string> {
- let deferred = this.$q.defer();
- let imageBase = new Image();
- let imageLayer = new Image();
+ /**
+ * Create an image composed of different image layers
+ * @param canvasImages
+ * @param canvasWidth
+ * @param canvasHeight
+ * returns a PROMISE
+ */
+ getMultiLayerBase64Image(canvasImages: ICanvasImage[], canvasWidth?:number, canvasHeight?:number):ng.IPromise<string> {
+ const deferred = this.$q.defer<string>();
+
+ 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;
- let onImageLoaded = () => {
+ const onImageLoaded = () => {
imagesLoaded++;
-
- if (imagesLoaded < 2) {
+ if(imagesLoaded < canvasImages.length){
return;
}
this._canvas.setAttribute('width', canvasWidth.toString());
- this._canvas.setAttribute('height', canvasWidth.toString());
-
- let canvasCtx = this._canvas.getContext('2d');
+ this._canvas.setAttribute('height', canvasHeight.toString());
+ const canvasCtx = this._canvas.getContext('2d');
canvasCtx.clearRect(0, 0, this._canvas.width, this._canvas.height);
-
- //Note: params below are: image, x to start drawing at, y to start drawing at, num of x pixels to draw, num of y pixels to draw
- canvasCtx.drawImage(imageBase, 0, canvasWidth - nodeWidth, nodeWidth, nodeWidth); //Draw the node: When nodeWidth == canvasWidth, we'll start at point 0,0. Otherwise, x starts at 0 (but will end before end of canvas) and y starts low enough that node img ends at bottom of canvas.
- canvasCtx.drawImage(imageLayer, canvasWidth - handleSize, 0, handleSize, handleSize); //Draw the icon: icon should be drawn in top right corner
-
+ images.forEach((image, index) => {
+ const canvasImage = canvasImages[index];
+ canvasCtx.drawImage(image, canvasImage.x, canvasImage.y, canvasImage.width, canvasImage.height);
+ });
let base64Image = this._canvas.toDataURL();
deferred.resolve(base64Image);
};
-
- imageBase.onload = onImageLoaded;
- imageLayer.onload = onImageLoaded;
- imageBase.src = imageBaseUri;
- imageLayer.src = imageLayerUri;
-
+ canvasImages.forEach(canvasImage => {
+ let image = new Image();
+ image.onload = onImageLoaded;
+ image.src = canvasImage.src;
+ images.push(image);
+ });
return deferred.promise;
}
}
diff --git a/catalog-ui/src/app/directives/graphs-v2/palette/palette.directive.ts b/catalog-ui/src/app/directives/graphs-v2/palette/palette.directive.ts
index 9b9235248e..ebc52c241b 100644
--- a/catalog-ui/src/app/directives/graphs-v2/palette/palette.directive.ts
+++ b/catalog-ui/src/app/directives/graphs-v2/palette/palette.directive.ts
@@ -27,9 +27,10 @@ import {LeftPaletteLoaderService} from "../../../services/components/utils/compo
import {Resource} from "app/models/components/resource";
import {ComponentType} from "app/utils/constants";
import {LeftPaletteMetadataTypes} from "../../../models/components/displayComponent";
+import { IDirectiveLinkFn, IScope } from "angular";
-interface IPaletteScope {
+interface IPaletteScope extends IScope{
components:Array<LeftPaletteComponent>;
currentComponent:Component;
model:any;
@@ -88,7 +89,8 @@ export class Palette implements ng.IDirective {
restrict = 'E';
template = require('./palette.html');
- link = (scope:IPaletteScope, el:JQuery) => {
+ link:IDirectiveLinkFn = (scope:IPaletteScope, el:JQuery) => {
+ this.LeftPaletteLoaderService.loadLeftPanel(scope.currentComponent);
this.nodeHtmlSubstitute = $('<div class="node-substitute"><span></span><img /></div>');
el.append(this.nodeHtmlSubstitute);
this.registerEventListenerForLeftPalette(scope);
@@ -277,7 +279,7 @@ export class Palette implements ng.IDirective {
let filteredResources = [];
angular.forEach(subcategory, function (component:LeftPaletteComponent) {
- let resourceFilterTerm:string = component.searchFilterTerms;
+ let resourceFilterTerm:string = component.searchFilterTerms.toLowerCase();
if (resourceFilterTerm.indexOf(searchText.toLowerCase()) >= 0) {
filteredResources.push(component);
}
diff --git a/catalog-ui/src/app/directives/graphs-v2/palette/palette.html b/catalog-ui/src/app/directives/graphs-v2/palette/palette.html
index a8139e3140..ee0c604ea9 100644
--- a/catalog-ui/src/app/directives/graphs-v2/palette/palette.html
+++ b/catalog-ui/src/app/directives/graphs-v2/palette/palette.html
@@ -26,7 +26,7 @@
data-ng-class="{'default-pointer': isViewOnly}"
data-ng-mouseover="!isViewOnly && onMouseOver(component, $event.currentTarget)"
data-ng-mouseleave="!isViewOnly && onMouseOut(component)"
- data-drag="!isViewOnly"
+ data-drag="!isViewOnly && component.isDraggable"
data-jqyoui-options="{revert: 'invalid', helper:setElementTemplate, appendTo:'body', cursorAt: {left:38, top: 38}, cursor:'move'}"
jqyoui-draggable="{index:{{$index}},animate:true,onStart:'dragStartCallback(component)',onStop:'dragStopCallback()', onDrag:'onDragCallback()'}"
data-ng-repeat="component in components | orderBy: 'displayName' track by $index"
diff --git a/catalog-ui/src/app/directives/graphs-v2/relation-menu/relation-menu.html b/catalog-ui/src/app/directives/graphs-v2/relation-menu/relation-menu.html
deleted file mode 100644
index e1cdf499a0..0000000000
--- a/catalog-ui/src/app/directives/graphs-v2/relation-menu/relation-menu.html
+++ /dev/null
@@ -1,63 +0,0 @@
-<div class="link-menu-open" data-tests-id="link-menu-open" data-ng-show="isLinkMenuOpen" ng-style="{left: connectRelationModel.menuPosition.x, top: connectRelationModel.menuPosition.y}" clicked-outside="{onClickedOutside: 'hideRelationMatch()', clickedOutsideEnable: 'isLinkMenuOpen'}" >
- <h4 sdc-smart-tooltip>{{relationMenuDirectiveObj.leftSideLink.componentInstance.name | resourceName}}</h4>
- <h4 sdc-smart-tooltip>{{relationMenuDirectiveObj.rightSideLink.componentInstance.name | resourceName}}</h4>
-
- <p>Select one of the options below to connect</p>
-
- <perfect-scrollbar scroll-y-margin-offset="0" include-padding="true" class="scrollbar-container">
- <div class="inner-title" data-ng-show="hasMatchesToShow(connectRelationModel.leftSideLink.requirements, connectRelationModel.rightSideLink.selectedMatch)">Requirements</div>
- <div class="link-item" data-tests-id="link-item-requirements" data-ng-repeat="(req ,matchArr) in connectRelationModel.leftSideLink.requirements"
- data-ng-click="connectRelationModel.leftSideLink.selectMatchArr(matchArr); updateSelectionText()"
- data-ng-show="showMatch(connectRelationModel.rightSideLink.selectedMatch, matchArr)"
- data-ng-class="{ 'selected': connectRelationModel.leftSideLink.selectedMatch === matchArr}">
- <div sdc-smart-tooltip>{{matchArr[0].requirement.getFullTitle()}}</div>
- </div>
-
- <div class="inner-title" data-ng-show="hasMatchesToShow(connectRelationModel.leftSideLink.capabilities, connectRelationModel.rightSideLink.selectedMatch)">Capabilities</div>
- <div class="link-item" data-tests-id="link-item-capabilities" data-ng-repeat="(cap, matchArr) in connectRelationModel.leftSideLink.capabilities"
- data-ng-click="connectRelationModel.leftSideLink.selectMatchArr(matchArr); updateSelectionText()"
- data-ng-show="showMatch(connectRelationModel.rightSideLink.selectedMatch, matchArr)"
- data-ng-class="{ 'selected': connectRelationModel.leftSideLink.selectedMatch === matchArr}">
- <div sdc-smart-tooltip>{{matchArr[0].capability.getFullTitle()}}</div>
- </div>
- </perfect-scrollbar>
-
- <perfect-scrollbar scroll-y-margin-offset="0" include-padding="true" class="scrollbar-container">
- <div class="inner-title" data-ng-show="hasMatchesToShow(connectRelationModel.rightSideLink.requirements, connectRelationModel.leftSideLink.selectedMatch)">Requirements</div>
- <div class="link-item" data-tests-id="link-item-requirements" data-ng-repeat="(req, matchArr) in connectRelationModel.rightSideLink.requirements"
- data-ng-click="connectRelationModel.rightSideLink.selectMatchArr(matchArr); updateSelectionText()"
- data-ng-show="showMatch(connectRelationModel.leftSideLink.selectedMatch, matchArr)"
- data-ng-class="{ 'selected': connectRelationModel.rightSideLink.selectedMatch === matchArr}">
- <div sdc-smart-tooltip>{{matchArr[0].secondRequirement ? matchArr[0].secondRequirement.getFullTitle() : matchArr[0].requirement.getFullTitle()}}</div>
- </div>
-
- <div class="inner-title" data-ng-show="hasMatchesToShow(connectRelationModel.rightSideLink.capabilities, connectRelationModel.leftSideLink.selectedMatch)">Capabilities</div>
- <div class="link-item" data-tests-id="link-item-capabilities" data-ng-repeat="(cap, matchArr) in connectRelationModel.rightSideLink.capabilities"
- data-ng-click="connectRelationModel.rightSideLink.selectMatchArr(matchArr); updateSelectionText()"
- data-ng-show="showMatch(connectRelationModel.leftSideLink.selectedMatch, matchArr)"
- data-ng-class="{ 'selected': connectRelationModel.rightSideLink.selectedMatch === matchArr}">
- <div sdc-smart-tooltip>{{matchArr[0].capability.getFullTitle()}}</div>
- </div>
- </perfect-scrollbar>
-
- <div class="vl-type" data-ng-class="{'disabled': !connectRelationModel.leftSideLink.selectedMatch[0].secondRequirement || !connectRelationModel.rightSideLink.selectedMatch[0].secondRequirement}">
- <sdc-radio-button sdc-model="relationMenuDirectiveObj.vlType" value="ptp"
- disabled="!relationMenuDirectiveObj.leftSideLink.selectedMatch[0].secondRequirement || !relationMenuDirectiveObj.rightSideLink.selectedMatch[0].secondRequirement || !relationMenuDirectiveObj.p2pVL"
- text="Point to point" elem-id="radioPTP" elem-name="vlType"></sdc-radio-button>
-
- <sdc-radio-button sdc-model="relationMenuDirectiveObj.vlType" value="mptmp"
- disabled="!relationMenuDirectiveObj.leftSideLink.selectedMatch[0].secondRequirement || !relationMenuDirectiveObj.rightSideLink.selectedMatch[0].secondRequirement || !relationMenuDirectiveObj.mp2mpVL"
- text="Multi point" elem-id="radioMPTMP" elem-name="vlType"></sdc-radio-button>
-
- <span class="sprite-new info-icon" tooltips tooltip-content="You are required to choose the type of the Virtual Link."></span>
- </div>
-
- <div class="result" sdc-smart-tooltip>&#8203;{{relationMenuDirectiveObj.selectionText}}
-
- </div>
-
- <button class="tlv-btn grey" data-tests-id="link-menu-button-cancel" data-ng-click="hideRelationMatch()">Cancel</button>
- <button class="tlv-btn blue" data-tests-id="link-menu-button-connect" data-ng-disabled="!connectRelationModel.leftSideLink.selectedMatch || !connectRelationModel.rightSideLink.selectedMatch ||
- (connectRelationModel.leftSideLink.selectedMatch[0].secondRequirement && !connectRelationModel.vlType)"
- data-ng-click="saveRelation()">Connect</button>
-</div>
diff --git a/catalog-ui/src/app/directives/graphs-v2/relation-menu/relation-menu.less b/catalog-ui/src/app/directives/graphs-v2/relation-menu/relation-menu.less
deleted file mode 100644
index dea814dbec..0000000000
--- a/catalog-ui/src/app/directives/graphs-v2/relation-menu/relation-menu.less
+++ /dev/null
@@ -1,118 +0,0 @@
-.link-menu-open {
- display: block !important;
- color: @main_color_m;
- font-size: 14px;
- position: absolute;
- z-index: 99999;
- border-radius: 2px;
- background-color: #ffffff;
- box-shadow: 0px 0px 6px 0px rgba(0, 0, 0, 0.5);
- width: 460px;
- height: 418px;
-
- h4 {
- width: 50%;
- float: left;
- background-color: @tlv_color_u;
- font-size: 14px;
- font-weight: bold;
- line-height: 36px;
- margin: 0;
- padding: 0 15px;
-
- & + h4 {
- border-left: #d8d8d8 1px solid;
- }
- }
- p {
- clear: both;
- text-indent: 15px;
- border-bottom: #d8d8d8 1px solid;
- line-height: 34px;
- margin: 0;
- color: @func_color_s;
- }
-
- .scrollbar-container {
- height: 232px;
- width: 50%;
- float: left;
- margin-bottom: 5px;
- .perfect-scrollbar;
-
- & + .scrollbar-container {
- border-left: #d8d8d8 1px solid;
- }
-
- .inner-title {
- width: 189px;
- margin: 5px auto 3px auto;
- //text-indent: 10px;
- color: @func_color_s;
- text-transform: uppercase;
- font-weight: bold;
-
- //&:not(:first-child) {
- // margin-top: 10px;
- //}
- }
-
- .link-item {
- padding: 0 10px;
- line-height: 23px;
- height: 23px;
- text-indent: 5px;
- .hand;
-
- &.selected {
- background-color: @tlv_color_v;
- }
- }
- }
-
- .vl-type {
- height: 33px;
- border-top: #d8d8d8 solid 1px;
- clear: both;
- padding: 0 10px;
- line-height: 32px;
- color: @main_color_m;
-
- &.disabled {
- background-color: #f2f2f2;
- color: @color_m;
- }
- .info-icon {
- float:right;
- margin-top: 9px;
- }
- .tlv-radio {
- margin-right: 10px;
- }
- }
-
- .result {
- background-color: @main_color_m;
- line-height: 29px;
- color: #ffffff;
- padding: 0 15px;
- }
-
- button {
- float: right;
- margin-top: 9px;
- margin-right: 10px;
- }
-}
-.link-menu-item {
- cursor: pointer;
- line-height: 24px;
- padding: 0 10px;
- &:hover {
- color: @color_a;
- }
-}
-.link-menu::before {
- right: inherit !important;
- left: 50px;
-} \ No newline at end of file
diff --git a/catalog-ui/src/app/directives/graphs-v2/relation-menu/relation-menu.ts b/catalog-ui/src/app/directives/graphs-v2/relation-menu/relation-menu.ts
deleted file mode 100644
index 78a269ead1..0000000000
--- a/catalog-ui/src/app/directives/graphs-v2/relation-menu/relation-menu.ts
+++ /dev/null
@@ -1,104 +0,0 @@
-/*-
- * ============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 * as _ from "lodash";
-import {Match, ConnectRelationModel} from "app/models";
-import {Component} from "../../../models/components/component";
-
-export interface IRelationMenuScope extends ng.IScope {
- relationMenuDirectiveObj:ConnectRelationModel;
- createRelation:Function;
- isLinkMenuOpen:boolean;
- hideRelationMatch:Function;
- cancel:Function;
-
- saveRelation();
- showMatch(arr1:Array<Match>, arr2:Array<Match>):boolean;
- hasMatchesToShow(matchesObj:Match, selectedMatch:Array<Match>);
- updateSelectionText():void;
-
-}
-
-
-export class RelationMenuDirective implements ng.IDirective {
-
- constructor(private $filter:ng.IFilterService) {
- }
-
- scope = {
- relationMenuDirectiveObj: '=',
- isLinkMenuOpen: '=',
- createRelation: '&',
- cancel: '&'
- };
-
- restrict = 'E';
- replace = true;
- template = ():string => {
- return require('./relation-menu.html');
- };
-
- link = (scope:IRelationMenuScope, element:JQuery, $attr:ng.IAttributes) => {
-
- scope.saveRelation = ():void=> {
- let chosenMatches:Array<any> = _.intersection(scope.relationMenuDirectiveObj.rightSideLink.selectedMatch, scope.relationMenuDirectiveObj.leftSideLink.selectedMatch);
- let chosenMatch:Match = chosenMatches[0];
- scope.createRelation()(chosenMatch);
- };
-
-
- scope.hideRelationMatch = () => {
- scope.isLinkMenuOpen = false;
- scope.cancel();
- };
-
- //to show options in link menu
- scope.showMatch = (arr1:Array<Match>, arr2:Array<Match>):boolean => {
- return !arr1 || !arr2 || _.intersection(arr1, arr2).length > 0;
- };
-
- //to show requirements/capabilities title
- scope.hasMatchesToShow = (matchesObj:Match, selectedMatch:Array<Match>):boolean => {
- let result:boolean = false;
- _.forEach(matchesObj, (matchesArr:Array<Match>) => {
- if (!result) {
- result = scope.showMatch(matchesArr, selectedMatch);
- }
- });
- return result;
- };
-
-
- scope.updateSelectionText = ():void => {
- let left:string = scope.relationMenuDirectiveObj.leftSideLink.selectedMatch ? this.$filter('resourceName')(scope.relationMenuDirectiveObj.leftSideLink.selectedMatch[0].getDisplayText('left')) : '';
- let both:string = scope.relationMenuDirectiveObj.leftSideLink.selectedMatch && scope.relationMenuDirectiveObj.rightSideLink.selectedMatch ? ' - ' +
- this.$filter('resourceName')(scope.relationMenuDirectiveObj.leftSideLink.selectedMatch[0].requirement.relationship) + ' - ' : '';
- let right:string = scope.relationMenuDirectiveObj.rightSideLink.selectedMatch ? this.$filter('resourceName')(scope.relationMenuDirectiveObj.rightSideLink.selectedMatch[0].getDisplayText('right')) : '';
- scope.relationMenuDirectiveObj.selectionText = left + both + right;
- };
-
-
- }
- public static factory = ($filter:ng.IFilterService)=> {
- return new RelationMenuDirective($filter);
- };
-}
-
-RelationMenuDirective.factory.$inject = ['$filter'];