blob: 537bc13859042f9155b314863d58eb33e2f4d467 [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);
151 }
152
153 function respDetailsCb(data) {
154 $scope.panelData = data.details;
155 host = data.host;
156 $scope.$apply();
157 }
158
159 function respNameCb(data) {
160 if (data.warn) {
161 $log.warn(data.warn, data.id);
162 top.select('h2').text(data.id);
163 }
164 }
165
166 function createDetailsPane() {
167 detailsPanel = ps.createPanel(pName, {
168 width: wSize.width,
169 margin: 0,
170 hideMargin: 0
171 });
172 detailsPanel.el().style({
173 position: 'absolute',
174 top: pStartY + 'px'
175 });
176 $scope.hidePanel = function () { detailsPanel.hide(); };
177 detailsPanel.hide();
178 }
179
180
181 // Defines the Host View controller...
Thomas Vachuskae586b792015-03-26 13:59:38 -0700182 angular.module('ovHost', [])
183 .controller('OvHostCtrl',
Simon Hunte408af72017-06-14 18:32:06 -0700184 ['$log', '$scope',
185 '$location',
186 'TableBuilderService',
187 'FnService', 'MastService', 'PanelService', 'WebSocketService',
188 'IconService', 'NavService', 'KeyService',
Thomas Vachuskae586b792015-03-26 13:59:38 -0700189
Simon Hunte408af72017-06-14 18:32:06 -0700190 function (_$log_, _$scope_, _$location_,
191 tbs,
192 _fs_, _mast_, _ps_, _wss_,
193 _is_, _ns_, _ks_) {
194
195 var params,
196 handlers = {};
197
198 $log = _$log_;
199 $scope = _$scope_;
200 $loc = _$location_;
201 fs = _fs_;
202 mast = _mast_;
203 ps = _ps_;
204 wss = _wss_;
205 is = _is_;
206 ns = _ns_;
207 ks = _ks_;
208
209 params = $loc.search();
210
211 $scope.panelData = {};
212
213 // details panel handlers
214 handlers[detailsResp] = respDetailsCb;
215 handlers[nameChangeResp] = respNameCb;
216 wss.bindHandlers(handlers);
217
218 // query for if a certain host needs to be highlighted
219 if (params.hasOwnProperty('hostId')) {
220 $scope.selId = params['hostId'];
221 wss.sendEvent(detailsReq, { id: $scope.selId });
222 }
223
224 function selCb($event, row) {
225 if ($scope.selId) {
226 wss.sendEvent(detailsReq, { id: row.id });
227 } else {
228 $scope.hidePanel();
229 }
230 $log.debug('Got a click on:', row);
231 }
232
Bri Prebilic Cole864cdd62015-04-02 15:46:47 -0700233 tbs.buildTable({
Bri Prebilic Cole864cdd62015-04-02 15:46:47 -0700234 scope: $scope,
Simon Hunte408af72017-06-14 18:32:06 -0700235 tag: 'host',
236 selCb: selCb
237 });
238
239 $scope.nav = function (path) {
240 if ($scope.selId) {
241 ns.navTo(path, { hostId: $scope.selId });
242 }
243 };
244
245 $scope.$on('$destroy', function () {
246 wss.unbindHandlers(handlers);
Thomas Vachuskae586b792015-03-26 13:59:38 -0700247 });
Bri Prebilic Cole3d4d01c2015-04-30 13:48:36 -0700248
Bri Prebilic Cole19a32dd2015-03-26 18:00:03 -0700249 $log.log('OvHostCtrl has been created');
Simon Hunte408af72017-06-14 18:32:06 -0700250 }])
251
252 .directive('hostDetailsPanel',
253 ['$rootScope', '$window', '$timeout', 'KeyService',
254 function ($rootScope, $window, $timeout, ks) {
255 return function (scope) {
256 var unbindWatch;
257
258 function heightCalc() {
259 pStartY = fs.noPxStyle(d3.select('.tabular-header'), 'height')
260 + mast.mastHeight() + topPdg;
261 wSize = fs.windowSize(pStartY);
262 pHeight = wSize.height;
263 }
264
265 function initPanel() {
266 heightCalc();
267 createDetailsPane();
268 }
269
270 // Safari has a bug where it renders the fixed-layout table wrong
271 // if you ask for the window's size too early
272 if (scope.onos.browser === 'safari') {
273 $timeout(initPanel);
274 } else {
275 initPanel();
276 }
277 // create key bindings to handle panel
278 ks.keyBindings({
279 enter: editNameSave,
280 esc: [handleEscape, 'Close the details panel'],
281 _helpFormat: ['esc']
282 });
283 ks.gestureNotes([
284 ['click', 'Select a row to show device details'],
285 ['scroll down', 'See more devices']
286 ]);
287
288 // if the panelData changes
289 scope.$watch('panelData', function () {
290 if (!fs.isEmptyObject(scope.panelData)) {
291 populateDetails(scope.panelData);
292 detailsPanel.show();
293 }
294 });
295
296 // if the window size changes
297 unbindWatch = $rootScope.$watchCollection(
298 function () {
299 return {
300 h: $window.innerHeight,
301 w: $window.innerWidth
302 };
303 }, function () {
304 if (!fs.isEmptyObject(scope.panelData)) {
305 heightCalc();
306 populateDetails(scope.panelData);
307 }
308 }
309 );
310
311 scope.$on('$destroy', function () {
312 unbindWatch();
313 ks.unbindKeys();
314 ps.destroyPanel(pName);
315 });
316 };
317 }]);
Thomas Vachuskae586b792015-03-26 13:59:38 -0700318}());