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 @@
+
+
+ |
Upload Date |
Test Run ID |
Shared |
@@ -51,10 +54,96 @@
-
+
+
+
+
+
+
+ |
{{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):