blob: 78834f6e570ce30f666f3e013300da35284878be [file] [log] [blame]
Bri Prebilic Cole7c92a3d2015-01-09 16:50:03 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Bri Prebilic Cole7c92a3d2015-01-09 16:50:03 -08003 *
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 */
16
17/*
Bri Prebilic Coleaa0f0882015-02-04 15:27:55 -080018 ONOS GUI -- Device View Module
Bri Prebilic Cole7c92a3d2015-01-09 16:50:03 -080019 */
20
21(function () {
22 'use strict';
23
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -070024 // injected refs
Simon Huntd5579252015-10-06 15:09:14 -070025 var $log, $scope, $loc, fs, mast, ps, wss, is, ns, ks;
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -070026
27 // internal state
Bri Prebilic Colee568ead2015-05-01 09:51:28 -070028 var detailsPanel,
Simon Huntd766c312015-10-06 11:46:32 -070029 pStartY,
30 pHeight,
31 top,
32 bottom,
33 iconDiv,
34 wSize,
35 editingName = false;
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -070036
37 // constants
Bri Prebilic Cole45069382015-04-14 15:21:38 -070038 var topPdg = 13,
39 ctnrPdg = 24,
Bri Prebilic Cole9cf1a8d2015-04-21 13:15:29 -070040 scrollSize = 17,
Bri Prebilic Cole45069382015-04-14 15:21:38 -070041 portsTblPdg = 50,
42
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -070043 pName = 'device-details-panel',
44 detailsReq = 'deviceDetailsRequest',
45 detailsResp = 'deviceDetailsResponse',
Simon Huntd5579252015-10-06 15:09:14 -070046 nameChangeReq = 'deviceNameChangeRequest',
47 nameChangeResp = 'deviceNameChangeResponse',
Bri Prebilic Cole45069382015-04-14 15:21:38 -070048
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -070049 propOrder = [
Simon Huntd5579252015-10-06 15:09:14 -070050 'id', 'type', 'masterid', 'chassisid',
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -070051 'mfr', 'hw', 'sw', 'protocol', 'serial'
52 ],
53 friendlyProps = [
Simon Huntd5579252015-10-06 15:09:14 -070054 'URI', 'Type', 'Master ID', 'Chassis ID',
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -070055 'Vendor', 'H/W Version', 'S/W Version', 'Protocol', 'Serial #'
56 ],
57 portCols = [
Thomas Vachuskab52a0142015-04-21 17:48:15 -070058 'enabled', 'id', 'speed', 'type', 'elinks_dest', 'name'
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -070059 ],
60 friendlyPortCols = [
Thomas Vachuskab52a0142015-04-21 17:48:15 -070061 'Enabled', 'ID', 'Speed', 'Type', 'Egress Links', 'Name'
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -070062 ];
63
Bri Prebilic Cole9dcaea52015-07-21 14:39:48 -070064 function closePanel() {
65 if (detailsPanel.isVisible()) {
66 $scope.selId = null;
67 detailsPanel.hide();
Simon Huntd766c312015-10-06 11:46:32 -070068 return true;
Bri Prebilic Cole9dcaea52015-07-21 14:39:48 -070069 }
Simon Huntd766c312015-10-06 11:46:32 -070070 return false;
Bri Prebilic Cole9dcaea52015-07-21 14:39:48 -070071 }
72
Bri Prebilic Coleb699a162015-04-13 12:01:39 -070073 function addCloseBtn(div) {
Bri Prebilic Coleab582b82015-04-14 15:08:22 -070074 is.loadEmbeddedIcon(div, 'plus', 30);
Bri Prebilic Coleb699a162015-04-13 12:01:39 -070075 div.select('g').attr('transform', 'translate(25, 0) rotate(45)');
Bri Prebilic Cole9dcaea52015-07-21 14:39:48 -070076 div.on('click', closePanel);
Bri Prebilic Coleb699a162015-04-13 12:01:39 -070077 }
78
Simon Huntd5579252015-10-06 15:09:14 -070079 function exitEditMode(nameH2, name) {
80 nameH2.html(name);
81 nameH2.classed('editable', true);
82 editingName = false;
83 ks.enableGlobalKeys(true);
Simon Huntd766c312015-10-06 11:46:32 -070084 }
85
86 function editNameSave() {
Simon Huntd5579252015-10-06 15:09:14 -070087 var nameH2 = top.select('h2'),
88 id = $scope.panelData.id,
89 val,
Simon Huntd766c312015-10-06 11:46:32 -070090 newVal;
Simon Huntd5579252015-10-06 15:09:14 -070091
Simon Huntd766c312015-10-06 11:46:32 -070092 if (editingName) {
Simon Huntd5579252015-10-06 15:09:14 -070093 val = nameH2.select('input').property('value').trim();
94 newVal = val || id;
Simon Huntd766c312015-10-06 11:46:32 -070095
Simon Huntd5579252015-10-06 15:09:14 -070096 exitEditMode(nameH2, newVal);
Simon Huntd766c312015-10-06 11:46:32 -070097 $scope.panelData.name = newVal;
Simon Huntd5579252015-10-06 15:09:14 -070098 wss.sendEvent(nameChangeReq, { id: id, name: val });
Simon Huntd766c312015-10-06 11:46:32 -070099 }
100 }
101
102 function editNameCancel() {
Simon Huntd766c312015-10-06 11:46:32 -0700103 if (editingName) {
Simon Huntd5579252015-10-06 15:09:14 -0700104 exitEditMode(top.select('h2'), $scope.panelData.name);
Simon Huntd766c312015-10-06 11:46:32 -0700105 return true;
106 }
107 return false;
108 }
109
110 function editName() {
Simon Huntd5579252015-10-06 15:09:14 -0700111 var nameH2 = top.select('h2'),
112 tf, el;
113
Simon Huntd766c312015-10-06 11:46:32 -0700114 if (!editingName) {
Simon Huntd5579252015-10-06 15:09:14 -0700115 nameH2.classed('editable', false);
116 nameH2.html('');
117 tf = nameH2.append('input').classed('name-input', true)
Simon Huntd766c312015-10-06 11:46:32 -0700118 .attr('type', 'text')
119 .attr('value', $scope.panelData.name);
Simon Huntd5579252015-10-06 15:09:14 -0700120 el = tf[0][0];
121 el.focus();
122 el.select();
123 editingName = true;
124 ks.enableGlobalKeys(false);
Simon Huntd766c312015-10-06 11:46:32 -0700125 }
126 }
127
128 function handleEscape() {
129 return editNameCancel() || closePanel();
130 }
131
Bri Prebilic Coleb699a162015-04-13 12:01:39 -0700132 function setUpPanel() {
Bri Prebilic Cole8f07f0d2015-04-23 13:28:43 -0700133 var container, closeBtn, tblDiv;
Bri Prebilic Coleb699a162015-04-13 12:01:39 -0700134 detailsPanel.empty();
135
136 container = detailsPanel.append('div').classed('container', true);
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -0700137
138 top = container.append('div').classed('top', true);
139 closeBtn = top.append('div').classed('close-btn', true);
140 addCloseBtn(closeBtn);
Bri Prebilic Coleb699a162015-04-13 12:01:39 -0700141 iconDiv = top.append('div').classed('dev-icon', true);
Simon Huntd5579252015-10-06 15:09:14 -0700142 top.append('h2').classed('editable', true).on('click', editName);
Simon Huntd766c312015-10-06 11:46:32 -0700143
Bri Prebilic Cole8f07f0d2015-04-23 13:28:43 -0700144 tblDiv = top.append('div').classed('top-tables', true);
145 tblDiv.append('div').classed('left', true).append('table');
146 tblDiv.append('div').classed('right', true).append('table');
147
Bri Prebilic Cole45069382015-04-14 15:21:38 -0700148 top.append('hr');
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -0700149
150 bottom = container.append('div').classed('bottom', true);
Bri Prebilic Cole45069382015-04-14 15:21:38 -0700151 bottom.append('h2').classed('ports-title', true).html('Ports');
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -0700152 bottom.append('table');
153 }
154
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -0700155 function addProp(tbody, index, value) {
156 var tr = tbody.append('tr');
157
158 function addCell(cls, txt) {
159 tr.append('td').attr('class', cls).html(txt);
160 }
161 addCell('label', friendlyProps[index] + ' :');
162 addCell('value', value);
163 }
164
Bri Prebilic Cole9b1fb9a2015-07-01 13:57:11 -0700165 function populateTop(tblDiv, details) {
Bri Prebilic Cole8f07f0d2015-04-23 13:28:43 -0700166 var leftTbl = tblDiv.select('.left')
167 .select('table')
168 .append('tbody'),
169 rightTbl = tblDiv.select('.right')
170 .select('table')
171 .append('tbody');
172
Bri Prebilic Coleb699a162015-04-13 12:01:39 -0700173 is.loadEmbeddedIcon(iconDiv, details._iconid_type, 40);
Simon Huntd5579252015-10-06 15:09:14 -0700174 top.select('h2').html(details.name);
Bri Prebilic Coleb699a162015-04-13 12:01:39 -0700175
176 propOrder.forEach(function (prop, i) {
Bri Prebilic Cole8f07f0d2015-04-23 13:28:43 -0700177 // properties are split into two tables
Simon Huntd5579252015-10-06 15:09:14 -0700178 addProp(i < 4 ? leftTbl : rightTbl, i, details[prop]);
Bri Prebilic Coleb699a162015-04-13 12:01:39 -0700179 });
180 }
181
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -0700182 function addPortRow(tbody, port) {
183 var tr = tbody.append('tr');
184
185 portCols.forEach(function (col) {
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -0700186 tr.append('td').html(port[col]);
187 });
188 }
189
Bri Prebilic Coleb699a162015-04-13 12:01:39 -0700190 function populateBottom(table, ports) {
191 var theader = table.append('thead').append('tr'),
192 tbody = table.append('tbody'),
Bri Prebilic Cole45069382015-04-14 15:21:38 -0700193 tbWidth, tbHeight;
Bri Prebilic Coleb699a162015-04-13 12:01:39 -0700194
195 friendlyPortCols.forEach(function (col) {
196 theader.append('th').html(col);
197 });
198 ports.forEach(function (port) {
199 addPortRow(tbody, port);
200 });
201
202 tbWidth = fs.noPxStyle(tbody, 'width') + scrollSize;
Bri Prebilic Cole45069382015-04-14 15:21:38 -0700203 tbHeight = pHeight
204 - (fs.noPxStyle(detailsPanel.el()
205 .select('.top'), 'height')
206 + fs.noPxStyle(detailsPanel.el()
207 .select('.ports-title'), 'height')
208 + portsTblPdg);
Bri Prebilic Coleb699a162015-04-13 12:01:39 -0700209
210 table.style({
211 height: tbHeight + 'px',
212 width: tbWidth + 'px',
213 overflow: 'auto',
214 display: 'block'
215 });
216
Bri Prebilic Cole45069382015-04-14 15:21:38 -0700217 detailsPanel.width(tbWidth + ctnrPdg);
Bri Prebilic Coleb699a162015-04-13 12:01:39 -0700218 }
219
Simon Huntd766c312015-10-06 11:46:32 -0700220 function populateName(div, name) {
221 var lab = div.select('.label'),
222 val = div.select('.value');
223 lab.html('Friendly Name:');
224 val.html(name);
225 }
226
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -0700227 function populateDetails(details) {
Simon Huntd766c312015-10-06 11:46:32 -0700228 var nameDiv, topTbs, btmTbl, ports;
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -0700229 setUpPanel();
230
Simon Huntd766c312015-10-06 11:46:32 -0700231 nameDiv = top.select('.name-div');
Bri Prebilic Cole8f07f0d2015-04-23 13:28:43 -0700232 topTbs = top.select('.top-tables');
Bri Prebilic Cole45069382015-04-14 15:21:38 -0700233 btmTbl = bottom.select('table');
234 ports = details.ports;
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -0700235
Simon Huntd766c312015-10-06 11:46:32 -0700236 populateName(nameDiv, details.name);
Bri Prebilic Cole9b1fb9a2015-07-01 13:57:11 -0700237 populateTop(topTbs, details);
Bri Prebilic Coleb699a162015-04-13 12:01:39 -0700238 populateBottom(btmTbl, ports);
Bri Prebilic Cole45069382015-04-14 15:21:38 -0700239
240 detailsPanel.height(pHeight);
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -0700241 }
242
243 function respDetailsCb(data) {
Bri Prebilic Colee568ead2015-05-01 09:51:28 -0700244 $scope.panelData = data.details;
Bri Prebilic Cole54bbfb92015-05-28 16:02:28 -0700245 $scope.$apply();
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -0700246 }
247
Simon Huntd5579252015-10-06 15:09:14 -0700248 function respNameCb(data) {
249 if (data.warn) {
250 $log.warn(data.warn, data.id);
251 top.select('h2').html(data.id);
252 }
253 }
254
Bri Prebilic Cole45069382015-04-14 15:21:38 -0700255 function createDetailsPane() {
256 detailsPanel = ps.createPanel(pName, {
257 width: wSize.width,
258 margin: 0,
259 hideMargin: 0
260 });
261 detailsPanel.el().style({
262 position: 'absolute',
263 top: pStartY + 'px'
264 });
Bri Prebilic Cole68844ba2015-07-22 15:41:37 -0700265 $scope.hidePanel = function () { detailsPanel.hide(); };
Bri Prebilic Cole45069382015-04-14 15:21:38 -0700266 detailsPanel.hide();
267 }
268
Bri Prebilic Cole7c92a3d2015-01-09 16:50:03 -0800269 angular.module('ovDevice', [])
Simon Hunta89f0f92015-02-26 16:47:12 -0800270 .controller('OvDeviceCtrl',
Bri Prebilic Cole17c6d0a2015-07-16 14:56:40 -0700271 ['$log', '$scope', '$location', 'TableBuilderService', 'FnService',
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -0700272 'MastService', 'PanelService', 'WebSocketService', 'IconService',
Simon Huntd5579252015-10-06 15:09:14 -0700273 'NavService', 'KeyService',
Simon Hunta89f0f92015-02-26 16:47:12 -0800274
Bri Prebilic Cole17c6d0a2015-07-16 14:56:40 -0700275 function (_$log_, _$scope_, _$location_,
Simon Huntd5579252015-10-06 15:09:14 -0700276 tbs, _fs_, _mast_, _ps_, _wss_, _is_, _ns_, _ks_) {
277 var params,
278 handlers = {};
279
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -0700280 $log = _$log_;
281 $scope = _$scope_;
Simon Huntd5579252015-10-06 15:09:14 -0700282 $loc = _$location_;
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -0700283 fs = _fs_;
284 mast = _mast_;
285 ps = _ps_;
286 wss = _wss_;
287 is = _is_;
Bri Prebilic Cole8f07f0d2015-04-23 13:28:43 -0700288 ns = _ns_;
Simon Huntd5579252015-10-06 15:09:14 -0700289 ks = _ks_;
290
291 params = $loc.search();
292
Bri Prebilic Cole68844ba2015-07-22 15:41:37 -0700293 $scope.panelData = {};
Bri Prebilic Coleeef67ae2015-07-01 16:26:59 -0700294 $scope.flowTip = 'Show flow view for selected device';
295 $scope.portTip = 'Show port view for selected device';
296 $scope.groupTip = 'Show group view for selected device';
Jian Li1f544732015-12-30 23:36:37 -0800297 $scope.meterTip = 'Show meter view for selected device';
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -0700298
Bri Prebilic Cole17c6d0a2015-07-16 14:56:40 -0700299 // details panel handlers
300 handlers[detailsResp] = respDetailsCb;
Simon Huntd5579252015-10-06 15:09:14 -0700301 handlers[nameChangeResp] = respNameCb;
Bri Prebilic Cole17c6d0a2015-07-16 14:56:40 -0700302 wss.bindHandlers(handlers);
303
304 // query for if a certain device needs to be highlighted
305 if (params.hasOwnProperty('devId')) {
306 $scope.selId = params['devId'];
307 wss.sendEvent(detailsReq, { id: $scope.selId });
308 }
309
Bri Prebilic Coleb699a162015-04-13 12:01:39 -0700310 function selCb($event, row) {
Bri Prebilic Colebfab9c72015-06-01 14:33:18 -0700311 if ($scope.selId) {
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -0700312 wss.sendEvent(detailsReq, { id: row.id });
313 } else {
Bri Prebilic Cole68844ba2015-07-22 15:41:37 -0700314 $scope.hidePanel();
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -0700315 }
316 $log.debug('Got a click on:', row);
317 }
318
Bri Prebilic Cole864cdd62015-04-02 15:46:47 -0700319 tbs.buildTable({
Bri Prebilic Cole864cdd62015-04-02 15:46:47 -0700320 scope: $scope,
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -0700321 tag: 'device',
322 selCb: selCb
323 });
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -0700324
Bri Prebilic Cole9b1fb9a2015-07-01 13:57:11 -0700325 $scope.nav = function (path) {
326 if ($scope.selId) {
327 ns.navTo(path, { devId: $scope.selId });
328 }
329 };
330
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -0700331 $scope.$on('$destroy', function () {
Bri Prebilic Cole0feedc02015-04-09 14:17:37 -0700332 wss.unbindHandlers(handlers);
Simon Hunta89f0f92015-02-26 16:47:12 -0800333 });
334
Bri Prebilic Cole72eb6db2015-03-30 16:58:53 -0700335 $log.log('OvDeviceCtrl has been created');
Bri Prebilic Cole54bbfb92015-05-28 16:02:28 -0700336 }])
337
Bri Prebilic Cole55ee09b2015-08-04 14:34:07 -0700338 .directive('deviceDetailsPanel',
339 ['$rootScope', '$window', '$timeout', 'KeyService',
340 function ($rootScope, $window, $timeout, ks) {
Bri Prebilic Cole17c6d0a2015-07-16 14:56:40 -0700341 return function (scope) {
Bri Prebilic Cole0bc4de22015-07-20 17:07:55 -0700342 var unbindWatch;
Bri Prebilic Cole54bbfb92015-05-28 16:02:28 -0700343
Bri Prebilic Cole17c6d0a2015-07-16 14:56:40 -0700344 function heightCalc() {
345 pStartY = fs.noPxStyle(d3.select('.tabular-header'), 'height')
346 + mast.mastHeight() + topPdg;
347 wSize = fs.windowSize(pStartY);
348 pHeight = wSize.height;
349 }
Bri Prebilic Cole17c6d0a2015-07-16 14:56:40 -0700350
Bri Prebilic Cole55ee09b2015-08-04 14:34:07 -0700351 function initPanel() {
352 heightCalc();
353 createDetailsPane();
354 }
Bri Prebilic Cole17c6d0a2015-07-16 14:56:40 -0700355
Bri Prebilic Cole55ee09b2015-08-04 14:34:07 -0700356 // Safari has a bug where it renders the fixed-layout table wrong
357 // if you ask for the window's size too early
358 if (scope.onos.browser === 'safari') {
359 $timeout(initPanel);
360 } else {
361 initPanel();
362 }
Bri Prebilic Cole9dcaea52015-07-21 14:39:48 -0700363 // create key bindings to handle panel
364 ks.keyBindings({
Simon Huntd766c312015-10-06 11:46:32 -0700365 enter: editNameSave,
366 esc: [handleEscape, 'Close the details panel'],
Bri Prebilic Cole9dcaea52015-07-21 14:39:48 -0700367 _helpFormat: ['esc']
368 });
369 ks.gestureNotes([
370 ['click', 'Select a row to show device details'],
371 ['scroll down', 'See more devices']
372 ]);
373
Bri Prebilic Cole55ee09b2015-08-04 14:34:07 -0700374 // if the panelData changes
Bri Prebilic Cole17c6d0a2015-07-16 14:56:40 -0700375 scope.$watch('panelData', function () {
376 if (!fs.isEmptyObject(scope.panelData)) {
377 populateDetails(scope.panelData);
378 detailsPanel.show();
Bri Prebilic Cole54bbfb92015-05-28 16:02:28 -0700379 }
Bri Prebilic Cole17c6d0a2015-07-16 14:56:40 -0700380 });
Bri Prebilic Cole54bbfb92015-05-28 16:02:28 -0700381
Bri Prebilic Cole55ee09b2015-08-04 14:34:07 -0700382 // if the window size changes
Bri Prebilic Cole0bc4de22015-07-20 17:07:55 -0700383 unbindWatch = $rootScope.$watchCollection(
Bri Prebilic Cole17c6d0a2015-07-16 14:56:40 -0700384 function () {
385 return {
386 h: $window.innerHeight,
387 w: $window.innerWidth
388 };
389 }, function () {
Bri Prebilic Cole54bbfb92015-05-28 16:02:28 -0700390 if (!fs.isEmptyObject(scope.panelData)) {
Bri Prebilic Cole17c6d0a2015-07-16 14:56:40 -0700391 heightCalc();
Bri Prebilic Cole54bbfb92015-05-28 16:02:28 -0700392 populateDetails(scope.panelData);
Bri Prebilic Cole54bbfb92015-05-28 16:02:28 -0700393 }
Bri Prebilic Cole17c6d0a2015-07-16 14:56:40 -0700394 }
395 );
Bri Prebilic Cole54bbfb92015-05-28 16:02:28 -0700396
Bri Prebilic Cole17c6d0a2015-07-16 14:56:40 -0700397 scope.$on('$destroy', function () {
Bri Prebilic Cole0bc4de22015-07-20 17:07:55 -0700398 unbindWatch();
Bri Prebilic Cole9dcaea52015-07-21 14:39:48 -0700399 ks.unbindKeys();
Bri Prebilic Cole17c6d0a2015-07-16 14:56:40 -0700400 ps.destroyPanel(pName);
401 });
402 };
403 }]);
Bri Prebilic Cole7c92a3d2015-01-09 16:50:03 -0800404}());