diff options
Diffstat (limited to 'catalog-ui/src/app/directives')
24 files changed, 651 insertions, 240 deletions
diff --git a/catalog-ui/src/app/directives/capabilities-and-requirements/requirement/requirements-list-directive.ts b/catalog-ui/src/app/directives/capabilities-and-requirements/requirement/requirements-list-directive.ts index 14cafa98c4..cda2f9723e 100644 --- a/catalog-ui/src/app/directives/capabilities-and-requirements/requirement/requirements-list-directive.ts +++ b/catalog-ui/src/app/directives/capabilities-and-requirements/requirement/requirements-list-directive.ts @@ -28,6 +28,7 @@ * Created by obarda on 1/8/2017. */ 'use strict'; +import * as _ from "lodash"; import {RequirementsGroup, Component, Relationship, RelationshipModel} from "app/models"; export interface IRequirementsListScope extends ng.IScope { diff --git a/catalog-ui/src/app/directives/ecomp-header/ecomp-header.ts b/catalog-ui/src/app/directives/ecomp-header/ecomp-header.ts index f73c82a190..76bc1692b4 100644 --- a/catalog-ui/src/app/directives/ecomp-header/ecomp-header.ts +++ b/catalog-ui/src/app/directives/ecomp-header/ecomp-header.ts @@ -19,6 +19,7 @@ */ 'use strict'; +import * as _ from "lodash"; import {IAppConfigurtaion, User, IUser} from "app/models"; import {IUserProperties} from "../../models/user"; import {UserService} from "../../ng2/services/user.service"; diff --git a/catalog-ui/src/app/directives/export-json-to-excel/export-json-to-excel.ts b/catalog-ui/src/app/directives/export-json-to-excel/export-json-to-excel.ts index c4800fc0b4..25e7143e64 100644 --- a/catalog-ui/src/app/directives/export-json-to-excel/export-json-to-excel.ts +++ b/catalog-ui/src/app/directives/export-json-to-excel/export-json-to-excel.ts @@ -19,6 +19,7 @@ */ 'use strict'; +import * as _ from "lodash"; import {FileUtils} from "app/utils"; export interface IJsonExportExcelScope extends ng.IScope { diff --git a/catalog-ui/src/app/directives/file-opener/file-opener.ts b/catalog-ui/src/app/directives/file-opener/file-opener.ts index 4abd2573bb..8240d07958 100644 --- a/catalog-ui/src/app/directives/file-opener/file-opener.ts +++ b/catalog-ui/src/app/directives/file-opener/file-opener.ts @@ -19,6 +19,7 @@ */ 'use strict'; +import * as _ from "lodash"; export interface IFileOpenerScope extends ng.IScope { importFile:any; diff --git a/catalog-ui/src/app/directives/file-upload/file-upload.ts b/catalog-ui/src/app/directives/file-upload/file-upload.ts index 5a8fd87849..4902741927 100644 --- a/catalog-ui/src/app/directives/file-upload/file-upload.ts +++ b/catalog-ui/src/app/directives/file-upload/file-upload.ts @@ -22,6 +22,7 @@ * Created by obarda on 1/27/2016. */ 'use strict'; +import * as _ from "lodash"; import {IAppConfigurtaion} from "app/models"; export class FileUploadModel { diff --git a/catalog-ui/src/app/directives/graphs-v2/common/common-graph-utils.ts b/catalog-ui/src/app/directives/graphs-v2/common/common-graph-utils.ts index 2a7fd74e53..81d41509e7 100644 --- a/catalog-ui/src/app/directives/graphs-v2/common/common-graph-utils.ts +++ b/catalog-ui/src/app/directives/graphs-v2/common/common-graph-utils.ts @@ -18,8 +18,11 @@ * ============LICENSE_END========================================================= */ +import * as _ from "lodash"; import {CommonNodeBase, CompositionCiLinkBase, RelationshipModel, Relationship, CompositionCiNodeBase, NodesFactory, LinksFactory} from "app/models"; import {GraphUIObjects} from "app/utils"; +import {CompositionCiServicePathLink} from "app/models/graph/graph-links/composition-graph-links/composition-ci-service-path-link"; +import {Requirement, Capability} from "app/models"; /** * Created by obarda on 12/21/2016. */ @@ -56,11 +59,11 @@ export class CommonGraphUtils { classes: compositionGraphNode.classes }); - if(!node.data().isUcpe) { //ucpe should not have tooltip - this.initNodeTooltip(node); - } - return node; - }; + if(!node.data().isUcpe) { //ucpe should not have tooltip + this.initNodeTooltip(node); + } + return node; + }; /** * The function will create a component instance node by the componentInstance position. @@ -135,33 +138,30 @@ export class CommonGraphUtils { }; /** - * + * Returns relation source and target nodes. * @param nodes - all nodes in graph in order to find the edge connecting the two nodes * @param fromNodeId * @param toNodeId - * @returns {boolean} true/false if the edge is certified (from node and to node are certified) + * @returns [source, target] array of source node and target node. */ - public isRelationCertified(nodes:Cy.CollectionNodes, fromNodeId:string, toNodeId:string):boolean { - let resourceTemp = _.filter(nodes, function (node:Cy.CollectionFirst) { - return node.data().id === fromNodeId || node.data().id === toNodeId; - }); - let certified:boolean = true; - - _.forEach(resourceTemp, (item) => { - certified = certified && item.data().certified; - }); - - return certified; + public getRelationNodes(nodes:Cy.CollectionNodes, fromNodeId:string, toNodeId:string) { + return [ + _.find(nodes, (node:Cy.CollectionFirst) => node.data().id === fromNodeId), + _.find(nodes, (node:Cy.CollectionFirst) => node.data().id === toNodeId) + ]; } /** * Add link to graph - only draw the link * @param cy * @param link + * @param getRelationRequirementCapability */ - public insertLinkToGraph = (cy:Cy.Instance, link:CompositionCiLinkBase) => { - - if (!this.isRelationCertified(cy.nodes(), link.source, link.target)) { + public insertLinkToGraph = (cy:Cy.Instance, link:CompositionCiLinkBase, getRelationRequirementCapability:Function) => { + const relationNodes = this.getRelationNodes(cy.nodes(), link.source, link.target); + const sourceNode:CompositionCiNodeBase = relationNodes[0] && relationNodes[0].data(); + const targetNode:CompositionCiNodeBase = relationNodes[1] && relationNodes[1].data(); + if ((sourceNode && !sourceNode.certified) || (targetNode && !targetNode.certified)) { link.classes = 'not-certified-link'; } let linkElement = cy.add({ @@ -169,32 +169,85 @@ export class CommonGraphUtils { data: link, classes: link.classes }); - this.initLinkTooltip(linkElement, link); + const getLinkRequirementCapability = () => + getRelationRequirementCapability(link.relation.relationships[0], sourceNode.componentInstance, targetNode.componentInstance); + this.initLinkTooltip(linkElement, link.relation.relationships[0], getLinkRequirementCapability); }; /** + * Add service path link to graph - only draw the link + * @param cy + * @param link + */ + public insertServicePathLinkToGraph = (cy:Cy.Instance, link:CompositionCiServicePathLink) => { + let linkElement = cy.add({ + group: 'edges', + data: link, + classes: link.classes + }); + this.initServicePathTooltip(linkElement, link); + }; + + /** + * Returns function for the link tooltip content + * @param {Relationship} linkRelation + * @param {Requirement} requirement + * @param {Capability} capability + * @returns {() => string} + * @private + */ + private _getLinkTooltipContent(linkRelation:Relationship, requirement?:Requirement, capability?:Capability):string { + return '<div class="line">' + + '<span class="req-cap-label">R: </span>' + + '<span>' + (requirement ? requirement.getTitle() : linkRelation.relation.requirement) + '</span>' + + '</div>' + + '<div class="line">' + + '<div class="sprite-new link-tooltip-arrow"></div>' + + '<span class="req-cap-label">C: </span>' + + '<span>' + (capability ? capability.getTitle() : linkRelation.relation.capability) + '</span>' + + '</div>'; + } + + /** * This function will init qtip tooltip on the link - * @params linkElement - the link we want the tooltip to apply on, + * @param linkElement - the link we want the tooltip to apply on, + * @param link + * @param getLinkRequirementCapability * link - the link obj */ - public initLinkTooltip(linkElement:Cy.CollectionElements, link:CompositionCiLinkBase) { + public initLinkTooltip(linkElement:Cy.CollectionElements, link:Relationship, getLinkRequirementCapability:Function) { + const content = () => this._getLinkTooltipContent(link); // base tooltip content without owner names + const render = (event, api) => { + // on render (called once at first show), get the link requirement and capability and change to full tooltip content (with owner names) + getLinkRequirementCapability().then((linkReqCap) => { + const fullContent = () => this._getLinkTooltipContent(link, linkReqCap.requirement, linkReqCap.capability); + api.set('content.text', fullContent); + }); + }; + linkElement.qtip(this.prepareInitTooltipData({content, events: {render}})); + }; - let opts = { - content: function () { - return '<div class="line">' + - '<span class="req-cap-label">R: </span>' + - '<span>'+ link.relation.relationships[0].relation.requirement + '</span>' + - '</div>' + - '<div class="line">' + - '<div class="sprite-new link-tooltip-arrow"></div>' + - '<span class="req-cap-label">C: </span>' + - '<span>' + link.relation.relationships[0].relation.capability + '</span>' + - '</div>'; - }, + /** + * + * @param linkElement + * @param link + */ + public initServicePathTooltip(linkElement:Cy.CollectionElements, link:CompositionCiServicePathLink) { + let content = function () { + return '<div class="line">' + + '<div>'+link.pathName+'</div>' + + '</div>'; + }; + linkElement.qtip(this.prepareInitTooltipData({content})); + }; + + private prepareInitTooltipData(options?:Object) { + return _.merge({ position: { my: 'top center', at: 'bottom center', - adjust: {x:0, y:0} + adjust: {x:0, y:0}, + effect: false }, style: { classes: 'qtip-dark qtip-rounded qtip-custom link-qtip', @@ -208,24 +261,24 @@ export class CommonGraphUtils { delay: 1000 }, hide: {event: 'mouseout mousedown'}, - includeLabels: true - }; - - linkElement.qtip(opts); - }; + includeLabels: true, + events: {} + }, options); + } /** * go over the relations and draw links on the graph * @param cy * @param instancesRelations + * @param getRelationRequirementCapability - function to get requirement and capability of a relation */ - public initGraphLinks(cy:Cy.Instance, instancesRelations:Array<RelationshipModel>) { + public initGraphLinks(cy:Cy.Instance, instancesRelations:Array<RelationshipModel>, getRelationRequirementCapability:Function) { if (instancesRelations) { _.forEach(instancesRelations, (relationshipModel:RelationshipModel) => { _.forEach(relationshipModel.relationships, (relationship:Relationship) => { let linkToCreate = this.LinksFactory.createGraphLink(cy, relationshipModel, relationship); - this.insertLinkToGraph(cy, linkToCreate); + this.insertLinkToGraph(cy, linkToCreate, getRelationRequirementCapability); }); }); } @@ -297,8 +350,8 @@ export class CommonGraphUtils { public getCytoscapeNodePosition = (cy:Cy.Instance, event:IDragDropEvent):Cy.Position => { let targetOffset = $(event.target).offset(); - let x = event.pageX - targetOffset.left; - let y = event.pageY - targetOffset.top; + let x = (event.pageX - targetOffset.left) / cy.zoom(); + let y = (event.pageY - targetOffset.top) / cy.zoom(); return this.HTMLCoordsToCytoscapeCoords(cy.extent(), { x: x, @@ -316,14 +369,14 @@ export class CommonGraphUtils { return nodePosition; } - /** - * Generic function that can be used for any html elements overlaid on canvas - * Returns the html position of a node on canvas, including left palette and header offsets. Option to pass in additional offset to add to return position. - * @param node - * @param additionalOffset - * @returns {Cy.Position} - - public getNodePositionWithOffset = (node:Cy.CollectionFirstNode, additionalOffset?:Cy.Position): Cy.Position => { + /** + * Generic function that can be used for any html elements overlaid on canvas + * Returns the html position of a node on canvas, including left palette and header offsets. Option to pass in additional offset to add to return position. + * @param node + * @param additionalOffset + * @returns {Cy.Position} + + public getNodePositionWithOffset = (node:Cy.CollectionFirstNode, additionalOffset?:Cy.Position): Cy.Position => { if(!additionalOffset) additionalOffset = {x: 0, y:0}; let nodePosition = node.renderedPosition(); @@ -334,13 +387,13 @@ export class CommonGraphUtils { return posWithOffset; };*/ - /** - * return true/false if first node contains in second - this used in order to verify is node is entirely inside ucpe - * @param firstBox - * @param secondBox - * @returns {boolean} - */ - public isFirstBoxContainsInSecondBox(firstBox:Cy.BoundingBox, secondBox:Cy.BoundingBox) { + /** + * return true/false if first node contains in second - this used in order to verify is node is entirely inside ucpe + * @param firstBox + * @param secondBox + * @returns {boolean} + */ + public isFirstBoxContainsInSecondBox(firstBox:Cy.BoundingBox, secondBox:Cy.BoundingBox) { return firstBox.x1 > secondBox.x1 && firstBox.x2 < secondBox.x2 && firstBox.y1 > secondBox.y1 && firstBox.y2 < secondBox.y2; @@ -385,50 +438,50 @@ export class CommonGraphUtils { */ public nodeLocationsCompatible(cy:Cy.Instance, node1:Cy.CollectionFirstNode, node2:Cy.CollectionFirstNode) { - let ucpe = cy.nodes('[?isUcpe]'); - if(!ucpe.length){ return true; } - if(node1.data().isUcpePart || node2.data().isUcpePart) { return true; } + let ucpe = cy.nodes('[?isUcpe]'); + if(!ucpe.length){ return true; } + if(node1.data().isUcpePart || node2.data().isUcpePart) { return true; } return (this.isFirstBoxContainsInSecondBox(node1.boundingbox(), ucpe.boundingbox()) == this.isFirstBoxContainsInSecondBox(node2.boundingbox(), ucpe.boundingbox())); } - /** - * This function will init qtip tooltip on the node - * @param node - the node we want the tooltip to apply on - */ - public initNodeTooltip(node:Cy.CollectionNodes) { - - let opts = { - content: function () { - return this.data('name'); - }, - position: { - my: 'top center', - at: 'bottom center', - adjust: {x:0, y:-5} - }, - style: { - classes: 'qtip-dark qtip-rounded qtip-custom', - tip: { - width: 16, - height: 8 - } - }, - show: { - event: 'mouseover', - delay: 1000 - }, - hide: {event: 'mouseout mousedown'}, - includeLabels: true - }; - - if (node.data().isUcpePart){ //fix tooltip positioning for UCPE-cps - opts.position.adjust = {x:0, y:20}; - } - - node.qtip(opts); + /** + * This function will init qtip tooltip on the node + * @param node - the node we want the tooltip to apply on + */ + public initNodeTooltip(node:Cy.CollectionNodes) { + + let opts = { + content: function () { + return this.data('name'); + }, + position: { + my: 'top center', + at: 'bottom center', + adjust: {x:0, y:-5} + }, + style: { + classes: 'qtip-dark qtip-rounded qtip-custom', + tip: { + width: 16, + height: 8 + } + }, + show: { + event: 'mouseover', + delay: 1000 + }, + hide: {event: 'mouseout mousedown'}, + includeLabels: true }; + + if (node.data().isUcpePart){ //fix tooltip positioning for UCPE-cps + opts.position.adjust = {x:0, y:20}; + } + + node.qtip(opts); + }; } CommonGraphUtils.$inject = ['NodesFactory', 'LinksFactory']; 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 36c75c55fc..596dcecc13 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 @@ -176,6 +176,17 @@ export class ComponentInstanceNodesStyle { } }, { + selector: '.vl-link-1', + css: { + 'width': 3, + 'line-color': GraphColors.ACTIVE_LINK, + 'curve-style': 'unbundled-bezier', + 'target-arrow-color': '#3b7b9b', + 'target-arrow-shape': 'triangle', + 'control-point-step-size': 30 + } + }, + { selector: '.ucpe-host-link', css: { 'width': 0 @@ -196,6 +207,17 @@ export class ComponentInstanceNodesStyle { }, { + selector: '.service-path-link', + css: { + 'width': 2, + 'line-color': GraphColors.SERVICE_PATH_LINK, + 'target-arrow-color': GraphColors.SERVICE_PATH_LINK, + 'target-arrow-shape': 'triangle', + 'curve-style': 'bezier', + 'control-point-step-size': 30 + } + }, + { selector: '.not-certified', css: { 'shape': 'rectangle', 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 cdb163bda1..2144ecfbfa 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 @@ -18,6 +18,7 @@ * ============LICENSE_END========================================================= */ +import * as _ from "lodash"; import { Match, LinkMenu, @@ -28,13 +29,15 @@ import { Relationship, PropertyModel, Component, + Service, ConnectRelationModel, CompositionCiNodeBase, CompositionCiNodeVl, ModalModel, ButtonModel, NodesFactory/*, - AssetPopoverObj*/ + AssetPopoverObj*/, + Point } from "app/models"; import {ComponentInstanceFactory, ComponentFactory, GRAPH_EVENTS, GraphColors} from "app/utils"; import {EventListenerService, LoaderService} from "app/services"; @@ -60,13 +63,32 @@ 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"; -interface ICompositionGraphScope extends ng.IScope { + +export interface ICompositionGraphScope extends ng.IScope { component:Component; isLoading: boolean; isViewOnly: boolean; withSidebar: boolean; + + //zones + newZoneInstance; + zoneTagMode:string; + activeZoneInstance:ZoneInstanceConfig; + zones:any; + zoneInstanceModeChanged(newMode:ZoneInstanceMode, instance:ZoneInstanceConfig, zoneId:string); + clickOutsideZoneInstance():void; + // Link menu - create link menu relationMenuDirectiveObj:ConnectRelationModel; isLinkMenuOpen:boolean; @@ -76,6 +98,7 @@ interface ICompositionGraphScope extends ng.IScope { //modify link menu - for now only delete menu relationMenuTimeout:ng.IPromise<any>; linkMenuObject:LinkMenu; + isOnDrag: boolean; //left palette functions callbacks dropCallback(event:JQueryEventObject, ui:any):void; @@ -95,7 +118,12 @@ interface ICompositionGraphScope extends ng.IScope { highlightSearchMatches(searchTerm: string): void; canvasMenuProps:any; - + + createOrUpdateServicePath(data: any):void; + deletePathsOnCy():void; + drawPathOnCy(data: ForwardingPath):void; + selectedPathId: string; + /*//asset popover menu assetPopoverObj:AssetPopoverObj; assetPopoverOpen:boolean; @@ -124,10 +152,13 @@ export class CompositionGraph implements ng.IDirective { private commonGraphUtils:CommonGraphUtils, private matchCapabilitiesRequirementsUtils:MatchCapabilitiesRequirementsUtils, private CompositionGraphPaletteUtils:CompositionGraphPaletteUtils, + private compositionGraphZoneUtils:CompositionGraphZoneUtils, private ComponentServiceNg2: ComponentServiceNg2, private ModalServiceNg2: ModalService, private ConnectionWizardServiceNg2: ConnectionWizardService, - private ComponentInstanceServiceNg2: ComponentInstanceServiceNg2) { + private ComponentInstanceServiceNg2: ComponentInstanceServiceNg2, + private servicePathGraphUtils: ServicePathGraphUtils, + private policiesService:PoliciesService) { } @@ -140,7 +171,6 @@ export class CompositionGraph implements ng.IDirective { }; link = (scope:ICompositionGraphScope, el:JQuery) => { - this.loadGraph(scope, el); if(scope.component.componentInstances && scope.component.componentInstancesRelations) { @@ -164,15 +194,16 @@ export class CompositionGraph implements ng.IDirective { private loadGraphData = (scope:ICompositionGraphScope) => { this.initGraphNodes(scope.component.componentInstances, scope.isViewOnly); - this.commonGraphUtils.initGraphLinks(this._cy, scope.component.componentInstancesRelations); + 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); } private loadGraph = (scope:ICompositionGraphScope, el:JQuery) => { - let graphEl = el.find('.sdc-composition-graph-wrapper'); this.initGraph(graphEl, scope.isViewOnly); this.initDropZone(scope); + this.initZones(scope); this.registerCytoscapeGraphEvents(scope); this.registerCustomEvents(scope, el); this.initViewMode(scope.isViewOnly); @@ -210,6 +241,12 @@ export class CompositionGraph implements ng.IDirective { private registerCustomEvents(scope:ICompositionGraphScope, el:JQuery) { this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HOVER_IN, (leftPaletteComponent:LeftPaletteComponent) => { + if(scope.isOnDrag || + leftPaletteComponent.categoryType === LeftPaletteMetadataTypes.Group || + leftPaletteComponent.categoryType === LeftPaletteMetadataTypes.Policy) { + return; + } + this.$log.info(`composition-graph::registerEventServiceEvents:: palette hover on component: ${leftPaletteComponent.uniqueId}`); let nodesData = this.NodesGraphUtils.getAllNodesData(this._cy.nodes()); @@ -240,6 +277,33 @@ export class CompositionGraph implements ng.IDirective { }); }); + 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.policiesService.createPolicyInstance(component.componentType, component.uniqueId, paletteComponent.type).subscribe((newInstance)=>{ + + this.LoaderService.hideLoader('composition-graph'); + scope.newZoneInstance = newInstance; + this.compositionGraphZoneUtils.showAnimationToZone(startPosition, zoneType); + }, (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); @@ -362,17 +426,11 @@ export class CompositionGraph implements ng.IDirective { .updateInstanceCapabilityProperties( scope.component, this.ConnectionWizardServiceNg2.selectedMatch.toNode, - this.ConnectionWizardServiceNg2.selectedMatch.capability.type, - this.ConnectionWizardServiceNg2.selectedMatch.capability.name, + this.ConnectionWizardServiceNg2.selectedMatch.capability, capabilityPropertiesBE ) .subscribe((response) => { console.log("Update resource instance capability properties response: ", response); - response.forEach((resProperty) => { - this.ConnectionWizardServiceNg2.selectedMatch.capabilityProperties.find((property) => { - return property.uniqueId == resProperty.uniqueId; - }).value = resProperty.value; - }); this.ConnectionWizardServiceNg2.changedCapabilityProperties = []; resolve(capabilityPropertiesBE); }); @@ -400,6 +458,16 @@ export class CompositionGraph implements ng.IDirective { }); }; + scope.createOrUpdateServicePath = (data:any) => { + this.servicePathGraphUtils.createOrUpdateServicePath(scope, data); + }; + scope.deletePathsOnCy = () => { + this.servicePathGraphUtils.deletePathsFromGraph(this._cy, <Service> scope.component); + }; + scope.drawPathOnCy = (data: ForwardingPath) => { + this.servicePathGraphUtils.drawPath(this._cy, data, <Service> scope.component); + }; + scope.viewRelation = (link:Cy.CollectionEdges) => { scope.hideRelationMenu(); @@ -408,41 +476,9 @@ export class CompositionGraph implements ng.IDirective { const targetNode:CompositionCiNodeBase = link.target().data(); const relationship:Relationship = linkData.relation.relationships[0]; - let capability:Capability; - _.some(_.values(targetNode.componentInstance.capabilities), (capGroup) => { - //item.uniqueId + item.ownerId + item.name === (selectedReqOrCapModel.uniqueId + selectedReqOrCapModel.ownerId + selectedReqOrCapModel.name) - capability = _.find<Capability>(_.values<Capability>(capGroup), (cap:Capability) => ( - cap.uniqueId === relationship.relation.capabilityUid && - cap.ownerId === relationship.relation.capabilityOwnerId && - cap.name === relationship.relation.capability - )); - return capability; - }); - let requirement:Requirement; - _.some(_.values(sourceNode.componentInstance.requirements), (reqGroup) => { - requirement = _.find<Requirement>(_.values<Requirement>(reqGroup), (req:Requirement) => ( - req.uniqueId === relationship.relation.requirementUid && - req.ownerId === relationship.relation.requirementOwnerId && - req.name === relationship.relation.requirement - )); - return requirement; - }); - - new Promise<{capability:Capability, requirement:Requirement}>((resolve, reject) => { - if (capability && requirement) { - resolve({capability, requirement}); - } - else { - scope.component.fetchRelation(relationship.relation.id).then((fetchedRelation) => { - resolve({ - capability: fetchedRelation.relationships[0].capability, - requirement: fetchedRelation.relationships[0].requirement - }); - }, reject); - } - }).then((objReqCap) => { - capability = objReqCap.capability; - requirement = objReqCap.requirement; + scope.component.getRelationRequirementCapability(relationship, sourceNode.componentInstance, targetNode.componentInstance).then((objReqCap) => { + const capability = objReqCap.capability; + const requirement = objReqCap.requirement; this.ConnectionWizardServiceNg2.currentComponent = scope.component; this.ConnectionWizardServiceNg2.connectRelationModel = new ConnectRelationModel(sourceNode, targetNode, []); @@ -459,11 +495,19 @@ export class CompositionGraph implements ng.IDirective { this.ModalServiceNg2.addDynamicContentToModal(modalInstance, ConnectionPropertiesViewComponent); modalInstance.instance.open(); - this.ComponentInstanceServiceNg2.getInstanceCapabilityProperties(scope.component, linkData.target, capability.type, capability.name) - .subscribe((response: Array<PropertyModel>) => { - this.ConnectionWizardServiceNg2.selectedMatch.capabilityProperties = response; - this.ModalServiceNg2.addDynamicContentToModal(modalInstance, ConnectionPropertiesViewComponent); - }, (error) => {}); + new Promise((resolve) => { + if (!this.ConnectionWizardServiceNg2.selectedMatch.capability.properties) { + this.ComponentInstanceServiceNg2.getInstanceCapabilityProperties(scope.component, linkData.target, capability) + .subscribe(() => { + resolve(); + }, (error) => {}); + } else { + resolve(); + } + }).then(() => { + this.ModalServiceNg2.addDynamicContentToModal(modalInstance, ConnectionPropertiesViewComponent); + }) + }, (error) => {}); }; @@ -504,7 +548,7 @@ export class CompositionGraph implements ng.IDirective { this.ConnectionWizardServiceNg2.currentComponent = scope.component; //TODO: init with the selected values this.ConnectionWizardServiceNg2.selectedMatch = null; - + let steps:Array<StepModel> = []; let fromNodeName:string = scope.relationMenuDirectiveObj.fromNode.componentInstance.name; let toNodeName:string = scope.relationMenuDirectiveObj.toNode.componentInstance.name; @@ -523,6 +567,7 @@ export class CompositionGraph implements ng.IDirective { } }); this._cy.on('tapstart', 'node', (event:Cy.EventObject) => { + scope.isOnDrag = true; this._currentlyCLickedNodePosition = angular.copy(event.cyTarget[0].position()); //update node position on drag if (event.cyTarget.data().isUcpe) { this._cy.nodes('.ucpe-cp').unlock(); @@ -592,7 +637,7 @@ export class CompositionGraph implements ng.IDirective { this._cy.on('tapend', (event:Cy.EventObject) => { - + scope.isOnDrag = false; if (event.cyTarget === this._cy) { //On Background clicked if (this._cy.$('node:selected').length === 0) { //if the background click but not dragged this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_GRAPH_BACKGROUND_CLICKED); @@ -603,6 +648,9 @@ export class CompositionGraph implements ng.IDirective { 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; + } this.openModifyLinkMenu(scope, this.CompositionGraphLinkUtils.getModifyLinkMenu(event.cyTarget[0], event), 6000); } @@ -640,13 +688,6 @@ export class CompositionGraph implements ng.IDirective { }); } - /* - private showNodePopoverMenu = (scope:ICompositionGraphScope, node:Cy.CollectionNodes) => { - - scope.assetPopoverObj = this.NodesGraphUtils.createAssetPopover(this._cy, node, scope.isViewOnly); - scope.assetPopoverOpen = true; - - };*/ private openModifyLinkMenu = (scope:ICompositionGraphScope, linkMenuObject:LinkMenu, timeOutInMilliseconds?:number) => { scope.hideRelationMenu(); this.$timeout(() => { @@ -732,6 +773,49 @@ 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(); + } + } else { + scope.setZoneInstanceMode(newMode, instance, zoneId); + } + }; + + scope.setZoneInstanceMode = (newMode:ZoneInstanceMode, instance:ZoneInstanceConfig, zoneId:string):void => { + instance.mode = newMode; + switch(newMode){ + case ZoneInstanceMode.TAG: { + scope.zoneTagMode = zoneId + "-tagging"; + } + case ZoneInstanceMode.SELECTED: { //case TAG flows into here as well + scope.activeZoneInstance = instance; + break; + } + } + }; + + scope.unsetActiveZoneInstance = ():void => { + scope.activeZoneInstance.mode = ZoneInstanceMode.NONE; + scope.activeZoneInstance = null; + scope.zoneTagMode = null; + }; + + scope.clickOutsideZoneInstance = ():void => { + if(!scope.zoneTagMode) + scope.unsetActiveZoneInstance(); + }; + + }; + + + + public static factory = ($q, $log, $timeout, @@ -746,10 +830,13 @@ export class CompositionGraph implements ng.IDirective { CommonGraphUtils, MatchCapabilitiesRequirementsUtils, CompositionGraphPaletteUtils, + CompositionGraphZoneUtils, ComponentServiceNg2, ModalService, ConnectionWizardService, - ComponentInstanceServiceNg2) => { + ComponentInstanceServiceNg2, + ServicePathGraphUtils, + PoliciesService) => { return new CompositionGraph( $q, $log, @@ -765,10 +852,13 @@ export class CompositionGraph implements ng.IDirective { CommonGraphUtils, MatchCapabilitiesRequirementsUtils, CompositionGraphPaletteUtils, + CompositionGraphZoneUtils, ComponentServiceNg2, ModalService, ConnectionWizardService, - ComponentInstanceServiceNg2); + ComponentInstanceServiceNg2, + ServicePathGraphUtils, + PoliciesService); } } @@ -787,8 +877,11 @@ CompositionGraph.factory.$inject = [ 'CommonGraphUtils', 'MatchCapabilitiesRequirementsUtils', 'CompositionGraphPaletteUtils', + 'CompositionGraphZoneUtils', 'ComponentServiceNg2', 'ModalServiceNg2', 'ConnectionWizardServiceNg2', - 'ComponentInstanceServiceNg2' + 'ComponentInstanceServiceNg2', + 'ServicePathGraphUtils', + 'PoliciesServiceNg2' ]; 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 bbf2d6bbb2..487e4cb65a 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,5 +1,5 @@ <loader display="isLoading" loader-type="composition-graph"></loader> -<div class="sdc-composition-graph-wrapper" ng-class="{'view-only':isViewOnly}" +<div class="sdc-composition-graph-wrapper {{zoneTagMode}}" ng-class="{'view-only':isViewOnly}" data-drop="true" data-jqyoui-options="{accept: verifyDrop}" data-jqyoui-droppable="{onDrop:'dropCallback', beforeDrop: 'beforeDropCallback'}"> @@ -11,10 +11,37 @@ <menu-list-ng2 [props]="canvasMenuProps"></menu-list-ng2> <div class="w-sdc-search-menu" data-ng-class="{'with-sidebar': withSidebar}"> - <ng2-search-with-autocomplete [search-placeholder]="'Type to search'" [auto-complete-values]="componentInstanceNames" (search-changed)="getAutoCompleteValues($event)" (search-button-clicked)="highlightSearchMatches($event)" - [search-bar-class]="'composition-search'"></ng2-search-with-autocomplete> + + <ng2-service-path-selector + ng-if="component.isService()" + [service]="component" + [draw-path]="drawPathOnCy" + [delete-paths]="deletePathsOnCy" + [selected-path-id]="selectedPathId"> + </ng2-service-path-selector> + <ng2-service-path + ng-if="component.isService()" + [service]="component" + [on-create]="createOrUpdateServicePath"> + </ng2-service-path> + <ng2-search-with-autocomplete + [search-placeholder]="'Type to search'" + [auto-complete-values]="componentInstanceNames" + (search-changed)="getAutoCompleteValues($event)" + (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 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-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)"> + </ng2-zone-instance> + </ng2-zone-container> +</div> 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 56c8b5529d..5a6a104670 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 @@ -11,4 +11,28 @@ composition-graph { .view-only{ background-color:rgb(248, 248, 248); } + + .sdc-canvas-zones__wrapper { + position: absolute; + bottom: 10px; + right: 12px; + display:flex; + transition: right 0.2s; + + &.with-sidebar { + right:310px; + } + + ng2-zone-container { + display:flex; + margin-left: 10px; + } + } + + .group-tagging { + cursor: url("/assets/styles/images/canvas-tagging-icons/adding_group.svg"), pointer; + } + .policy-tagging { + cursor: url("/assets/styles/images/canvas-tagging-icons/adding_policy.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 da7d48e6ae..73e03e954d 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 @@ -18,6 +18,7 @@ * ============LICENSE_END========================================================= */ +import * as _ from "lodash"; import {ComponentInstance, Component, Match, CompositionCiLinkBase, CompositionCiNodeUcpeCp} from "app/models"; import {QueueUtils, Dictionary, GraphUIObjects} from "app/utils"; import {LoaderService} from "app/services"; 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 index 89c5e14602..705367c5f7 100644 --- 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 @@ -21,6 +21,7 @@ /** * Created by obarda on 6/28/2016. */ +import * as _ from "lodash"; import {GraphUIObjects} from "app/utils"; import {LoaderService} from "app/services"; import { @@ -39,6 +40,7 @@ import { import {CommonGraphUtils} from "../../common/common-graph-utils"; import {CompositionGraphGeneralUtils} from "./composition-graph-general-utils"; import {MatchCapabilitiesRequirementsUtils} from "./match-capability-requierment-utils"; +import {CompositionCiServicePathLink} from "../../../../models/graph/graph-links/composition-graph-links/composition-ci-service-path-link"; export class CompositionGraphLinkUtils { @@ -86,7 +88,7 @@ export class CompositionGraphLinkUtils { let onSuccess:(response:RelationshipModel) => void = (relation:RelationshipModel) => { link.setRelation(relation); - this.commonGraphUtils.insertLinkToGraph(cy, link); + this.commonGraphUtils.insertLinkToGraph(cy, link, component.getRelationRequirementCapability.bind(component)); }; link.updateLinkDirection(); @@ -212,6 +214,28 @@ export class CompositionGraphLinkUtils { this.createLink(link, cy, component); }; + private handlePathLink(cy:Cy.Instance, event:Cy.EventObject) { + let linkData = event.cyTarget.data(); + let selectedPathId = linkData.pathId; + let pathEdges = cy.collection(`[pathId='${selectedPathId}']`); + if (pathEdges.length > 1) { + setTimeout(() => { + pathEdges.select(); + }, 0); + } + } + + private handleVLLink(event:Cy.EventObject) { + let vl:Cy.CollectionNodes = event.cyTarget[0].target('.vl-node'); + let connectedEdges:Cy.CollectionEdges = vl.connectedEdges(`[type!="${CompositionCiServicePathLink.LINK_TYPE}"]`); + if (vl.length && connectedEdges.length > 1) { + setTimeout(() => { + vl.select(); + connectedEdges.select(); + }, 0); + } + } + /** * Handles click event on links. @@ -224,18 +248,13 @@ export class CompositionGraphLinkUtils { if (cy.$('edge:selected').length > 1 && 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); + if (event.cyTarget[0].data().type === CompositionCiServicePathLink.LINK_TYPE) { + this.handlePathLink(cy, event); + } + else { + this.handleVLLink(event); } } - } 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 449d551cc0..fb1e6650bd 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 @@ -18,11 +18,15 @@ * ============LICENSE_END========================================================= */ -import {Component, NodesFactory, ComponentInstance, CompositionCiNodeVl,IAppMenu,AssetPopoverObj} from "app/models"; +import * as _ from "lodash"; +import {Component, NodesFactory, ComponentInstance, CompositionCiNodeVl,IAppMenu,AssetPopoverObj, Service} from "app/models"; import {EventListenerService, LoaderService} from "app/services"; import {GRAPH_EVENTS,ModalsHandler,GraphUIObjects} from "app/utils"; import {CompositionGraphGeneralUtils} from "./composition-graph-general-utils"; import {CommonGraphUtils} from "../../common/common-graph-utils"; +import {CompositionCiServicePathLink} from "app/models/graph/graph-links/composition-graph-links/composition-ci-service-path-link"; +import {ServiceGenericResponse} from "app/ng2/services/responses/service-generic-response"; +import {ServiceServiceNg2} from 'app/ng2/services/component-services/service.service'; /** * Created by obarda on 11/9/2016. */ @@ -31,9 +35,10 @@ export class CompositionGraphNodesUtils { private GeneralGraphUtils:CompositionGraphGeneralUtils, private commonGraphUtils:CommonGraphUtils, private eventListenerService:EventListenerService, - private loaderService:LoaderService /*, - private sdcMenu: IAppMenu, - private ModalsHandler: ModalsHandler*/) { + private loaderService:LoaderService, + private serviceService:ServiceServiceNg2, + /*private sdcMenu: IAppMenu, + private ModalsHandler: ModalsHandler*/) { } @@ -88,9 +93,20 @@ export class CompositionGraphNodesUtils { this.handleConnectedVlsToDelete(connectedVls); } + // check whether there is a service path going through this node, and if so clean it from the graph. + let nodeId = nodeToDelete.data().id; + let connectedPathLinks = cy.collection(`[type="${CompositionCiServicePathLink.LINK_TYPE}"][source="${nodeId}"], [type="${CompositionCiServicePathLink.LINK_TYPE}"][target="${nodeId}"]`); + _.forEach(connectedPathLinks, (link, key) => { + cy.remove(`[pathId="${link.data().pathId}"]`); + }); + + // update service path list + this.serviceService.getComponentCompositionData(component).subscribe((response:ServiceGenericResponse) => { + (<Service>component).forwardingPaths = response.forwardingPaths; + }); + //update UI cy.remove(nodeToDelete); - }; let onFailed:(response:any) => void = (response:any) => { @@ -297,5 +313,5 @@ export class CompositionGraphNodesUtils { } - CompositionGraphNodesUtils.$inject = ['NodesFactory', '$log', 'CompositionGraphGeneralUtils', 'CommonGraphUtils', 'EventListenerService', 'LoaderService' /*, 'sdcMenu', 'ModalsHandler'*/] + CompositionGraphNodesUtils.$inject = ['NodesFactory', '$log', 'CompositionGraphGeneralUtils', 'CommonGraphUtils', 'EventListenerService', 'LoaderService', 'ServiceServiceNg2' /*, 'sdcMenu', 'ModalsHandler'*/] 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 new file mode 100644 index 0000000000..ef047d7dd3 --- /dev/null +++ b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-service-path-utils.ts @@ -0,0 +1,80 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +import * as _ from "lodash"; +import {LoaderService} from "app/services"; +import {CompositionGraphGeneralUtils} from "./composition-graph-general-utils"; +import {ICompositionGraphScope} from "../composition-graph.directive"; +import {ServiceServiceNg2} from 'app/ng2/services/component-services/service.service'; +import {Service} from "../../../../models/components/service"; +import {ForwardingPath} from "app/models/forwarding-path"; +import {ForwardingPathLink} from "app/models/forwarding-path-link"; +import {CompositionCiServicePathLink} from "../../../../models/graph/graph-links/composition-graph-links/composition-ci-service-path-link"; +import {CommonGraphUtils} from "app/directives/graphs-v2/common/common-graph-utils"; + +export class ServicePathGraphUtils { + + constructor( + private loaderService:LoaderService, + private generalGraphUtils:CompositionGraphGeneralUtils, + private serviceService:ServiceServiceNg2, + private commonGraphUtils:CommonGraphUtils + ) {} + + public deletePathsFromGraph(cy: Cy.Instance, service:Service){ + cy.remove(`[type="${CompositionCiServicePathLink.LINK_TYPE}"]`); + } + + public drawPath(cy: Cy.Instance, forwardingPath: ForwardingPath, service:Service) { + let pathElements = forwardingPath.pathElements.listToscaDataDefinition; + + _.forEach(pathElements, (link: ForwardingPathLink) => { + let data:CompositionCiServicePathLink = new CompositionCiServicePathLink(link); + data.source = data.forwardingPathLink.fromNode; + data.target = data.forwardingPathLink.toNode; + data.pathId = forwardingPath.uniqueId; + data.pathName = forwardingPath.name; + this.commonGraphUtils.insertServicePathLinkToGraph(cy, data); + }); + } + + public createOrUpdateServicePath = (scope:ICompositionGraphScope, path: any): void => { + let service = <Service>scope.component; + this.loaderService.showLoader('composition-graph'); + + let onSuccess: (response: ForwardingPath) => void = (response: ForwardingPath) => { + + service.forwardingPaths[response.uniqueId] = response; + scope.selectedPathId = response.uniqueId; + }; + + this.generalGraphUtils.getGraphUtilsServerUpdateQueue().addBlockingUIActionWithReleaseCallback( + () => this.serviceService.createOrUpdateServicePath(service, path).subscribe(onSuccess), + () => this.loaderService.hideLoader('composition-graph') + ); + }; +} + +ServicePathGraphUtils.$inject = [ + 'LoaderService', + 'CompositionGraphGeneralUtils', + 'ServiceServiceNg2', + 'CommonGraphUtils' +]; 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 new file mode 100644 index 0000000000..28f2dc85d2 --- /dev/null +++ b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-zone-utils.ts @@ -0,0 +1,55 @@ +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"; + +export class CompositionGraphZoneUtils { + + constructor(private dynamicComponentService: DynamicComponentService) {} + + 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; + } + _.forEach(policies, (policy:PolicyInstance) => { + policyZone.instances.push(new ZoneInstanceConfig(policy)); + }); + } + + public addInstanceToZone(zone:ZoneConfig, instance:PolicyInstance){ + zone.instances.push(new ZoneInstanceConfig(instance)); + }; + + 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'); + return point; + } + + public showAnimationToZone = (startPoint:Point, zoneType:string) => { + + let paletteToZoneAnimation = this.dynamicComponentService.createDynamicComponent(PaletteAnimationComponent); + paletteToZoneAnimation.instance.from = startPoint; + paletteToZoneAnimation.instance.to = this.findZoneCoordinates(zoneType); + paletteToZoneAnimation.instance.iconName = zoneType; + paletteToZoneAnimation.instance.runAnimation(); + } + + +} + +CompositionGraphZoneUtils.$inject = [ + 'DynamicComponentService' +];
\ 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 6a02381902..3a05ce901f 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 @@ -18,6 +18,7 @@ * ============LICENSE_END========================================================= */ +import * as _ from "lodash"; import { Requirement, CompositionCiLinkBase, CapabilitiesGroup, RequirementsGroup, Match, CompositionCiNodeBase, Component, Capability @@ -142,7 +143,7 @@ export class MatchCapabilitiesRequirementsUtils { let requirementArray:Array<Requirement> = []; _.forEach(_.flatten(_.values(requirements)), (requirement:Requirement)=> { - if (requirement.name !== "dependency" && !MatchCapabilitiesRequirementsUtils.isRequirementFulfilled(fromNodeId, requirement, links)) { + if (requirement.name !== 'dependency' && requirement.parentName !== 'dependency' && !MatchCapabilitiesRequirementsUtils.isRequirementFulfilled(fromNodeId, requirement, links)) { requirementArray.push(requirement); } }); 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 127f43b734..c542e9fc95 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 @@ -18,6 +18,7 @@ * ============LICENSE_END========================================================= */ +import * as _ from "lodash"; import { Component, Module, NodesFactory, ComponentInstance } from "app/models"; import { ComponentInstanceFactory } from "app/utils"; import { DeploymentGraphGeneralUtils } from "./deployment-utils/deployment-graph-general-utils"; @@ -133,7 +134,7 @@ export class DeploymentGraph implements ng.IDirective { }); this.initGraphNodes(this._cy, scope.component); //creating instances nodes - this.commonGraphUtils.initGraphLinks(this._cy, scope.component.componentInstancesRelations); + this.commonGraphUtils.initGraphLinks(this._cy, scope.component.componentInstancesRelations, scope.component.getRelationRequirementCapability.bind(scope.component)); this._cy.collapseAll(); this.registerGraphEvents(); 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 e481b1d268..3a90115179 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 @@ -18,6 +18,7 @@ * ============LICENSE_END========================================================= */ +import * as _ from "lodash"; import {Module} from "app/models"; /** * Created by obarda on 12/21/2016. 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 8abf968c82..9b9235248e 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 @@ -7,9 +7,9 @@ * 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. @@ -17,7 +17,8 @@ * limitations under the License. * ============LICENSE_END========================================================= */ -import {Component, IAppMenu, LeftPanelModel, NodesFactory, LeftPaletteComponent, CompositionCiNodeBase, ComponentInstance} from "app/models"; +import * as _ from "lodash"; +import {Component, IAppMenu, LeftPanelModel, NodesFactory, LeftPaletteComponent, CompositionCiNodeBase, ComponentInstance, Point} from "app/models"; import {CompositionGraphGeneralUtils} from "../composition-graph/utils/composition-graph-general-utils"; import {EventListenerService} from "app/services"; import {ResourceType, GRAPH_EVENTS, EVENTS, ComponentInstanceFactory, ModalsHandler} from "app/utils"; @@ -25,6 +26,8 @@ import 'sdc-angular-dragdrop'; import {LeftPaletteLoaderService} from "../../../services/components/utils/composition-left-palette-service"; import {Resource} from "app/models/components/resource"; import {ComponentType} from "app/utils/constants"; +import {LeftPaletteMetadataTypes} from "../../../models/components/displayComponent"; + interface IPaletteScope { components:Array<LeftPaletteComponent>; @@ -39,10 +42,15 @@ interface IPaletteScope { ui:any } + addInstanceClick: ()=>void; // added code + onPopupMouseOver: ()=>void // added code + onPopupMouseOut: ()=>void // added code + sectionClick:(section:string)=>void; searchComponents:(searchText:string)=>void; - onMouseOver:(displayComponent:LeftPaletteComponent)=>void; + onMouseOver:(displayComponent:LeftPaletteComponent, elem: HTMLElement)=>void; onMouseOut:(displayComponent:LeftPaletteComponent)=>void; + dragStartCallback:(event:JQueryEventObject, ui, displayComponent:LeftPaletteComponent)=>void; dragStopCallback:()=>void; onDragCallback:(event:JQueryEventObject) => void; @@ -65,8 +73,8 @@ export class Palette implements ng.IDirective { private CompositionGraphGeneralUtils:CompositionGraphGeneralUtils, private EventListenerService:EventListenerService, private sdcMenu:IAppMenu, - private ModalsHandler:ModalsHandler) { - + private ModalsHandler:ModalsHandler + ) { } private fetchingComponentFromServer:boolean = false; @@ -84,7 +92,6 @@ export class Palette implements ng.IDirective { this.nodeHtmlSubstitute = $('<div class="node-substitute"><span></span><img /></div>'); el.append(this.nodeHtmlSubstitute); this.registerEventListenerForLeftPalette(scope); - // this.LeftPaletteLoaderService.loadLeftPanel(scope.currentComponent.componentType); this.initComponents(scope); this.initEvents(scope); @@ -96,31 +103,15 @@ export class Palette implements ng.IDirective { }); }; - private getUpdateLeftPaletteEventName = (component:Component):string => { - switch (component.componentType) { - case ComponentType.SERVICE: - return EVENTS.SERVICE_LEFT_PALETTE_UPDATE_EVENT; - case ComponentType.RESOURCE: - if((<Resource>component).resourceType == ResourceType.PNF){ - return EVENTS.RESOURCE_PNF_LEFT_PALETTE_UPDATE_EVENT; - }else{ - return EVENTS.RESOURCE_LEFT_PALETTE_UPDATE_EVENT; - } - default: - console.log('ERROR: Component type '+ component.componentType + ' is not exists'); - } - }; private registerEventListenerForLeftPalette = (scope:IPaletteScope):void => { - let updateEventName:string = this.getUpdateLeftPaletteEventName(scope.currentComponent); - this.EventListenerService.registerObserverCallback(updateEventName, () => { + this.EventListenerService.registerObserverCallback(EVENTS.LEFT_PALETTE_UPDATE_EVENT, () => { this.updateLeftPanelDisplay(scope); }); }; private unRegisterEventListenerForLeftPalette = (scope:IPaletteScope):void => { - let updateEventName:string = this.getUpdateLeftPaletteEventName(scope.currentComponent); - this.EventListenerService.unRegisterObserver(updateEventName); + this.EventListenerService.unRegisterObserver(EVENTS.LEFT_PALETTE_UPDATE_EVENT); }; private leftPanelResourceFilter(resourcesNotAbstract:Array<LeftPaletteComponent>, resourceFilterTypes:Array<string>):Array<LeftPaletteComponent> { @@ -132,7 +123,7 @@ export class Palette implements ng.IDirective { private initLeftPanel(leftPanelComponents:Array<LeftPaletteComponent>, resourceFilterTypes:Array<string>):LeftPanelModel { let leftPanelModel = new LeftPanelModel(); - + if (resourceFilterTypes && resourceFilterTypes.length) { leftPanelComponents = this.leftPanelResourceFilter(leftPanelComponents, resourceFilterTypes); } @@ -151,10 +142,7 @@ export class Palette implements ng.IDirective { private initEvents(scope:IPaletteScope) { - /** - * - * @param section - */ + scope.sectionClick = (section:string) => { if (section === scope.expandedSection) { scope.expandedSection = ''; @@ -163,20 +151,37 @@ export class Palette implements ng.IDirective { scope.expandedSection = section; }; - scope.onMouseOver = (displayComponent:LeftPaletteComponent) => { - if (scope.isOnDrag) { - return; + scope.onMouseOver = (displayComponent:LeftPaletteComponent, sectionElem: HTMLElement) => { + if (this.isGroupOrPolicy(displayComponent)) { + this.EventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_SHOW_POPUP_PANEL, scope.currentComponent, displayComponent, sectionElem); + } else { + if (scope.isOnDrag) { + return; + } + scope.isOnDrag = true; + this.EventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HOVER_IN, displayComponent); + this.$log.debug('palette::onMouseOver:: fired'); } - scope.isOnDrag = true; - this.EventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HOVER_IN, displayComponent); - this.$log.debug('palette::onMouseOver:: fired'); }; - scope.onMouseOut = () => { - scope.isOnDrag = false; - this.EventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HOVER_OUT); + scope.onMouseOut = (displayComponent:LeftPaletteComponent) => { + if(this.isGroupOrPolicy(displayComponent)) { + this.EventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HIDE_POPUP_PANEL); + } else { + scope.isOnDrag = false; + this.EventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HOVER_OUT); + } + }; + } + + private isGroupOrPolicy(component:LeftPaletteComponent): boolean { + if(component && + (component.categoryType === LeftPaletteMetadataTypes.Group || + component.categoryType === LeftPaletteMetadataTypes.Policy)) { + return true; } + return false; } private initComponents(scope:IPaletteScope) { @@ -193,10 +198,10 @@ export class Palette implements ng.IDirective { let entityType:string = scope.currentComponent.componentType.toLowerCase(); let resourceFilterTypes:Array<string> = this.sdcConfig.resourceTypesFilter[entityType]; scope.components = this.LeftPaletteLoaderService.getLeftPanelComponentsForDisplay(scope.currentComponent); - //remove the container component from the list + //remove the container component from the list let componentTempToDisplay = angular.copy(scope.components); - componentTempToDisplay = _.remove(componentTempToDisplay, function (component) { - return component.component.invariantUUID !== scope.currentComponent.invariantUUID; + componentTempToDisplay = _.remove(componentTempToDisplay, function (leftPalettecomponent) { + return leftPalettecomponent.invariantUUID !== scope.currentComponent.invariantUUID; }); scope.model = this.initLeftPanel(componentTempToDisplay, resourceFilterTypes); scope.displaySortedCategories = angular.copy(scope.model.sortedCategories); @@ -224,7 +229,7 @@ export class Palette implements ng.IDirective { private initDragEvents(scope:IPaletteScope) { scope.dragStartCallback = (event:IDragDropEvent, ui, displayComponent:LeftPaletteComponent):void => { - if (scope.isLoading || !scope.isDragable || scope.isViewOnly) { + if (scope.isLoading || !scope.isDragable || scope.isViewOnly || this.isGroupOrPolicy(displayComponent)) { return; } @@ -302,7 +307,8 @@ export class Palette implements ng.IDirective { CompositionGraphGeneralUtils, EventListenerService, sdcMenu, - ModalsHandler) => { + ModalsHandler + ) => { return new Palette($log, LeftPaletteLoaderService, sdcConfig, @@ -312,7 +318,8 @@ export class Palette implements ng.IDirective { CompositionGraphGeneralUtils, EventListenerService, sdcMenu, - ModalsHandler); + ModalsHandler + ); }; } 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 7f9bfd1e0d..a8139e3140 100644 --- a/catalog-ui/src/app/directives/graphs-v2/palette/palette.html +++ b/catalog-ui/src/app/directives/graphs-v2/palette/palette.html @@ -24,9 +24,9 @@ </div> <div class="i-sdc-designer-leftbar-section-content-item" data-ng-class="{'default-pointer': isViewOnly}" - data-ng-mouseover="!isViewOnly && onMouseOver(component)" - data-ng-mouseleave="!isViewOnly && onMouseOut()" - data-drag="{{!isViewOnly}}" + data-ng-mouseover="!isViewOnly && onMouseOver(component, $event.currentTarget)" + data-ng-mouseleave="!isViewOnly && onMouseOut(component)" + data-drag="!isViewOnly" 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" @@ -40,14 +40,16 @@ </div> </div> <div class="i-sdc-designer-leftbar-section-content-item-info"> - <span class="i-sdc-designer-leftbar-section-content-item-info-title" - uib-tooltip="{{component.displayName}}" tooltip-class="uib-custom-tooltip" - tooltip-placement="bottom" tooltip-popup-delay="700"> - {{component.displayName}}</span> + <span class="i-sdc-designer-leftbar-section-content-item-info-title" + uib-tooltip="{{component.displayName}}" tooltip-class="uib-custom-tooltip" + tooltip-placement="bottom" tooltip-popup-delay="700"> + {{component.displayName}}</span> <div class="i-sdc-designer-leftbar-section-content-item-info-text"> V.{{component.version}} </div> - <div class="i-sdc-designer-leftbar-section-content-item-info-text"> Type: + <div class="i-sdc-designer-leftbar-section-content-item-info-text" + uib-tooltip="{{component.type}}" tooltip-class="uib-custom-tooltip" + tooltip-placement="top" tooltip-popup-delay="700"> Type: {{component.componentSubType}} </div> </div> 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 index f73e855c0e..78a269ead1 100644 --- 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 @@ -18,6 +18,7 @@ * ============LICENSE_END========================================================= */ 'use strict' +import * as _ from "lodash"; import {Match, ConnectRelationModel} from "app/models"; import {Component} from "../../../models/components/component"; diff --git a/catalog-ui/src/app/directives/property-types/data-type-fields-structure/data-type-fields-structure.ts b/catalog-ui/src/app/directives/property-types/data-type-fields-structure/data-type-fields-structure.ts index 476f86d8a6..eed209d438 100644 --- a/catalog-ui/src/app/directives/property-types/data-type-fields-structure/data-type-fields-structure.ts +++ b/catalog-ui/src/app/directives/property-types/data-type-fields-structure/data-type-fields-structure.ts @@ -22,6 +22,7 @@ * Created by obarda on 1/27/2016. */ 'use strict'; +import * as _ from "lodash"; import {DataTypesService} from "app/services"; import { ValidationUtils } from "app/utils"; import { DataTypePropertyModel } from "app/models/data-type-properties"; diff --git a/catalog-ui/src/app/directives/select-property-types/select-data-type-fields-structure/select-data-type-fields-structure.ts b/catalog-ui/src/app/directives/select-property-types/select-data-type-fields-structure/select-data-type-fields-structure.ts index a8bcf3f155..f5e9a36041 100644 --- a/catalog-ui/src/app/directives/select-property-types/select-data-type-fields-structure/select-data-type-fields-structure.ts +++ b/catalog-ui/src/app/directives/select-property-types/select-data-type-fields-structure/select-data-type-fields-structure.ts @@ -22,6 +22,7 @@ * Created by obarda on 1/27/2016. */ 'use strict'; +import * as _ from "lodash"; import {ValidationUtils} from "app/utils"; import { DataTypesService } from "app/services"; import { DataTypePropertyModel } from "app/models/data-type-properties"; diff --git a/catalog-ui/src/app/directives/structure-tree/structure-tree-directive.ts b/catalog-ui/src/app/directives/structure-tree/structure-tree-directive.ts index 4f80ae86c0..59fa700dc9 100644 --- a/catalog-ui/src/app/directives/structure-tree/structure-tree-directive.ts +++ b/catalog-ui/src/app/directives/structure-tree/structure-tree-directive.ts @@ -18,6 +18,7 @@ * ============LICENSE_END========================================================= */ 'use strict'; +import * as _ from "lodash"; import {RelationshipModel, Component, ComponentInstance} from "app/models"; import {Dictionary} from "app/utils"; |