From 39a4e0cb1b805470ad85ed4cf4fdeb69610ae98c Mon Sep 17 00:00:00 2001 From: Michael Lando Date: Tue, 18 Jul 2017 20:46:42 +0300 Subject: [SDC] rebase 1710 Change-Id: I07fced02f40a57700d9d35ed3ba498bca351fb13 Signed-off-by: Michael Lando --- .../style/component-instances-nodes-style.ts | 4 +- .../composition-graph.directive.ts | 60 +++++++++++++++++++--- .../composition-graph/composition-graph.html | 7 +++ .../utils/composition-graph-general-utils.ts | 8 +++ .../utils/composition-graph-nodes-utils.ts | 15 ++++++ 5 files changed, 86 insertions(+), 8 deletions(-) (limited to 'catalog-ui/src/app/directives/graphs-v2') 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 0dcc93dfa7..64197594e2 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 @@ -231,7 +231,7 @@ export class ComponentInstanceNodesStyle { public static getBasicNodeHanlde = () => { return { - positionX: "center", + positionX: "right", positionY: "top", offsetX: 15, offsetY: -20, @@ -248,7 +248,7 @@ export class ComponentInstanceNodesStyle { public static getBasicSmallNodeHandle = () => { return { - positionX: "center", + positionX: "right", positionY: "top", offsetX: 3, offsetY: -25, 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 651a4281fa..9aa7941272 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 @@ -47,7 +47,8 @@ interface ICompositionGraphScope extends ng.IScope { component:Component; isLoading: boolean; - isViewOnly:boolean; + isViewOnly: boolean; + withSidebar: boolean; // Link menu - create link menu relationMenuDirectiveObj:RelationMenuDirectiveObj; isLinkMenuOpen:boolean; @@ -65,6 +66,14 @@ interface ICompositionGraphScope extends ng.IScope { //Links menus deleteRelation(link:Cy.CollectionEdges):void; hideRelationMenu(); + + //search,zoom in/out/all + componentInstanceNames: Array; //id, name + zoom(zoomIn: boolean): void; + zoomAll(nodes?:Cy.CollectionNodes): void; + getAutoCompleteValues(searchTerm: string):void; + highlightSearchMatches(searchTerm: string): void; + /*//asset popover menu assetPopoverObj:AssetPopoverObj; assetPopoverOpen:boolean; @@ -101,7 +110,8 @@ export class CompositionGraph implements ng.IDirective { template = require('./composition-graph.html'); scope = { component: '=', - isViewOnly: '=' + isViewOnly: '=', + withSidebar: '=' }; link = (scope:ICompositionGraphScope, el:JQuery) => { @@ -147,7 +157,11 @@ export class CompositionGraph implements ng.IDirective { this._cy = cytoscape({ container: graphEl, style: ComponentInstanceNodesStyle.getCompositionGraphStyle(), - zoomingEnabled: false, + zoomingEnabled: true, + maxZoom: 2.5, + minZoom: .1, + userZoomingEnabled: false, + userPanningEnabled: true, selectionType: 'single', boxSelectionEnabled: true, autolock: isViewOnly, @@ -270,6 +284,40 @@ export class CompositionGraph implements ng.IDirective { this.loadGraphData(scope); }); + scope.zoom = (zoomIn: boolean):void => { + let currentZoom: number = this._cy.zoom(); + if (zoomIn) { + this.GeneralGraphUtils.zoomGraphTo(this._cy, currentZoom + .1); + } else { + this.GeneralGraphUtils.zoomGraphTo(this._cy, currentZoom - .1); + } + } + + //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) => { + scope.withSidebar = false; + this._cy.animate({ + fit: { eles: nodes, padding: 20 }, + center: { eles: nodes } + }, { duration: 400 }); + }; + + 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); + scope.componentInstanceNames = _.map(nodes, node => node.data('name')); + } else { + scope.componentInstanceNames = []; + } + }; + + scope.highlightSearchMatches = (searchTerm: string) => { + if (searchTerm === undefined) return; //dont zoom & highlight if click on Search initially (searchTerm will be undefined). However, allow highlights to be cleared after subsequent search (searchTerm will be "") + + this.NodesGraphUtils.highlightMatchingNodesByName(this._cy, searchTerm); + let matchingNodes: Cy.CollectionNodes = this.NodesGraphUtils.getMatchingNodesByName(this._cy, searchTerm); + scope.zoomAll(matchingNodes); + }; scope.createLinkFromMenu = (chosenMatch:MatchBase):void => { scope.isLinkMenuOpen = false; @@ -367,7 +415,7 @@ export class CompositionGraph implements ng.IDirective { });*/ 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 + 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; } let nodesData = this.NodesGraphUtils.getAllNodesData(this._cy.nodes()); @@ -377,9 +425,9 @@ export class CompositionGraph implements ng.IDirective { let filteredNodesData = this.matchCapabilitiesRequirementsUtils.findByMatchingCapabilitiesToRequirements(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();*/ + /*scope.hideAssetPopover();*/ }); this._cy.on('handlemouseout', () => { 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 1e69d3384a..248f19fb70 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 @@ -20,4 +20,11 @@ +
+ +
+
+
+
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 608031430b..0ea38af825 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 @@ -64,6 +64,14 @@ export class CompositionGraphGeneralUtils { }; + public zoomGraphTo = (cy:Cy.Instance, zoomLevel: number):void => { + let zy = cy.height() / 2; + let zx = cy.width() / 2; + cy.zoom({ + level: zoomLevel, + renderedPosition: { x: zx, y: zy } + }); + } /** * will return true/false if two nodes overlapping * 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 feb6ac9a54..449d551cc0 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 @@ -48,6 +48,21 @@ export class CompositionGraphNodesUtils { }) }; + + public highlightMatchingNodesByName = (cy: Cy.Instance, nameToMatch: string) => { + + cy.batch(() => { + cy.nodes("[name !@^= '" + nameToMatch + "']").style({ 'background-image-opacity': 0.4 }); + cy.nodes("[name @^= '" + nameToMatch + "']").style({ 'background-image-opacity': 1 }); + }) + + } + + //Returns all nodes whose name starts with searchTerm + public getMatchingNodesByName = (cy: Cy.Instance, nameToMatch: string): Cy.CollectionNodes => { + return cy.nodes("[name @^= '" + nameToMatch + "']"); + }; + /** * Deletes component instances on server and then removes it from the graph as well * @param cy -- cgit 1.2.3-korg