blob: c2462b20a2ea46468c07e03de4a62362b91b5f6d [file] [log] [blame]
Jian Lia23f46d2017-05-02 18:07:31 +09001/*
2 * Copyright 2017-present Open Networking Laboratory
3 *
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 -- Mapping Management View Module
19 */
20(function () {
21 'use strict';
22
23 // injected references
Jian Libdf8ae52017-05-05 01:31:55 +090024 var $log, $scope, $location, fs, tbs, mast, ps, wss, is, ks;
25
26 // internal state
27 var detailsPanel,
28 pStartY,
29 pHeight,
30 top,
31 topTable,
32 keyDiv,
33 valueDiv,
34 topKeyTable,
35 bottomValueTable,
36 iconDiv,
37 nameDiv,
38 wSize;
39
40 // constants
41 var topPdg = 28,
42 ctnrPdg = 24,
43 scrollSize = 17,
44 portsTblPdg = 50,
45 htPdg = 479,
46 wtPdg = 532,
47
48 pName = 'mapping-details-panel',
49 detailsReq = 'mappingDetailsRequest',
50 detailsResp = 'mappingDetailsResponse',
51
52 propOrder = [
53 'mappingId', 'type', 'state', 'mappingAction'
54 ],
55 friendlyProps = [
56 'Mapping ID', 'Store Type', 'State', 'Mapping Action'
57 ],
58
59 treatmentPropOrder = [
60 'address', 'unicastPriority', 'unicastWeight', 'multicastPriority',
61 'multicastWeight'
62 ],
63 treatmentFriendlyProps = [
64 'Address', 'U P', 'U W', 'M P', 'M W'
65 ];
66
67 function closePanel() {
68 if (detailsPanel.isVisible()) {
69 $scope.selId = null;
70 detailsPanel.hide();
71 return true;
72 }
73 return false;
74 }
75
76 function addCloseBtn(div) {
77 is.loadEmbeddedIcon(div, 'close', 20);
78 div.on('click', closePanel);
79 }
80
81 function handleEscape() {
82 return closePanel();
83 }
84
85 function setUpPanel() {
86 var container, closeBtn, tblDiv;
87 detailsPanel.empty();
88
89 container = detailsPanel.append('div').classed('container', true);
90 top = container.append('div').classed('top', true);
91 keyDiv = container.append('div').classed('top', true);
92 valueDiv = container.append('div').classed('bottom', true);
93 closeBtn = top.append('div').classed('close-btn', true);
94 addCloseBtn(closeBtn);
95 iconDiv = top.append('div').classed('dev-icon', true);
96 top.append('h2');
97 topTable = top.append('div').classed('top-content', true)
98 .append('table');
99 top.append('hr');
Simon Hunt239f09e2017-05-18 13:10:09 -0700100 keyDiv.append('h2').text('Mapping Key');
Jian Libdf8ae52017-05-05 01:31:55 +0900101 topKeyTable = keyDiv.append('div').classed('top-content', true)
102 .append('table');
103 keyDiv.append('hr');
Simon Hunt239f09e2017-05-18 13:10:09 -0700104 valueDiv.append('h2').text('Mapping Value');
Jian Libdf8ae52017-05-05 01:31:55 +0900105 bottomValueTable = valueDiv.append('table');
106
107 // TODO: add more details later
108 }
109
110 function addProp(tbody, index, value) {
111 var tr = tbody.append('tr');
112
113 function addCell(cls, txt) {
Simon Hunt239f09e2017-05-18 13:10:09 -0700114 tr.append('td').attr('class', cls).text(txt);
Jian Libdf8ae52017-05-05 01:31:55 +0900115 }
116 addCell('label', friendlyProps[index] + ' :');
117 addCell('value', value);
118 }
119
120 function populateTable(tbody, label, value) {
121 var tr = tbody.append('tr');
122
123 function addCell(cls, txt) {
Simon Hunt239f09e2017-05-18 13:10:09 -0700124 tr.append('td').attr('class', cls).text(txt);
Jian Libdf8ae52017-05-05 01:31:55 +0900125 }
126 addCell('label', label + ' :');
127 addCell('value', value);
128 }
129
130 function populateTop(details) {
131 is.loadEmbeddedIcon(iconDiv, 'mappingTable', 40);
Simon Hunt239f09e2017-05-18 13:10:09 -0700132 top.select('h2').text(details.mappingId);
Jian Libdf8ae52017-05-05 01:31:55 +0900133
134 var tbody = topTable.append('tbody');
135
136 var topKeyTablebody = topKeyTable.append('tbody');
137 var keyObject = details['mappingKey'];
138 var address = keyObject.address;
139
140 var bottomValueTableheader = bottomValueTable.append('thead').append('tr')
141 var bottomValueTablebody = bottomValueTable.append('tbody');
142 var valueObject = details['mappingValue'];
143 var treatments = valueObject.mappingTreatments;
144
145 propOrder.forEach(function (prop, i) {
146 addProp(tbody, i, details[prop]);
147 });
148
Simon Hunt239f09e2017-05-18 13:10:09 -0700149 topKeyTablebody.append('tr').append('td').attr('class', 'value').text(address);
Jian Libdf8ae52017-05-05 01:31:55 +0900150
151 treatmentFriendlyProps.forEach(function (col) {
Simon Hunt239f09e2017-05-18 13:10:09 -0700152 bottomValueTableheader.append('th').text(col);
Jian Libdf8ae52017-05-05 01:31:55 +0900153 });
154 treatments.forEach(function (sel) {
155 populateTreatmentTable(bottomValueTablebody, sel);
156 });
157 }
158
159 function populateTreatmentTable(tbody, treatment) {
160 var tr = tbody.append('tr');
161 treatmentPropOrder.forEach(function (prop) {
162 addTreatmentProp(tr, treatment[prop]);
163 });
164 }
165
166 function addTreatmentProp(tr, value) {
167 function addCell(cls, txt) {
Simon Hunt239f09e2017-05-18 13:10:09 -0700168 tr.append('td').attr('class', cls).text(txt);
Jian Libdf8ae52017-05-05 01:31:55 +0900169 }
170 addCell('value', value);
171 }
172
173 function createDetailsPane() {
174 detailsPanel = ps.createPanel(pName, {
175 width: wSize.width,
176 margin: 0,
177 hideMargin: 0
178 });
179 detailsPanel.el().style({
180 position: 'absolute',
181 top: pStartY + 'px'
182 });
183 $scope.hidePanel = function () { detailsPanel.hide(); };
184 detailsPanel.hide();
185 }
186
187 function populateDetails(details) {
188 setUpPanel();
189 populateTop(details);
190
191 //ToDo add more details
192 detailsPanel.height(pHeight);
193 detailsPanel.width(wtPdg);
194 }
195
196 function respDetailsCb(data) {
197 $log.debug("Got response from server :", data);
198 $scope.panelData = data.details;
199 $scope.$apply();
200 }
Jian Lia23f46d2017-05-02 18:07:31 +0900201
202 angular.module('ovMapping', [])
203 .controller('OvMappingCtrl',
Jian Libdf8ae52017-05-05 01:31:55 +0900204 ['$log', '$scope', '$location', 'FnService', 'TableBuilderService',
205 'MastService', 'PanelService', 'KeyService', 'IconService',
206 'WebSocketService',
Jian Lia23f46d2017-05-02 18:07:31 +0900207
Jian Libdf8ae52017-05-05 01:31:55 +0900208 function (_$log_, _$scope_, _$location_, _fs_, _tbs_, _mast_, _ps_,
209 _ks_, _is_, _wss_) {
210 var params,
211 handlers = {};
Jian Li4689f812017-05-04 07:30:35 +0900212
Jian Lia23f46d2017-05-02 18:07:31 +0900213 $log = _$log_;
214 $scope = _$scope_;
215 $location = _$location_;
Jian Libdf8ae52017-05-05 01:31:55 +0900216 fs = _fs_;
Jian Li4689f812017-05-04 07:30:35 +0900217 tbs = _tbs_;
Jian Libdf8ae52017-05-05 01:31:55 +0900218 mast = _mast_;
219 ps = _ps_;
220 ks = _ks_;
221 is = _is_;
222 wss = _wss_;
Jian Li7d73ff92017-05-06 00:49:17 +0900223 $scope.deviceTip = 'Show device table';
224 $scope.briefTip = 'Switch to brief view';
225 $scope.detailTip = 'Switch to detailed view';
226 $scope.brief = true;
Jian Li4689f812017-05-04 07:30:35 +0900227
228 params = $location.search();
229 if (params.hasOwnProperty('devId')) {
230 $scope.devId = params['devId'];
231 }
232
233 tbs.buildTable({
234 scope: $scope,
235 tag: 'mapping',
Jian Libdf8ae52017-05-05 01:31:55 +0900236 selCb: selCb,
Jian Li4689f812017-05-04 07:30:35 +0900237 query: params
238 });
Jian Lia23f46d2017-05-02 18:07:31 +0900239
Jian Libdf8ae52017-05-05 01:31:55 +0900240 // details panel handlers
241 handlers[detailsResp] = respDetailsCb;
242 wss.bindHandlers(handlers);
243
244 function selCb($event, row) {
245 if ($scope.selId) {
246 wss.sendEvent(detailsReq, {mappingId: row.id, type: row.type});
247 } else {
248 $scope.hidePanel();
249 }
250 $log.debug('Got a click on:', row);
251 }
252
253 $scope.$on('$destroy', function () {
254 wss.unbindHandlers(handlers);
255 });
256
Jian Li7d73ff92017-05-06 00:49:17 +0900257 $scope.briefToggle = function () {
258 $scope.brief = !$scope.brief;
259 };
260
261 Object.defineProperty($scope, "queryFilter", {
262 get: function() {
263 var out = {};
264 out[$scope.queryBy || "$"] = $scope.queryTxt;
265 return out;
266 }
267 });
268
Jian Lia23f46d2017-05-02 18:07:31 +0900269 $log.log('OvMappingCtrl has been created');
Jian Libdf8ae52017-05-05 01:31:55 +0900270 }])
271
272 .directive('mappingDetailsPanel',
273 ['$rootScope', '$window', '$timeout', 'KeyService',
274 function ($rootScope, $window, $timeout, ks) {
275 return function (scope) {
276 var unbindWatch;
277
278 function heightCalc() {
279 pStartY = fs.noPxStyle(d3.select('.tabular-header'), 'height')
280 + mast.mastHeight() + topPdg;
281 wSize = fs.windowSize(pStartY);
282 pHeight = wSize.height;
283 }
284
285 function initPanel() {
286 heightCalc();
287 createDetailsPane();
288 }
289
290 // Safari has a bug where it renders the fixed-layout table wrong
291 // if you ask for the window's size too early
292 if (scope.onos.browser === 'safari') {
293 $timeout(initPanel);
294 } else {
295 initPanel();
296 }
297 // create key bindings to handle panel
298 ks.keyBindings({
299 esc: [handleEscape, 'Close the details panel'],
300 _helpFormat: ['esc']
301 });
302 ks.gestureNotes([
303 ['click', 'Select a row to show cluster node details'],
304 ['scroll down', 'See available cluster nodes']
305 ]);
306 // if the panelData changes
307 scope.$watch('panelData', function () {
308 if (!fs.isEmptyObject(scope.panelData)) {
309 populateDetails(scope.panelData);
310 detailsPanel.show();
311 }
312 });
313 // if the window size changes
314 unbindWatch = $rootScope.$watchCollection(
315 function () {
316 return {
317 h: $window.innerHeight,
318 w: $window.innerWidth
319 };
320 }, function () {
321 if (!fs.isEmptyObject(scope.panelData)) {
322 heightCalc();
323 populateDetails(scope.panelData);
324 }
325 }
326 );
327
328 scope.$on('$destroy', function () {
329 unbindWatch();
330 ps.destroyPanel(pName);
331 });
332 };
333 }]);
Jian Lia23f46d2017-05-02 18:07:31 +0900334}());