ONOS-2074 - GUI -- Refactor Application view to use directives. WIP.
Change-Id: If886b5af1313ef350e041dc9f9a21ba150edcd79
Showing
7 changed files
with
127 additions
and
63 deletions
... | @@ -18,7 +18,6 @@ package org.onosproject.ui.impl; | ... | @@ -18,7 +18,6 @@ package org.onosproject.ui.impl; |
18 | import com.sun.jersey.multipart.FormDataParam; | 18 | import com.sun.jersey.multipart.FormDataParam; |
19 | import org.onlab.rest.BaseResource; | 19 | import org.onlab.rest.BaseResource; |
20 | import org.onosproject.app.ApplicationAdminService; | 20 | import org.onosproject.app.ApplicationAdminService; |
21 | -import org.onosproject.core.Application; | ||
22 | 21 | ||
23 | import javax.ws.rs.Consumes; | 22 | import javax.ws.rs.Consumes; |
24 | import javax.ws.rs.POST; | 23 | import javax.ws.rs.POST; |
... | @@ -38,8 +37,8 @@ public class ApplicationResource extends BaseResource { | ... | @@ -38,8 +37,8 @@ public class ApplicationResource extends BaseResource { |
38 | @POST | 37 | @POST |
39 | @Consumes(MediaType.MULTIPART_FORM_DATA) | 38 | @Consumes(MediaType.MULTIPART_FORM_DATA) |
40 | public Response upload(@FormDataParam("file") InputStream stream) throws IOException { | 39 | public Response upload(@FormDataParam("file") InputStream stream) throws IOException { |
41 | - Application app = get(ApplicationAdminService.class).install(stream); | 40 | + get(ApplicationAdminService.class).install(stream); |
42 | - return Response.ok(app.toString()).build(); | 41 | + return Response.ok().build(); |
43 | } | 42 | } |
44 | 43 | ||
45 | } | 44 | } | ... | ... |
... | @@ -24,9 +24,9 @@ | ... | @@ -24,9 +24,9 @@ |
24 | 24 | ||
25 | angular.module('onosRemote') | 25 | angular.module('onosRemote') |
26 | .factory('RestService', | 26 | .factory('RestService', |
27 | - ['$log', '$http', 'UrlFnService', | 27 | + ['$log', '$http', 'FnService', 'UrlFnService', |
28 | 28 | ||
29 | - function (_$log_, $http, ufs) { | 29 | + function (_$log_, $http, fs, ufs) { |
30 | $log = _$log_; | 30 | $log = _$log_; |
31 | 31 | ||
32 | function get(url, callback, errorCb) { | 32 | function get(url, callback, errorCb) { |
... | @@ -45,8 +45,28 @@ | ... | @@ -45,8 +45,28 @@ |
45 | }); | 45 | }); |
46 | } | 46 | } |
47 | 47 | ||
48 | + // TODO: test this | ||
49 | + function post(url, data, callbacks) { | ||
50 | + var fullUrl = ufs.rsUrl(url); | ||
51 | + $http.post(fullUrl, data).then(function (response) { | ||
52 | + // success | ||
53 | + if (callbacks && fs.isF(callbacks.success)) { | ||
54 | + callbacks.success(response.data); | ||
55 | + } | ||
56 | + }, function (response) { | ||
57 | + // error | ||
58 | + var msg = 'Problem with $http post request: ' + fullUrl; | ||
59 | + $log.warn(msg, response.status, response.data); | ||
60 | + | ||
61 | + if (callbacks && fs.isF(callbacks.error)) { | ||
62 | + callbacks.error(msg); | ||
63 | + } | ||
64 | + }); | ||
65 | + } | ||
66 | + | ||
48 | return { | 67 | return { |
49 | - get: get | 68 | + get: get, |
69 | + post: post | ||
50 | }; | 70 | }; |
51 | }]); | 71 | }]); |
52 | }()); | 72 | }()); | ... | ... |
... | @@ -44,6 +44,7 @@ | ... | @@ -44,6 +44,7 @@ |
44 | req = o.tag + 'DataRequest', | 44 | req = o.tag + 'DataRequest', |
45 | resp = o.tag + 'DataResponse', | 45 | resp = o.tag + 'DataResponse', |
46 | onSel = fs.isF(o.selCb), | 46 | onSel = fs.isF(o.selCb), |
47 | + onResp = fs.isF(o.respCb), | ||
47 | promise; | 48 | promise; |
48 | 49 | ||
49 | o.scope.tableData = []; | 50 | o.scope.tableData = []; |
... | @@ -52,6 +53,7 @@ | ... | @@ -52,6 +53,7 @@ |
52 | 53 | ||
53 | function respCb(data) { | 54 | function respCb(data) { |
54 | o.scope.tableData = data[root]; | 55 | o.scope.tableData = data[root]; |
56 | + onResp && onResp(); | ||
55 | o.scope.$apply(); | 57 | o.scope.$apply(); |
56 | } | 58 | } |
57 | 59 | ... | ... |
... | @@ -7,31 +7,28 @@ | ... | @@ -7,31 +7,28 @@ |
7 | icon icon-size="36" icon-id="refresh" | 7 | icon icon-size="36" icon-id="refresh" |
8 | ng-click="toggleRefresh()"></div> | 8 | ng-click="toggleRefresh()"></div> |
9 | <div class="separator"></div> | 9 | <div class="separator"></div> |
10 | - <div id="app-install" | 10 | + |
11 | - icon icon-size="36" icon-id="plus" | 11 | + <form id="inputFileForm"> |
12 | - class="active"> | 12 | + <input id="uploadFile" |
13 | + type="file" size="50" accept=".oar" | ||
14 | + file-model="appFile"> | ||
15 | + </form> | ||
16 | + <div icon icon-size="36" icon-id="plus" | ||
17 | + class="active" trigger-form> | ||
13 | </div> | 18 | </div> |
14 | - <div id="app-activate" | 19 | + <div icon icon-size="36" icon-id="play" |
15 | - icon icon-size="36" icon-id="play" | 20 | + ng-click="appAction('activate')" |
16 | ng-class="{active: ctrlBtnState.installed}"> | 21 | ng-class="{active: ctrlBtnState.installed}"> |
17 | </div> | 22 | </div> |
18 | - <div id="app-deactivate" | 23 | + <div icon icon-size="36" icon-id="stop" |
19 | - icon icon-size="36" icon-id="stop" | 24 | + ng-click="appAction('deactivate')" |
20 | ng-class="{active: ctrlBtnState.active}"> | 25 | ng-class="{active: ctrlBtnState.active}"> |
21 | </div> | 26 | </div> |
22 | - <div id="app-uninstall" | 27 | + <div icon icon-size="36" icon-id="garbage" |
23 | - icon icon-size="36" icon-id="garbage" | 28 | + ng-click="appAction('uninstall')" |
24 | ng-class="{active: ctrlBtnState.selection}"> | 29 | ng-class="{active: ctrlBtnState.selection}"> |
25 | </div> | 30 | </div> |
26 | </div> | 31 | </div> |
27 | - | ||
28 | - <form id="app-form" method="POST" action="rs/applications/upload" | ||
29 | - target="app-form-response" enctype="multipart/form-data" style="display:none"> | ||
30 | - <input type="file" name="file" id="file" size="50" accept=".oar"> | ||
31 | - <button type="submit" id="app-upload">Upload</button> | ||
32 | - </form> | ||
33 | - <iframe id="app-form-response" name="app-form-response" | ||
34 | - src="" width="0" height="0" style="visibility:hidden;display:none"></iframe> | ||
35 | </div> | 32 | </div> |
36 | 33 | ||
37 | <div class="summary-list" onos-fixed-header> | 34 | <div class="summary-list" onos-fixed-header> | ... | ... |
... | @@ -21,74 +21,115 @@ | ... | @@ -21,74 +21,115 @@ |
21 | (function () { | 21 | (function () { |
22 | 'use strict'; | 22 | 'use strict'; |
23 | 23 | ||
24 | - var selectionObj; | 24 | + // constants |
25 | + var INSTALLED = 'INSTALLED', | ||
26 | + ACTIVE = 'ACTIVE', | ||
27 | + APP_MGMENT_REQ = 'appManagementRequest', | ||
28 | + FILE_UPLOAD_URL = 'applications/upload'; | ||
25 | 29 | ||
26 | angular.module('ovApp', []) | 30 | angular.module('ovApp', []) |
27 | .controller('OvAppCtrl', | 31 | .controller('OvAppCtrl', |
28 | - ['$log', '$scope', 'FnService', 'TableBuilderService', 'WebSocketService', | 32 | + ['$log', '$scope', '$http', |
33 | + 'FnService', 'TableBuilderService', 'WebSocketService', 'UrlFnService', | ||
29 | 34 | ||
30 | - function ($log, $scope, fs, tbs, wss) { | 35 | + function ($log, $scope, $http, fs, tbs, wss, ufs) { |
36 | + var refreshCtrls; | ||
31 | $scope.ctrlBtnState = {}; | 37 | $scope.ctrlBtnState = {}; |
32 | - // TODO: clean up view | ||
33 | - // all DOM manipulation (adding styles, getting elements and doing stuff | ||
34 | - // with them) should be done in directives | ||
35 | 38 | ||
36 | function selCb($event, row) { | 39 | function selCb($event, row) { |
40 | + // selId comes from tableBuilder | ||
37 | $scope.ctrlBtnState.selection = !!$scope.selId; | 41 | $scope.ctrlBtnState.selection = !!$scope.selId; |
38 | - selectionObj = row; | ||
39 | $log.debug('Got a click on:', row); | 42 | $log.debug('Got a click on:', row); |
40 | 43 | ||
44 | + refreshCtrls = function () { | ||
41 | if ($scope.ctrlBtnState.selection) { | 45 | if ($scope.ctrlBtnState.selection) { |
42 | - $scope.ctrlBtnState.installed = row.state === 'INSTALLED'; | 46 | + $scope.ctrlBtnState.installed = row.state === INSTALLED; |
43 | - $scope.ctrlBtnState.active = row.state === 'ACTIVE'; | 47 | + $scope.ctrlBtnState.active = row.state === ACTIVE; |
44 | } else { | 48 | } else { |
45 | $scope.ctrlBtnState.installed = false; | 49 | $scope.ctrlBtnState.installed = false; |
46 | $scope.ctrlBtnState.active = false; | 50 | $scope.ctrlBtnState.active = false; |
47 | } | 51 | } |
52 | + }; | ||
53 | + | ||
54 | + refreshCtrls(); | ||
55 | + } | ||
56 | + | ||
57 | + function respCb() { | ||
58 | + refreshCtrls && refreshCtrls(); | ||
48 | } | 59 | } |
49 | 60 | ||
50 | tbs.buildTable({ | 61 | tbs.buildTable({ |
51 | scope: $scope, | 62 | scope: $scope, |
52 | tag: 'app', | 63 | tag: 'app', |
53 | - selCb: selCb | 64 | + selCb: selCb, |
65 | + respCb: respCb | ||
54 | }); | 66 | }); |
55 | 67 | ||
56 | - // TODO: use d3 click events -- move to directive | 68 | + $scope.appAction = function (action) { |
57 | - d3.select('#app-install').on('click', function () { | 69 | + if ($scope.ctrlBtnState.selection) { |
58 | - $log.debug('Initiating install'); | 70 | + $log.debug('Initiating ' + action + ' of ' + $scope.selId); |
59 | - var evt = document.createEvent("HTMLEvents"); | 71 | + wss.sendEvent(APP_MGMENT_REQ, { |
60 | - evt.initEvent("click", true, true); | 72 | + action: action, |
61 | - document.getElementById('file').dispatchEvent(evt); | 73 | + name: $scope.selId |
62 | }); | 74 | }); |
63 | - | 75 | + } |
64 | - // TODO: use d3 to select elements -- move to directive | ||
65 | - document.getElementById('app-form-response').onload = function () { | ||
66 | - document.getElementById('app-form').reset(); | ||
67 | - $scope.$apply(); | ||
68 | - //$scope.sortCallback($scope.sortParams); | ||
69 | }; | 76 | }; |
70 | 77 | ||
71 | - function appAction(action) { | 78 | + $scope.$on('FileChanged', function () { |
72 | - if ($scope.ctrlBtnState.selection) { | 79 | + var formData = new FormData(); |
73 | - $log.debug('Initiating ' + action + ' of', selectionObj); | 80 | + if ($scope.appFile) { |
74 | - wss.sendEvent('appManagementRequest', {action: action, name: selectionObj.id}); | 81 | + formData.append('file', $scope.appFile); |
82 | + $http.post(ufs.rsUrl(FILE_UPLOAD_URL), formData, { | ||
83 | + transformRequest: angular.identity, | ||
84 | + headers: { | ||
85 | + 'Content-Type': undefined | ||
75 | } | 86 | } |
87 | + }) | ||
88 | + // TODO: look for finally function to combine lines | ||
89 | + // TODO: reexamine reset input value | ||
90 | + .success(function () { | ||
91 | + $scope.sortCallback($scope.sortParams); | ||
92 | + document.getElementById('inputFileForm').reset(); | ||
93 | + }) | ||
94 | + .error(function () { | ||
95 | + $scope.sortCallback($scope.sortParams); | ||
96 | + }); | ||
76 | } | 97 | } |
98 | + }); | ||
77 | 99 | ||
78 | - // TODO: use d3 to select elements -- move to directive | 100 | + $log.log('OvAppCtrl has been created'); |
79 | - d3.select('#file').on('change', function () { | 101 | + }]) |
80 | - var file = document.getElementById('file').value.replace('C:\\fakepath\\', ''); | 102 | + |
81 | - $log.info('Handling file', file); | 103 | + // triggers the input form to appear when button is clicked |
82 | - var evt = document.createEvent("HTMLEvents"); | 104 | + .directive('triggerForm', function () { |
83 | - evt.initEvent("click", true, true); | 105 | + return { |
84 | - document.getElementById('app-upload').dispatchEvent(evt); | 106 | + restrict: 'A', |
107 | + link: function (scope, elem) { | ||
108 | + elem.bind('click', function () { | ||
109 | + document.getElementById('uploadFile') | ||
110 | + .dispatchEvent(new Event('click')); | ||
85 | }); | 111 | }); |
112 | + } | ||
113 | + }; | ||
114 | + }) | ||
86 | 115 | ||
87 | - // TODO: move to directive | 116 | + // binds the model file to the scope in scope.appFile |
88 | - d3.select('#app-uninstall').on('click', function () { appAction('uninstall'); }); | 117 | + // sends upload request to the server |
89 | - d3.select('#app-activate').on('click', function () { appAction('activate'); }); | 118 | + .directive('fileModel', ['$parse', |
90 | - d3.select('#app-deactivate').on('click', function () { appAction('deactivate'); }); | 119 | + function ($parse) { |
120 | + return { | ||
121 | + restrict: 'A', | ||
122 | + link: function (scope, elem, attrs) { | ||
123 | + var model = $parse(attrs.fileModel), | ||
124 | + modelSetter = model.assign; | ||
91 | 125 | ||
92 | - $log.log('OvAppCtrl has been created'); | 126 | + elem.bind('change', function () { |
127 | + scope.$apply(function () { | ||
128 | + modelSetter(scope, elem[0].files[0]); | ||
129 | + }); | ||
130 | + scope.$emit('FileChanged'); | ||
131 | + }); | ||
132 | + } | ||
133 | + }; | ||
93 | }]); | 134 | }]); |
94 | }()); | 135 | }()); | ... | ... |
... | @@ -18,8 +18,8 @@ | ... | @@ -18,8 +18,8 @@ |
18 | <div id="ov-port"> | 18 | <div id="ov-port"> |
19 | <div class="tabular-header"> | 19 | <div class="tabular-header"> |
20 | <h2> | 20 | <h2> |
21 | - Ports for Device {{devId || "(No device selected)"}} | 21 | + Port Statistics for Device {{devId || "(No device selected)"}} |
22 | - ({{tableData.length}} total) | 22 | + ({{tableData.length}} Ports total) |
23 | </h2> | 23 | </h2> |
24 | <div class="ctrl-btns"> | 24 | <div class="ctrl-btns"> |
25 | <div class="refresh" ng-class="{active: autoRefresh}" | 25 | <div class="refresh" ng-class="{active: autoRefresh}" | ... | ... |
-
Please register or login to post a comment