1
0
mirror of https://github.com/ascribe/onion.git synced 2024-12-22 17:33:14 +01:00

Add file-format-specific call to action for thumbnail generation

This commit is contained in:
Tim Daubenschütz 2015-11-17 15:46:46 +01:00
parent 2ffc26d703
commit 971d42b36d
6 changed files with 106 additions and 57 deletions

View File

@ -7,6 +7,7 @@ import UserActions from '../../actions/user_actions';
import Form from './form'; import Form from './form';
import Property from './property'; import Property from './property';
import PropertyCollapsible from './property_collapsible';
import InputFineUploader from './input_fineuploader'; import InputFineUploader from './input_fineuploader';
import UploadButton from '../ascribe_uploader/ascribe_upload_button/upload_button'; import UploadButton from '../ascribe_uploader/ascribe_upload_button/upload_button';
@ -16,7 +17,7 @@ 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 } from '../ascribe_uploader/react_s3_fine_uploader_utils'; import { formSubmissionValidation, displayValidFilesFilter } from '../ascribe_uploader/react_s3_fine_uploader_utils';
let RegisterPieceForm = React.createClass({ let RegisterPieceForm = React.createClass({
@ -50,7 +51,8 @@ let RegisterPieceForm = React.createClass({
return mergeOptions( return mergeOptions(
{ {
digitalWorkKeyReady: false, digitalWorkKeyReady: false,
thumbnailKeyReady: true thumbnailKeyReady: true,
thumbnailKeyDialogExpanded: false
}, },
UserStore.getState() UserStore.getState()
); );
@ -82,6 +84,20 @@ let RegisterPieceForm = React.createClass({
}; };
}, },
handleSelectFiles(files) {
const validFiles = files.filter(displayValidFilesFilter);
if(validFiles.length > 0) {
const { type: fileType } = validFiles[0].type;
const fileExtension = fileType && fileType.split('/').length ? fileType.split('/')[1]
: 'unknown';
const thumbnailKeyDialogExpanded = AppConstants.supportedThumbnailFileFormats.indexOf(fileExtension) === -1;
this.setState({ thumbnailKeyDialogExpanded });
} else {
this.setState({ thumbnailKeyDialogExpanded: false });
}
},
render() { render() {
const { disabled, const { disabled,
handleSuccess, handleSuccess,
@ -95,7 +111,8 @@ let RegisterPieceForm = React.createClass({
enableLocalHashing } = this.props; enableLocalHashing } = this.props;
const { currentUser, const { currentUser,
digitalWorkKeyReady, digitalWorkKeyReady,
thumbnailKeyReady } = this.state; thumbnailKeyReady,
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;
@ -141,10 +158,12 @@ let RegisterPieceForm = React.createClass({
onLoggedOut={onLoggedOut} onLoggedOut={onLoggedOut}
disabled={!isFineUploaderEditable} disabled={!isFineUploaderEditable}
enableLocalHashing={hashLocally} enableLocalHashing={hashLocally}
uploadMethod={location.query.method} /> uploadMethod={location.query.method}
handleSelectFiles={this.handleSelectFiles}/>
</Property> </Property>
<Property <Property
name="thumbnail_file"> name="thumbnail_file"
expanded={thumbnailKeyDialogExpanded}>
<InputFineUploader <InputFineUploader
fileInputElement={UploadButton({ className: 'btn btn-secondary btn-sm' })} fileInputElement={UploadButton({ className: 'btn btn-secondary btn-sm' })}
createBlobRoutine={{ createBlobRoutine={{

View File

@ -51,7 +51,8 @@ const InputFineUploader = React.createClass({
fileClassToUpload: shape({ fileClassToUpload: shape({
singular: string, singular: string,
plural: string plural: string
}) }),
handleSelectFiles: func
}, },
getDefaultProps() { getDefaultProps() {
@ -104,7 +105,8 @@ const InputFineUploader = React.createClass({
onLoggedOut, onLoggedOut,
enableLocalHashing, enableLocalHashing,
fileClassToUpload, fileClassToUpload,
uploadMethod } = this.props; uploadMethod,
handleSelectFiles } = 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
@ -142,7 +144,8 @@ const InputFineUploader = React.createClass({
onInactive={onLoggedOut} onInactive={onLoggedOut}
enableLocalHashing={enableLocalHashing} enableLocalHashing={enableLocalHashing}
uploadMethod={uploadMethod} uploadMethod={uploadMethod}
fileClassToUpload={fileClassToUpload} /> fileClassToUpload={fileClassToUpload}
handleSelectFiles={handleSelectFiles}/>
); );
} }
}); });

View File

@ -3,52 +3,54 @@
import React from 'react'; import React from 'react';
import ReactAddons from 'react/addons'; import ReactAddons from 'react/addons';
import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger'; import Panel from 'react-bootstrap/lib/Panel';
import Tooltip from 'react-bootstrap/lib/Tooltip';
import AppConstants from '../../constants/application_constants'; import AppConstants from '../../constants/application_constants';
import { mergeOptions } from '../../utils/general_utils'; import { mergeOptions } from '../../utils/general_utils';
let Property = React.createClass({ const { bool, element, string, oneOfType, func, object, arrayOf } = React.PropTypes;
propTypes: {
hidden: React.PropTypes.bool,
editable: React.PropTypes.bool, const Property = React.createClass({
propTypes: {
hidden: bool,
editable: bool,
// If we want Form to have a different value for disabled as Property has one for // If we want Form to have a different value for disabled as Property has one for
// editable, we need to set overrideForm to true, as it will then override Form's // editable, we need to set overrideForm to true, as it will then override Form's
// disabled value for individual Properties // disabled value for individual Properties
overrideForm: React.PropTypes.bool, overrideForm: bool,
tooltip: React.PropTypes.element, label: string,
label: React.PropTypes.string, value: oneOfType([
value: React.PropTypes.oneOfType([ string,
React.PropTypes.string, element
React.PropTypes.element
]), ]),
footer: React.PropTypes.element, footer: element,
handleChange: React.PropTypes.func, handleChange: func,
ignoreFocus: React.PropTypes.bool, ignoreFocus: bool,
name: React.PropTypes.string.isRequired, name: string.isRequired,
className: React.PropTypes.string, className: string,
onClick: React.PropTypes.func, onClick: func,
onChange: React.PropTypes.func, onChange: func,
onBlur: React.PropTypes.func, onBlur: func,
children: React.PropTypes.oneOfType([ children: oneOfType([
React.PropTypes.arrayOf(React.PropTypes.element), arrayOf(element),
React.PropTypes.element element
]), ]),
style: React.PropTypes.object style: object,
expanded: bool
}, },
getDefaultProps() { getDefaultProps() {
return { return {
editable: true, editable: true,
hidden: false, hidden: false,
expanded: true,
className: '' className: ''
}; };
}, },
@ -190,7 +192,7 @@ let Property = React.createClass({
}, },
getClassName() { getClassName() {
if(this.props.hidden){ if(this.props.hidden || !this.props.expanded){
return 'is-hidden'; return 'is-hidden';
} }
if(!this.props.editable){ if(!this.props.editable){
@ -235,16 +237,8 @@ let Property = React.createClass({
render() { render() {
let footer = null; let footer = null;
let tooltip = <span/>;
let style = this.props.style ? mergeOptions({}, this.props.style) : {}; let style = this.props.style ? mergeOptions({}, this.props.style) : {};
if(this.props.tooltip){
tooltip = (
<Tooltip>
{this.props.tooltip}
</Tooltip>);
}
if(this.props.footer){ if(this.props.footer){
footer = ( footer = (
<div className="ascribe-property-footer"> <div className="ascribe-property-footer">
@ -261,16 +255,16 @@ let Property = React.createClass({
className={'ascribe-property-wrapper ' + this.getClassName()} className={'ascribe-property-wrapper ' + this.getClassName()}
onClick={this.handleFocus} onClick={this.handleFocus}
style={style}> style={style}>
<OverlayTrigger <Panel
delay={500} collapsible
placement="top" expanded={this.props.expanded}
overlay={tooltip}> className="bs-custom-panel">
<div className={'ascribe-property ' + this.props.className}> <div className={'ascribe-property ' + this.props.className}>
{this.getLabelAndErrors()} {this.getLabelAndErrors()}
{this.renderChildren(style)} {this.renderChildren(style)}
{footer} {footer}
</div> </div>
</OverlayTrigger> </Panel>
</div> </div>
); );
} }

View File

@ -48,7 +48,8 @@ const ReactS3FineUploader = React.createClass({
number number
]) ])
}), }),
submitFile: func, handleSelectFiles: 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, autoUpload: bool,
debug: bool, debug: bool,
objectProperties: shape({ objectProperties: shape({
@ -522,7 +523,12 @@ const ReactS3FineUploader = React.createClass({
onCancel(id) { onCancel(id) {
// 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(() => {
if(typeof this.props.handleSelectFiles === 'function') {
this.props.handleSelectFiles(this.state.filesToUpload);
}
});
let notification = new GlobalNotificationModel(getLangText('File upload canceled'), 'success', 5000); let notification = new GlobalNotificationModel(getLangText('File upload canceled'), 'success', 5000);
GlobalNotificationActions.appendGlobalNotification(notification); GlobalNotificationActions.appendGlobalNotification(notification);
@ -616,7 +622,12 @@ const ReactS3FineUploader = React.createClass({
// //
// If there is an error during the deletion, we will just change the status back to 'online' // If there is an error during the deletion, we will just change the status back to 'online'
// and display an error message // and display an error message
this.setStatusOfFile(fileId, 'deleted'); this.setStatusOfFile(fileId, 'deleted')
.then(() => {
if(typeof this.props.handleSelectFiles === 'function') {
this.props.handleSelectFiles(this.state.filesToUpload);
}
});
// In some instances (when the file was already uploaded and is just displayed to the user // In some instances (when the file was already uploaded and is just displayed to the user
// - for example in the contract or additional files dialog) // - for example in the contract or additional files dialog)
@ -856,21 +867,35 @@ const ReactS3FineUploader = React.createClass({
// set the new file array // set the new file array
let filesToUpload = React.addons.update(this.state.filesToUpload, { $set: oldAndNewFiles }); let filesToUpload = React.addons.update(this.state.filesToUpload, { $set: oldAndNewFiles });
this.setState({ filesToUpload }); this.setState({ filesToUpload }, () => {
// when files have been dropped or selected by a user, we want to propagate that
// 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);
}
});
}, },
// This method has been made promise-based to immediately afterwards
// call a callback function (instantly after this.setState went through)
// This is e.g. needed when showing/hiding the optional thumbnail upload
// field in the registration form
setStatusOfFile(fileId, status) { setStatusOfFile(fileId, status) {
let changeSet = {}; return Q.Promise((resolve) => {
let changeSet = {};
if(status === 'deleted' || status === 'canceled') { if(status === 'deleted' || status === 'canceled') {
changeSet.progress = { $set: 0 }; changeSet.progress = { $set: 0 };
} }
changeSet.status = { $set: status }; changeSet.status = { $set: status };
let filesToUpload = React.addons.update(this.state.filesToUpload, { [fileId]: changeSet }); let filesToUpload = React.addons.update(this.state.filesToUpload, { [fileId]: changeSet });
this.setState({ filesToUpload }); this.setState({ filesToUpload }, resolve);
});
}, },
isDropzoneInactive() { isDropzoneInactive() {

View File

@ -85,8 +85,11 @@ const constants = {
'Bildrecht GmbH', 'SABAM', 'AUTVIS', 'CREAIMAGEN', 'SONECA', 'Copydan', 'EAU', 'Kuvasto', 'GCA', 'HUNGART', 'Bildrecht GmbH', 'SABAM', 'AUTVIS', 'CREAIMAGEN', 'SONECA', 'Copydan', 'EAU', 'Kuvasto', 'GCA', 'HUNGART',
'IVARO', 'SIAE', 'JASPAR-SPDA', 'AKKA/LAA', 'LATGA-A', 'SOMAAP', 'ARTEGESTION', 'CARIER', 'BONO', 'APSAV', 'IVARO', 'SIAE', 'JASPAR-SPDA', 'AKKA/LAA', 'LATGA-A', 'SOMAAP', 'ARTEGESTION', 'CARIER', 'BONO', 'APSAV',
'SPA', 'GESTOR', 'VISaRTA', 'RAO', 'LITA', 'DALRO', 'VeGaP', 'BUS', 'ProLitteris', 'AGADU', 'AUTORARTE', 'BUBEDRA', 'BBDA', 'BCDA', 'BURIDA', 'ADAVIS', 'BSDA'], 'SPA', 'GESTOR', 'VISaRTA', 'RAO', 'LITA', 'DALRO', 'VeGaP', 'BUS', 'ProLitteris', 'AGADU', 'AUTORARTE', 'BUBEDRA', 'BBDA', 'BCDA', 'BURIDA', 'ADAVIS', 'BSDA'],
'searchThreshold': 500, 'searchThreshold': 500,
'supportedThumbnailFileFormats': ['png', 'jpg', 'jpeg', 'gif', 'mp4'],
// in case of whitelabel customization, we store stuff here // in case of whitelabel customization, we store stuff here
'whitelabel': {}, 'whitelabel': {},

View File

@ -1,3 +1,8 @@
.panel {
/* Here we are overriding bootstrap to show the is-focused background color */
background-color: transparent;
}
.ascribe-panel-wrapper { .ascribe-panel-wrapper {
border: 1px solid #ddd; border: 1px solid #ddd;
height: 5em; height: 5em;