diff --git a/js/components/ascribe_forms/form.js b/js/components/ascribe_forms/form.js
index 0e3517a2..a0b2d251 100644
--- a/js/components/ascribe_forms/form.js
+++ b/js/components/ascribe_forms/form.js
@@ -238,7 +238,16 @@ let Form = React.createClass({
renderChildren() {
return ReactAddons.Children.map(this.props.children, (child, i) => {
if (child) {
- return ReactAddons.addons.cloneWithProps(child, {
+
+ // Since refs will be overwritten by this functions return statement,
+ // we still want to be able to define refs for nested `Form` or `Property`
+ // children, which is why we're upfront simply invoking the callback-ref-
+ // function before overwriting it.
+ if(typeof child.ref === 'function' && this.refs[child.props.name]) {
+ child.ref(this.refs[child.props.name]);
+ }
+
+ return React.cloneElement(child, {
handleChange: this.handleChangeChild,
ref: child.props.name,
key: i,
diff --git a/js/components/ascribe_forms/form_register_piece.js b/js/components/ascribe_forms/form_register_piece.js
index 76bbd68e..232ef444 100644
--- a/js/components/ascribe_forms/form_register_piece.js
+++ b/js/components/ascribe_forms/form_register_piece.js
@@ -17,7 +17,9 @@ import AscribeSpinner from '../ascribe_spinner';
import { getLangText } from '../../utils/lang_utils';
import { mergeOptions } from '../../utils/general_utils';
-import { formSubmissionValidation, displayValidFilesFilter } from '../ascribe_uploader/react_s3_fine_uploader_utils';
+import { formSubmissionValidation,
+ displayValidFilesFilter,
+ displayRemovedFilesFilter } from '../ascribe_uploader/react_s3_fine_uploader_utils';
let RegisterPieceForm = React.createClass({
@@ -50,9 +52,7 @@ let RegisterPieceForm = React.createClass({
getInitialState(){
return mergeOptions(
{
- digitalWorkKeyReady: false,
- thumbnailKeyReady: true,
- thumbnailKeyDialogExpanded: false
+ digitalWorkFile: null
},
UserStore.getState()
);
@@ -84,31 +84,34 @@ let RegisterPieceForm = React.createClass({
};
},
- handleSelectFiles(files) {
- const validFiles = files.filter(displayValidFilesFilter);
-
- if(validFiles.length > 0) {
- const { type: mimeType } = validFiles[0];
- const mimeSubType = mimeType && mimeType.split('/').length ? mimeType.split('/')[1]
- : 'unknown';
- const thumbnailKeyDialogExpanded = AppConstants.supportedThumbnailFileFormats.indexOf(mimeSubType) === -1;
- this.setState({ thumbnailKeyDialogExpanded });
- } else {
- // Reset the thumbnail that has been set in `handleSelectFilesThumbnail`
- let file = this.refs.form.refs.digital_work_key.refs.input.refs.fineuploader.state.filesToUpload[0];
- file.type = '';
- file.url = '';
-
+ handleChangedDigitalWork(digitalWorkFile) {
+ if (digitalWorkFile &&
+ (digitalWorkFile.status === 'deleted' || digitalWorkFile.status === 'canceled')) {
this.refs.form.refs.thumbnail_file.reset();
- this.setState({ thumbnailKeyDialogExpanded: false });
+ this.setState({ digitalWorkFile: null });
+ } else {
+ this.setState({ digitalWorkFile });
}
},
- handleSelectFilesThumbnail([thumbnailFile, ]) {
- // This is truly terrible, but at least we're not coding this mess into ReactS3Fineuploader
- let file = this.refs.form.refs.digital_work_key.refs.input.refs.fineuploader.state.filesToUpload[0];
- file.type = thumbnailFile.type;
- file.url = thumbnailFile.url;
+ handleChangedThumbnail(thumbnailFile) {
+ const { digitalWorkFile } = this.state;
+ const { fineuploader } = this.refs.digitalWorkFineUploader.refs;
+
+ fineuploader.setThumbnailForFileId(digitalWorkFile.id, thumbnailFile.url);
+ },
+
+ isThumbnailDialogExpanded() {
+ const { digitalWorkFile } = this.state;
+
+ if(digitalWorkFile) {
+ const { type: mimeType } = digitalWorkFile;
+ const mimeSubType = mimeType && mimeType.split('/').length ? mimeType.split('/')[1]
+ : 'unknown';
+ return AppConstants.supportedThumbnailFileFormats.indexOf(mimeSubType) === -1;
+ } else {
+ return false;
+ }
},
render() {
@@ -122,8 +125,7 @@ let RegisterPieceForm = React.createClass({
location,
children,
enableLocalHashing } = this.props;
- const { currentUser,
- thumbnailKeyDialogExpanded } = this.state;
+ const { currentUser} = this.state;
const profileHashLocally = currentUser && currentUser.profile ? currentUser.profile.hash_locally : false;
const hashLocally = profileHashLocally && enableLocalHashing;
@@ -155,8 +157,9 @@ let RegisterPieceForm = React.createClass({
+ label={getLangText('Your Work')}>
this.refs.digitalWorkFineUploader = ref}
keyRoutine={{
url: AppConstants.serverUrl + 's3/key/',
fileClass: 'digitalwork'
@@ -172,17 +175,18 @@ let RegisterPieceForm = React.createClass({
disabled={!isFineUploaderEditable}
enableLocalHashing={hashLocally}
uploadMethod={location.query.method}
- handleSelectFiles={this.handleSelectFiles}/>
+ handleChangedFile={this.handleChangedDigitalWork}/>
+ expanded={this.isThumbnailDialogExpanded()}>
this.refs.thumbnailFineUploader = ref}
fileInputElement={UploadButton({ className: 'btn btn-secondary btn-sm' })}
createBlobRoutine={{
url: ApiUrls.blob_thumbnails
}}
- handleSelectFiles={this.handleSelectFilesThumbnail}
+ handleChangedFile={this.handleChangedThumbnail}
isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}
keyRoutine={{
url: AppConstants.serverUrl + 's3/key/',
diff --git a/js/components/ascribe_forms/input_fineuploader.js b/js/components/ascribe_forms/input_fineuploader.js
index 8d1ad70e..eb20fcd1 100644
--- a/js/components/ascribe_forms/input_fineuploader.js
+++ b/js/components/ascribe_forms/input_fineuploader.js
@@ -52,7 +52,7 @@ const InputFineUploader = React.createClass({
singular: string,
plural: string
}),
- handleSelectFiles: func
+ handleChangedFile: func
},
getDefaultProps() {
@@ -106,7 +106,7 @@ const InputFineUploader = React.createClass({
enableLocalHashing,
fileClassToUpload,
uploadMethod,
- handleSelectFiles } = this.props;
+ handleChangedFile } = this.props;
let editable = this.props.isFineUploaderActive;
// if disabled is actually set by property, we want to override
@@ -145,7 +145,7 @@ const InputFineUploader = React.createClass({
enableLocalHashing={enableLocalHashing}
uploadMethod={uploadMethod}
fileClassToUpload={fileClassToUpload}
- handleSelectFiles={handleSelectFiles}/>
+ handleChangedFile={handleChangedFile}/>
);
}
});
diff --git a/js/components/ascribe_forms/property.js b/js/components/ascribe_forms/property.js
index 4d01790d..063d27dd 100644
--- a/js/components/ascribe_forms/property.js
+++ b/js/components/ascribe_forms/property.js
@@ -231,7 +231,16 @@ const Property = React.createClass({
// if the component is actually being shown (!== 'expanded === false')
if((this.state.expanded && this.props.checkboxLabel) || !this.props.checkboxLabel) {
return ReactAddons.Children.map(this.props.children, (child) => {
- return ReactAddons.addons.cloneWithProps(child, {
+
+ // Since refs will be overriden by this functions return statement,
+ // we still want to be able to define refs for nested `Form` or `Property`
+ // children, which is why we're upfront simply invoking the callback-ref-
+ // function before overriding it.
+ if(typeof child.ref === 'function' && this.refs.input) {
+ child.ref(this.refs.input);
+ }
+
+ return React.cloneElement(child, {
style,
onChange: this.handleChange,
onFocus: this.handleFocus,
diff --git a/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_preview.js b/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_preview.js
index 5528ec25..ca1be2d2 100644
--- a/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_preview.js
+++ b/js/components/ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop_preview.js
@@ -106,12 +106,13 @@ const FileDragAndDropPreview = React.createClass({
let previewElement;
// Decide whether an image or a placeholder picture should be displayed
- if(file.type.split('/')[0] === 'image') {
+ // If a file has its `thumbnailUrl` defined, then we display it also as an image
+ if(file.type.split('/')[0] === 'image' || file.thumbnailUrl) {
previewElement = (
{
- if(typeof this.props.handleSelectFiles === 'function') {
- this.props.handleSelectFiles(this.state.filesToUpload);
+ if(typeof this.props.handleChangedFile === 'function') {
+ this.props.handleChangedFile(this.state.filesToUpload[id]);
}
});
@@ -624,8 +637,8 @@ const ReactS3FineUploader = React.createClass({
// and display an error message
this.setStatusOfFile(fileId, 'deleted')
.then(() => {
- if(typeof this.props.handleSelectFiles === 'function') {
- this.props.handleSelectFiles(this.state.filesToUpload);
+ if(typeof this.props.handleChangedFile === 'function') {
+ this.props.handleChangedFile(this.state.filesToUpload[fileId]);
}
});
@@ -872,8 +885,10 @@ const ReactS3FineUploader = React.createClass({
// information to the outside components, so they can act on it (in our case, because
// we want the user to define a thumbnail when the actual work is not renderable
// (like e.g. a .zip file))
- if(typeof this.props.handleSelectFiles === 'function') {
- this.props.handleSelectFiles(this.state.filesToUpload);
+ if(typeof this.props.handleChangedFile === 'function') {
+ // its save to assume that the last file in `filesToUpload` is always
+ // the latest file added
+ this.props.handleChangedFile(this.state.filesToUpload.slice(-1)[0]);
}
});
},
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 cd1dbce2..ed76c5e8 100644
--- a/js/components/ascribe_uploader/react_s3_fine_uploader_utils.js
+++ b/js/components/ascribe_uploader/react_s3_fine_uploader_utils.js
@@ -42,6 +42,15 @@ export function displayValidFilesFilter(file) {
return file.status !== 'deleted' && file.status !== 'canceled';
}
+/**
+ * Filter function for filtering all files except for deleted and canceled files
+ * @param {object} file A file from filesToUpload that has status as a prop.
+ * @return {boolean}
+ */
+export function displayRemovedFilesFilter(file) {
+ return file.status === 'deleted' || file.status === 'canceled';
+}
+
/**
* Filter function for which files to integrate in the progress process