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:
parent
2ffc26d703
commit
971d42b36d
@ -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={{
|
||||||
|
@ -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}/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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() {
|
||||||
|
@ -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': {},
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user