Skip to content
Snippets Groups Projects
Commit 5a3321d3 authored by Antoine Detailleur's avatar Antoine Detailleur
Browse files

[NRRPLT-8094] import experiments and scan storage buttons with new...

[NRRPLT-8094] import experiments and scan storage buttons with new architecture for the services (but not functional)
parent 63ccbdd7
No related branches found
No related tags found
No related merge requests found
......@@ -8,6 +8,7 @@ li.nostyle {
grid-template-rows: auto;
grid-template-columns: auto;
grid-template-areas:
"import-experiments"
"experiments";
}
......@@ -18,6 +19,10 @@ li.nostyle {
background-color: white;
}
.import-experiments {
grid-area: import-experiments;
}
.no-items-notification {
margin: 10px;
font-size: 1.5em;
......
import React from 'react';
import ImportExperimentButtons from '../experiment-list/import-experiment-buttons.js';
import ExperimentListElement from './experiment-list-element.js';
import ImportExperimentButtons from './import-experiment-buttons.js';
import './experiment-list.css';
......@@ -9,6 +9,9 @@ export default class ExperimentList extends React.Component {
render() {
return (
<div className='experiment-list-wrapper'>
<div className='import-experiment'>
<ImportExperimentButtons />
</div>
<div className='experiment-list'>
{this.props.experiments.length === 0 ?
<div className='no-items-notification'>List is currently empty ...</div> :
......
import React from 'react';
import ExperimentStorageService from '../../services/experiments/storage/experiment-storage-service.js';
import ImportExperimentService from '../../services/experiments/storage/import-experiment-service.js';
import { FaFolder, FaFileArchive, FaAudible } from 'react-icons/fa';
import './experiment-list-element.css';
import './import-experiment-buttons.css';
class ImportExperimentButtons extends React.Component {
export default class ImportExperimentButtons extends React.Component {
constructor(props) {
super(props);
this.state = {};
......@@ -29,45 +29,34 @@ class ImportExperimentButtons extends React.Component {
});
}
importExperimentFolderChange(e) {
importExperimentFolderChange(event) {
this.setState({
isImporting : true
});
let ExperimentStorage = ExperimentStorageService.instance;
ExperimentStorage
.importExperimentFolder(e)
ImportExperimentService.instance
.importExperimentFolder(event)
.then(response => {
this.setState({
importFolderResponse : response
});
ExperimentStorage.getExperiments(true);
})
.finally(() => {
if (this.state.importExperimentFolderInput){
// Allows to re-import the same zip file
let items = [...this.state.importExperimentFolderInput];
let item = {...items[0]};
item.value = '';
items[0] = item;
}
this.setState({
isImporting : false
});
});
};
importZippedExperimentChange(e) {
importZippedExperimentChange(event) {
this.setState({
isImporting : true
});
let ExperimentStorage = ExperimentStorageService.instance;
ExperimentStorage
.importZippedExperiment(e)
ImportExperimentService.instance
.importZippedExperiment(event)
.then(responses => {
this.setState({
importZipResponses : responses
});
ExperimentStorage.getExperiments(true);
})
.finally(() => {
this.setState({
......@@ -80,14 +69,12 @@ class ImportExperimentButtons extends React.Component {
this.setState({
isImporting : true
});
let ExperimentStorage = ExperimentStorageService.instance;
ExperimentStorage
ImportExperimentService.instance
.scanStorage()
.then(response => {
this.setState({
scanStorageResponse : response
});
ExperimentStorage.getExperiments(true);
})
.finally(() => {
this.setState({
......@@ -159,10 +146,10 @@ class ImportExperimentButtons extends React.Component {
<div className="list-entry-buttons flex-container center">
<input id="folder" type="file" style={{display:'none'}}
multiple directory="" webkitdirectory=""
onChange={(e) => this.importExperimentFolderChange(e)}/>
onChange={(event) => this.importExperimentFolderChange(event)}/>
<input id="zip" type="file" style={{display:'none'}}
multiple webkitdirectory directory accept='.zip'
onChange={(e) => this.importZippedExperimentChange(e)}/>
onChange={(event) => this.importZippedExperimentChange(event)}/>
{!this.state.isImporting
? <div className="btn-group" role="group">
<button>
......@@ -185,5 +172,3 @@ class ImportExperimentButtons extends React.Component {
);
}
}
\ No newline at end of file
export default ImportExperimentButtons;
\ No newline at end of file
import JSZip from 'jszip';
import { HttpService } from '../../http-service.js';
import ErrorHandlingService from '../../error-handler-service.js';
import endpoints from '../../proxy/data/endpoints.json';
import config from '../../../config.json';
const storageExperimentsURL = `${config.api.proxy.url}${endpoints.proxy.storage.experiments.url}`;
const storageScanStorage = `${config.api.proxy.url}${endpoints.proxy.storage.scanStorage.url}`;
const storageImportExperiment = `${config.api.proxy.url}${endpoints.proxy.storage.importExperiment.url}`;
let _instance = null;
const SINGLETON_ENFORCER = Symbol();
......
import { HttpService } from '../../http-service.js';
import ErrorHandlerService from '../../error-handler-service.js';
import JSZip from 'jszip';
import endpoints from '../../proxy/data/endpoints.json';
import config from '../../../config.json';
const importExperimentURL = `${config.api.proxy.url}${endpoints.proxy.storage.importExperiment.url}`;
const scanStorageURL = `${config.api.proxy.url}${endpoints.proxy.storage.scanStorage.url}`;
let _instance = null;
const SINGLETON_ENFORCER = Symbol();
export default class ImportExperimentService extends HttpService {
constructor(enforcer) {
super();
if (enforcer !== SINGLETON_ENFORCER) {
throw new Error('Use ' + this.constructor.name + '.instance');
}
}
static get instance() {
if (_instance == null) {
_instance = new ImportExperimentService(SINGLETON_ENFORCER);
}
return _instance;
}
getImportZipResponses(responses) {
let importZipResponses = {};
importZipResponses.numberOfZips = responses.length;
['zipBaseFolderName', 'destFolderName'].forEach(name => {
importZipResponses[name] = responses
.map(response => response[name])
.join(', ');
});
return importZipResponses;
}
getScanStorageResponse(response) {
let scanStorageResponse = {};
['deletedFolders', 'addedFolders'].forEach(name => {
scanStorageResponse[`${name}Number`] = response[name].length;
scanStorageResponse[name] = response[name].join(', ');
});
return scanStorageResponse;
}
scanStorage() {
return this.httpRequestPOST(scanStorageURL)
.then(this.getScanStorageResponse)
.catch(ErrorHandlerService.instance.displayError({
type: 'Import Error.'
}));
}
zipExperimentFolder(event) {
let zip = new JSZip();
let files = event.target.files;
if (files.length === 0){
return; // The folder upload was aborted by user
}
let promises = [];
Array.from(files).forEach(file => {
promises.push(
new Promise((resolve, reject) => {
let reader = new FileReader();
reader.onerror = error => {
reader.abort();
return reject(error);
};
reader.onload = f =>
resolve([file.webkitRelativePath, f.target.result]);
if (
file.type.startsWith('image') ||
file.type === 'application/zip' ||
file.webkitRelativePath.split('.').pop() === 'h5'
) {
reader.readAsArrayBuffer(file);
}
else {
reader.readAsText(file);
}
})
.then(([filepath, filecontent]) =>
Promise.resolve(
zip.file(filepath, filecontent, { createFolders: true })
)
)
.catch(error => {
ErrorHandlerService.instance.displayError(error);
return Promise.reject(error);
})
);
});
return Promise.all(promises)
.then(() => zip.generateAsync({ type: 'blob' }))
.catch(error => {
ErrorHandlerService.instance.displayError(error);
return Promise.reject(error);
});
}
importExperimentFolder(event) {
return this.zipExperimentFolder(event).then(zipContent => {
return this.httpRequestPOST(importExperimentURL, zipContent)
.catch(ErrorHandlerService.instance
.displayError({
type: 'Import Error.'
})
);
});
}
readZippedExperimentExperiment(event) {
let files = event.target.files;
let zipFiles = [];
Array.from(files).forEach(file => {
if (file.type !== 'application/zip') {
ErrorHandlerService.instance.displayError({
type: 'Import Error.',
message:`The file ${file.name} cannot be imported because it is not a zip file.`
});
}
else {
zipFiles.push(file);
}
});
let promises = zipFiles.map(zipFile => {
return new Promise(resolve => {
let reader = new FileReader();
reader.onload = f => resolve(f.target.result);
reader.readAsArrayBuffer(zipFile);
});
});
return Promise.all(promises);
}
importZippedExperiment(event) {
let promises = this.readZippedExperimentExperiment(event)
.then(zipContents =>
zipContents.map(zipContent =>
this.httpRequestPOST(importExperimentURL, zipContent).catch(error => {
ErrorHandlerService.instance.displayError(error);
return Promise.reject(error);
})
)
)
.then(responses =>
Promise
.all(responses)
.then(responses => this.getImportZipResponses(responses))
);
return promises;
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment