refstack/refstack-ui/app/components/products/productController.js

521 lines
18 KiB
JavaScript

/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function () {
'use strict';
angular
.module('refstackApp')
.controller('ProductController', ProductController);
ProductController.$inject = [
'$scope', '$http', '$state', '$stateParams', '$window', '$uibModal',
'refstackApiUrl', 'raiseAlert'
];
/**
* RefStack Product Controller
* This controller is for the '/product/' details page where owner can
* view details of the product.
*/
function ProductController($scope, $http, $state, $stateParams,
$window, $uibModal, refstackApiUrl, raiseAlert) {
var ctrl = this;
ctrl.getProduct = getProduct;
ctrl.getProductVersions = getProductVersions;
ctrl.deleteProduct = deleteProduct;
ctrl.deleteProductVersion = deleteProductVersion;
ctrl.getProductTests = getProductTests;
ctrl.switchProductPublicity = switchProductPublicity;
ctrl.associateTestMeta = associateTestMeta;
ctrl.getGuidelineVersionList = getGuidelineVersionList;
ctrl.addProductVersion = addProductVersion;
ctrl.unassociateTest = unassociateTest;
ctrl.openVersionModal = openVersionModal;
ctrl.openProductEditModal = openProductEditModal;
/** The product id extracted from the URL route. */
ctrl.id = $stateParams.id;
ctrl.productVersions = [];
if (!$scope.auth.isAuthenticated) {
$state.go('home');
}
/** Mappings of Interop WG components to marketing program names. */
ctrl.targetMappings = {
'platform': 'Openstack Powered Platform',
'compute': 'OpenStack Powered Compute',
'object': 'OpenStack Powered Object Storage',
'dns': 'OpenStack with DNS',
'orchestration': 'OpenStack with Orchestration',
'shared-file-system': 'OpenStack with Shared File System'
};
// Pagination controls.
ctrl.currentPage = 1;
ctrl.itemsPerPage = 20;
ctrl.maxSize = 5;
ctrl.getProduct();
ctrl.getProductVersions();
ctrl.getProductTests();
/**
* This will contact the Refstack API to get a product information.
*/
function getProduct() {
ctrl.showError = false;
ctrl.product = null;
var content_url = refstackApiUrl + '/products/' + ctrl.id;
ctrl.productRequest = $http.get(content_url).success(
function(data) {
ctrl.product = data;
ctrl.productProperties =
angular.fromJson(data.properties);
}
).error(function(error) {
ctrl.showError = true;
ctrl.error =
'Error retrieving from server: ' +
angular.toJson(error);
}).then(function() {
var url = refstackApiUrl + '/vendors/' +
ctrl.product.organization_id;
$http.get(url).success(function(data) {
ctrl.vendor = data;
}).error(function(error) {
ctrl.showError = true;
ctrl.error =
'Error retrieving from server: ' +
angular.toJson(error);
});
});
}
/**
* This will contact the Refstack API to get product versions.
*/
function getProductVersions() {
ctrl.showError = false;
var content_url = refstackApiUrl + '/products/' + ctrl.id +
'/versions';
ctrl.productVersionsRequest = $http.get(content_url).success(
function(data) {
ctrl.productVersions = data;
// Determine the null version.
for (var i = 0; i < data.length; i++) {
if (data[i].version === null) {
ctrl.nullVersion = data[i];
break;
}
}
}
).error(function(error) {
ctrl.showError = true;
ctrl.error =
'Error retrieving versions from server: ' +
angular.toJson(error);
});
}
/**
* This will delete the product.
*/
function deleteProduct() {
var url = [refstackApiUrl, '/products/', ctrl.id].join('');
$http.delete(url).success(function () {
$window.location.href = '/';
}).error(function (error) {
raiseAlert('danger', 'Error: ', error.detail);
});
}
/**
* This will delete the given product versions.
*/
function deleteProductVersion(versionId) {
var url = [
refstackApiUrl, '/products/', ctrl.id,
'/versions/', versionId ].join('');
$http.delete(url).success(function () {
ctrl.getProductVersions();
}).error(function (error) {
raiseAlert('danger', 'Error: ', error.detail);
});
}
/**
* Set a POST request to the API server to add a new version for
* the product.
*/
function addProductVersion() {
var url = [refstackApiUrl, '/products/', ctrl.id,
'/versions'].join('');
ctrl.addVersionRequest = $http.post(url,
{'version': ctrl.newProductVersion})
.success(function (data) {
ctrl.productVersions.push(data);
ctrl.newProductVersion = '';
ctrl.showNewVersionInput = false;
}).error(function (error) {
raiseAlert('danger', error.title, error.detail);
});
}
/**
* Get tests runs associated with the current product.
*/
function getProductTests() {
ctrl.showTestsError = false;
var content_url = refstackApiUrl + '/results' +
'?page=' + ctrl.currentPage + '&product_id='
+ ctrl.id;
ctrl.testsRequest = $http.get(content_url).success(
function(data) {
ctrl.testsData = data.results;
ctrl.totalItems = data.pagination.total_pages *
ctrl.itemsPerPage;
ctrl.currentPage = data.pagination.current_page;
}
).error(function(error) {
ctrl.showTestsError = true;
ctrl.testsError =
'Error retrieving tests from server: ' +
angular.toJson(error);
});
}
/**
* This will switch public/private property of the product.
*/
function switchProductPublicity() {
var url = [refstackApiUrl, '/products/', ctrl.id].join('');
$http.put(url, {public: !ctrl.product.public}).success(
function (data) {
ctrl.product = data;
ctrl.productProperties = angular.fromJson(data.properties);
}).error(function (error) {
raiseAlert('danger', 'Error: ', error.detail);
});
}
/**
* 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 associateTestMeta(index, key, value) {
var testId = ctrl.testsData[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.testsData[index][editFlag] = false;
}).error(function (error) {
raiseAlert('danger', error.title, error.detail);
});
} else {
ctrl.unassociateRequest = $http.delete(metaUrl)
.success(function () {
ctrl.testsData[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 getGuidelineVersionList() {
if (ctrl.versionList) {
return;
}
var content_url = refstackApiUrl + '/guidelines';
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');
});
}
/**
* Send a PUT request to the API server to unassociate a product with
* a test result.
*/
function unassociateTest(index) {
var testId = ctrl.testsData[index].id;
var url = refstackApiUrl + '/results/' + testId;
ctrl.associateRequest = $http.put(url, {'product_version_id': null})
.success(function () {
ctrl.testsData.splice(index, 1);
}).error(function (error) {
raiseAlert('danger', error.title, error.detail);
});
}
/**
* This will open the modal that will allow a product version
* to be managed.
*/
function openVersionModal(version) {
$uibModal.open({
templateUrl: '/components/products/partials' +
'/versionsModal.html',
backdrop: true,
windowClass: 'modal',
animation: true,
controller: 'ProductVersionModalController as modal',
size: 'lg',
resolve: {
version: function () {
return version;
},
parent: function () {
return ctrl;
}
}
});
}
/**
* This will open the modal that will allow product details
* to be edited.
*/
function openProductEditModal() {
$uibModal.open({
templateUrl: '/components/products/partials' +
'/productEditModal.html',
backdrop: true,
windowClass: 'modal',
animation: true,
controller: 'ProductEditModalController as modal',
size: 'lg',
resolve: {
product: function () {
return ctrl.product;
},
version: function () {
return ctrl.nullVersion;
}
}
});
}
}
angular
.module('refstackApp')
.controller('ProductVersionModalController',
ProductVersionModalController);
ProductVersionModalController.$inject = [
'$uibModalInstance', '$http', 'refstackApiUrl', 'version', 'parent'
];
/**
* Product Version Modal Controller
* This controller is for the modal that appears if a user wants to
* manage a product version.
*/
function ProductVersionModalController($uibModalInstance, $http,
refstackApiUrl, version, parent) {
var ctrl = this;
ctrl.version = angular.copy(version);
ctrl.parent = parent;
ctrl.close = close;
ctrl.deleteProductVersion = deleteProductVersion;
ctrl.saveChanges = saveChanges;
/**
* This function will close/dismiss the modal.
*/
function close() {
$uibModalInstance.dismiss('exit');
}
/**
* Call the parent function to delete a version, then close the modal.
*/
function deleteProductVersion() {
ctrl.parent.deleteProductVersion(ctrl.version.id);
ctrl.close();
}
/**
* This will update the current version, saving changes.
*/
function saveChanges() {
ctrl.showSuccess = false;
ctrl.showError = false;
var url = [
refstackApiUrl, '/products/', ctrl.version.product_id,
'/versions/', ctrl.version.id ].join('');
var content = {'cpid': ctrl.version.cpid};
$http.put(url, content).success(function() {
// Update the original version object.
version.cpid = ctrl.version.cpid;
ctrl.showSuccess = true;
}).error(function(error) {
ctrl.showError = true;
ctrl.error = error.detail;
});
}
}
angular
.module('refstackApp')
.controller('ProductEditModalController', ProductEditModalController);
ProductEditModalController.$inject = [
'$uibModalInstance', '$http', '$state', 'product',
'version', 'refstackApiUrl'
];
/**
* Product Edit Modal Controller
* This controls the modal that allows editing a product.
*/
function ProductEditModalController($uibModalInstance, $http,
$state, product, version, refstackApiUrl) {
var ctrl = this;
ctrl.close = close;
ctrl.addField = addField;
ctrl.saveChanges = saveChanges;
ctrl.removeProperty = removeProperty;
ctrl.product = angular.copy(product);
ctrl.productName = product.name;
ctrl.productProperties = [];
ctrl.productVersion = angular.copy(version);
ctrl.originalCpid = version ? version.cpid : null;
parseProductProperties();
/**
* Close the product edit modal.
*/
function close() {
$uibModalInstance.dismiss('exit');
}
/**
* Push a blank property key-value pair into the productProperties
* array. This will spawn new input boxes.
*/
function addField() {
ctrl.productProperties.push({'key': '', 'value': ''});
}
/**
* Send a PUT request to the server with the changes.
*/
function saveChanges() {
ctrl.showError = false;
ctrl.showSuccess = false;
var url = [refstackApiUrl, '/products/', ctrl.product.id].join('');
var properties = propertiesToJson();
var content = {'description': ctrl.product.description,
'properties': properties};
if (ctrl.productName !== ctrl.product.name) {
content.name = ctrl.product.name;
}
// Request for product detail updating.
$http.put(url, content).success(function() {
// Request for product version CPID update if it has changed.
if (ctrl.productVersion &&
ctrl.originalCpid !== ctrl.productVersion.cpid) {
url = url + '/versions/' + ctrl.productVersion.id;
content = {'cpid': ctrl.productVersion.cpid};
$http.put(url, content).success(function() {
ctrl.showSuccess = true;
ctrl.originalCpid = ctrl.productVersion.cpid;
$state.reload();
}).error(function(error) {
ctrl.showError = true;
ctrl.error = error.detail;
});
} else {
ctrl.showSuccess = true;
$state.reload();
}
}).error(function(error) {
ctrl.showError = true;
ctrl.error = error.detail;
});
}
/**
* Remove a property from the productProperties array at the given
* index.
*/
function removeProperty(index) {
ctrl.productProperties.splice(index, 1);
}
/**
* Parse the product properties and put them in a format more suitable
* for forms.
*/
function parseProductProperties() {
var props = angular.fromJson(ctrl.product.properties);
angular.forEach(props, function(value, key) {
ctrl.productProperties.push({'key': key, 'value': value});
});
}
/**
* Convert the list of property objects to a dict containing the
* each key-value pair.
*/
function propertiesToJson() {
if (!ctrl.productProperties.length) {
return null;
}
var properties = {};
for (var i = 0, len = ctrl.productProperties.length; i < len; i++) {
var prop = ctrl.productProperties[i];
if (prop.key && prop.value) {
properties[prop.key] = prop.value;
}
}
return properties;
}
}
})();