summaryrefslogtreecommitdiffstats
path: root/catalog-ui/src/app/directives/graphs-v2/composition-graph
diff options
context:
space:
mode:
Diffstat (limited to 'catalog-ui/src/app/directives/graphs-v2/composition-graph')
-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
8 files changed, 552 insertions, 230 deletions
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 {