mirror of
https://github.com/ascribe/onion.git
synced 2024-12-22 09:23:13 +01:00
Remove old uploaders
This commit is contained in:
parent
819b367896
commit
1069121e07
@ -1,119 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import Property from './../ascribe_forms/property';
|
||||
|
||||
import ReactS3FineUploader from './../ascribe_uploader/react_s3_fine_uploader';
|
||||
|
||||
import AppConstants from '../../constants/application_constants';
|
||||
import { ValidationTypes } from '../../constants/uploader_constants';
|
||||
|
||||
import { makeCsrfHeader } from '../../utils/csrf';
|
||||
import { getLangText } from '../../utils/lang';
|
||||
import { resolveUrl } from '../../utils/url_resolver';
|
||||
|
||||
|
||||
const { func, bool, number, object, string, arrayOf } = React.PropTypes;
|
||||
|
||||
let FurtherDetailsFileuploader = React.createClass({
|
||||
propTypes: {
|
||||
pieceId: number.isRequired,
|
||||
|
||||
editable: bool,
|
||||
label: string,
|
||||
otherData: arrayOf(object),
|
||||
|
||||
// Props for ReactS3FineUploader
|
||||
areAssetsDownloadable: bool,
|
||||
isReadyForFormSubmission: func,
|
||||
submitFile: func, // TODO: rename to onSubmitFile
|
||||
onValidationFailed: func,
|
||||
multiple: bool,
|
||||
setIsUploadReady: func, //TODO: rename to setIsUploaderValidated
|
||||
showErrorPrompt: bool,
|
||||
validation: ReactS3FineUploader.propTypes.validation
|
||||
},
|
||||
|
||||
getDefaultProps() {
|
||||
return {
|
||||
areAssetsDownloadable: true,
|
||||
label: getLangText('Additional files'),
|
||||
multiple: false,
|
||||
validation: ValidationTypes.additionalData
|
||||
};
|
||||
},
|
||||
|
||||
render() {
|
||||
const { editable,
|
||||
isReadyForFormSubmission,
|
||||
multiple,
|
||||
onValidationFailed,
|
||||
otherData,
|
||||
pieceId,
|
||||
setIsUploadReady,
|
||||
showErrorPrompt,
|
||||
submitFile,
|
||||
validation } = this.props;
|
||||
|
||||
// Essentially there a three cases important to the fileuploader
|
||||
//
|
||||
// 1. there is no other_data => do not show the fileuploader at all (where otherData is now an array)
|
||||
// 2. there is other_data, but user has no edit rights => show fileuploader but without action buttons
|
||||
// 3. both other_data and editable are defined or true => show fileuploader with all action buttons
|
||||
if (!editable && (!otherData || otherData.length === 0)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let otherDataIds = otherData ? otherData.map((data) => data.id).join() : null;
|
||||
|
||||
return (
|
||||
<Property
|
||||
name="other_data_key"
|
||||
label={this.props.label}>
|
||||
<ReactS3FineUploader
|
||||
areAssetsDownloadable
|
||||
areAssetsEditable={editable}
|
||||
createBlobRoutine={{
|
||||
url: resolveUrl('blob_otherdatas'),
|
||||
pieceId: pieceId
|
||||
}}
|
||||
deleteFile={{
|
||||
enabled: true,
|
||||
method: 'DELETE',
|
||||
endpoint: `${AppConstants.serverUrl}/s3/delete`,
|
||||
customHeaders: makeCsrfHeader()
|
||||
}}
|
||||
isReadyForFormSubmission={isReadyForFormSubmission}
|
||||
keyRoutine={{
|
||||
url: `${AppConstants.serverUrl}/s3/key/`,
|
||||
fileClass: 'otherdata',
|
||||
pieceId: pieceId
|
||||
}}
|
||||
multiple={multiple}
|
||||
onValidationFailed={onValidationFailed}
|
||||
setIsUploadReady={setIsUploadReady}
|
||||
session={{
|
||||
endpoint: `${AppConstants.serverUrl}/api/blob/otherdatas/fineuploader_session/`,
|
||||
customHeaders: makeCsrfHeader(),
|
||||
params: {
|
||||
'pk': otherDataIds
|
||||
},
|
||||
cors: {
|
||||
expected: true,
|
||||
sendCredentials: true
|
||||
}
|
||||
}}
|
||||
signature={{
|
||||
endpoint: `${AppConstants.serverUrl}/s3/signature/`,
|
||||
customHeaders: makeCsrfHeader()
|
||||
}}
|
||||
submitFile={submitFile}
|
||||
showErrorPrompt={showErrorPrompt}
|
||||
validation={validation} />
|
||||
</Property>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default FurtherDetailsFileuploader;
|
@ -1,141 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import ReactS3FineUploader from '../ascribe_uploader/react_s3_fine_uploader';
|
||||
import FileDragAndDrop from '../ascribe_uploader/ascribe_file_drag_and_drop/file_drag_and_drop';
|
||||
|
||||
import AppConstants from '../../constants/application_constants';
|
||||
|
||||
import { makeCsrfHeader } from '../../utils/csrf';
|
||||
|
||||
|
||||
const { func, bool, oneOf } = React.PropTypes;
|
||||
|
||||
const InputFineUploader = React.createClass({
|
||||
propTypes: {
|
||||
// isFineUploaderActive is used to lock react fine uploader in case
|
||||
// a user is actually not logged in already to prevent him from droping files
|
||||
// before login in
|
||||
isFineUploaderActive: bool,
|
||||
|
||||
// provided by Property
|
||||
disabled: bool,
|
||||
onChange: func,
|
||||
|
||||
// Props for ReactS3FineUploader
|
||||
areAssetsDownloadable: bool,
|
||||
createBlobRoutine: ReactS3FineUploader.propTypes.createBlobRoutine,
|
||||
enableLocalHashing: bool,
|
||||
fileClassToUpload: ReactS3FineUploader.propTypes.fileClassToUpload,
|
||||
fileInputElement: ReactS3FineUploader.propTypes.fileInputElement,
|
||||
isReadyForFormSubmission: func,
|
||||
keyRoutine: ReactS3FineUploader.propTypes.keyRoutine,
|
||||
handleChangedFile: func, // TODO: rename to onChangedFile
|
||||
submitFile: func, // TODO: rename to onSubmitFile
|
||||
onValidationFailed: func,
|
||||
setIsUploadReady: func, //TODO: rename to setIsUploaderValidated
|
||||
setWarning: func,
|
||||
showErrorPrompt: bool,
|
||||
uploadMethod: oneOf(['hash', 'upload']),
|
||||
validation: ReactS3FineUploader.propTypes.validation,
|
||||
},
|
||||
|
||||
getDefaultProps() {
|
||||
return {
|
||||
fileInputElement: FileDragAndDrop
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
value: null,
|
||||
file: null
|
||||
};
|
||||
},
|
||||
|
||||
submitFile(file) {
|
||||
this.setState({
|
||||
file,
|
||||
value: file.key
|
||||
});
|
||||
|
||||
if (this.state.value && typeof this.props.onChange === 'function') {
|
||||
this.props.onChange({ target: { value: this.state.value } });
|
||||
}
|
||||
|
||||
if (typeof this.props.submitFile === 'function') {
|
||||
this.props.submitFile(file);
|
||||
}
|
||||
},
|
||||
|
||||
reset() {
|
||||
this.refs.fineuploader.reset();
|
||||
},
|
||||
|
||||
createBlobRoutine() {
|
||||
const { fineuploader } = this.refs;
|
||||
const { file } = this.state;
|
||||
|
||||
fineuploader.createBlob(file);
|
||||
},
|
||||
|
||||
render() {
|
||||
const { areAssetsDownloadable,
|
||||
createBlobRoutine,
|
||||
enableLocalHashing,
|
||||
disabled,
|
||||
fileClassToUpload,
|
||||
fileInputElement,
|
||||
handleChangedFile,
|
||||
isFineUploaderActive,
|
||||
isReadyForFormSubmission,
|
||||
keyRoutine,
|
||||
onValidationFailed,
|
||||
setIsUploadReady,
|
||||
setWarning,
|
||||
showErrorPrompt,
|
||||
uploadMethod,
|
||||
validation } = this.props;
|
||||
let editable = isFineUploaderActive;
|
||||
|
||||
// if disabled is actually set by property, we want to override
|
||||
// isFineUploaderActive
|
||||
if (typeof disabled !== 'undefined') {
|
||||
editable = !disabled;
|
||||
}
|
||||
|
||||
return (
|
||||
<ReactS3FineUploader
|
||||
ref="fineuploader"
|
||||
fileInputElement={fileInputElement}
|
||||
keyRoutine={keyRoutine}
|
||||
createBlobRoutine={createBlobRoutine}
|
||||
validation={validation}
|
||||
submitFile={this.submitFile}
|
||||
onValidationFailed={onValidationFailed}
|
||||
setIsUploadReady={setIsUploadReady}
|
||||
isReadyForFormSubmission={isReadyForFormSubmission}
|
||||
areAssetsDownloadable={areAssetsDownloadable}
|
||||
areAssetsEditable={editable}
|
||||
setWarning={setWarning}
|
||||
showErrorPrompt={showErrorPrompt}
|
||||
signature={{
|
||||
endpoint: `${AppConstants.serverUrl}/s3/signature/`,
|
||||
customHeaders: makeCsrfHeader()
|
||||
}}
|
||||
deleteFile={{
|
||||
enabled: true,
|
||||
method: 'DELETE',
|
||||
endpoint: `${AppConstants.serverUrl}/s3/delete`,
|
||||
customHeaders: makeCsrfHeader()
|
||||
}}
|
||||
enableLocalHashing={enableLocalHashing}
|
||||
uploadMethod={uploadMethod}
|
||||
fileClassToUpload={fileClassToUpload}
|
||||
handleChangedFile={handleChangedFile} />
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default InputFineUploader;
|
@ -1,253 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import ProgressBar from 'react-bootstrap/lib/ProgressBar';
|
||||
|
||||
import FileDragAndDropDialog from './file_drag_and_drop_dialog';
|
||||
import FileDragAndDropErrorDialog from './file_drag_and_drop_error_dialog';
|
||||
import FileDragAndDropPreviewIterator from './file_drag_and_drop_preview_iterator';
|
||||
|
||||
import { FileStatus } from '../react_s3_fine_uploader_utils';
|
||||
import { getLangText } from '../../../utils/lang';
|
||||
|
||||
|
||||
// Taken from: https://github.com/fedosejev/react-file-drag-and-drop
|
||||
let FileDragAndDrop = React.createClass({
|
||||
propTypes: {
|
||||
areAssetsDownloadable: React.PropTypes.bool,
|
||||
areAssetsEditable: React.PropTypes.bool,
|
||||
multiple: React.PropTypes.bool,
|
||||
dropzoneInactive: React.PropTypes.bool,
|
||||
filesToUpload: React.PropTypes.array,
|
||||
|
||||
onDrop: React.PropTypes.func.isRequired,
|
||||
onDragOver: React.PropTypes.func,
|
||||
handleDeleteFile: React.PropTypes.func,
|
||||
handleCancelFile: React.PropTypes.func,
|
||||
handlePauseFile: React.PropTypes.func,
|
||||
handleResumeFile: React.PropTypes.func,
|
||||
handleRetryFiles: React.PropTypes.func,
|
||||
|
||||
enableLocalHashing: React.PropTypes.bool,
|
||||
uploadMethod: React.PropTypes.string,
|
||||
|
||||
// triggers a FileDragAndDrop-global spinner
|
||||
hashingProgress: React.PropTypes.number,
|
||||
// sets the value of this.state.hashingProgress in reactfineuploader
|
||||
// to -1 which is code for: aborted
|
||||
handleCancelHashing: React.PropTypes.func,
|
||||
|
||||
showError: React.PropTypes.bool,
|
||||
errorClass: React.PropTypes.shape({
|
||||
name: React.PropTypes.string,
|
||||
prettifiedText: React.PropTypes.string
|
||||
}),
|
||||
|
||||
// A class of a file the user has to upload
|
||||
// Needs to be defined both in singular as well as in plural
|
||||
fileClassToUpload: React.PropTypes.shape({
|
||||
singular: React.PropTypes.string,
|
||||
plural: React.PropTypes.string
|
||||
}),
|
||||
|
||||
allowedExtensions: React.PropTypes.string
|
||||
},
|
||||
|
||||
clearSelection() {
|
||||
this.refs.fileSelector.value = '';
|
||||
},
|
||||
|
||||
handleDragOver(event) {
|
||||
event.preventDefault();
|
||||
|
||||
if (typeof this.props.onDragOver === 'function') {
|
||||
this.props.onDragOver(event);
|
||||
}
|
||||
},
|
||||
|
||||
handleDrop(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
if (!this.props.dropzoneInactive) {
|
||||
let files;
|
||||
|
||||
// handle Drag and Drop
|
||||
if(event.dataTransfer && event.dataTransfer.files.length > 0) {
|
||||
files = event.dataTransfer.files;
|
||||
} else if(event.target.files) { // handle input type file
|
||||
files = event.target.files;
|
||||
}
|
||||
|
||||
if(typeof this.props.onDrop === 'function' && files) {
|
||||
this.props.onDrop(files);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
handleDeleteFile(fileId) {
|
||||
// input's value is not changed the second time someone
|
||||
// inputs the same file again, therefore we need to reset its value
|
||||
this.clearSelection();
|
||||
this.props.handleDeleteFile(fileId);
|
||||
},
|
||||
|
||||
handleCancelFile(fileId) {
|
||||
// input's value is not changed the second time someone
|
||||
// inputs the same file again, therefore we need to reset its value
|
||||
this.clearSelection();
|
||||
this.props.handleCancelFile(fileId);
|
||||
},
|
||||
|
||||
handlePauseFile(fileId) {
|
||||
// input's value is not changed the second time someone
|
||||
// inputs the same file again, therefore we need to reset its value
|
||||
this.clearSelection();
|
||||
this.props.handlePauseFile(fileId);
|
||||
},
|
||||
|
||||
handleResumeFile(fileId) {
|
||||
// input's value is not changed the second time someone
|
||||
// inputs the same file again, therefore we need to reset its value
|
||||
this.clearSelection();
|
||||
this.props.handleResumeFile(fileId);
|
||||
},
|
||||
|
||||
handleOnClick() {
|
||||
// do not propagate event if the drop zone's inactive,
|
||||
// for example when multiple is set to false and the user already uploaded a piece
|
||||
if (!this.props.dropzoneInactive) {
|
||||
let evt;
|
||||
|
||||
try {
|
||||
evt = new MouseEvent('click', {
|
||||
view: window,
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
});
|
||||
} catch(e) {
|
||||
// For browsers that do not support the new MouseEvent syntax
|
||||
evt = document.createEvent('MouseEvents');
|
||||
evt.initMouseEvent('click', true, true, window, 0, 0, 0, 80, 20, false, false, false, false, 0, null);
|
||||
}
|
||||
|
||||
evt.stopPropagation();
|
||||
this.refs.fileSelector.dispatchEvent(evt);
|
||||
}
|
||||
},
|
||||
|
||||
getErrorDialog(failedFiles) {
|
||||
const { errorClass } = this.props;
|
||||
|
||||
return (
|
||||
<FileDragAndDropErrorDialog
|
||||
errorClass={errorClass}
|
||||
files={failedFiles}
|
||||
handleRetryFiles={this.props.handleRetryFiles} />
|
||||
);
|
||||
},
|
||||
|
||||
getPreviewIterator() {
|
||||
const { areAssetsDownloadable, areAssetsEditable, filesToUpload } = this.props;
|
||||
|
||||
return (
|
||||
<FileDragAndDropPreviewIterator
|
||||
files={filesToUpload}
|
||||
handleDeleteFile={this.handleDeleteFile}
|
||||
handleCancelFile={this.handleCancelFile}
|
||||
handlePauseFile={this.handlePauseFile}
|
||||
handleResumeFile={this.handleResumeFile}
|
||||
areAssetsDownloadable={areAssetsDownloadable}
|
||||
areAssetsEditable={areAssetsEditable} />
|
||||
);
|
||||
},
|
||||
|
||||
getUploadDialog() {
|
||||
const { enableLocalHashing, fileClassToUpload, multiple, uploadMethod } = this.props;
|
||||
|
||||
return (
|
||||
<FileDragAndDropDialog
|
||||
multipleFiles={multiple}
|
||||
onClick={this.handleOnClick}
|
||||
enableLocalHashing={enableLocalHashing}
|
||||
uploadMethod={uploadMethod}
|
||||
fileClassToUpload={fileClassToUpload} />
|
||||
);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
const { allowedExtensions,
|
||||
dropzoneInactive,
|
||||
errorClass,
|
||||
filesToUpload,
|
||||
handleCancelHashing,
|
||||
hashingProgress,
|
||||
multiple,
|
||||
showError } = this.props;
|
||||
|
||||
// has files only is true if there are files that do not have the status deleted, canceled, or failed
|
||||
const hasFiles = filesToUpload
|
||||
.filter((file) => {
|
||||
return file.status !== FileStatus.DELETED &&
|
||||
file.status !== FileStatus.CANCELED &&
|
||||
file.status !== FileStatus.UPLOAD_FAILED &&
|
||||
file.size !== -1;
|
||||
})
|
||||
.length > 0;
|
||||
|
||||
const failedFiles = filesToUpload.filter((file) => file.status === FileStatus.UPLOAD_FAILED);
|
||||
let hasError = showError && errorClass && failedFiles.length > 0;
|
||||
|
||||
// if !== -2: triggers a FileDragAndDrop-global spinner
|
||||
if (hashingProgress !== -2) {
|
||||
return (
|
||||
<div className="file-drag-and-drop-hashing-dialog">
|
||||
<p>{getLangText('Computing hash(es)... This may take a few minutes.')}</p>
|
||||
<p>
|
||||
<a onClick={handleCancelHashing}> {getLangText('Cancel hashing')}</a>
|
||||
</p>
|
||||
<ProgressBar
|
||||
now={Math.ceil(hashingProgress)}
|
||||
label="%(percent)s%"
|
||||
className="ascribe-progress-bar"/>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div
|
||||
className={classNames('file-drag-and-drop', dropzoneInactive ? 'inactive-dropzone' : 'active-dropzone', { 'has-files': hasFiles })}
|
||||
onDrag={this.handleDrop}
|
||||
onDragOver={this.handleDragOver}
|
||||
onDrop={this.handleDrop}>
|
||||
{hasError ? this.getErrorDialog(failedFiles) : this.getPreviewIterator()}
|
||||
{!hasFiles && !hasError ? this.getUploadDialog() : null}
|
||||
{/*
|
||||
Opera doesn't trigger simulated click events
|
||||
if the targeted input has `display:none` set.
|
||||
Which means we need to set its visibility to hidden
|
||||
instead of using `display:none`.
|
||||
|
||||
See:
|
||||
- http://stackoverflow.com/questions/12880604/jquery-triggerclick-not-working-on-opera-if-the-element-is-not-displayed
|
||||
*/}
|
||||
<input
|
||||
multiple={multiple}
|
||||
ref="fileSelector"
|
||||
type="file"
|
||||
style={{
|
||||
visibility: 'hidden',
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
height: 0,
|
||||
width: 0
|
||||
}}
|
||||
onChange={this.handleDrop}
|
||||
accept={allowedExtensions}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export default FileDragAndDrop;
|
@ -1,123 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router';
|
||||
|
||||
import { dragAndDropAvailable } from 'js-utility-belt/es6/feature_detection';
|
||||
|
||||
import { getLangText } from '../../../utils/lang';
|
||||
import { getCurrentQueryParams } from '../../../utils/url';
|
||||
|
||||
let FileDragAndDropDialog = React.createClass({
|
||||
propTypes: {
|
||||
multipleFiles: React.PropTypes.bool,
|
||||
enableLocalHashing: React.PropTypes.bool,
|
||||
uploadMethod: React.PropTypes.string,
|
||||
onClick: React.PropTypes.func,
|
||||
|
||||
// A class of a file the user has to upload
|
||||
// Needs to be defined both in singular as well as in plural
|
||||
fileClassToUpload: React.PropTypes.shape({
|
||||
singular: React.PropTypes.string,
|
||||
plural: React.PropTypes.string
|
||||
})
|
||||
},
|
||||
|
||||
getDragDialog(fileClass) {
|
||||
if (dragAndDropAvailable) {
|
||||
return [
|
||||
<p className="file-drag-and-drop-dialog-title">{getLangText('Drag %s here', fileClass)}</p>,
|
||||
<p>{getLangText('or')}</p>
|
||||
];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
render() {
|
||||
const {
|
||||
enableLocalHashing,
|
||||
fileClassToUpload,
|
||||
multipleFiles,
|
||||
onClick,
|
||||
uploadMethod
|
||||
} = this.props;
|
||||
let dialogElement;
|
||||
|
||||
if (enableLocalHashing && !uploadMethod) {
|
||||
const currentQueryParams = getCurrentQueryParams();
|
||||
|
||||
const queryParamsHash = Object.assign({}, currentQueryParams);
|
||||
queryParamsHash.method = 'hash';
|
||||
|
||||
const queryParamsUpload = Object.assign({}, currentQueryParams);
|
||||
queryParamsUpload.method = 'upload';
|
||||
|
||||
dialogElement = (
|
||||
<div className="present-options">
|
||||
<p className="file-drag-and-drop-dialog-title">{getLangText('Would you rather')}</p>
|
||||
{/*
|
||||
The frontend in live is hosted under /app,
|
||||
Since `Link` is appending that base url, if its defined
|
||||
by itself, we need to make sure to not set it at this point.
|
||||
Otherwise it will be appended twice.
|
||||
*/}
|
||||
<Link
|
||||
to={`/${window.location.pathname.split('/').pop()}`}
|
||||
query={queryParamsHash}>
|
||||
<span className="btn btn-default btn-sm">
|
||||
{getLangText('Hash your work')}
|
||||
</span>
|
||||
</Link>
|
||||
<span> {getLangText('or')} </span>
|
||||
<Link
|
||||
to={`/${window.location.pathname.split('/').pop()}`}
|
||||
query={queryParamsUpload}>
|
||||
<span className="btn btn-default btn-sm">
|
||||
{getLangText('Upload and hash your work')}
|
||||
</span>
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
if (multipleFiles) {
|
||||
dialogElement = [
|
||||
this.getDragDialog(fileClassToUpload.plural),
|
||||
(<span
|
||||
key='mutlipleFilesBtn'
|
||||
className="btn btn-default"
|
||||
onClick={onClick}>
|
||||
{getLangText('choose %s to upload', fileClassToUpload.plural)}
|
||||
</span>)
|
||||
];
|
||||
} else {
|
||||
const dialog = uploadMethod === 'hash' ? getLangText('choose a %s to hash', fileClassToUpload.singular)
|
||||
: getLangText('choose a %s to upload', fileClassToUpload.singular);
|
||||
|
||||
dialogElement = [
|
||||
this.getDragDialog(fileClassToUpload.singular),
|
||||
(<span
|
||||
key='singleFileBtn'
|
||||
className="btn btn-default"
|
||||
onClick={onClick}>
|
||||
{dialog}
|
||||
</span>)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="file-drag-and-drop-dialog">
|
||||
<div className="hidden-print">
|
||||
{dialogElement}
|
||||
</div>
|
||||
{/* Hide the uploader and just show that there's been on files uploaded yet when printing */}
|
||||
<p className="text-align-center visible-print">
|
||||
{getLangText('No files uploaded')}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default FileDragAndDropDialog;
|
@ -1,86 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { ErrorClasses } from '../../../constants/error_constants';
|
||||
|
||||
import { getLangText } from '../../../utils/lang';
|
||||
|
||||
let FileDragAndDropErrorDialog = React.createClass({
|
||||
propTypes: {
|
||||
errorClass: React.PropTypes.shape({
|
||||
name: React.PropTypes.string,
|
||||
prettifiedText: React.PropTypes.string
|
||||
}).isRequired,
|
||||
files: React.PropTypes.array.isRequired,
|
||||
handleRetryFiles: React.PropTypes.func.isRequired
|
||||
},
|
||||
|
||||
getRetryButton(text, openIntercom) {
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className='btn btn-default'
|
||||
onClick={() => {
|
||||
if (openIntercom) {
|
||||
window.Intercom('showNewMessage', getLangText("I'm having trouble uploading my file."));
|
||||
}
|
||||
|
||||
this.retryAllFiles()
|
||||
}}>
|
||||
{getLangText(text)}
|
||||
</button>
|
||||
);
|
||||
},
|
||||
|
||||
getContactUsDetail() {
|
||||
return (
|
||||
<div className='file-drag-and-drop-error'>
|
||||
<h4>{getLangText('Let us help you')}</h4>
|
||||
<p>{getLangText('Still having problems? Send us a message.')}</p>
|
||||
{this.getRetryButton('Contact us', true)}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
getErrorDetail(multipleFiles) {
|
||||
const { errorClass: { prettifiedText }, files } = this.props;
|
||||
|
||||
return (
|
||||
<div className='file-drag-and-drop-error'>
|
||||
<div className={classNames('file-drag-and-drop-error-detail', { 'file-drag-and-drop-error-detail-multiple-files': multipleFiles })}>
|
||||
<h4>{getLangText(multipleFiles ? 'Some files did not upload correctly'
|
||||
: 'Error uploading the file!')}
|
||||
</h4>
|
||||
<p>{prettifiedText}</p>
|
||||
{this.getRetryButton('Retry')}
|
||||
</div>
|
||||
<span className={classNames('file-drag-and-drop-error-icon-container', { 'file-drag-and-drop-error-icon-container-multiple-files': multipleFiles })}>
|
||||
<span className='ascribe-icon icon-ascribe-thin-cross'></span>
|
||||
</span>
|
||||
<div className='file-drag-and-drop-error-file-names'>
|
||||
<ul>
|
||||
{files.map((file) => (<li key={file.id} className='file-name'>{file.originalName}</li>))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
retryAllFiles() {
|
||||
const { files, handleRetryFiles } = this.props;
|
||||
handleRetryFiles(files.map(file => file.id));
|
||||
},
|
||||
|
||||
render() {
|
||||
const { errorClass: { name: errorName }, files } = this.props;
|
||||
|
||||
const multipleFiles = files.length > 1;
|
||||
const contactUs = errorName === ErrorClasses.upload.contactUs.name;
|
||||
|
||||
return contactUs ? this.getContactUsDetail() : this.getErrorDetail(multipleFiles);
|
||||
}
|
||||
});
|
||||
|
||||
export default FileDragAndDropErrorDialog;
|
@ -1,152 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import FileDragAndDropPreviewImage from './file_drag_and_drop_preview_image';
|
||||
import FileDragAndDropPreviewOther from './file_drag_and_drop_preview_other';
|
||||
|
||||
import { FileStatus } from '../react_s3_fine_uploader_utils';
|
||||
import { extractFileExtensionFromString } from '../../../utils/file';
|
||||
import { getLangText } from '../../../utils/lang';
|
||||
import { truncateText } from '../../../utils/text';
|
||||
|
||||
|
||||
const { shape, string, number, func, bool } = React.PropTypes;
|
||||
|
||||
const FileDragAndDropPreview = React.createClass({
|
||||
propTypes: {
|
||||
file: shape({
|
||||
url: string,
|
||||
type: string,
|
||||
progress: number,
|
||||
id: number,
|
||||
status: string,
|
||||
s3Url: string,
|
||||
s3UrlSafe: string
|
||||
}).isRequired,
|
||||
|
||||
areAssetsDownloadable: bool,
|
||||
areAssetsEditable: bool,
|
||||
handleDeleteFile: func,
|
||||
handleCancelFile: func,
|
||||
handlePauseFile: func,
|
||||
handleResumeFile: func,
|
||||
numberOfDisplayedFiles: number
|
||||
},
|
||||
|
||||
toggleUploadProcess() {
|
||||
const { file, handlePauseFile, handleResumeFile } = this.props;
|
||||
|
||||
if (file.status === FileStatus.UPLOADING) {
|
||||
handlePauseFile(file.id);
|
||||
} else if (file.status === FileStatus.PAUSED) {
|
||||
handleResumeFile(file.id);
|
||||
}
|
||||
},
|
||||
|
||||
handleDeleteFile() {
|
||||
const { file,
|
||||
handleDeleteFile,
|
||||
handleCancelFile } = this.props;
|
||||
// `handleDeleteFile` is optional, so if its not submitted, don't run it
|
||||
//
|
||||
// For delete though, we only want to trigger it, when we're sure that
|
||||
// the file has *completely* been uploaded to S3 and call now also be
|
||||
// deleted using an HTTP DELETE request.
|
||||
if (handleDeleteFile &&
|
||||
file.progress === 100 &&
|
||||
(file.status === FileStatus.UPLOAD_SUCCESSFUL || file.status === FileStatus.ONLINE) &&
|
||||
file.s3UrlSafe) {
|
||||
handleDeleteFile(file.id);
|
||||
} else if (handleCancelFile) {
|
||||
handleCancelFile(file.id);
|
||||
}
|
||||
},
|
||||
|
||||
handleDownloadFile() {
|
||||
if (this.props.file.s3Url) {
|
||||
// This simply opens a new browser tab with the url provided
|
||||
open(this.props.file.s3Url);
|
||||
}
|
||||
},
|
||||
|
||||
getFileName() {
|
||||
const { numberOfDisplayedFiles, file } = this.props;
|
||||
|
||||
if (numberOfDisplayedFiles === 1) {
|
||||
return (
|
||||
<span className="file-name">
|
||||
{truncateText(file.name, 30, `(...).${extractFileExtensionFromString(file.name)}`)}
|
||||
</span>
|
||||
);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
getRemoveButton() {
|
||||
if (this.props.areAssetsEditable) {
|
||||
return (
|
||||
<div className="delete-file">
|
||||
<span
|
||||
className="glyphicon glyphicon-remove text-center"
|
||||
aria-hidden="true"
|
||||
title={getLangText('Remove file')}
|
||||
onClick={this.handleDeleteFile}/>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
render() {
|
||||
const { file,
|
||||
areAssetsDownloadable,
|
||||
numberOfDisplayedFiles } = this.props;
|
||||
const innerStyle = numberOfDisplayedFiles === 1 ? { verticalAlign: 'middle' } : null;
|
||||
const outerStyle = numberOfDisplayedFiles !== 1 ? { display: 'inline-block' } : null;
|
||||
|
||||
let previewElement;
|
||||
|
||||
// Decide whether an image or a placeholder picture should be displayed
|
||||
// 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.thumbnailUrl || file.url}
|
||||
toggleUploadProcess={this.toggleUploadProcess}
|
||||
areAssetsDownloadable={areAssetsDownloadable}
|
||||
downloadUrl={file.s3UrlSafe}
|
||||
showProgress={numberOfDisplayedFiles > 1} />
|
||||
);
|
||||
} else {
|
||||
previewElement = (
|
||||
<FileDragAndDropPreviewOther
|
||||
onClick={this.handleDeleteFile}
|
||||
progress={file.progress}
|
||||
type={extractFileExtensionFromString(file.name)}
|
||||
toggleUploadProcess={this.toggleUploadProcess}
|
||||
areAssetsDownloadable={areAssetsDownloadable}
|
||||
downloadUrl={file.s3UrlSafe}
|
||||
showProgress={numberOfDisplayedFiles > 1} />
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={outerStyle}>
|
||||
<div
|
||||
style={innerStyle}
|
||||
className="file-drag-and-drop-position">
|
||||
{this.getRemoveButton()}
|
||||
{previewElement}
|
||||
</div>
|
||||
{this.getFileName()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default FileDragAndDropPreview;
|
@ -1,85 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import ProgressBar from 'react-bootstrap/lib/ProgressBar';
|
||||
|
||||
import AclProxy from '../../acl_proxy';
|
||||
import AscribeSpinner from '../../ascribe_spinner';
|
||||
import { getLangText } from '../../../utils/lang';
|
||||
|
||||
|
||||
const { number, string, func, bool } = React.PropTypes;
|
||||
|
||||
const FileDragAndDropPreviewImage = React.createClass({
|
||||
propTypes: {
|
||||
progress: number,
|
||||
url: string,
|
||||
toggleUploadProcess: func,
|
||||
downloadUrl: string,
|
||||
areAssetsDownloadable: bool,
|
||||
showProgress: bool
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
paused: true
|
||||
};
|
||||
},
|
||||
|
||||
toggleUploadProcess(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
this.setState({
|
||||
paused: !this.state.paused
|
||||
});
|
||||
|
||||
this.props.toggleUploadProcess();
|
||||
},
|
||||
|
||||
render() {
|
||||
const { url,
|
||||
progress,
|
||||
areAssetsDownloadable,
|
||||
downloadUrl,
|
||||
showProgress } = this.props;
|
||||
const imageStyle = {
|
||||
backgroundImage: 'url("' + url + '")',
|
||||
backgroundSize: 'cover'
|
||||
};
|
||||
|
||||
let actionSymbol;
|
||||
|
||||
// only if assets are actually downloadable, there should be a download icon if the process is already at
|
||||
// 100%. If not, no actionSymbol should be displayed
|
||||
if(progress === 100 && areAssetsDownloadable) {
|
||||
actionSymbol = <a href={downloadUrl} target="_blank" className="glyphicon glyphicon-download action-file" aria-hidden="true" title={getLangText('Download file')}/>;
|
||||
} else if(progress >= 0 && progress < 100) {
|
||||
actionSymbol = (
|
||||
<div className="spinner-file">
|
||||
<AscribeSpinner color='dark-blue' size='md' />
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
actionSymbol = (
|
||||
<span className='ascribe-icon icon-ascribe-ok action-file'/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className="file-drag-and-drop-preview-image hidden-print"
|
||||
style={imageStyle}>
|
||||
<AclProxy
|
||||
show={showProgress}>
|
||||
<ProgressBar
|
||||
now={Math.ceil(progress)}
|
||||
className="ascribe-progress-bar ascribe-progress-bar-xs"/>
|
||||
</AclProxy>
|
||||
{actionSymbol}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default FileDragAndDropPreviewImage;
|
@ -1,60 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import FileDragAndDropPreview from './file_drag_and_drop_preview';
|
||||
import FileDragAndDropPreviewProgress from './file_drag_and_drop_preview_progress';
|
||||
|
||||
import { displayValidFilesFilter } from '../react_s3_fine_uploader_utils';
|
||||
|
||||
|
||||
let FileDragAndDropPreviewIterator = React.createClass({
|
||||
propTypes: {
|
||||
files: React.PropTypes.array,
|
||||
handleDeleteFile: React.PropTypes.func,
|
||||
handleCancelFile: React.PropTypes.func,
|
||||
handlePauseFile: React.PropTypes.func,
|
||||
handleResumeFile: React.PropTypes.func,
|
||||
areAssetsDownloadable: React.PropTypes.bool,
|
||||
areAssetsEditable: React.PropTypes.bool
|
||||
},
|
||||
|
||||
render() {
|
||||
let {
|
||||
files,
|
||||
handleDeleteFile,
|
||||
handleCancelFile,
|
||||
handlePauseFile,
|
||||
handleResumeFile,
|
||||
areAssetsDownloadable,
|
||||
areAssetsEditable
|
||||
} = this.props;
|
||||
files = files.filter(displayValidFilesFilter);
|
||||
|
||||
if(files && files.length > 0) {
|
||||
return (
|
||||
<div>
|
||||
{files.map((file, i) => {
|
||||
return (
|
||||
<FileDragAndDropPreview
|
||||
key={i}
|
||||
file={file}
|
||||
handleDeleteFile={handleDeleteFile}
|
||||
handleCancelFile={handleCancelFile}
|
||||
handlePauseFile={handlePauseFile}
|
||||
handleResumeFile={handleResumeFile}
|
||||
areAssetsDownloadable={areAssetsDownloadable}
|
||||
areAssetsEditable={areAssetsEditable}
|
||||
numberOfDisplayedFiles={files.length}/>
|
||||
);
|
||||
})}
|
||||
<FileDragAndDropPreviewProgress files={files} />
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export default FileDragAndDropPreviewIterator;
|
@ -1,87 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import ProgressBar from 'react-bootstrap/lib/ProgressBar';
|
||||
|
||||
import AscribeSpinner from '../../ascribe_spinner';
|
||||
import { getLangText } from '../../../utils/lang';
|
||||
|
||||
|
||||
const { string, number, bool, func } = React.PropTypes;
|
||||
|
||||
const FileDragAndDropPreviewOther = React.createClass({
|
||||
propTypes: {
|
||||
type: string,
|
||||
progress: number,
|
||||
areAssetsDownloadable: bool,
|
||||
toggleUploadProcess: func,
|
||||
downloadUrl: string,
|
||||
showProgress: bool
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
paused: true
|
||||
};
|
||||
},
|
||||
|
||||
toggleUploadProcess(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
this.setState({
|
||||
paused: !this.state.paused
|
||||
});
|
||||
|
||||
this.props.toggleUploadProcess();
|
||||
},
|
||||
|
||||
render() {
|
||||
const { progress,
|
||||
areAssetsDownloadable,
|
||||
downloadUrl,
|
||||
type,
|
||||
showProgress } = this.props;
|
||||
const style = !showProgress ? { visibility: 'hidden' } : null;
|
||||
let actionSymbol;
|
||||
|
||||
// only if assets are actually downloadable, there should be a
|
||||
// download icon if the process is already at 100%.
|
||||
// If not, no actionSymbol should be displayed
|
||||
if (progress === 100 && areAssetsDownloadable) {
|
||||
actionSymbol = (
|
||||
<a
|
||||
href={downloadUrl}
|
||||
target="_blank"
|
||||
className="glyphicon glyphicon-download action-file"
|
||||
aria-hidden="true"
|
||||
title={getLangText('Download file')} />
|
||||
);
|
||||
} else if (progress >= 0 && progress < 100) {
|
||||
actionSymbol = (
|
||||
<div className="spinner-file">
|
||||
<AscribeSpinner color='dark-blue' size='md' />
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
actionSymbol = (
|
||||
<span className='ascribe-icon icon-ascribe-ok action-file' />
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="file-drag-and-drop-preview">
|
||||
<ProgressBar
|
||||
now={Math.ceil(progress)}
|
||||
style={style}
|
||||
className="ascribe-progress-bar ascribe-progress-bar-xs" />
|
||||
<div className="file-drag-and-drop-preview-other">
|
||||
{actionSymbol}
|
||||
<p style={style}>{'.' + (type ? type : 'file')}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default FileDragAndDropPreviewOther;
|
@ -1,58 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import ProgressBar from 'react-bootstrap/lib/ProgressBar';
|
||||
|
||||
import { displayValidProgressFilesFilter } from '../react_s3_fine_uploader_utils';
|
||||
|
||||
|
||||
const FileDragAndDropPreviewProgress = React.createClass({
|
||||
propTypes: {
|
||||
files: React.PropTypes.array
|
||||
},
|
||||
|
||||
calcOverallFileSize() {
|
||||
let overallFileSize = 0;
|
||||
let files = this.props.files.filter(displayValidProgressFilesFilter);
|
||||
|
||||
// We just sum up all files' sizes
|
||||
for(let i = 0; i < files.length; i++) {
|
||||
overallFileSize += files[i].size;
|
||||
}
|
||||
|
||||
return overallFileSize;
|
||||
},
|
||||
|
||||
calcOverallProgress() {
|
||||
let overallProgress = 0;
|
||||
let overallFileSize = this.calcOverallFileSize();
|
||||
let files = this.props.files.filter(displayValidProgressFilesFilter);
|
||||
|
||||
// We calculate the overall progress by summing the individuals
|
||||
// files' progresses in relation to their size
|
||||
for(let i = 0; i < files.length; i++) {
|
||||
overallProgress += files[i].size / overallFileSize * files[i].progress;
|
||||
}
|
||||
|
||||
return overallProgress;
|
||||
},
|
||||
|
||||
render() {
|
||||
const files = this.props.files.filter(displayValidProgressFilesFilter);
|
||||
const style = !files.length ? { display: 'none' } : null;
|
||||
let overallProgress = this.calcOverallProgress();
|
||||
|
||||
return (
|
||||
<div style={{marginTop: '1.3em'}}>
|
||||
<ProgressBar
|
||||
now={Math.ceil(overallProgress)}
|
||||
label={'%(percent)s%'}
|
||||
className="ascribe-progress-bar"
|
||||
style={style} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default FileDragAndDropPreviewProgress;
|
@ -1,188 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { displayValidProgressFilesFilter, FileStatus } from '../react_s3_fine_uploader_utils';
|
||||
import { getLangText } from '../../../utils/lang';
|
||||
import { truncateText } from '../../../utils/text';
|
||||
|
||||
const { func, array, bool, shape, string } = React.PropTypes;
|
||||
|
||||
|
||||
export default function UploadButton({ className = 'btn btn-default btn-sm', showLabel = true } = {}) {
|
||||
return React.createClass({
|
||||
displayName: 'UploadButton',
|
||||
|
||||
propTypes: {
|
||||
onDrop: func.isRequired,
|
||||
filesToUpload: array,
|
||||
multiple: bool,
|
||||
|
||||
// For simplification purposes we're just going to use this prop as a
|
||||
// label for the upload button
|
||||
fileClassToUpload: shape({
|
||||
singular: string,
|
||||
plural: string
|
||||
}),
|
||||
|
||||
allowedExtensions: string,
|
||||
|
||||
// provided by ReactS3FineUploader
|
||||
handleCancelFile: func,
|
||||
handleDeleteFile: func
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
disabled: this.getUploadingFiles().length !== 0
|
||||
};
|
||||
},
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if(this.props.filesToUpload !== nextProps.filesToUpload) {
|
||||
this.setState({
|
||||
disabled: this.getUploadingFiles(nextProps.filesToUpload).length !== 0
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
handleDrop(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
let files = event.target.files;
|
||||
|
||||
if(typeof this.props.onDrop === 'function' && files) {
|
||||
this.props.onDrop(files);
|
||||
}
|
||||
},
|
||||
|
||||
getUploadingFiles(filesToUpload = this.props.filesToUpload) {
|
||||
return filesToUpload.filter((file) => file.status === FileStatus.UPLOADING);
|
||||
},
|
||||
|
||||
getUploadedFile() {
|
||||
return this.props.filesToUpload.filter((file) => file.status === FileStatus.UPLOAD_SUCCESSFUL)[0];
|
||||
},
|
||||
|
||||
clearSelection() {
|
||||
this.refs.fileSelector.value = '';
|
||||
},
|
||||
|
||||
handleOnClick() {
|
||||
if(!this.state.disabled) {
|
||||
let evt;
|
||||
|
||||
// First, remove any currently uploading or uploaded items
|
||||
this.onClickRemove();
|
||||
|
||||
try {
|
||||
evt = new MouseEvent('click', {
|
||||
view: window,
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
});
|
||||
} catch(e) {
|
||||
// For browsers that do not support the new MouseEvent syntax
|
||||
evt = document.createEvent('MouseEvents');
|
||||
evt.initMouseEvent('click', true, true, window, 0, 0, 0, 80, 20, false, false, false, false, 0, null);
|
||||
}
|
||||
evt.stopPropagation();
|
||||
this.refs.fileSelector.dispatchEvent(evt);
|
||||
}
|
||||
},
|
||||
|
||||
onClickRemove() {
|
||||
const uploadingFiles = this.getUploadingFiles();
|
||||
const uploadedFile = this.getUploadedFile();
|
||||
|
||||
this.clearSelection();
|
||||
if(uploadingFiles.length) {
|
||||
this.props.handleCancelFile(uploadingFiles[0].id);
|
||||
} else if(uploadedFile && !uploadedFile.s3UrlSafe) {
|
||||
this.props.handleCancelFile(uploadedFile.id);
|
||||
} else if(uploadedFile && uploadedFile.s3UrlSafe) {
|
||||
this.props.handleDeleteFile(uploadedFile.id);
|
||||
}
|
||||
},
|
||||
|
||||
getButtonLabel() {
|
||||
let { filesToUpload, fileClassToUpload } = this.props;
|
||||
|
||||
// filter invalid files that might have been deleted or canceled...
|
||||
filesToUpload = filesToUpload.filter(displayValidProgressFilesFilter);
|
||||
|
||||
if(this.getUploadingFiles().length !== 0) {
|
||||
return getLangText('Upload progress') + ': ' + Math.ceil(filesToUpload[0].progress) + '%';
|
||||
} else {
|
||||
return fileClassToUpload.singular;
|
||||
}
|
||||
},
|
||||
|
||||
getUploadedFileLabel() {
|
||||
if (showLabel) {
|
||||
const uploadedFile = this.getUploadedFile();
|
||||
const uploadingFiles = this.getUploadingFiles();
|
||||
|
||||
if (uploadingFiles.length) {
|
||||
return (
|
||||
<span>
|
||||
{` ${truncateText(uploadingFiles[0].name, 40)} `}
|
||||
[<a onClick={this.onClickRemove}>{getLangText('cancel upload')}</a>]
|
||||
</span>
|
||||
);
|
||||
} else if (uploadedFile) {
|
||||
return (
|
||||
<span>
|
||||
<span className='ascribe-icon icon-ascribe-ok'/>
|
||||
{` ${truncateText(uploadedFile.name, 40)} `}
|
||||
[<a onClick={this.onClickRemove}>{getLangText('remove')}</a>]
|
||||
</span>
|
||||
);
|
||||
} else {
|
||||
return <span>{getLangText('No file chosen')}</span>;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
render() {
|
||||
const { allowedExtensions, multiple } = this.props;
|
||||
const { disabled } = this.state;
|
||||
|
||||
|
||||
/*
|
||||
* We do not want a button that submits here.
|
||||
* As UploadButton could be used in forms that want to be submitted independent
|
||||
* of clicking the selector.
|
||||
* Therefore the wrapping component needs to be an `anchor` tag instead of a `button`
|
||||
*/
|
||||
return (
|
||||
<div className={classNames('ascribe-upload-button', {'ascribe-upload-button-has-label': showLabel})}>
|
||||
{/*
|
||||
The button needs to be of `type="button"` as it would
|
||||
otherwise submit the form its in.
|
||||
*/}
|
||||
<button
|
||||
type="button"
|
||||
onClick={this.handleOnClick}
|
||||
className={className}
|
||||
disabled={disabled}>
|
||||
{this.getButtonLabel()}
|
||||
<input
|
||||
multiple={multiple}
|
||||
ref="fileSelector"
|
||||
type="file"
|
||||
style={{
|
||||
display: 'none',
|
||||
height: 0,
|
||||
width: 0
|
||||
}}
|
||||
onChange={this.handleDrop}
|
||||
accept={allowedExtensions}/>
|
||||
</button>
|
||||
{this.getUploadedFileLabel()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
import request from '../utils/request';
|
||||
|
||||
let S3Fetcher = {
|
||||
/**
|
||||
* Fetch the registered applications of a user from the API.
|
||||
*/
|
||||
const S3Fetcher = {
|
||||
deleteFile(key, bucket) {
|
||||
return request('s3_delete_file', {
|
||||
method: 'DELETE',
|
||||
|
Loading…
Reference in New Issue
Block a user