blob: 750162fc6c88a997b72150b881b4ec6b1e6afc1c [file] [log] [blame]
Sean Condonf4f54a12018-10-10 23:25:46 +01001/*
Sean Condon91481822019-01-01 13:56:14 +00002 * Copyright 2019-present Open Networking Foundation
Sean Condonf4f54a12018-10-10 23:25:46 +01003 *
4 * Licensed under the Apache License, Version 2.0 (the 'License');
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an 'AS IS' BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Sean Condon0c577f62018-11-18 22:40:05 +000016import {
17 Component,
18 OnDestroy,
Sean Condon021f0fa2018-12-06 23:31:11 -080019 OnInit, SimpleChange,
Sean Condon0c577f62018-11-18 22:40:05 +000020 ViewChild
21} from '@angular/core';
Sean Condon55c30532018-10-29 12:26:57 +000022import * as d3 from 'd3';
Sean Condonf4f54a12018-10-10 23:25:46 +010023import {
Sean Condon91481822019-01-01 13:56:14 +000024 FnService, IconService,
Sean Condon0c577f62018-11-18 22:40:05 +000025 KeysService,
Sean Condon91481822019-01-01 13:56:14 +000026 KeysToken, LionService,
Sean Condon0c577f62018-11-18 22:40:05 +000027 LogService,
28 PrefsService,
29 SvgUtilService,
30 WebSocketService,
Sean Condonf4f54a12018-10-10 23:25:46 +010031} from 'gui2-fw-lib';
Sean Condon0c577f62018-11-18 22:40:05 +000032import {InstanceComponent} from '../panel/instance/instance.component';
Sean Condon0c577f62018-11-18 22:40:05 +000033import {DetailsComponent} from '../panel/details/details.component';
34import {BackgroundSvgComponent} from '../layer/backgroundsvg/backgroundsvg.component';
35import {ForceSvgComponent} from '../layer/forcesvg/forcesvg.component';
36import {TopologyService} from '../topology.service';
Sean Condon91481822019-01-01 13:56:14 +000037import {
38 HostLabelToggle,
39 LabelToggle,
40 UiElement
41} from '../layer/forcesvg/models';
Sean Condonb2c483c2019-01-16 20:28:55 +000042import {
43 INSTANCE_TOGGLE, SUMMARY_TOGGLE, DETAILS_TOGGLE,
44 HOSTS_TOGGLE, OFFLINE_TOGGLE, PORTS_TOGGLE,
45 BKGRND_TOGGLE, CYCLELABELS_BTN, CYCLEHOSTLABEL_BTN,
46 RESETZOOM_BTN, EQMASTER_BTN,
Sean Condon0d064ec2019-02-04 21:53:53 +000047 CANCEL_TRAFFIC, ALL_TRAFFIC, QUICKHELP_BTN, BKGRND_SELECT
Sean Condonb2c483c2019-01-16 20:28:55 +000048} from '../panel/toolbar/toolbar.component';
Sean Condon50855cf2018-12-23 15:37:42 +000049import {TrafficService} from '../traffic.service';
Sean Condon91481822019-01-01 13:56:14 +000050import {ZoomableDirective} from '../layer/zoomable.directive';
Sean Condon0d064ec2019-02-04 21:53:53 +000051import {MapObject} from '../layer/maputils';
Sean Condonf4f54a12018-10-10 23:25:46 +010052
Sean Condonb2c483c2019-01-16 20:28:55 +000053const TOPO2_PREFS = 'topo2_prefs';
Sean Condon0d064ec2019-02-04 21:53:53 +000054const TOPO_MAPID_PREFS = 'topo_mapid';
55
Sean Condonb2c483c2019-01-16 20:28:55 +000056const PREF_BG = 'bg';
57const PREF_DETAIL = 'detail';
58const PREF_DLBLS = 'dlbls';
59const PREF_HLBLS = 'hlbls';
60const PREF_HOSTS = 'hosts';
61const PREF_INSTS = 'insts';
62const PREF_OFFDEV = 'offdev';
63const PREF_PORTHL = 'porthl';
64const PREF_SUMMARY = 'summary';
65const PREF_TOOLBAR = 'toolbar';
66
67/**
Sean Condon0d064ec2019-02-04 21:53:53 +000068 * Model of the topo2_prefs object - this is a subset of the overall Prefs returned
Sean Condonb2c483c2019-01-16 20:28:55 +000069 * by the server
70 */
71export interface Topo2Prefs {
72 bg: number;
73 detail: number;
74 dlbls: number;
75 hlbls: number;
76 hosts: number;
77 insts: number;
78 offdev: number;
79 porthl: number;
80 spr: number;
81 ovid: string;
82 summary: number;
83 toolbar: number;
84}
85
Sean Condonf4f54a12018-10-10 23:25:46 +010086/**
87 * ONOS GUI Topology View
88 *
89 * This Topology View component is the top level component in a hierarchy that
90 * comprises the whole Topology View
91 *
92 * There are three main parts (panels, graphical and breadcrumbs)
93 * The panel hierarchy
94 * |-- Instances Panel (shows ONOS instances)
95 * |-- Summary Panel (summary of ONOS)
96 * |-- Toolbar Panel (the toolbar)
97 * |-- Details Panel (when a node is selected in the Force graphical view (see below))
98 *
99 * The graphical hierarchy contains
100 * Topology (this)
101 * |-- No Devices Connected (only of there are no nodes to show)
102 * |-- Zoom Layer (everything beneath this can be zoomed and panned)
103 * |-- Background (container for any backgrounds - can be toggled on and off)
104 * |-- Map
105 * |-- Forces (all of the nodes and links laid out by a d3.force simulation)
106 *
107 * The breadcrumbs
108 * |-- Breadcrumb (in region view a way of navigating back up through regions)
109 */
110@Component({
111 selector: 'onos-topology',
112 templateUrl: './topology.component.html',
113 styleUrls: ['./topology.component.css']
114})
Sean Condonaa4366d2018-11-02 14:29:01 +0000115export class TopologyComponent implements OnInit, OnDestroy {
116 // These are references to the components inserted in the template
Sean Condonf4f54a12018-10-10 23:25:46 +0100117 @ViewChild(InstanceComponent) instance: InstanceComponent;
Sean Condonf4f54a12018-10-10 23:25:46 +0100118 @ViewChild(DetailsComponent) details: DetailsComponent;
Sean Condonaa4366d2018-11-02 14:29:01 +0000119 @ViewChild(BackgroundSvgComponent) background: BackgroundSvgComponent;
120 @ViewChild(ForceSvgComponent) force: ForceSvgComponent;
Sean Condon91481822019-01-01 13:56:14 +0000121 @ViewChild(ZoomableDirective) zoomDirective: ZoomableDirective;
Sean Condonf4f54a12018-10-10 23:25:46 +0100122
123 flashMsg: string = '';
Sean Condonb2c483c2019-01-16 20:28:55 +0000124 // These are used as defaults if nothing is set on the server
125 prefsState: Topo2Prefs = <Topo2Prefs>{
126 bg: 0,
127 detail: 1,
128 dlbls: 0,
129 hlbls: 2,
130 hosts: 0,
131 insts: 1,
132 offdev: 1,
133 ovid: 'traffic', // default to traffic overlay
134 porthl: 1,
135 spr: 0,
136 summary: 1,
137 toolbar: 0,
138 };
Sean Condon0d064ec2019-02-04 21:53:53 +0000139
140 mapIdState: MapObject = <MapObject>{
141 id: undefined,
142 scale: 1.0
143 };
144 mapSelShown: boolean = false;
Sean Condon91481822019-01-01 13:56:14 +0000145 lionFn; // Function
Sean Condon55c30532018-10-29 12:26:57 +0000146
Sean Condonf4f54a12018-10-10 23:25:46 +0100147 constructor(
148 protected log: LogService,
149 protected fs: FnService,
150 protected ks: KeysService,
151 protected sus: SvgUtilService,
152 protected ps: PrefsService,
Sean Condon55c30532018-10-29 12:26:57 +0000153 protected wss: WebSocketService,
Sean Condonaa4366d2018-11-02 14:29:01 +0000154 protected ts: TopologyService,
Sean Condon91481822019-01-01 13:56:14 +0000155 protected trs: TrafficService,
156 protected is: IconService,
157 private lion: LionService,
Sean Condonf4f54a12018-10-10 23:25:46 +0100158 ) {
Sean Condon91481822019-01-01 13:56:14 +0000159 if (this.lion.ubercache.length === 0) {
160 this.lionFn = this.dummyLion;
161 this.lion.loadCbs.set('topo-toolbar', () => this.doLion());
162 } else {
163 this.doLion();
164 }
Sean Condonf4f54a12018-10-10 23:25:46 +0100165
Sean Condon91481822019-01-01 13:56:14 +0000166 this.is.loadIconDef('bird');
167 this.is.loadIconDef('active');
168 this.is.loadIconDef('uiAttached');
169 this.is.loadIconDef('m_switch');
170 this.is.loadIconDef('m_roadm');
171 this.is.loadIconDef('m_router');
172 this.is.loadIconDef('m_uiAttached');
173 this.is.loadIconDef('m_endstation');
174 this.is.loadIconDef('m_ports');
175 this.is.loadIconDef('m_summary');
176 this.is.loadIconDef('m_details');
177 this.is.loadIconDef('m_map');
Sean Condon0d064ec2019-02-04 21:53:53 +0000178 this.is.loadIconDef('m_selectMap');
Sean Condon91481822019-01-01 13:56:14 +0000179 this.is.loadIconDef('m_cycleLabels');
180 this.is.loadIconDef('m_resetZoom');
181 this.is.loadIconDef('m_eqMaster');
182 this.is.loadIconDef('m_unknown');
183 this.is.loadIconDef('m_allTraffic');
184 this.is.loadIconDef('deviceTable');
185 this.is.loadIconDef('flowTable');
186 this.is.loadIconDef('portTable');
187 this.is.loadIconDef('groupTable');
188 this.is.loadIconDef('meterTable');
189 this.is.loadIconDef('triangleUp');
Sean Condonf4f54a12018-10-10 23:25:46 +0100190 this.log.debug('Topology component constructed');
191 }
192
Sean Condon91481822019-01-01 13:56:14 +0000193 /**
194 * Static functions must come before member variables
195 * @param index
196 */
Sean Condon021f0fa2018-12-06 23:31:11 -0800197 private static deviceLabelFlashMessage(index: number): string {
198 switch (index) {
Sean Condon91481822019-01-01 13:56:14 +0000199 case 0: return 'fl_device_labels_hide';
200 case 1: return 'fl_device_labels_show_friendly';
201 case 2: return 'fl_device_labels_show_id';
Sean Condon021f0fa2018-12-06 23:31:11 -0800202 }
203 }
204
205 private static hostLabelFlashMessage(index: number): string {
206 switch (index) {
Sean Condon91481822019-01-01 13:56:14 +0000207 case 0: return 'fl_host_labels_hide';
208 case 1: return 'fl_host_labels_show_friendly';
209 case 2: return 'fl_host_labels_show_ip';
210 case 3: return 'fl_host_labels_show_mac';
Sean Condon021f0fa2018-12-06 23:31:11 -0800211 }
212 }
213
Sean Condon91481822019-01-01 13:56:14 +0000214 /**
215 * Pass the list of Key Commands to the KeyService, and initialize the Topology
216 * Service - which communicates with through the WebSocket to the ONOS server
217 * to get the nodes and links.
218 */
Sean Condonf4f54a12018-10-10 23:25:46 +0100219 ngOnInit() {
220 this.bindCommands();
Sean Condonaa4366d2018-11-02 14:29:01 +0000221 // The components from the template are handed over to TopologyService here
222 // so that WebSocket responses can be passed back in to them
223 // The handling of the WebSocket call is delegated out to the Topology
224 // Service just to compartmentalize things a bit
225 this.ts.init(this.instance, this.background, this.force);
Sean Condonb2c483c2019-01-16 20:28:55 +0000226
227 this.ps.addListener((data) => this.prefsUpdateHandler(data));
228 this.prefsState = this.ps.getPrefs(TOPO2_PREFS, this.prefsState);
Sean Condon0d064ec2019-02-04 21:53:53 +0000229 this.mapIdState = this.ps.getPrefs(TOPO_MAPID_PREFS, this.mapIdState);
Sean Condonf4f54a12018-10-10 23:25:46 +0100230 this.log.debug('Topology component initialized');
231 }
232
Sean Condon91481822019-01-01 13:56:14 +0000233 /**
Sean Condonb2c483c2019-01-16 20:28:55 +0000234 * Callback function that's called whenever new Prefs are received from WebSocket
235 *
236 * Note: At present the backend server does not filter updated by logged in user,
237 * so you might get updates pertaining to a different user
238 */
239 prefsUpdateHandler(data: any): void {
240 // Extract the TOPO2 prefs from it
Sean Condon0d064ec2019-02-04 21:53:53 +0000241 if (data[TOPO2_PREFS]) {
242 this.prefsState = data[TOPO2_PREFS];
243 }
244 if (data[TOPO_MAPID_PREFS]) {
245 this.mapIdState = data[TOPO_MAPID_PREFS];
246 }
247 this.log.debug('Updated topo2 prefs', this.prefsState, this.mapIdState);
Sean Condonb2c483c2019-01-16 20:28:55 +0000248 }
249
250 /**
Sean Condon91481822019-01-01 13:56:14 +0000251 * When this component is being stopped, disconnect the TopologyService from
252 * the WebSocket
253 */
Sean Condonaa4366d2018-11-02 14:29:01 +0000254 ngOnDestroy() {
255 this.ts.destroy();
Sean Condonb2c483c2019-01-16 20:28:55 +0000256 this.ps.removeListener((data) => this.prefsUpdateHandler(data));
Sean Condonaa4366d2018-11-02 14:29:01 +0000257 this.log.debug('Topology component destroyed');
258 }
259
Sean Condon91481822019-01-01 13:56:14 +0000260 /**
261 * When ever a toolbar button is clicked, an event is sent up from toolbar
262 * component which is caught and passed on to here.
263 * @param name The name of the button that was clicked
264 */
265 toolbarButtonClicked(name: string) {
266 switch (name) {
Sean Condonb2c483c2019-01-16 20:28:55 +0000267 case INSTANCE_TOGGLE:
Sean Condon91481822019-01-01 13:56:14 +0000268 this.toggleInstancePanel();
269 break;
Sean Condonb2c483c2019-01-16 20:28:55 +0000270 case SUMMARY_TOGGLE:
Sean Condon91481822019-01-01 13:56:14 +0000271 this.toggleSummary();
272 break;
Sean Condonb2c483c2019-01-16 20:28:55 +0000273 case DETAILS_TOGGLE:
Sean Condon91481822019-01-01 13:56:14 +0000274 this.toggleDetails();
275 break;
Sean Condonb2c483c2019-01-16 20:28:55 +0000276 case HOSTS_TOGGLE:
Sean Condon91481822019-01-01 13:56:14 +0000277 this.toggleHosts();
278 break;
Sean Condonb2c483c2019-01-16 20:28:55 +0000279 case OFFLINE_TOGGLE:
Sean Condon91481822019-01-01 13:56:14 +0000280 this.toggleOfflineDevices();
281 break;
Sean Condonb2c483c2019-01-16 20:28:55 +0000282 case PORTS_TOGGLE:
Sean Condon91481822019-01-01 13:56:14 +0000283 this.togglePorts();
284 break;
Sean Condonb2c483c2019-01-16 20:28:55 +0000285 case BKGRND_TOGGLE:
Sean Condon91481822019-01-01 13:56:14 +0000286 this.toggleBackground();
287 break;
Sean Condon0d064ec2019-02-04 21:53:53 +0000288 case BKGRND_SELECT:
289 this.mapSelShown = !this.mapSelShown;
290 break;
Sean Condonb2c483c2019-01-16 20:28:55 +0000291 case CYCLELABELS_BTN:
Sean Condon91481822019-01-01 13:56:14 +0000292 this.cycleDeviceLabels();
293 break;
Sean Condonb2c483c2019-01-16 20:28:55 +0000294 case CYCLEHOSTLABEL_BTN:
Sean Condon91481822019-01-01 13:56:14 +0000295 this.cycleHostLabels();
296 break;
Sean Condonb2c483c2019-01-16 20:28:55 +0000297 case RESETZOOM_BTN:
Sean Condon91481822019-01-01 13:56:14 +0000298 this.resetZoom();
299 break;
Sean Condonb2c483c2019-01-16 20:28:55 +0000300 case EQMASTER_BTN:
Sean Condon91481822019-01-01 13:56:14 +0000301 this.equalizeMasters();
302 break;
Sean Condonb2c483c2019-01-16 20:28:55 +0000303 case CANCEL_TRAFFIC:
Sean Condon91481822019-01-01 13:56:14 +0000304 this.cancelTraffic();
305 break;
Sean Condonb2c483c2019-01-16 20:28:55 +0000306 case ALL_TRAFFIC:
Sean Condon91481822019-01-01 13:56:14 +0000307 this.monitorAllTraffic();
308 break;
Sean Condonb2c483c2019-01-16 20:28:55 +0000309 case QUICKHELP_BTN:
310 this.ks.quickHelpShown = true;
311 break;
Sean Condon91481822019-01-01 13:56:14 +0000312 default:
313 this.log.warn('Unhandled Toolbar action', name);
314 }
315 }
316
317 /**
318 * The list of key strokes that will be active in the Topology View.
319 *
320 * This action map is passed to the KeyService through the bindCommands()
321 * when this component is being initialized
322 */
Sean Condonf4f54a12018-10-10 23:25:46 +0100323 actionMap() {
324 return {
Sean Condon50855cf2018-12-23 15:37:42 +0000325 A: [() => {this.monitorAllTraffic(); }, 'Monitor all traffic'],
Sean Condonf4f54a12018-10-10 23:25:46 +0100326 L: [() => {this.cycleDeviceLabels(); }, 'Cycle device labels'],
327 B: [(token) => {this.toggleBackground(token); }, 'Toggle background'],
328 D: [(token) => {this.toggleDetails(token); }, 'Toggle details panel'],
329 I: [(token) => {this.toggleInstancePanel(token); }, 'Toggle ONOS Instance Panel'],
Sean Condon0d064ec2019-02-04 21:53:53 +0000330 G: [() => {this.mapSelShown = !this.mapSelShown; }, 'Show map selection dialog'],
Sean Condonf4f54a12018-10-10 23:25:46 +0100331 O: [() => {this.toggleSummary(); }, 'Toggle the Summary Panel'],
332 R: [() => {this.resetZoom(); }, 'Reset pan / zoom'],
333 P: [(token) => {this.togglePorts(token); }, 'Toggle Port Highlighting'],
334 E: [() => {this.equalizeMasters(); }, 'Equalize mastership roles'],
335 X: [() => {this.resetNodeLocation(); }, 'Reset Node Location'],
336 U: [() => {this.unpinNode(); }, 'Unpin node (mouse over)'],
337 H: [() => {this.toggleHosts(); }, 'Toggle host visibility'],
338 M: [() => {this.toggleOfflineDevices(); }, 'Toggle offline visibility'],
339 dot: [() => {this.toggleToolbar(); }, 'Toggle Toolbar'],
Sean Condon50855cf2018-12-23 15:37:42 +0000340 0: [() => {this.cancelTraffic(); }, 'Cancel traffic monitoring'],
Sean Condonf4f54a12018-10-10 23:25:46 +0100341 'shift-L': [() => {this.cycleHostLabels(); }, 'Cycle host labels'],
342
343 // -- instance color palette debug
Sean Condon55c30532018-10-29 12:26:57 +0000344 9: () => {
345 this.sus.cat7().testCard(d3.select('svg#topo2'));
Sean Condonf4f54a12018-10-10 23:25:46 +0100346 },
347
Sean Condonb2c483c2019-01-16 20:28:55 +0000348 esc: [() => {this.handleEscape(); }, 'Cancel commands'],
Sean Condonf4f54a12018-10-10 23:25:46 +0100349
350 // TODO update after adding in Background Service
351 // topology overlay selections
352 // F1: function () { t2tbs.fnKey(0); },
353 // F2: function () { t2tbs.fnKey(1); },
354 // F3: function () { t2tbs.fnKey(2); },
355 // F4: function () { t2tbs.fnKey(3); },
356 // F5: function () { t2tbs.fnKey(4); },
357 //
358 // _keyListener: t2tbs.keyListener.bind(t2tbs),
359
360 _helpFormat: [
361 ['I', 'O', 'D', 'H', 'M', 'P', 'dash', 'B'],
362 ['X', 'Z', 'N', 'L', 'shift-L', 'U', 'R', 'E', 'dot'],
363 [], // this column reserved for overlay actions
364 ],
365 };
366 }
367
368
369 bindCommands(additional?: any) {
370
371 const am = this.actionMap();
372 const add = this.fs.isO(additional);
373
Sean Condonf4f54a12018-10-10 23:25:46 +0100374 this.ks.keyBindings(am);
375
376 this.ks.gestureNotes([
377 ['click', 'Select the item and show details'],
378 ['shift-click', 'Toggle selection state'],
379 ['drag', 'Reposition (and pin) device / host'],
380 ['cmd-scroll', 'Zoom in / out'],
381 ['cmd-drag', 'Pan'],
382 ]);
383 }
384
385 handleEscape() {
386
387 if (false) {
388 // TODO: Cancel show mastership
389 // TODO: Cancel Active overlay
390 // TODO: Reinstate with components
391 } else {
Sean Condonb2c483c2019-01-16 20:28:55 +0000392 this.nodeSelected(undefined);
Sean Condonf4f54a12018-10-10 23:25:46 +0100393 this.log.debug('Handling escape');
394 // } else if (t2rs.deselectAllNodes()) {
395 // // else if we have node selections, deselect them all
396 // // (work already done)
397 // } else if (t2rs.deselectLink()) {
398 // // else if we have a link selection, deselect it
399 // // (work already done)
400 // } else if (t2is.isVisible()) {
401 // // If the instance panel is visible, close it
402 // t2is.toggle();
403 // } else if (t2sp.isVisible()) {
404 // // If the summary panel is visible, close it
405 // t2sp.toggle();
406 }
407 }
408
Sean Condonb2c483c2019-01-16 20:28:55 +0000409 /**
410 * Updates the cache of preferences locally and onwards to the PrefsService
411 * @param what The attribute of the local topo2-prefs cache to update
412 * @param b the value to update it with
413 */
414 updatePrefsState(what: string, b: number) {
415 this.prefsState[what] = b;
416 this.ps.setPrefs(TOPO2_PREFS, this.prefsState);
Sean Condonf4f54a12018-10-10 23:25:46 +0100417 }
418
Sean Condonb2c483c2019-01-16 20:28:55 +0000419 /**
420 * When the button is clicked on the toolbar or the L key is pressed
421 * 1) cycle through options
422 * 2) flash up a message
423 * 3a) Update the local prefs cache
424 * 3b) And passes on to the global prefs service which sends back to the server
425 * 3c) It also has a knock on effect of passing it on to ForceSvgComponent
426 * because prefsState.dlbls is given as an input to it
427 * 3d) This will in turn pass it down to the DeviceSvgComponent which
428 * displays the label
429 */
Sean Condonf4f54a12018-10-10 23:25:46 +0100430 protected cycleDeviceLabels() {
Sean Condonb2c483c2019-01-16 20:28:55 +0000431 const old: LabelToggle = this.prefsState.dlbls;
Sean Condon021f0fa2018-12-06 23:31:11 -0800432 const next = LabelToggle.next(old);
Sean Condon91481822019-01-01 13:56:14 +0000433 this.flashMsg = this.lionFn(TopologyComponent.deviceLabelFlashMessage(next));
Sean Condonb2c483c2019-01-16 20:28:55 +0000434 this.updatePrefsState(PREF_DLBLS, next);
Sean Condon021f0fa2018-12-06 23:31:11 -0800435 this.log.debug('Cycling device labels', old, next);
Sean Condonf4f54a12018-10-10 23:25:46 +0100436 }
437
438 protected cycleHostLabels() {
Sean Condonb2c483c2019-01-16 20:28:55 +0000439 const old: HostLabelToggle = this.prefsState.hlbls;
Sean Condon021f0fa2018-12-06 23:31:11 -0800440 const next = HostLabelToggle.next(old);
Sean Condon91481822019-01-01 13:56:14 +0000441 this.flashMsg = this.lionFn(TopologyComponent.hostLabelFlashMessage(next));
Sean Condonb2c483c2019-01-16 20:28:55 +0000442 this.updatePrefsState(PREF_HLBLS, next);
Sean Condon021f0fa2018-12-06 23:31:11 -0800443 this.log.debug('Cycling host labels', old, next);
Sean Condonf4f54a12018-10-10 23:25:46 +0100444 }
445
Sean Condonb2c483c2019-01-16 20:28:55 +0000446 /**
447 * When the button is clicked on the toolbar or the B key is pressed
448 * 1) Find the inverse of the current state (held as 1 or 0)
449 * 2) Flash up a message on screen
450 * 3b) And passes on to the global prefs service which sends back to the server
451 * 3c) It also has a knock on effect of passing it on to ToolbarComponent
452 * because prefsState.bg is given as an input to it
453 * @param token
454 */
Sean Condon91481822019-01-01 13:56:14 +0000455 protected toggleBackground(token?: KeysToken) {
Sean Condonb2c483c2019-01-16 20:28:55 +0000456 const bg: boolean = !Boolean(this.prefsState.bg);
457 this.flashMsg = this.lionFn(bg ? 'show' : 'hide') +
Sean Condon91481822019-01-01 13:56:14 +0000458 ' ' + this.lionFn('fl_background_map');
Sean Condonb2c483c2019-01-16 20:28:55 +0000459 this.updatePrefsState(PREF_BG, bg ? 1 : 0);
460 this.log.debug('Toggling background', token, bg ? 'shown' : 'hidden');
Sean Condonf4f54a12018-10-10 23:25:46 +0100461 }
462
Sean Condon91481822019-01-01 13:56:14 +0000463 protected toggleDetails(token?: KeysToken) {
Sean Condonb2c483c2019-01-16 20:28:55 +0000464 const on: boolean = !Boolean(this.prefsState.detail);
465 this.flashMsg = this.lionFn(on ? 'show' : 'hide') +
466 ' ' + this.lionFn('fl_panel_details');
467 this.updatePrefsState(PREF_DETAIL, on ? 1 : 0);
468 this.log.debug('Toggling details', token);
Sean Condonf4f54a12018-10-10 23:25:46 +0100469 }
470
Sean Condon91481822019-01-01 13:56:14 +0000471 protected toggleInstancePanel(token?: KeysToken) {
Sean Condonb2c483c2019-01-16 20:28:55 +0000472 const on: boolean = !Boolean(this.prefsState.insts);
Sean Condon91481822019-01-01 13:56:14 +0000473 this.flashMsg = this.lionFn(on ? 'show' : 'hide') +
474 ' ' + this.lionFn('fl_panel_instances');
Sean Condonb2c483c2019-01-16 20:28:55 +0000475 this.updatePrefsState(PREF_INSTS, on ? 1 : 0);
Sean Condon91481822019-01-01 13:56:14 +0000476 this.log.debug('Toggling instances', token, on);
Sean Condonf4f54a12018-10-10 23:25:46 +0100477 }
478
479 protected toggleSummary() {
Sean Condonb2c483c2019-01-16 20:28:55 +0000480 const on: boolean = !Boolean(this.prefsState.summary);
Sean Condon91481822019-01-01 13:56:14 +0000481 this.flashMsg = this.lionFn(on ? 'show' : 'hide') +
482 ' ' + this.lionFn('fl_panel_summary');
Sean Condonb2c483c2019-01-16 20:28:55 +0000483 this.updatePrefsState(PREF_SUMMARY, on ? 1 : 0);
484 }
485
486 protected togglePorts(token?: KeysToken) {
487 const current: boolean = !Boolean(this.prefsState.porthl);
488 this.flashMsg = this.lionFn(current ? 'enable' : 'disable') +
489 ' ' + this.lionFn('fl_port_highlighting');
490 this.updatePrefsState(PREF_PORTHL, current ? 1 : 0);
491 this.log.debug(current ? 'Enable' : 'Disable', 'port highlighting');
492 }
493
494 protected toggleToolbar() {
495 const on: boolean = !Boolean(this.prefsState.toolbar);
496 this.updatePrefsState(PREF_TOOLBAR, on ? 1 : 0);
497 this.log.debug('toggling toolbar', on ? 'shown' : 'hidden');
498 }
499
500 protected toggleHosts() {
501 const current: boolean = !Boolean(this.prefsState.hosts);
502 this.flashMsg = this.lionFn('hosts') + ' ' +
503 this.lionFn(this.force.showHosts ? 'visible' : 'hidden');
504 this.updatePrefsState(PREF_HOSTS, current ? 1 : 0);
505 this.log.debug('toggling hosts: ', this.prefsState.hosts ? 'Show' : 'Hide');
506 }
507
508 protected toggleOfflineDevices() {
509 const on: boolean = !Boolean(this.prefsState.offdev);
510 this.flashMsg = this.lionFn(on ? 'show' : 'hide') +
511 ' ' + this.lionFn('fl_offline_devices');
512 this.updatePrefsState(PREF_OFFDEV, on ? 1 : 0);
513 this.log.debug('toggling offline devices', this.prefsState.offdev);
Sean Condonf4f54a12018-10-10 23:25:46 +0100514 }
515
516 protected resetZoom() {
Sean Condon91481822019-01-01 13:56:14 +0000517 this.zoomDirective.resetZoom();
518 this.flashMsg = this.lionFn('fl_pan_zoom_reset');
Sean Condonf4f54a12018-10-10 23:25:46 +0100519 }
520
Sean Condonf4f54a12018-10-10 23:25:46 +0100521 protected equalizeMasters() {
522 this.wss.sendEvent('equalizeMasters', null);
Sean Condon91481822019-01-01 13:56:14 +0000523 this.flashMsg = this.lionFn('fl_eq_masters');
Sean Condonf4f54a12018-10-10 23:25:46 +0100524 this.log.debug('equalizing masters');
Sean Condonf4f54a12018-10-10 23:25:46 +0100525 }
526
527 protected resetNodeLocation() {
Sean Condon91481822019-01-01 13:56:14 +0000528 // TODO: Implement reset locations
529 this.flashMsg = this.lionFn('fl_reset_node_locations');
Sean Condonf4f54a12018-10-10 23:25:46 +0100530 this.log.debug('resetting node location');
Sean Condonf4f54a12018-10-10 23:25:46 +0100531 }
532
533 protected unpinNode() {
Sean Condon91481822019-01-01 13:56:14 +0000534 // TODO: Implement this
Sean Condonf4f54a12018-10-10 23:25:46 +0100535 this.log.debug('unpinning node');
Sean Condonf4f54a12018-10-10 23:25:46 +0100536 }
537
Sean Condon91481822019-01-01 13:56:14 +0000538 /**
539 * Check to see if this is needed anymore
540 * @param what
541 */
Sean Condonf4f54a12018-10-10 23:25:46 +0100542 protected notValid(what) {
543 this.log.warn('topo.js getActionEntry(): Not a valid ' + what);
544 }
545
Sean Condon91481822019-01-01 13:56:14 +0000546 /**
547 * Check to see if this is needed anymore
548 * @param what
549 */
Sean Condonf4f54a12018-10-10 23:25:46 +0100550 getActionEntry(key) {
551 let entry;
552
553 if (!key) {
554 this.notValid('key');
555 return null;
556 }
557
558 entry = this.actionMap()[key];
559
560 if (!entry) {
561 this.notValid('actionMap (' + key + ') entry');
562 return null;
563 }
564 return this.fs.isA(entry) || [entry, ''];
565 }
566
Sean Condon91481822019-01-01 13:56:14 +0000567 /**
568 * An event handler that updates the details panel as items are
569 * selected in the forcesvg layer
570 * @param nodeOrLink the item to display details of
571 */
572 nodeSelected(nodeOrLink: UiElement) {
573 this.details.ngOnChanges({'selectedNode':
574 new SimpleChange(undefined, nodeOrLink, true)});
Sean Condon0c577f62018-11-18 22:40:05 +0000575 }
576
Sean Condon50855cf2018-12-23 15:37:42 +0000577 /**
578 * Enable traffic monitoring
579 */
580 monitorAllTraffic() {
Sean Condon91481822019-01-01 13:56:14 +0000581 // TODO: Implement support for toggling between bits, packets and octets
582 this.flashMsg = this.lionFn('tr_fl_pstats_bits');
Sean Condon50855cf2018-12-23 15:37:42 +0000583 this.trs.init(this.force);
584 }
585
586 /**
587 * Cancel traffic monitoring
588 */
589 cancelTraffic() {
Sean Condon91481822019-01-01 13:56:14 +0000590 this.flashMsg = this.lionFn('fl_monitoring_canceled');
Sean Condon50855cf2018-12-23 15:37:42 +0000591 this.trs.destroy();
592 }
Sean Condon91481822019-01-01 13:56:14 +0000593
Sean Condon0d064ec2019-02-04 21:53:53 +0000594 changeMap(map: MapObject) {
595 this.mapSelShown = false; // Hide the MapSelector component
596 this.mapIdState = map;
597 this.ps.setPrefs(TOPO_MAPID_PREFS, this.mapIdState);
598 this.log.debug('Map has been changed to ', map);
599 }
600
Sean Condon91481822019-01-01 13:56:14 +0000601 /**
602 * Read the LION bundle for Toolbar and set up the lionFn
603 */
604 doLion() {
605 this.lionFn = this.lion.bundle('core.view.Topo');
606 }
607
608 /**
609 * A dummy implementation of the lionFn until the response is received and the LION
610 * bundle is received from the WebSocket
611 */
612 dummyLion(key: string): string {
613 return '%' + key + '%';
614 }
Sean Condonf4f54a12018-10-10 23:25:46 +0100615}