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