blob: 11c897d7b7ac457fdf156645160e3deb0398a3f1 [file] [log] [blame]
Simon Hunt1002cd82015-04-23 14:44:03 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Simon Hunt1002cd82015-04-23 14:44:03 -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 -- Flow View Module
19 */
20
21(function () {
22 'use strict';
23
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -070024 // injected references
Viswanath KSP7bdc9172016-10-19 20:19:17 +053025 var $log, $scope, $location, fs, tbs, ns, mast, ps, wss, is, ks;
26
27 // internal state
28 var detailsPanel,
29 pStartY,
30 pHeight,
31 top,
Viswanath KSP70e0d142016-10-28 21:58:32 +053032 topTable,
Viswanath KSPed55ecf2016-12-22 18:15:45 +053033 trmtDiv,
34 selDiv,
35 topSelTable,
36 topTrmtTable,
Viswanath KSP7bdc9172016-10-19 20:19:17 +053037 bottom,
38 iconDiv,
39 nameDiv,
40 wSize;
41
42
43 // constants
44 var topPdg = 28,
45 ctnrPdg = 24,
46 scrollSize = 17,
47 portsTblPdg = 50,
48 htPdg = 479,
49 wtPdg = 532,
50
51 pName = 'flow-details-panel',
52 detailsReq = 'flowDetailsRequest',
Viswanath KSP70e0d142016-10-28 21:58:32 +053053 detailsResp = 'flowDetailsResponse',
54
55 propOrder = [
Simon Hunt9bff5952017-07-13 14:05:09 -070056 'flowId',
57 'state',
58
59 'bytes',
60 'packets',
61 'duration',
62
63 'priority',
64 'tableId',
65 'appId',
66
67 'groupId',
68 'timeout',
69 'permanent'
Viswanath KSP70e0d142016-10-28 21:58:32 +053070 ],
71 friendlyProps = [
Simon Hunt9bff5952017-07-13 14:05:09 -070072 'Flow ID',
73 'State',
74
75 'Bytes',
76 'Packets',
77 'Duration',
78
79 'Flow Priority',
80 'Table ID',
81 'App ID',
82
83 'Group ID',
84 'Timeout',
85 'Permanent'
Viswanath KSP70e0d142016-10-28 21:58:32 +053086 ];
Viswanath KSP7bdc9172016-10-19 20:19:17 +053087
88 function closePanel() {
89 if (detailsPanel.isVisible()) {
90 $scope.selId = null;
91 detailsPanel.hide();
92 return true;
93 }
94 return false;
95 }
96
97 function addCloseBtn(div) {
98 is.loadEmbeddedIcon(div, 'close', 20);
99 div.on('click', closePanel);
100 }
101
Viswanath KSP70e0d142016-10-28 21:58:32 +0530102 function handleEscape() {
103 return closePanel();
104 }
105
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530106 function setUpPanel() {
107 var container, closeBtn, tblDiv;
108 detailsPanel.empty();
109
110 container = detailsPanel.append('div').classed('container', true);
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530111 top = container.append('div').classed('top', true);
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530112 selDiv = container.append('div').classed('top', true);
Simon Hunt9bff5952017-07-13 14:05:09 -0700113 trmtDiv = container.append('div').classed('top', true);
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530114 closeBtn = top.append('div').classed('close-btn', true);
115 addCloseBtn(closeBtn);
116 iconDiv = top.append('div').classed('dev-icon', true);
117 top.append('h2');
Viswanath KSP70e0d142016-10-28 21:58:32 +0530118 topTable = top.append('div').classed('top-content', true)
119 .append('table');
Simon Hunt9bff5952017-07-13 14:05:09 -0700120
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530121 top.append('hr');
Simon Hunt9bff5952017-07-13 14:05:09 -0700122
Simon Hunt239f09e2017-05-18 13:10:09 -0700123 selDiv.append('h2').text('Selector');
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530124 topSelTable = selDiv.append('div').classed('top-content', true)
125 .append('table');
126
Simon Hunt9bff5952017-07-13 14:05:09 -0700127 selDiv.append('hr');
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530128
Simon Hunt9bff5952017-07-13 14:05:09 -0700129 trmtDiv.append('h2').text('Treatment');
130 topTrmtTable = trmtDiv.append('div').classed('top-content', true)
131 .append('table');
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530132 }
133
Viswanath KSP70e0d142016-10-28 21:58:32 +0530134 function addProp(tbody, index, value) {
135 var tr = tbody.append('tr');
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530136
Viswanath KSP70e0d142016-10-28 21:58:32 +0530137 function addCell(cls, txt) {
Simon Hunt239f09e2017-05-18 13:10:09 -0700138 tr.append('td').attr('class', cls).text(txt);
Viswanath KSP70e0d142016-10-28 21:58:32 +0530139 }
140 addCell('label', friendlyProps[index] + ' :');
141 addCell('value', value);
142 }
143
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530144 function populateTable(tbody, label, value) {
145 var tr = tbody.append('tr');
146
147 function addCell(cls, txt) {
Simon Hunt239f09e2017-05-18 13:10:09 -0700148 tr.append('td').attr('class', cls).text(txt);
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530149 }
150 addCell('label', label + ' :');
151 addCell('value', value);
152 }
153
Viswanath KSP70e0d142016-10-28 21:58:32 +0530154 function populateTop(details) {
155 is.loadEmbeddedIcon(iconDiv, 'flowTable', 40);
Simon Hunt239f09e2017-05-18 13:10:09 -0700156 top.select('h2').text(details.flowId);
Viswanath KSP70e0d142016-10-28 21:58:32 +0530157
158 var tbody = topTable.append('tbody');
159
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530160 var topSelTablebody = topSelTable.append('tbody');
161 var selectorString = details['selector'];
162 var selectors = selectorString.split(',');
163
164 var topTrmtTablebody = topTrmtTable.append('tbody');
165 var treatmentString = details['treatment'];
166 var treatment = treatmentString.split(',');
167
Viswanath KSP70e0d142016-10-28 21:58:32 +0530168 propOrder.forEach(function (prop, i) {
169 addProp(tbody, i, details[prop]);
170 });
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530171
172 selectors.forEach(function (sel) {
Jian Li70c460a2017-05-11 02:26:07 +0900173 var selArray = sel.match(/^([^:]*):([\s\S]*)/);
174 populateTable(topSelTablebody, selArray[1], selArray[2]);
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530175 });
176
177 treatment.forEach(function (sel) {
Jian Li70c460a2017-05-11 02:26:07 +0900178 var selArray = sel.match(/^([^:]*):([\s\S]*)/);
179 populateTable(topTrmtTable, selArray[1], selArray[2]);
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530180 });
181
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530182 }
183
184 function createDetailsPane() {
185 detailsPanel = ps.createPanel(pName, {
186 width: wSize.width,
187 margin: 0,
188 hideMargin: 0
189 });
190 detailsPanel.el().style({
191 position: 'absolute',
192 top: pStartY + 'px'
193 });
194 $scope.hidePanel = function () { detailsPanel.hide(); };
195 detailsPanel.hide();
196 }
197
198 function populateDetails(details) {
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530199 setUpPanel();
200 populateTop(details);
201
202 //ToDo add more details
203 detailsPanel.height(pHeight);
204 detailsPanel.width(wtPdg);
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530205 }
206
207 function respDetailsCb(data) {
Viswanath KSP70e0d142016-10-28 21:58:32 +0530208 $log.debug("Got response from server :", data);
209 $scope.panelData = data.details;
210 $scope.$apply();
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530211 }
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700212
Simon Hunt1002cd82015-04-23 14:44:03 -0700213 angular.module('ovFlow', [])
214 .controller('OvFlowCtrl',
Bri Prebilic Cole3d4d01c2015-04-30 13:48:36 -0700215 ['$log', '$scope', '$location',
Bri Prebilic Cole9b1fb9a2015-07-01 13:57:11 -0700216 'FnService', 'TableBuilderService', 'NavService',
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530217 'MastService', 'PanelService', 'KeyService', 'IconService',
218 'WebSocketService',
Simon Hunt1002cd82015-04-23 14:44:03 -0700219
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530220 function (_$log_, _$scope_, _$location_, _fs_, _tbs_, _ns_,
221 _mast_, _ps_, _ks_, _is_, _wss_) {
222 var params,
223 handlers = {};
224
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700225 $log = _$log_;
226 $scope = _$scope_;
227 $location = _$location_;
228 fs = _fs_;
229 tbs = _tbs_;
Bri Prebilic Cole9b1fb9a2015-07-01 13:57:11 -0700230 ns = _ns_;
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530231 is = _is_;
232 wss = _wss_;
233 mast = _mast_;
234 ps = _ps_;
Simon Hunt20856ec2015-11-16 15:58:14 -0800235 $scope.deviceTip = 'Show device table';
Bri Prebilic Coleeef67ae2015-07-01 16:26:59 -0700236 $scope.portTip = 'Show port view for this device';
237 $scope.groupTip = 'Show group view for this device';
Jian Li1f544732015-12-30 23:36:37 -0800238 $scope.meterTip = 'Show meter view for selected device';
Kavitha Alagesaneaf614c2016-08-22 23:46:05 -0700239 $scope.briefTip = 'Switch to brief view';
240 $scope.detailTip = 'Switch to detailed view';
241 $scope.brief = true;
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700242 params = $location.search();
243 if (params.hasOwnProperty('devId')) {
Bri Prebilic Colee568ead2015-05-01 09:51:28 -0700244 $scope.devId = params['devId'];
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700245 }
246
247 tbs.buildTable({
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700248 scope: $scope,
249 tag: 'flow',
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530250 selCb: selCb,
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700251 query: params
252 });
Bri Prebilic Cole3d4d01c2015-04-30 13:48:36 -0700253
Bri Prebilic Cole9b1fb9a2015-07-01 13:57:11 -0700254 $scope.nav = function (path) {
255 if ($scope.devId) {
256 ns.navTo(path, { devId: $scope.devId });
257 }
258 };
259
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530260 // details panel handlers
261 handlers[detailsResp] = respDetailsCb;
262 wss.bindHandlers(handlers);
263
264 function selCb($event, row) {
265 if ($scope.selId) {
266 wss.sendEvent(detailsReq, {flowId: row.id, appId: row.appId});
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530267 } else {
268 $scope.hidePanel();
269 }
270 $log.debug('Got a click on:', row);
271 }
272
Viswanath KSP70e0d142016-10-28 21:58:32 +0530273 $scope.$on('$destroy', function () {
274 wss.unbindHandlers(handlers);
275 });
276
Kavitha Alagesaneaf614c2016-08-22 23:46:05 -0700277 $scope.briefToggle = function () {
278 $scope.brief = !$scope.brief;
279 };
280
sisubram9ada8d72016-09-02 13:54:40 +0530281 Object.defineProperty($scope, "queryFilter", {
282 get: function() {
Simon Huntc8f06d92016-09-28 17:28:26 -0700283 var out = {};
284 out[$scope.queryBy || "$"] = $scope.queryTxt;
285 return out;
sisubram9ada8d72016-09-02 13:54:40 +0530286 }
287 });
288
Simon Hunt1002cd82015-04-23 14:44:03 -0700289 $log.log('OvFlowCtrl has been created');
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530290 }])
291
292 .directive('flowDetailsPanel',
293 ['$rootScope', '$window', '$timeout', 'KeyService',
294 function ($rootScope, $window, $timeout, ks) {
295 return function (scope) {
296 var unbindWatch;
297
298 function heightCalc() {
299 pStartY = fs.noPxStyle(d3.select('.tabular-header'), 'height')
300 + mast.mastHeight() + topPdg;
301 wSize = fs.windowSize(pStartY);
302 pHeight = wSize.height;
303 }
304
305 function initPanel() {
306 heightCalc();
307 createDetailsPane();
308 }
309
310 // Safari has a bug where it renders the fixed-layout table wrong
311 // if you ask for the window's size too early
312 if (scope.onos.browser === 'safari') {
313 $timeout(initPanel);
314 } else {
315 initPanel();
316 }
Viswanath KSP70e0d142016-10-28 21:58:32 +0530317 // create key bindings to handle panel
318 ks.keyBindings({
319 esc: [handleEscape, 'Close the details panel'],
320 _helpFormat: ['esc']
321 });
322 ks.gestureNotes([
323 ['click', 'Select a row to show cluster node details'],
324 ['scroll down', 'See available cluster nodes']
325 ]);
326 // if the panelData changes
327 scope.$watch('panelData', function () {
328 if (!fs.isEmptyObject(scope.panelData)) {
329 populateDetails(scope.panelData);
330 detailsPanel.show();
331 }
332 });
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530333 // if the window size changes
334 unbindWatch = $rootScope.$watchCollection(
335 function () {
336 return {
337 h: $window.innerHeight,
338 w: $window.innerWidth
339 };
340 }, function () {
341 if (!fs.isEmptyObject(scope.panelData)) {
342 heightCalc();
343 populateDetails(scope.panelData);
344 }
345 }
346 );
347
348 scope.$on('$destroy', function () {
349 unbindWatch();
350 ps.destroyPanel(pName);
351 });
352 };
353 }]);
354
Simon Hunt1002cd82015-04-23 14:44:03 -0700355}());