blob: bae6b892ecb8274cc2f22aab18cae54786e7ff8e [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');
100 keyDiv.append('h2').html('Mapping Key');
101 topKeyTable = keyDiv.append('div').classed('top-content', true)
102 .append('table');
103 keyDiv.append('hr');
104 valueDiv.append('h2').html('Mapping Value');
105 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) {
114 tr.append('td').attr('class', cls).html(txt);
115 }
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) {
124 tr.append('td').attr('class', cls).html(txt);
125 }
126 addCell('label', label + ' :');
127 addCell('value', value);
128 }
129
130 function populateTop(details) {
131 is.loadEmbeddedIcon(iconDiv, 'mappingTable', 40);
132 top.select('h2').html(details.mappingId);
133
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
149 topKeyTablebody.append('tr').append('td').attr('class', 'value').html(address);
150
151 treatmentFriendlyProps.forEach(function (col) {
152 bottomValueTableheader.append('th').html(col);
153 });
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) {
168 tr.append('td').attr('class', cls).html(txt);
169 }
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 Li4689f812017-05-04 07:30:35 +0900223
224 params = $location.search();
225 if (params.hasOwnProperty('devId')) {
226 $scope.devId = params['devId'];
227 }
228
229 tbs.buildTable({
230 scope: $scope,
231 tag: 'mapping',
Jian Libdf8ae52017-05-05 01:31:55 +0900232 selCb: selCb,
Jian Li4689f812017-05-04 07:30:35 +0900233 query: params
234 });
Jian Lia23f46d2017-05-02 18:07:31 +0900235
Jian Libdf8ae52017-05-05 01:31:55 +0900236 // details panel handlers
237 handlers[detailsResp] = respDetailsCb;
238 wss.bindHandlers(handlers);
239
240 function selCb($event, row) {
241 if ($scope.selId) {
242 wss.sendEvent(detailsReq, {mappingId: row.id, type: row.type});
243 } else {
244 $scope.hidePanel();
245 }
246 $log.debug('Got a click on:', row);
247 }
248
249 $scope.$on('$destroy', function () {
250 wss.unbindHandlers(handlers);
251 });
252
Jian Lia23f46d2017-05-02 18:07:31 +0900253 $log.log('OvMappingCtrl has been created');
Jian Libdf8ae52017-05-05 01:31:55 +0900254 }])
255
256 .directive('mappingDetailsPanel',
257 ['$rootScope', '$window', '$timeout', 'KeyService',
258 function ($rootScope, $window, $timeout, ks) {
259 return function (scope) {
260 var unbindWatch;
261
262 function heightCalc() {
263 pStartY = fs.noPxStyle(d3.select('.tabular-header'), 'height')
264 + mast.mastHeight() + topPdg;
265 wSize = fs.windowSize(pStartY);
266 pHeight = wSize.height;
267 }
268
269 function initPanel() {
270 heightCalc();
271 createDetailsPane();
272 }
273
274 // Safari has a bug where it renders the fixed-layout table wrong
275 // if you ask for the window's size too early
276 if (scope.onos.browser === 'safari') {
277 $timeout(initPanel);
278 } else {
279 initPanel();
280 }
281 // create key bindings to handle panel
282 ks.keyBindings({
283 esc: [handleEscape, 'Close the details panel'],
284 _helpFormat: ['esc']
285 });
286 ks.gestureNotes([
287 ['click', 'Select a row to show cluster node details'],
288 ['scroll down', 'See available cluster nodes']
289 ]);
290 // if the panelData changes
291 scope.$watch('panelData', function () {
292 if (!fs.isEmptyObject(scope.panelData)) {
293 populateDetails(scope.panelData);
294 detailsPanel.show();
295 }
296 });
297 // if the window size changes
298 unbindWatch = $rootScope.$watchCollection(
299 function () {
300 return {
301 h: $window.innerHeight,
302 w: $window.innerWidth
303 };
304 }, function () {
305 if (!fs.isEmptyObject(scope.panelData)) {
306 heightCalc();
307 populateDetails(scope.panelData);
308 }
309 }
310 );
311
312 scope.$on('$destroy', function () {
313 unbindWatch();
314 ps.destroyPanel(pName);
315 });
316 };
317 }]);
Jian Lia23f46d2017-05-02 18:07:31 +0900318}());