summaryrefslogtreecommitdiffstats
path: root/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-links-utils.ts
diff options
context:
space:
mode:
Diffstat (limited to 'catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-links-utils.ts')
-rw-r--r--catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-links-utils.ts271
1 files changed, 271 insertions, 0 deletions
diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-links-utils.ts b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-links-utils.ts
new file mode 100644
index 0000000000..314c761edd
--- /dev/null
+++ b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-links-utils.ts
@@ -0,0 +1,271 @@
+/**
+ * Created by obarda on 6/28/2016.
+ */
+import {GraphUIObjects, ComponentInstanceFactory, ResourceType} from "app/utils";
+import {LeftPaletteLoaderService, LoaderService} from "app/services";
+import {
+ NodeUcpe,
+ CompositionCiNodeVf,
+ MatchReqToCapability,
+ MatchBase,
+ MatchReqToReq,
+ ComponentInstance,
+ CompositionCiNodeBase,
+ RelationshipModel,
+ RelationMenuDirectiveObj,
+ CapabilitiesGroup,
+ LinksFactory,
+ NodesFactory,
+ RequirementsGroup,
+ Component,
+ Relationship,
+ Capability,
+ LinkMenu,
+ Point,
+ CompositionCiLinkBase
+} from "app/models";
+import {CommonGraphUtils} from "../../common/common-graph-utils";
+import {CompositionGraphGeneralUtils} from "./composition-graph-general-utils";
+import {MatchCapabilitiesRequirementsUtils} from "./match-capability-requierment-utils";
+
+export class CompositionGraphLinkUtils {
+
+ constructor(private linksFactory:LinksFactory,
+ private loaderService:LoaderService,
+ private generalGraphUtils:CompositionGraphGeneralUtils,
+ private commonGraphUtils:CommonGraphUtils,
+ private matchCapabilitiesRequirementsUtils:MatchCapabilitiesRequirementsUtils) {
+ }
+
+
+ /**
+ * Delete the link on server and then remove it from graph
+ * @param component
+ * @param releaseLoading - true/false release the loader when finished
+ * @param link - the link to delete
+ */
+ public deleteLink = (cy:Cy.Instance, component:Component, releaseLoading:boolean, link:Cy.CollectionEdges) => {
+
+ this.loaderService.showLoader('composition-graph');
+ let onSuccessDeleteRelation = (response) => {
+ cy.remove(link);
+ };
+
+ if (!releaseLoading) {
+ this.generalGraphUtils.getGraphUtilsServerUpdateQueue().addBlockingUIAction(
+ () => component.deleteRelation(link.data().relation).then(onSuccessDeleteRelation)
+ );
+ } else {
+ this.generalGraphUtils.getGraphUtilsServerUpdateQueue().addBlockingUIActionWithReleaseCallback(
+ () => component.deleteRelation(link.data().relation).then(onSuccessDeleteRelation),
+ () => this.loaderService.hideLoader('composition-graph'));
+ }
+ };
+
+ /**
+ * create the link on server and than draw it on graph
+ * @param link - the link to create
+ * @param cy
+ * @param component
+ */
+ public createLink = (link:CompositionCiLinkBase, cy:Cy.Instance, component:Component):void => {
+
+ this.loaderService.showLoader('composition-graph');
+
+ let onSuccess:(response:RelationshipModel) => void = (relation:RelationshipModel) => {
+ link.setRelation(relation);
+ this.commonGraphUtils.insertLinkToGraph(cy, link);
+ };
+
+ link.updateLinkDirection();
+
+ this.generalGraphUtils.getGraphUtilsServerUpdateQueue().addBlockingUIActionWithReleaseCallback(
+ () => component.createRelation(link.relation).then(onSuccess),
+ () => this.loaderService.hideLoader('composition-graph')
+ );
+ };
+
+ private createSimpleLink = (match:MatchReqToCapability, cy:Cy.Instance, component:Component):void => {
+ let newRelation:RelationshipModel = match.matchToRelationModel();
+ let linkObg:CompositionCiLinkBase = this.linksFactory.createGraphLink(cy, newRelation, newRelation.relationships[0]);
+ this.createLink(linkObg, cy, component);
+ };
+
+ public createLinkFromMenu = (cy:Cy.Instance, chosenMatch:MatchBase, component:Component):void => {
+
+ if (chosenMatch) {
+ if (chosenMatch && chosenMatch instanceof MatchReqToCapability) {
+ this.createSimpleLink(chosenMatch, cy, component);
+ }
+ }
+ };
+
+
+ /**
+ * Filters the matches for UCPE links so that shown requirements and capabilites are only related to the selected ucpe-cp
+ * @param fromNode
+ * @param toNode
+ * @param matchesArray
+ * @returns {Array<MatchBase>}
+ */
+ public filterUcpeLinks(fromNode:CompositionCiNodeBase, toNode:CompositionCiNodeBase, matchesArray:Array<MatchBase>):any {
+
+ let matchLink:Array<MatchBase>;
+
+ if (fromNode.isUcpePart) {
+ matchLink = _.filter(matchesArray, (match:MatchBase) => {
+ return match.isOwner(fromNode.id);
+ });
+ }
+
+ if (toNode.isUcpePart) {
+ matchLink = _.filter(matchesArray, (match:MatchBase) => {
+ return match.isOwner(toNode.id);
+ });
+ }
+ return matchLink ? matchLink : matchesArray;
+ }
+
+
+ /**
+ * open the connect link menu if the link drawn is valid - match requirements & capabilities
+ * @param cy
+ * @param fromNode
+ * @param toNode
+ * @returns {any}
+ */
+ public onLinkDrawn(cy:Cy.Instance, fromNode:Cy.CollectionFirstNode, toNode:Cy.CollectionFirstNode):RelationMenuDirectiveObj {
+
+ if (!this.commonGraphUtils.nodeLocationsCompatible(cy, fromNode, toNode)) {
+ return null;
+ }
+ let linkModel:Array<CompositionCiLinkBase> = this.generalGraphUtils.getAllCompositionCiLinks(cy);
+
+ let possibleRelations:Array<MatchBase> = this.matchCapabilitiesRequirementsUtils.getMatchedRequirementsCapabilities(fromNode.data().componentInstance,
+ toNode.data().componentInstance, linkModel);
+
+ //filter relations found to limit to specific ucpe-cp
+ possibleRelations = this.filterUcpeLinks(fromNode.data(), toNode.data(), possibleRelations);
+
+ //if found possibleRelations between the nodes we create relation menu directive and open the link menu
+ if (possibleRelations.length) {
+ let menuPosition = this.generalGraphUtils.getLinkMenuPosition(cy, toNode.renderedPoint());
+ return new RelationMenuDirectiveObj(fromNode.data(), toNode.data(), menuPosition, possibleRelations);
+ }
+ return null;
+ };
+
+
+ /**
+ * when we drag instance in to UCPE or out of UCPE - get all links we need to delete - one node in ucpe and one node outside of ucpe
+ * @param node - the node we dragged into or out of the ucpe
+ */
+ public deleteLinksWhenNodeMovedFromOrToUCPE(component:Component, cy:Cy.Instance, nodeMoved:Cy.CollectionNodes, vlsPendingDeletion?:Cy.CollectionNodes):void {
+
+
+ let linksToDelete:Cy.CollectionElements = cy.collection();
+ _.forEach(nodeMoved.neighborhood('node'), (neighborNode)=> {
+
+ if (neighborNode.data().isUcpePart) { //existing connections to ucpe or ucpe-cp - we want to delete even though nodeLocationsCompatible will technically return true
+ linksToDelete = linksToDelete.add(nodeMoved.edgesWith(neighborNode)); // This will delete the ucpe-host-link, or the vl-ucpe-link if nodeMoved is vl
+ } else if (!this.commonGraphUtils.nodeLocationsCompatible(cy, nodeMoved, neighborNode)) { //connection to regular node or vl - check if locations are compatible
+ if (!vlsPendingDeletion || !vlsPendingDeletion.intersect(neighborNode).length) { //Check if this is a link to a VL pending deletion, to prevent double deletion of between the node moved and vl
+ linksToDelete = linksToDelete.add(nodeMoved.edgesWith(neighborNode));
+ }
+ }
+ });
+
+ linksToDelete.each((i, link)=> {
+ this.deleteLink(cy, component, false, link);
+ });
+
+ };
+
+ /**
+ * Creates a hostedOn link between a VF and UCPE
+ * @param component
+ * @param cy
+ * @param ucpeNode
+ * @param vfNode
+ */
+ public createVfToUcpeLink = (component:Component, cy:Cy.Instance, ucpeNode:NodeUcpe, vfNode:CompositionCiNodeVf):void => {
+ let hostedOnMatch:MatchReqToCapability = this.generalGraphUtils.canBeHostedOn(cy, ucpeNode.componentInstance, vfNode.componentInstance);
+ /* create relation */
+ let newRelation = new RelationshipModel();
+ newRelation.fromNode = ucpeNode.id;
+ newRelation.toNode = vfNode.id;
+
+ let link:CompositionCiLinkBase = this.linksFactory.createUcpeHostLink(newRelation);
+ link.relation = hostedOnMatch.matchToRelationModel();
+ this.createLink(link, cy, component);
+ };
+
+
+ /**
+ * Handles click event on links.
+ * If one edge selected: do nothing.
+ /*Two edges selected - always select all
+ /* Three or more edges: first click - select all, secondary click - select single.
+ * @param cy
+ * @param event
+ */
+ public handleLinkClick(cy:Cy.Instance, event:Cy.EventObject) {
+ if (cy.$('edge:selected').length > 2 && event.cyTarget[0].selected()) {
+ cy.$(':selected').unselect();
+ } else {
+
+ let vl:Cy.CollectionNodes = event.cyTarget[0].target('.vl-node');
+ let connectedEdges:Cy.CollectionEdges = vl.connectedEdges();
+ if (vl.length && connectedEdges.length > 1) {
+
+ setTimeout(() => {
+ vl.select();
+ connectedEdges.select();
+ }, 0);
+ }
+ }
+
+ }
+
+
+ /**
+ * Calculates the position for the menu that modifies an existing link
+ * @param event
+ * @param elementWidth
+ * @param elementHeight
+ * @returns {Point}
+ */
+ public calculateLinkMenuPosition(event, elementWidth, elementHeight):Point {
+ let point:Point = new Point(event.originalEvent.x, event.originalEvent.y);
+ if (event.originalEvent.view.screen.height - elementHeight < point.y) {
+ point.y = event.originalEvent.view.screen.height - elementHeight;
+ }
+ if (event.originalEvent.view.screen.width - elementWidth < point.x) {
+ point.x = event.originalEvent.view.screen.width - elementWidth;
+ }
+ return point;
+ };
+
+
+ /**
+ * Gets the menu that is displayed when you click an existing link.
+ * @param link
+ * @param event
+ * @returns {LinkMenu}
+ */
+ public getModifyLinkMenu(link:Cy.CollectionFirstEdge, event:Cy.EventObject):LinkMenu {
+ let point:Point = this.calculateLinkMenuPosition(event, GraphUIObjects.MENU_LINK_VL_WIDTH_OFFSET, GraphUIObjects.MENU_LINK_VL_HEIGHT_OFFSET);
+ let menu:LinkMenu = new LinkMenu(point, true, link);
+ return menu;
+ };
+
+}
+
+
+CompositionGraphLinkUtils.$inject = [
+ 'LinksFactory',
+ 'LoaderService',
+ 'CompositionGraphGeneralUtils',
+ 'CommonGraphUtils',
+ 'MatchCapabilitiesRequirementsUtils'
+];