1
0
mirror of https://github.com/ascribe/onion.git synced 2024-06-30 13:41:57 +02:00
onion/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop.js
Tim Daubenschütz fbbbd1de89 Merge branch 'AD-456-ikonotv-branded-page-for-registra' into AD-957-custom-upload-button-for-contract
Fix merge conflicts

Conflicts:
	js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop.js
	js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_dialog.js
	js/components/ascribe_uploader/react_s3_fine_uploader.js
2015-09-15 13:47:36 +02:00

270 lines
9.9 KiB
JavaScript

'use strict';
import React from 'react';
import ProgressBar from 'react-bootstrap/lib/ProgressBar';
import FileDragAndDropDialog from './file_drag_and_drop_dialog';
import FileDragAndDropPreviewIterator from './file_drag_and_drop_preview_iterator';
import { getLangText } from '../../../utils/lang_utils';
// Taken from: https://github.com/fedosejev/react-file-drag-and-drop
let FileDragAndDrop = React.createClass({
propTypes: {
className: React.PropTypes.string,
onDragStart: React.PropTypes.func,
onDrop: React.PropTypes.func.isRequired,
onDrag: React.PropTypes.func,
onDragEnter: React.PropTypes.func,
onLeave: React.PropTypes.func,
onDragLeave: React.PropTypes.func,
onDragOver: React.PropTypes.func,
onDragEnd: React.PropTypes.func,
onInactive: React.PropTypes.func,
filesToUpload: React.PropTypes.array,
handleDeleteFile: React.PropTypes.func,
handleCancelFile: React.PropTypes.func,
handlePauseFile: React.PropTypes.func,
handleResumeFile: React.PropTypes.func,
multiple: React.PropTypes.bool,
dropzoneInactive: React.PropTypes.bool,
areAssetsDownloadable: React.PropTypes.bool,
areAssetsEditable: React.PropTypes.bool,
enableLocalHashing: React.PropTypes.bool,
// triggers a FileDragAndDrop-global spinner
hashingProgress: React.PropTypes.number,
// sets the value of this.state.hashingProgress in reactfineuploader
// to -1 which is code for: aborted
handleCancelHashing: React.PropTypes.func,
// A class of a file the user has to upload
// Needs to be defined both in singular as well as in plural
fileClassToUpload: React.PropTypes.shape({
singular: React.PropTypes.string,
plural: React.PropTypes.string
}),
validation: React.PropTypes.shape({
itemLimit: React.PropTypes.number,
sizeLimit: React.PropTypes.string,
allowedExtensions: React.PropTypes.arrayOf(React.PropTypes.string)
})
},
handleDragStart(event) {
if (typeof this.props.onDragStart === 'function') {
this.props.onDragStart(event);
}
},
handleDrag(event) {
if (typeof this.props.onDrag === 'function') {
this.props.onDrag(event);
}
},
handleDragEnd(event) {
if (typeof this.props.onDragEnd === 'function') {
this.props.onDragEnd(event);
}
},
handleDragEnter(event) {
if (typeof this.props.onDragEnter === 'function') {
this.props.onDragEnter(event);
}
},
handleDragLeave(event) {
if (typeof this.props.onDragLeave === 'function') {
this.props.onDragLeave(event);
}
},
handleDragOver(event) {
event.preventDefault();
if (typeof this.props.onDragOver === 'function') {
this.props.onDragOver(event);
}
},
handleDrop(event) {
event.preventDefault();
event.stopPropagation();
let files;
if(this.props.dropzoneInactive) {
// if there is a handle function for doing stuff
// when the dropzone is inactive, then call it
if(this.props.onInactive) {
this.props.onInactive();
}
return;
}
// handle Drag and Drop
if(event.dataTransfer && event.dataTransfer.files.length > 0) {
files = event.dataTransfer.files;
} else if(event.target.files) { // handle input type file
files = event.target.files;
}
if(typeof this.props.onDrop === 'function' && files) {
this.props.onDrop(files);
}
},
handleDeleteFile(fileId) {
// input's value is not change the second time someone
// inputs the same file again, therefore we need to reset its value
this.refs.fileinput.getDOMNode().value = '';
this.props.handleDeleteFile(fileId);
},
handleCancelFile(fileId) {
// input's value is not change the second time someone
// inputs the same file again, therefore we need to reset its value
this.refs.fileinput.getDOMNode().value = '';
this.props.handleCancelFile(fileId);
},
handlePauseFile(fileId) {
// input's value is not change the second time someone
// inputs the same file again, therefore we need to reset its value
this.refs.fileinput.getDOMNode().value = '';
this.props.handlePauseFile(fileId);
},
handleResumeFile(fileId) {
// input's value is not change the second time someone
// inputs the same file again, therefore we need to reset its value
this.refs.fileinput.getDOMNode().value = '';
this.props.handleResumeFile(fileId);
},
handleOnClick() {
// when multiple is set to false and the user already uploaded a piece,
// do not propagate event
if(this.props.dropzoneInactive) {
// if there is a handle function for doing stuff
// when the dropzone is inactive, then call it
if(this.props.onInactive) {
this.props.onInactive();
}
return;
}
// 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);
},
render: function () {
let { filesToUpload,
dropzoneInactive,
className,
hashingProgress,
handleCancelHashing,
multiple,
enableLocalHashing,
fileClassToUpload,
areAssetsDownloadable,
areAssetsEditable,
validation
} = this.props;
// has files only is true if there are files that do not have the status deleted or canceled
let hasFiles = filesToUpload.filter((file) => file.status !== 'deleted' && file.status !== 'canceled' && file.size !== -1).length > 0;
let updatedClassName = hasFiles ? 'has-files ' : '';
updatedClassName += dropzoneInactive ? 'inactive-dropzone' : 'active-dropzone';
updatedClassName += ' file-drag-and-drop';
// if !== -2: triggers a FileDragAndDrop-global spinner
if(hashingProgress !== -2) {
return (
<div className={className}>
<div className="file-drag-and-drop-hashing-dialog">
<p>{getLangText('Computing hash(es)... This may take a few minutes.')}</p>
<p>
<a onClick={this.props.handleCancelHashing}> {getLangText('Cancel hashing')}</a>
</p>
<ProgressBar
now={Math.ceil(this.props.hashingProgress)}
label="%(percent)s%"
className="ascribe-progress-bar"/>
</div>
</div>
);
} else {
let accept = '';
/**
* Fineuploader allows to specify the file extensions that are allowed to upload.
* For our self defined input, we can reuse those declarations to restrict which files
* the user can pick from his hard drive.
*/
if(validation && validation.allowedExtensions && validation.allowedExtensions.length > 0) {
// add a dot in front of the extension
let prefixedAllowedExtensions = validation.allowedExtensions.map((ext) => '.' + ext);
// generate a comma separated list to add them to the DOM element
// See: http://stackoverflow.com/questions/4328947/limit-file-format-when-using-input-type-file
accept = prefixedAllowedExtensions.join(', ');
}
return (
<div
className={updatedClassName}
onDragStart={this.handleDragStart}
onDrag={this.handleDrop}
onDragEnter={this.handleDragEnter}
onDragLeave={this.handleDragLeave}
onDragOver={this.handleDragOver}
onDrop={this.handleDrop}
onDragEnd={this.handleDragEnd}>
<FileDragAndDropDialog
multipleFiles={multiple}
hasFiles={hasFiles}
onClick={this.handleOnClick}
enableLocalHashing={enableLocalHashing}
fileClassToUpload={fileClassToUpload}/>
<FileDragAndDropPreviewIterator
files={filesToUpload}
handleDeleteFile={this.handleDeleteFile}
handleCancelFile={this.handleCancelFile}
handlePauseFile={this.handlePauseFile}
handleResumeFile={this.handleResumeFile}
areAssetsDownloadable={areAssetsDownloadable}
areAssetsEditable={areAssetsEditable}/>
<input
multiple={multiple}
ref="fileinput"
type="file"
style={{
display: 'none',
height: 0,
width: 0
}}
onChange={this.handleDrop}
accept={accept}/>
</div>
);
}
}
});
export default FileDragAndDrop;