From ade52043a6e8cf01594941435344d8939cdc9bfc Mon Sep 17 00:00:00 2001 From: Paul Van Eck Date: Sun, 9 Oct 2016 20:28:38 -0700 Subject: [PATCH] Add ability in UI to associate test to product/version On the private results page, a user can now optionally associate a test result to a specific product and version that they have created or have access to. Change-Id: I85112d999cd832d7ce1b8c14057a8301b5e5ed7d --- .../app/components/results/results.html | 56 ++++++++++- .../components/results/resultsController.js | 98 +++++++++++++++++++ refstack-ui/app/shared/filters.js | 4 +- refstack-ui/tests/unit/ControllerSpec.js | 47 +++++++++ 4 files changed, 203 insertions(+), 2 deletions(-) diff --git a/refstack-ui/app/components/results/results.html b/refstack-ui/app/components/results/results.html index d75048a3..2552fba3 100644 --- a/refstack-ui/app/components/results/results.html +++ b/refstack-ui/app/components/results/results.html @@ -134,7 +134,7 @@ @@ -143,6 +143,60 @@ title="Save" class="glyphicon glyphicon-floppy-disk"> +
+ + Associated Product: + + None + + + + + {{ctrl.products[result.product_version.product_info.id].name}} + + ({{result.product_version.version}}) + + + + + + {{ctrl.products[result.product_version.product_info.id].name}} + + ({{result.product_version.version}}) + + + + + + + + + + Version: + + + + + + + +
diff --git a/refstack-ui/app/components/results/resultsController.js b/refstack-ui/app/components/results/resultsController.js index c3f14829..044b4232 100644 --- a/refstack-ui/app/components/results/resultsController.js +++ b/refstack-ui/app/components/results/resultsController.js @@ -37,6 +37,10 @@ ctrl.clearFilters = clearFilters; ctrl.associateMeta = associateMeta; ctrl.getVersionList = getVersionList; + ctrl.getUserProducts = getUserProducts; + ctrl.associateProductVersion = associateProductVersion; + ctrl.getProductVersions = getProductVersions; + ctrl.prepVersionEdit = prepVersionEdit; /** Mappings of DefCore components to marketing program names. */ ctrl.targetMappings = { @@ -90,6 +94,7 @@ if (ctrl.isUserResults) { ctrl.authRequest = $scope.auth.doSignCheck() .then(ctrl.update); + ctrl.getUserProducts(); } else { ctrl.update(); } @@ -206,5 +211,98 @@ }); } + /** + * Get products user has management rights to or all products depending + * on the passed in parameter value. + */ + function getUserProducts() { + if (ctrl.products) { + return; + } + var contentUrl = refstackApiUrl + '/products'; + ctrl.productsRequest = + $http.get(contentUrl).success(function (data) { + ctrl.products = {}; + angular.forEach(data.products, function(prod) { + if (prod.can_manage) { + ctrl.products[prod.id] = prod; + } + }); + }).error(function (error) { + ctrl.products = null; + ctrl.showError = true; + ctrl.error = + 'Error retrieving Products listing from server: ' + + angular.toJson(error); + }); + } + + /** + * Send a PUT request to the API server to associate a product with + * a test result. + */ + function associateProductVersion(result) { + var verId = (result.selectedVersion ? + result.selectedVersion.id : null); + var testId = result.id; + var url = refstackApiUrl + '/results/' + testId; + ctrl.associateRequest = $http.put(url, {'product_version_id': + verId}) + .success(function (data) { + result.product_version = result.selectedVersion; + if (result.selectedVersion) { + result.product_version.product_info = + result.selectedProduct; + } + result.productEdit = false; + }).error(function (error) { + raiseAlert('danger', error.title, error.detail); + }); + } + + /** + * Get all versions for a product. + */ + function getProductVersions(result) { + if (!result.selectedProduct) { + result.productVersions = []; + result.selectedVersion = null; + return; + } + + var url = refstackApiUrl + '/products/' + + result.selectedProduct.id + '/versions'; + ctrl.getVersionsRequest = $http.get(url) + .success(function (data) { + result.productVersions = data; + + // If the test result isn't already associated to a + // version, default it to the null version. + if (!result.product_version) { + angular.forEach(data, function(ver) { + if (!ver.version) { + result.selectedVersion = ver; + } + }); + } + }).error(function (error) { + raiseAlert('danger', error.title, error.detail); + }); + } + + /** + * Instantiate variables needed for editing product/version + * associations. + */ + function prepVersionEdit(result) { + result.productEdit = true; + if (result.product_version) { + result.selectedProduct = + ctrl.products[result.product_version.product_info.id]; + } + result.selectedVersion = result.product_version; + ctrl.getProductVersions(result); + } + } })(); diff --git a/refstack-ui/app/shared/filters.js b/refstack-ui/app/shared/filters.js index 84b171b6..e38789f5 100644 --- a/refstack-ui/app/shared/filters.js +++ b/refstack-ui/app/shared/filters.js @@ -31,7 +31,9 @@ return function (objects) { var array = []; angular.forEach(objects, function (object, key) { - object.id = key; + if (!('id' in object)) { + object.id = key; + } array.push(object); }); return array; diff --git a/refstack-ui/tests/unit/ControllerSpec.js b/refstack-ui/tests/unit/ControllerSpec.js index fb941eb7..c8028e07 100644 --- a/refstack-ui/tests/unit/ControllerSpec.js +++ b/refstack-ui/tests/unit/ControllerSpec.js @@ -215,6 +215,8 @@ describe('Refstack controllers', function () { beforeEach(inject(function ($rootScope, $controller) { scope = $rootScope.$new(); ctrl = $controller('ResultsController', {$scope: scope}); + $httpBackend.when('GET', fakeApiUrl + + '/results?page=1').respond(fakeResponse); })); it('should fetch the first page of results with proper URL args', @@ -301,6 +303,51 @@ describe('Refstack controllers', function () { expect(ctrl.versionList).toEqual(['2015.04.json', '2015.03.json']); }); + + it('should have a function to get products manageable by a user', + function () { + var prodResp = {'products': [{'id': 'abc', + 'can_manage': true}, + {'id': 'foo', + 'can_manage': false}]}; + ctrl.products = null; + $httpBackend.expectGET(fakeApiUrl + '/products') + .respond(200, prodResp); + ctrl.getUserProducts(); + $httpBackend.flush(); + var expected = {'abc': {'id': 'abc', 'can_manage': true}}; + expect(ctrl.products).toEqual(expected); + }); + + it('should have a function to associate a product version to a test', + function () { + var result = {'id': 'bar', + 'selectedVersion': {'id': 'foo'}, + 'selectedProduct': {'id': 'prod'}}; + ctrl.products = null; + $httpBackend.expectPUT(fakeApiUrl + '/results/bar') + .respond(201); + ctrl.associateProductVersion(result); + $httpBackend.flush(); + var expected = {'id': 'foo', 'product_info': {'id': 'prod'}}; + expect(result.product_version).toEqual(expected); + }); + + it('should have a function to get product versions', + function () { + var result = {'id': 'bar', + 'selectedProduct': {'id': 'prod'}}; + var verResp = [{'id': 'ver1', 'version': '1.0'}, + {'id': 'ver2', 'version': null}]; + ctrl.products = null; + $httpBackend.expectGET(fakeApiUrl + '/products/prod/versions') + .respond(200, verResp); + ctrl.getProductVersions(result); + $httpBackend.flush(); + expect(result.productVersions).toEqual(verResp); + var expected = {'id': 'ver2', 'version': null}; + expect(result.selectedVersion).toEqual(expected); + }); }); describe('ResultsReportController', function () {