2017-04-29 02:42:32 +08:00
|
|
|
import React, { Component } from 'react';
|
2017-09-08 02:18:14 +08:00
|
|
|
import PropTypes from 'prop-types';
|
2017-09-29 22:03:08 +08:00
|
|
|
import { defineMessages, injectIntl, intlShape } from 'react-intl';
|
2017-06-07 20:28:41 +08:00
|
|
|
import Dropzone from 'react-dropzone';
|
2017-05-04 00:36:16 +08:00
|
|
|
import update from 'immutability-helper';
|
2017-06-07 20:28:41 +08:00
|
|
|
import cx from 'classnames';
|
|
|
|
|
2017-05-04 04:51:17 +08:00
|
|
|
import ModalFullscreen from '/imports/ui/components/modal/fullscreen/component';
|
2017-04-29 02:42:32 +08:00
|
|
|
import Icon from '/imports/ui/components/icon/component';
|
|
|
|
import ButtonBase from '/imports/ui/components/button/base/component';
|
2017-05-04 00:36:16 +08:00
|
|
|
import Checkbox from '/imports/ui/components/checkbox/component';
|
2017-04-29 02:42:32 +08:00
|
|
|
import styles from './styles.scss';
|
|
|
|
|
2017-09-08 02:18:14 +08:00
|
|
|
const propTypes = {
|
2017-09-30 04:32:31 +08:00
|
|
|
intl: intlShape.isRequired,
|
2017-09-08 02:18:14 +08:00
|
|
|
defaultFileName: PropTypes.string.isRequired,
|
|
|
|
fileSizeMin: PropTypes.number.isRequired,
|
|
|
|
fileSizeMax: PropTypes.number.isRequired,
|
|
|
|
handleSave: PropTypes.func.isRequired,
|
|
|
|
fileValidMimeTypes: PropTypes.arrayOf(PropTypes.string).isRequired,
|
|
|
|
presentations: PropTypes.arrayOf(PropTypes.shape({
|
|
|
|
id: PropTypes.string.isRequired,
|
|
|
|
filename: PropTypes.string.isRequired,
|
|
|
|
isCurrent: PropTypes.bool.isRequired,
|
|
|
|
conversion: PropTypes.object,
|
|
|
|
upload: PropTypes.object,
|
|
|
|
})).isRequired,
|
|
|
|
};
|
|
|
|
|
|
|
|
const defaultProps = {
|
|
|
|
defaultFileName: 'default.pdf',
|
|
|
|
};
|
|
|
|
|
2017-04-29 02:42:32 +08:00
|
|
|
const intlMessages = defineMessages({
|
|
|
|
title: {
|
|
|
|
id: 'app.presentationUploder.title',
|
|
|
|
defaultMessage: 'Presentation',
|
|
|
|
},
|
|
|
|
message: {
|
|
|
|
id: 'app.presentationUploder.message',
|
|
|
|
defaultMessage: `As a presenter in BigBlueButton, you have the ability of
|
|
|
|
uploading any office document or PDF file. We recommend for the best results,
|
|
|
|
to please upload a PDF file.`,
|
|
|
|
},
|
|
|
|
confirmLabel: {
|
|
|
|
id: 'app.presentationUploder.confirmLabel',
|
|
|
|
defaultMessage: 'Start',
|
|
|
|
},
|
|
|
|
confirmDesc: {
|
|
|
|
id: 'app.presentationUploder.confirmDesc',
|
|
|
|
defaultMessage: 'Save your changes and start the presentation',
|
|
|
|
},
|
|
|
|
dismissLabel: {
|
|
|
|
id: 'app.presentationUploder.dismissLabel',
|
|
|
|
defaultMessage: 'Cancel',
|
|
|
|
},
|
|
|
|
dismissDesc: {
|
|
|
|
id: 'app.presentationUploder.dismissDesc',
|
2017-09-29 22:03:08 +08:00
|
|
|
defaultMessage: 'Close the modal window and discard your changes',
|
2017-04-29 02:42:32 +08:00
|
|
|
},
|
|
|
|
dropzoneLabel: {
|
|
|
|
id: 'app.presentationUploder.dropzoneLabel',
|
|
|
|
defaultMessage: 'Drag files here to upload',
|
|
|
|
},
|
|
|
|
browseFilesLabel: {
|
|
|
|
id: 'app.presentationUploder.browseFilesLabel',
|
|
|
|
defaultMessage: 'or browse for files',
|
|
|
|
},
|
2017-05-06 04:17:38 +08:00
|
|
|
fileToUpload: {
|
|
|
|
id: 'app.presentationUploder.fileToUpload',
|
|
|
|
defaultMessage: 'To be uploaded...',
|
|
|
|
},
|
2017-09-08 02:18:14 +08:00
|
|
|
uploadProcess: {
|
|
|
|
id: 'app.presentationUploder.upload.progress',
|
|
|
|
defaultMessage: 'Uploading ({progress}%)',
|
|
|
|
},
|
|
|
|
413: {
|
|
|
|
id: 'app.presentationUploder.upload.413',
|
|
|
|
defaultMessage: 'File is too large.',
|
2017-05-06 04:17:38 +08:00
|
|
|
},
|
|
|
|
conversionProcessingSlides: {
|
|
|
|
id: 'app.presentationUploder.conversion.conversionProcessingSlides',
|
|
|
|
defaultMessage: 'Processing page {current} of {total}',
|
|
|
|
},
|
|
|
|
genericConversionStatus: {
|
|
|
|
id: 'app.presentationUploder.conversion.genericConversionStatus',
|
|
|
|
defaultMessage: 'Converting file...',
|
|
|
|
},
|
|
|
|
GENERATING_THUMBNAIL: {
|
|
|
|
id: 'app.presentationUploder.conversion.generatingThumbnail',
|
|
|
|
defaultMessage: 'Generating thumbnails...',
|
|
|
|
},
|
2017-09-27 03:45:33 +08:00
|
|
|
GENERATING_SVGIMAGES: {
|
|
|
|
id: 'app.presentationUploder.conversion.generatingSvg',
|
|
|
|
defaultMessage: 'Generating SVG images...',
|
|
|
|
},
|
2017-05-06 04:17:38 +08:00
|
|
|
GENERATED_SLIDE: {
|
|
|
|
id: 'app.presentationUploder.conversion.generatedSlides',
|
|
|
|
defaultMessage: 'Slides generated...',
|
|
|
|
},
|
2017-04-29 02:42:32 +08:00
|
|
|
});
|
|
|
|
|
2017-05-06 04:17:38 +08:00
|
|
|
class PresentationUploader extends Component {
|
2017-04-29 02:42:32 +08:00
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
|
|
|
|
this.state = {
|
|
|
|
presentations: props.presentations,
|
2017-05-06 04:17:38 +08:00
|
|
|
preventClosing: false,
|
|
|
|
disableActions: false,
|
2017-04-29 02:42:32 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
this.handleConfirm = this.handleConfirm.bind(this);
|
|
|
|
this.handleDismiss = this.handleDismiss.bind(this);
|
|
|
|
this.handleFiledrop = this.handleFiledrop.bind(this);
|
|
|
|
this.handleCurrentChange = this.handleCurrentChange.bind(this);
|
|
|
|
this.handleRemove = this.handleRemove.bind(this);
|
2017-09-27 03:45:33 +08:00
|
|
|
|
|
|
|
this.updateFileKey = this.updateFileKey.bind(this);
|
|
|
|
this.deepMergeUpdateFileKey = this.deepMergeUpdateFileKey.bind(this);
|
2017-04-29 02:42:32 +08:00
|
|
|
}
|
|
|
|
|
2017-05-06 04:17:38 +08:00
|
|
|
componentWillReceiveProps(nextProps) {
|
2017-09-23 04:45:31 +08:00
|
|
|
const nextPresentations = nextProps.presentations;
|
2017-05-06 04:17:38 +08:00
|
|
|
|
2017-09-27 03:45:33 +08:00
|
|
|
// Update only the conversion state when receiving new props
|
2017-09-23 04:45:31 +08:00
|
|
|
nextPresentations.forEach((file) => {
|
2017-09-27 03:45:33 +08:00
|
|
|
this.updateFileKey(file.filename, 'id', file.id);
|
|
|
|
this.deepMergeUpdateFileKey(file.id, 'conversion', file.conversion);
|
2017-09-23 04:45:31 +08:00
|
|
|
});
|
2017-05-06 04:17:38 +08:00
|
|
|
}
|
|
|
|
|
2017-09-27 03:45:33 +08:00
|
|
|
updateFileKey(id, key, value, operation = '$set') {
|
|
|
|
this.setState(({ presentations }) => {
|
|
|
|
// Compare id and filename since non-uploaded files dont have a real id
|
|
|
|
const fileIndex = presentations.findIndex(f => f.id === id || f.filename === id);
|
|
|
|
|
|
|
|
return fileIndex === -1 ? false : {
|
|
|
|
presentations: update(presentations, {
|
|
|
|
[fileIndex]: { $apply: file =>
|
|
|
|
update(file, { [key]: {
|
|
|
|
[operation]: value,
|
|
|
|
} }),
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
};
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
deepMergeUpdateFileKey(id, key, value) {
|
|
|
|
const applyValue = toUpdate => update(toUpdate, { $merge: value });
|
|
|
|
this.updateFileKey(id, key, applyValue, '$apply');
|
|
|
|
}
|
|
|
|
|
2017-04-29 02:42:32 +08:00
|
|
|
handleConfirm() {
|
2017-06-07 20:28:41 +08:00
|
|
|
const { presentations } = this.state;
|
2017-05-04 00:36:16 +08:00
|
|
|
|
2017-05-06 04:17:38 +08:00
|
|
|
this.setState({
|
|
|
|
disableActions: true,
|
|
|
|
preventClosing: true,
|
|
|
|
});
|
2017-05-04 00:36:16 +08:00
|
|
|
|
2017-09-27 03:45:33 +08:00
|
|
|
return this.props.handleSave(presentations)
|
2017-09-30 01:44:18 +08:00
|
|
|
.then(() => {
|
|
|
|
this.setState({
|
|
|
|
disableActions: false,
|
|
|
|
preventClosing: false,
|
|
|
|
});
|
|
|
|
})
|
2017-09-27 03:45:33 +08:00
|
|
|
.catch((error) => {
|
|
|
|
this.setState({
|
|
|
|
disableActions: false,
|
|
|
|
preventClosing: true,
|
|
|
|
error,
|
|
|
|
});
|
|
|
|
});
|
2017-04-29 02:42:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
handleDismiss() {
|
2017-06-07 20:28:41 +08:00
|
|
|
return new Promise((resolve) => {
|
2017-05-06 04:17:38 +08:00
|
|
|
this.setState({
|
|
|
|
preventClosing: false,
|
|
|
|
disableActions: false,
|
|
|
|
}, resolve);
|
|
|
|
});
|
2017-04-29 02:42:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
handleFiledrop(files) {
|
2017-06-07 20:28:41 +08:00
|
|
|
const presentationsToUpload = files.map(file => ({
|
|
|
|
file,
|
2017-09-27 03:45:33 +08:00
|
|
|
id: file.name,
|
2017-04-29 02:42:32 +08:00
|
|
|
filename: file.name,
|
2017-09-08 02:18:14 +08:00
|
|
|
isCurrent: false,
|
2017-06-07 20:28:41 +08:00
|
|
|
conversion: { done: false, error: false },
|
2017-09-08 02:18:14 +08:00
|
|
|
upload: { done: false, error: false, progress: 0 },
|
|
|
|
onProgress: (event) => {
|
2017-09-23 04:45:31 +08:00
|
|
|
if (!event.lengthComputable) {
|
2017-09-27 03:45:33 +08:00
|
|
|
this.deepMergeUpdateFileKey(file.name, 'upload', {
|
2017-09-23 04:45:31 +08:00
|
|
|
progress: 100,
|
|
|
|
done: true,
|
|
|
|
});
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2017-09-08 02:18:14 +08:00
|
|
|
|
2017-09-27 03:45:33 +08:00
|
|
|
this.deepMergeUpdateFileKey(file.name, 'upload', {
|
2017-09-08 02:18:14 +08:00
|
|
|
progress: (event.loaded / event.total) * 100,
|
|
|
|
done: event.loaded === event.total,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
onError: (error) => {
|
2017-09-27 03:45:33 +08:00
|
|
|
this.deepMergeUpdateFileKey(file.name, 'upload', { error });
|
2017-09-08 02:18:14 +08:00
|
|
|
},
|
2017-04-29 02:42:32 +08:00
|
|
|
}));
|
|
|
|
|
|
|
|
this.setState(({ presentations }) => ({
|
2017-09-08 02:18:14 +08:00
|
|
|
presentations: presentations.concat(presentationsToUpload),
|
2017-04-29 02:42:32 +08:00
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
handleCurrentChange(item) {
|
2017-09-27 03:45:33 +08:00
|
|
|
const { presentations, disableActions } = this.state;
|
|
|
|
if (disableActions) return;
|
|
|
|
|
2017-04-29 02:42:32 +08:00
|
|
|
const currentIndex = presentations.findIndex(p => p.isCurrent);
|
|
|
|
const newCurrentIndex = presentations.indexOf(item);
|
|
|
|
|
2017-06-07 20:28:41 +08:00
|
|
|
const commands = {};
|
2017-09-26 04:49:54 +08:00
|
|
|
|
|
|
|
// we can end up without a current presentation
|
|
|
|
if (currentIndex !== -1) {
|
|
|
|
commands[currentIndex] = {
|
|
|
|
$apply: (_) => {
|
|
|
|
const p = _;
|
|
|
|
p.isCurrent = false;
|
|
|
|
return p;
|
|
|
|
},
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2017-04-29 02:42:32 +08:00
|
|
|
commands[newCurrentIndex] = {
|
2017-06-07 20:28:41 +08:00
|
|
|
$apply: (_) => {
|
|
|
|
const p = _;
|
2017-04-29 02:42:32 +08:00
|
|
|
p.isCurrent = true;
|
|
|
|
return p;
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2017-06-07 20:28:41 +08:00
|
|
|
const presentationsUpdated = update(presentations, commands);
|
2017-04-29 02:42:32 +08:00
|
|
|
|
|
|
|
this.setState({
|
|
|
|
presentations: presentationsUpdated,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
handleRemove(item) {
|
2017-09-27 03:45:33 +08:00
|
|
|
const { presentations, disableActions } = this.state;
|
|
|
|
if (disableActions) return;
|
|
|
|
|
2017-04-29 02:42:32 +08:00
|
|
|
const toRemoveIndex = presentations.indexOf(item);
|
2017-05-06 04:17:38 +08:00
|
|
|
const toRemove = presentations[toRemoveIndex];
|
|
|
|
|
2017-09-27 03:45:33 +08:00
|
|
|
|
2017-05-06 04:17:38 +08:00
|
|
|
if (toRemove.isCurrent) {
|
2017-09-23 04:45:31 +08:00
|
|
|
const defaultPresentation =
|
|
|
|
presentations.find(_ => _.filename === this.props.defaultFileName);
|
2017-05-06 04:17:38 +08:00
|
|
|
this.handleCurrentChange(defaultPresentation);
|
|
|
|
}
|
2017-04-29 02:42:32 +08:00
|
|
|
|
|
|
|
this.setState({
|
|
|
|
presentations: update(presentations, {
|
|
|
|
$splice: [[toRemoveIndex, 1]],
|
|
|
|
}),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
renderPresentationList() {
|
2017-06-07 20:28:41 +08:00
|
|
|
const { presentations } = this.state;
|
2017-04-29 02:42:32 +08:00
|
|
|
|
2017-06-07 20:28:41 +08:00
|
|
|
const presentationsSorted = presentations
|
2017-09-23 04:45:31 +08:00
|
|
|
.sort((a, b) => b.filename === this.props.defaultFileName);
|
2017-04-29 02:42:32 +08:00
|
|
|
|
|
|
|
return (
|
2017-05-04 00:36:16 +08:00
|
|
|
<div className={styles.fileList}>
|
|
|
|
<table className={styles.table}>
|
|
|
|
<tbody>
|
2017-06-07 20:28:41 +08:00
|
|
|
{ presentationsSorted.map(item => this.renderPresentationItem(item))}
|
2017-05-04 00:36:16 +08:00
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
</div>
|
2017-04-29 02:42:32 +08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-05-06 04:17:38 +08:00
|
|
|
renderPresentationItemStatus(item) {
|
2017-06-07 20:28:41 +08:00
|
|
|
const { intl } = this.props;
|
2017-05-06 04:17:38 +08:00
|
|
|
|
2017-09-08 02:18:14 +08:00
|
|
|
if (!item.upload.done && item.upload.progress === 0) {
|
|
|
|
return intl.formatMessage(intlMessages.fileToUpload);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!item.upload.done && !item.upload.error) {
|
|
|
|
return intl.formatMessage(intlMessages.uploadProcess, {
|
2017-11-01 20:19:18 +08:00
|
|
|
progress: Math.floor(item.upload.progress).toString(),
|
2017-09-08 02:18:14 +08:00
|
|
|
});
|
|
|
|
}
|
2017-05-06 04:17:38 +08:00
|
|
|
|
2017-09-08 02:18:14 +08:00
|
|
|
if (item.upload.done && item.upload.error) {
|
|
|
|
const errorMessage = intlMessages[item.upload.error.code] || intlMessages.genericError;
|
|
|
|
return intl.formatMessage(errorMessage);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!item.conversion.done && item.conversion.error) {
|
2017-05-06 04:17:38 +08:00
|
|
|
const errorMessage = intlMessages[status] || intlMessages.genericError;
|
|
|
|
return intl.formatMessage(errorMessage);
|
|
|
|
}
|
|
|
|
|
2017-09-08 02:18:14 +08:00
|
|
|
if (!item.conversion.done && !item.conversion.error) {
|
|
|
|
if (item.conversion.pagesCompleted < item.conversion.numPages) {
|
2017-05-06 04:17:38 +08:00
|
|
|
return intl.formatMessage(intlMessages.conversionProcessingSlides, {
|
2017-09-08 02:18:14 +08:00
|
|
|
current: item.conversion.pagesCompleted,
|
|
|
|
total: item.conversion.numPages,
|
2017-05-06 04:17:38 +08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
const conversionStatusMessage =
|
|
|
|
intlMessages[item.conversion.status] || intlMessages.genericConversionStatus;
|
|
|
|
return intl.formatMessage(conversionStatusMessage);
|
|
|
|
}
|
|
|
|
|
2017-09-08 02:18:14 +08:00
|
|
|
return null;
|
2017-05-06 04:17:38 +08:00
|
|
|
}
|
|
|
|
|
2017-04-29 02:42:32 +08:00
|
|
|
renderPresentationItem(item) {
|
2017-09-08 02:18:14 +08:00
|
|
|
const { disableActions } = this.state;
|
2017-05-04 00:36:16 +08:00
|
|
|
|
2017-09-29 20:49:42 +08:00
|
|
|
const isProcessing = (!item.conversion.done && item.upload.done)
|
|
|
|
|| (!item.upload.done && item.upload.progress > 0);
|
2017-06-07 20:28:41 +08:00
|
|
|
const itemClassName = {};
|
2017-04-29 02:42:32 +08:00
|
|
|
|
2017-05-06 04:17:38 +08:00
|
|
|
itemClassName[styles.tableItemNew] = item.id === item.filename;
|
2017-09-08 02:18:14 +08:00
|
|
|
itemClassName[styles.tableItemUploading] = !item.upload.done;
|
2017-09-27 03:45:33 +08:00
|
|
|
itemClassName[styles.tableItemProcessing] = !item.conversion.done && item.upload.done;
|
2017-09-08 02:18:14 +08:00
|
|
|
itemClassName[styles.tableItemError] = item.conversion.error || item.upload.error;
|
2017-09-29 20:49:42 +08:00
|
|
|
itemClassName[styles.tableItemAnimated] = isProcessing;
|
2017-04-29 02:42:32 +08:00
|
|
|
|
2017-09-29 20:49:42 +08:00
|
|
|
const hideRemove = isProcessing || item.filename === this.props.defaultFileName;
|
2017-05-04 04:51:17 +08:00
|
|
|
|
2017-04-29 02:42:32 +08:00
|
|
|
return (
|
|
|
|
<tr
|
2017-05-04 00:36:16 +08:00
|
|
|
key={item.id}
|
2017-04-29 02:42:32 +08:00
|
|
|
className={cx(itemClassName)}
|
|
|
|
>
|
|
|
|
<td className={styles.tableItemIcon}>
|
2017-06-07 20:28:41 +08:00
|
|
|
<Icon iconName={'file'} />
|
2017-04-29 02:42:32 +08:00
|
|
|
</td>
|
|
|
|
<th className={styles.tableItemName}>
|
|
|
|
<span>{item.filename}</span>
|
|
|
|
</th>
|
2017-05-06 04:17:38 +08:00
|
|
|
<td className={styles.tableItemStatus}>
|
|
|
|
{this.renderPresentationItemStatus(item)}
|
2017-04-29 02:42:32 +08:00
|
|
|
</td>
|
2017-05-23 22:05:42 +08:00
|
|
|
<td className={styles.tableItemActions}>
|
2017-09-08 02:18:14 +08:00
|
|
|
<Checkbox
|
|
|
|
disabled={disableActions}
|
|
|
|
ariaLabel={'Set as current presentation'}
|
|
|
|
className={styles.itemAction}
|
|
|
|
checked={item.isCurrent}
|
|
|
|
onChange={() => this.handleCurrentChange(item)}
|
|
|
|
/>
|
|
|
|
{ hideRemove ? null : (
|
|
|
|
<ButtonBase
|
|
|
|
disabled={disableActions}
|
|
|
|
className={cx(styles.itemAction, styles.itemActionRemove)}
|
|
|
|
label={'Remove presentation'}
|
|
|
|
onClick={() => this.handleRemove(item)}
|
|
|
|
>
|
|
|
|
<Icon iconName={'delete'} />
|
|
|
|
</ButtonBase>
|
|
|
|
)}
|
2017-05-23 22:05:42 +08:00
|
|
|
</td>
|
2017-04-29 02:42:32 +08:00
|
|
|
</tr>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
renderDropzone() {
|
2017-05-04 00:36:16 +08:00
|
|
|
const {
|
|
|
|
intl,
|
|
|
|
fileSizeMin,
|
|
|
|
fileSizeMax,
|
|
|
|
fileValidMimeTypes,
|
|
|
|
} = this.props;
|
2017-04-29 02:42:32 +08:00
|
|
|
|
2017-05-06 04:17:38 +08:00
|
|
|
const { disableActions } = this.state;
|
|
|
|
|
2017-09-29 20:50:20 +08:00
|
|
|
if (disableActions) return null;
|
2017-05-04 04:51:17 +08:00
|
|
|
|
2017-04-29 02:42:32 +08:00
|
|
|
return (
|
|
|
|
<Dropzone
|
2017-09-08 02:18:14 +08:00
|
|
|
multiple
|
2017-04-29 02:42:32 +08:00
|
|
|
className={styles.dropzone}
|
|
|
|
activeClassName={styles.dropzoneActive}
|
|
|
|
rejectClassName={styles.dropzoneReject}
|
2017-05-04 00:36:16 +08:00
|
|
|
accept={fileValidMimeTypes.join()}
|
|
|
|
minSize={fileSizeMin}
|
|
|
|
maxSize={fileSizeMax}
|
2017-06-07 20:28:41 +08:00
|
|
|
disablePreview
|
2017-04-29 02:42:32 +08:00
|
|
|
onDrop={this.handleFiledrop}
|
|
|
|
>
|
2017-06-07 20:28:41 +08:00
|
|
|
<Icon className={styles.dropzoneIcon} iconName={'upload'} />
|
2017-04-29 02:42:32 +08:00
|
|
|
<p className={styles.dropzoneMessage}>
|
|
|
|
{intl.formatMessage(intlMessages.dropzoneLabel)}
|
|
|
|
<span className={styles.dropzoneLink}>
|
|
|
|
{intl.formatMessage(intlMessages.browseFilesLabel)}
|
|
|
|
</span>
|
|
|
|
</p>
|
|
|
|
</Dropzone>
|
|
|
|
);
|
|
|
|
}
|
2017-06-07 20:28:41 +08:00
|
|
|
|
|
|
|
render() {
|
|
|
|
const { intl } = this.props;
|
|
|
|
const { preventClosing, disableActions } = this.state;
|
|
|
|
|
|
|
|
return (
|
|
|
|
<ModalFullscreen
|
|
|
|
title={intl.formatMessage(intlMessages.title)}
|
|
|
|
preventClosing={preventClosing}
|
|
|
|
confirm={{
|
|
|
|
callback: this.handleConfirm,
|
|
|
|
label: intl.formatMessage(intlMessages.confirmLabel),
|
|
|
|
description: intl.formatMessage(intlMessages.confirmDesc),
|
|
|
|
disabled: disableActions,
|
|
|
|
}}
|
|
|
|
dismiss={{
|
|
|
|
callback: this.handleDismiss,
|
|
|
|
label: intl.formatMessage(intlMessages.dismissLabel),
|
|
|
|
description: intl.formatMessage(intlMessages.dismissDesc),
|
|
|
|
disabled: disableActions,
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<p>{intl.formatMessage(intlMessages.message)}</p>
|
|
|
|
{this.renderPresentationList()}
|
|
|
|
{this.renderDropzone()}
|
|
|
|
</ModalFullscreen>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2017-04-29 02:42:32 +08:00
|
|
|
|
2017-09-23 04:45:31 +08:00
|
|
|
PresentationUploader.propTypes = propTypes;
|
|
|
|
PresentationUploader.defaultProps = defaultProps;
|
|
|
|
|
2017-05-06 04:17:38 +08:00
|
|
|
export default injectIntl(PresentationUploader);
|