diff --git a/refstack-ui/app/assets/css/style.css b/refstack-ui/app/assets/css/style.css index f9cc2e3c..a9d41230 100644 --- a/refstack-ui/app/assets/css/style.css +++ b/refstack-ui/app/assets/css/style.css @@ -188,3 +188,7 @@ h1, h2, h3, h4, h5, h6 { .test-detail ul { padding-left: 20px; } + +a.glyphicon { + text-decoration: none; +} diff --git a/refstack-ui/app/components/results-report/resultsReport.html b/refstack-ui/app/components/results-report/resultsReport.html index feab7d3f..b176e154 100644 --- a/refstack-ui/app/components/results-report/resultsReport.html +++ b/refstack-ui/app/components/results-report/resultsReport.html @@ -34,9 +34,11 @@
Capabilities Version: -
diff --git a/refstack-ui/app/components/results-report/resultsReportController.js b/refstack-ui/app/components/results-report/resultsReportController.js index bf1cd53b..6da35e17 100644 --- a/refstack-ui/app/components/results-report/resultsReportController.js +++ b/refstack-ui/app/components/results-report/resultsReportController.js @@ -89,7 +89,9 @@ ctrl.versionsRequest = $http.get(content_url).success(function (data) { ctrl.versionList = data.sort().reverse(); - ctrl.version = ctrl.versionList[0]; + if (!ctrl.version) { + ctrl.version = ctrl.versionList[0]; + } ctrl.updateCapabilities(); }).error(function (error) { ctrl.showError = true; @@ -109,6 +111,10 @@ ctrl.resultsRequest = $http.get(content_url).success(function (data) { ctrl.resultsData = data; + ctrl.version = ctrl.resultsData.meta.guideline; + if (ctrl.resultsData.meta.target) { + ctrl.target = ctrl.resultsData.meta.target; + } getVersionList(); }).error(function (error) { ctrl.showError = true; diff --git a/refstack-ui/app/components/results/results.html b/refstack-ui/app/components/results/results.html index e0d34a0c..6b728c52 100644 --- a/refstack-ui/app/components/results/results.html +++ b/refstack-ui/app/components/results/results.html @@ -38,12 +38,15 @@
+
+
+ @@ -51,10 +54,96 @@ - + + - + + + + +
Upload Date Test Run ID Shared
+ + + + + {{result.created_at}} {{result.id}} + +
+ Publicly Shared: + Yes + + No + + + + +
+ + Associated Guideline: + + None + + + {{result.meta.guideline.slice(0, -5)}} + + + + + +
+ + Associated Target Program: + + None + + + {{ctrl.targetMappings[result.meta.target]}} + + + + + +
@@ -79,4 +168,3 @@ Error: {{ctrl.error}}
- diff --git a/refstack-ui/app/components/results/resultsController.js b/refstack-ui/app/components/results/resultsController.js index 8668dcf3..4c0bc51b 100644 --- a/refstack-ui/app/components/results/resultsController.js +++ b/refstack-ui/app/components/results/resultsController.js @@ -20,7 +20,7 @@ .controller('ResultsController', ResultsController); ResultsController.$inject = [ - '$scope', '$http', '$filter', '$state', 'refstackApiUrl' + '$scope', '$http', '$filter', '$state', 'refstackApiUrl','raiseAlert' ]; /** @@ -28,12 +28,22 @@ * This controller is for the '/results' page where a user can browse * a listing of community uploaded results. */ - function ResultsController($scope, $http, $filter, $state, refstackApiUrl) { + function ResultsController($scope, $http, $filter, $state, refstackApiUrl, + raiseAlert) { var ctrl = this; ctrl.update = update; ctrl.open = open; ctrl.clearFilters = clearFilters; + ctrl.associateMeta = associateMeta; + ctrl.getVersionList = getVersionList; + + /** Mappings of DefCore components to marketing program names. */ + ctrl.targetMappings = { + 'platform': 'Openstack Powered Platform', + 'compute': 'OpenStack Powered Compute', + 'object': 'OpenStack Powered Object Storage' + }; /** Initial page to be on. */ ctrl.currentPage = 1; @@ -143,5 +153,58 @@ ctrl.endDate = null; ctrl.update(); } + + /** + * This will send an API request in order to associate a metadata + * key-value pair with the given testId + * @param {Number} index - index of the test object in the results list + * @param {String} key - metadata key + * @param {String} value - metadata value + */ + function associateMeta(index, key, value) { + var testId = ctrl.data.results[index].id; + var metaUrl = [ + refstackApiUrl, '/results/', testId, '/meta/', key + ].join(''); + + var editFlag = key + 'Edit'; + if (value) { + ctrl.associateRequest = $http.post(metaUrl, value) + .success(function () { + ctrl.data.results[index][editFlag] = false; + }).error(function (error) { + raiseAlert('danger', error.title, error.detail); + }); + } + else { + ctrl.unassociateRequest = $http.delete(metaUrl) + .success(function () { + ctrl.data.results[index][editFlag] = false; + }).error(function (error) { + raiseAlert('danger', error.title, error.detail); + }); + } + } + + /** + * Retrieve an array of available capability files from the Refstack + * API server, sort this array reverse-alphabetically, and store it in + * a scoped variable. + * Sample API return array: ["2015.03.json", "2015.04.json"] + */ + function getVersionList() { + if (ctrl.versionList) { + return; + } + var content_url = refstackApiUrl + '/capabilities'; + ctrl.versionsRequest = + $http.get(content_url).success(function (data) { + ctrl.versionList = data.sort().reverse(); + }).error(function (error) { + raiseAlert('danger', error.title, + 'Unable to retrieve version list'); + }); + } + } })(); diff --git a/refstack-ui/tests/unit/ControllerSpec.js b/refstack-ui/tests/unit/ControllerSpec.js index 043b00c0..4d8a410d 100644 --- a/refstack-ui/tests/unit/ControllerSpec.js +++ b/refstack-ui/tests/unit/ControllerSpec.js @@ -160,7 +160,7 @@ describe('Refstack controllers', function () { 'pagination': {'current_page': 1, 'total_pages': 2}, 'results': [{ 'created_at': '2015-03-09 01:23:45', - 'test_id': 'some-id', + 'id': 'some-id', 'cpid': 'some-cpid' }] }; @@ -212,11 +212,56 @@ describe('Refstack controllers', function () { expect(ctrl.startDate).toBe(null); expect(ctrl.endDate).toBe(null); }); + + it('should have a function to associate metadata to a test run', + function () { + $httpBackend.expectGET(fakeApiUrl + '/results?page=1') + .respond(fakeResponse); + ctrl.data = fakeResponse; + ctrl.data.results[0].targetEdit = true; + ctrl.associateMeta(0, 'target', 'platform'); + $httpBackend.expectPOST( + fakeApiUrl + '/results/some-id/meta/target', + 'platform') + .respond(201, ''); + $httpBackend.flush(); + expect(ctrl.data.results[0].targetEdit).toBe(false); + }); + + it('should have a function to delete metadata from a test run', + function () { + $httpBackend.expectGET(fakeApiUrl + '/results?page=1') + .respond(fakeResponse); + ctrl.data = fakeResponse; + ctrl.data.results[0].targetEdit = true; + ctrl.associateMeta(0, 'target', ''); + $httpBackend.expectDELETE( + fakeApiUrl + '/results/some-id/meta/target') + .respond(200, ''); + $httpBackend.flush(); + expect(ctrl.data.results[0].targetEdit).toBe(false); + }); + + it('should have a function to get guideline versions', + function () { + $httpBackend.expectGET(fakeApiUrl + '/results?page=1') + .respond(fakeResponse); + $httpBackend.expectGET(fakeApiUrl + + '/capabilities').respond(['2015.03.json', '2015.04.json']); + ctrl.getVersionList(); + $httpBackend.flush(); + // Expect the list to have the latest guideline first. + expect(ctrl.versionList).toEqual(['2015.04.json', + '2015.03.json']); + }); }); describe('ResultsReportController', function () { var stateparams, ctrl; - var fakeResultResponse = {'results': ['test_id_1']}; + var fakeResultResponse = {'results': ['test_id_1'], 'meta': { + 'public_key': 'ssh-rsa', 'guideline': '2015.04.json', 'target': + 'object' + }}; var fakeCapabilityResponse = { 'platform': {'required': ['compute']}, 'schema': '1.2', diff --git a/refstack/api/controllers/results.py b/refstack/api/controllers/results.py index 8ecf6c32..28aaad22 100644 --- a/refstack/api/controllers/results.py +++ b/refstack/api/controllers/results.py @@ -36,7 +36,7 @@ CONF = cfg.CONF class MetadataController(rest.RestController): """/v1/results//meta handler.""" - rw_access_keys = ('shared',) + rw_access_keys = ('shared', 'guideline', 'target',) @pecan.expose('json') def get(self, test_id):