Update GUI2 topology host icons
Change-Id: I6d74de9df93b91eb9ca126ab54cbc2912c16caff
diff --git a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/svg/icon.service.ts b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/svg/icon.service.ts
index 6a900fb..5b801ab 100644
--- a/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/svg/icon.service.ts
+++ b/web/gui2-fw-lib/projects/gui2-fw-lib/src/lib/svg/icon.service.ts
@@ -42,6 +42,9 @@
['m_ports', 'm_ports'],
['m_switch', 'm_switch'],
+ ['m_roadm', 'm_roadm'],
+ ['m_router', 'm_router'],
+ ['m_endstation', 'm_endstation'],
['topo', 'topo'],
['bird', 'bird'],
diff --git a/web/gui2/package-lock.json b/web/gui2/package-lock.json
index 7cf1766..9e975be 100644
--- a/web/gui2/package-lock.json
+++ b/web/gui2/package-lock.json
@@ -4705,7 +4705,7 @@
},
"fm-gui2-lib": {
"version": "file:../../apps/faultmanagement/fm-gui2-lib/dist/fm-gui2-lib/fm-gui2-lib-2.0.0.tgz",
- "integrity": "sha512-AYRLoCF5jSYYAvi6fYJCepKtCm9Woregjte79YTQvgzL/+2AvTtXf9m2ezj/wmUnZOfFH6wTqVdW1OLzK/TQiQ==",
+ "integrity": "sha512-4t2yYPn5gA2+2UIJvecu1konQkWe67giLToloF23LmbjKFLgdxOslL22hL3lpvIHUr2xNmKAO0zUt10vQFRS2w==",
"requires": {
"tslib": "1.9.3"
}
@@ -5560,7 +5560,7 @@
},
"gui2-fw-lib": {
"version": "file:../gui2-fw-lib/dist/gui2-fw-lib/gui2-fw-lib-2.0.0.tgz",
- "integrity": "sha512-wAhrApE0c7FWqRDgB/8itVppmsd1Z4T+j8woxmDzkYwIkEqSvc7pvF3+QIOF0IQDkRCU2P31Ms1AtZ5cQliXTA==",
+ "integrity": "sha512-Yzq0PJtfLjiEM0/U9MYD17RMAEYrnbj+m24urMEJwgOZcn9502ZcmlJInl04gAxxGtU0GxlScAYh9TfxW1ZpCw==",
"requires": {
"tslib": "1.9.3"
}
diff --git a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/forcesvg.component.html b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/forcesvg.component.html
index f02b3a1..1f1d757 100644
--- a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/forcesvg.component.html
+++ b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/forcesvg.component.html
@@ -16,20 +16,55 @@
<svg:g class="topo2-force" xmlns:svg="http://www.w3.org/2000/svg">
<svg:g id="new-zoom-layer">
<svg:g class="topo2-links">
- <svg:g onos-linkvisual [link]="link" *ngFor="let link of regionData.links">
+ <!-- Template explanation: Creates an SVG Group and in
+ line 1) use the svg component onos-linkvisual, setting it's link
+ Input parameter to the link item from the next line
+ line 2) Use the built in NgFor directive to iterate through the
+ set of links filtered by the filteredLinks() function.
+ -->
+ <svg:g onos-linkvisual [link]="link"
+ *ngFor="let link of filteredLinks()">
</svg:g>
</svg:g>
<svg:g class="topo2-linkLabels" />
<svg:g class="topo2-numLinkLabels" />
<svg:g class="topo2-nodes">
+ <!-- Template explanation - create an SVG Group and
+ line 1) use the svg component onos-devicenodesvg, setting it's device
+ Input parameter to the device item from the next line
+ line 2) Use the built in NgFor directive to iterate through all
+ of the devices in the chosen layer index. The current iteration
+ is in the device variable
+ line 3) Use the onosDraggable directive and pass this device in to
+ its draggableNode Input parameter and setting the draggableInGraph
+ Input parameter to 'graph'
+ line 4) when the onos-devicenodesvg component emits the selectedEvent
+ call the updateSelected() method of this (forcesvg) component
+ -->
<svg:g onos-devicenodesvg [device]="device"
*ngFor="let device of regionData.devices[visibleLayerIdx()]"
onosDraggableNode [draggableNode]="device" [draggableInGraph]="graph"
(selectedEvent)="updateSelected($event)">
</svg:g>
- <svg:g onos-hostnodesvg [host]="host"
- *ngFor="let host of regionData.hosts[visibleLayerIdx()]"
- onosDraggableNode [draggableNode]="host" [draggableInGraph]="graph">
+ <!-- Template explanation - only display the hosts if 'showHosts' is set true -->
+ <svg:g *ngIf="showHosts">
+ <!-- Template explanation - create an SVG Group and
+ line 1) use the svg component onos-hostnodesvg, setting it's host
+ Input parameter to the host item from the next line
+ line 2) Use the built in NgFor directive to iterate through all
+ of the hosts in the chosen layer index. The current iteration
+ is in the 'host' variable
+ line 3) Use the onosDraggable directive and pass this host in to
+ its draggableNode Input parameter and setting the draggableInGraph
+ Input parameter to 'graph'
+ line 4) when the onos-hostnodesvg component emits the selectedEvent
+ call the updateSelected() method of this (forcesvg) component
+ -->
+ <svg:g onos-hostnodesvg [host]="host"
+ *ngFor="let host of regionData.hosts[visibleLayerIdx()]"
+ onosDraggableNode [draggableNode]="host" [draggableInGraph]="graph"
+ (selectedEvent)="updateSelected($event)">
+ </svg:g>
</svg:g>
<svg:g onos-subregionnodesvg [subRegion]="subRegion"
*ngFor="let subRegion of regionData.subregions"
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'));
}
}
diff --git a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/models/force-directed-graph.ts b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/models/force-directed-graph.ts
index 3db25ae..46d3ba7 100644
--- a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/models/force-directed-graph.ts
+++ b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/models/force-directed-graph.ts
@@ -21,7 +21,7 @@
const FORCES = {
LINKS: 1 / 50,
COLLISION: 1,
- CHARGE: -1
+ CHARGE: -10
};
export interface Options {
diff --git a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/models/node.ts b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/models/node.ts
index d19de88..a7a7cb1 100644
--- a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/models/node.ts
+++ b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/models/node.ts
@@ -23,7 +23,7 @@
} from './regions';
/**
- * Toggle state for how labels should be displayed
+ * Toggle state for how device labels should be displayed
*/
export enum LabelToggle {
NONE,
@@ -31,6 +31,9 @@
NAME
}
+/**
+ * Add the method 'next()' to the LabelToggle enum above
+ */
export namespace LabelToggle {
export function next(current: LabelToggle) {
if (current === LabelToggle.NONE) {
@@ -44,6 +47,33 @@
}
/**
+ * Toggle state for how host labels should be displayed
+ */
+export enum HostLabelToggle {
+ NONE,
+ NAME,
+ IP,
+ MAC
+}
+
+/**
+ * Add the method 'next()' to the HostLabelToggle enum above
+ */
+export namespace HostLabelToggle {
+ export function next(current: HostLabelToggle) {
+ if (current === HostLabelToggle.NONE) {
+ return HostLabelToggle.NAME;
+ } else if (current === HostLabelToggle.NAME) {
+ return HostLabelToggle.IP;
+ } else if (current === HostLabelToggle.IP) {
+ return HostLabelToggle.MAC;
+ } else if (current === HostLabelToggle.MAC) {
+ return HostLabelToggle.NONE;
+ }
+ }
+}
+
+/**
* model of the topo2CurrentRegion device props from Device below
*/
export interface DeviceProps {
diff --git a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.html b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.html
index d00e906..e329874 100644
--- a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.html
+++ b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.html
@@ -16,7 +16,7 @@
<svg:g xmlns:svg="http://www.w3.org/2000/svg" #devSvg
[attr.transform]="'translate(' + device?.x + ',' + device?.y + '), scale(' + scale + ')'"
[ngClass]="['node', 'device', device.online?'online':'', selected?'selected':'']"
- (click)="toggleSelected()">
+ (click)="toggleSelected(device)">
<svg:rect class="node-container" x="-18" y="-18" width="36" height="36">
<!--[attr.width]="devText.getComputedTextLength()+36" -->
<!--[@deviceLabelToggle]="{ value: labelToggle, params: {txtWidth: devSvg.getBBox().width+'px' }}">-->
@@ -26,5 +26,9 @@
<svg:text #devText text-anchor="start" y="0.3em" x="22" [ngStyle]="{'transform': 'scale(' + scale + ')'}">
{{ labelToggle == 0 ? '': labelToggle == 1 ? device.id:device.props.name }}
</svg:text>
- <svg:use xlink:href="#m_switch" width="36" height="36" x="-18" y="-18"></svg:use>
+ <!-- It's not possible to drive the following xref dynamically -->
+ <svg:use *ngIf="device.type == 'switch'" xlink:href="#m_switch" width="36" height="36" x="-18" y="-18">
+ </svg:use>
+ <svg:use *ngIf="device.type == 'roadm'" xlink:href="#m_roadm" width="36" height="36" x="-18" y="-18">
+ </svg:use>
</svg:g>
\ No newline at end of file
diff --git a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.ts b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.ts
index bec4529..036fc08 100644
--- a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.ts
+++ b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.ts
@@ -22,8 +22,9 @@
SimpleChanges,
ViewChild
} from '@angular/core';
-import {Device, LabelToggle} from '../../models';
+import {Node, Device, LabelToggle} from '../../models';
import {LogService} from 'gui2-fw-lib';
+import {NodeVisual} from '../nodevisual';
/**
* The Device node in the force graph
@@ -50,19 +51,18 @@
// ])
// ]
})
-export class DeviceNodeSvgComponent implements OnChanges {
+export class DeviceNodeSvgComponent extends NodeVisual implements OnChanges {
@Input() device: Device;
@Input() scale: number = 1.0;
@Input() labelToggle: LabelToggle = LabelToggle.NONE;
- selected: boolean;
- @Output() selectedEvent = new EventEmitter<string>();
+ @Output() selectedEvent = new EventEmitter<Node>();
textWidth: number = 36;
@ViewChild('idTxt') idTxt: ElementRef;
-
constructor(
protected log: LogService,
private ref: ChangeDetectorRef
) {
+ super();
}
/**
@@ -84,18 +84,4 @@
}
this.ref.markForCheck();
}
-
- toggleSelected() {
- this.selected = !this.selected;
- if (this.selected) {
- this.selectedEvent.emit(this.device.id);
- } else {
- this.selectedEvent.emit();
- }
- }
-
- deselect() {
- this.selected = false;
- }
-
}
diff --git a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.css b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.css
index 60cedab..92a114f 100644
--- a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.css
+++ b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.css
@@ -17,4 +17,27 @@
/*
ONOS GUI -- Topology View (forces host visual) -- CSS file
- */
\ No newline at end of file
+ */
+.node.host text {
+ stroke: none;
+ font-size: 13px;
+ fill: #846;
+}
+
+.node.host circle {
+ stroke: #a3a596;
+ fill: #e0dfd6;
+}
+
+.node.host.selected > circle {
+ stroke-width: 2.0;
+ stroke: #009fdb;
+}
+
+.node.host use {
+ fill: #3c3a3a;
+}
+
+.node.host rect {
+ fill: #ffffff;
+}
\ No newline at end of file
diff --git a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.html b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.html
index 8626cf5..9cac8b0 100644
--- a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.html
+++ b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.html
@@ -13,11 +13,11 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<svg:g xmlns:svg="http://www.w3.org/2000/svg" [attr.transform]="'translate(' + host?.x + ',' + host?.y + ')'">>
- <svg:circle
- cx="0"
- cy="0"
- r="5">
- </svg:circle>
- <svg:text>{{host?.id}}</svg:text>
+<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)">
+ <svg:circle r="15"></svg:circle>
+ <svg:use xlink:href="#m_endstation" width="22.5" height="22.5" x="-11.25" y="-11.25" style="transform: scale(1);"></svg:use>
+ <svg:text *ngIf="labelToggle != 0" dy="24" text-anchor="middle" style="transform: scale(1);">{{hostName()}}</svg:text>
</svg:g>
\ No newline at end of file
diff --git a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.ts b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.ts
index 4b1f4ab..0720d0e 100644
--- a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.ts
+++ b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/hostnodesvg/hostnodesvg.component.ts
@@ -15,32 +15,37 @@
*/
import {
Component,
+ EventEmitter,
Input,
OnChanges,
+ Output,
SimpleChanges
} from '@angular/core';
-import { Host } from '../../models';
+import {Host, HostLabelToggle, Node} from '../../models';
import {LogService} from 'gui2-fw-lib';
+import {NodeVisual} from '../nodevisual';
/**
* The Host node in the force graph
*
- * Note 1: here the selector is given square brackets [] so that it can be
+ * Note: here the selector is given square brackets [] so that it can be
* inserted in SVG element like a directive
- * Note 2: the selector is exactly the same as the @Input alias to make this
- * directive trick work
*/
@Component({
selector: '[onos-hostnodesvg]',
templateUrl: './hostnodesvg.component.html',
styleUrls: ['./hostnodesvg.component.css']
})
-export class HostNodeSvgComponent implements OnChanges {
+export class HostNodeSvgComponent extends NodeVisual implements OnChanges {
@Input() host: Host;
+ @Input() scale: number = 1.0;
+ @Input() labelToggle: HostLabelToggle = HostLabelToggle.IP;
+ @Output() selectedEvent = new EventEmitter<Node>();
constructor(
protected log: LogService
) {
+ super();
}
ngOnChanges(changes: SimpleChanges) {
@@ -48,5 +53,23 @@
this.host.x = 0;
this.host.y = 0;
}
+
+ if (changes['labelToggle']) {
+ this.labelToggle = changes['labelToggle'].currentValue;
+ }
+ // this.ref.markForCheck();
+ }
+
+ hostName(): string {
+ if (this.host === undefined) {
+ return undefined;
+ } else if (this.labelToggle === HostLabelToggle.IP) {
+ return this.host.ips.join(',');
+ } else if (this.labelToggle === HostLabelToggle.MAC) {
+ return this.host.id;
+ } else {
+ return this.host.id; // Todo - replace with a friendly name
+ }
+
}
}
diff --git a/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/nodevisual.ts b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/nodevisual.ts
new file mode 100644
index 0000000..677745d
--- /dev/null
+++ b/web/gui2/src/main/webapp/app/view/topology/layer/forcesvg/visuals/nodevisual.ts
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * 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.
+ */
+import {EventEmitter} from '@angular/core';
+import {Node} from '../models';
+
+export abstract class NodeVisual {
+ selected: boolean;
+ selectedEvent = new EventEmitter<Node>();
+
+ toggleSelected(node: Node) {
+ this.selected = !this.selected;
+ if (this.selected) {
+ this.selectedEvent.emit(node);
+ } else {
+ this.selectedEvent.emit();
+ }
+ }
+
+ deselect() {
+ this.selected = false;
+ }
+}
diff --git a/web/gui2/src/main/webapp/app/view/topology/topology/topology.component.ts b/web/gui2/src/main/webapp/app/view/topology/topology/topology.component.ts
index d4decb0..433f749 100644
--- a/web/gui2/src/main/webapp/app/view/topology/topology/topology.component.ts
+++ b/web/gui2/src/main/webapp/app/view/topology/topology/topology.component.ts
@@ -16,7 +16,7 @@
import {
Component,
OnDestroy,
- OnInit,
+ OnInit, SimpleChange,
ViewChild
} from '@angular/core';
import * as d3 from 'd3';
@@ -38,7 +38,7 @@
import {BackgroundSvgComponent} from '../layer/backgroundsvg/backgroundsvg.component';
import {ForceSvgComponent} from '../layer/forcesvg/forcesvg.component';
import {TopologyService} from '../topology.service';
-import {Node} from '../layer/forcesvg/models';
+import {HostLabelToggle, LabelToggle, Node} from '../layer/forcesvg/models';
/**
* ONOS GUI Topology View
@@ -98,6 +98,23 @@
this.log.debug('Topology component constructed');
}
+ private static deviceLabelFlashMessage(index: number): string {
+ switch (index) {
+ case 0: return 'Hide device labels';
+ case 1: return 'Show friendly device labels';
+ case 2: return 'Show device ID labels';
+ }
+ }
+
+ private static hostLabelFlashMessage(index: number): string {
+ switch (index) {
+ case 0: return 'Hide host labels';
+ case 1: return 'Show friendly host labels';
+ case 2: return 'Show host IP labels';
+ case 3: return 'Show host MAC Address labels';
+ }
+ }
+
ngOnInit() {
this.bindCommands();
this.zoomer = this.createZoomer(<ZoomOpts>{
@@ -228,43 +245,22 @@
this.ps.setPrefs('topo2_prefs', this.prefsState);
}
- deviceLabelFlashMessage(index) {
- switch (index) {
- case 0: return 'Hide device labels';
- case 1: return 'Show friendly device labels';
- case 2: return 'Show device ID labels';
- }
- }
-
- hostLabelFlashMessage(index) {
- switch (index) {
- case 0: return 'Hide host labels';
- case 1: return 'Show friendly host labels';
- case 2: return 'Show host IP labels';
- case 3: return 'Show host MAC Address labels';
- }
- }
-
protected cycleDeviceLabels() {
- this.log.debug('Cycling device labels');
- // TODO: Reinstate with components
- this.force.updateDeviceLabelToggle();
- // let deviceLabelIndex = t2ps.get('dlbls') + 1;
- // let newDeviceLabelIndex = deviceLabelIndex % 3;
- //
- // t2ps.set('dlbls', newDeviceLabelIndex);
- // t2fs.updateNodes();
- // flash.flash(deviceLabelFlashMessage(newDeviceLabelIndex));
+ const old: LabelToggle = this.force.deviceLabelToggle;
+ const next = LabelToggle.next(old);
+ this.force.ngOnChanges({'deviceLabelToggle':
+ new SimpleChange(old, next, false)});
+ this.flashMsg = TopologyComponent.deviceLabelFlashMessage(next);
+ this.log.debug('Cycling device labels', old, next);
}
protected cycleHostLabels() {
- const hostLabelIndex = this.hostLabelIdx + 1;
- this.hostLabelIdx = hostLabelIndex % 4;
- this.flashMsg = this.hostLabelFlashMessage(this.hostLabelIdx);
- this.log.debug('Cycling host labels');
- // TODO: Reinstate with components
- // t2ps.set('hlbls', newHostLabelIndex);
- // t2fs.updateNodes();
+ const old: HostLabelToggle = this.force.hostLabelToggle;
+ const next = HostLabelToggle.next(old);
+ this.force.ngOnChanges({'hostLabelToggle':
+ new SimpleChange(old, next, false)});
+ this.flashMsg = TopologyComponent.hostLabelFlashMessage(next);
+ this.log.debug('Cycling host labels', old, next);
}
protected toggleBackground(token: KeysToken) {
@@ -346,11 +342,11 @@
}
protected toggleHosts() {
- // this.flashMsg = on ? 'Show': 'Hide', 'Hosts';
- this.log.debug('toggling hosts');
- // TODO: Reinstate with components
- // let on = t2rs.toggleHosts();
- // this.actionedFlashed(on ? 'Show': 'Hide', 'Hosts');
+ const old: boolean = this.force.showHosts;
+ const current = !this.force.showHosts;
+ this.force.ngOnChanges({'showHosts': new SimpleChange(old, current, false)});
+ this.flashMsg = (this.force.showHosts ? 'Show' : 'Hide') + ' Hosts';
+ this.log.debug('toggling hosts: ', this.force.showHosts ? 'Show' : 'Hide');
}
protected toggleOfflineDevices() {