);
} 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 (
+ accept={allowedExtensions}/>
);
}
diff --git a/js/components/ascribe_uploader/ascribe_upload_button/upload_button.js b/js/components/ascribe_uploader/ascribe_upload_button/upload_button.js
new file mode 100644
index 00000000..a3fa985c
--- /dev/null
+++ b/js/components/ascribe_uploader/ascribe_upload_button/upload_button.js
@@ -0,0 +1,114 @@
+'use strict';
+
+import React from 'react';
+
+import { displayValidProgressFilesFilter } from '../react_s3_fine_uploader_utils';
+
+let UploadButton = React.createClass({
+ propTypes: {
+ 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,
+
+
+ // 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
+ }),
+
+ allowedExtensions: React.PropTypes.string
+ },
+
+ 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');
+ },
+
+ handleOnClick() {
+ let uploadingFiles = this.getUploadingFiles();
+
+ // 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);
+ }
+ },
+
+ getButtonLabel() {
+ let { filesToUpload, fileClassToUpload } = this.props;
+
+ // filter invalid files that might have been deleted or canceled...
+ filesToUpload = filesToUpload.filter(displayValidProgressFilesFilter);
+
+ // Depending on wether there is an upload going on or not we
+ // display the progress
+ if(filesToUpload.length > 0) {
+ return 'Upload progress: ' + Math.ceil(filesToUpload[0].progress) + '%';
+ } else {
+ return fileClassToUpload.singular;
+ }
+ },
+
+ render() {
+ let {
+ multiple,
+ fileClassToUpload,
+ allowedExtensions
+ } = this.props;
+
+ return (
+
+ );
+ }
+});
+
+export default UploadButton;
\ No newline at end of file
diff --git a/js/components/ascribe_uploader/react_s3_fine_uploader.js b/js/components/ascribe_uploader/react_s3_fine_uploader.js
index 8ba53444..05709ad2 100644
--- a/js/components/ascribe_uploader/react_s3_fine_uploader.js
+++ b/js/components/ascribe_uploader/react_s3_fine_uploader.js
@@ -16,7 +16,7 @@ import AppConstants from '../../constants/application_constants';
import { computeHashOfFile } from '../../utils/file_utils';
-import { displayValidFilesFilter } from './react_s3_fine_uploader_utils';
+import { displayValidFilesFilter, transformAllowedExtensionsToInputAcceptProp } from './react_s3_fine_uploader_utils';
import { getCookie } from '../../utils/fetch_api_utils';
import { getLangText } from '../../utils/lang_utils';
@@ -125,7 +125,10 @@ let ReactS3FineUploader = React.createClass({
// Uploading functionality of react fineuploader is disconnected from its UI
// layer, which means that literally every (properly adjusted) react element
// can handle the UI handling.
- fileInputElement: React.PropTypes.func
+ fileInputElement: React.PropTypes.oneOfType([
+ React.PropTypes.func,
+ React.PropTypes.element
+ ])
},
mixins: [Router.State],
@@ -838,6 +841,16 @@ let ReactS3FineUploader = React.createClass({
},
+ getAllowedExtensions() {
+ let { validation } = this.props;
+
+ if(validation && validation.allowedExtensions && validation.allowedExtensions.length > 0) {
+ return transformAllowedExtensionsToInputAcceptProp(validation.allowedExtensions);
+ } else {
+ return null;
+ }
+ },
+
render() {
let {
multiple,
@@ -868,7 +881,7 @@ let ReactS3FineUploader = React.createClass({
hashingProgress: this.state.hashingProgress,
enableLocalHashing: enableLocalHashing,
fileClassToUpload: fileClassToUpload,
- validation: validation
+ allowedExtensions: this.getAllowedExtensions()
});
}
diff --git a/js/components/ascribe_uploader/react_s3_fine_uploader_utils.js b/js/components/ascribe_uploader/react_s3_fine_uploader_utils.js
index 92d5c2ba..cd1dbce2 100644
--- a/js/components/ascribe_uploader/react_s3_fine_uploader_utils.js
+++ b/js/components/ascribe_uploader/react_s3_fine_uploader_utils.js
@@ -52,3 +52,22 @@ export function displayValidProgressFilesFilter(file) {
return file.status !== 'deleted' && file.status !== 'canceled' && file.status !== 'online';
}
+
+/**
+ * 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.
+ *
+ * Takes an array of file extensions (['pdf', 'png', ...]) and transforms them into a string
+ * that can be passed into an html5 input via its 'accept' prop.
+ * @param {array} allowedExtensions Array of strings without a dot prefixed
+ * @return {string} Joined string (comma-separated) of the passed-in array
+ */
+export function transformAllowedExtensionsToInputAcceptProp(allowedExtensions) {
+ // add a dot in front of the extension
+ let prefixedAllowedExtensions = 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
+ return prefixedAllowedExtensions.join(', ');
+}
diff --git a/sass/ascribe_uploader.scss b/sass/ascribe_uploader.scss
index 6e9eebd9..331b6b00 100644
--- a/sass/ascribe_uploader.scss
+++ b/sass/ascribe_uploader.scss
@@ -9,6 +9,7 @@
text-align: center;
vertical-align: middle;
cursor: default !important;
+ padding: 1.5em 0 1.5em 0;
.file-drag-and-drop-dialog > p:first-child {
font-size: 1.5em !important;