GUI2 Display of mastership for devices
Change-Id: I13ed95d1a58d055aa913c69402541b87855c28c8
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 89923ae..af0ca2b 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
@@ -28,7 +28,7 @@
SimpleChanges,
ViewChildren
} from '@angular/core';
-import {LocMeta, LogService, MetaUi, WebSocketService, ZoomUtils} from 'gui2-fw-lib';
+import {LocMeta, LogService, MetaUi, SvgUtilService, WebSocketService, ZoomUtils} from 'gui2-fw-lib';
import {
Device,
DeviceProps,
@@ -256,6 +256,21 @@
}
/**
+ * If instance has a value then mute colors of devices not connected to it
+ * Otherwise if instance does not have a value unmute all
+ * @param instanceName name of the selected instance
+ */
+ changeInstSelection(instanceName: string) {
+ this.log.debug('Mastership changed', instanceName);
+ this.devices.filter((d) => d.device.master !== instanceName)
+ .forEach((d) => {
+ const isMuted = Boolean(instanceName);
+ d.ngOnChanges({'colorMuted': new SimpleChange(!isMuted, isMuted, true)});
+ }
+ );
+ }
+
+ /**
* If a node has a fixed location then assign it to fx and fy so
* that it doesn't get affected by forces
* @param graphNode The node whose location should be processed
@@ -397,6 +412,11 @@
if (changes.locationChanged) {
this.fixPosition(oldDevice);
}
+ const svgDevice: DeviceNodeSvgComponent =
+ this.devices.find((svgdevice) => svgdevice.device.id === subject);
+ svgDevice.ngOnChanges({'device':
+ new SimpleChange(<Device>{}, oldDevice, true)
+ });
}
} else {
this.log.warn('Device ', memo, ' - not yet implemented', data);
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 35c3fd4..fb0569b 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
@@ -67,7 +67,7 @@
overlaid on the above. This is the blue box, and its width and height does
not change
-->
- <svg:rect x="-16" y="-16" width="32" height="32" [ngStyle]="{'fill': panelColour(0)}">
+ <svg:rect x="-16" y="-16" width="32" height="32" [ngStyle]="{'fill': panelColor}">
</svg:rect>
<svg:path *ngIf="device.location && device.location.locType != 'none'"
d="M-15 12 v3 h5" style="stroke: white; stroke-width: 1; fill: none"></svg:path>
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.spec.ts b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.spec.ts
index b2f0592..994967d 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.spec.ts
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/layer/forcesvg/visuals/devicenodesvg/devicenodesvg.component.spec.ts
@@ -16,12 +16,13 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { DeviceNodeSvgComponent } from './devicenodesvg.component';
-import {FnService, IconService, LogService} from 'gui2-fw-lib';
+import {FnService, IconService, LogService, SvgUtilService} from 'gui2-fw-lib';
import {ActivatedRoute, Params} from '@angular/router';
import {of} from 'rxjs';
import {ChangeDetectorRef} from '@angular/core';
import {Device} from '../../models';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
+import {TopologyService} from '../../../../topology.service';
class MockActivatedRoute extends ActivatedRoute {
constructor(params: Params) {
@@ -34,6 +35,40 @@
loadIconDef() { }
}
+class MockSvgUtilService {
+
+ cat7() {
+ const tcid = 'd3utilTestCard';
+
+ function getColor(id, muted, theme) {
+ // NOTE: since we are lazily assigning domain ids, we need to
+ // get the color from all 4 scales, to keep the domains
+ // in sync.
+ const ln = '#5b99d2';
+ const lm = '#9ebedf';
+ const dn = '#5b99d2';
+ const dm = '#9ebedf';
+ if (theme === 'dark') {
+ return muted ? dm : dn;
+ } else {
+ return muted ? lm : ln;
+ }
+ }
+
+ return {
+ // testCard: testCard,
+ getColor: getColor,
+ };
+ }
+}
+
+class MockTopologyService {
+ public instancesIndex: Map<string, number>;
+ constructor() {
+ this.instancesIndex = new Map();
+ }
+}
+
describe('DeviceNodeSvgComponent', () => {
let fs: FnService;
let logServiceSpy: jasmine.SpyObj<LogService>;
@@ -71,6 +106,8 @@
{ provide: ActivatedRoute, useValue: ar },
{ provide: ChangeDetectorRef, useClass: ChangeDetectorRef },
{ provide: IconService, useClass: MockIconService },
+ { provide: SvgUtilService, useClass: MockSvgUtilService },
+ { provide: TopologyService, useClass: MockTopologyService },
{ provide: 'Window', useValue: windowMock },
]
})
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 d40f413..9c246d9 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
@@ -19,7 +19,7 @@
Component,
EventEmitter,
Input,
- OnChanges, Output,
+ OnChanges, OnInit, Output,
SimpleChanges,
} from '@angular/core';
import {Device, LabelToggle, UiElement} from '../../models';
@@ -27,6 +27,7 @@
import {NodeVisual, SelectedEvent} from '../nodevisual';
import {animate, state, style, transition, trigger} from '@angular/animations';
import {LocationType} from '../../../backgroundsvg/backgroundsvg.component';
+import {TopologyService} from '../../../../topology.service';
/**
* The Device node in the force graph
@@ -64,21 +65,30 @@
])
]
})
-export class DeviceNodeSvgComponent extends NodeVisual implements OnChanges {
+export class DeviceNodeSvgComponent extends NodeVisual implements OnInit, OnChanges {
@Input() device: Device;
@Input() scale: number = 1.0;
@Input() labelToggle: LabelToggle.Enum = LabelToggle.Enum.NONE;
+ @Input() colorMuted: boolean = false;
+ @Input() colorTheme: string = 'light';
@Output() selectedEvent = new EventEmitter<SelectedEvent>();
textWidth: number = 36;
+ panelColor: string = '#9ebedf';
+
constructor(
protected log: LogService,
private is: IconService,
protected sus: SvgUtilService,
+ protected ts: TopologyService,
private ref: ChangeDetectorRef
) {
super();
}
+ ngOnInit(): void {
+ this.panelColor = this.panelColour();
+ }
+
/**
* Called by parent (forcesvg) when a change happens
*
@@ -92,6 +102,13 @@
this.device.x = 0;
this.device.y = 0;
}
+ // The master might have changed - recalculate color
+ this.panelColor = this.panelColour();
+ }
+
+ if (changes['colorMuted']) {
+ this.colorMuted = changes['colorMuted'].currentValue;
+ this.panelColor = this.panelColour();
}
this.ref.markForCheck();
}
@@ -137,7 +154,8 @@
* Get a colour for the banner of the nth panel
* @param idx The index of the panel (0-6)
*/
- panelColour(idx: number): string {
- return this.sus.cat7().getColor(idx, false, '');
+ panelColour(): string {
+ const idx = this.ts.instancesIndex.get(this.device.master);
+ return this.sus.cat7().getColor(idx, this.colorMuted, this.colorTheme);
}
}
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/panel/instance/instance.component.html b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/panel/instance/instance.component.html
index f5a2859..9f2ee1a 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/panel/instance/instance.component.html
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/panel/instance/instance.component.html
@@ -15,7 +15,7 @@
-->
<div id="topo-p-instance" class="floatpanel" [ngStyle]="{'left': '20px', 'top':divTopPx+'px', 'width': (onosInstances.length * 170)+'px', 'height': '85px'}" [@instancePanelState]="on">
<div *ngFor="let inst of onosInstances | keyvalue ; let i=index"
- [ngClass]="['onosInst', inst.value.online?'online':'', inst.value.ready? 'ready': '', mastership?'mastership':'', 'affinity']"
+ [ngClass]="['onosInst', inst.value.online?'online':'', inst.value.ready? 'ready': '', mastership===inst.value.id?'mastership':'', 'affinity']"
(click)="chooseMastership(inst.value.id)">
<svg xmlns="http://www.w3.org/2000/svg" width="170" height="85" viewBox="0 0 170 85">
<!-- The following blue-glow effect is applied (through CSS) when mastership style is activated on a rectangle -->
@@ -37,4 +37,4 @@
<use *ngIf="inst.value.uiAttached" width="24" height="24" class="glyph overlay badgeIcon uiBadge" xlink:href="#uiAttached" transform="translate(14,54)"></use>
</svg>
</div>
-</div>
\ No newline at end of file
+</div>
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/panel/instance/instance.component.ts b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/panel/instance/instance.component.ts
index 70cbb1f..1ae8de4 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/panel/instance/instance.component.ts
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/panel/instance/instance.component.ts
@@ -17,7 +17,7 @@
Component,
Input,
Output,
- EventEmitter
+ EventEmitter, OnChanges, SimpleChanges
} from '@angular/core';
import { animate, state, style, transition, trigger } from '@angular/animations';
import {
@@ -71,11 +71,11 @@
])
]
})
-export class InstanceComponent extends PanelBaseImpl {
+export class InstanceComponent extends PanelBaseImpl implements OnChanges {
+ @Input() onosInstances: Instance[] = [];
@Input() divTopPx: number = 100;
@Input() on: boolean = false; // Override the parent class attribute
@Output() mastershipEvent = new EventEmitter<string>();
- public onosInstances: Array<Instance>;
public mastership: string;
lionFn; // Function
@@ -87,7 +87,6 @@
private lion: LionService
) {
super(fs, log);
- this.onosInstances = <Array<Instance>>[];
if (this.lion.ubercache.length === 0) {
this.lionFn = this.dummyLion;
@@ -98,6 +97,12 @@
this.log.debug('InstanceComponent constructed');
}
+ ngOnChanges(changes: SimpleChanges): void {
+ if (changes['onosInstances']) {
+ this.onosInstances = <Instance[]>changes['onosInstances'].currentValue;
+ }
+ }
+
/**
* Get a colour for the banner of the nth panel
* @param idx The index of the panel (0-6)
@@ -113,7 +118,7 @@
*/
chooseMastership(instId: string): void {
if (this.mastership === instId) {
- this.mastership = '';
+ this.mastership = undefined;
} else {
this.mastership = instId;
}
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology.service.ts b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology.service.ts
index 304be9e..f2a1f60 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology.service.ts
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology.service.ts
@@ -17,7 +17,7 @@
import {
LogService, WebSocketService,
} from 'gui2-fw-lib';
-import { InstanceComponent } from './panel/instance/instance.component';
+import {Instance, InstanceComponent} from './panel/instance/instance.component';
import { BackgroundSvgComponent } from './layer/backgroundsvg/backgroundsvg.component';
import { ForceSvgComponent } from './layer/forcesvg/forcesvg.component';
import {
@@ -34,11 +34,13 @@
private handlers: string[] = [];
private openListener: any;
+ public instancesIndex: Map<string, number>;
constructor(
protected log: LogService,
protected wss: WebSocketService
) {
+ this.instancesIndex = new Map();
this.log.debug('TopologyService constructed');
}
@@ -50,7 +52,14 @@
this.wss.bindHandlers(new Map<string, (data) => void>([
['topo2AllInstances', (data) => {
this.log.debug('Instances updated through WSS as topo2AllInstances', data);
- instance.onosInstances = data.members;
+ instance.ngOnChanges(
+ {'onosInstances': new SimpleChange({}, data.members, true)});
+
+ // Also generate an index locally of the instances
+ // needed so that devices can be coloured by instance
+ this.instancesIndex.clear();
+ (<Instance[]>data.members).forEach((inst, idx) => this.instancesIndex.set(inst.id, idx));
+ this.log.debug('Created local index of instances', this.instancesIndex);
}
],
['topo2CurrentLayout', (data) => {
diff --git a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology/topology.component.html b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology/topology.component.html
index e7425d1..e49ae9e 100644
--- a/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology/topology.component.html
+++ b/web/gui2-topo-lib/projects/gui2-topo-lib/src/lib/topology/topology.component.html
@@ -23,7 +23,7 @@
These are referenced inside the typescript by @ViewChild and their label
-->
<onos-instance #instance [divTopPx]="80"
- (mastershipEvent)="force.onosInstMastership = $event"
+ (mastershipEvent)="force.changeInstSelection($event)"
[on]="prefsState.insts">
</onos-instance>
<onos-summary #summary [on]="prefsState.summary"></onos-summary>