1
0
mirror of https://github.com/ascribe/onion.git synced 2024-06-28 00:28:00 +02: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:
Tim Daubenschütz 2015-11-23 17:59:20 +01:00
parent 59244f208a
commit 809ca6f40a
7 changed files with 92 additions and 45 deletions

View File

@ -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,

View File

@ -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/',

View File

@ -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}/>
);
}
});

View File

@ -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,

View File

@ -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}

View File

@ -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]);
}
});
},

View File

@ -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