Bri Prebilic Cole

ONOS-2074 - GUI -- Refactor Application view to use directives. WIP.

Change-Id: If886b5af1313ef350e041dc9f9a21ba150edcd79
......@@ -18,7 +18,6 @@ package org.onosproject.ui.impl;
import com.sun.jersey.multipart.FormDataParam;
import org.onlab.rest.BaseResource;
import org.onosproject.app.ApplicationAdminService;
import org.onosproject.core.Application;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
......@@ -38,8 +37,8 @@ public class ApplicationResource extends BaseResource {
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response upload(@FormDataParam("file") InputStream stream) throws IOException {
Application app = get(ApplicationAdminService.class).install(stream);
return Response.ok(app.toString()).build();
get(ApplicationAdminService.class).install(stream);
return Response.ok().build();
}
}
......
......@@ -24,9 +24,9 @@
angular.module('onosRemote')
.factory('RestService',
['$log', '$http', 'UrlFnService',
['$log', '$http', 'FnService', 'UrlFnService',
function (_$log_, $http, ufs) {
function (_$log_, $http, fs, ufs) {
$log = _$log_;
function get(url, callback, errorCb) {
......@@ -37,7 +37,7 @@
callback(response.data);
}, function (response) {
// error
var emsg = 'Failed to retrieve JSON data: ' + fullUrl;
var emsg = 'Failed to retrieve JSON data: ' + fullUrl;
$log.warn(emsg, response.status, response.data);
if (errorCb) {
errorCb(emsg);
......@@ -45,8 +45,28 @@
});
}
// TODO: test this
function post(url, data, callbacks) {
var fullUrl = ufs.rsUrl(url);
$http.post(fullUrl, data).then(function (response) {
// success
if (callbacks && fs.isF(callbacks.success)) {
callbacks.success(response.data);
}
}, function (response) {
// error
var msg = 'Problem with $http post request: ' + fullUrl;
$log.warn(msg, response.status, response.data);
if (callbacks && fs.isF(callbacks.error)) {
callbacks.error(msg);
}
});
}
return {
get: get
get: get,
post: post
};
}]);
}());
......
......@@ -44,6 +44,7 @@
req = o.tag + 'DataRequest',
resp = o.tag + 'DataResponse',
onSel = fs.isF(o.selCb),
onResp = fs.isF(o.respCb),
promise;
o.scope.tableData = [];
......@@ -52,6 +53,7 @@
function respCb(data) {
o.scope.tableData = data[root];
onResp && onResp();
o.scope.$apply();
}
......
......@@ -31,3 +31,8 @@
width: 24px;
border: none;
}
#ov-app form#inputFileForm,
#ov-app input#uploadFile {
display: none;
}
......
......@@ -7,31 +7,28 @@
icon icon-size="36" icon-id="refresh"
ng-click="toggleRefresh()"></div>
<div class="separator"></div>
<div id="app-install"
icon icon-size="36" icon-id="plus"
class="active">
<form id="inputFileForm">
<input id="uploadFile"
type="file" size="50" accept=".oar"
file-model="appFile">
</form>
<div icon icon-size="36" icon-id="plus"
class="active" trigger-form>
</div>
<div id="app-activate"
icon icon-size="36" icon-id="play"
<div icon icon-size="36" icon-id="play"
ng-click="appAction('activate')"
ng-class="{active: ctrlBtnState.installed}">
</div>
<div id="app-deactivate"
icon icon-size="36" icon-id="stop"
<div icon icon-size="36" icon-id="stop"
ng-click="appAction('deactivate')"
ng-class="{active: ctrlBtnState.active}">
</div>
<div id="app-uninstall"
icon icon-size="36" icon-id="garbage"
<div icon icon-size="36" icon-id="garbage"
ng-click="appAction('uninstall')"
ng-class="{active: ctrlBtnState.selection}">
</div>
</div>
<form id="app-form" method="POST" action="rs/applications/upload"
target="app-form-response" enctype="multipart/form-data" style="display:none">
<input type="file" name="file" id="file" size="50" accept=".oar">
<button type="submit" id="app-upload">Upload</button>
</form>
<iframe id="app-form-response" name="app-form-response"
src="" width="0" height="0" style="visibility:hidden;display:none"></iframe>
</div>
<div class="summary-list" onos-fixed-header>
......
......@@ -21,74 +21,115 @@
(function () {
'use strict';
var selectionObj;
// constants
var INSTALLED = 'INSTALLED',
ACTIVE = 'ACTIVE',
APP_MGMENT_REQ = 'appManagementRequest',
FILE_UPLOAD_URL = 'applications/upload';
angular.module('ovApp', [])
.controller('OvAppCtrl',
['$log', '$scope', 'FnService', 'TableBuilderService', 'WebSocketService',
['$log', '$scope', '$http',
'FnService', 'TableBuilderService', 'WebSocketService', 'UrlFnService',
function ($log, $scope, fs, tbs, wss) {
function ($log, $scope, $http, fs, tbs, wss, ufs) {
var refreshCtrls;
$scope.ctrlBtnState = {};
// TODO: clean up view
// all DOM manipulation (adding styles, getting elements and doing stuff
// with them) should be done in directives
function selCb($event, row) {
// selId comes from tableBuilder
$scope.ctrlBtnState.selection = !!$scope.selId;
selectionObj = row;
$log.debug('Got a click on:', row);
if ($scope.ctrlBtnState.selection) {
$scope.ctrlBtnState.installed = row.state === 'INSTALLED';
$scope.ctrlBtnState.active = row.state === 'ACTIVE';
} else {
$scope.ctrlBtnState.installed = false;
$scope.ctrlBtnState.active = false;
}
refreshCtrls = function () {
if ($scope.ctrlBtnState.selection) {
$scope.ctrlBtnState.installed = row.state === INSTALLED;
$scope.ctrlBtnState.active = row.state === ACTIVE;
} else {
$scope.ctrlBtnState.installed = false;
$scope.ctrlBtnState.active = false;
}
};
refreshCtrls();
}
function respCb() {
refreshCtrls && refreshCtrls();
}
tbs.buildTable({
scope: $scope,
tag: 'app',
selCb: selCb
selCb: selCb,
respCb: respCb
});
// TODO: use d3 click events -- move to directive
d3.select('#app-install').on('click', function () {
$log.debug('Initiating install');
var evt = document.createEvent("HTMLEvents");
evt.initEvent("click", true, true);
document.getElementById('file').dispatchEvent(evt);
});
// TODO: use d3 to select elements -- move to directive
document.getElementById('app-form-response').onload = function () {
document.getElementById('app-form').reset();
$scope.$apply();
//$scope.sortCallback($scope.sortParams);
};
function appAction(action) {
$scope.appAction = function (action) {
if ($scope.ctrlBtnState.selection) {
$log.debug('Initiating ' + action + ' of', selectionObj);
wss.sendEvent('appManagementRequest', {action: action, name: selectionObj.id});
$log.debug('Initiating ' + action + ' of ' + $scope.selId);
wss.sendEvent(APP_MGMENT_REQ, {
action: action,
name: $scope.selId
});
}
}
};
// TODO: use d3 to select elements -- move to directive
d3.select('#file').on('change', function () {
var file = document.getElementById('file').value.replace('C:\\fakepath\\', '');
$log.info('Handling file', file);
var evt = document.createEvent("HTMLEvents");
evt.initEvent("click", true, true);
document.getElementById('app-upload').dispatchEvent(evt);
$scope.$on('FileChanged', function () {
var formData = new FormData();
if ($scope.appFile) {
formData.append('file', $scope.appFile);
$http.post(ufs.rsUrl(FILE_UPLOAD_URL), formData, {
transformRequest: angular.identity,
headers: {
'Content-Type': undefined
}
})
// TODO: look for finally function to combine lines
// TODO: reexamine reset input value
.success(function () {
$scope.sortCallback($scope.sortParams);
document.getElementById('inputFileForm').reset();
})
.error(function () {
$scope.sortCallback($scope.sortParams);
});
}
});
// TODO: move to directive
d3.select('#app-uninstall').on('click', function () { appAction('uninstall'); });
d3.select('#app-activate').on('click', function () { appAction('activate'); });
d3.select('#app-deactivate').on('click', function () { appAction('deactivate'); });
$log.log('OvAppCtrl has been created');
}])
// triggers the input form to appear when button is clicked
.directive('triggerForm', function () {
return {
restrict: 'A',
link: function (scope, elem) {
elem.bind('click', function () {
document.getElementById('uploadFile')
.dispatchEvent(new Event('click'));
});
}
};
})
// binds the model file to the scope in scope.appFile
// sends upload request to the server
.directive('fileModel', ['$parse',
function ($parse) {
return {
restrict: 'A',
link: function (scope, elem, attrs) {
var model = $parse(attrs.fileModel),
modelSetter = model.assign;
elem.bind('change', function () {
scope.$apply(function () {
modelSetter(scope, elem[0].files[0]);
});
scope.$emit('FileChanged');
});
}
};
}]);
}());
......
......@@ -18,8 +18,8 @@
<div id="ov-port">
<div class="tabular-header">
<h2>
Ports for Device {{devId || "(No device selected)"}}
({{tableData.length}} total)
Port Statistics for Device {{devId || "(No device selected)"}}
({{tableData.length}} Ports total)
</h2>
<div class="ctrl-btns">
<div class="refresh" ng-class="{active: autoRefresh}"
......