mirror of
https://github.com/ascribe/onion.git
synced 2024-12-22 17:33:14 +01:00
Merge remote-tracking branch 'remotes/origin/AD-496-add-control-buttons-to-fineupload' into AD-368-harmonize-functionality-of-ascrib
Conflicts: js/components/ascribe_uploader/react_s3_fine_uploader.js
This commit is contained in:
commit
e36681ad4d
@ -7,6 +7,7 @@ import FileDragAndDropPreviewIterator from './file_drag_and_drop_preview_iterato
|
|||||||
// Taken from: https://github.com/fedosejev/react-file-drag-and-drop
|
// Taken from: https://github.com/fedosejev/react-file-drag-and-drop
|
||||||
var FileDragAndDrop = React.createClass({
|
var FileDragAndDrop = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
|
className: React.PropTypes.string,
|
||||||
onDragStart: React.PropTypes.func,
|
onDragStart: React.PropTypes.func,
|
||||||
onDrop: React.PropTypes.func.isRequired,
|
onDrop: React.PropTypes.func.isRequired,
|
||||||
onDrag: React.PropTypes.func,
|
onDrag: React.PropTypes.func,
|
||||||
@ -17,6 +18,7 @@ var FileDragAndDrop = React.createClass({
|
|||||||
onDragEnd: React.PropTypes.func,
|
onDragEnd: React.PropTypes.func,
|
||||||
filesToUpload: React.PropTypes.array,
|
filesToUpload: React.PropTypes.array,
|
||||||
handleDeleteFile: React.PropTypes.func,
|
handleDeleteFile: React.PropTypes.func,
|
||||||
|
handleCancelFile: React.PropTypes.func,
|
||||||
multiple: React.PropTypes.bool,
|
multiple: React.PropTypes.bool,
|
||||||
dropzoneInactive: React.PropTypes.bool
|
dropzoneInactive: React.PropTypes.bool
|
||||||
},
|
},
|
||||||
@ -59,7 +61,6 @@ var FileDragAndDrop = React.createClass({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
handleDrop(event) {
|
handleDrop(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
@ -85,6 +86,13 @@ var FileDragAndDrop = React.createClass({
|
|||||||
this.props.handleDeleteFile(fileId);
|
this.props.handleDeleteFile(fileId);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
handleCancelFile(fileId) {
|
||||||
|
// input's value is not change the second time someone
|
||||||
|
// inputs the same file again, therefore we need to reset its value
|
||||||
|
this.refs.fileinput.getDOMNode().value = '';
|
||||||
|
this.props.handleCancelFile(fileId);
|
||||||
|
},
|
||||||
|
|
||||||
handleOnClick() {
|
handleOnClick() {
|
||||||
// when multiple is set to false and the user already uploaded a piece,
|
// when multiple is set to false and the user already uploaded a piece,
|
||||||
// do not propagate event
|
// do not propagate event
|
||||||
@ -99,9 +107,11 @@ var FileDragAndDrop = React.createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
render: function () {
|
render: function () {
|
||||||
let hasFiles = this.props.filesToUpload.length > 0;
|
// has files only is true if there are files that do not have the status deleted or canceled
|
||||||
let className = hasFiles ? 'file-drag-and-drop has-files ' : 'file-drag-and-drop ';
|
let hasFiles = this.props.filesToUpload.filter((file) => file.status !== 'deleted' && file.status !== 'canceled').length > 0;
|
||||||
|
let className = hasFiles ? 'has-files ' : '';
|
||||||
className += this.props.dropzoneInactive ? 'inactive-dropzone' : 'active-dropzone';
|
className += this.props.dropzoneInactive ? 'inactive-dropzone' : 'active-dropzone';
|
||||||
|
className += this.props.className ? ' ' + this.props.className : '';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@ -114,10 +124,11 @@ var FileDragAndDrop = React.createClass({
|
|||||||
onDragOver={this.handleDragOver}
|
onDragOver={this.handleDragOver}
|
||||||
onDrop={this.handleDrop}
|
onDrop={this.handleDrop}
|
||||||
onDragEnd={this.handleDragEnd}>
|
onDragEnd={this.handleDragEnd}>
|
||||||
{hasFiles ? null : this.props.multiple ? <span>Click or drag to add files</span> : <span>Click or drag to add a file</span>}
|
{hasFiles ? null : this.props.multiple ? <span className="file-drag-and-drop-dialog">Click or drag to add files</span> : <span className="file-drag-and-drop-dialog">Click or drag to add a file</span>}
|
||||||
<FileDragAndDropPreviewIterator
|
<FileDragAndDropPreviewIterator
|
||||||
files={this.props.filesToUpload}
|
files={this.props.filesToUpload}
|
||||||
handleDeleteFile={this.handleDeleteFile}/>
|
handleDeleteFile={this.handleDeleteFile}
|
||||||
|
handleCancelFile={this.handleCancelFile}/>
|
||||||
<input
|
<input
|
||||||
multiple={this.props.multiple}
|
multiple={this.props.multiple}
|
||||||
ref="fileinput"
|
ref="fileinput"
|
||||||
|
@ -13,17 +13,19 @@ let FileDragAndDropPreview = React.createClass({
|
|||||||
url: React.PropTypes.string,
|
url: React.PropTypes.string,
|
||||||
type: React.PropTypes.string
|
type: React.PropTypes.string
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
handleDeleteFile: React.PropTypes.func
|
handleDeleteFile: React.PropTypes.func,
|
||||||
|
handleCancelFile: React.PropTypes.func
|
||||||
},
|
},
|
||||||
|
|
||||||
handleDeleteFile(event) {
|
handleDeleteFile() {
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
|
|
||||||
// handleDeleteFile is optional, so if its not submitted,
|
// handleDeleteFile is optional, so if its not submitted,
|
||||||
// don't run it
|
// don't run it
|
||||||
if(this.props.handleDeleteFile) {
|
// On the other hand, if the files progress is not yet at a 100%,
|
||||||
|
// just run fineuploader.cancel
|
||||||
|
if(this.props.handleDeleteFile && this.props.file.progress === 100) {
|
||||||
this.props.handleDeleteFile(this.props.file.id);
|
this.props.handleDeleteFile(this.props.file.id);
|
||||||
|
} else if(this.props.handleCancelFile && this.props.file.progress !== 100) {
|
||||||
|
this.props.handleCancelFile(this.props.file.id);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ProgressBar from 'react-progressbar';
|
import ProgressBar from 'react-progressbar';
|
||||||
|
|
||||||
|
import AppConstants from '../../constants/application_constants';
|
||||||
|
|
||||||
let FileDragAndDropPreviewImage = React.createClass({
|
let FileDragAndDropPreviewImage = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
progress: React.PropTypes.number,
|
progress: React.PropTypes.number,
|
||||||
@ -10,19 +12,36 @@ let FileDragAndDropPreviewImage = React.createClass({
|
|||||||
onClick: React.PropTypes.func
|
onClick: React.PropTypes.func
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getInitialState() {
|
||||||
|
return {
|
||||||
|
loading: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
onClick(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
loading: true
|
||||||
|
});
|
||||||
|
|
||||||
|
this.props.onClick(e);
|
||||||
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let imageStyle = {
|
let imageStyle = {
|
||||||
backgroundImage: 'url("' + this.props.url + '")',
|
backgroundImage: 'url("' + this.props.url + '")',
|
||||||
backgroundSize: 'cover'
|
backgroundSize: 'cover'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let actionSymbol = this.state.loading ? <img src={AppConstants.baseUrl + 'static/img/ascribe_animated_medium.gif'} /> : <span className="glyphicon glyphicon-remove delete-file" aria-hidden="true" title="Delete or cancel upload" onClick={this.onClick} />;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
onClick={this.props.onClick}
|
|
||||||
className="file-drag-and-drop-preview-image"
|
className="file-drag-and-drop-preview-image"
|
||||||
style={imageStyle}>
|
style={imageStyle}>
|
||||||
<ProgressBar completed={this.props.progress} color="black"/>
|
<ProgressBar completed={this.props.progress} color="black"/>
|
||||||
{this.props.progress === 100 ? <span className="glyphicon glyphicon-remove delete-file" aria-hidden="true" title="Delete"></span> : null}
|
{actionSymbol}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,8 @@ import FileDragAndDropPreview from './file_drag_and_drop_preview';
|
|||||||
let FileDragAndDropPreviewIterator = React.createClass({
|
let FileDragAndDropPreviewIterator = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
files: React.PropTypes.array,
|
files: React.PropTypes.array,
|
||||||
handleDeleteFile: React.PropTypes.func
|
handleDeleteFile: React.PropTypes.func,
|
||||||
|
handleCancelFile: React.PropTypes.func
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -15,12 +16,17 @@ let FileDragAndDropPreviewIterator = React.createClass({
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{this.props.files.map((file, i) => {
|
{this.props.files.map((file, i) => {
|
||||||
return (
|
if(file.status !== 'deleted' && file.status !== 'canceled') {
|
||||||
<FileDragAndDropPreview
|
return (
|
||||||
key={i}
|
<FileDragAndDropPreview
|
||||||
file={file}
|
key={i}
|
||||||
handleDeleteFile={this.props.handleDeleteFile}/>
|
file={file}
|
||||||
);
|
handleDeleteFile={this.props.handleDeleteFile}
|
||||||
|
handleCancelFile={this.props.handleCancelFile}/>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ProgressBar from 'react-progressbar';
|
import ProgressBar from 'react-progressbar';
|
||||||
|
|
||||||
|
import AppConstants from '../../constants/application_constants';
|
||||||
|
|
||||||
let FileDragAndDropPreviewOther = React.createClass({
|
let FileDragAndDropPreviewOther = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
type: React.PropTypes.string,
|
type: React.PropTypes.string,
|
||||||
@ -10,15 +12,32 @@ let FileDragAndDropPreviewOther = React.createClass({
|
|||||||
onClick: React.PropTypes.func
|
onClick: React.PropTypes.func
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getInitialState() {
|
||||||
|
return {
|
||||||
|
loading: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
onClick(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
loading: true
|
||||||
|
});
|
||||||
|
|
||||||
|
this.props.onClick(e);
|
||||||
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
let actionSymbol = this.state.loading ? <img src={AppConstants.baseUrl + 'static/img/ascribe_animated_medium.gif'} /> : <span className="glyphicon glyphicon-remove delete-file" aria-hidden="true" title="Delete or cancel upload" onClick={this.onClick} />;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
onClick={this.props.onClick}
|
|
||||||
className="file-drag-and-drop-preview">
|
className="file-drag-and-drop-preview">
|
||||||
<ProgressBar completed={this.props.progress} color="black"/>
|
<ProgressBar completed={this.props.progress} color="black"/>
|
||||||
<div className="file-drag-and-drop-preview-table-wrapper">
|
<div className="file-drag-and-drop-preview-table-wrapper">
|
||||||
<div className="file-drag-and-drop-preview-other">
|
<div className="file-drag-and-drop-preview-other">
|
||||||
{this.props.progress === 100 ? <span className="glyphicon glyphicon-remove delete-file" aria-hidden="true" title="Delete"></span> : null}
|
{actionSymbol}
|
||||||
<span>{'.' + this.props.type}</span>
|
<span>{'.' + this.props.type}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
13
js/components/ascribe_uploader/file_drag_and_drop_toolbar.js
Normal file
13
js/components/ascribe_uploader/file_drag_and_drop_toolbar.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
let FileDragAndDropToolbar = React.createClass({
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div></div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default FileDragAndDropToolbar;
|
@ -12,6 +12,7 @@ import { getCookie } from '../../utils/fetch_api_utils';
|
|||||||
|
|
||||||
import fineUploader from 'fineUploader';
|
import fineUploader from 'fineUploader';
|
||||||
import FileDragAndDrop from './file_drag_and_drop';
|
import FileDragAndDrop from './file_drag_and_drop';
|
||||||
|
import FileDragAndDropToolbar from './file_drag_and_drop_toolbar';
|
||||||
|
|
||||||
import GlobalNotificationModel from '../../models/global_notification_model';
|
import GlobalNotificationModel from '../../models/global_notification_model';
|
||||||
import GlobalNotificationActions from '../../actions/global_notification_actions';
|
import GlobalNotificationActions from '../../actions/global_notification_actions';
|
||||||
@ -27,7 +28,7 @@ var ReactS3FineUploader = React.createClass({
|
|||||||
createBlobRoutine: React.PropTypes.shape({
|
createBlobRoutine: React.PropTypes.shape({
|
||||||
url: React.PropTypes.string
|
url: React.PropTypes.string
|
||||||
}),
|
}),
|
||||||
handleChange: React.PropTypes.func,
|
submitKey: React.PropTypes.func,
|
||||||
autoUpload: React.PropTypes.bool,
|
autoUpload: React.PropTypes.bool,
|
||||||
debug: React.PropTypes.bool,
|
debug: React.PropTypes.bool,
|
||||||
objectProperties: React.PropTypes.shape({
|
objectProperties: React.PropTypes.shape({
|
||||||
@ -63,7 +64,8 @@ var ReactS3FineUploader = React.createClass({
|
|||||||
deleteFile: React.PropTypes.shape({
|
deleteFile: React.PropTypes.shape({
|
||||||
enabled: React.PropTypes.bool,
|
enabled: React.PropTypes.bool,
|
||||||
method: React.PropTypes.string,
|
method: React.PropTypes.string,
|
||||||
endpoint: React.PropTypes.string
|
endpoint: React.PropTypes.string,
|
||||||
|
customHeaders: React.PropTypes.object
|
||||||
}),
|
}),
|
||||||
session: React.PropTypes.shape({
|
session: React.PropTypes.shape({
|
||||||
endpoint: React.PropTypes.bool
|
endpoint: React.PropTypes.bool
|
||||||
@ -79,15 +81,11 @@ var ReactS3FineUploader = React.createClass({
|
|||||||
multiple: React.PropTypes.bool,
|
multiple: React.PropTypes.bool,
|
||||||
retry: React.PropTypes.shape({
|
retry: React.PropTypes.shape({
|
||||||
enableAuto: React.PropTypes.bool
|
enableAuto: React.PropTypes.bool
|
||||||
})
|
}),
|
||||||
|
setUploadStatus: React.PropTypes.func,
|
||||||
|
isReadyForFormSubmission: React.PropTypes.func
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState() {
|
|
||||||
return {
|
|
||||||
filesToUpload: [],
|
|
||||||
uploader: new fineUploader.s3.FineUploaderBasic(this.propsToConfig())
|
|
||||||
};
|
|
||||||
},
|
|
||||||
getDefaultProps() {
|
getDefaultProps() {
|
||||||
return {
|
return {
|
||||||
autoUpload: true,
|
autoUpload: true,
|
||||||
@ -108,7 +106,7 @@ var ReactS3FineUploader = React.createClass({
|
|||||||
signature: {
|
signature: {
|
||||||
endpoint: AppConstants.serverUrl + 's3/signature/',
|
endpoint: AppConstants.serverUrl + 's3/signature/',
|
||||||
customHeaders: {
|
customHeaders: {
|
||||||
'X-CSRFToken': getCookie('csrftoken')
|
'X-CSRFToken': getCookie('csrftoken')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
deleteFile: {
|
deleteFile: {
|
||||||
@ -116,7 +114,7 @@ var ReactS3FineUploader = React.createClass({
|
|||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
endpoint: AppConstants.serverUrl + 's3/delete',
|
endpoint: AppConstants.serverUrl + 's3/delete',
|
||||||
customHeaders: {
|
customHeaders: {
|
||||||
'X-CSRFToken': getCookie('csrftoken')
|
'X-CSRFToken': getCookie('csrftoken')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
cors: {
|
cors: {
|
||||||
@ -147,6 +145,14 @@ var ReactS3FineUploader = React.createClass({
|
|||||||
multiple: false
|
multiple: false
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getInitialState() {
|
||||||
|
return {
|
||||||
|
filesToUpload: [],
|
||||||
|
uploader: new fineUploader.s3.FineUploaderBasic(this.propsToConfig())
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
propsToConfig() {
|
propsToConfig() {
|
||||||
let objectProperties = this.props.objectProperties;
|
let objectProperties = this.props.objectProperties;
|
||||||
objectProperties.key = this.requestKey;
|
objectProperties.key = this.requestKey;
|
||||||
@ -171,6 +177,7 @@ var ReactS3FineUploader = React.createClass({
|
|||||||
callbacks: {
|
callbacks: {
|
||||||
onSubmit: this.onSubmit,
|
onSubmit: this.onSubmit,
|
||||||
onComplete: this.onComplete,
|
onComplete: this.onComplete,
|
||||||
|
onCancel: this.onCancel,
|
||||||
onDelete: this.onDelete,
|
onDelete: this.onDelete,
|
||||||
onSessionRequestComplete: this.onSessionRequestComplete,
|
onSessionRequestComplete: this.onSessionRequestComplete,
|
||||||
onProgress: this.onProgress,
|
onProgress: this.onProgress,
|
||||||
@ -235,8 +242,16 @@ var ReactS3FineUploader = React.createClass({
|
|||||||
});
|
});
|
||||||
this.setState(newState);
|
this.setState(newState);
|
||||||
this.createBlob(files[id]);
|
this.createBlob(files[id]);
|
||||||
this.props.handleChange();
|
this.props.submitKey(files[id].key);
|
||||||
console.log('completed ' + files[id].name);
|
|
||||||
|
// also, lets check if after the completion of this upload,
|
||||||
|
// the form is ready for submission or not
|
||||||
|
if(this.props.isReadyForFormSubmission && this.props.isReadyForFormSubmission(this.state.filesToUpload)) {
|
||||||
|
// if so, set uploadstatus to true
|
||||||
|
this.props.setUploadStatus(true);
|
||||||
|
} else {
|
||||||
|
this.props.setUploadStatus(false);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
createBlob(file) {
|
createBlob(file) {
|
||||||
@ -282,13 +297,18 @@ var ReactS3FineUploader = React.createClass({
|
|||||||
console.log('delete');
|
console.log('delete');
|
||||||
},
|
},
|
||||||
|
|
||||||
onCancel() {
|
onCancel(id) {
|
||||||
console.log('cancel');
|
this.removeFileWithIdFromFilesToUpload(id);
|
||||||
// handle file removal here, for this.state.filesToUpload (same as in onDeleteComplete)
|
|
||||||
},
|
|
||||||
|
|
||||||
onSessionRequestComplete() {
|
let notification = new GlobalNotificationModel('File upload canceled', 'success', 5000);
|
||||||
console.log('sessionrequestcomplete');
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
|
|
||||||
|
if(this.props.isReadyForFormSubmission && this.props.isReadyForFormSubmission(this.state.filesToUpload)) {
|
||||||
|
// if so, set uploadstatus to true
|
||||||
|
this.props.setUploadStatus(true);
|
||||||
|
} else {
|
||||||
|
this.props.setUploadStatus(false);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onDeleteComplete(id, xhr, isError) {
|
onDeleteComplete(id, xhr, isError) {
|
||||||
@ -296,21 +316,18 @@ var ReactS3FineUploader = React.createClass({
|
|||||||
let notification = new GlobalNotificationModel('Couldn\'t delete file', 'danger', 10000);
|
let notification = new GlobalNotificationModel('Couldn\'t delete file', 'danger', 10000);
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
} else {
|
} else {
|
||||||
// also, sync files from state with the ones from fineuploader
|
this.removeFileWithIdFromFilesToUpload(id);
|
||||||
let filesToUpload = JSON.parse(JSON.stringify(this.state.filesToUpload));
|
|
||||||
|
|
||||||
// splice because I can
|
let notification = new GlobalNotificationModel('File deleted', 'success', 5000);
|
||||||
filesToUpload.splice(id, 1);
|
|
||||||
|
|
||||||
// set state
|
|
||||||
let newState = React.addons.update(this.state, {
|
|
||||||
filesToUpload: { $set: filesToUpload }
|
|
||||||
});
|
|
||||||
this.setState(newState);
|
|
||||||
|
|
||||||
let notification = new GlobalNotificationModel('File deleted', 'success', 10000);
|
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(this.props.isReadyForFormSubmission && this.props.isReadyForFormSubmission(this.state.filesToUpload)) {
|
||||||
|
// if so, set uploadstatus to true
|
||||||
|
this.props.setUploadStatus(true);
|
||||||
|
} else {
|
||||||
|
this.props.setUploadStatus(false);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onProgress(id, name, uploadedBytes, totalBytes) {
|
onProgress(id, name, uploadedBytes, totalBytes) {
|
||||||
@ -330,11 +347,15 @@ var ReactS3FineUploader = React.createClass({
|
|||||||
// promise
|
// promise
|
||||||
},
|
},
|
||||||
|
|
||||||
|
handleCancelFile(fileId) {
|
||||||
|
this.state.uploader.cancel(fileId);
|
||||||
|
},
|
||||||
|
|
||||||
handleUploadFile(files) {
|
handleUploadFile(files) {
|
||||||
|
|
||||||
// If multiple set and user already uploaded its work,
|
// If multiple set and user already uploaded its work,
|
||||||
// cancel upload
|
// cancel upload
|
||||||
if(!this.props.multiple && this.state.filesToUpload.length > 0) {
|
if(!this.props.multiple && this.state.filesToUpload.filter((file) => file.status !== 'deleted' && file.status !== 'canceled').length > 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,24 +394,45 @@ var ReactS3FineUploader = React.createClass({
|
|||||||
oldAndNewFiles[i].progress = oldFiles[j].progress;
|
oldAndNewFiles[i].progress = oldFiles[j].progress;
|
||||||
oldAndNewFiles[i].type = oldFiles[j].type;
|
oldAndNewFiles[i].type = oldFiles[j].type;
|
||||||
oldAndNewFiles[i].url = oldFiles[j].url;
|
oldAndNewFiles[i].url = oldFiles[j].url;
|
||||||
|
oldAndNewFiles[i].key = oldFiles[j].key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set the new file array
|
||||||
let newState = React.addons.update(this.state, {
|
let newState = React.addons.update(this.state, {
|
||||||
filesToUpload: { $set: oldAndNewFiles }
|
filesToUpload: { $set: oldAndNewFiles }
|
||||||
});
|
});
|
||||||
this.setState(newState);
|
this.setState(newState);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
removeFileWithIdFromFilesToUpload(fileId) {
|
||||||
|
// also, sync files from state with the ones from fineuploader
|
||||||
|
let filesToUpload = JSON.parse(JSON.stringify(this.state.filesToUpload));
|
||||||
|
|
||||||
|
// splice because I can
|
||||||
|
filesToUpload.splice(fileId, 1);
|
||||||
|
|
||||||
|
// set state
|
||||||
|
let newState = React.addons.update(this.state, {
|
||||||
|
filesToUpload: { $set: filesToUpload }
|
||||||
|
});
|
||||||
|
this.setState(newState);
|
||||||
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<FileDragAndDrop
|
<div>
|
||||||
onDrop={this.handleUploadFile}
|
<FileDragAndDrop
|
||||||
filesToUpload={this.state.filesToUpload}
|
className="file-drag-and-drop"
|
||||||
handleDeleteFile={this.handleDeleteFile}
|
onDrop={this.handleUploadFile}
|
||||||
multiple={this.props.multiple}
|
filesToUpload={this.state.filesToUpload}
|
||||||
dropzoneInactive={!this.props.multiple && this.state.filesToUpload.length > 0} />
|
handleDeleteFile={this.handleDeleteFile}
|
||||||
|
handleCancelFile={this.handleCancelFile}
|
||||||
|
multiple={this.props.multiple}
|
||||||
|
dropzoneInactive={!this.props.multiple && this.state.filesToUpload.filter((file) => file.status !== 'deleted' && file.status !== 'canceled').length > 0} />
|
||||||
|
<FileDragAndDropToolbar />
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -434,12 +434,40 @@ let EditionFurtherDetails = React.createClass({
|
|||||||
edition: React.PropTypes.object,
|
edition: React.PropTypes.object,
|
||||||
handleSuccess: React.PropTypes.func
|
handleSuccess: React.PropTypes.func
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getInitialState() {
|
||||||
|
return {
|
||||||
|
loading: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
showNotification(){
|
showNotification(){
|
||||||
this.props.handleSuccess();
|
this.props.handleSuccess();
|
||||||
let notification = new GlobalNotificationModel('Details updated', 'success');
|
let notification = new GlobalNotificationModel('Details updated', 'success');
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
submitKey(key){
|
||||||
|
this.setState({
|
||||||
|
otherDataKey: key
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setUploadStatus(isReady) {
|
||||||
|
this.setState({
|
||||||
|
uploadStatus: isReady
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
isReadyForFormSubmission(files) {
|
||||||
|
files = files.filter((file) => file.status !== 'deleted' && file.status !== 'canceled');
|
||||||
|
if(files.length > 0 && files[0].status === 'upload successful') {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let editable = this.props.edition.acl.indexOf('edit') > -1;
|
let editable = this.props.edition.acl.indexOf('edit') > -1;
|
||||||
return (
|
return (
|
||||||
@ -464,22 +492,26 @@ let EditionFurtherDetails = React.createClass({
|
|||||||
editable={editable}
|
editable={editable}
|
||||||
edition={this.props.edition} />
|
edition={this.props.edition} />
|
||||||
<FileUploader
|
<FileUploader
|
||||||
edition={this.props.edition}
|
submitKey={this.submitKey}
|
||||||
ref='uploader'/>
|
setUploadStatus={this.setUploadStatus}
|
||||||
|
isReadyForFormSubmission={this.isReadyForFormSubmission}
|
||||||
|
edition={this.props.edition}/>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let FileUploader = React.createClass( {
|
let FileUploader = React.createClass({
|
||||||
handleChange(){
|
propTypes: {
|
||||||
this.setState({other_data_key: this.refs.fineuploader.state.filesToUpload[0].key});
|
setUploadStatus: React.PropTypes.func,
|
||||||
|
submitKey: React.PropTypes.func,
|
||||||
|
isReadyForFormSubmission: React.PropTypes.func
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<ReactS3FineUploader
|
<ReactS3FineUploader
|
||||||
ref='fineuploader'
|
|
||||||
keyRoutine={{
|
keyRoutine={{
|
||||||
url: AppConstants.serverUrl + 's3/key/',
|
url: AppConstants.serverUrl + 's3/key/',
|
||||||
fileClass: 'otherdata',
|
fileClass: 'otherdata',
|
||||||
@ -488,11 +520,13 @@ let FileUploader = React.createClass( {
|
|||||||
createBlobRoutine={{
|
createBlobRoutine={{
|
||||||
url: apiUrls.blob_digitalworks
|
url: apiUrls.blob_digitalworks
|
||||||
}}
|
}}
|
||||||
handleChange={this.handleChange}
|
|
||||||
validation={{
|
validation={{
|
||||||
itemLimit: 100000,
|
itemLimit: 100000,
|
||||||
sizeLimit: '10000000'
|
sizeLimit: '10000000'
|
||||||
}}/>
|
}}
|
||||||
|
submitKey={this.props.submitKey}
|
||||||
|
setUploadStatus={this.props.setUploadStatus}
|
||||||
|
isReadyForFormSubmission={this.props.isReadyForFormSubmission}/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -24,8 +24,12 @@ let RegisterPiece = React.createClass( {
|
|||||||
mixins: [Router.Navigation],
|
mixins: [Router.Navigation],
|
||||||
|
|
||||||
getInitialState(){
|
getInitialState(){
|
||||||
return {digital_work_key: null};
|
return {
|
||||||
|
digitalWorkKey: null,
|
||||||
|
uploadStatus: false
|
||||||
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
handleSuccess(){
|
handleSuccess(){
|
||||||
let notification = new GlobalNotificationModel('Login successsful', 'success', 10000);
|
let notification = new GlobalNotificationModel('Login successsful', 'success', 10000);
|
||||||
GlobalNotificationActions.appendGlobalNotification(notification);
|
GlobalNotificationActions.appendGlobalNotification(notification);
|
||||||
@ -37,30 +41,44 @@ let RegisterPiece = React.createClass( {
|
|||||||
for (let ref in this.refs.form.refs){
|
for (let ref in this.refs.form.refs){
|
||||||
data[this.refs.form.refs[ref].props.name] = this.refs.form.refs[ref].state.value;
|
data[this.refs.form.refs[ref].props.name] = this.refs.form.refs[ref].state.value;
|
||||||
}
|
}
|
||||||
data.digital_work_key = this.state.digital_work_key;
|
data.digital_work_key = this.state.digitalWorkKey;
|
||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
handleChange(){
|
|
||||||
this.setState({digital_work_key: this.refs.uploader.refs.fineuploader.state.filesToUpload[0].key});
|
submitKey(key){
|
||||||
|
this.setState({
|
||||||
|
digitalWorkKey: key
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setUploadStatus(isReady) {
|
||||||
|
this.setState({
|
||||||
|
uploadStatus: isReady
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
isReadyForFormSubmission(files) {
|
||||||
|
files = files.filter((file) => file.status !== 'deleted' && file.status !== 'canceled');
|
||||||
|
if(files.length > 0 && files[0].status === 'upload successful') {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let buttons = null;
|
let buttons = null;
|
||||||
if (this.refs.uploader && this.refs.uploader.refs.fineuploader.state.filesToUpload[0].status === 'upload successful'){
|
|
||||||
|
if (this.state.uploadStatus){
|
||||||
buttons = (
|
buttons = (
|
||||||
<button type="submit" className="btn ascribe-btn ascribe-btn-login">
|
<button type="submit" className="btn ascribe-btn ascribe-btn-login">
|
||||||
Register your artwork
|
Register your artwork
|
||||||
</button>);
|
</button>);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="row ascribe-row">
|
<div className="row ascribe-row">
|
||||||
<div className="col-md-5">
|
<div className="col-md-12">
|
||||||
<FileUploader
|
|
||||||
ref='uploader'
|
|
||||||
handleChange={this.handleChange}/>
|
|
||||||
<br />
|
|
||||||
</div>
|
|
||||||
<div className="col-md-7">
|
|
||||||
<h3 style={{'marginTop': 0}}>Lock down title</h3>
|
<h3 style={{'marginTop': 0}}>Lock down title</h3>
|
||||||
<Form
|
<Form
|
||||||
ref='form'
|
ref='form'
|
||||||
@ -73,6 +91,13 @@ let RegisterPiece = React.createClass( {
|
|||||||
<img src="https://s3-us-west-2.amazonaws.com/ascribe0/media/thumbnails/ascribe_animated_medium.gif" />
|
<img src="https://s3-us-west-2.amazonaws.com/ascribe0/media/thumbnails/ascribe_animated_medium.gif" />
|
||||||
</button>
|
</button>
|
||||||
}>
|
}>
|
||||||
|
<Property
|
||||||
|
label="Files to upload">
|
||||||
|
<FileUploader
|
||||||
|
submitKey={this.submitKey}
|
||||||
|
setUploadStatus={this.setUploadStatus}
|
||||||
|
isReadyForFormSubmission={this.isReadyForFormSubmission}/>
|
||||||
|
</Property>
|
||||||
<Property
|
<Property
|
||||||
name='artist_name'
|
name='artist_name'
|
||||||
label="Artist Name">
|
label="Artist Name">
|
||||||
@ -116,11 +141,16 @@ let RegisterPiece = React.createClass( {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
let FileUploader = React.createClass( {
|
let FileUploader = React.createClass({
|
||||||
|
propTypes: {
|
||||||
|
setUploadStatus: React.PropTypes.func,
|
||||||
|
submitKey: React.PropTypes.func,
|
||||||
|
isReadyForFormSubmission: React.PropTypes.func
|
||||||
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<ReactS3FineUploader
|
<ReactS3FineUploader
|
||||||
ref='fineuploader'
|
|
||||||
keyRoutine={{
|
keyRoutine={{
|
||||||
url: AppConstants.serverUrl + 's3/key/',
|
url: AppConstants.serverUrl + 's3/key/',
|
||||||
fileClass: 'digitalwork'
|
fileClass: 'digitalwork'
|
||||||
@ -128,11 +158,13 @@ let FileUploader = React.createClass( {
|
|||||||
createBlobRoutine={{
|
createBlobRoutine={{
|
||||||
url: apiUrls.blob_digitalworks
|
url: apiUrls.blob_digitalworks
|
||||||
}}
|
}}
|
||||||
handleChange={this.props.handleChange}
|
submitKey={this.props.submitKey}
|
||||||
validation={{
|
validation={{
|
||||||
itemLimit: 100000,
|
itemLimit: 100000,
|
||||||
sizeLimit: '25000000000'
|
sizeLimit: '25000000000'
|
||||||
}}/>
|
}}
|
||||||
|
setUploadStatus={this.props.setUploadStatus}
|
||||||
|
isReadyForFormSubmission={this.props.isReadyForFormSubmission}/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -68,12 +68,14 @@
|
|||||||
|
|
||||||
padding-top: 1em;
|
padding-top: 1em;
|
||||||
padding-left: 1.5em;
|
padding-left: 1.5em;
|
||||||
|
padding-right: 1.5em;
|
||||||
|
|
||||||
cursor:pointer;
|
cursor:pointer;
|
||||||
|
|
||||||
input, div, span, pre, textarea, select {
|
input, div, span:not(.glyphicon), pre, textarea, select {
|
||||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
@ -81,8 +83,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
div {
|
div {
|
||||||
margin-top: 10px;
|
/* margin-top: 10px; */
|
||||||
div {
|
div:not(.file-drag-and-drop div) {
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
@ -92,6 +94,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.progressbar-container, .progressbar-progress {
|
||||||
|
margin-top: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
input, pre, textarea, select {
|
input, pre, textarea, select {
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 1.1em;
|
font-size: 1.1em;
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
.file-drag-and-drop {
|
.file-drag-and-drop {
|
||||||
display: table-cell;
|
display: block;
|
||||||
outline: 1px dashed #616161;
|
outline: 1px dashed #616161;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
height:208px;
|
height: auto;
|
||||||
width: 672px;
|
|
||||||
background-color: #FAFAFA;
|
background-color: #FAFAFA;
|
||||||
transition: .1s linear background-color;
|
overflow: auto;
|
||||||
|
margin-top: 1em;
|
||||||
|
|
||||||
|
padding: 3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.inactive-dropzone {
|
.inactive-dropzone {
|
||||||
@ -22,25 +24,34 @@
|
|||||||
background-color: rgba(72, 218, 203, 0.2);
|
background-color: rgba(72, 218, 203, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-drag-and-drop > span {
|
.file-drag-and-drop .file-drag-and-drop-dialog {
|
||||||
font-size: 1.5em;
|
font-size: 1.25em !important;
|
||||||
|
|
||||||
|
margin-top: 1em;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
content: ' ';
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle; /* vertical alignment of the inline element */
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.has-files {
|
.has-files {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
padding: 3em 0 0 0;
|
padding: 4% 0 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-drag-and-drop-position {
|
.file-drag-and-drop-position {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin: 0 0 3em 3em;
|
margin: 0 0 4% 4%;
|
||||||
float:left;
|
float:left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-drag-and-drop-preview-table-wrapper {
|
.file-drag-and-drop-preview-table-wrapper {
|
||||||
display: table;
|
display: table;
|
||||||
height:94px;
|
height:64px;
|
||||||
width:104px;
|
width:74px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-drag-and-drop-preview {
|
.file-drag-and-drop-preview {
|
||||||
@ -52,16 +63,16 @@
|
|||||||
|
|
||||||
.file-drag-and-drop-preview-image {
|
.file-drag-and-drop-preview-image {
|
||||||
display: table;
|
display: table;
|
||||||
height:104px;
|
height:74px;
|
||||||
width:104px;
|
width:74px;
|
||||||
overflow:hidden;
|
overflow:hidden;
|
||||||
border: 1px solid #616161;
|
border: 1px solid #616161;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-drag-and-drop-preview-image .delete-file {
|
.file-drag-and-drop-preview-image .delete-file {
|
||||||
font-size: 3em;
|
font-size: 2.5em;
|
||||||
margin-top: .5em;
|
margin-top: .3em;
|
||||||
color: white;
|
color: white;
|
||||||
text-shadow: -2px 0 black, 0 2px black, 2px 0 black, 0 -2px black;
|
text-shadow: -2px 0 black, 0 2px black, 2px 0 black, 0 -2px black;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@ -73,9 +84,9 @@
|
|||||||
|
|
||||||
.file-drag-and-drop-preview-other .delete-file {
|
.file-drag-and-drop-preview-other .delete-file {
|
||||||
position: relative;
|
position: relative;
|
||||||
top: .45em;
|
top: .3em;
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
font-size: 3em;
|
font-size: 2.5em;
|
||||||
color: white;
|
color: white;
|
||||||
text-shadow: -2px 0 black, 0 2px black, 2px 0 black, 0 -2px black;
|
text-shadow: -2px 0 black, 0 2px black, 2px 0 black, 0 -2px black;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@ -94,5 +105,5 @@
|
|||||||
|
|
||||||
.file-drag-and-drop-preview-other span:not(:first-child) {
|
.file-drag-and-drop-preview-other span:not(:first-child) {
|
||||||
display: block;
|
display: block;
|
||||||
margin-top: 1.5em;
|
margin-top: .5em;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user