blob: 0f41b148b3723a019f4f258d37338ff0dc82381c [file] [log] [blame]
Simon Hunt1002cd82015-04-23 14:44:03 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
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
ArturoF Velasco604ad0b2018-01-03 00:43:58 +010025 var $log, $scope, $location, fs, tbs, ns, mast, ps, wss, is, ls;
Viswanath KSP7bdc9172016-10-19 20:19:17 +053026
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 topSelTable,
Simon Hunt8f057ee2017-07-19 14:05:26 -070034 topTrtTable,
Viswanath KSP7bdc9172016-10-19 20:19:17 +053035 iconDiv,
Viswanath KSP7bdc9172016-10-19 20:19:17 +053036 wSize;
37
Viswanath KSP7bdc9172016-10-19 20:19:17 +053038 // constants
39 var topPdg = 28,
Thomas Vachuska3da62122017-10-04 13:49:12 -070040 wtPdg = 400,
Viswanath KSP7bdc9172016-10-19 20:19:17 +053041
42 pName = 'flow-details-panel',
43 detailsReq = 'flowDetailsRequest',
Viswanath KSP70e0d142016-10-28 21:58:32 +053044 detailsResp = 'flowDetailsResponse',
45
46 propOrder = [
Simon Hunt9bff5952017-07-13 14:05:09 -070047 'flowId',
48 'state',
49
50 'bytes',
51 'packets',
52 'duration',
53
54 'priority',
Yi Tseng18177a52017-09-08 01:26:59 -070055 'tableName',
Simon Hunt36b658d2017-07-14 16:20:11 -070056 'appName',
Simon Hunt9bff5952017-07-13 14:05:09 -070057 'appId',
58
59 'groupId',
Thomas Vachuska3da62122017-10-04 13:49:12 -070060 'idleTimeout',
61 'hardTimeout',
Steven Burrows1c2a9682017-07-14 16:52:46 +010062 'permanent',
Viswanath KSP70e0d142016-10-28 21:58:32 +053063 ];
Viswanath KSP7bdc9172016-10-19 20:19:17 +053064
ArturoF Velasco604ad0b2018-01-03 00:43:58 +010065// deferred localization strings
66 var warnDeactivate,
67 warnOwnRisk,
68 friendlyProps,
69 lion;
70
71 function doLion() {
72 lion = ls.bundle('core.view.Flow');
73
74 warnDeactivate = lion('dlg_warn_deactivate');
75 warnOwnRisk = lion('dlg_warn_own_risk');
76
77 friendlyProps = [
78 lion('flowId'), lion('state'), lion('bytes'), lion('packets'),
79 lion('duration'), lion('priority'),lion('tableName'),lion('appName'),lion('appId'),
80 lion('groupId'),lion('idleTimeout'),lion('hardTimeout'),lion('permanent')
81 ];
82 }
83
84
Viswanath KSP7bdc9172016-10-19 20:19:17 +053085 function closePanel() {
86 if (detailsPanel.isVisible()) {
87 $scope.selId = null;
88 detailsPanel.hide();
89 return true;
90 }
91 return false;
92 }
93
94 function addCloseBtn(div) {
95 is.loadEmbeddedIcon(div, 'close', 20);
96 div.on('click', closePanel);
97 }
98
Viswanath KSP70e0d142016-10-28 21:58:32 +053099 function handleEscape() {
100 return closePanel();
101 }
102
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530103 function setUpPanel() {
Simon Huntcaed0412017-08-12 13:49:17 -0700104 var container, closeBtn;
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530105 detailsPanel.empty();
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530106 container = detailsPanel.append('div').classed('container', true);
Simon Hunt8f057ee2017-07-19 14:05:26 -0700107
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530108 top = container.append('div').classed('top', true);
109 closeBtn = top.append('div').classed('close-btn', true);
110 addCloseBtn(closeBtn);
111 iconDiv = top.append('div').classed('dev-icon', true);
112 top.append('h2');
Viswanath KSP70e0d142016-10-28 21:58:32 +0530113 topTable = top.append('div').classed('top-content', true)
114 .append('table');
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530115 top.append('hr');
Simon Hunt9bff5952017-07-13 14:05:09 -0700116
Thomas Vachuska3da62122017-10-04 13:49:12 -0700117 top.append('h3').text('Selector');
118 topSelTable = top.append('div').classed('top-content', true).append('table');
119 top.append('hr');
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530120
Thomas Vachuska3da62122017-10-04 13:49:12 -0700121 top.append('h3').text('Treatment');
122 topTrtTable = top.append('div').classed('top-content', true).append('table');
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530123 }
124
Simon Hunt8f057ee2017-07-19 14:05:26 -0700125 function addProp(tbody, label, value) {
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530126 var tr = tbody.append('tr');
127
128 function addCell(cls, txt) {
Simon Hunt239f09e2017-05-18 13:10:09 -0700129 tr.append('td').attr('class', cls).text(txt);
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530130 }
131 addCell('label', label + ' :');
132 addCell('value', value);
133 }
134
Simon Hunt8f057ee2017-07-19 14:05:26 -0700135
136 function getLionClearDeferred() {
137 // TODO: Localization...
138 return 'Clear deferred';
139 }
140
Viswanath KSP70e0d142016-10-28 21:58:32 +0530141 function populateTop(details) {
142 is.loadEmbeddedIcon(iconDiv, 'flowTable', 40);
Simon Hunt239f09e2017-05-18 13:10:09 -0700143 top.select('h2').text(details.flowId);
Viswanath KSP70e0d142016-10-28 21:58:32 +0530144
Simon Hunt8f057ee2017-07-19 14:05:26 -0700145 var tbody = topTable.append('tbody'),
146 tbodySel = topSelTable.append('tbody'),
147 tbodyTrt = topTrtTable.append('tbody'),
148 selArray = details.selector,
149 treat = details.treatment,
150 propLabels = getLionProps();
Viswanath KSP70e0d142016-10-28 21:58:32 +0530151
Simon Hunt8f057ee2017-07-19 14:05:26 -0700152 function addLabVal(tbody, lv) {
153 var bits = lv.match(/^([^:]*):(.*)/);
154 addProp(tbody, bits[1], bits[2]);
155 }
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530156
Simon Hunt8f057ee2017-07-19 14:05:26 -0700157 function popInstrList(items, tag) {
158 items.forEach(function (item) {
159 addLabVal(tbodyTrt, tag + item);
160 });
161 }
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530162
Simon Hunt8f057ee2017-07-19 14:05:26 -0700163 // basic flow properties
Viswanath KSP70e0d142016-10-28 21:58:32 +0530164 propOrder.forEach(function (prop, i) {
Simon Hunt8f057ee2017-07-19 14:05:26 -0700165 addProp(tbody, propLabels[i], details[prop]);
Viswanath KSP70e0d142016-10-28 21:58:32 +0530166 });
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530167
Simon Hunt8f057ee2017-07-19 14:05:26 -0700168 // selection criteria
169 selArray.forEach(function (lv) {
170 addLabVal(tbodySel, lv);
Viswanath KSPed55ecf2016-12-22 18:15:45 +0530171 });
172
Simon Hunt8f057ee2017-07-19 14:05:26 -0700173 // traffic treatment
174 treat.immed && popInstrList(treat.immed, '[imm]');
175 treat.defer && popInstrList(treat.defer, '[def]');
176 treat.meter && addLabVal(tbodyTrt, treat.meter);
177 treat.table && addLabVal(tbodyTrt, treat.table);
178 treat.meta && addLabVal(tbodyTrt, treat.meta);
179 addProp(tbodyTrt, getLionClearDeferred(), treat.clearDef);
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530180 }
181
182 function createDetailsPane() {
183 detailsPanel = ps.createPanel(pName, {
184 width: wSize.width,
185 margin: 0,
Steven Burrows1c2a9682017-07-14 16:52:46 +0100186 hideMargin: 0,
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530187 });
188 detailsPanel.el().style({
189 position: 'absolute',
Steven Burrows1c2a9682017-07-14 16:52:46 +0100190 top: pStartY + 'px',
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530191 });
192 $scope.hidePanel = function () { detailsPanel.hide(); };
193 detailsPanel.hide();
194 }
195
196 function populateDetails(details) {
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530197 setUpPanel();
198 populateTop(details);
199
Steven Burrows1c2a9682017-07-14 16:52:46 +0100200 // ToDo add more details
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530201 detailsPanel.height(pHeight);
202 detailsPanel.width(wtPdg);
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530203 }
204
205 function respDetailsCb(data) {
Steven Burrows1c2a9682017-07-14 16:52:46 +0100206 $log.debug('Got response from server :', data);
Viswanath KSP70e0d142016-10-28 21:58:32 +0530207 $scope.panelData = data.details;
208 $scope.$apply();
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530209 }
Bri Prebilic Colecdc188d2015-04-24 16:40:11 -0700210
Simon Hunt1002cd82015-04-23 14:44:03 -0700211 angular.module('ovFlow', [])
Steven Burrows1c2a9682017-07-14 16:52:46 +0100212 .controller('OvFlowCtrl',
213 ['$log', '$scope', '$location',
214 'FnService', 'TableBuilderService', 'NavService',
215 'MastService', 'PanelService', 'KeyService', 'IconService',
ArturoF Velasco604ad0b2018-01-03 00:43:58 +0100216 'WebSocketService','LionService',
Simon Hunt1002cd82015-04-23 14:44:03 -0700217
Steven Burrows1c2a9682017-07-14 16:52:46 +0100218 function (_$log_, _$scope_, _$location_, _fs_, _tbs_, _ns_,
ArturoF Velasco604ad0b2018-01-03 00:43:58 +0100219 _mast_, _ps_, _ks_, _is_, _wss_, _ls_) {
Steven Burrows1c2a9682017-07-14 16:52:46 +0100220 var params,
221 handlers = {};
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530222
Steven Burrows1c2a9682017-07-14 16:52:46 +0100223 $log = _$log_;
224 $scope = _$scope_;
225 $location = _$location_;
226 fs = _fs_;
227 tbs = _tbs_;
228 ns = _ns_;
229 is = _is_;
230 wss = _wss_;
231 mast = _mast_;
232 ps = _ps_;
ArturoF Velasco604ad0b2018-01-03 00:43:58 +0100233 ls = _ls_;
234
235 doLion();
236
237 $scope.lion = lion;
238
239 $scope.deviceTip = lion('tt_ctl_show_device');
240 $scope.portTip = lion('tt_ctl_show_port');
241 $scope.groupTip = lion('tt_ctl_show_group');
242 $scope.meterTip = lion('tt_ctl_show_meter');
243 $scope.pipeconfTip = lion('tt_ctl_show_pipeconf');
244 $scope.briefTip = lion('tt_ctl_switcth_brief');
245 $scope.detailTip = lion('tt_ctl_switcth_detailed');
Yi Tsenga87b40c2017-09-10 00:59:03 -0700246
Steven Burrows1c2a9682017-07-14 16:52:46 +0100247 $scope.brief = true;
248 params = $location.search();
249 if (params.hasOwnProperty('devId')) {
250 $scope.devId = params['devId'];
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530251 }
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530252
Steven Burrows1c2a9682017-07-14 16:52:46 +0100253 tbs.buildTable({
254 scope: $scope,
255 tag: 'flow',
256 selCb: selCb,
257 query: params,
258 });
259
260 $scope.nav = function (path) {
261 if ($scope.devId) {
262 ns.navTo(path, { devId: $scope.devId });
263 }
264 };
265
266 // details panel handlers
267 handlers[detailsResp] = respDetailsCb;
268 wss.bindHandlers(handlers);
269
270 function selCb($event, row) {
271 if ($scope.selId) {
Simon Huntf257a962017-08-25 18:58:47 -0700272 wss.sendEvent(detailsReq, {
273 flowId: row.id,
274 appId: row.appId
275 });
Steven Burrows1c2a9682017-07-14 16:52:46 +0100276 } else {
277 $scope.hidePanel();
278 }
279 $log.debug('Got a click on:', row);
280 }
281
282 $scope.$on('$destroy', function () {
283 wss.unbindHandlers(handlers);
284 });
285
286 $scope.briefToggle = function () {
287 $scope.brief = !$scope.brief;
288 };
289
290 Object.defineProperty($scope, 'queryFilter', {
291 get: function () {
292 var out = {};
293 out[$scope.queryBy || '$'] = $scope.queryTxt;
294 return out;
295 },
296 });
297
298 $log.log('OvFlowCtrl has been created');
299 }])
300
301 .directive('flowDetailsPanel',
302 ['$rootScope', '$window', '$timeout', 'KeyService',
Simon Huntf257a962017-08-25 18:58:47 -0700303 function ($rootScope, $window, $timeout, ks) {
304 return function (scope) {
305 var unbindWatch;
Steven Burrows1c2a9682017-07-14 16:52:46 +0100306
Simon Huntf257a962017-08-25 18:58:47 -0700307 function heightCalc() {
308 var tabhead = d3.select('.tabular-header');
Steven Burrows1c2a9682017-07-14 16:52:46 +0100309
Simon Huntf257a962017-08-25 18:58:47 -0700310 pStartY = fs.noPxStyle(tabhead, 'height') +
311 mast.mastHeight() + topPdg;
312 wSize = fs.windowSize(pStartY);
313 pHeight = wSize.height;
314 }
Steven Burrows1c2a9682017-07-14 16:52:46 +0100315
Simon Huntf257a962017-08-25 18:58:47 -0700316 function initPanel() {
317 heightCalc();
318 createDetailsPane();
319 }
320
321 // Safari has a bug where it renders the fixed-layout
322 // table wrong if you ask for the window's size too early
323 if (scope.onos.browser === 'safari') {
324 $timeout(initPanel);
325 } else {
326 initPanel();
327 }
328 // create key bindings to handle panel
329 ks.keyBindings({
330 esc: [handleEscape, 'Close the details panel'],
331 _helpFormat: ['esc'],
332 });
333 ks.gestureNotes([
334 ['click', 'Select a row to show cluster node details'],
335 ['scroll down', 'See available cluster nodes'],
336 ]);
337 // if the panelData changes
338 scope.$watch('panelData', function () {
339 if (!fs.isEmptyObject(scope.panelData)) {
340 populateDetails(scope.panelData);
341 detailsPanel.show();
Steven Burrows1c2a9682017-07-14 16:52:46 +0100342 }
Simon Huntf257a962017-08-25 18:58:47 -0700343 });
344 // if the window size changes
345 unbindWatch = $rootScope.$watchCollection(
346 function () {
347 return {
348 h: $window.innerHeight,
349 w: $window.innerWidth,
350 };
351 }, function () {
Steven Burrows1c2a9682017-07-14 16:52:46 +0100352 if (!fs.isEmptyObject(scope.panelData)) {
Simon Huntf257a962017-08-25 18:58:47 -0700353 heightCalc();
Steven Burrows1c2a9682017-07-14 16:52:46 +0100354 populateDetails(scope.panelData);
Steven Burrows1c2a9682017-07-14 16:52:46 +0100355 }
Simon Huntf257a962017-08-25 18:58:47 -0700356 }
357 );
Steven Burrows1c2a9682017-07-14 16:52:46 +0100358
Simon Huntf257a962017-08-25 18:58:47 -0700359 scope.$on('$destroy', function () {
360 unbindWatch();
361 ps.destroyPanel(pName);
362 });
363 };
364 }]);
Viswanath KSP7bdc9172016-10-19 20:19:17 +0530365
Simon Hunt1002cd82015-04-23 14:44:03 -0700366}());