blob: 6dfb89064dfd65f77b71ae5a65233282f45500fe [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
Simon Hunt3ee1f432017-03-31 17:18:53 -070028 var topPdg = 20,
29 hFudge = 12,
30 srcFudge = 130,
31 pWidth = 800;
Simon Huntcc035c52017-02-22 21:12:51 -080032
33 // internal state
34 var detailsPanel,
Simon Hunt7d5e9842017-02-23 11:37:02 -080035 pStartY,
36 pHeight,
37 wSize,
38 top,
Thomas Vachuskacde197c2017-03-23 17:51:08 -070039 bottom,
Simon Hunt3ee1f432017-03-31 17:18:53 -070040 iconDiv,
41 srcFrame,
42 srcDiv;
Simon Huntcc035c52017-02-22 21:12:51 -080043
44 // constants
45 var pName = 'yang-model-details-panel',
46 detailsReq = 'yangModelDetailsRequest',
Simon Hunt3ee1f432017-03-31 17:18:53 -070047 detailsResp = 'yangModelDetailsResponse';
Simon Huntcc035c52017-02-22 21:12:51 -080048
Simon Hunt7d5e9842017-02-23 11:37:02 -080049
Simon Hunt7d5e9842017-02-23 11:37:02 -080050 function createDetailsPanel() {
51 detailsPanel = ps.createPanel(pName, {
52 width: pWidth,
53 margin: 0,
54 hideMargin: 0
55 });
Simon Hunt3ee1f432017-03-31 17:18:53 -070056 detailsPanel.el().style({ top: pStartY + 'px'});
Simon Hunt7d5e9842017-02-23 11:37:02 -080057 $scope.hidePanel = function () { detailsPanel.hide(); };
58 detailsPanel.hide();
59 }
60
Simon Hunt3ee1f432017-03-31 17:18:53 -070061 function fixHeight(d, h) {
62 d.style({ height: h + 'px'});
63 }
64
Simon Hunt7d5e9842017-02-23 11:37:02 -080065 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 Hunt3ee1f432017-03-31 17:18:53 -070069
70 detailsPanel.height(pHeight);
71 // also have to fix the height of the source frame to make scroll work
72 fixHeight(srcFrame, pHeight - srcFudge);
Simon Hunt7d5e9842017-02-23 11:37:02 -080073 }
74
75 function setUpPanel() {
Simon Hunt3ee1f432017-03-31 17:18:53 -070076 var container, closeBtn;
Simon Hunt7d5e9842017-02-23 11:37:02 -080077 detailsPanel.empty();
78
79 container = detailsPanel.append('div').classed('container', true);
80
81 top = container.append('div').classed('top', true);
Simon Hunt3ee1f432017-03-31 17:18:53 -070082
Simon Hunt7d5e9842017-02-23 11:37:02 -080083 closeBtn = top.append('div').classed('close-btn', true);
84 addCloseBtn(closeBtn);
Simon Hunt3ee1f432017-03-31 17:18:53 -070085
Simon Hunt7d5e9842017-02-23 11:37:02 -080086 iconDiv = top.append('div').classed('dev-icon', true);
87 top.append('h2');
Thomas Vachuskacde197c2017-03-23 17:51:08 -070088 top.append('hr');
Simon Hunt7d5e9842017-02-23 11:37:02 -080089
Thomas Vachuskacde197c2017-03-23 17:51:08 -070090 bottom = container.append('div').classed('bottom', true);
Simon Hunt239f09e2017-05-18 13:10:09 -070091 bottom.append('h2').text('YANG Source');
Simon Hunt7d5e9842017-02-23 11:37:02 -080092
Simon Hunt3ee1f432017-03-31 17:18:53 -070093 srcFrame = bottom.append('div').classed('src-frame', true);
94 srcDiv = srcFrame.append('div').classed('module-source', true);
95 srcDiv.append('pre');
Thomas Vachuskacde197c2017-03-23 17:51:08 -070096 }
97
98 function populateTop(details) {
99 is.loadEmbeddedIcon(iconDiv, 'nav_yang', 40);
Simon Hunt3ee1f432017-03-31 17:18:53 -0700100 top.select('h2')
Simon Hunt239f09e2017-05-18 13:10:09 -0700101 .text('Module ' + details.id + ' (' + details.revision + ')');
Thomas Vachuskacde197c2017-03-23 17:51:08 -0700102 }
103
Thomas Vachuskae0792f12017-03-31 00:15:06 -0700104 function populateBottom(source) {
Simon Hunt3ee1f432017-03-31 17:18:53 -0700105 var src = srcDiv.select('pre');
Simon Hunt239f09e2017-05-18 13:10:09 -0700106 src.text(source.join('\n'));
Simon Hunt7d5e9842017-02-23 11:37:02 -0800107 }
108
109 function closePanel() {
110 if (detailsPanel.isVisible()) {
111 $scope.selId = null;
112 detailsPanel.hide();
113 return true;
114 }
115 return false;
116 }
117
118 function addCloseBtn(div) {
119 is.loadEmbeddedIcon(div, 'close', 20);
120 div.on('click', closePanel);
121 }
122
Simon Huntcc035c52017-02-22 21:12:51 -0800123 // callback invoked when data from a details request returns from server
124 function respDetailsCb(data) {
125 $scope.panelData = data.details;
Simon Huntcc035c52017-02-22 21:12:51 -0800126 $scope.$apply();
Simon Huntcc035c52017-02-22 21:12:51 -0800127 $log.debug('YANG_MODEL>', detailsResp, data);
128 }
129
Simon Hunt7d5e9842017-02-23 11:37:02 -0800130 function handleEscape() {
131 return closePanel();
132 }
133
134
135 // defines view controller
Simon Huntcc035c52017-02-22 21:12:51 -0800136 angular.module('ovYangModel', [])
Simon Hunt7d5e9842017-02-23 11:37:02 -0800137 .controller('OvYangModelCtrl', [
138 '$log', '$scope', 'TableBuilderService', 'TableDetailService',
139 'FnService', 'MastService', 'PanelService', 'WebSocketService',
140 'IconService',
Simon Huntcc035c52017-02-22 21:12:51 -0800141
Simon Hunt7d5e9842017-02-23 11:37:02 -0800142 function (_$log_, _$scope_, tbs, tds, _fs_, _mast_, _ps_, _wss_, _is_) {
143 var handlers = {};
Simon Huntcc035c52017-02-22 21:12:51 -0800144
Simon Hunt7d5e9842017-02-23 11:37:02 -0800145 $log = _$log_;
146 $scope = _$scope_;
147 fs = _fs_;
148 mast = _mast_;
149 ps = _ps_;
150 wss = _wss_;
151 is = _is_;
Simon Huntcc035c52017-02-22 21:12:51 -0800152
Simon Hunt7d5e9842017-02-23 11:37:02 -0800153 $scope.panelData = {};
Simon Huntcc035c52017-02-22 21:12:51 -0800154
Simon Hunt7d5e9842017-02-23 11:37:02 -0800155 // register response handler
156 handlers[detailsResp] = respDetailsCb;
157 wss.bindHandlers(handlers);
Simon Huntcc035c52017-02-22 21:12:51 -0800158
Simon Hunt7d5e9842017-02-23 11:37:02 -0800159 // row selection callback
160 function selCb($event, row) {
161 if ($scope.selId) {
Thomas Vachuska401a1d32017-03-31 09:58:11 -0700162 wss.sendEvent(detailsReq, { modelId: row.modelId, id: row.id });
Simon Hunt7d5e9842017-02-23 11:37:02 -0800163 } else {
164 $scope.hidePanel();
Simon Huntcc035c52017-02-22 21:12:51 -0800165 }
Simon Hunt7d5e9842017-02-23 11:37:02 -0800166 $log.debug('Got a click on:', row);
Simon Huntcc035c52017-02-22 21:12:51 -0800167 }
Simon Huntcc035c52017-02-22 21:12:51 -0800168
Simon Hunt7d5e9842017-02-23 11:37:02 -0800169 tbs.buildTable({
170 scope: $scope,
171 tag: 'yangModel',
172 selCb: selCb
173 });
174
175 $scope.$on('$destroy', function () {
176 wss.unbindHandlers(handlers);
177 });
178
179 $log.log('OvYangModelCtrl has been created');
180 }
181 ])
182
183 .directive('yangModelDetailsPanel', [
184 '$rootScope', '$window', '$timeout', 'KeyService',
185
186 function ($rootScope, $window, $timeout, ks) {
187 return function (scope) {
188 var unbindWatch;
189
190 function heightCalc() {
191 pStartY = fs.noPxStyle(d3.select('.tabular-header'), 'height')
192 + mast.mastHeight() + topPdg;
193 wSize = fs.windowSize(pStartY);
Simon Hunt3ee1f432017-03-31 17:18:53 -0700194 pHeight = wSize.height - hFudge;
Simon Hunt7d5e9842017-02-23 11:37:02 -0800195 }
196
197 function initPanel() {
198 heightCalc();
199 createDetailsPanel();
200 }
201
202 // Safari has a bug where it renders the fixed-layout table wrong
203 // if you ask for the window's size too early
204 if (scope.onos.browser === 'safari') {
205 $timeout(initPanel);
206 } else {
207 initPanel();
208 }
209
210 // create key bindings to handle panel
211 ks.keyBindings({
212 esc: [handleEscape, 'Close the details panel'],
213 _helpFormat: ['esc']
214 });
215 ks.gestureNotes([
216 ['click', 'Select a row to show YANG model details'],
217 ['scroll down', 'See more models']
218 ]);
219
220 // if the panelData changes
221 scope.$watch('panelData', function () {
222 if (!fs.isEmptyObject(scope.panelData)) {
223 populateDetails(scope.panelData);
224 detailsPanel.show();
225 }
226 });
227
228 // if the window size changes
229 unbindWatch = $rootScope.$watchCollection(
230 function () {
231 return {
232 h: $window.innerHeight,
233 w: $window.innerWidth
234 };
235 }, function () {
236 if (!fs.isEmptyObject(scope.panelData)) {
237 heightCalc();
238 populateDetails(scope.panelData);
239 }
240 }
241 );
242
243 scope.$on('$destroy', function () {
244 unbindWatch();
245 ks.unbindKeys();
246 ps.destroyPanel(pName);
247 });
248 };
249 }]);
Simon Huntcc035c52017-02-22 21:12:51 -0800250
251}());