var Composer = {};
var FileManager = {};
+var PackageManager = {};
var DataCenters = {};
// Catalog module methods
Composer.get = function(req) {
});
}
-Composer.update = function(req) {
- console.log(' Updating file', req.file.originalname, 'as', req.file.filename);
+PackageManager.upload = function(req) {
+ console.log(' Uploading file', req.file.originalname, 'as', req.file.filename);
var api_server = req.query['api_server'];
// dev_download_server is for testing purposes.
// It is the direct IP address of the Node server where the
var download_host = req.query['dev_download_server'];
if (!download_host) {
- download_host = req.protocol + '://' + req.get('host');//api_server + ':' + utils.getPortForProtocol(req.protocol);
- }
- var input = {
- 'external-url': download_host + '/composer/update/' + req.file.filename,
- 'package-type': 'VNFD',
- 'package-id': uuid()
+ download_host = req.protocol + '://' + req.get('host');//req.api_server + ':' + utils.getPortForProtocol(req.protocol);
}
+
return new Promise(function(resolve, reject) {
Promise.all([
rp({
- uri: utils.confdPort(api_server) + '/api/operations/package-update',
+ uri: utils.confdPort(api_server) + '/api/operations/package-create',
method: 'POST',
headers: _.extend({}, constants.HTTP_HEADERS.accept.collection, {
'Authorization': req.get('Authorization')
resolveWithFullResponse: true,
json: true,
body: {
- input: input
+ input: {
+ 'external-url': download_host + '/composer/upload/' + req.file.filename,
+ 'package-type': 'VNFD',
+ 'package-id': uuid()
+ }
}
})
]).then(function(result) {
data['transaction_id'] = result[0].body['output']['transaction-id'];
// Add a status checker on the transaction and then to delete the file later
- PackageFileHandler.checkCreatePackageStatusAndHandleFile(req, data['transaction_id'], true);
+ PackageFileHandler.checkCreatePackageStatusAndHandleFile(req, data['transaction_id']);
// Return status to composer UI to update the status.
resolve({
});
}).catch(function(error) {
var res = {};
- console.log('Problem with Composer.upload', error);
+ console.log('Problem with PackageManager.upload', error);
res.statusCode = error.statusCode || 500;
res.errorMessage = {
error: 'Failed to upload package ' + req.file.originalname + '. Error: ' + error
});
};
-Composer.upload = function(req) {
- console.log(' Uploading file', req.file.originalname, 'as', req.file.filename);
+PackageManager.update = function(req) {
+ console.log(' Updating file', req.file.originalname, 'as', req.file.filename);
var api_server = req.query['api_server'];
// dev_download_server is for testing purposes.
// It is the direct IP address of the Node server where the
var download_host = req.query['dev_download_server'];
if (!download_host) {
- download_host = req.protocol + '://' + req.get('host');//req.api_server + ':' + utils.getPortForProtocol(req.protocol);
+ download_host = req.protocol + '://' + req.get('host');//api_server + ':' + utils.getPortForProtocol(req.protocol);
+ }
+ var input = {
+ 'external-url': download_host + '/composer/update/' + req.file.filename,
+ 'package-type': 'VNFD',
+ 'package-id': uuid()
}
-
return new Promise(function(resolve, reject) {
Promise.all([
rp({
- uri: utils.confdPort(api_server) + '/api/operations/package-create',
+ uri: utils.confdPort(api_server) + '/api/operations/package-update',
method: 'POST',
headers: _.extend({}, constants.HTTP_HEADERS.accept.collection, {
'Authorization': req.get('Authorization')
resolveWithFullResponse: true,
json: true,
body: {
- input: {
- 'external-url': download_host + '/composer/upload/' + req.file.filename,
- 'package-type': 'VNFD',
- 'package-id': uuid()
- }
+ input: input
}
})
]).then(function(result) {
data['transaction_id'] = result[0].body['output']['transaction-id'];
// Add a status checker on the transaction and then to delete the file later
- PackageFileHandler.checkCreatePackageStatusAndHandleFile(req, data['transaction_id']);
+ PackageFileHandler.checkCreatePackageStatusAndHandleFile(req, data['transaction_id'], true);
// Return status to composer UI to update the status.
resolve({
});
};
-
-
-Composer.addFile = function(req) {
- console.log(' Uploading file', req.file.originalname, 'as', req.file.filename);
+PackageManager.export = function(req) {
+ // /api/operations/package-export
var api_server = req.query['api_server'];
- var download_host = req.query['dev_download_server'];
- var package_id = req.query['package_id'];
- var package_type = req.query['package_type'].toUpperCase();
- var package_path = req.query['package_path'];
- if (!download_host) {
- download_host = req.protocol + '://' + req.get('host');//api_server + ':' + utils.getPortForProtocol(req.protocol);
- }
- var input = {
- 'external-url': download_host + '/composer/upload/' + req.query['package_id'] + '/' + req.file.filename,
- 'package-type': package_type,
- 'package-id': package_id,
- 'package-path': package_path + '/' + req.file.filename
- }
return new Promise(function(resolve, reject) {
Promise.all([
rp({
- uri: utils.confdPort(api_server) + '/api/operations/package-file-add',
+ uri: utils.confdPort(api_server) + '/api/operations/package-export',
method: 'POST',
headers: _.extend({}, constants.HTTP_HEADERS.accept.collection, {
'Authorization': req.get('Authorization')
rejectUnauthorized: false,
resolveWithFullResponse: true,
json: true,
- body: {
- input: input
- }
+ body: { "input": req.body}
})
]).then(function(result) {
var data = {};
- data['transaction_id'] = result[0].body['output']['task-id'];
resolve({
statusCode: constants.HTTP_RESPONSE_CODES.SUCCESS.OK,
- data: data
+ data: result[0].body
});
}).catch(function(error) {
var res = {};
- console.log('Problem with Composer.upload', error);
+ console.log('Problem with PackageManager.export', error);
res.statusCode = error.statusCode || 500;
res.errorMessage = {
- error: 'Failed to upload package ' + req.file.originalname + '. Error: ' + error
+ error: error
};
reject(res);
});
});
}
-Composer.exportPackage = function(req) {
- // /api/operations/package-export
+PackageManager.copy = function(req) {
+ // /api/operations/package-copy
var api_server = req.query['api_server'];
return new Promise(function(resolve, reject) {
Promise.all([
rp({
- uri: utils.confdPort(api_server) + '/api/operations/package-export',
+ uri: utils.confdPort(api_server) + '/api/operations/package-copy',
method: 'POST',
headers: _.extend({}, constants.HTTP_HEADERS.accept.collection, {
'Authorization': req.get('Authorization')
});
}).catch(function(error) {
var res = {};
- console.log('Problem with Composer.exportPackage', error);
+ console.log('Problem with PackageManager.copy', error);
res.statusCode = error.statusCode || 500;
res.errorMessage = {
error: error
});
}
+PackageManager.getJobStatus = function(req) {
+ var api_server = req.query["api_server"];
+ var uri = utils.confdPort(api_server);
+ var url = '/api/operational/copy-jobs';
+ var id = req.params['id'];
+ return new Promise(function(resolve, reject) {
+ request({
+ url: uri + url + '?deep',
+ method: 'GET',
+ headers: _.extend({}, constants.HTTP_HEADERS.accept.data, {
+ 'Authorization': req.get('Authorization')
+ }),
+ forever: constants.FOREVER_ON,
+ rejectUnauthorized: false,
+ }, function(error, response, body) {
+ if (utils.validateResponse('restconfAPI.streams', error, response, body, resolve, reject)) {
+ var data = JSON.parse(response.body)['rw-pkg-mgmt:copy-jobs'];
+ var returnData = [];
+ data && data.job.map(function(d) {
+ if(d['transaction-id'] == id) {
+ returnData.push(d)
+ }
+ })
+ resolve({
+ statusCode: response.statusCode,
+ data: returnData
+ })
+ };
+ })
+ })
+}
+
+FileManager.addFile = function(req) {
+ console.log(' Uploading file', req.file.originalname, 'as', req.file.filename);
+ var api_server = req.query['api_server'];
+ var download_host = req.query['dev_download_server'];
+ var package_id = req.query['package_id'];
+ var package_type = req.query['package_type'].toUpperCase();
+ var package_path = req.query['package_path'];
+ if (!download_host) {
+ download_host = req.protocol + '://' + req.get('host');//api_server + ':' + utils.getPortForProtocol(req.protocol);
+ }
+ var input = {
+ 'external-url': download_host + '/composer/upload/' + req.query['package_id'] + '/' + req.file.filename,
+ 'package-type': package_type,
+ 'package-id': package_id,
+ 'package-path': package_path + '/' + req.file.filename
+ }
+ return new Promise(function(resolve, reject) {
+ Promise.all([
+ rp({
+ uri: utils.confdPort(api_server) + '/api/operations/package-file-add',
+ method: 'POST',
+ headers: _.extend({}, constants.HTTP_HEADERS.accept.collection, {
+ 'Authorization': req.get('Authorization')
+ }),
+ forever: constants.FOREVER_ON,
+ rejectUnauthorized: false,
+ resolveWithFullResponse: true,
+ json: true,
+ body: {
+ input: input
+ }
+ })
+ ]).then(function(result) {
+ var data = {};
+ data['transaction_id'] = result[0].body['output']['task-id'];
+ resolve({
+ statusCode: constants.HTTP_RESPONSE_CODES.SUCCESS.OK,
+ data: data
+ });
+ }).catch(function(error) {
+ var res = {};
+ console.log('Problem with Composer.upload', error);
+ res.statusCode = error.statusCode || 500;
+ res.errorMessage = {
+ error: 'Failed to upload package ' + req.file.originalname + '. Error: ' + error
+ };
+ reject(res);
+ });
+ });
+}
+
FileManager.get = function(req) {
var api_server = req.query['api_server'];
var type = req.query['package_type'] && req.query['package_type'].toUpperCase();
}
module.exports = {
Composer:Composer,
- FileManager: FileManager
+ FileManager: FileManager,
+ PackageManager: PackageManager
};
var C = require('./api/composer.js');
var Composer = C.Composer;
var FileManager = C.FileManager;
+var PackageManager = C.PackageManager;
var multer = require('multer');
var fs = require('fs');
var path = require('path');
res.send(error.errorMessage);
});
});
-router.post('/upload', cors(), upload.single('package'), function (req, res, next) {
- Composer.upload(req).then(function(data) {
+
+router.post('/api/file-manager', cors(), upload.single('package'), function (req, res, next) {
+ FileManager.addFile(req).then(function(data) {
utils.sendSuccessResponse(data, res);
}, function(error) {
utils.sendErrorResponse(error, res);
});
});
-router.use('/upload', cors(), express.static('upload/packages'));
-router.post('/update', cors(), upload.single('package'), function (req, res, next) {
- Composer.update(req).then(function(data) {
+router.get('/api/file-manager', cors(), function(req, res) {
+ FileManager.get(req).then(function(data) {
+ utils.sendSuccessResponse(data, res);
+ }, function(error) {
+ utils.sendErrorResponse(error, res);
+ });
+})
+router.get('/api/file-manager/jobs/:id', cors(), function(req, res) {
+ FileManager.job(req).then(function(data) {
+ utils.sendSuccessResponse(data, res);
+ }, function(error) {
+ utils.sendErrorResponse(error, res);
+ });
+});
+router.delete('/api/file-manager', cors(), function(req, res) {
+ FileManager.get(req).then(function(data) {
utils.sendSuccessResponse(data, res);
}, function(error) {
utils.sendErrorResponse(error, res);
});
});
-router.use('/update', cors(), express.static('upload/packages'));
-
+// Catalog operations via package manager
-router.post('/api/file-manager', cors(), upload.single('package'), function (req, res, next) {
- Composer.addFile(req).then(function(data) {
+router.post('/upload', cors(), upload.single('package'), function (req, res, next) {
+ PackageManager.upload(req).then(function(data) {
utils.sendSuccessResponse(data, res);
}, function(error) {
utils.sendErrorResponse(error, res);
});
});
+router.use('/upload', cors(), express.static('upload/packages'));
-router.get('/api/file-manager', cors(), function(req, res) {
- FileManager.get(req).then(function(data) {
+router.post('/update', cors(), upload.single('package'), function (req, res, next) {
+ PackageManager.update(req).then(function(data) {
utils.sendSuccessResponse(data, res);
}, function(error) {
utils.sendErrorResponse(error, res);
});
-})
-router.get('/api/file-manager/jobs/:id', cors(), function(req, res) {
- FileManager.job(req).then(function(data) {
+});
+router.use('/update', cors(), express.static('upload/packages'));
+
+router.post('/api/package-export', cors(), function (req, res, next) {
+ PackageManager.export(req).then(function(data) {
utils.sendSuccessResponse(data, res);
}, function(error) {
utils.sendErrorResponse(error, res);
});
});
-router.delete('/api/file-manager', cors(), function(req, res) {
- FileManager.get(req).then(function(data) {
+router.post('/api/package-copy', cors(), function (req, res, next) {
+ PackageManager.copy(req).then(function(data) {
utils.sendSuccessResponse(data, res);
}, function(error) {
utils.sendErrorResponse(error, res);
});
});
-
-router.post('/api/package-export', cors(), function (req, res, next) {
- Composer.exportPackage(req).then(function(data) {
+router.get('/api/package-manager/jobs/:id', cors(), function (req, res, next) {
+ PackageManager.getJobStatus(req).then(function(data) {
utils.sendSuccessResponse(data, res);
}, function(error) {
utils.sendErrorResponse(error, res);
class CatalogPackageManagerActions {
constructor() {
- this.generateActions('downloadCatalogPackage', 'downloadCatalogPackageStatusUpdated', 'downloadCatalogPackageError', 'uploadCatalogPackage', 'uploadCatalogPackageStatusUpdated', 'uploadCatalogPackageError', 'removeCatalogPackage');
+ this.generateActions(
+ 'downloadCatalogPackage',
+ 'downloadCatalogPackageStatusUpdated',
+ 'downloadCatalogPackageError',
+ 'uploadCatalogPackage',
+ 'uploadCatalogPackageStatusUpdated',
+ 'uploadCatalogPackageError',
+ 'copyCatalogPackage',
+ 'updateStatus',
+ 'removeCatalogOperation'
+ );
}
}
var createItem = function (catalogPackage) {
const onClickRemove = function () {
- CatalogPackageManagerActions.removeCatalogPackage(catalogPackage);
+ CatalogPackageManagerActions.removeCatalogOperation(catalogPackage);
};
const classNames = ClassNames('item', {'-error': catalogPackage.error, '-success': catalogPackage.success});
return (
);
};
- const packages = this.state.packages || [];
+ const operations = this.state.operations || [];
return (
<div className="CatalogPackageManager">
<div className="items">
- {packages.map(createItem)}
+ {operations.map(createItem)}
</div>
</div>
);
CatalogItemsActions.createCatalogItem(type);
},
onClickDuplicateCatalogItem() {
+ CatalogPanelTrayActions.open();
CatalogItemsActions.duplicateSelectedCatalogItem();
},
onClickExportCatalogItems() {
*/
'use strict';
-import $ from 'jquery'
import alt from '../alt'
-import utils from '../libraries/utils'
+import catalogUtils from '../libraries/utils'
import CatalogPackageManagerActions from '../actions/CatalogPackageManagerActions'
-let Utils = require('utils/utils.js');
-function getApiServerOrigin() {
- return utils.getSearchParams(window.location).upload_server + ':4567';
-}
+import Utils from 'utils/utils.js';
-function ajaxRequest(path, catalogPackage, resolve, reject, method = 'GET', input, urlOverride) {
- let options = {
- url: getApiServerOrigin() + path,
- type: method,
- beforeSend: Utils.addAuthorizationStub,
- dataType: 'json',
- success: function(data) {
- if (typeof data == 'string') {
- data = JSON.parse(data);
- }
- resolve({
- data: data,
- state: catalogPackage
- });
- },
- error: function(error) {
- if (typeof error == 'string') {
- error = JSON.parse(error);
- }
- reject({
- data: error,
- state: catalogPackage
- });
- }
+const getAuthorization = () => 'Basic ' + window.sessionStorage.getItem("auth");
+
+const getStateApiPath = (operation, id) =>
+ catalogUtils.getSearchParams(window.location).upload_server + ':4567/api/' + operation + '/' + id + '/state';
+
+const getComposerApiPath = (api) =>
+ window.location.origin + '/composer/api/' + api + '?api_server=' + catalogUtils.getSearchParams(window.location).api_server;
+
+const SUCCESS = {
+ pending: false,
+ success: true,
+ error: false,
+ message: "Completely successfully"
};
- if(input) {
- options.data = input;
+const FAILED = {
+ pending: false,
+ success: false,
+ error: true,
+ message: "Failed"
+ };
+const PENDING = {
+ pending: true,
+ success: false,
+ error: false,
+ message: "In progress"
+ };
+
+function ajaxFetch(url, operation, resolve, reject, method = 'GET', input, urlOverride) {
+ let credentials = 'same-origin';
+ let body = input ? JSON.stringify(input) : null;
+ let headers = new Headers();
+ headers.append('Authorization', getAuthorization());
+ headers.append('Accept', 'application/json');
+ if (input) {
+ headers.append('Content-Type', 'application/json');
}
- if (urlOverride) {
- options.url = window.location.origin + path;
+
+ fetch(url, {method, credentials, headers, body})
+ .then(checkStatusGetJson)
+ .then(handleSuccess)
+ .catch(handleError);
+
+ function checkStatusGetJson(response) {
+ if (response.status >= 200 && response.status < 300) {
+ return response.json();
+ } else {
+ var error = new Error(response.statusText)
+ error.status = response.status;
+ error.statusText = response.statusText;
+ throw error
+ }
}
- $.ajax(options).fail(function(xhr){
- //Authentication and the handling of fail states should be wrapped up into a connection class.
- Utils.checkAuthentication(xhr.status);
- });
-}
+ function handleSuccess (data) {
+ if (typeof data == 'string') {
+ data = JSON.parse(data);
+ }
+ resolve({
+ state: operation,
+ data,
+ operation
+ });
+ }
+ function handleError (data) {
+ if (typeof data == 'string') {
+ data = JSON.parse(data);
+ }
+ reject({
+ state: operation,
+ data,
+ operation
+ });
+ }
+}
const CatalogPackageManagerSource = {
- requestCatalogPackageDownload: function () {
+ requestCatalogPackageDownload: function () {
return {
remote: function (state, download, format, grammar, schema) {
return new Promise((resolve, reject) => {
- // the server does not add a status in the payload
- // so we add one so that the success handler will
- // be able to follow the flow of this download
- const setStatusBeforeResolve = (response = {}) => {
+ // we need an initial status for UI (server does not send)
+ const setStatusBeforeResolve = (response) => {
response.data.status = 'download-requested';
resolve(response);
};
- // RIFT-13485 requires to send type (nsd/vnfd) as a path element.
- // Backend no longer supports mixed multi-package download.
- // Probably does not even support multi-package download of same type.
- // Hence, pick the type from the first element.
const data = {
"package-type": download['catalogItems'][0]['uiState']['type'].toUpperCase(),
"package-id": download.ids,
"export-grammar": grammar && grammar.toUpperCase() || 'OSM',
"export-schema": schema && schema.toUpperCase() || "RIFT"
}
- const path = "/composer/api/package-export?api_server=" + utils.getSearchParams(window.location).api_server;
- ajaxRequest(path, download, setStatusBeforeResolve, reject, 'POST', data, true);
+ const path = getComposerApiPath('package-export');
+ ajaxFetch(path, download, setStatusBeforeResolve, reject, 'POST', data, true);
})
- //.then(function(data) {
- // let filename = data.data.output.filename;
- // window.open(getApiServerOrigin() + "/api/export/" + filename, "_blank")
- //});
},
success: CatalogPackageManagerActions.downloadCatalogPackageStatusUpdated,
error: CatalogPackageManagerActions.downloadCatalogPackageError
remote: function(state, download) {
const transactionId = download.transactionId;
return new Promise(function(resolve, reject) {
- const path = '/api/export/' + transactionId + '/state';
- ajaxRequest(path, download, resolve, reject);
+ const path = getStateApiPath('export', transactionId);
+ ajaxFetch(path, download, resolve, reject);
});
},
success: CatalogPackageManagerActions.downloadCatalogPackageStatusUpdated,
}
},
+ requestCatalogPackageCopy: function () {
+ return {
+ remote: function (state, operationInfo) {
+ return new Promise((resolve, reject) => {
+ // we need an initial status for UI (server does not send)
+ const successHandler = (response) => {
+ const status = response.data.output.status;
+ const state = status === "COMPLETED" ? SUCCESS : status === "FAILED" ? FAILED : PENDING;
+ state.progress = 25; // put something
+ let operation = Object.assign({}, operationInfo, state);
+ operation.transactionId = response.data.output['transaction-id'];
+ resolve(operation);
+ }
+ const failHandler = (response) => {
+ let operation = Object.assign({}, this, FAILED);
+ reject(operation);
+ };
+ const data = {
+ "package-type": operationInfo.packageType,
+ "package-id": operationInfo.id,
+ "package-name": operationInfo.name
+ }
+ const path = getComposerApiPath('package-copy');
+ ajaxFetch(path, operationInfo, successHandler, failHandler, 'POST', data, true);
+ })
+ },
+ success: CatalogPackageManagerActions.updateStatus,
+ error: CatalogPackageManagerActions.updateStatus
+ };
+ },
+
+ requestCatalogPackageCopyStatus: function() {
+ return {
+ remote: function(state, operation) {
+ return new Promise(function(resolve, reject) {
+ const successHandler = (response) => {
+ const status = response.data[0].status;
+ const state = status === "COMPLETED" ? SUCCESS : status === "FAILED" ? FAILED : PENDING;
+ state.progress = state.pending ? operation.progress + ((100 - operation.progress) / 2) : 100;
+ let newOp = Object.assign({}, operation, state);
+ resolve(newOp);
+ };
+ const failHandler = (response) => {
+ let operation = Object.assign({}, this, FAILED);
+ reject(operation);
+ };
+ const path = getComposerApiPath('package-manager/jobs/' + operation.transactionId);
+ ajaxFetch(path, operation, successHandler, failHandler);
+ });
+ },
+ success: CatalogPackageManagerActions.updateStatus,
+ error: CatalogPackageManagerActions.updateStatus
+ }
+ },
+
requestCatalogPackageUploadStatus: function () {
return {
remote: function (state, upload) {
const transactionId = upload.transactionId;
return new Promise(function (resolve, reject) {
const action = upload.riftAction === 'onboard' ? 'upload' : 'update';
- const path = '/api/' + action + '/' + transactionId + '/state';
- ajaxRequest(path, upload, resolve, reject);
+ const path = getStateApiPath(action, transactionId);
+ ajaxFetch(path, upload, resolve, reject);
});
},
success: CatalogPackageManagerActions.uploadCatalogPackageStatusUpdated,
}
duplicateSelectedCatalogItem() {
- const item = this.getFirstSelectedCatalogItem();
- if (item) {
- const newItem = _cloneDeep(item);
- newItem.name = newItem.name + ' Copy';
- newItem.id = guid();
- UID.assignUniqueId(newItem.uiState);
- const nsd = this.addNewItemToCatalog(newItem);
- this.selectCatalogItem(nsd);
- nsd.uiState.isNew = true;
- nsd.uiState.modified = true;
- nsd.uiState['instance-ref-count'] = 0;
- // note duplicated items get a new id, map the layout position
- // of the old id to the new id in order to preserve the layout
- if (nsd.uiState.containerPositionMap) {
- nsd.uiState.containerPositionMap[nsd.id] = nsd.uiState.containerPositionMap[item.id];
- delete nsd.uiState.containerPositionMap[item.id];
- }
- setTimeout(() => {
- this.selectCatalogItem(nsd);
- CatalogItemsActions.editCatalogItem.defer(nsd);
- }, 200);
+ // make request to backend to duplicate an item
+ const srcItem = this.getFirstSelectedCatalogItem();
+ if (srcItem) {
+ CatalogPackageManagerActions.copyCatalogPackage.defer(srcItem);
}
}
import imgDownload from '../../../node_modules/open-iconic/svg/cloud-download.svg'
import imgOnboard from '../../../node_modules/open-iconic/svg/cloud-upload.svg'
import imgUpdate from '../../../node_modules/open-iconic/svg/data-transfer-upload.svg'
+import imgCopy from '../../../node_modules/open-iconic/svg/layers.svg'
const defaults = {
+ operation: {
+ id: '',
+ name: '',
+ icon: '',
+ transactionId: '',
+ progress: 0,
+ message: 'Requested',
+ args: {},
+ pending: false,
+ success: false,
+ error: false,
+ },
downloadPackage: {
id: '',
name: '',
return utils.getSearchParams(window.location).upload_server + ':4567';
}
-function delayStatusCheck(statusCheckFunction, catalogPackage) {
- if (!catalogPackage.checkStatusTimeoutId) {
+function delayStatusCheck(statusCheckFunction, operation) {
+ if (!operation.checkStatusTimeoutId) {
const delayCallback = function () {
- delete catalogPackage.checkStatusTimeoutId;
- statusCheckFunction(catalogPackage).catch(exception);
+ delete operation.checkStatusTimeoutId;
+ statusCheckFunction(operation).catch(exception);
};
- catalogPackage.checkStatusTimeoutId = _delay(delayCallback, defaults.checkStatusDelayInSeconds * 1000);
+ operation.checkStatusTimeoutId = _delay(delayCallback, defaults.checkStatusDelayInSeconds * 1000);
}
}
constructor() {
- this.packages = [];
+ this.operations = [];
this.registerAsync(CatalogDataSource);
this.registerAsync(CatalogPackageManagerSource);
- this.bindAction(CatalogPackageManagerActions.REMOVE_CATALOG_PACKAGE, this.removeCatalogPackage);
+ this.bindAction(CatalogPackageManagerActions.REMOVE_CATALOG_OPERATION, this.removeCatalogOperation);
this.bindAction(CatalogPackageManagerActions.DOWNLOAD_CATALOG_PACKAGE, this.downloadCatalogPackage);
this.bindAction(CatalogPackageManagerActions.DOWNLOAD_CATALOG_PACKAGE_STATUS_UPDATED, this.onDownloadCatalogPackageStatusUpdated);
this.bindAction(CatalogPackageManagerActions.DOWNLOAD_CATALOG_PACKAGE_ERROR, this.onDownloadCatalogPackageError);
this.bindAction(CatalogPackageManagerActions.UPLOAD_CATALOG_PACKAGE, this.uploadCatalogPackage);
this.bindAction(CatalogPackageManagerActions.UPLOAD_CATALOG_PACKAGE_STATUS_UPDATED, this.onUploadCatalogPackageStatusUpdated);
this.bindAction(CatalogPackageManagerActions.UPLOAD_CATALOG_PACKAGE_ERROR, this.onUploadCatalogPackageError);
-
+ this.bindAction(CatalogPackageManagerActions.COPY_CATALOG_PACKAGE, this.copyCatalogPackage);
+ this.bindAction(CatalogPackageManagerActions.UPDATE_STATUS, this.updateOperationStatus);
}
- addPackage(catalogPackage) {
- const packages = [catalogPackage].concat(this.packages);
- this.setState({packages: packages});
+ addOperation(operation) {
+ const operations = [operation].concat(this.operations);
+ this.setState({operations});
}
- updatePackage(catalogPackage) {
- const packages = this.packages.map(d => {
- if (d.id === catalogPackage.id) {
- return Object.assign({}, d, catalogPackage);
+ updateOperation(operation) {
+ const operations = this.operations.map(d => {
+ if (d.id === operation.id) {
+ return Object.assign({}, d, operation);
}
return d;
});
- this.setState({packages: packages});
+ this.setState({operations});
+ }
+
+ removeCatalogOperation(operation) {
+ const operations = this.operations.filter(d => d.id !== operation.id);
+ this.setState({operations});
}
- removeCatalogPackage(catalogPackage) {
- const packages = this.packages.filter(d => d.id !== catalogPackage.id);
- this.setState({packages: packages});
+ copyCatalogPackage(sourcePackage) {
+ let operationInfo = Object.assign({}, defaults.operation);
+ operationInfo.name = "Duplication of " + sourcePackage.name;
+ operationInfo.id = guid();
+ operationInfo.icon = imgCopy;
+ operationInfo.type = 'copy';
+ operationInfo.message = 'Requesting package duplication.';
+ operationInfo.args.packageType = sourcePackage['uiState']['type'].toUpperCase();
+ operationInfo.args.id = sourcePackage.id;
+ operationInfo.args.name = sourcePackage.name + ' copy';
+
+ this.addOperation(operationInfo);
+ this.getInstance().requestCatalogPackageCopy(operationInfo, sourcePackage);
+ }
+
+ updateOperationStatus(operation) {
+ console.debug('package manager operation status update', operation);
+ this.updateOperation(operation);
+ if (operation.pending) {
+ delayStatusCheck(this.getInstance().requestCatalogPackageCopyStatus, operation);
+ }
}
uploadCatalogPackage(file) {
file.id = file.id || guid();
- const catalogPackage = _pick(file, packagePropertyNames);
- catalogPackage.icon = file.riftAction === 'onboard' ? imgOnboard : imgUpdate;
- catalogPackage.type = 'upload';
- this.addPackage(catalogPackage);
+ const operation = _pick(file, packagePropertyNames);
+ operation.icon = file.riftAction === 'onboard' ? imgOnboard : imgUpdate;
+ operation.type = 'upload';
+ this.addOperation(operation);
// note DropZone.js handles the async upload so we don't have to invoke any async action creators
}
onUploadCatalogPackageStatusUpdated(response) {
const upload = updateStatusInfo(response);
- this.updatePackage(upload);
+ this.updateOperation(upload);
console.log('updating package upload')
// if pending with no transaction id - do nothing
// bc DropZone.js will notify upload progress
onUploadCatalogPackageError(response) {
console.warn('onUploadCatalogPackageError', response);
- const catalogPackage = updateStatusInfo(response);
- this.updatePackage(catalogPackage);
+ const operation = updateStatusInfo(response);
+ this.updateOperation(operation);
}
downloadCatalogPackage(data) {
let grammar = data['selectedGrammar'] || 'osm';
let format = "YAML";
if (catalogItems.length) {
- const catalogPackage = Object.assign({}, defaults.downloadPackage, {id: guid()});
- catalogPackage.name = catalogItems[0].name;
- catalogPackage.type = 'download';
+ const operation = Object.assign({}, defaults.downloadPackage, {id: guid()});
+ operation.name = catalogItems[0].name;
+ operation.type = 'download';
if (catalogItems.length > 1) {
- catalogPackage.name += ' (' + catalogItems.length + ' items)';
+ operation.name += ' (' + catalogItems.length + ' items)';
}
- catalogPackage.ids = catalogItems.map(d => d.id).sort().toString();
- catalogPackage.catalogItems = catalogItems;
- this.addPackage(catalogPackage);
- this.getInstance().requestCatalogPackageDownload(catalogPackage, format, grammar, schema).catch(exception);
+ operation.ids = catalogItems.map(d => d.id).sort().toString();
+ operation.catalogItems = catalogItems;
+ this.addOperation(operation);
+ this.getInstance().requestCatalogPackageDownload(operation, format, grammar, schema).catch(exception);
}
}
onDownloadCatalogPackageStatusUpdated(response) {
const download = updateStatusInfo(response);
- this.updatePackage(download);
+ this.updateOperation(download);
if (download.pending) {
delayStatusCheck(this.getInstance().requestCatalogPackageDownloadStatus, download);
}
onDownloadCatalogPackageError(response) {
console.warn('onDownloadCatalogPackageError', response);
- const catalogPackage = updateStatusInfo(response);
- this.updatePackage(catalogPackage);
+ const operation = updateStatusInfo(response);
+ this.updateOperation(operation);
}
}
}
function updateStatusInfo(response) {
- // returns the catalogPackage object with the status fields updated based on the server response
+ // returns the operation object with the status fields updated based on the server response
const statusInfo = {
pending: false,
success: false,
error: false
};
const responseData = (response.data.output) ? response.data.output : response.data;
- const catalogPackage = response.state;
+ const operation = response.state;
if ( typeof response.data.status !== "number" ) {
switch(response.data.status) {
case 'upload-progress':
statusInfo.pending = true;
statusInfo.progress = parseFloat(responseData.progress) || 0;
- statusInfo.message = calculateUploadProgressMessage(catalogPackage.size, responseData.progress, responseData.bytesSent);
+ statusInfo.message = calculateUploadProgressMessage(operation.size, responseData.progress, responseData.bytesSent);
break;
case 'upload-success':
statusInfo.pending = true;
statusInfo.progress = 100;
statusInfo.message = 'Upload completed.';
- statusInfo.transactionId = responseData['transaction_id'] || responseData['transaction-id'] || catalogPackage.transactionId;
+ statusInfo.transactionId = responseData['transaction_id'] || responseData['transaction-id'] || operation.transactionId;
break;
case 'upload-error':
statusInfo.error = true;
case 'download-requested':
statusInfo.pending = true;
statusInfo.progress = 25;
- statusInfo.transactionId = responseData['transaction_id'] || responseData['transaction-id'] || catalogPackage.transactionId;
+ statusInfo.transactionId = responseData['transaction_id'] || responseData['transaction-id'] || operation.transactionId;
break;
case 'pending':
statusInfo.pending = true;
statusInfo.success = true;
statusInfo.progress = 100;
statusInfo.message = responseData.events[responseData.events.length - 1].text;
- if (catalogPackage.type === 'download') {
+ if (operation.type === 'download') {
statusInfo.urlValidUntil = moment().add(defaults.downloadUrlTimeToLiveInMinutes, 'minutes').toISOString();
if (responseData.filename) {
statusInfo.url = getCatalogPackageManagerServerOrigin() + '/api/export/' + responseData.filename;
} else {
- statusInfo.url = getCatalogPackageManagerServerOrigin() + '/api/export/' + catalogPackage.transactionId + '.tar.gz';
+ statusInfo.url = getCatalogPackageManagerServerOrigin() + '/api/export/' + operation.transactionId + '.tar.gz';
}
}
break;
statusInfo.error = true;
statusInfo.message = responseData.statusText || 'Error';
}
- return Object.assign({}, catalogPackage, statusInfo);
+ return Object.assign({}, operation, statusInfo);
}
export default alt.createStore(CatalogPackageManagerStore, 'CatalogPackageManagerStore');