blob: 7de8c2c3ef5a982f8561d42d4d42549c4354753e [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 = [
Thomas Vachuskacde197c2017-03-23 17:51:08 -070053 ];
Simon Hunt7d5e9842017-02-23 11:37:02 -080054
Simon Hunt7d5e9842017-02-23 11:37:02 -080055 function createDetailsPanel() {
56 detailsPanel = ps.createPanel(pName, {
57 width: pWidth,
58 margin: 0,
59 hideMargin: 0
60 });
61 $scope.hidePanel = function () { detailsPanel.hide(); };
62 detailsPanel.hide();
63 }
64
65 function populateDetails(details) {
Simon Hunt7d5e9842017-02-23 11:37:02 -080066 setUpPanel();
Thomas Vachuskacde197c2017-03-23 17:51:08 -070067 populateTop(details);
Thomas Vachuskae0792f12017-03-31 00:15:06 -070068 populateBottom(details.source);
Simon Hunt7d5e9842017-02-23 11:37:02 -080069 }
70
71 function setUpPanel() {
72 var container, closeBtn, dataDiv;
73 detailsPanel.empty();
74
75 container = detailsPanel.append('div').classed('container', true);
76
77 top = container.append('div').classed('top', true);
78 closeBtn = top.append('div').classed('close-btn', true);
79 addCloseBtn(closeBtn);
80 iconDiv = top.append('div').classed('dev-icon', true);
81 top.append('h2');
Thomas Vachuskacde197c2017-03-23 17:51:08 -070082 topTable = top.append('div').classed('top-content', true)
83 .append('table');
84 top.append('hr');
Simon Hunt7d5e9842017-02-23 11:37:02 -080085
Thomas Vachuskacde197c2017-03-23 17:51:08 -070086 bottom = container.append('div').classed('bottom', true);
Thomas Vachuskae0792f12017-03-31 00:15:06 -070087 bottom.append('h2').classed('modules-title', true).html('YANG Source');
88 bottom.append('div').classed('module-source');
89 bottom.select('div').append('pre');
Simon Hunt7d5e9842017-02-23 11:37:02 -080090 }
91
Thomas Vachuskacde197c2017-03-23 17:51:08 -070092 function addProp(tbody, index, value) {
93 var tr = tbody.append('tr');
Simon Hunt7d5e9842017-02-23 11:37:02 -080094
Thomas Vachuskacde197c2017-03-23 17:51:08 -070095 function addCell(cls, txt) {
96 tr.append('td').attr('class', cls).html(txt);
97 }
98 addCell('label', friendlyProps[index] + ' :');
99 addCell('value', value);
100 }
101
102 function populateTop(details) {
103 is.loadEmbeddedIcon(iconDiv, 'nav_yang', 40);
Thomas Vachuskae0792f12017-03-31 00:15:06 -0700104 top.select('h2').html('Module ' + details.module + " (" + details.revision + ")");
Thomas Vachuskacde197c2017-03-23 17:51:08 -0700105
106 var tbody = topTable.append('tbody');
107
108 propOrder.forEach(function (prop, i) {
109 addProp(tbody, i, details[prop]);
110 });
111 }
112
113 function addModuleRow(tbody, module) {
114 var tr = tbody.append('tr');
115 moduleCols.forEach(function (col) {
116 tr.append('td').attr('width', 160)
117 .html('<a href="/v1/yang/modules/' + module.name + '" target="_model">' + module[col] + "</a>");
118 });
119 }
120
Thomas Vachuskae0792f12017-03-31 00:15:06 -0700121 function populateBottom(source) {
122 var src = bottom.select('pre');
123 src.html(source.join('\n'));
Simon Hunt7d5e9842017-02-23 11:37:02 -0800124 }
125
126 function closePanel() {
127 if (detailsPanel.isVisible()) {
128 $scope.selId = null;
129 detailsPanel.hide();
130 return true;
131 }
132 return false;
133 }
134
135 function addCloseBtn(div) {
136 is.loadEmbeddedIcon(div, 'close', 20);
137 div.on('click', closePanel);
138 }
139
140
Simon Huntcc035c52017-02-22 21:12:51 -0800141 // callback invoked when data from a details request returns from server
142 function respDetailsCb(data) {
143 $scope.panelData = data.details;
144 ymodel = data.yangModel;
145 $scope.$apply();
146 // TODO: complete the detail panel directive.
147 $log.debug('YANG_MODEL>', detailsResp, data);
148 }
149
Simon Hunt7d5e9842017-02-23 11:37:02 -0800150 function handleEscape() {
151 return closePanel();
152 }
153
154
155 // defines view controller
Simon Huntcc035c52017-02-22 21:12:51 -0800156 angular.module('ovYangModel', [])
Simon Hunt7d5e9842017-02-23 11:37:02 -0800157 .controller('OvYangModelCtrl', [
158 '$log', '$scope', 'TableBuilderService', 'TableDetailService',
159 'FnService', 'MastService', 'PanelService', 'WebSocketService',
160 'IconService',
Simon Huntcc035c52017-02-22 21:12:51 -0800161
Simon Hunt7d5e9842017-02-23 11:37:02 -0800162 function (_$log_, _$scope_, tbs, tds, _fs_, _mast_, _ps_, _wss_, _is_) {
163 var handlers = {};
Simon Huntcc035c52017-02-22 21:12:51 -0800164
Simon Hunt7d5e9842017-02-23 11:37:02 -0800165 $log = _$log_;
166 $scope = _$scope_;
167 fs = _fs_;
168 mast = _mast_;
169 ps = _ps_;
170 wss = _wss_;
171 is = _is_;
Simon Huntcc035c52017-02-22 21:12:51 -0800172
Simon Hunt7d5e9842017-02-23 11:37:02 -0800173 $scope.panelData = {};
Simon Huntcc035c52017-02-22 21:12:51 -0800174
Simon Hunt7d5e9842017-02-23 11:37:02 -0800175 // register response handler
176 handlers[detailsResp] = respDetailsCb;
177 wss.bindHandlers(handlers);
Simon Huntcc035c52017-02-22 21:12:51 -0800178
Simon Hunt7d5e9842017-02-23 11:37:02 -0800179 // row selection callback
180 function selCb($event, row) {
181 if ($scope.selId) {
Thomas Vachuskae0792f12017-03-31 00:15:06 -0700182 wss.sendEvent(detailsReq, { id: row.id, module: row.module });
Simon Hunt7d5e9842017-02-23 11:37:02 -0800183 } else {
184 $scope.hidePanel();
Simon Huntcc035c52017-02-22 21:12:51 -0800185 }
Simon Hunt7d5e9842017-02-23 11:37:02 -0800186 $log.debug('Got a click on:', row);
Simon Huntcc035c52017-02-22 21:12:51 -0800187 }
Simon Huntcc035c52017-02-22 21:12:51 -0800188
Simon Hunt7d5e9842017-02-23 11:37:02 -0800189 tbs.buildTable({
190 scope: $scope,
191 tag: 'yangModel',
192 selCb: selCb
193 });
194
195 $scope.$on('$destroy', function () {
196 wss.unbindHandlers(handlers);
197 });
198
199 $log.log('OvYangModelCtrl has been created');
200 }
201 ])
202
203 .directive('yangModelDetailsPanel', [
204 '$rootScope', '$window', '$timeout', 'KeyService',
205
206 function ($rootScope, $window, $timeout, ks) {
207 return function (scope) {
208 var unbindWatch;
209
210 function heightCalc() {
211 pStartY = fs.noPxStyle(d3.select('.tabular-header'), 'height')
212 + mast.mastHeight() + topPdg;
213 wSize = fs.windowSize(pStartY);
214 pHeight = wSize.height;
215 }
216
217 function initPanel() {
218 heightCalc();
219 createDetailsPanel();
220 }
221
222 // Safari has a bug where it renders the fixed-layout table wrong
223 // if you ask for the window's size too early
224 if (scope.onos.browser === 'safari') {
225 $timeout(initPanel);
226 } else {
227 initPanel();
228 }
229
230 // create key bindings to handle panel
231 ks.keyBindings({
232 esc: [handleEscape, 'Close the details panel'],
233 _helpFormat: ['esc']
234 });
235 ks.gestureNotes([
236 ['click', 'Select a row to show YANG model details'],
237 ['scroll down', 'See more models']
238 ]);
239
240 // if the panelData changes
241 scope.$watch('panelData', function () {
242 if (!fs.isEmptyObject(scope.panelData)) {
243 populateDetails(scope.panelData);
244 detailsPanel.show();
245 }
246 });
247
248 // if the window size changes
249 unbindWatch = $rootScope.$watchCollection(
250 function () {
251 return {
252 h: $window.innerHeight,
253 w: $window.innerWidth
254 };
255 }, function () {
256 if (!fs.isEmptyObject(scope.panelData)) {
257 heightCalc();
258 populateDetails(scope.panelData);
259 }
260 }
261 );
262
263 scope.$on('$destroy', function () {
264 unbindWatch();
265 ks.unbindKeys();
266 ps.destroyPanel(pName);
267 });
268 };
269 }]);
Simon Huntcc035c52017-02-22 21:12:51 -0800270
271}());