1
0
mirror of https://github.com/ascribe/onion.git synced 2024-12-23 01:39:36 +01:00

Implement lazy blob creation routine and increase robustness of upload button template for react-fineuploader

This commit is contained in:
Tim Daubenschütz 2015-11-09 16:58:35 +01:00
parent 3e22ad1d9d
commit deceb61c60
3 changed files with 135 additions and 83 deletions

View File

@ -2,6 +2,8 @@
import React from 'react'; import React from 'react';
import Glyphicon from 'react-bootstrap/lib/Glyphicon';
import ReactS3FineUploader from '../ascribe_uploader/react_s3_fine_uploader'; import ReactS3FineUploader from '../ascribe_uploader/react_s3_fine_uploader';
import UploadButton from '../ascribe_uploader/ascribe_upload_button/upload_button'; import UploadButton from '../ascribe_uploader/ascribe_upload_button/upload_button';
@ -29,24 +31,41 @@ const UploadFileButton = React.createClass({
fileClassToUpload: shape({ fileClassToUpload: shape({
singular: string, singular: string,
plural: string plural: string
}).isRequired }).isRequired,
createBlobRoutine: shape({
url: string,
pieceId: number
})
}, },
submitFile(file) { getInitialState() {
console.log(file); return {
file: null
};
},
handleSubmitFile(file) {
this.setState({
file
});
},
createBlobRoutine() {
const { fineuploader } = this.refs;
const { file } = this.state;
fineuploader.createBlob(file);
}, },
render() { render() {
const { fileClassToUpload, validation, keyRoutine, createBlobRoutine } = this.props;
const { fileClassToUpload, validation, keyRoutine } = this.props;
return ( return (
<ReactS3FineUploader <ReactS3FineUploader
ref="fineuploader"
fileInputElement={UploadButton} fileInputElement={UploadButton}
keyRoutine={keyRoutine} keyRoutine={keyRoutine}
createBlobRoutine={{ createBlobRoutine={createBlobRoutine}
url: ApiUrls.blob_contracts
}}
validation={validation} validation={validation}
setIsUploadReady={() =>{/* So that ReactS3FineUploader is not complaining */}} setIsUploadReady={() =>{/* So that ReactS3FineUploader is not complaining */}}
signature={{ signature={{
@ -65,7 +84,7 @@ const UploadFileButton = React.createClass({
}} }}
fileClassToUpload={fileClassToUpload} fileClassToUpload={fileClassToUpload}
isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile} isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}
submitFile={this.submitFile} submitFile={this.handleSubmitFile}
location={this.props.location}/> location={this.props.location}/>
); );
} }

View File

