blob: 5a2272e9a39c31101829f92711063e4db9e998de [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',
Thomas Vachuska08b4dec2017-08-31 15:20:17 -070048 appUrlPrefix = 'rs/applications/',
Jian Lia54de5a2016-01-20 23:10:39 -080049 iconUrlSuffix = '/icon',
Thomas Vachuska08b4dec2017-08-31 15:20:17 -070050 downloadSuffix = '/download',
Simon Hunt8d28a552016-01-11 14:01:02 -080051 dialogId = 'app-dialog',
52 dialogOpts = {
Simon Hunt0991b342016-06-08 13:18:16 -070053 edge: 'right',
Steven Burrows1c2a9682017-07-14 16:52:46 +010054 width: 400,
Simon Hunt3f92c432016-01-12 17:34:23 -080055 },
56 strongWarning = {
Steven Burrows1c2a9682017-07-14 16:52:46 +010057 'org.onosproject.drivers': true,
Simon Hunt3f92c432016-01-12 17:34:23 -080058 },
Simon Hunt94f36fc2017-07-12 17:47:17 -070059 propOrder = ['id', 'state', 'category', 'version', 'origin', 'role'];
Simon Hunt31642932016-01-22 20:34:00 -080060 // note: url is handled separately
Jian Lia54de5a2016-01-20 23:10:39 -080061
Simon Hunt94f36fc2017-07-12 17:47:17 -070062 // deferred localization strings
Simon Huntcaed0412017-08-12 13:49:17 -070063 var warnDeactivate,
64 warnOwnRisk,
Simon Hunt94f36fc2017-07-12 17:47:17 -070065 friendlyProps,
66 lion;
67
68 function doLion() {
69 lion = ls.bundle('core.view.App');
70
Simon Huntcaed0412017-08-12 13:49:17 -070071 warnDeactivate = lion('dlg_warn_deactivate');
72 warnOwnRisk = lion('dlg_warn_own_risk');
Simon Hunt94f36fc2017-07-12 17:47:17 -070073
74 friendlyProps = [
75 lion('app_id'), lion('state'), lion('category'), lion('version'),
Steven Burrows1c2a9682017-07-14 16:52:46 +010076 lion('origin'), lion('role'),
Simon Hunt94f36fc2017-07-12 17:47:17 -070077 ];
78 }
79
Jian Lia54de5a2016-01-20 23:10:39 -080080 function createDetailsPane() {
81 detailsPanel = ps.createPanel(pName, {
82 width: wSize.width,
83 margin: 0,
Steven Burrows1c2a9682017-07-14 16:52:46 +010084 hideMargin: 0,
Jian Lia54de5a2016-01-20 23:10:39 -080085 });
86 detailsPanel.el().style({
87 position: 'absolute',
Steven Burrows1c2a9682017-07-14 16:52:46 +010088 top: pStartY + 'px',
Jian Lia54de5a2016-01-20 23:10:39 -080089 });
90 $scope.hidePanel = function () { detailsPanel.hide(); };
91 detailsPanel.hide();
92 }
93
94 function closePanel() {
95 if (detailsPanel.isVisible()) {
96 $scope.selId = null;
97 detailsPanel.hide();
98 return true;
99 }
100 return false;
101 }
102
Jian Lia54de5a2016-01-20 23:10:39 -0800103 function addCloseBtn(div) {
Simon Hunte6e09842016-06-07 11:11:26 -0700104 is.loadEmbeddedIcon(div, 'close', 26);
Jian Lia54de5a2016-01-20 23:10:39 -0800105 div.on('click', closePanel);
106 }
107
108 function setUpPanel() {
Simon Hunt31642932016-01-22 20:34:00 -0800109 var container, closeBtn, div;
110
Jian Lia54de5a2016-01-20 23:10:39 -0800111 detailsPanel.empty();
Simon Hunt31642932016-01-22 20:34:00 -0800112 detailsPanel.width(panelWidth);
Jian Lia54de5a2016-01-20 23:10:39 -0800113
114 container = detailsPanel.append('div').classed('container', true);
115
116 top = container.append('div').classed('top', true);
117 closeBtn = top.append('div').classed('close-btn', true);
118 addCloseBtn(closeBtn);
Jian Lia54de5a2016-01-20 23:10:39 -0800119
Simon Hunt31642932016-01-22 20:34:00 -0800120 div = top.append('div').classed('top-content', true);
Jian Lia54de5a2016-01-20 23:10:39 -0800121
Simon Hunt31642932016-01-22 20:34:00 -0800122 function ndiv(cls, tcls) {
Steven Burrows1c2a9682017-07-14 16:52:46 +0100123 var d = div.append('div').classed(cls, true);
Simon Hunt31642932016-01-22 20:34:00 -0800124 if (tcls) {
125 d.append('table').classed(tcls, true);
126 }
127 }
128
Simon Hunt877ee982016-03-09 10:53:16 -0800129 ndiv('app-title');
Simon Hunt31642932016-01-22 20:34:00 -0800130 ndiv('left app-icon');
131 ndiv('right', 'app-props');
132 ndiv('app-url');
133
134 container.append('hr');
Jian Lia54de5a2016-01-20 23:10:39 -0800135
Jian Lida253e02016-01-21 17:46:17 -0800136 middle = container.append('div').classed('middle', true);
Simon Hunt31642932016-01-22 20:34:00 -0800137 middle.append('div').classed('app-readme', true);
Jian Lida253e02016-01-21 17:46:17 -0800138
Simon Hunt31642932016-01-22 20:34:00 -0800139 container.append('hr');
Jian Lida253e02016-01-21 17:46:17 -0800140
Simon Hunt31642932016-01-22 20:34:00 -0800141 // TODO: make bottom container scrollable
Jian Lia54de5a2016-01-20 23:10:39 -0800142 bottom = container.append('div').classed('bottom', true);
Simon Hunt31642932016-01-22 20:34:00 -0800143
144 function nTable(hdr, cls) {
Simon Hunt239f09e2017-05-18 13:10:09 -0700145 bottom.append('h2').text(hdr);
Simon Hunt31642932016-01-22 20:34:00 -0800146 bottom.append('div').classed(cls, true).append('table');
147 }
148
Simon Hunt94f36fc2017-07-12 17:47:17 -0700149 nTable(lion('dp_features'), 'features');
150 nTable(lion('dp_required_apps'), 'required-apps');
151 nTable(lion('dp_permissions'), 'permissions');
Jian Lia54de5a2016-01-20 23:10:39 -0800152 }
153
154 function addProp(tbody, index, value) {
Simon Hunt811d8572016-06-02 13:40:14 -0700155 var tr = tbody.append('tr');
Jian Lia54de5a2016-01-20 23:10:39 -0800156
157 function addCell(cls, txt) {
Simon Hunt239f09e2017-05-18 13:10:09 -0700158 tr.append('td').attr('class', cls).text(txt);
Jian Lia54de5a2016-01-20 23:10:39 -0800159 }
Simon Hunt31642932016-01-22 20:34:00 -0800160
161 addCell('label', friendlyProps[index] + ':');
Simon Hunt811d8572016-06-02 13:40:14 -0700162 addCell('value', value);
Jian Lia54de5a2016-01-20 23:10:39 -0800163 }
164
Simon Hunt31642932016-01-22 20:34:00 -0800165 function urlize(u) {
Simon Hunt239f09e2017-05-18 13:10:09 -0700166 u = fs.sanitize(u);
Thomas Vachuska3bdfa772017-05-10 18:33:42 -0700167 return '<a href="' + u + '" target="_blank">' + u + '</a>';
Simon Hunta477b602016-01-22 12:10:07 -0800168 }
169
Simon Hunt31642932016-01-22 20:34:00 -0800170 function addIcon(elem, value) {
Thomas Vachuska08b4dec2017-08-31 15:20:17 -0700171 elem.append('img').attr('src', appUrlPrefix + value + iconUrlSuffix);
Jian Lia54de5a2016-01-20 23:10:39 -0800172 }
173
Simon Hunt31642932016-01-22 20:34:00 -0800174 function populateTop(details) {
175 var propsBody = top.select('.app-props').append('tbody'),
176 url = details.url;
Jian Lia54de5a2016-01-20 23:10:39 -0800177
Simon Hunt877ee982016-03-09 10:53:16 -0800178 top.select('.app-title').text(details.title);
179
Simon Hunt31642932016-01-22 20:34:00 -0800180 addIcon(top.select('.app-icon'), details.id);
Jian Lia54de5a2016-01-20 23:10:39 -0800181
Jian Lia54de5a2016-01-20 23:10:39 -0800182 propOrder.forEach(function (prop, i) {
Simon Hunt31642932016-01-22 20:34:00 -0800183 addProp(propsBody, i, details[prop]);
Jian Lia54de5a2016-01-20 23:10:39 -0800184 });
185
Simon Hunt31642932016-01-22 20:34:00 -0800186 if (url) {
187 top.select('.app-url').html(urlize(url));
188 }
Jian Lida253e02016-01-21 17:46:17 -0800189 }
190
Simon Hunt31642932016-01-22 20:34:00 -0800191 function populateMiddle(details) {
192 middle.select('.app-readme').text(details.readme);
Jian Lia54de5a2016-01-20 23:10:39 -0800193 }
194
Simon Hunt31642932016-01-22 20:34:00 -0800195 function populateBottom(details) {
196
197 function addItems(cls, items) {
198 var table = bottom.select('.' + cls).select('table'),
199 tbody = table.append('tbody');
200
201 items.forEach(function (item) {
Simon Hunt239f09e2017-05-18 13:10:09 -0700202 tbody.append('tr').append('td').text(item);
Simon Hunt31642932016-01-22 20:34:00 -0800203 });
204 }
205
206 addItems('features', details.features);
207 addItems('required-apps', details.required_apps);
208 addItems('permissions', details.permissions);
Jian Lia54de5a2016-01-20 23:10:39 -0800209 }
210
211 function populateDetails(details) {
Jian Lia54de5a2016-01-20 23:10:39 -0800212 setUpPanel();
Simon Hunt31642932016-01-22 20:34:00 -0800213 populateTop(details);
214 populateMiddle(details);
215 populateBottom(details);
Jian Lia54de5a2016-01-20 23:10:39 -0800216 detailsPanel.height(pHeight);
217 }
218
Jian Lia54de5a2016-01-20 23:10:39 -0800219 function respDetailsCb(data) {
220 $scope.panelData = data.details;
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800221 $scope.selId = data.details.id;
222 $scope.ctrlBtnState.selection = data.details.id;
Jian Lia54de5a2016-01-20 23:10:39 -0800223 $scope.$apply();
224 }
Bri Prebilic Coleb699a162015-04-13 12:01:39 -0700225
Thomas Vachuska0fa583c2015-03-30 23:07:41 -0700226 angular.module('ovApp', [])
227 .controller('OvAppCtrl',
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800228 ['$log', '$scope', '$http', '$timeout',
Simon Hunt31642932016-01-22 20:34:00 -0800229 'WebSocketService', 'FnService', 'KeyService', 'PanelService',
230 'IconService', 'UrlFnService', 'DialogService', 'TableBuilderService',
Simon Hunt94f36fc2017-07-12 17:47:17 -0700231 'LionService',
Thomas Vachuska0fa583c2015-03-30 23:07:41 -0700232
Simon Huntf51bf462016-06-29 16:22:57 -0700233 function (_$log_, _$scope_, $http, $timeout, _wss_, _fs_, _ks_, _ps_, _is_,
Simon Hunt94f36fc2017-07-12 17:47:17 -0700234 ufs, ds, tbs, _ls_) {
Jian Lia54de5a2016-01-20 23:10:39 -0800235 $log = _$log_;
236 $scope = _$scope_;
237 wss = _wss_;
Jian Lia54de5a2016-01-20 23:10:39 -0800238 fs = _fs_;
Simon Hunt31642932016-01-22 20:34:00 -0800239 ks = _ks_;
Jian Lia54de5a2016-01-20 23:10:39 -0800240 ps = _ps_;
241 is = _is_;
Simon Hunt94f36fc2017-07-12 17:47:17 -0700242 ls = _ls_;
243
244 doLion();
245
246 $scope.lion = lion;
247
Jian Lia54de5a2016-01-20 23:10:39 -0800248 $scope.panelData = {};
Bri Prebilic Cole6b95a3f2015-06-04 09:15:00 -0700249 $scope.ctrlBtnState = {};
Simon Hunt94f36fc2017-07-12 17:47:17 -0700250 $scope.uploadTip = lion('tt_ctl_upload');
251 $scope.activateTip = lion('tt_ctl_activate');
252 $scope.deactivateTip = lion('tt_ctl_deactivate');
253 $scope.uninstallTip = lion('tt_ctl_uninstall');
Thomas Vachuska08b4dec2017-08-31 15:20:17 -0700254 $scope.downloadTip = lion('tt_ctl_download');
Simon Hunt94f36fc2017-07-12 17:47:17 -0700255
Bri Prebilic Cole6b95a3f2015-06-04 09:15:00 -0700256
Jian Lia54de5a2016-01-20 23:10:39 -0800257 var handlers = {};
258
259 // details panel handlers
260 handlers[detailsResp] = respDetailsCb;
261 wss.bindHandlers(handlers);
262
Bri Prebilic Coleb699a162015-04-13 12:01:39 -0700263 function selCb($event, row) {
Simon Hunt3f92c432016-01-12 17:34:23 -0800264 // $scope.selId is set by code in tableBuilder
Bri Prebilic Cole6b95a3f2015-06-04 09:15:00 -0700265 $scope.ctrlBtnState.selection = !!$scope.selId;
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700266 refreshCtrls();
Steven Burrows1c2a9682017-07-14 16:52:46 +0100267 ds.closeDialog(); // don't want dialog from previous selection
Jian Lia54de5a2016-01-20 23:10:39 -0800268
269 if ($scope.selId) {
270 wss.sendEvent(detailsReq, { id: row.id });
271 } else {
272 $scope.hidePanel();
273 }
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700274 }
275
Bri Prebilic Colea7f81e52015-06-23 10:11:08 -0700276 function refreshCtrls() {
277 var row, rowIdx;
278 if ($scope.ctrlBtnState.selection) {
279 rowIdx = fs.find($scope.selId, $scope.tableData);
280 row = rowIdx >= 0 ? $scope.tableData[rowIdx] : null;
281
282 $scope.ctrlBtnState.installed = row && row.state === INSTALLED;
283 $scope.ctrlBtnState.active = row && row.state === ACTIVE;
284 } else {
285 $scope.ctrlBtnState.installed = false;
286 $scope.ctrlBtnState.active = false;
287 }
Thomas Vachuska619c5382015-04-02 13:41:47 -0700288 }
Thomas Vachuska0fa583c2015-03-30 23:07:41 -0700289
Bri Prebilic Cole6b95a3f2015-06-04 09:15:00 -0700290 tbs.buildTable({
291 scope: $scope,
292 tag: 'app',
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700293 selCb: selCb,
Simon Hunta678b842016-01-11 17:14:18 -0800294 respCb: refreshCtrls,
295 // pre-populate sort so active apps are at the top of the list
296 sortParams: {
Simon Hunt051e9fa2016-01-19 15:54:22 -0800297 firstCol: 'state',
298 firstDir: 'desc',
Simon Hunt877ee982016-03-09 10:53:16 -0800299 secondCol: 'title',
Steven Burrows1c2a9682017-07-14 16:52:46 +0100300 secondDir: 'asc',
Simon Hunt94f36fc2017-07-12 17:47:17 -0700301 },
Steven Burrows1c2a9682017-07-14 16:52:46 +0100302 lion_toggle_auto_refresh: lion('tt_ctl_auto_refresh'),
Bri Prebilic Cole6b95a3f2015-06-04 09:15:00 -0700303 });
304
Bri Prebilic Cole9dcaea52015-07-21 14:39:48 -0700305 ks.keyBindings({
Simon Hunt94f36fc2017-07-12 17:47:17 -0700306 esc: [$scope.selectCallback, lion('qh_hint_esc')],
Steven Burrows1c2a9682017-07-14 16:52:46 +0100307 _helpFormat: ['esc'],
Bri Prebilic Cole9dcaea52015-07-21 14:39:48 -0700308 });
309 ks.gestureNotes([
Simon Hunt94f36fc2017-07-12 17:47:17 -0700310 [lion('click_row'), lion('qh_hint_click_row')],
Steven Burrows1c2a9682017-07-14 16:52:46 +0100311 [lion('scroll_down'), lion('qh_hint_scroll_down')],
Bri Prebilic Cole9dcaea52015-07-21 14:39:48 -0700312 ]);
313
Simon Hunt3f92c432016-01-12 17:34:23 -0800314 function createConfirmationText(action, itemId) {
Simon Hunt8d28a552016-01-11 14:01:02 -0800315 var content = ds.createDiv();
Simon Hunt94f36fc2017-07-12 17:47:17 -0700316 content.append('p').text(lion(action) + ' ' + itemId);
Simon Hunt3f92c432016-01-12 17:34:23 -0800317 if (strongWarning[itemId]) {
Simon Hunt94f36fc2017-07-12 17:47:17 -0700318 content.append('p').html(
Simon Huntcaed0412017-08-12 13:49:17 -0700319 fs.sanitize(warnDeactivate) +
Simon Hunt94f36fc2017-07-12 17:47:17 -0700320 '<br>' +
Simon Huntcaed0412017-08-12 13:49:17 -0700321 fs.sanitize(warnOwnRisk)
Simon Hunt94f36fc2017-07-12 17:47:17 -0700322 ).classed('strong', true);
Simon Hunt3f92c432016-01-12 17:34:23 -0800323 }
Simon Hunt8d28a552016-01-11 14:01:02 -0800324 return content;
325 }
326
327 function confirmAction(action) {
Simon Hunt3f92c432016-01-12 17:34:23 -0800328 var itemId = $scope.selId,
Simon Hunt8d28a552016-01-11 14:01:02 -0800329 spar = $scope.sortParams;
330
331 function dOk() {
Simon Hunt3f92c432016-01-12 17:34:23 -0800332 $log.debug('Initiating', action, 'of', itemId);
Simon Hunt8d28a552016-01-11 14:01:02 -0800333 wss.sendEvent(appMgmtReq, {
334 action: action,
Simon Hunt3f92c432016-01-12 17:34:23 -0800335 name: itemId,
Simon Hunt8d28a552016-01-11 14:01:02 -0800336 sortCol: spar.sortCol,
Steven Burrows1c2a9682017-07-14 16:52:46 +0100337 sortDir: spar.sortDir,
Simon Hunt8d28a552016-01-11 14:01:02 -0800338 });
Simon Hunt94f36fc2017-07-12 17:47:17 -0700339 if (action === 'uninstall') {
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800340 detailsPanel.hide();
341 } else {
Steven Burrows1c2a9682017-07-14 16:52:46 +0100342 wss.sendEvent(detailsReq, { id: itemId });
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800343 }
Simon Hunt8d28a552016-01-11 14:01:02 -0800344 }
345
346 function dCancel() {
Simon Hunt3f92c432016-01-12 17:34:23 -0800347 $log.debug('Canceling', action, 'of', itemId);
Simon Hunt8d28a552016-01-11 14:01:02 -0800348 }
349
350 ds.openDialog(dialogId, dialogOpts)
Simon Hunt94f36fc2017-07-12 17:47:17 -0700351 .setTitle(lion('dlg_confirm_action'))
Simon Hunt3f92c432016-01-12 17:34:23 -0800352 .addContent(createConfirmationText(action, itemId))
Simon Hunt5198f082016-02-04 13:41:17 -0800353 .addOk(dOk)
354 .addCancel(dCancel)
355 .bindKeys();
Simon Hunt8d28a552016-01-11 14:01:02 -0800356 }
357
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700358 $scope.appAction = function (action) {
359 if ($scope.ctrlBtnState.selection) {
Simon Hunt8d28a552016-01-11 14:01:02 -0800360 confirmAction(action);
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700361 }
Bri Prebilic Colebd0bc772015-05-13 13:02:26 -0700362 };
Thomas Vachuska530e52a2015-05-06 19:51:32 -0700363
Thomas Vachuska08b4dec2017-08-31 15:20:17 -0700364 $scope.downloadApp = function () {
365 if ($scope.ctrlBtnState.selection) {
366 window.location = appUrlPrefix + $scope.selId + downloadSuffix;
367 }
368 };
369
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700370 $scope.$on('FileChanged', function () {
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800371 var formData = new FormData(),
372 url;
Simon Huntf51bf462016-06-29 16:22:57 -0700373
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700374 if ($scope.appFile) {
375 formData.append('file', $scope.appFile);
Simon Huntf51bf462016-06-29 16:22:57 -0700376 url = fileUploadUrl + activateImmediately;
377
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800378 $http.post(ufs.rsUrl(url), formData, {
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700379 transformRequest: angular.identity,
380 headers: {
Steven Burrows1c2a9682017-07-14 16:52:46 +0100381 'Content-Type': undefined,
382 },
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700383 })
Simon Huntf51bf462016-06-29 16:22:57 -0700384 .finally(function () {
385 activateImmediately = '';
386 $scope.sortCallback($scope.sortParams);
387 document.getElementById('inputFileForm').reset();
388 $timeout(function () { wss.sendEvent(detailsReq); }, 250);
389 });
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -0700390 }
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -0700391 });
392
Steven Burrows1c2a9682017-07-14 16:52:46 +0100393 $scope.appDropped = function () {
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800394 activateImmediately = activateOption;
395 $scope.$emit('FileChanged');
396 $scope.appFile = null;
397 };
398
Bri Prebilic Cole9dcaea52015-07-21 14:39:48 -0700399 $scope.$on('$destroy', function () {
400 ks.unbindKeys();
Jian Lia54de5a2016-01-20 23:10:39 -0800401 wss.unbindHandlers(handlers);
Simon Hunt0991b342016-06-08 13:18:16 -0700402 ds.closeDialog();
Bri Prebilic Cole9dcaea52015-07-21 14:39:48 -0700403 });
404
Thomas Vachuska619c5382015-04-02 13:41:47 -0700405 $log.log('OvAppCtrl has been created');
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700406 }])
407
408 // triggers the input form to appear when button is clicked
409 .directive('triggerForm', function () {
410 return {
411 restrict: 'A',
412 link: function (scope, elem) {
413 elem.bind('click', function () {
414 document.getElementById('uploadFile')
Bri Prebilic Cole6c82ade2015-08-05 11:12:30 -0700415 .dispatchEvent(new MouseEvent('click'));
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700416 });
Steven Burrows1c2a9682017-07-14 16:52:46 +0100417 },
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700418 };
419 })
420
421 // binds the model file to the scope in scope.appFile
422 // sends upload request to the server
423 .directive('fileModel', ['$parse',
Simon Huntf51bf462016-06-29 16:22:57 -0700424 function ($parse) {
425 return {
426 restrict: 'A',
427 link: function (scope, elem, attrs) {
428 var model = $parse(attrs.fileModel),
429 modelSetter = model.assign;
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700430
Simon Huntf51bf462016-06-29 16:22:57 -0700431 elem.bind('change', function () {
432 scope.$apply(function () {
433 modelSetter(scope, elem[0].files[0]);
434 });
435 scope.$emit('FileChanged');
Bri Prebilic Cole522e7562015-06-22 15:56:25 -0700436 });
Steven Burrows1c2a9682017-07-14 16:52:46 +0100437 },
Simon Huntf51bf462016-06-29 16:22:57 -0700438 };
439 }])
Jian Lia54de5a2016-01-20 23:10:39 -0800440
Steven Burrows1c2a9682017-07-14 16:52:46 +0100441 .directive('filedrop', ['$parse', '$document', function ($parse, $document) {
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800442 return {
Steven Burrows1c2a9682017-07-14 16:52:46 +0100443 restrict: 'A',
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800444 link: function (scope, element, attrs) {
445 var onAppDrop = $parse(attrs.onFileDrop);
446
447 // When an item is dragged over the document
448 var onDragOver = function (e) {
Thomas Vachuskaebf3be02016-04-11 09:52:06 -0700449 d3.select('#frame').classed('dropping', true);
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800450 e.preventDefault();
451 };
452
453 // When the user leaves the window, cancels the drag or drops the item
454 var onDragEnd = function (e) {
Thomas Vachuskaebf3be02016-04-11 09:52:06 -0700455 d3.select('#frame').classed('dropping', false);
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800456 e.preventDefault();
457 };
458
459 // When a file is dropped
460 var loadFile = function (file) {
461 scope.appFile = file;
462 scope.$apply(onAppDrop(scope));
463 };
464
465 // Dragging begins on the document
Steven Burrows1c2a9682017-07-14 16:52:46 +0100466 $document.bind('dragover', onDragOver);
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800467
468 // Dragging ends on the overlay, which takes the whole window
Steven Burrows1c2a9682017-07-14 16:52:46 +0100469 element.bind('dragleave', onDragEnd)
470 .bind('drop', function (e) {
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800471 $log.info('Drag leave', e);
472 loadFile(e.dataTransfer.files[0]);
473 onDragEnd(e);
474 });
Steven Burrows1c2a9682017-07-14 16:52:46 +0100475 },
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800476 };
Steven Burrows96ee21e2017-07-11 19:49:45 +0100477 }])
Thomas Vachuskaa42ce0b2016-03-09 09:02:49 -0800478
Jian Lia54de5a2016-01-20 23:10:39 -0800479 .directive('applicationDetailsPanel',
480 ['$rootScope', '$window', '$timeout', 'KeyService',
481 function ($rootScope, $window, $timeout, ks) {
482 return function (scope) {
483 var unbindWatch;
484
485 function heightCalc() {
486 pStartY = fs.noPxStyle(d3.select('.tabular-header'), 'height')
487 + topPdg;
488 wSize = fs.windowSize(pStartY);
489 pHeight = wSize.height;
490 }
491
492 function initPanel() {
493 heightCalc();
494 createDetailsPane();
495 $log.debug('start to initialize panel!');
496 }
497
498 // Safari has a bug where it renders the fixed-layout table wrong
499 // if you ask for the window's size too early
500 if (scope.onos.browser === 'safari') {
501 $timeout(initPanel);
502 } else {
503 initPanel();
504 }
505 // create key bindings to handle panel
506 ks.keyBindings({
Simon Hunt94f36fc2017-07-12 17:47:17 -0700507 esc: [closePanel, lion('qh_hint_close_detail')],
Steven Burrows1c2a9682017-07-14 16:52:46 +0100508 _helpFormat: ['esc'],
Jian Lia54de5a2016-01-20 23:10:39 -0800509 });
Simon Hunt94f36fc2017-07-12 17:47:17 -0700510
511 // TODO: Review - why are we doing this in the detail panel...?
Jian Lia54de5a2016-01-20 23:10:39 -0800512 ks.gestureNotes([
Simon Hunt94f36fc2017-07-12 17:47:17 -0700513 [lion('click_row'), lion('qh_hint_click_row')],
Steven Burrows1c2a9682017-07-14 16:52:46 +0100514 [lion('scroll_down'), lion('qh_hint_scroll_down')],
Jian Lia54de5a2016-01-20 23:10:39 -0800515 ]);
516
517 // if the panelData changes
518 scope.$watch('panelData', function () {
519 if (!fs.isEmptyObject(scope.panelData)) {
520 populateDetails(scope.panelData);
521 detailsPanel.show();
522 }
523 });
524
525 // if the window size changes
526 unbindWatch = $rootScope.$watchCollection(
527 function () {
528 return {
529 h: $window.innerHeight,
Steven Burrows1c2a9682017-07-14 16:52:46 +0100530 w: $window.innerWidth,
Jian Lia54de5a2016-01-20 23:10:39 -0800531 };
532 }, function () {
533 if (!fs.isEmptyObject(scope.panelData)) {
534 heightCalc();
535 populateDetails(scope.panelData);
536 }
537 }
538 );
539
540 scope.$on('$destroy', function () {
541 unbindWatch();
542 ks.unbindKeys();
543 ps.destroyPanel(pName);
544 });
545 };
546 }]);
Thomas Vachuska0fa583c2015-03-30 23:07:41 -0700547}());