Update GUI2 topology host icons
Change-Id: I6d74de9df93b91eb9ca126ab54cbc2912c16caff
diff --git a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/forcesvg.component.ts b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/forcesvg.component.ts
index 97c9e1e..1d6ebf4 100644
--- a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/forcesvg.component.ts
+++ b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/forcesvg.component.ts
@@ -22,21 +22,24 @@
Input,
OnChanges,
OnInit,
- Output, QueryList, SimpleChange,
- SimpleChanges, ViewChildren
+ Output,
+ QueryList,
+ SimpleChanges,
+ ViewChildren
} from '@angular/core';
import {IconService, LogService} from 'gui2-fw-lib';
import {
Device,
ForceDirectedGraph,
- Host,
+ Host, HostLabelToggle,
LabelToggle,
LayerType,
+ Node,
Region,
RegionLink,
SubRegion
} from './models';
-import {DeviceNodeSvgComponent} from './visuals';
+import {DeviceNodeSvgComponent, HostNodeSvgComponent} from './visuals';
/**
@@ -55,20 +58,19 @@
@Input() onosInstMastership: string = '';
@Input() visibleLayer: LayerType = LayerType.LAYER_DEFAULT;
@Output() linkSelected = new EventEmitter<RegionLink>();
- @Output() selectedNodeEvent = new EventEmitter<Device>();
+ @Output() selectedNodeEvent = new EventEmitter<Node>();
@Input() selectedLink: RegionLink = null;
- private graph: ForceDirectedGraph;
-
+ @Input() showHosts: boolean = false;
+ @Input() deviceLabelToggle: LabelToggle = LabelToggle.NONE;
+ @Input() hostLabelToggle: HostLabelToggle = HostLabelToggle.NONE;
@Input() regionData: Region = <Region>{devices: [ [], [], [] ], hosts: [ [], [], [] ], links: []};
+ private graph: ForceDirectedGraph;
private _options: { width, height } = { width: 800, height: 600 };
+ // 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
@ViewChildren(DeviceNodeSvgComponent) devices: QueryList<DeviceNodeSvgComponent>;
-
- @HostListener('window:resize', ['$event'])
- onResize(event) {
- this.graph.initSimulation(this.options);
- this.log.debug('Simulation reinit after resize', event);
- }
+ @ViewChildren(HostNodeSvgComponent) hosts: QueryList<HostNodeSvgComponent>;
constructor(
protected log: LogService,
@@ -80,16 +82,47 @@
}
/**
+ * Utility for extracting a node name from an endpoint string
+ * In some cases - have to remove the port number from the end of a device
+ * name
+ * @param endPtStr The end point name
+ */
+ private static extractNodeName(endPtStr: string): string {
+ const slash: number = endPtStr.indexOf('/');
+ if (slash === -1) {
+ return endPtStr;
+ } else {
+ const afterSlash = endPtStr.substr(slash + 1);
+ if (afterSlash === 'None') {
+ return endPtStr;
+ } else {
+ return endPtStr.substr(0, slash);
+ }
+ }
+ }
+
+ @HostListener('window:resize', ['$event'])
+ onResize(event) {
+ this.graph.initSimulation(this.options);
+ this.log.debug('Simulation reinit after resize', event);
+ }
+
+ /**
* After the component is initialized create the Force simulation
+ * The list of devices, hosts and links will not have been receieved back
+ * from the WebSocket yet as this time - they will be updated later through
+ * ngOnChanges()
*/
ngOnInit() {
// Receiving an initialized simulated graph from our custom d3 service
this.graph = new ForceDirectedGraph(this.options);
/** Binding change detection check on each tick
- * This along with an onPush change detection strategy should enforce checking only when relevant!
- * This improves scripting computation duration in a couple of tests I've made, consistently.
- * Also, it makes sense to avoid unnecessary checks when we are dealing only with simulations data binding.
+ * This along with an onPush change detection strategy should enforce
+ * checking only when relevant! This improves scripting computation
+ * duration in a couple of tests I've made, consistently. Also, it makes
+ * sense to avoid unnecessary checks when we are dealing only with
+ * simulations data binding.
*/
this.graph.ticker.subscribe((simulation) => {
// this.log.debug("Force simulation has ticked", simulation);
@@ -98,12 +131,16 @@
this.log.debug('ForceSvgComponent initialized - waiting for nodes and links');
this.is.loadIconDef('m_switch');
+ this.is.loadIconDef('m_roadm');
+ this.is.loadIconDef('m_router');
+ this.is.loadIconDef('m_endstation');
}
/**
- * When any one of the inputs get changed by a containing component, this gets called automatically
- * In addition this is called manually by topology.service when a response
- * is received from the WebSocket from the server
+ * When any one of the inputs get changed by a containing component, this
+ * gets called automatically. In addition this is called manually by
+ * topology.service when a response is received from the WebSocket from the
+ * server
*
* The Devices, Hosts and SubRegions are all added to the Node list for the simulation
* The Links are added to the Link list of the simulation.
@@ -132,12 +169,16 @@
// Associate the endpoints of each link with a real node
this.graph.links = [];
for (const linkIdx of Object.keys(this.regionData.links)) {
+ const epA = ForceSvgComponent.extractNodeName(
+ this.regionData.links[linkIdx].epA);
this.regionData.links[linkIdx].source =
this.graph.nodes.find((node) =>
- node.id === this.regionData.links[linkIdx].epA);
+ node.id === epA);
+ const epB = ForceSvgComponent.extractNodeName(
+ this.regionData.links[linkIdx].epB);
this.regionData.links[linkIdx].target =
this.graph.nodes.find((node) =>
- node.id === this.regionData.links[linkIdx].epB);
+ node.id === epB);
this.regionData.links[linkIdx].index = Number(linkIdx);
}
@@ -148,6 +189,28 @@
this.log.debug('ForceSvgComponent input changed',
this.graph.nodes.length, 'nodes,', this.graph.links.length, 'links');
}
+
+ if (changes['showHosts']) {
+ this.showHosts = changes['showHosts'].currentValue;
+ }
+
+ // Pass on the changes to device
+ if (changes['deviceLabelToggle']) {
+ this.deviceLabelToggle = changes['deviceLabelToggle'].currentValue;
+ this.devices.forEach((d) => {
+ d.ngOnChanges({'labelToggle': changes['deviceLabelToggle']});
+ });
+ }
+
+ // Pass on the changes to host
+ if (changes['hostLabelToggle']) {
+ this.hostLabelToggle = changes['hostLabelToggle'].currentValue;
+ this.hosts.forEach((h) => {
+ h.ngOnChanges({'labelToggle': changes['hostLabelToggle']});
+ });
+ }
+
+ this.ref.markForCheck();
}
/**
@@ -176,26 +239,36 @@
};
}
- updateDeviceLabelToggle() {
- this.devices.forEach((d) => {
- const old: LabelToggle = d.labelToggle;
- const next = LabelToggle.next(old);
- d.ngOnChanges({'labelToggle': new SimpleChange(old, next, false)});
- });
+ /**
+ * Iterate through all hosts and devices to deselect the previously selected
+ * node. The emit an event to the parent that lets it know the selection has
+ * changed.
+ * @param selectedNode the newly selected node
+ */
+ updateSelected(selectedNode: Node): void {
+ this.log.debug('Device selected', selectedNode);
+ 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());
+
+ this.selectedNodeEvent.emit(selectedNode);
}
- updateSelected(selectedNodeId: string): void {
- this.log.debug('Device selected', selectedNodeId);
- this.devices.filter((d) => d.device.id !== selectedNodeId).forEach((d) => {
- d.deselect();
- });
- const selectedDevice: DeviceNodeSvgComponent =
- (this.devices.find((d) => d.device.id === selectedNodeId));
- if (selectedDevice) {
- this.selectedNodeEvent.emit(selectedDevice.device);
- } else {
- this.selectedNodeEvent.emit();
- }
+ /**
+ * We want to filter links to show only those not related to hosts if the
+ * 'showHosts' flag has been switched off. If 'shwoHosts' is true, then
+ * display all links.
+ */
+ filteredLinks() {
+ return this.regionData.links.filter((h) =>
+ this.showHosts ||
+ ((<Host>h.source).nodeType !== 'host' &&
+ (<Host>h.target).nodeType !== 'host'));
}
}