1
0
mirror of https://github.com/ascribe/onion.git synced 2024-11-15 01:25:17 +01:00

Refactor UploadButton to resemble HTML5 file chooser input

This commit is contained in:
Tim Daubenschütz 2015-11-12 14:18:08 +01:00
parent d1b931715d
commit 45d5821abb
3 changed files with 130 additions and 113 deletions

View File

@ -56,7 +56,7 @@ let ContractSettingsUpdateButton = React.createClass({
render() {
return (
<ReactS3FineUploader
fileInputElement={UploadButton()}
fileInputElement={UploadButton}
keyRoutine={{
url: AppConstants.serverUrl + 's3/key/',
fileClass: 'contract'

View File

@ -8,119 +8,132 @@ import { displayValidProgressFilesFilter } from '../react_s3_fine_uploader_utils
import { getLangText } from '../../../utils/lang_utils';
import { truncateTextAtCharIndex } from '../../../utils/general_utils';
const { func, array, bool, shape, string } = React.PropTypes;
export default function UploadButton(label) {
return React.createClass({
propTypes: {
onDrop: React.PropTypes.func.isRequired,
filesToUpload: React.PropTypes.array,
multiple: React.PropTypes.bool,
let UploadButton = React.createClass({
propTypes: {
onDrop: func.isRequired,
filesToUpload: array,
multiple: bool,
// For simplification purposes we're just going to use this prop as a
// label for the upload button
fileClassToUpload: React.PropTypes.shape({
singular: React.PropTypes.string,
plural: React.PropTypes.string
}),
// For simplification purposes we're just going to use this prop as a
// label for the upload button
fileClassToUpload: shape({
singular: string,
plural: string
}),
allowedExtensions: React.PropTypes.string
},
allowedExtensions: string,
handleDrop(event) {
event.preventDefault();
event.stopPropagation();
let files = event.target.files;
handleCancelFile: func // provided by ReactS3FineUploader
},
if(typeof this.props.onDrop === 'function' && files) {
this.props.onDrop(files);
}
handleDrop(event) {
event.preventDefault();
event.stopPropagation();
let files = event.target.files;
},
if(typeof this.props.onDrop === 'function' && files) {
this.props.onDrop(files);
}
getUploadingFiles() {
return this.props.filesToUpload.filter((file) => file.status === 'uploading');
},
},
getUploadedFile() {
return this.props.filesToUpload.filter((file) => file.status === 'upload successful')[0];
},
getUploadingFiles() {
return this.props.filesToUpload.filter((file) => file.status === 'uploading');
},
handleOnClick() {
let uploadingFiles = this.getUploadingFiles();
getUploadedFile() {
return this.props.filesToUpload.filter((file) => file.status === 'upload successful')[0];
},
handleOnClick() {
const uploadingFiles = this.getUploadingFiles();
const uploadedFile = this.getUploadedFile();
if(uploadedFile) {
this.props.handleCancelFile(uploadedFile.id);
}
if(uploadingFiles.length === 0) {
// We only want the button to be clickable if there are no files currently uploading
if(uploadingFiles.length === 0) {
// Firefox only recognizes the simulated mouse click if bubbles is set to true,
// but since Google Chrome propagates the event much further than needed, we
// need to stop propagation as soon as the event is created
var evt = new MouseEvent('click', {
view: window,
bubbles: true,
cancelable: true
});
evt.stopPropagation();
this.refs.fileinput.getDOMNode().dispatchEvent(evt);
}
},
// Firefox only recognizes the simulated mouse click if bubbles is set to true,
// but since Google Chrome propagates the event much further than needed, we
// need to stop propagation as soon as the event is created
var evt = new MouseEvent('click', {
view: window,
bubbles: true,
cancelable: true
});
getButtonLabel() {
const uploadedFile = this.getUploadedFile();
let { filesToUpload, fileClassToUpload } = this.props;
evt.stopPropagation();
this.refs.fileinput.getDOMNode().dispatchEvent(evt);
}
},
// filter invalid files that might have been deleted or canceled...
filesToUpload = filesToUpload.filter(displayValidProgressFilesFilter);
getButtonLabel() {
let { filesToUpload, fileClassToUpload } = this.props;
// Depending on whether there is an upload going on or not we
// display the progress or the successfully uploaded file's name
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) + '%';
} else {
return fileClassToUpload.singular;
}
},
// filter invalid files that might have been deleted or canceled...
filesToUpload = filesToUpload.filter(displayValidProgressFilesFilter);
render() {
let {
multiple,
allowedExtensions
} = this.props;
if(this.getUploadingFiles().length !== 0) {
return getLangText('Upload progress') + ': ' + Math.ceil(filesToUpload[0].progress) + '%';
} else {
return fileClassToUpload.singular;
}
},
/*
* We do not want a button that submits here.
* As UploadButton could be used in forms that want to be submitted independent
* of clicking the selector.
* Therefore the wrapping component needs to be an `anchor` tag instead of a `button`
*/
getUploadedFileLabel() {
const uploadedFile = this.getUploadedFile();
if(uploadedFile) {
return (
<div className="upload-button-wrapper">
<a
onClick={this.handleOnClick}
className="btn btn-default btn-sm margin-left-2px"
disabled={this.getUploadingFiles().length !== 0 || !!this.getUploadedFile()}>
{this.getButtonLabel()}
<input
multiple={multiple}
ref="fileinput"
type="file"
style={{
display: 'none',
height: 0,
width: 0
}}
onChange={this.handleDrop}
accept={allowedExtensions}/>
</a>
{label}
</div>
<span>
<Glyphicon glyph="ok" />
{' ' + truncateTextAtCharIndex(uploadedFile.name, 20)}
</span>
);
} else {
return (
<span>{getLangText('No file chosen')}</span>
);
}
});
}
},
render() {
let { multiple,
allowedExtensions } = this.props;
/*
* We do not want a button that submits here.
* As UploadButton could be used in forms that want to be submitted independent
* of clicking the selector.
* Therefore the wrapping component needs to be an `anchor` tag instead of a `button`
*/
return (
<div className="upload-button-wrapper">
<a
onClick={this.handleOnClick}
className="btn btn-default btn-sm margin-left-2px"
disabled={this.getUploadingFiles().length !== 0}>
{this.getButtonLabel()}
<input
multiple={multiple}
ref="fileinput"
type="file"
style={{
display: 'none',
height: 0,
width: 0
}}
onChange={this.handleDrop}
accept={allowedExtensions}/>
</a>
{this.getUploadedFileLabel()}
</div>
);
}
});
export default UploadButton;

View File

@ -249,9 +249,10 @@ const PRRegisterPieceForm = React.createClass({
className="ascribe-form-bordered"
ref="uploadersForm">
<Property
name="digitalWorkKey">
name="digitalWorkKey"
label={getLangText('Select the PDF with your work')}>
<InputFineuploader
fileInputElement={UploadButton(<span>{getLangText('Select the PDF with your work')}</span>)}
fileInputElement={UploadButton}
isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}
setIsUploadReady={this.setIsUploadReady('digitalWorkKeyReady')}
createBlobRoutine={{
@ -268,15 +269,16 @@ const PRRegisterPieceForm = React.createClass({
}}
location={location}
fileClassToUpload={{
singular: getLangText('Upload the Portfolio'),
plural: getLangText('Upload the Portfolios')
singular: getLangText('Select the Portfolio'),
plural: getLangText('Select the Portfolios')
}}
required/>
</Property>
<Property
name="thumbnailKey">
name="thumbnailKey"
label={getLangText('Featured Cover photo')}>
<InputFineuploader
fileInputElement={UploadButton(<span>{getLangText('Featured Cover photo')}</span>)}
fileInputElement={UploadButton}
createBlobRoutine={{
url: ApiUrls.blob_thumbnails
}}
@ -293,15 +295,16 @@ const PRRegisterPieceForm = React.createClass({
}}
location={location}
fileClassToUpload={{
singular: getLangText('Upload cover photo'),
plural: getLangText('Upload cover photos')
singular: getLangText('Select cover photo'),
plural: getLangText('Select cover photos')
}}
required/>
</Property>
<Property
name="supportingMaterials">
name="supportingMaterials"
label={getLangText('Supporting Materials (Optional)')}>
<InputFineuploader
fileInputElement={UploadButton(<span>{getLangText('Supporting Materials (Optional)')}</span>)}
fileInputElement={UploadButton}
isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}
setIsUploadReady={this.setIsUploadReady('supportingMaterialsReady')}
createBlobRoutine={this.getCreateBlobRoutine()}
@ -315,14 +318,15 @@ const PRRegisterPieceForm = React.createClass({
}}
location={location}
fileClassToUpload={{
singular: getLangText('Upload supporting material'),
plural: getLangText('Upload supporting materials')
singular: getLangText('Select supporting material'),
plural: getLangText('Select supporting materials')
}}/>
</Property>
<Property
name="proofOfPayment">
name="proofOfPayment"
label={getLangText('Proof of payment')}>
<InputFineuploader
fileInputElement={UploadButton(<span>{getLangText('Proof of payment')}</span>)}
fileInputElement={UploadButton}
isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}
setIsUploadReady={this.setIsUploadReady('proofOfPaymentReady')}
createBlobRoutine={this.getCreateBlobRoutine()}
@ -337,8 +341,8 @@ const PRRegisterPieceForm = React.createClass({
}}
location={location}
fileClassToUpload={{
singular: getLangText('Upload Screenshot'),
plural: getLangText('Upload Screenshots')
singular: getLangText('Select Screenshot'),
plural: getLangText('Select Screenshots')
}}
required/>
</Property>