blob: 89cb8a2a61106f07cbba85f9fd89e125f6b32250 [file] [log] [blame]
Bri Prebilic Cole384e8dc2015-04-13 15:51:14 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Bri Prebilic Cole384e8dc2015-04-13 15:51:14 -07003 *
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/*
18 ONOS GUI -- Cluster View Module
19 */
20
21(function () {
22 'use strict';
23
Simon Hunt6b5a9412016-10-26 19:32:04 -070024 // injected references
Simon Hunt083e6fb2017-06-16 16:51:41 -070025 var $log, $scope, fs, ns, mast, ps, is, wss;
Viswanath KSP9fcf9702016-10-23 17:13:29 +053026
Simon Hunt6b5a9412016-10-26 19:32:04 -070027 // internal state
28 var detailsPanel,
29 pStartY,
30 pHeight,
31 top,
32 topTable,
33 bottom,
34 iconDiv,
Simon Hunt6b5a9412016-10-26 19:32:04 -070035 wSize;
Viswanath KSP9fcf9702016-10-23 17:13:29 +053036
37
Simon Hunt6b5a9412016-10-26 19:32:04 -070038 // constants
39 var topPdg = 28,
40 ctnrPdg = 24,
41 scrollSize = 17,
42 portsTblPdg = 50,
Simon Hunt6b5a9412016-10-26 19:32:04 -070043 pName = 'cluster-details-panel',
44 detailsReq = 'clusterDetailsRequest',
45 detailsResp = 'clusterDetailsResponse',
Simon Hunt6b5a9412016-10-26 19:32:04 -070046 propOrder = [
47 'id', 'ip'
48 ],
Viswanath KSP116f0c12016-11-21 00:02:51 +053049 deviceCols = [
50 'id', 'type', 'chassisid', 'mfr',
51 'hw', 'sw', 'protocol', 'serial'
Simon Hunt6b5a9412016-10-26 19:32:04 -070052 ];
Viswanath KSP9fcf9702016-10-23 17:13:29 +053053
Simon Hunt083e6fb2017-06-16 16:51:41 -070054 // deferred fetching of user-visible strings, so that lion context is set
55 function getLionProps() {
56 var l = $scope.lion;
57 return [
58 l('node_id'),
59 l('ip_address')
60 ];
61 }
62
63 function getLionDeviceCols() {
64 var l = $scope.lion;
65 return [
66 l('uri'),
67 l('type'),
68 l('chassis_id'),
69 l('vendor'),
70 l('hw_version'),
71 l('sw_version'),
72 l('protocol'),
73 l('serial_number')
74 ];
75 }
76
Simon Hunt6b5a9412016-10-26 19:32:04 -070077 function closePanel() {
78 if (detailsPanel.isVisible()) {
79 $scope.selId = null;
Viswanath KSP9fcf9702016-10-23 17:13:29 +053080 detailsPanel.hide();
Simon Hunt6b5a9412016-10-26 19:32:04 -070081 return true;
Viswanath KSP9fcf9702016-10-23 17:13:29 +053082 }
Simon Hunt6b5a9412016-10-26 19:32:04 -070083 return false;
84 }
Viswanath KSP9fcf9702016-10-23 17:13:29 +053085
Simon Hunt6b5a9412016-10-26 19:32:04 -070086 function addCloseBtn(div) {
87 is.loadEmbeddedIcon(div, 'close', 20);
88 div.on('click', closePanel);
89 }
Viswanath KSP9fcf9702016-10-23 17:13:29 +053090
Viswanath KSP86016272016-10-27 09:49:46 +053091 function handleEscape() {
92 return closePanel();
93 }
94
Simon Hunt6b5a9412016-10-26 19:32:04 -070095 function setUpPanel() {
Simon Hunt083e6fb2017-06-16 16:51:41 -070096 var container, closeBtn;
Simon Hunt6b5a9412016-10-26 19:32:04 -070097 detailsPanel.empty();
Viswanath KSP9fcf9702016-10-23 17:13:29 +053098
Simon Hunt6b5a9412016-10-26 19:32:04 -070099 container = detailsPanel.append('div').classed('container', true);
Viswanath KSP9fcf9702016-10-23 17:13:29 +0530100
Simon Hunt6b5a9412016-10-26 19:32:04 -0700101 top = container.append('div').classed('top', true);
102 closeBtn = top.append('div').classed('close-btn', true);
103 addCloseBtn(closeBtn);
104 iconDiv = top.append('div').classed('dev-icon', true);
105 top.append('h2');
106 topTable = top.append('div').classed('top-content', true)
107 .append('table');
108 top.append('hr');
109
Viswanath KSP116f0c12016-11-21 00:02:51 +0530110 bottom = container.append('div').classed('bottom', true);
Simon Hunt239f09e2017-05-18 13:10:09 -0700111 bottom.append('h2').classed('devices-title', true).text('Devices');
Viswanath KSP116f0c12016-11-21 00:02:51 +0530112 bottom.append('table');
Simon Hunt083e6fb2017-06-16 16:51:41 -0700113 //TODO: add more details
Simon Hunt6b5a9412016-10-26 19:32:04 -0700114 }
115
Simon Hunt083e6fb2017-06-16 16:51:41 -0700116 function addProp(tbody, label, value) {
Simon Hunt6b5a9412016-10-26 19:32:04 -0700117 var tr = tbody.append('tr');
118
119 function addCell(cls, txt) {
Simon Hunt239f09e2017-05-18 13:10:09 -0700120 tr.append('td').attr('class', cls).text(txt);
Viswanath KSP9fcf9702016-10-23 17:13:29 +0530121 }
Simon Hunt083e6fb2017-06-16 16:51:41 -0700122 addCell('label', label + ' :');
Simon Hunt6b5a9412016-10-26 19:32:04 -0700123 addCell('value', value);
124 }
Viswanath KSP9fcf9702016-10-23 17:13:29 +0530125
Simon Hunt6b5a9412016-10-26 19:32:04 -0700126 function populateTop(details) {
Simon Hunt083e6fb2017-06-16 16:51:41 -0700127 var propLabels = getLionProps();
128
Simon Hunt6b5a9412016-10-26 19:32:04 -0700129 is.loadEmbeddedIcon(iconDiv, 'node', 40);
Simon Hunt239f09e2017-05-18 13:10:09 -0700130 top.select('h2').text(details.id);
Simon Hunt6b5a9412016-10-26 19:32:04 -0700131
132 var tbody = topTable.append('tbody');
133
134 propOrder.forEach(function (prop, i) {
Simon Hunt083e6fb2017-06-16 16:51:41 -0700135 addProp(tbody, propLabels[i], details[prop]);
Simon Hunt6b5a9412016-10-26 19:32:04 -0700136 });
137 }
138
Viswanath KSP116f0c12016-11-21 00:02:51 +0530139 function addDeviceRow(tbody, device) {
140 var tr = tbody.append('tr');
141
142 deviceCols.forEach(function (col) {
Simon Hunt239f09e2017-05-18 13:10:09 -0700143 tr.append('td').text(device[col]);
Viswanath KSP116f0c12016-11-21 00:02:51 +0530144 });
145 }
146
147 function populateBottom(devices) {
148 var table = bottom.select('table'),
149 theader = table.append('thead').append('tr'),
150 tbody = table.append('tbody'),
151 tbWidth, tbHeight;
152
Simon Hunt083e6fb2017-06-16 16:51:41 -0700153 getLionDeviceCols().forEach(function (col) {
Simon Hunt239f09e2017-05-18 13:10:09 -0700154 theader.append('th').text(col);
Viswanath KSP116f0c12016-11-21 00:02:51 +0530155 });
156 devices.forEach(function (device) {
157 addDeviceRow(tbody, device);
158 });
159
160 tbWidth = fs.noPxStyle(tbody, 'width') + scrollSize;
161 tbHeight = pHeight
162 - (fs.noPxStyle(detailsPanel.el()
163 .select('.top'), 'height')
164 + fs.noPxStyle(detailsPanel.el()
165 .select('.devices-title'), 'height')
166 + portsTblPdg);
167
168 table.style({
169 height: tbHeight + 'px',
170 width: tbWidth + 'px',
171 overflow: 'auto',
172 display: 'block'
173 });
174
175 detailsPanel.width(tbWidth + ctnrPdg);
176 }
177
Simon Hunt6b5a9412016-10-26 19:32:04 -0700178 function createDetailsPane() {
179 detailsPanel = ps.createPanel(pName, {
180 width: wSize.width,
181 margin: 0,
182 hideMargin: 0
183 });
184 detailsPanel.el().style({
185 position: 'absolute',
186 top: pStartY + 'px'
187 });
188 $scope.hidePanel = function () { detailsPanel.hide(); };
189 detailsPanel.hide();
190 }
191
192 function populateDetails(details) {
193 setUpPanel();
Viswanath KSP116f0c12016-11-21 00:02:51 +0530194
Simon Hunt6b5a9412016-10-26 19:32:04 -0700195 populateTop(details);
Viswanath KSP116f0c12016-11-21 00:02:51 +0530196 populateBottom(details.devices);
Simon Hunt6b5a9412016-10-26 19:32:04 -0700197 detailsPanel.height(pHeight);
Simon Hunt6b5a9412016-10-26 19:32:04 -0700198 }
199
200 function respDetailsCb(data) {
201 $scope.panelData = data.details;
202 $scope.$apply();
203 }
Viswanath KSP9fcf9702016-10-23 17:13:29 +0530204
205
Bri Prebilic Cole384e8dc2015-04-13 15:51:14 -0700206 angular.module('ovCluster', [])
207 .controller('OvClusterCtrl',
Simon Hunt94104e72017-06-13 11:38:55 -0700208 ['$log', '$scope', 'FnService', 'NavService', 'MastService',
209 'PanelService', 'IconService','WebSocketService',
210 'LionService', 'TableBuilderService',
Bri Prebilic Cole384e8dc2015-04-13 15:51:14 -0700211
Simon Hunt083e6fb2017-06-16 16:51:41 -0700212 function (_$log_, _$scope_, _fs_, _ns_, _mast_, _ps_, _is_, _wss_, lion, tbs) {
Simon Hunt6b5a9412016-10-26 19:32:04 -0700213 var handlers = {};
Viswanath KSP9fcf9702016-10-23 17:13:29 +0530214
Simon Hunt6b5a9412016-10-26 19:32:04 -0700215 $log = _$log_;
216 $scope = _$scope_;
217 fs = _fs_;
218 ns = _ns_;
Simon Hunt6b5a9412016-10-26 19:32:04 -0700219 mast = _mast_;
220 ps = _ps_;
Simon Hunt94104e72017-06-13 11:38:55 -0700221 is = _is_;
222 wss = _wss_;
Viswanath KSP9fcf9702016-10-23 17:13:29 +0530223
Simon Huntc1656ed2017-06-21 16:47:04 -0700224 $scope.lion = lion.bundle('core.view.Cluster');
Simon Hunt6b5a9412016-10-26 19:32:04 -0700225 $scope.panelData = {};
Viswanath KSP9fcf9702016-10-23 17:13:29 +0530226
Simon Hunt6b5a9412016-10-26 19:32:04 -0700227 tbs.buildTable({
228 scope: $scope,
229 selCb: selCb,
230 tag: 'cluster'
Viswanath KSP9fcf9702016-10-23 17:13:29 +0530231 });
232
Simon Hunt6b5a9412016-10-26 19:32:04 -0700233 // details panel handlers
234 handlers[detailsResp] = respDetailsCb;
235 wss.bindHandlers(handlers);
Viswanath KSP9fcf9702016-10-23 17:13:29 +0530236
Simon Hunt6b5a9412016-10-26 19:32:04 -0700237 function selCb($event, row) {
238 if ($scope.selId) {
239 wss.sendEvent(detailsReq, {id: row.id});
240 } else {
241 $scope.hidePanel();
242 }
243 $log.debug('Got a click on:', row);
244 }
245
246 $scope.$on('$destroy', function () {
247 wss.unbindHandlers(handlers);
248 });
249
250 $log.log('OvClusterCtrl has been created');
251 }])
Viswanath KSP9fcf9702016-10-23 17:13:29 +0530252
Simon Hunta271e0a2016-10-26 10:59:14 -0700253 .directive('clusterDetailsPanel',
Viswanath KSP9fcf9702016-10-23 17:13:29 +0530254 ['$rootScope', '$window', '$timeout', 'KeyService',
255 function ($rootScope, $window, $timeout, ks) {
256 return function (scope) {
Simon Hunt083e6fb2017-06-16 16:51:41 -0700257 var unbindWatch,
258 lion = scope.lion;
Viswanath KSP9fcf9702016-10-23 17:13:29 +0530259
260 function heightCalc() {
261 pStartY = fs.noPxStyle(d3.select('.tabular-header'), 'height')
262 + mast.mastHeight() + topPdg;
263 wSize = fs.windowSize(pStartY);
264 pHeight = wSize.height;
265 }
266
267 function initPanel() {
268 heightCalc();
269 createDetailsPane();
270 }
271
272 // Safari has a bug where it renders the fixed-layout table wrong
273 // if you ask for the window's size too early
274 if (scope.onos.browser === 'safari') {
275 $timeout(initPanel);
276 } else {
277 initPanel();
278 }
Viswanath KSP86016272016-10-27 09:49:46 +0530279 // create key bindings to handle panel
280 ks.keyBindings({
Simon Hunt17b4bcb2017-06-21 18:46:34 -0700281 esc: [handleEscape, lion('qh_hint_close_detail')],
Viswanath KSP86016272016-10-27 09:49:46 +0530282 _helpFormat: ['esc']
283 });
284 ks.gestureNotes([
Simon Hunt17b4bcb2017-06-21 18:46:34 -0700285 [lion('click'), lion('qh_hint_click')],
286 [lion('scroll_down'), lion('qh_hint_scroll_down')]
Viswanath KSP86016272016-10-27 09:49:46 +0530287 ]);
Simon Hunta271e0a2016-10-26 10:59:14 -0700288 // if the panelData changes
289 scope.$watch('panelData', function () {
290 if (!fs.isEmptyObject(scope.panelData)) {
291 populateDetails(scope.panelData);
292 detailsPanel.show();
293 }
294 });
295
Viswanath KSP9fcf9702016-10-23 17:13:29 +0530296 // if the window size changes
297 unbindWatch = $rootScope.$watchCollection(
298 function () {
299 return {
300 h: $window.innerHeight,
301 w: $window.innerWidth
302 };
303 }, function () {
304 if (!fs.isEmptyObject(scope.panelData)) {
305 heightCalc();
306 populateDetails(scope.panelData);
307 }
308 }
309 );
310
311 scope.$on('$destroy', function () {
312 unbindWatch();
313 ps.destroyPanel(pName);
314 });
315 };
316 }]);
Bri Prebilic Cole384e8dc2015-04-13 15:51:14 -0700317}());