Select Git revision
CentroidFunction.java
-
gmantele authored
[ADQL,TAP] Add STC-S and UDFs support in the ADQL parser. Now, it is possible to provide a list of allowed UDFs, regions and coordinate systems. The ServiceConnection of TAP is now able to provide these lists and to propagate them to the ADQLExecutor. UDFs and allowed regions are now listed automatically in the /capabilities resource of TAP. The type 'geometry' is now fully supported in ADQL. That's why the new function 'isGeometry()' has been added to all ADQLOperand extensions. Now the DBChecker is also able to check roughly types of columns and UDFs (unknown when parsing syntactically a query). The syntax of STC-S regions (expressed in the REGION function) are now checked by DBChecker. However, for the moment, geometries are not serialized in STC-S in the output....but it should be possible in some way in the next commit(s).
gmantele authored[ADQL,TAP] Add STC-S and UDFs support in the ADQL parser. Now, it is possible to provide a list of allowed UDFs, regions and coordinate systems. The ServiceConnection of TAP is now able to provide these lists and to propagate them to the ADQLExecutor. UDFs and allowed regions are now listed automatically in the /capabilities resource of TAP. The type 'geometry' is now fully supported in ADQL. That's why the new function 'isGeometry()' has been added to all ADQLOperand extensions. Now the DBChecker is also able to check roughly types of columns and UDFs (unknown when parsing syntactically a query). The syntax of STC-S regions (expressed in the REGION function) are now checked by DBChecker. However, for the moment, geometries are not serialized in STC-S in the output....but it should be possible in some way in the next commit(s).
uploadsManager.js 6.38 KiB
/*
* This file is part of vospace-ui
* Copyright (C) 2021 Istituto Nazionale di Astrofisica
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import Vue from 'vue';
import client from 'api-client';
function resetArray(array) {
array.splice(0, array.length);
}
export default {
state: {
files: [], // array of selected files
progress: [], // array of upload progress percentages (for tracking upload progress)
cancellations: [], // array of axios cancel tokens (for aborting uploads)
deletionStatuses: [], // status of upload deletions (true if request is being aborted, false otherwise)
errors: [], // errors happened during downloads
creatingMetadata: false, // true when nodes metadata is being created (pre-upload phase)
uploadInProgress: false, // true when data is being uploaded
},
mutations: {
setFilesToUpload(state, files) {
state.files = files;
},
resetUploadState(state) {
resetArray(state.progress);
resetArray(state.cancellations);
resetArray(state.deletionStatuses);
resetArray(state.errors);
},
setDeletion(state, data) {
Vue.set(state.deletionStatuses, data.index, data.value);
},
setProgress(state, data) {
Vue.set(state.progress, data.index, data.percent);
},
setCreatingMetadata(state, value) {
state.creatingMetadata = value;
},
setUploadInProgress(state, value) {
state.uploadInProgress = value;
},
setPreUploadResults(state, preUploadResults) {
for (let result of preUploadResults) {
if (Object.keys(result).includes('request')) {
state.cancellations.push(result.source); // axios cancellation token
state.deletionStatuses.push(null);
state.errors.push(null);
} else {
state.cancellations.push(null);
state.deletionStatuses.push(null);
state.errors.push(result);
}
}
state.uploadInProgress = true;
},
setError(state, data) {
Vue.set(state.errors, data.index, data.error);
}
},
actions: {
upload({ state, rootState, commit, dispatch }, bvModal) {
// Progress bars initialization
for (let index = 0; index < state.files.length; index++) {
let file = state.files[index];
let reader = new FileReader();
reader.addEventListener('progress', (event) => {
if (event.loaded && event.total) {
let percent = (event.loaded / event.total) * 100;
commit('setProgress', { index, percent });
}
});
reader.readAsDataURL(file);
}
commit('setCreatingMetadata', true);
// Create nodes metadata and obtain upload URLs
dispatch('prepareUpload')
.then((preUploadResults) => {
commit('setCreatingMetadata', false);
let promises = [];
for (let result of preUploadResults) {
if (Object.keys(result).includes('request')) {
promises.push(result.request); // upload http promise
} else {
// fictitious promise for failed pre-upload event
promises.push(new Promise(resolve => resolve()));
}
}
commit('setPreUploadResults', preUploadResults);
// wait until all downloads have been completed (both successfully or not)
return Promise.allSettled(promises);
})
.then((responses) => {
let deletionPromises = [];
for (let index = 0; index < responses.length; index++) {
let error = state.errors[index];
let response = responses[index];
if (response.status === 'fulfilled' && error === null) {
commit('setProgress', { index, percent: 100 });
} else {
if (state.deletionStatuses[index] || error === null) {
// delete node metadata both when user aborted the upload and when it failed
deletionPromises.push(client.deleteNodes(['/' + rootState.path + '/' + state.files[index].name], true));
if (state.deletionStatuses[index] === null) {
// e.g. server became unreachable during the upload
commit('setError', { index, error: 'Unable to upload file' });
}
}
}
}
// if there are some deletion promises, wait them
return Promise.allSettled(deletionPromises);
})
.then(deletionResults => {
// verify if metadata of aborted uploads has been correctly removed
let resultIndex = 0;
for (let i = 0; i < state.deletionStatuses.length; i++) {
let deletionStatus = state.deletionStatuses[i];
if (deletionStatus !== null) {
let deletionResult = deletionResults[resultIndex];
if (deletionResult.status === 'fulfilled') {
commit('setDeletion', { index: i, value: false });
} else {
commit('setError', { index: i, error: 'Failed to delete node metadata. Manual cleanup may be required.' });
}
resultIndex++;
}
}
})
.finally(() => {
// Reload current node when all uploads completed
dispatch('setPath', rootState.path);
commit('setCreatingMetadata', false);
commit('setUploadInProgress', false);
let hasErrors = state.errors.filter(e => e !== null).length > 0;
if (!hasErrors) {
bvModal.hide('upload-files-modal');
}
});
},
prepareUpload({ state, rootState }) {
let names = [];
for (let file of state.files) {
names.push(file.name);
}
return new Promise((resolve, reject) => {
client.prepareForUpload(rootState.path, names)
.then(preUploadResponses => {
let uploads = [];
for (let i = 0; i < state.files.length; i++) {
let uploadUrl = preUploadResponses[i].url;
if (uploadUrl !== null) {
uploads.push(client.uploadFile(uploadUrl, state.files[i]));
} else {
uploads.push(preUploadResponses[i].error);
}
}
resolve(uploads);
})
.catch(error => reject(error));
});
},
cancelUpload({ state, commit }, index) {
commit('setDeletion', { index, value: true });
state.cancellations[index].cancel();
}
}
}