show community results
[releng.git] / utils / test / testapi / 3rd_party / static / testapi-ui / components / results / resultsController.js
1 /*
2  * Licensed under the Apache License, Version 2.0 (the "License");
3  * you may not use this file except in compliance with the License.
4  * You may obtain a copy of the License at
5  *
6  * http://www.apache.org/licenses/LICENSE-2.0
7  *
8  * Unless required by applicable law or agreed to in writing, software
9  * distributed under the License is distributed on an "AS IS" BASIS,
10  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11  * See the License for the specific language governing permissions and
12  * limitations under the License.
13  */
14
15 (function () {
16     'use strict';
17
18     angular
19         .module('testapiApp')
20         .controller('ResultsController', ResultsController);
21
22     ResultsController.$inject = [
23         '$scope', '$http', '$filter', '$state', 'testapiApiUrl','raiseAlert'
24     ];
25
26     /**
27      * TestAPI Results Controller
28      * This controller is for the '/results' page where a user can browse
29      * a listing of community uploaded results.
30      */
31     function ResultsController($scope, $http, $filter, $state, testapiApiUrl,
32         raiseAlert) {
33         var ctrl = this;
34
35         ctrl.update = update;
36         ctrl.open = open;
37         ctrl.clearFilters = clearFilters;
38         ctrl.associateMeta = associateMeta;
39         ctrl.getVersionList = getVersionList;
40         ctrl.getUserProducts = getUserProducts;
41         ctrl.associateProductVersion = associateProductVersion;
42         ctrl.getProductVersions = getProductVersions;
43         ctrl.prepVersionEdit = prepVersionEdit;
44
45         /** Mappings of Interop WG components to marketing program names. */
46         ctrl.targetMappings = {
47             'platform': 'Openstack Powered Platform',
48             'compute': 'OpenStack Powered Compute',
49             'object': 'OpenStack Powered Object Storage'
50         };
51
52         /** Initial page to be on. */
53         ctrl.currentPage = 1;
54
55         /**
56          * How many results should display on each page. Since pagination
57          * is server-side implemented, this value should match the
58          * 'results_per_page' configuration of the TestAPI server which
59          * defaults to 20.
60          */
61         ctrl.itemsPerPage = 20;
62
63         /**
64          * How many page buttons should be displayed at max before adding
65          * the '...' button.
66          */
67         ctrl.maxSize = 5;
68
69         /** The upload date lower limit to be used in filtering results. */
70         ctrl.startDate = '';
71
72         /** The upload date upper limit to be used in filtering results. */
73         ctrl.endDate = '';
74
75         /** The date format for the date picker. */
76         ctrl.format = 'yyyy-MM-dd';
77
78         /** Check to see if this page should display user-specific results. */
79         ctrl.isUserResults = $state.current.name === 'userResults';
80
81         // Should only be on user-results-page if authenticated.
82         if (ctrl.isUserResults && !$scope.auth.isAuthenticated) {
83             $state.go('home');
84         }
85
86         ctrl.pageHeader = ctrl.isUserResults ?
87             'Private test results' : 'Community test results';
88
89         ctrl.pageParagraph = ctrl.isUserResults ?
90             'Your most recently uploaded test results are listed here.' :
91             'The most recently uploaded community test results are listed ' +
92             'here.';
93
94         if (ctrl.isUserResults) {
95             ctrl.authRequest = $scope.auth.doSignCheck()
96                 .then(ctrl.update);
97             ctrl.getUserProducts();
98         } else {
99             ctrl.update();
100         }
101
102         /**
103          * This will contact the TestAPI API to get a listing of test run
104          * results.
105          */
106         function update() {
107             ctrl.showError = false;
108             // Construct the API URL based on user-specified filters.
109             var content_url = testapiApiUrl + '/results' +
110                 '?page=' + ctrl.currentPage;
111             var start = $filter('date')(ctrl.startDate, 'yyyy-MM-dd');
112             if (start) {
113                 content_url =
114                     content_url + '&start_date=' + start + ' 00:00:00';
115             }
116             var end = $filter('date')(ctrl.endDate, 'yyyy-MM-dd');
117             if (end) {
118                 content_url = content_url + '&end_date=' + end + ' 23:59:59';
119             }
120             if (ctrl.isUserResults) {
121                 content_url = content_url + '&signed';
122             }
123             ctrl.resultsRequest =
124                 $http.get(content_url).success(function (data) {
125                     ctrl.data = data;
126                     ctrl.totalItems = 20 // ctrl.data.pagination.total_pages * ctrl.itemsPerPage;
127                     ctrl.currentPage = 1 // ctrl.data.pagination.current_page;
128                 }).error(function (error) {
129                     ctrl.data = null;
130                     ctrl.totalItems = 0;
131                     ctrl.showError = true;
132                     ctrl.error =
133                         'Error retrieving results listing from server: ' +
134                         angular.toJson(error);
135                 });
136         }
137
138         /**
139          * This is called when the date filter calendar is opened. It
140          * does some event handling, and sets a scope variable so the UI
141          * knows which calendar was opened.
142          * @param {Object} $event - The Event object
143          * @param {String} openVar - Tells which calendar was opened
144          */
145         function open($event, openVar) {
146             $event.preventDefault();
147             $event.stopPropagation();
148             ctrl[openVar] = true;
149         }
150
151         /**
152          * This function will clear all filters and update the results
153          * listing.
154          */
155         function clearFilters() {
156             ctrl.startDate = null;
157             ctrl.endDate = null;
158             ctrl.update();
159         }
160
161         /**
162          * This will send an API request in order to associate a metadata
163          * key-value pair with the given testId
164          * @param {Number} index - index of the test object in the results list
165          * @param {String} key - metadata key
166          * @param {String} value - metadata value
167          */
168         function associateMeta(index, key, value) {
169             var testId = ctrl.data.results[index].id;
170             var metaUrl = [
171                 testapiApiUrl, '/results/', testId, '/meta/', key
172             ].join('');
173
174             var editFlag = key + 'Edit';
175             if (value) {
176                 ctrl.associateRequest = $http.post(metaUrl, value)
177                     .success(function () {
178                         ctrl.data.results[index][editFlag] = false;
179                     }).error(function (error) {
180                         raiseAlert('danger', error.title, error.detail);
181                     });
182             }
183             else {
184                 ctrl.unassociateRequest = $http.delete(metaUrl)
185                     .success(function () {
186                         ctrl.data.results[index][editFlag] = false;
187                     }).error(function (error) {
188                         if (error.code == 404) {
189                             // Key doesn't exist, so count it as a success,
190                             // and don't raise an alert.
191                             ctrl.data.results[index][editFlag] = false;
192                         }
193                         else {
194                             raiseAlert('danger', error.title, error.detail);
195                         }
196                     });
197             }
198         }
199
200         /**
201          * Retrieve an array of available capability files from the TestAPI
202          * API server, sort this array reverse-alphabetically, and store it in
203          * a scoped variable.
204          * Sample API return array: ["2015.03.json", "2015.04.json"]
205          */
206         function getVersionList() {
207             if (ctrl.versionList) {
208                 return;
209             }
210             var content_url = testapiApiUrl + '/guidelines';
211             ctrl.versionsRequest =
212                 $http.get(content_url).success(function (data) {
213                     ctrl.versionList = data.sort().reverse();
214                 }).error(function (error) {
215                     raiseAlert('danger', error.title,
216                                'Unable to retrieve version list');
217                 });
218         }
219
220         /**
221          * Get products user has management rights to or all products depending
222          * on the passed in parameter value.
223          */
224         function getUserProducts() {
225             if (ctrl.products) {
226                 return;
227             }
228             var contentUrl = testapiApiUrl + '/products';
229             ctrl.productsRequest =
230                 $http.get(contentUrl).success(function (data) {
231                     ctrl.products = {};
232                     angular.forEach(data.products, function(prod) {
233                         if (prod.can_manage) {
234                             ctrl.products[prod.id] = prod;
235                         }
236                     });
237                 }).error(function (error) {
238                     ctrl.products = null;
239                     ctrl.showError = true;
240                     ctrl.error =
241                         'Error retrieving Products listing from server: ' +
242                         angular.toJson(error);
243                 });
244         }
245
246         /**
247          * Send a PUT request to the API server to associate a product with
248          * a test result.
249          */
250         function associateProductVersion(result) {
251             var verId = (result.selectedVersion ?
252                          result.selectedVersion.id : null);
253             var testId = result.id;
254             var url = testapiApiUrl + '/results/' + testId;
255             ctrl.associateRequest = $http.put(url, {'product_version_id':
256                                                     verId})
257                 .success(function (data) {
258                     result.product_version = result.selectedVersion;
259                     if (result.selectedVersion) {
260                         result.product_version.product_info =
261                             result.selectedProduct;
262                     }
263                     result.productEdit = false;
264                 }).error(function (error) {
265                     raiseAlert('danger', error.title, error.detail);
266                 });
267         }
268
269         /**
270          * Get all versions for a product.
271          */
272         function getProductVersions(result) {
273             if (!result.selectedProduct) {
274                 result.productVersions = [];
275                 result.selectedVersion = null;
276                 return;
277             }
278
279             var url = testapiApiUrl + '/products/' +
280                 result.selectedProduct.id + '/versions';
281             ctrl.getVersionsRequest = $http.get(url)
282                 .success(function (data) {
283                     result.productVersions = data;
284
285                     // If the test result isn't already associated to a
286                     // version, default it to the null version.
287                     if (!result.product_version) {
288                         angular.forEach(data, function(ver) {
289                             if (!ver.version) {
290                                 result.selectedVersion = ver;
291                             }
292                         });
293                     }
294                 }).error(function (error) {
295                     raiseAlert('danger', error.title, error.detail);
296                 });
297         }
298
299         /**
300          * Instantiate variables needed for editing product/version
301          * associations.
302          */
303         function prepVersionEdit(result) {
304             result.productEdit = true;
305             if (result.product_version) {
306                 result.selectedProduct =
307                     ctrl.products[result.product_version.product_info.id];
308             }
309             result.selectedVersion = result.product_version;
310             ctrl.getProductVersions(result);
311         }
312
313     }
314 })();