mirror of
https://github.com/ascribe/onion.git
synced 2025-01-03 10:25:08 +01:00
Restructure thumbnail creation functionality
- Add function in Property and Form for creating refs - Change `handleSelectFiles` to `handleChangedFile` - Add `setThumbnailForFile` method to `ReactS3Fineuploader`
This commit is contained in:
parent
59244f208a
commit
809ca6f40a
@ -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,
|
||||
|
@ -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({
|
||||
<Property
|
||||
name="digital_work_key"
|
||||
ignoreFocus={true}
|
||||
label={'Your Work'}>
|
||||
label={getLangText('Your Work')}>
|
||||
<InputFineUploader
|
||||
ref={ref => 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}/>
|
||||
</Property>
|
||||
<Property
|
||||
name="thumbnail_file"
|
||||
expanded={thumbnailKeyDialogExpanded}>
|
||||
expanded={this.isThumbnailDialogExpanded()}>
|
||||
<InputFineUploader
|
||||
ref={ref => 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/',
|
||||
|
@ -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}/>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -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,
|
||||
|
@ -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 = (
|
||||
<FileDragAndDropPreviewImage
|
||||
onClick={this.handleDeleteFile}
|
||||
progress={file.progress}
|
||||
url={file.url}
|
||||
url={file.thumbnailUrl || file.url}
|
||||
toggleUploadProcess={this.toggleUploadProcess}
|
||||
areAssetsDownloadable={areAssetsDownloadable}
|
||||
downloadUrl={file.s3UrlSafe}
|
||||
|
@ -48,7 +48,7 @@ const ReactS3FineUploader = React.createClass({
|
||||
number
|
||||
])
|
||||
}),
|
||||
handleSelectFiles: func, // is for when a file is dropped or selected
|
||||
handleChangedFile: func, // is for when a file is dropped or selected
|
||||
submitFile: func, // is for when a file has been successfully uploaded, TODO: rename to handleSubmitFile
|
||||
autoUpload: bool,
|
||||
debug: bool,
|
||||
@ -389,6 +389,19 @@ const ReactS3FineUploader = React.createClass({
|
||||
});
|
||||
},
|
||||
|
||||
setThumbnailForFileId(fileId, url) {
|
||||
const { filesToUpload } = this.state;
|
||||
|
||||
if(fileId < filesToUpload.length) {
|
||||
const changeSet = { $set: url };
|
||||
const newFilesToUpload = React.addons.update(filesToUpload, { [fileId]: { thumbnailUrl: changeSet } });
|
||||
|
||||
this.setState({ filesToUpload: newFilesToUpload });
|
||||
} else {
|
||||
throw new Error("You're accessing an index out of range of filesToUpload");
|
||||
}
|
||||
},
|
||||
|
||||
/* FineUploader specific callback function handlers */
|
||||
|
||||
onUploadChunk(id, name, chunkData) {
|
||||
@ -525,8 +538,8 @@ const ReactS3FineUploader = React.createClass({
|
||||
// when a upload is canceled, we need to update this components file array
|
||||
this.setStatusOfFile(id, 'canceled')
|
||||
.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[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]);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user