blob: ee23f004a3013a1d108fabaf6aed59257eb0c2a1 [file] [log] [blame]
Thomas Vachuskae586b792015-03-26 13:59:38 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Thomas Vachuskae586b792015-03-26 13:59:38 -07003 *
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 -- Host View Module
19 */
20
21(function () {
22 'use strict';
23
Simon Hunte408af72017-06-14 18:32:06 -070024 // injected refs
25 var $log, $scope, $loc, fs, mast, ps, wss, is, ns, ks;
26
27 // internal state
28 var detailsPanel,
29 pStartY,
30 pHeight,
31 top,
32 bottom,
33 iconDiv,
34 wSize,
35 editingName = false,
36 host;
37
38 // constants
39 var topPdg = 28,
40 ctnrPdg = 24,
41 scrollSize = 17,
42
43 pName = 'host-details-panel',
44 detailsReq = 'hostDetailsRequest',
45 detailsResp = 'hostDetailsResponse',
46 nameChangeReq = 'hostNameChangeRequest',
47 nameChangeResp = 'hostNameChangeResponse';
48
49
50 function closePanel() {
51 if (detailsPanel.isVisible()) {
52 $scope.selId = null;
53 detailsPanel.hide();
54 return true;
55 }
56 return false;
57 }
58
59 function addCloseBtn(div) {
60 is.loadEmbeddedIcon(div, 'close', 20);
61 div.on('click', closePanel);
62 }
63
64 function exitEditMode(nameH2, name) {
65 nameH2.text(name);
66 nameH2.classed('editable clickable', true);
67 editingName = false;
68 ks.enableGlobalKeys(true);
69 }
70
71 function editNameSave() {
72 var nameH2 = top.select('h2'),
73 id = $scope.panelData.id,
74 val,
75 newVal;
76
77 if (editingName) {
78 val = nameH2.select('input').property('value').trim();
79 newVal = val || id;
80
81 exitEditMode(nameH2, newVal);
82 $scope.panelData.name = newVal;
83 wss.sendEvent(nameChangeReq, { id: id, name: val });
84 }
85 }
86
87 function editNameCancel() {
88 if (editingName) {
89 exitEditMode(top.select('h2'), $scope.panelData.name);
90 return true;
91 }
92 return false;
93 }
94
95 function editName() {
96 var nameH2 = top.select('h2'),
97 tf, el;
98
99 if (!editingName) {
100 nameH2.classed('editable clickable', false);
101 nameH2.text('');
102 tf = nameH2.append('input').classed('name-input', true)
103 .attr('type', 'text')
104 .attr('value', $scope.panelData.name);
105 el = tf[0][0];
106 el.focus();
107 el.select();
108 editingName = true;
109 ks.enableGlobalKeys(false);
110 }
111 }
112
113 function handleEscape() {
114 return editNameCancel() || closePanel();
115 }
116
117 function setUpPanel() {
118 var container, closeBtn, tblDiv;
119 detailsPanel.empty();
120
121 container = detailsPanel.append('div').classed('container', true);
122
123 top = container.append('div').classed('top', true);
124 closeBtn = top.append('div').classed('close-btn', true);
125 addCloseBtn(closeBtn);
126 iconDiv = top.append('div').classed('host-icon', true);
127 top.append('h2').classed('editable clickable', true).on('click', editName);
128
129 // tblDiv = top.append('div').classed('top-tables', true);
130 // tblDiv.append('div').classed('left', true).append('table');
131 // tblDiv.append('div').classed('right', true).append('table');
132
133 top.append('hr');
134
135 // bottom = container.append('div').classed('bottom', true);
136 // bottom.append('h2').classed('ports-title', true).text('Ports');
137 // bottom.append('table');
138 }
139
140 function populateTop(details) {
141 is.loadEmbeddedIcon(iconDiv, details._iconid_type, 40);
142 top.select('h2').text(details.name);
143
144 // TODO: still need to add host properties (one per line)
145 }
146
147 function populateDetails(details) {
148 setUpPanel();
149 populateTop(details);
150 detailsPanel.height(pHeight);
Simon Hunt86943082017-06-15 13:18:42 -0700151 // configure width based on content.. for now hardcoded
152 detailsPanel.width(600);
Simon Hunte408af72017-06-14 18:32:06 -0700153 }
154
155 function respDetailsCb(data) {
156 $scope.panelData = data.details;
157 host = data.host;
158 $scope.$apply();
159 }
160
161 function respNameCb(data) {
162 if (data.warn) {
163 $log.warn(data.warn, data.id);
164 top.select('h2').text(data.id);
165 }
166 }
167
168 function createDetailsPane() {
169 detailsPanel = ps.createPanel(pName, {
170 width: wSize.width,
171 margin: 0,
172 hideMargin: 0
173 });
174 detailsPanel.el().style({
175 position: 'absolute',
176 top: pStartY + 'px'
177 });
178 $scope.hidePanel = function () { detailsPanel.hide(); };
179 detailsPanel.hide();
180 }
181
182
183 // Defines the Host View controller...
Thomas Vachuskae586b792015-03-26 13:59:38 -0700184 angular.module('ovHost', [])
185 .controller('OvHostCtrl',
Simon Hunte408af72017-06-14 18:32:06 -0700186 ['$log', '$scope',
187 '$location',
188 'TableBuilderService',
189 'FnService', 'MastService', 'PanelService', 'WebSocketService',
190 'IconService', 'NavService', 'KeyService',
Thomas Vachuskae586b792015-03-26 13:59:38 -0700191
Simon Hunte408af72017-06-14 18:32:06 -0700192 function (_$log_, _$scope_, _$location_,
193 tbs,
194 _fs_, _mast_, _ps_, _wss_,
195 _is_, _ns_, _ks_) {
196
197 var params,
198 handlers = {};
199
200 $log = _$log_;
201 $scope = _$scope_;
202 $loc = _$location_;
203 fs = _fs_;
204 mast = _mast_;
205 ps = _ps_;
206 wss = _wss_;
207 is = _is_;
208 ns = _ns_;
209 ks = _ks_;
210
211 params = $loc.search();
212
213 $scope.panelData = {};
214
215 // details panel handlers
216 handlers[detailsResp] = respDetailsCb;
217 handlers[nameChangeResp] = respNameCb;
218 wss.bindHandlers(handlers);
219
220 // query for if a certain host needs to be highlighted
221 if (params.hasOwnProperty('hostId')) {
222 $scope.selId = params['hostId'];
223 wss.sendEvent(detailsReq, { id: $scope.selId });
224 }
225
226 function selCb($event, row) {
227 if ($scope.selId) {
228 wss.sendEvent(detailsReq, { id: row.id });
229 } else {
230 $scope.hidePanel();
231 }
232 $log.debug('Got a click on:', row);
233 }
234
Bri Prebilic Cole864cdd62015-04-02 15:46:47 -0700235 tbs.buildTable({
Bri Prebilic Cole864cdd62015-04-02 15:46:47 -0700236 scope: $scope,
Simon Hunte408af72017-06-14 18:32:06 -0700237 tag: 'host',
238 selCb: selCb
239 });
240
241 $scope.nav = function (path) {
242 if ($scope.selId) {
243 ns.navTo(path, { hostId: $scope.selId });
244 }
245 };
246
247 $scope.$on('$destroy', function () {
248 wss.unbindHandlers(handlers);
Thomas Vachuskae586b792015-03-26 13:59:38 -0700249 });
Bri Prebilic Cole3d4d01c2015-04-30 13:48:36 -0700250
Bri Prebilic Cole19a32dd2015-03-26 18:00:03 -0700251 $log.log('OvHostCtrl has been created');
Simon Hunte408af72017-06-14 18:32:06 -0700252 }])
253
254 .directive('hostDetailsPanel',
255 ['$rootScope', '$window', '$timeout', 'KeyService',
256 function ($rootScope, $window, $timeout, ks) {
257 return function (scope) {
258 var unbindWatch;
259
260 function heightCalc() {
261 pStartY = fs.noPxStyle(d3.select('.tabular-header'), 'height')
262 + mast.mastHeight() + topPdg;
263 wSize = fs.windowSize(pStartY);
264 pHeight = wSize.height;
265 }
266
267 function initPanel() {
268 heightCalc();
269 createDetailsPane();
270 }
271
272 // Safari has a bug where it renders the fixed-layout table wrong
273 // if you ask for the window's size too early
274 if (scope.onos.browser === 'safari') {
275 $timeout(initPanel);
276 } else {
277 initPanel();
278 }
279 // create key bindings to handle panel
280 ks.keyBindings({
281 enter: editNameSave,
282 esc: [handleEscape, 'Close the details panel'],
283 _helpFormat: ['esc']
284 });
285 ks.gestureNotes([
286 ['click', 'Select a row to show device details'],
287 ['scroll down', 'See more devices']
288 ]);
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
298 // if the window size changes
299 unbindWatch = $rootScope.$watchCollection(
300 function () {
301 return {
302 h: $window.innerHeight,
303 w: $window.innerWidth
304 };
305 }, function () {
306 if (!fs.isEmptyObject(scope.panelData)) {
307 heightCalc();
308 populateDetails(scope.panelData);
309 }
310 }
311 );
312
313 scope.$on('$destroy', function () {
314 unbindWatch();
315 ks.unbindKeys();
316 ps.destroyPanel(pName);
317 });
318 };
319 }]);
Thomas Vachuskae586b792015-03-26 13:59:38 -0700320}());