blob: a01dd2eb3748312faedbc7dc5af882886bbbb5b9 [file] [log] [blame]
Thomas Vachuska0fa583c2015-03-30 23:07:41 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Thomas Vachuska0fa583c2015-03-30 23:07:41 -07003 *
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -07004 * Licensed under the Apache License, Version 2.0 (the 'License');
Thomas Vachuska0fa583c2015-03-30 23:07:41 -07005 * 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
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -070011 * distributed under the License is distributed on an 'AS IS' BASIS,
Thomas Vachuska0fa583c2015-03-30 23:07:41 -070012 * 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 -- App View Module
19 */
20
21(function () {
22 'use strict';
23
Jian Lia54de5a2016-01-20 23:10:39 -080024 // injected refs
Simon Hunt94f36fc2017-07-12 17:47:17 -070025 var $log, $scope, wss, fs, ks, ps, is, ls;
Jian Lia54de5a2016-01-20 23:10:39 -080026
27 // internal state
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -080028 var detailsPanel,
29 pStartY,
30 pHeight,
31 top,
32 middle,
33 bottom,
34 wSize = false,
Jayasree Ghosh25e21662016-12-23 15:59:47 +053035 activateImmediately = '';
Jian Lia54de5a2016-01-20 23:10:39 -080036
Bri Prebilic Cole522e7562015-06-22 15:56:25 -070037 // constants
38 var INSTALLED = 'INSTALLED',
39 ACTIVE = 'ACTIVE',
Simon Hunt8d28a552016-01-11 14:01:02 -080040 appMgmtReq = 'appManagementRequest',
Simon Hunt047f4052016-06-06 16:51:11 -070041 topPdg = 60,
42 panelWidth = 540,
Jian Lia54de5a2016-01-20 23:10:39 -080043 pName = 'application-details-panel',
44 detailsReq = 'appDetailsRequest',
45 detailsResp = 'appDetailsResponse',
Simon Hunt8d28a552016-01-11 14:01:02 -080046 fileUploadUrl = 'applications/upload',
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -080047 activateOption = '?activate=true',
Jian Lia54de5a2016-01-20 23:10:39 -080048 iconUrlPrefix = 'rs/applications/',
49 iconUrlSuffix = '/icon',
Simon Hunt8d28a552016-01-11 14:01:02 -080050 dialogId = 'app-dialog',
51 dialogOpts = {
Simon Hunt0991b342016-06-08 13:18:16 -070052 edge: 'right',
Steven Burrows1c2a9682017-07-14 16:52:46 +010053 width: 400,
Simon Hunt3f92c432016-01-12 17:34:23 -080054 },
55 strongWarning = {
Steven Burrows1c2a9682017-07-14 16:52:46 +010056 'org.onosproject.drivers': true,
Simon Hunt3f92c432016-01-12 17:34:23 -080057 },
Simon Hunt94f36fc2017-07-12 17:47:17 -070058 propOrder = ['id', 'state', 'category', 'version', 'origin', 'role'];
Simon Hunt31642932016-01-22 20:34:00 -080059 // note: url is handled separately
Jian Lia54de5a2016-01-20 23:10:39 -080060
Simon Hunt94f36fc2017-07-12 17:47:17 -070061 // deferred localization strings
Simon Huntcaed0412017-08-12 13:49:17 -070062 var warnDeactivate,
63 warnOwnRisk,
Simon Hunt94f36fc2017-07-12 17:47:17 -070064 friendlyProps,
65 lion;
66
67 function doLion() {
68 lion = ls.bundle('core.view.App');
69
Simon Huntcaed0412017-08-12 13:49:17 -070070 warnDeactivate = lion('dlg_warn_deactivate');
71 warnOwnRisk = lion('dlg_warn_own_risk');
Simon Hunt94f36fc2017-07-12 17:47:17 -070072
73 friendlyProps = [
74 lion('app_id'), lion('state'), lion('category'), lion('version'),
Steven Burrows1c2a9682017-07-14 16:52:46 +010075 lion('origin'), lion('role'),
Simon Hunt94f36fc2017-07-12 17:47:17 -070076 ];
77 }
78
Jian Lia54de5a2016-01-20 23:10:39 -080079 function createDetailsPane() {
80 detailsPanel = ps.createPanel(pName, {
81 width: wSize.width,
82 margin: 0,
Steven Burrows1c2a9682017-07-14 16:52:46 +010083 hideMargin: 0,
Jian Lia54de5a2016-01-20 23:10:39 -080084 });
85 detailsPanel.el().style({
86 position: 'absolute',
Steven Burrows1c2a9682017-07-14 16:52:46 +010087 top: pStartY + 'px',
Jian Lia54de5a2016-01-20 23:10:39 -080088 });
89 $scope.hidePanel = function () { detailsPanel.hide(); };
90 detailsPanel.hide();
91 }
92
93 function closePanel() {
94 if (detailsPanel.isVisible()) {
95 $scope.selId = null;
96 detailsPanel.hide();
97 return true;
98 }
99 return false;
100 }
101
Jian Lia54de5a2016-01-20 23:10:39 -0800102 function addCloseBtn(div) {
Simon Hunte6e09842016-06-07 11:11:26 -0700103 is.loadEmbeddedIcon(div, 'close', 26);
Jian Lia54de5a2016-01-20 23:10:39 -0800104 div.on('click', closePanel);
105 }
106
107 function setUpPanel() {
Simon Hunt31642932016-01-22 20:34:00 -0800108 var container, closeBtn, div;
109
Jian Lia54de5a2016-01-20 23:10:39 -0800110 detailsPanel.empty();
Simon Hunt31642932016-01-22 20:34:00 -0800111 detailsPanel.width(panelWidth);
Jian Lia54de5a2016-01-20 23:10:39 -0800112
113 container = detailsPanel.append('div').classed('container', true);
114
115 top = container.append('div').classed('top', true);
116 closeBtn = top.append('div').classed('close-btn', true);
117 addCloseBtn(closeBtn);
Jian Lia54de5a2016-01-20 23:10:39 -0800118
Simon Hunt31642932016-01-22 20:34:00 -0800119 div = top.append('div').classed('top-content', true);
Jian Lia54de5a2016-01-20 23:10:39 -0800120
Simon Hunt31642932016-01-22 20:34:00 -0800121 function ndiv(cls, tcls) {
Steven Burrows1c2a9682017-07-14 16:52:46 +0100122 var d = div.append('div').classed(cls, true);
Simon Hunt31642932016-01-22 20:34:00 -0800123 if (tcls) {
124 d.append('table').classed(tcls, true);
125 }
126 }
127
Simon Hunt877ee982016-03-09 10:53:16 -0800128 ndiv('app-title');
Simon Hunt31642932016-01-22 20:34:00 -0800129 ndiv('left app-icon');
130 ndiv('right', 'app-props');
131 ndiv('app-url');
132
133 container.append('hr');
Jian Lia54de5a2016-01-20 23:10:39 -0800134
Jian Lida253e02016-01-21 17:46:17 -0800135 middle = container.append('div').classed('middle', true);
Simon Hunt31642932016-01-22 20:34:00 -0800136 middle.append('div').classed('app-readme', true);
Jian Lida253e02016-01-21 17:46:17 -0800137
Simon Hunt31642932016-01-22 20:34:00 -0800138 container.append('hr');
Jian Lida253e02016-01-21 17:46:17 -0800139
Simon Hunt31642932016-01-22 20:34:00 -0800140 // TODO: make bottom container scrollable
Jian Lia54de5a2016-01-20 23:10:39 -0800141 bottom = container.append('div').classed('bottom', true);
Simon Hunt31642932016-01-22 20:34:00 -0800142
143 function nTable(hdr, cls) {
Simon Hunt239f09e2017-05-18 13:10:09 -0700144 bottom.append('h2').text(hdr);
Simon Hunt31642932016-01-22 20:34:00 -0800145 bottom.append('div').classed(cls, true).append('table');
146 }
147
Simon Hunt94f36fc2017-07-12 17:47:17 -0700148 nTable(lion('dp_features'), 'features');
149 nTable(lion('dp_required_apps'), 'required-apps');
150 nTable(lion('dp_permissions'), 'permissions');
Jian Lia54de5a2016-01-20 23:10:39 -0800151 }
152
153 function addProp(tbody, index, value) {
Simon Hunt811d8572016-06-02 13:40:14 -0700154 var tr = tbody.append('tr');
Jian Lia54de5a2016-01-20 23:10:39 -0800155
156 function addCell(cls, txt) {
Simon Hunt239f09e2017-05-18 13:10:09 -0700157 tr.append('td').attr('class', cls).text(txt);
Jian Lia54de5a2016-01-20 23:10:39 -0800158 }
Simon Hunt31642932016-01-22 20:34:00 -0800159
160 addCell('label', friendlyProps[index] + ':');
Simon Hunt811d8572016-06-02 13:40:14 -0700161 addCell('value', value);
Jian Lia54de5a2016-01-20 23:10:39 -0800162 }
163
Simon Hunt31642932016-01-22 20:34:00 -0800164 function urlize(u) {
Simon Hunt239f09e2017-05-18 13:10:09 -0700165 u = fs.sanitize(u);
Thomas Vachuska3bdfa772017-05-10 18:33:42 -0700166 return '<a href="' + u + '" target="_blank">' + u + '</a>';
Simon Hunta477b602016-01-22 12:10:07 -0800167 }
168
Simon Hunt31642932016-01-22 20:34:00 -0800169 function addIcon(elem, value) {
170 elem.append('img').attr('src', iconUrlPrefix + value + iconUrlSuffix);
Jian Lia54de5a2016-01-20 23:10:39 -0800171 }
172
Simon Hunt31642932016-01-22 20:34:00 -0800173 function populateTop(details) {
174 var propsBody = top.select('.app-props').append('tbody'),
175 url = details.url;
Jian Lia54de5a2016-01-20 23:10:39 -0800176
Simon Hunt877ee982016-03-09 10:53:16 -0800177 top.select('.app-title').text(details.title);
178
Simon Hunt31642932016-01-22 20:34:00 -0800179 addIcon(top.select('.app-icon'), details.id);
Jian Lia54de5a2016-01-20 23:10:39 -0800180
Jian Lia54de5a2016-01-20 23:10:39 -0800181 propOrder.forEach(function (prop, i) {
Simon Hunt31642932016-01-22 20:34:00 -0800182 addProp(propsBody, i, details[prop]);
Jian Lia54de5a2016-01-20 23:10:39 -0800183 });
184
Simon Hunt31642932016-01-22 20:34:00 -0800185 if (url) {
186 top.select('.app-url').html(urlize(url));
187 }
Jian Lida253e02016-01-21 17:46:17 -0800188 }
189
Simon Hunt31642932016-01-22 20:34:00 -0800190 function populateMiddle(details) {
191 middle.select('.app-readme').text(details.readme);
Jian Lia54de5a2016-01-20 23:10:39 -0800192 }
193
Simon Hunt31642932016-01-22 20:34:00 -0800194 function populateBottom(details) {
195
196 function addItems(cls, items) {
197 var table = bottom.select('.' + cls).select('table'),
198 tbody = table.append('tbody');
199
200 items.forEach(function (item) {
Simon Hunt239f09e2017-05-18 13:10:09 -0700201 tbody.append('tr').append('td').text(item);
Simon Hunt31642932016-01-22 20:34:00 -0800202 });
203 }
204
205 addItems('features', details.features);
206 addItems('required-apps', details.required_apps);
207 addItems('permissions', details.permissions);
Jian Lia54de5a2016-01-20 23:10:39 -0800208 }
209
210 function populateDetails(details) {
Jian Lia54de5a2016-01-20 23:10:39 -0800211 setUpPanel();
Simon Hunt31642932016-01-22 20:34:00 -0800212 populateTop(details);
213 populateMiddle(details);
214 populateBottom(details);
Jian Lia54de5a2016-01-20 23:10:39 -0800215 detailsPanel.height(pHeight);
216 }
217
Jian Lia54de5a2016-01-20 23:10:39 -0800218 function respDetailsCb(data) {
219 $scope.panelData = data.details;
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800220 $scope.selId = data.details.id;
221 $scope.ctrlBtnState.selection = data.details.id;
Jian Lia54de5a2016-01-20 23:10:39 -0800222 $scope.$apply();
223 }
Bri Prebilic Coleb699a162015-04-13 12:01:39 -0700224
Thomas Vachuska0fa583c2015-03-30 23:07:41 -0700225 angular.module('ovApp', [])
226 .controller('OvAppCtrl',
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800227 ['$log', '$scope', '$http', '$timeout',
Simon Hunt31642932016-01-22 20:34:00 -0800228 'WebSocketService', 'FnService', 'KeyService', 'PanelService',
229 'IconService', 'UrlFnService', 'DialogService', 'TableBuilderService',
Simon Hunt94f36fc2017-07-12 17:47:17 -0700230 'LionService',
Thomas Vachuska0fa583c2015-03-30 23:07:41 -0700231
Simon Huntf51bf462016-06-29 16:22:57 -0700232 function (_$log_, _$scope_, $http, $timeout, _wss_, _fs_, _ks_, _ps_, _is_,
Simon Hunt94f36fc2017-07-12 17:47:17 -0700233 ufs, ds, tbs, _ls_) {
Jian Lia54de5a2016-01-20 23:10:39 -0800234 $log = _$log_;
235 $scope = _$scope_;
236 wss = _wss_;
Jian Lia54de5a2016-01-20 23:10:39 -0800237 fs = _fs_;
Simon Hunt31642932016-01-22 20:34:00 -0800238 ks = _ks_;
Jian Lia54de5a2016-01-20 23:10:39 -0800239 ps = _ps_;
240 is = _is_;
Simon Hunt94f36fc2017-07-12 17:47:17 -0700241 ls = _ls_;
242
243 doLion();
244
245 $scope.lion = lion;
246
Jian Lia54de5a2016-01-20 23:10:39 -0800247 $scope.panelData = {};
Bri Prebilic Cole6b95a3f2015-06-04 09:15:00 -0700248 $scope.ctrlBtnState = {};
Simon Hunt94f36fc2017-07-12 17:47:17 -0700249 $scope.uploadTip = lion('tt_ctl_upload');
250 $scope.activateTip = lion('tt_ctl_activate');
251 $scope.deactivateTip = lion('tt_ctl_deactivate');
252 $scope.uninstallTip = lion('tt_ctl_uninstall');
253
Bri Prebilic Cole6b95a3f2015-06-04 09:15:00 -0700254
Jian Lia54de5a2016-01-20 23:10:39 -0800255 var handlers = {};
256
257 // details panel handlers
258 handlers[detailsResp] = respDetailsCb;
259 wss.bindHandlers(handlers);
260
Bri Prebilic Coleb699a162015-04-13 12:01:39 -0700261 function selCb($event, row) {
Simon Hunt3f92c432016-01-12 17:34:23 -0800262 // $scope.selId is set by code in tableBuilder
Bri Prebilic Cole6b95a3f2015-06-04 09:15:00 -0700263 $scope.ctrlBtnState.selection = !!$scope.selId;
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700264 refreshCtrls();
Steven Burrows1c2a9682017-07-14 16:52:46 +0100265 ds.closeDialog(); // don't want dialog from previous selection
Jian Lia54de5a2016-01-20 23:10:39 -0800266
267 if ($scope.selId) {
268 wss.sendEvent(detailsReq, { id: row.id });
269 } else {
270 $scope.hidePanel();
271 }
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700272 }
273
Bri Prebilic Colea7f81e52015-06-23 10:11:08 -0700274 function refreshCtrls() {
275 var row, rowIdx;
276 if ($scope.ctrlBtnState.selection) {
277 rowIdx = fs.find($scope.selId, $scope.tableData);
278 row = rowIdx >= 0 ? $scope.tableData[rowIdx] : null;
279
280 $scope.ctrlBtnState.installed = row && row.state === INSTALLED;
281 $scope.ctrlBtnState.active = row && row.state === ACTIVE;
282 } else {
283 $scope.ctrlBtnState.installed = false;
284 $scope.ctrlBtnState.active = false;
285 }
Thomas Vachuska619c5382015-04-02 13:41:47 -0700286 }
Thomas Vachuska0fa583c2015-03-30 23:07:41 -0700287
Bri Prebilic Cole6b95a3f2015-06-04 09:15:00 -0700288 tbs.buildTable({
289 scope: $scope,
290 tag: 'app',
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700291 selCb: selCb,
Simon Hunta678b842016-01-11 17:14:18 -0800292 respCb: refreshCtrls,
293 // pre-populate sort so active apps are at the top of the list
294 sortParams: {
Simon Hunt051e9fa2016-01-19 15:54:22 -0800295 firstCol: 'state',
296 firstDir: 'desc',
Simon Hunt877ee982016-03-09 10:53:16 -0800297 secondCol: 'title',
Steven Burrows1c2a9682017-07-14 16:52:46 +0100298 secondDir: 'asc',
Simon Hunt94f36fc2017-07-12 17:47:17 -0700299 },
Steven Burrows1c2a9682017-07-14 16:52:46 +0100300 lion_toggle_auto_refresh: lion('tt_ctl_auto_refresh'),
Bri Prebilic Cole6b95a3f2015-06-04 09:15:00 -0700301 });
302
Bri Prebilic Cole9dcaea52015-07-21 14:39:48 -0700303 ks.keyBindings({
Simon Hunt94f36fc2017-07-12 17:47:17 -0700304 esc: [$scope.selectCallback, lion('qh_hint_esc')],
Steven Burrows1c2a9682017-07-14 16:52:46 +0100305 _helpFormat: ['esc'],
Bri Prebilic Cole9dcaea52015-07-21 14:39:48 -0700306 });
307 ks.gestureNotes([
Simon Hunt94f36fc2017-07-12 17:47:17 -0700308 [lion('click_row'), lion('qh_hint_click_row')],
Steven Burrows1c2a9682017-07-14 16:52:46 +0100309 [lion('scroll_down'), lion('qh_hint_scroll_down')],
Bri Prebilic Cole9dcaea52015-07-21 14:39:48 -0700310 ]);
311
Simon Hunt3f92c432016-01-12 17:34:23 -0800312 function createConfirmationText(action, itemId) {
Simon Hunt8d28a552016-01-11 14:01:02 -0800313 var content = ds.createDiv();
Simon Hunt94f36fc2017-07-12 17:47:17 -0700314 content.append('p').text(lion(action) + ' ' + itemId);
Simon Hunt3f92c432016-01-12 17:34:23 -0800315 if (strongWarning[itemId]) {
Simon Hunt94f36fc2017-07-12 17:47:17 -0700316 content.append('p').html(
Simon Huntcaed0412017-08-12 13:49:17 -0700317 fs.sanitize(warnDeactivate) +
Simon Hunt94f36fc2017-07-12 17:47:17 -0700318 '<br>' +
Simon Huntcaed0412017-08-12 13:49:17 -0700319 fs.sanitize(warnOwnRisk)
Simon Hunt94f36fc2017-07-12 17:47:17 -0700320 ).classed('strong', true);
Simon Hunt3f92c432016-01-12 17:34:23 -0800321 }
Simon Hunt8d28a552016-01-11 14:01:02 -0800322 return content;
323 }
324
325 function confirmAction(action) {
Simon Hunt3f92c432016-01-12 17:34:23 -0800326 var itemId = $scope.selId,
Simon Hunt8d28a552016-01-11 14:01:02 -0800327 spar = $scope.sortParams;
328
329 function dOk() {
Simon Hunt3f92c432016-01-12 17:34:23 -0800330 $log.debug('Initiating', action, 'of', itemId);
Simon Hunt8d28a552016-01-11 14:01:02 -0800331 wss.sendEvent(appMgmtReq, {
332 action: action,
Simon Hunt3f92c432016-01-12 17:34:23 -0800333 name: itemId,
Simon Hunt8d28a552016-01-11 14:01:02 -0800334 sortCol: spar.sortCol,
Steven Burrows1c2a9682017-07-14 16:52:46 +0100335 sortDir: spar.sortDir,
Simon Hunt8d28a552016-01-11 14:01:02 -0800336 });
Simon Hunt94f36fc2017-07-12 17:47:17 -0700337 if (action === 'uninstall') {
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800338 detailsPanel.hide();
339 } else {
Steven Burrows1c2a9682017-07-14 16:52:46 +0100340 wss.sendEvent(detailsReq, { id: itemId });
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800341 }
Simon Hunt8d28a552016-01-11 14:01:02 -0800342 }
343
344 function dCancel() {
Simon Hunt3f92c432016-01-12 17:34:23 -0800345 $log.debug('Canceling', action, 'of', itemId);
Simon Hunt8d28a552016-01-11 14:01:02 -0800346 }
347
348 ds.openDialog(dialogId, dialogOpts)
Simon Hunt94f36fc2017-07-12 17:47:17 -0700349 .setTitle(lion('dlg_confirm_action'))
Simon Hunt3f92c432016-01-12 17:34:23 -0800350 .addContent(createConfirmationText(action, itemId))
Simon Hunt5198f082016-02-04 13:41:17 -0800351 .addOk(dOk)
352 .addCancel(dCancel)
353 .bindKeys();
Simon Hunt8d28a552016-01-11 14:01:02 -0800354 }
355
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700356 $scope.appAction = function (action) {
357 if ($scope.ctrlBtnState.selection) {
Simon Hunt8d28a552016-01-11 14:01:02 -0800358 confirmAction(action);
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700359 }
Bri Prebilic Colebd0bc772015-05-13 13:02:26 -0700360 };
Thomas Vachuska530e52a2015-05-06 19:51:32 -0700361
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700362 $scope.$on('FileChanged', function () {
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800363 var formData = new FormData(),
364 url;
Simon Huntf51bf462016-06-29 16:22:57 -0700365
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700366 if ($scope.appFile) {
367 formData.append('file', $scope.appFile);
Simon Huntf51bf462016-06-29 16:22:57 -0700368 url = fileUploadUrl + activateImmediately;
369
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800370 $http.post(ufs.rsUrl(url), formData, {
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700371 transformRequest: angular.identity,
372 headers: {
Steven Burrows1c2a9682017-07-14 16:52:46 +0100373 'Content-Type': undefined,
374 },
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700375 })
Simon Huntf51bf462016-06-29 16:22:57 -0700376 .finally(function () {
377 activateImmediately = '';
378 $scope.sortCallback($scope.sortParams);
379 document.getElementById('inputFileForm').reset();
380 $timeout(function () { wss.sendEvent(detailsReq); }, 250);
381 });
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -0700382 }
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -0700383 });
384
Steven Burrows1c2a9682017-07-14 16:52:46 +0100385 $scope.appDropped = function () {
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800386 activateImmediately = activateOption;
387 $scope.$emit('FileChanged');
388 $scope.appFile = null;
389 };
390
Bri Prebilic Cole9dcaea52015-07-21 14:39:48 -0700391 $scope.$on('$destroy', function () {
392 ks.unbindKeys();
Jian Lia54de5a2016-01-20 23:10:39 -0800393 wss.unbindHandlers(handlers);
Simon Hunt0991b342016-06-08 13:18:16 -0700394 ds.closeDialog();
Bri Prebilic Cole9dcaea52015-07-21 14:39:48 -0700395 });
396
Thomas Vachuska619c5382015-04-02 13:41:47 -0700397 $log.log('OvAppCtrl has been created');
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700398 }])
399
400 // triggers the input form to appear when button is clicked
401 .directive('triggerForm', function () {
402 return {
403 restrict: 'A',
404 link: function (scope, elem) {
405 elem.bind('click', function () {
406 document.getElementById('uploadFile')
Bri Prebilic Cole6c82ade2015-08-05 11:12:30 -0700407 .dispatchEvent(new MouseEvent('click'));
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700408 });
Steven Burrows1c2a9682017-07-14 16:52:46 +0100409 },
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700410 };
411 })
412
413 // binds the model file to the scope in scope.appFile
414 // sends upload request to the server
415 .directive('fileModel', ['$parse',
Simon Huntf51bf462016-06-29 16:22:57 -0700416 function ($parse) {
417 return {
418 restrict: 'A',
419 link: function (scope, elem, attrs) {
420 var model = $parse(attrs.fileModel),
421 modelSetter = model.assign;
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700422
Simon Huntf51bf462016-06-29 16:22:57 -0700423 elem.bind('change', function () {
424 scope.$apply(function () {
425 modelSetter(scope, elem[0].files[0]);
426 });
427 scope.$emit('FileChanged');
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700428 });
Steven Burrows1c2a9682017-07-14 16:52:46 +0100429 },
Simon Huntf51bf462016-06-29 16:22:57 -0700430 };
431 }])
Jian Lia54de5a2016-01-20 23:10:39 -0800432
Steven Burrows1c2a9682017-07-14 16:52:46 +0100433 .directive('filedrop', ['$parse', '$document', function ($parse, $document) {
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800434 return {
Steven Burrows1c2a9682017-07-14 16:52:46 +0100435 restrict: 'A',
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800436 link: function (scope, element, attrs) {
437 var onAppDrop = $parse(attrs.onFileDrop);
438
439 // When an item is dragged over the document
440 var onDragOver = function (e) {
Thomas Vachuskaebf3be02016-04-11 09:52:06 -0700441 d3.select('#frame').classed('dropping', true);
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800442 e.preventDefault();
443 };
444
445 // When the user leaves the window, cancels the drag or drops the item
446 var onDragEnd = function (e) {
Thomas Vachuskaebf3be02016-04-11 09:52:06 -0700447 d3.select('#frame').classed('dropping', false);
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800448 e.preventDefault();
449 };
450
451 // When a file is dropped
452 var loadFile = function (file) {
453 scope.appFile = file;
454 scope.$apply(onAppDrop(scope));
455 };
456
457 // Dragging begins on the document
Steven Burrows1c2a9682017-07-14 16:52:46 +0100458 $document.bind('dragover', onDragOver);
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800459
460 // Dragging ends on the overlay, which takes the whole window
Steven Burrows1c2a9682017-07-14 16:52:46 +0100461 element.bind('dragleave', onDragEnd)
462 .bind('drop', function (e) {
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800463 $log.info('Drag leave', e);
464 loadFile(e.dataTransfer.files[0]);
465 onDragEnd(e);
466 });
Steven Burrows1c2a9682017-07-14 16:52:46 +0100467 },
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800468 };
Steven Burrows96ee21e2017-07-11 19:49:45 +0100469 }])
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800470
Jian Lia54de5a2016-01-20 23:10:39 -0800471 .directive('applicationDetailsPanel',
472 ['$rootScope', '$window', '$timeout', 'KeyService',
473 function ($rootScope, $window, $timeout, ks) {
474 return function (scope) {
475 var unbindWatch;
476
477 function heightCalc() {
478 pStartY = fs.noPxStyle(d3.select('.tabular-header'), 'height')
479 + topPdg;
480 wSize = fs.windowSize(pStartY);
481 pHeight = wSize.height;
482 }
483
484 function initPanel() {
485 heightCalc();
486 createDetailsPane();
487 $log.debug('start to initialize panel!');
488 }
489
490 // Safari has a bug where it renders the fixed-layout table wrong
491 // if you ask for the window's size too early
492 if (scope.onos.browser === 'safari') {
493 $timeout(initPanel);
494 } else {
495 initPanel();
496 }
497 // create key bindings to handle panel
498 ks.keyBindings({
Simon Hunt94f36fc2017-07-12 17:47:17 -0700499 esc: [closePanel, lion('qh_hint_close_detail')],
Steven Burrows1c2a9682017-07-14 16:52:46 +0100500 _helpFormat: ['esc'],
Jian Lia54de5a2016-01-20 23:10:39 -0800501 });
Simon Hunt94f36fc2017-07-12 17:47:17 -0700502
503 // TODO: Review - why are we doing this in the detail panel...?
Jian Lia54de5a2016-01-20 23:10:39 -0800504 ks.gestureNotes([
Simon Hunt94f36fc2017-07-12 17:47:17 -0700505 [lion('click_row'), lion('qh_hint_click_row')],
Steven Burrows1c2a9682017-07-14 16:52:46 +0100506 [lion('scroll_down'), lion('qh_hint_scroll_down')],
Jian Lia54de5a2016-01-20 23:10:39 -0800507 ]);
508
509 // if the panelData changes
510 scope.$watch('panelData', function () {
511 if (!fs.isEmptyObject(scope.panelData)) {
512 populateDetails(scope.panelData);
513 detailsPanel.show();
514 }
515 });
516
517 // if the window size changes
518 unbindWatch = $rootScope.$watchCollection(
519 function () {
520 return {
521 h: $window.innerHeight,
Steven Burrows1c2a9682017-07-14 16:52:46 +0100522 w: $window.innerWidth,
Jian Lia54de5a2016-01-20 23:10:39 -0800523 };
524 }, function () {
525 if (!fs.isEmptyObject(scope.panelData)) {
526 heightCalc();
527 populateDetails(scope.panelData);
528 }
529 }
530 );
531
532 scope.$on('$destroy', function () {
533 unbindWatch();
534 ks.unbindKeys();
535 ps.destroyPanel(pName);
536 });
537 };
538 }]);
Thomas Vachuska0fa583c2015-03-30 23:07:41 -0700539}());