@ -2,8 +2,11 @@
import React from 'react'; import React from 'react';
import Glyphicon from 'react-bootstrap/lib/Glyphicon';
import { displayValidProgressFilesFilter } from '../react_s3_fine_uploader_utils'; import { displayValidProgressFilesFilter } from '../react_s3_fine_uploader_utils';
import { getLangText } from '../../../utils/lang_utils'; import { getLangText } from '../../../utils/lang_utils';
import { truncateTextAtCharIndex } from '../../../utils/general_utils';
let UploadButton = React.createClass({ let UploadButton = React.createClass({
@ -37,6 +40,10 @@ let UploadButton = React.createClass({
return this.props.filesToUpload.filter((file) => file.status === 'uploading'); return this.props.filesToUpload.filter((file) => file.status === 'uploading');
}, },
getUploadedFile() {
return this.props.filesToUpload.filter((file) => file.status === 'upload successful')[0];
},
handleOnClick() { handleOnClick() {
let uploadingFiles = this.getUploadingFiles(); let uploadingFiles = this.getUploadingFiles();
@ -57,14 +64,22 @@ let UploadButton = React.createClass({
}, },
getButtonLabel() { getButtonLabel() {
const uploadedFile = this.getUploadedFile();
let { filesToUpload, fileClassToUpload } = this.props; let { filesToUpload, fileClassToUpload } = this.props;
// filter invalid files that might have been deleted or canceled... // filter invalid files that might have been deleted or canceled...
filesToUpload = filesToUpload.filter(displayValidProgressFilesFilter); filesToUpload = filesToUpload.filter(displayValidProgressFilesFilter);
// Depending on wether there is an upload going on or not we // Depending on whether there is an upload going on or not we
// display the progress // display the progress or the successfully uploaded file's name
if(filesToUpload.length > 0) { if(uploadedFile) {
return (
<span>
<Glyphicon glyph="ok" />
{' ' + truncateTextAtCharIndex(uploadedFile.name, 20)}
</span>
);
} else if(filesToUpload.length > 0) {
return getLangText('Upload progress') + ': ' + Math.ceil(filesToUpload[0].progress) + '%'; return getLangText('Upload progress') + ': ' + Math.ceil(filesToUpload[0].progress) + '%';
} else { } else {
return fileClassToUpload.singular; return fileClassToUpload.singular;
@ -74,7 +89,6 @@ let UploadButton = React.createClass({
render() { render() {
let { let {
multiple, multiple,
fileClassToUpload,
allowedExtensions allowedExtensions
} = this.props; } = this.props;
@ -82,7 +96,7 @@ let UploadButton = React.createClass({
<button <button
onClick={this.handleOnClick} onClick={this.handleOnClick}
className="btn btn-default btn-sm margin-left-2px" className="btn btn-default btn-sm margin-left-2px"
disabled={this.getUploadingFiles().length !== 0}> disabled={this.getUploadingFiles().length !== 0 || !!this.getUploadedFile()}>
{this.getButtonLabel()} {this.getButtonLabel()}
<input <input
multiple={multiple} multiple={multiple}

View File

@ -308,8 +308,15 @@ let ReactS3FineUploader = React.createClass({
}, },
createBlob(file) { createBlob(file) {
const { createBlobRoutine } = this.props;
// returning here without doing anything enables us to
// lazy create the blob at any time after the upload
if(!createBlobRoutine) {
return null;
} else {
return Q.Promise((resolve, reject) => { return Q.Promise((resolve, reject) => {
window.fetch(this.props.createBlobRoutine.url, { window.fetch(createBlobRoutine.url, {
method: 'post', method: 'post',
headers: { headers: {
'Accept': 'application/json', 'Accept': 'application/json',
@ -320,7 +327,7 @@ let ReactS3FineUploader = React.createClass({
body: JSON.stringify({ body: JSON.stringify({
'filename': file.name, 'filename': file.name,
'key': file.key, 'key': file.key,
'piece_id': this.props.createBlobRoutine.pieceId 'piece_id': createBlobRoutine.pieceId
}) })
}) })
.then((res) => { .then((res) => {
@ -336,6 +343,9 @@ let ReactS3FineUploader = React.createClass({
} else if(res.contractblob) { } else if(res.contractblob) {
file.s3Url = res.contractblob.url_safe; file.s3Url = res.contractblob.url_safe;
file.s3UrlSafe = res.contractblob.url_safe; file.s3UrlSafe = res.contractblob.url_safe;
} else if(res.thumbnail) {
file.s3Url = res.thumbnail.url_safe;
file.s3UrlSafe = res.thumbnail.url_safe;
} else { } else {
throw new Error(getLangText('Could not find a url to download.')); throw new Error(getLangText('Could not find a url to download.'));
} }
@ -349,6 +359,7 @@ let ReactS3FineUploader = React.createClass({
reject(err); reject(err);
}); });
}); });
}
}, },
/* FineUploader specific callback function handlers */ /* FineUploader specific callback function handlers */
@ -404,6 +415,14 @@ let ReactS3FineUploader = React.createClass({
let filesToUpload = React.addons.update(this.state.filesToUpload, { $set: files }); let filesToUpload = React.addons.update(this.state.filesToUpload, { $set: files });
this.setState({ filesToUpload }); this.setState({ filesToUpload });
const createBlobResult = this.createBlob(files[id]);
if(!createBlobResult) {
if(this.props.submitFile) {
this.props.submitFile(files[id]);
} else {
console.warn('You didn\'t define submitFile in as a prop in react-s3-fine-uploader');
}
} else {
// Only after the blob has been created server-side, we can make the form submittable. // Only after the blob has been created server-side, we can make the form submittable.
this.createBlob(files[id]) this.createBlob(files[id])
.then(() => { .then(() => {
@ -414,7 +433,6 @@ let ReactS3FineUploader = React.createClass({
} else { } else {
console.warn('You didn\'t define submitFile in as a prop in react-s3-fine-uploader'); console.warn('You didn\'t define submitFile in as a prop in react-s3-fine-uploader');
} }
// for explanation, check comment of if statement above // for explanation, check comment of if statement above
if(this.props.isReadyForFormSubmission && this.props.setIsUploadReady) { if(this.props.isReadyForFormSubmission && this.props.setIsUploadReady) {
// also, lets check if after the completion of this upload, // also, lets check if after the completion of this upload,
@ -438,6 +456,7 @@ let ReactS3FineUploader = React.createClass({
GlobalNotificationActions.appendGlobalNotification(notification); GlobalNotificationActions.appendGlobalNotification(notification);
}); });
} }
}
}, },
onError(id, name, errorReason) { onError(id, name, errorReason) {