GUI2 Topo Allow selection of multiple nodes at once
Change-Id: I0bb226d4697e3df49da0a049d440a70aed172263
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/forcesvg.component.ts b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/forcesvg.component.ts
index 843c19c..85f5de7 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/forcesvg.component.ts
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/forcesvg.component.ts
@@ -48,6 +48,7 @@
ModelEventMemo,
ModelEventType,
Node,
+ Options,
Region,
RegionLink,
SubRegion,
@@ -57,7 +58,7 @@
import {DeviceNodeSvgComponent} from './visuals/devicenodesvg/devicenodesvg.component';
import { HostNodeSvgComponent} from './visuals/hostnodesvg/hostnodesvg.component';
import { LinkSvgComponent} from './visuals/linksvg/linksvg.component';
-import { Options } from './models/force-directed-graph';
+import {SelectedEvent} from './visuals/nodevisual';
interface UpdateMeta {
id: string;
@@ -98,8 +99,9 @@
@Input() scale: number = 1;
@Input() regionData: Region = <Region>{devices: [ [], [], [] ], hosts: [ [], [], [] ], links: []};
@Output() linkSelected = new EventEmitter<RegionLink>();
- @Output() selectedNodeEvent = new EventEmitter<UiElement>();
+ @Output() selectedNodeEvent = new EventEmitter<UiElement[]>();
public graph: ForceDirectedGraph;
+ private selectedNodes: UiElement[] = [];
// References to the children of this component - these are created in the
// template view with the *ngFor and we get them by a query here
@@ -308,28 +310,52 @@
}
/**
- * Iterate through all hosts and devices to deselect the previously selected
+ * Iterate through all hosts and devices and links to deselect the previously selected
* node. The emit an event to the parent that lets it know the selection has
* changed.
+ *
+ * This function collates all of the nodes that have been selected and passes
+ * a collection of nodes up to the topology component
+ *
* @param selectedNode the newly selected node
*/
- updateSelected(selectedNode: UiElement): void {
- this.log.debug('Node or link selected', selectedNode ? selectedNode.id : 'none');
- this.devices
- .filter((d) =>
- selectedNode === undefined || d.device.id !== selectedNode.id)
- .forEach((d) => d.deselect());
- this.hosts
- .filter((h) =>
- selectedNode === undefined || h.host.id !== selectedNode.id)
- .forEach((h) => h.deselect());
+ updateSelected(selectedNode: SelectedEvent): void {
+ this.log.debug('Node or link ',
+ selectedNode.uiElement,
+ selectedNode.deselecting ? 'deselected' : 'selected',
+ selectedNode.isShift ? 'Multiple' : '');
- this.links
- .filter((l) =>
- selectedNode === undefined || l.link.id !== selectedNode.id)
- .forEach((l) => l.deselect());
+ if (selectedNode.isShift && selectedNode.deselecting) {
+ const idx = this.selectedNodes.findIndex((n) =>
+ n.id === selectedNode.uiElement.id
+ );
+ this.selectedNodes.splice(idx, 1);
+ this.log.debug('Removed node', idx);
+
+ } else if (selectedNode.isShift) {
+ this.selectedNodes.push(selectedNode.uiElement);
+
+ } else if (selectedNode.deselecting) {
+ this.selectedNodes = [];
+
+ } else {
+ const selNodeId = selectedNode.uiElement.id;
+ // Otherwise if shift was not pressed deselect previous
+ this.devices
+ .filter((d) => d.device.id !== selNodeId)
+ .forEach((d) => d.deselect());
+ this.hosts
+ .filter((h) => h.host.id !== selNodeId)
+ .forEach((h) => h.deselect());
+
+ this.links
+ .filter((l) => l.link.id !== selNodeId)
+ .forEach((l) => l.deselect());
+
+ this.selectedNodes = [selectedNode.uiElement];
+ }
// Push the changes back up to parent (Topology Component)
- this.selectedNodeEvent.emit(selectedNode);
+ this.selectedNodeEvent.emit(this.selectedNodes);
}
/**
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.html b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.html
index 399955c..e87e1a8 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.html
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.html
@@ -47,7 +47,7 @@
<svg:g xmlns:svg="http://www.w3.org/2000/svg"
[attr.transform]="'translate(' + device?.x + ',' + device?.y + '), scale(' + scale + ')'"
[ngClass]="['node', 'device', device.online?'online':'', selected?'selected':'']"
- (click)="toggleSelected(device)">
+ (click)="toggleSelected(device, $event)">
<svg:desc>Device {{device.id}}</svg:desc>
<!-- Template explanation: Creates an SVG Rectangle and in
line 1) set a css style and shift so that it's centred
@@ -88,4 +88,4 @@
</svg:text>
<svg:use [attr.xlink:href]="'#' + deviceIcon()" width="36" height="36" x="-18" y="-18">
</svg:use>
-</svg:g>
\ No newline at end of file
+</svg:g>
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.ts b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.ts
index ce6bd46..adcd788 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.ts
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.ts
@@ -24,7 +24,7 @@
} from '@angular/core';
import {Device, LabelToggle, UiElement} from '../../models';
import {IconService, LocMeta, LogService, MetaUi, ZoomUtils} from 'gui2-fw-lib';
-import {NodeVisual} from '../nodevisual';
+import {NodeVisual, SelectedEvent} from '../nodevisual';
import {animate, state, style, transition, trigger} from '@angular/animations';
import {LocationType} from '../../../backgroundsvg/backgroundsvg.component';
@@ -68,7 +68,7 @@
@Input() device: Device;
@Input() scale: number = 1.0;
@Input() labelToggle: LabelToggle.Enum = LabelToggle.Enum.NONE;
- @Output() selectedEvent = new EventEmitter<UiElement>();
+ @Output() selectedEvent = new EventEmitter<SelectedEvent>();
textWidth: number = 36;
constructor(
protected log: LogService,
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.html b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.html
index ccce65a..0ce4a4a 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.html
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.html
@@ -45,7 +45,7 @@
<svg:g xmlns:svg="http://www.w3.org/2000/svg"
[attr.transform]="'translate(' + host?.x + ',' + host?.y + '), scale(' + scale + ')'"
[ngClass]="['node', 'host', 'endstation', 'fixed', selected?'selected':'', 'hovered']"
- (click)="toggleSelected(host)">
+ (click)="toggleSelected(host, $event)">
<svg:desc>Host {{host.id}}</svg:desc>
<!-- Template explanation: Creates an SVG Circle and in
line 1) Apply the drop shadow defined above to this circle
@@ -67,4 +67,4 @@
*ngIf="labelToggle != 0"
dy="30" text-anchor="middle"
>{{hostName()}}</svg:text>
-</svg:g>
\ No newline at end of file
+</svg:g>
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.ts b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.ts
index 26c105a..806f9b2 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.ts
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.ts
@@ -23,7 +23,7 @@
} from '@angular/core';
import {Host, HostLabelToggle, Node} from '../../models';
import {LogService} from 'gui2-fw-lib';
-import {NodeVisual} from '../nodevisual';
+import {NodeVisual, SelectedEvent} from '../nodevisual';
/**
* The Host node in the force graph
@@ -40,7 +40,7 @@
@Input() host: Host;
@Input() scale: number = 1.0;
@Input() labelToggle: HostLabelToggle.Enum = HostLabelToggle.Enum.IP;
- @Output() selectedEvent = new EventEmitter<Node>();
+ @Output() selectedEvent = new EventEmitter<SelectedEvent>();
constructor(
protected log: LogService
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/linksvg/linksvg.component.html b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/linksvg/linksvg.component.html
index c856763..a94914d 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/linksvg/linksvg.component.html
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/linksvg/linksvg.component.html
@@ -39,7 +39,7 @@
[attr.x2]="link.target?.x" [attr.y2]="link.target?.y"
[ngClass]="['link', selected?'selected':'', enhanced?'enhanced':'', highlighted]"
[ngStyle]="{'stroke-width': (enhanced ? 4 : 2) * scale + 'px'}"
- (click)="toggleSelected(link)"
+ (click)="toggleSelected(link, $event)"
(mouseover)="enhance()"
[attr.filter]="highlighted?'url(#glow)':'none'">
</svg:line>
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/linksvg/linksvg.component.ts b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/linksvg/linksvg.component.ts
index eab533f..9853889 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/linksvg/linksvg.component.ts
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/linksvg/linksvg.component.ts
@@ -20,7 +20,7 @@
} from '@angular/core';
import {Link, LinkHighlight, UiElement} from '../../models';
import {LogService} from 'gui2-fw-lib';
-import {NodeVisual} from '../nodevisual';
+import {NodeVisual, SelectedEvent} from '../nodevisual';
import {animate, state, style, transition, trigger} from '@angular/animations';
interface Point {
@@ -52,7 +52,7 @@
@Input() label: string;
@Input() scale = 1.0;
isHighlighted: boolean = false;
- @Output() selectedEvent = new EventEmitter<UiElement>();
+ @Output() selectedEvent = new EventEmitter<SelectedEvent>();
@Output() enhancedEvent = new EventEmitter<Link>();
enhanced: boolean = false;
labelPosSrc: Point = {x: 0, y: 0};
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/nodevisual.ts b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/nodevisual.ts
index a41df62..10bf3d8 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/nodevisual.ts
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/nodevisual.ts
@@ -16,20 +16,30 @@
import {EventEmitter} from '@angular/core';
import {UiElement} from '../models';
+export interface SelectedEvent {
+ uiElement: UiElement;
+ deselecting: boolean;
+ isShift: boolean;
+ isCtrl: boolean;
+ isAlt: boolean;
+}
+
/**
* A base class for the Host and Device components
*/
export abstract class NodeVisual {
selected: boolean;
- selectedEvent = new EventEmitter<UiElement>();
+ selectedEvent = new EventEmitter<SelectedEvent>();
- toggleSelected(uiElement: UiElement) {
+ toggleSelected(uiElement: UiElement, event: MouseEvent) {
this.selected = !this.selected;
- if (this.selected) {
- this.selectedEvent.emit(uiElement);
- } else {
- this.selectedEvent.emit();
- }
+ this.selectedEvent.emit(<SelectedEvent>{
+ uiElement: uiElement,
+ deselecting: !this.selected,
+ isShift: event.shiftKey,
+ isCtrl: event.ctrlKey,
+ isAlt: event.altKey
+ });
}
deselect() {
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/panel/details/details.component.html b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/panel/details/details.component.html
index ca23ca1..845611f 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/panel/details/details.component.html
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/panel/details/details.component.html
@@ -14,7 +14,7 @@
~ limitations under the License.
-->
<div id="topo2-p-detail" class="floatpanel topo2-p"
- [@detailsPanelState]="on && selectedNode !== undefined">
+ [@detailsPanelState]="on && selectedNodes.length > 0">
<!-- Template explanation - Create a HTML header which has an SVG icon along
side title text. -->
<div class="header">
@@ -54,13 +54,13 @@
-->
<div *ngFor="let btn of showDetails?.buttons" class="actionBtn">
<onos-icon id="topo2-p-detail-core-{{ btn }}"
- (click)="navto(buttonAttribs(btn).path, showDetails.navPath, showDetails.id)"
+ (click)="navto(buttonAttribs(btn).path)"
[iconSize]="25"
[iconId]="buttonAttribs(btn).gid"
- [toolTip]="lionFn(buttonAttribs(btn).tt)"
+ [toolTip]="lionFnTopo(buttonAttribs(btn).tt)"
classes="button icon selected">
</onos-icon>
</div>
</div>
</div>
-</div>
\ No newline at end of file
+</div>
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/panel/details/details.component.ts b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/panel/details/details.component.ts
index 85282e1..21ad66e 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/panel/details/details.component.ts
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/panel/details/details.component.ts
@@ -13,22 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import {
- Component,
- Input,
- OnChanges,
- OnDestroy,
- OnInit,
- SimpleChanges
-} from '@angular/core';
+import {Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges} from '@angular/core';
import {animate, state, style, transition, trigger} from '@angular/animations';
-import {
- DetailsPanelBaseImpl,
- FnService, LionService,
- LogService,
- WebSocketService
-} from 'gui2-fw-lib';
-import {Host, Link, LinkType, UiElement} from '../../layer/forcesvg/models';
+import {DetailsPanelBaseImpl, FnService, LionService, LogService, WebSocketService} from 'gui2-fw-lib';
+import {Host, Link, LinkType, NodeType, UiElement} from '../../layer/forcesvg/models';
import {Params, Router} from '@angular/router';
@@ -68,6 +56,22 @@
tt: 'tt_ctl_show_pipeconf',
path: 'pipeconf',
};
+const RELATEDINTENTS: ButtonAttrs = {
+ gid: 'm_relatedIntents',
+ tt: 'tr_btn_show_related_traffic',
+ path: 'relatedIntents',
+};
+const CREATEHOSTTOHOSTFLOW: ButtonAttrs = {
+ gid: 'm_endstation',
+ tt: 'tr_btn_create_h2h_flow',
+ path: 'create_h2h_flow',
+};
+const CREATEMULTISOURCEFLOW: ButtonAttrs = {
+ gid: 'm_flows',
+ tt: 'tr_btn_create_msrc_flow',
+ path: 'create_msrc_flow',
+};
+
interface ShowDetails {
buttons: string[];
@@ -83,6 +87,12 @@
* ONOS GUI -- Topology Details Panel.
* Displays details of selected device. When no device is selected the panel slides
* off to the side and disappears
+ *
+ * This Panel is a child of the Topology component and it gets the 'selectedNodes'
+ * from there as an input component. See TopologyComponent.nodeSelected()
+ * The topology component gets these by listening to events from ForceSvgComponent
+ * which gets them in turn from Device, Host, SubRegion and Link components. This
+ * is so that each component respects the hierarchy
*/
@Component({
selector: 'onos-details',
@@ -108,11 +118,12 @@
]
})
export class DetailsComponent extends DetailsPanelBaseImpl implements OnInit, OnDestroy, OnChanges {
- @Input() selectedNode: UiElement = undefined; // Populated when user selects node or link
+ @Input() selectedNodes: UiElement[] = []; // Populated when user selects node or link
@Input() on: boolean = false; // Override the parent class attribute
// deferred localization strings
- lionFn; // Function
+ lionFnTopo; // Function
+ lionFnFlow; // Function for flow bundle
showDetails: ShowDetails; // Will be populated on callback. Cleared if nothing is selected
constructor(
@@ -125,8 +136,9 @@
super(fs, log, wss, 'topo');
if (this.lion.ubercache.length === 0) {
- this.lionFn = this.dummyLion;
- this.lion.loadCbs.set('flow', () => this.doLion());
+ this.lionFnTopo = this.dummyLion;
+ this.lionFnFlow = this.dummyLion;
+ this.lion.loadCbs.set('detailscore', () => this.doLion());
} else {
this.doLion();
}
@@ -160,32 +172,75 @@
/**
* If changes are detected on the Input param selectedNode, call on WSS sendEvent
+ * and expect ShowDetails to be updated from data sent back from server.
+ *
* Note the difference in call to the WSS with requestDetails between a node
* and a link - the handling is done in TopologyViewMessageHandler#RequestDetails.process()
*
+ * When multiple items are selected fabricate the ShowDetails here, and
+ * present buttons that allow custom actions
+ *
* The WSS will call back asynchronously (see fn in ngOnInit())
*
* @param changes Simple Changes set of updates
*/
ngOnChanges(changes: SimpleChanges): void {
- if (changes['selectedNode']) {
- this.selectedNode = changes['selectedNode'].currentValue;
+ if (changes['selectedNodes']) {
+ this.selectedNodes = changes['selectedNodes'].currentValue;
let type: any;
-
- if (this.selectedNode === undefined) {
+ if (this.selectedNodes.length === 0) {
// Selection has been cleared
this.showDetails = <ShowDetails>{};
return;
+ } else if (this.selectedNodes.length > 1) {
+ // Don't send message to WSS just form dialog here
+ const propOrder: string[] = [];
+ const propValues: Object = {};
+ const propLabels: Object = {};
+ let numHosts: number = 0;
+ for (let i = 0; i < this.selectedNodes.length; i++) {
+ propOrder.push(i.toString());
+ propLabels[i.toString()] = i.toString();
+ propValues[i.toString()] = this.selectedNodes[i].id;
+ if (this.selectedNodes[i].hasOwnProperty('nodeType') &&
+ (<Host>this.selectedNodes[i]).nodeType === NodeType.HOST) {
+ numHosts++;
+ } else {
+ numHosts = -128; // Negate the whole thing so other buttons will not be shown
+ }
+ }
+ const buttons: string[] = [];
+ if (numHosts === 2) {
+ buttons.push('createHostToHostFlow');
+ } else if (numHosts > 2) {
+ buttons.push('createMultiSourceFlow');
+ }
+ buttons.push('relatedIntents');
+
+ this.showDetails = <ShowDetails>{
+ buttons: buttons,
+ glyphId: undefined,
+ id: 'multiple',
+ navPath: undefined,
+ propLabels: propLabels,
+ propOrder: propOrder,
+ propValues: propValues,
+ title: this.lionFnTopo('title_selected_items')
+ };
+ this.log.debug('Details panel generated from multiple devices', this.showDetails);
+ return;
}
- if (this.selectedNode.hasOwnProperty('nodeType')) { // For Device, Host, SubRegion
- type = (<Host>this.selectedNode).nodeType;
+ // If only one thing has been selected then request details of that from the server
+ const selectedNode = this.selectedNodes[0];
+ if (selectedNode.hasOwnProperty('nodeType')) { // For Device, Host, SubRegion
+ type = (<Host>selectedNode).nodeType;
this.wss.sendEvent('requestDetails', {
- id: this.selectedNode.id,
+ id: selectedNode.id,
class: type,
});
- } else if (this.selectedNode.hasOwnProperty('type')) { // Must be link
- const link: Link = <Link>this.selectedNode;
+ } else if (selectedNode.hasOwnProperty('type')) { // Must be link
+ const link: Link = <Link>selectedNode;
if (<LinkType><unknown>LinkType[link.type] === LinkType.UiEdgeLink) { // Number based enum
this.wss.sendEvent('requestDetails', {
key: link.id,
@@ -207,7 +262,7 @@
});
}
} else {
- this.log.warn('Unexpected type for selected element', this.selectedNode);
+ this.log.warn('Unexpected type for selected element', selectedNode);
}
}
}
@@ -231,6 +286,12 @@
return SHOWMETERVIEW;
case 'showPipeConfView':
return SHOWPIPECONFVIEW;
+ case 'relatedIntents':
+ return RELATEDINTENTS;
+ case 'createHostToHostFlow':
+ return CREATEHOSTTOHOSTFLOW;
+ case 'createMultiSourceFlow':
+ return CREATEMULTISOURCEFLOW;
default:
return <ButtonAttrs>{
gid: btnName,
@@ -244,19 +305,46 @@
* e.g. if params are 'meter', 'device' and 'null:0000000000001' then the
* navigation URL will become "http://localhost:4200/#/meter?devId=null:0000000000000002"
*
+ * When multiple hosts are selected other actions have to be accommodated
+ *
* @param path The path to navigate to
* @param navPath The parameter name to use
* @param selId the parameter value to use
*/
- navto(path: string, navPath: string, selId: string): void {
- this.log.debug('navigate to', path, 'for', navPath, '=', selId);
- // Special case until it's fixed
- if (selId) {
+ navto(path: string): void {
+ this.log.debug('navigate to', path, 'for',
+ this.showDetails.navPath, '=', this.showDetails.id);
+
+ const ids: string[] = [];
+ Object.values(this.showDetails.propValues).forEach((v) => ids.push(v));
+ if (path === 'relatedIntents' && this.showDetails.id === 'multiple') {
+ this.wss.sendEvent('requestRelatedIntents', {
+ 'ids': ids,
+ 'hover': ''
+ });
+
+ } else if (path === 'create_h2h_flow' && this.showDetails.id === 'multiple') {
+ this.wss.sendEvent('addHostIntent', {
+ 'one': ids[0],
+ 'two': ids[1],
+ 'ids': ids
+ });
+
+ } else if (path === 'create_msrc_flow' && this.showDetails.id === 'multiple') {
+ // Should only happen when there are 3 or more ids
+ this.wss.sendEvent('addMultiSourceIntent', {
+ 'src': ids.slice(0, ids.length - 1),
+ 'dst': ids[ids.length - 1],
+ 'ids': ids
+ });
+
+ } else if (this.showDetails.id) {
+ let navPath = this.showDetails.navPath;
if (navPath === 'device') {
navPath = 'devId';
}
const queryPar: Params = {};
- queryPar[navPath] = selId;
+ queryPar[navPath] = this.showDetails.id;
this.router.navigate([path], { queryParams: queryPar });
}
}
@@ -265,8 +353,8 @@
* Read the LION bundle for Details panel and set up the lionFn
*/
doLion() {
- this.lionFn = this.lion.bundle('core.view.Flow');
-
+ this.lionFnTopo = this.lion.bundle('core.view.Topo');
+ this.lionFnFlow = this.lion.bundle('core.view.Flow');
}
}
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/panel/mapselector/mapselector.component.ts b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/panel/mapselector/mapselector.component.ts
index 5e4cf17..881e742 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/panel/mapselector/mapselector.component.ts
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/panel/mapselector/mapselector.component.ts
@@ -74,7 +74,7 @@
}
/**
- * Read the LION bundle for Details panel and set up the lionFn
+ * Read the LION bundle for panel and set up the lionFn
*/
doLion() {
this.lionFn = this.lion.bundle('core.view.Topo');
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology/topology.component.ts b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology/topology.component.ts
index 9f2a08b..10bc846 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology/topology.component.ts
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology/topology.component.ts
@@ -646,11 +646,12 @@
/**
* An event handler that updates the details panel as items are
* selected in the forcesvg layer
- * @param nodeOrLink the item to display details of
+ *
+ * @param nodesOrLink the item(s) to display details of
*/
- nodeSelected(nodeOrLink: UiElement) {
- this.details.ngOnChanges({'selectedNode':
- new SimpleChange(undefined, nodeOrLink, true)});
+ nodeSelected(nodesOrLink: UiElement[]) {
+ this.details.ngOnChanges({'selectedNodes':
+ new SimpleChange(undefined, nodesOrLink, true)});
}
/**