Commit 056fe057 authored by hh1966's avatar hh1966
Browse files

Add polling for import

parent 9d46d5f3
......@@ -2,6 +2,10 @@ module Chemotion
class ImportAPI < Grape::API
resource :imports do
desc "Create export job"
params do
requires :file, type: File
end
post do
# create an id for the import
import_id = SecureRandom.uuid
......@@ -22,6 +26,26 @@ module Chemotion
# return the import_id to the client
return {:import_id => import_id}
end
desc "Poll import job"
params do
requires :id, type: String
end
get '/:id' do
import_id = params[:id]
# look for the lock file file
file_path = Import::ImportCollections.zip_file_path(import_id)
if File.exist?(file_path)
return {
:status => 'EXECUTING',
}
end
error! :not_found, 404
end
end
end
end
......@@ -209,7 +209,6 @@ class ElementActions {
}
importCollectionsFromFile(params) {
console.log(params);
return (dispatch) => { ImportCollectionsFetcher.createJob(params)
.then((result) => {
dispatch(result);
......
......@@ -9,6 +9,7 @@ import ModalImportChemScanner from './ModalImportChemScanner';
import ModalExport from './ModalExport';
import ModalReactionExport from './ModalReactionExport';
import ModalCollectionExport from './ModalCollectionExport';
import ModalImportCollection from './ModalImportCollection';
const ExportImportButton = ({ isDisabled, updateModalProps, customClass }) => (
<Dropdown id='export-dropdown'>
......@@ -128,7 +129,7 @@ const exportCollectionFunction = (updateModalProps) => {
const importCollectionFunction = (updateModalProps) => {
const title = "Import Collections from ZIP archive";
const component = ModalImport;
const component = ModalImportCollection;
const action = ElementActions.importCollectionsFromFile;
const listSharedCollections = false;
......
import React from 'react';
import {Button, ButtonToolbar, Radio, FormGroup} from 'react-bootstrap';
import PropTypes from 'prop-types';
import {Button, ButtonToolbar} from 'react-bootstrap';
import UIStore from './../stores/UIStore';
import UserStore from './../stores/UserStore';
import NotificationActions from '../actions/NotificationActions';
export default class ModalCollectionExport extends React.Component {
......@@ -44,7 +41,7 @@ export default class ModalCollectionExport extends React.Component {
onHide();
let notification = {
title: "Exporting",
title: "Export collections",
message: "The export file is created on the server. This might take a while. The download will start automatically. Please don't close the window.",
level: "warning",
dismissible: false,
......@@ -67,7 +64,3 @@ export default class ModalCollectionExport extends React.Component {
)
}
}
ModalCollectionExport.propTypes = {
onHide: PropTypes.func,
}
import React from 'react';
import {Button, ButtonToolbar} from 'react-bootstrap';
import Dropzone from 'react-dropzone';
import UIStore from '../stores/UIStore';
import NotificationActions from '../actions/NotificationActions';
export default class ModalImportCollection extends React.Component {
constructor(props) {
super(props);
this.state = {
file: null
};
}
handleClick() {
const {onHide, action} = this.props;
const {file} = this.state;
let ui_state = UIStore.getState();
let params = {
file: file
}
action(params);
onHide();
let notification = {
title: "Import collections",
message: "The file is uploaded to the server and your collections are imported into the database. This might take a while. Please don't close the window as long as this notification is visible.",
level: "warning",
dismissible: false,
uid: "import_collections",
position: "bl",
autoDismiss: null
}
NotificationActions.add(notification);
}
handleFileDrop(attachment_file) {
this.setState({file: attachment_file[0]});
}
handleAttachmentRemove() {
this.setState({file: null});
}
dropzoneOrfilePreview() {
const {file} = this.state;
if (file) {
return (
<div>
{file.name}
<Button bsSize="xsmall" bsStyle="danger" onClick={() => this.handleAttachmentRemove()} className="pull-right">
<i className="fa fa-trash-o"></i>
</Button>
</div>
);
} else {
return (
<Dropzone
onDrop={attachment_file => this.handleFileDrop(attachment_file)}
style={{height: 50, width: '100%', border: '3px dashed lightgray'}}
>
<div style={{textAlign: 'center', paddingTop: 12, color: 'gray'}}>
Drop File, or Click to Select.
</div>
</Dropzone>
);
}
}
isDisabled() {
const {file} = this.state;
return file == null
}
render() {
const {onHide} = this.props;
return (
<div>
{this.dropzoneOrfilePreview()}
&nbsp;
<ButtonToolbar>
<Button bsStyle="primary" onClick={() => onHide()}>Cancel</Button>
<Button bsStyle="warning" onClick={() => this.handleClick()} disabled={this.isDisabled()}>Import</Button>
</ButtonToolbar>
</div>
)
}
}
......@@ -45,7 +45,7 @@ export default class ExportCollectionsFetcher {
// continue polling
setTimeout(() => {
ExportCollectionsFetcher.pollJob(exportId);
}, 4000);
}, 1000);
} else if (json.status == 'COMPLETED') {
// remove the notification
NotificationActions.removeByUid('export_collections')
......
import 'whatwg-fetch';
import CollectionActions from '../actions/CollectionActions';
import NotificationActions from '../actions/NotificationActions';
export default class ImportCollectionsFetcher {
......@@ -14,11 +16,12 @@ export default class ImportCollectionsFetcher {
}).then((response) => {
return response.json()
}).then((json) => {
console.log('ok!');
// // after a short delay, start polling
// setTimeout(() => {
// ExportFetcher.pollJob(json.job_id)
// }, 1000);
// after a short delay, start polling
setTimeout(() => {
ImportCollectionsFetcher.pollJob(json.import_id)
}, 1000);
return json;
}).catch((errorMessage) => {
console.log(errorMessage);
});
......@@ -26,31 +29,34 @@ export default class ImportCollectionsFetcher {
return promise;
}
// static pollJob(jobId) {
// let promise = fetch(`/api/v1/imports/${jobId}`, {
// credentials: 'same-origin',
// method: 'GET',
// headers: {
// 'Accept': 'application/json',
// 'Content-Type': 'application/json'
// }
// }).then((response) => {
// return response.json()
// }).then((json) => {
// if (json.status == 'EXECUTING') {
// // continue polling
// setTimeout(() => {
// ExportFetcher.pollJob(jobId);
// }, 4000);
// } else if (json.status == 'COMPLETED') {
// // download the file, headers will prevent the browser from reloading the page
// window.location.href = json.url;
// }
// }).catch((errorMessage) => {
// console.log(errorMessage);
// });
// return promise;
// }
static pollJob(importId) {
let promise = fetch(`/api/v1/imports/${importId}`, {
credentials: 'same-origin',
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
}).then((response) => {
return response.json()
}).then((json) => {
if (json.status == 'EXECUTING') {
// continue polling
setTimeout(() => {
ImportCollectionsFetcher.pollJob(importId);
}, 1000);
} else {
// remove the notification
NotificationActions.removeByUid('import_collections')
// reload the unshared collections
CollectionActions.fetchUnsharedCollectionRoots()
}
}).catch((errorMessage) => {
console.log(errorMessage);
});
return promise;
}
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment