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() {
|
renderChildren() {
|
||||||
return ReactAddons.Children.map(this.props.children, (child, i) => {
|
return ReactAddons.Children.map(this.props.children, (child, i) => {
|
||||||
if (child) {
|
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,
|
handleChange: this.handleChangeChild,
|
||||||
ref: child.props.name,
|
ref: child.props.name,
|
||||||
key: i,
|
key: i,
|
||||||
|
@ -17,7 +17,9 @@ import AscribeSpinner from '../ascribe_spinner';
|
|||||||
|
|
||||||
import { getLangText } from '../../utils/lang_utils';
|
import { getLangText } from '../../utils/lang_utils';
|
||||||
import { mergeOptions } from '../../utils/general_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({
|
let RegisterPieceForm = React.createClass({
|
||||||
@ -50,9 +52,7 @@ let RegisterPieceForm = React.createClass({
|
|||||||
getInitialState(){
|
getInitialState(){
|
||||||
return mergeOptions(
|
return mergeOptions(
|
||||||
{
|
{
|
||||||
digitalWorkKeyReady: false,
|
digitalWorkFile: null
|
||||||
thumbnailKeyReady: true,
|
|
||||||
thumbnailKeyDialogExpanded: false
|
|
||||||
},
|
},
|
||||||
UserStore.getState()
|
UserStore.getState()
|
||||||
);
|
);
|
||||||
@ -84,31 +84,34 @@ let RegisterPieceForm = React.createClass({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
handleSelectFiles(files) {
|
handleChangedDigitalWork(digitalWorkFile) {
|
||||||
const validFiles = files.filter(displayValidFilesFilter);
|
if (digitalWorkFile &&
|
||||||
|
(digitalWorkFile.status === 'deleted' || digitalWorkFile.status === 'canceled')) {
|
||||||
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 = '';
|
|
||||||
|
|
||||||
this.refs.form.refs.thumbnail_file.reset();
|
this.refs.form.refs.thumbnail_file.reset();
|
||||||
this.setState({ thumbnailKeyDialogExpanded: false });
|
this.setState({ digitalWorkFile: null });
|
||||||
|
} else {
|
||||||
|
this.setState({ digitalWorkFile });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
handleSelectFilesThumbnail([thumbnailFile, ]) {
|
handleChangedThumbnail(thumbnailFile) {
|
||||||
// This is truly terrible, but at least we're not coding this mess into ReactS3Fineuploader
|
const { digitalWorkFile } = this.state;
|
||||||
let file = this.refs.form.refs.digital_work_key.refs.input.refs.fineuploader.state.filesToUpload[0];
|
const { fineuploader } = this.refs.digitalWorkFineUploader.refs;
|
||||||
file.type = thumbnailFile.type;
|
|
||||||
file.url = thumbnailFile.url;
|
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() {
|
render() {
|
||||||
@ -122,8 +125,7 @@ let RegisterPieceForm = React.createClass({
|
|||||||
location,
|
location,
|
||||||
children,
|
children,
|
||||||
enableLocalHashing } = this.props;
|
enableLocalHashing } = this.props;
|
||||||
const { currentUser,
|
const { currentUser} = this.state;
|
||||||
thumbnailKeyDialogExpanded } = this.state;
|
|
||||||
|
|
||||||
const profileHashLocally = currentUser && currentUser.profile ? currentUser.profile.hash_locally : false;
|
const profileHashLocally = currentUser && currentUser.profile ? currentUser.profile.hash_locally : false;
|
||||||
const hashLocally = profileHashLocally && enableLocalHashing;
|
const hashLocally = profileHashLocally && enableLocalHashing;
|
||||||
@ -155,8 +157,9 @@ let RegisterPieceForm = React.createClass({
|
|||||||
<Property
|
<Property
|
||||||
name="digital_work_key"
|
name="digital_work_key"
|
||||||
ignoreFocus={true}
|
ignoreFocus={true}
|
||||||
label={'Your Work'}>
|
label={getLangText('Your Work')}>
|
||||||
<InputFineUploader
|
<InputFineUploader
|
||||||
|
ref={ref => this.refs.digitalWorkFineUploader = ref}
|
||||||
keyRoutine={{
|
keyRoutine={{
|
||||||
url: AppConstants.serverUrl + 's3/key/',
|
url: AppConstants.serverUrl + 's3/key/',
|
||||||
fileClass: 'digitalwork'
|
fileClass: 'digitalwork'
|
||||||
@ -172,17 +175,18 @@ let RegisterPieceForm = React.createClass({
|
|||||||
disabled={!isFineUploaderEditable}
|
disabled={!isFineUploaderEditable}
|
||||||
enableLocalHashing={hashLocally}
|
enableLocalHashing={hashLocally}
|
||||||
uploadMethod={location.query.method}
|
uploadMethod={location.query.method}
|
||||||
handleSelectFiles={this.handleSelectFiles}/>
|
handleChangedFile={this.handleChangedDigitalWork}/>
|
||||||
</Property>
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name="thumbnail_file"
|
name="thumbnail_file"
|
||||||
expanded={thumbnailKeyDialogExpanded}>
|
expanded={this.isThumbnailDialogExpanded()}>
|
||||||
<InputFineUploader
|
<InputFineUploader
|
||||||
|
ref={ref => this.refs.thumbnailFineUploader = ref}
|
||||||
fileInputElement={UploadButton({ className: 'btn btn-secondary btn-sm' })}
|
fileInputElement={UploadButton({ className: 'btn btn-secondary btn-sm' })}
|
||||||
createBlobRoutine={{
|
createBlobRoutine={{
|
||||||
url: ApiUrls.blob_thumbnails
|
url: ApiUrls.blob_thumbnails
|
||||||
}}
|
}}
|
||||||
handleSelectFiles={this.handleSelectFilesThumbnail}
|
handleChangedFile={this.handleChangedThumbnail}
|
||||||
isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}
|
isReadyForFormSubmission={formSubmissionValidation.atLeastOneUploadedFile}
|
||||||
keyRoutine={{
|
keyRoutine={{
|
||||||
url: AppConstants.serverUrl + 's3/key/',
|
url: AppConstants.serverUrl + 's3/key/',
|
||||||
|
@ -52,7 +52,7 @@ const InputFineUploader = React.createClass({
|
|||||||
singular: string,
|
singular: string,
|
||||||
plural: string
|
plural: string
|
||||||
}),
|
}),
|
||||||
handleSelectFiles: func
|
handleChangedFile: func
|
||||||
},
|
},
|
||||||
|
|
||||||
getDefaultProps() {
|
getDefaultProps() {
|
||||||
@ -106,7 +106,7 @@ const InputFineUploader = React.createClass({
|
|||||||
enableLocalHashing,
|
enableLocalHashing,
|
||||||
fileClassToUpload,
|
fileClassToUpload,
|
||||||
uploadMethod,
|
uploadMethod,
|
||||||
handleSelectFiles } = this.props;
|
handleChangedFile } = this.props;
|
||||||
let editable = this.props.isFineUploaderActive;
|
let editable = this.props.isFineUploaderActive;
|
||||||
|
|
||||||
// if disabled is actually set by property, we want to override
|
// if disabled is actually set by property, we want to override
|
||||||
@ -145,7 +145,7 @@ const InputFineUploader = React.createClass({
|
|||||||
enableLocalHashing={enableLocalHashing}
|
enableLocalHashing={enableLocalHashing}
|
||||||
uploadMethod={uploadMethod}
|
uploadMethod={uploadMethod}
|
||||||
fileClassToUpload={fileClassToUpload}
|
fileClassToUpload={fileClassToUpload}
|
||||||
handleSelectFiles={handleSelectFiles}/>
|
handleChangedFile={handleChangedFile}/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -231,7 +231,16 @@ const Property = React.createClass({
|
|||||||
// if the component is actually being shown (!== 'expanded === false')
|
// if the component is actually being shown (!== 'expanded === false')
|
||||||
if((this.state.expanded && this.props.checkboxLabel) || !this.props.checkboxLabel) {
|
if((this.state.expanded && this.props.checkboxLabel) || !this.props.checkboxLabel) {
|
||||||
return ReactAddons.Children.map(this.props.children, (child) => {
|
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,
|
style,
|
||||||
onChange: this.handleChange,
|
onChange: this.handleChange,
|
||||||
onFocus: this.handleFocus,
|
onFocus: this.handleFocus,
|
||||||
|
@ -106,12 +106,13 @@ const FileDragAndDropPreview = React.createClass({
|
|||||||
let previewElement;
|
let previewElement;
|
||||||
|
|
||||||
// Decide whether an image or a placeholder picture should be displayed
|
// 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 = (
|
previewElement = (
|
||||||
<FileDragAndDropPreviewImage
|
<FileDragAndDropPreviewImage
|
||||||
onClick={this.handleDeleteFile}
|
onClick={this.handleDeleteFile}
|
||||||
progress={file.progress}
|
progress={file.progress}
|
||||||
url={file.url}
|
url={file.thumbnailUrl || file.url}
|
||||||
toggleUploadProcess={this.toggleUploadProcess}
|
toggleUploadProcess={this.toggleUploadProcess}
|
||||||
areAssetsDownloadable={areAssetsDownloadable}
|
areAssetsDownloadable={areAssetsDownloadable}
|
||||||
downloadUrl={file.s3UrlSafe}
|
downloadUrl={file.s3UrlSafe}
|
||||||
|
@ -48,7 +48,7 @@ const ReactS3FineUploader = React.createClass({
|
|||||||
number
|
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
|
submitFile: func, // is for when a file has been successfully uploaded, TODO: rename to handleSubmitFile
|
||||||
autoUpload: bool,
|
autoUpload: bool,
|
||||||
debug: 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 */
|
/* FineUploader specific callback function handlers */
|
||||||
|
|
||||||
onUploadChunk(id, name, chunkData) {
|
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
|
// when a upload is canceled, we need to update this components file array
|
||||||
this.setStatusOfFile(id, 'canceled')
|
this.setStatusOfFile(id, 'canceled')
|
||||||
.then(() => {
|
.then(() => {
|
||||||
if(typeof this.props.handleSelectFiles === 'function') {
|
if(typeof this.props.handleChangedFile === 'function') {
|
||||||
this.props.handleSelectFiles(this.state.filesToUpload);
|
this.props.handleChangedFile(this.state.filesToUpload[id]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -624,8 +637,8 @@ const ReactS3FineUploader = React.createClass({
|
|||||||
// and display an error message
|
// and display an error message
|
||||||
this.setStatusOfFile(fileId, 'deleted')
|
this.setStatusOfFile(fileId, 'deleted')
|
||||||
.then(() => {
|
.then(() => {
|
||||||
if(typeof this.props.handleSelectFiles === 'function') {
|
if(typeof this.props.handleChangedFile === 'function') {
|
||||||
this.props.handleSelectFiles(this.state.filesToUpload);
|
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
|
// 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
|
// we want the user to define a thumbnail when the actual work is not renderable
|
||||||
// (like e.g. a .zip file))
|
// (like e.g. a .zip file))
|
||||||
if(typeof this.props.handleSelectFiles === 'function') {
|
if(typeof this.props.handleChangedFile === 'function') {
|
||||||
this.props.handleSelectFiles(this.state.filesToUpload);
|
// 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';
|
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
|
* Filter function for which files to integrate in the progress process
|
||||||
|
Loading…
Reference in New Issue
Block a user