blob: a8a4ac147cea9e1211e5212b79a386c092c07f80 [file] [log] [blame]
Simon Huntcc035c52017-02-22 21:12:51 -08001/*
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 -- YANG Model table view
19 */
20
21(function () {
22 'use strict';
23
24 // injected refs
Simon Hunt7d5e9842017-02-23 11:37:02 -080025 var $log, $scope, fs, mast, ps, wss, is;
26
27 // constants
28 var topPdg = 28,
Thomas Vachuskacde197c2017-03-23 17:51:08 -070029 ctnrPdg = 24,
30 pWidth = 800,
31 scrollSize = 17,
32 tblPdg = 50;
Simon Huntcc035c52017-02-22 21:12:51 -080033
34 // internal state
35 var detailsPanel,
Simon Hunt7d5e9842017-02-23 11:37:02 -080036 ymodel,
37 pStartY,
38 pHeight,
39 wSize,
40 top,
Thomas Vachuskacde197c2017-03-23 17:51:08 -070041 topTable,
42 bottom,
Simon Hunt7d5e9842017-02-23 11:37:02 -080043 iconDiv;
Simon Huntcc035c52017-02-22 21:12:51 -080044
45 // constants
46 var pName = 'yang-model-details-panel',
47 detailsReq = 'yangModelDetailsRequest',
Thomas Vachuskacde197c2017-03-23 17:51:08 -070048 detailsResp = 'yangModelDetailsResponse',
Simon Huntcc035c52017-02-22 21:12:51 -080049
Thomas Vachuskacde197c2017-03-23 17:51:08 -070050 propOrder = [
51 ],
52 friendlyProps = [
53 ],
54
55 moduleCols = [
56 'name', 'revision'
57 ],
58 friendlyModuleCols = [
59 'Module Name', 'Revision'
60 ];
Simon Hunt7d5e9842017-02-23 11:37:02 -080061
62
63 function createDetailsPanel() {
64 detailsPanel = ps.createPanel(pName, {
65 width: pWidth,
66 margin: 0,
67 hideMargin: 0
68 });
69 $scope.hidePanel = function () { detailsPanel.hide(); };
70 detailsPanel.hide();
71 }
72
73 function populateDetails(details) {
Simon Hunt7d5e9842017-02-23 11:37:02 -080074 setUpPanel();
Thomas Vachuskacde197c2017-03-23 17:51:08 -070075
76 populateTop(details);
77 populateBottom(details.modules);
78
79 // topData = top.select('.top-data');
80 // populateTop(topData, details);
Simon Hunt7d5e9842017-02-23 11:37:02 -080081 detailsPanel.height(pHeight);
82 }
83
84 function setUpPanel() {
85 var container, closeBtn, dataDiv;
86 detailsPanel.empty();
87
88 container = detailsPanel.append('div').classed('container', true);
89
90 top = container.append('div').classed('top', true);
91 closeBtn = top.append('div').classed('close-btn', true);
92 addCloseBtn(closeBtn);
93 iconDiv = top.append('div').classed('dev-icon', true);
94 top.append('h2');
Thomas Vachuskacde197c2017-03-23 17:51:08 -070095 topTable = top.append('div').classed('top-content', true)
96 .append('table');
97 top.append('hr');
Simon Hunt7d5e9842017-02-23 11:37:02 -080098
Thomas Vachuskacde197c2017-03-23 17:51:08 -070099 bottom = container.append('div').classed('bottom', true);
100 bottom.append('h2').classed('modules-title', true).html('Modules');
101 bottom.append('table');
Simon Hunt7d5e9842017-02-23 11:37:02 -0800102 }
103
Thomas Vachuskacde197c2017-03-23 17:51:08 -0700104 function addProp(tbody, index, value) {
105 var tr = tbody.append('tr');
Simon Hunt7d5e9842017-02-23 11:37:02 -0800106
Thomas Vachuskacde197c2017-03-23 17:51:08 -0700107 function addCell(cls, txt) {
108 tr.append('td').attr('class', cls).html(txt);
109 }
110 addCell('label', friendlyProps[index] + ' :');
111 addCell('value', value);
112 }
113
114 function populateTop(details) {
115 is.loadEmbeddedIcon(iconDiv, 'nav_yang', 40);
116 top.select('h2').html('Model ID ' + details.id);
117
118 var tbody = topTable.append('tbody');
119
120 propOrder.forEach(function (prop, i) {
121 addProp(tbody, i, details[prop]);
122 });
123 }
124
125 function addModuleRow(tbody, module) {
126 var tr = tbody.append('tr');
127 moduleCols.forEach(function (col) {
128 tr.append('td').attr('width', 160)
129 .html('<a href="/v1/yang/modules/' + module.name + '" target="_model">' + module[col] + "</a>");
130 });
131 }
132
133 function populateBottom(modules) {
134 var table = bottom.select('table'),
135 theader = table.append('thead').append('tr'),
136 tbody = table.append('tbody'),
137 tbWidth, tbHeight;
138
139 friendlyModuleCols.forEach(function (col) {
140 theader.append('th').html(col);
141 });
142 modules.forEach(function (module) {
143 addModuleRow(tbody, module);
144 });
145
146 tbWidth = fs.noPxStyle(tbody, 'width') + scrollSize;
147 tbHeight = pHeight
148 - (fs.noPxStyle(detailsPanel.el()
149 .select('.top'), 'height')
150 + fs.noPxStyle(detailsPanel.el()
151 .select('.modules-title'), 'height')
152 + tblPdg);
153
154 table.style({
155 height: tbHeight + 'px',
156 width: tbWidth + 'px',
157 overflow: 'auto',
158 display: 'block'
159 });
160
161 detailsPanel.width(tbWidth + ctnrPdg);
Simon Hunt7d5e9842017-02-23 11:37:02 -0800162 }
163
164 function closePanel() {
165 if (detailsPanel.isVisible()) {
166 $scope.selId = null;
167 detailsPanel.hide();
168 return true;
169 }
170 return false;
171 }
172
173 function addCloseBtn(div) {
174 is.loadEmbeddedIcon(div, 'close', 20);
175 div.on('click', closePanel);
176 }
177
178
Simon Huntcc035c52017-02-22 21:12:51 -0800179 // callback invoked when data from a details request returns from server
180 function respDetailsCb(data) {
181 $scope.panelData = data.details;
182 ymodel = data.yangModel;
183 $scope.$apply();
184 // TODO: complete the detail panel directive.
185 $log.debug('YANG_MODEL>', detailsResp, data);
186 }
187
Simon Hunt7d5e9842017-02-23 11:37:02 -0800188 function handleEscape() {
189 return closePanel();
190 }
191
192
193 // defines view controller
Simon Huntcc035c52017-02-22 21:12:51 -0800194 angular.module('ovYangModel', [])
Simon Hunt7d5e9842017-02-23 11:37:02 -0800195 .controller('OvYangModelCtrl', [
196 '$log', '$scope', 'TableBuilderService', 'TableDetailService',
197 'FnService', 'MastService', 'PanelService', 'WebSocketService',
198 'IconService',
Simon Huntcc035c52017-02-22 21:12:51 -0800199
Simon Hunt7d5e9842017-02-23 11:37:02 -0800200 function (_$log_, _$scope_, tbs, tds, _fs_, _mast_, _ps_, _wss_, _is_) {
201 var handlers = {};
Simon Huntcc035c52017-02-22 21:12:51 -0800202
Simon Hunt7d5e9842017-02-23 11:37:02 -0800203 $log = _$log_;
204 $scope = _$scope_;
205 fs = _fs_;
206 mast = _mast_;
207 ps = _ps_;
208 wss = _wss_;
209 is = _is_;
Simon Huntcc035c52017-02-22 21:12:51 -0800210
Simon Hunt7d5e9842017-02-23 11:37:02 -0800211 $scope.panelData = {};
Simon Huntcc035c52017-02-22 21:12:51 -0800212
Simon Hunt7d5e9842017-02-23 11:37:02 -0800213 // register response handler
214 handlers[detailsResp] = respDetailsCb;
215 wss.bindHandlers(handlers);
Simon Huntcc035c52017-02-22 21:12:51 -0800216
Simon Hunt7d5e9842017-02-23 11:37:02 -0800217 // row selection callback
218 function selCb($event, row) {
219 if ($scope.selId) {
220 wss.sendEvent(detailsReq, { id: row.id });
221 } else {
222 $scope.hidePanel();
Simon Huntcc035c52017-02-22 21:12:51 -0800223 }
Simon Hunt7d5e9842017-02-23 11:37:02 -0800224 $log.debug('Got a click on:', row);
Simon Huntcc035c52017-02-22 21:12:51 -0800225 }
Simon Huntcc035c52017-02-22 21:12:51 -0800226
Simon Hunt7d5e9842017-02-23 11:37:02 -0800227 tbs.buildTable({
228 scope: $scope,
229 tag: 'yangModel',
230 selCb: selCb
231 });
232
233 $scope.$on('$destroy', function () {
234 wss.unbindHandlers(handlers);
235 });
236
237 $log.log('OvYangModelCtrl has been created');
238 }
239 ])
240
241 .directive('yangModelDetailsPanel', [
242 '$rootScope', '$window', '$timeout', 'KeyService',
243
244 function ($rootScope, $window, $timeout, ks) {
245 return function (scope) {
246 var unbindWatch;
247
248 function heightCalc() {
249 pStartY = fs.noPxStyle(d3.select('.tabular-header'), 'height')
250 + mast.mastHeight() + topPdg;
251 wSize = fs.windowSize(pStartY);
252 pHeight = wSize.height;
253 }
254
255 function initPanel() {
256 heightCalc();
257 createDetailsPanel();
258 }
259
260 // Safari has a bug where it renders the fixed-layout table wrong
261 // if you ask for the window's size too early
262 if (scope.onos.browser === 'safari') {
263 $timeout(initPanel);
264 } else {
265 initPanel();
266 }
267
268 // create key bindings to handle panel
269 ks.keyBindings({
270 esc: [handleEscape, 'Close the details panel'],
271 _helpFormat: ['esc']
272 });
273 ks.gestureNotes([
274 ['click', 'Select a row to show YANG model details'],
275 ['scroll down', 'See more models']
276 ]);
277
278 // if the panelData changes
279 scope.$watch('panelData', function () {
280 if (!fs.isEmptyObject(scope.panelData)) {
281 populateDetails(scope.panelData);
282 detailsPanel.show();
283 }
284 });
285
286 // if the window size changes
287 unbindWatch = $rootScope.$watchCollection(
288 function () {
289 return {
290 h: $window.innerHeight,
291 w: $window.innerWidth
292 };
293 }, function () {
294 if (!fs.isEmptyObject(scope.panelData)) {
295 heightCalc();
296 populateDetails(scope.panelData);
297 }
298 }
299 );
300
301 scope.$on('$destroy', function () {
302 unbindWatch();
303 ks.unbindKeys();
304 ps.destroyPanel(pName);
305 });
306 };
307 }]);
Simon Huntcc035c52017-02-22 21:12:51 -0800308
309}());