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';
|
2020-05-26 04:00:13 +08:00
|
|
|
import { defineMessages, injectIntl } from 'react-intl';
|
2022-09-23 23:24:39 +08:00
|
|
|
import { PresentationUploaderToast } from '/imports/ui/components/presentation/presentation-toast/presentation-uploader-toast/component';
|
2021-08-30 08:53:06 +08:00
|
|
|
import { TAB } from '/imports/utils/keyCodes';
|
2021-04-01 01:13:36 +08:00
|
|
|
import deviceInfo from '/imports/utils/deviceInfo';
|
2022-02-15 04:20:50 +08:00
|
|
|
import Button from '/imports/ui/components/common/button/component';
|
2022-02-15 22:51:51 +08:00
|
|
|
import Icon from '/imports/ui/components/common/icon/component';
|
2017-05-04 00:36:16 +08:00
|
|
|
import update from 'immutability-helper';
|
2018-07-12 06:03:56 +08:00
|
|
|
import logger from '/imports/startup/client/logger';
|
2020-02-26 03:29:14 +08:00
|
|
|
import { notify } from '/imports/ui/services/notification';
|
|
|
|
import { toast } from 'react-toastify';
|
2020-03-10 05:14:13 +08:00
|
|
|
import _ from 'lodash';
|
2021-09-05 06:36:48 +08:00
|
|
|
import { registerTitleView, unregisterTitleView } from '/imports/utils/dom-utils';
|
2021-11-08 21:57:55 +08:00
|
|
|
import Styled from './styles';
|
|
|
|
import Settings from '/imports/ui/services/settings';
|
2022-02-15 03:26:19 +08:00
|
|
|
import Checkbox from '/imports/ui/components/common/checkbox/component';
|
2017-06-07 20:28:41 +08:00
|
|
|
|
2021-04-01 01:13:36 +08:00
|
|
|
const { isMobile } = deviceInfo;
|
2017-04-29 02:42:32 +08:00
|
|
|
|
2017-09-08 02:18:14 +08:00
|
|
|
const propTypes = {
|
2020-05-26 04:00:13 +08:00
|
|
|
intl: PropTypes.object.isRequired,
|
2022-01-20 03:45:24 +08:00
|
|
|
fileUploadConstraintsHint: PropTypes.bool.isRequired,
|
|
|
|
fileSizeMax: PropTypes.number.isRequired,
|
|
|
|
filePagesMax: PropTypes.number.isRequired,
|
2017-09-08 02:18:14 +08:00
|
|
|
handleSave: PropTypes.func.isRequired,
|
2019-02-21 06:20:04 +08:00
|
|
|
dispatchTogglePresentationDownloadable: PropTypes.func.isRequired,
|
2019-03-08 03:53:01 +08:00
|
|
|
fileValidMimeTypes: PropTypes.arrayOf(PropTypes.object).isRequired,
|
2017-09-08 02:18:14 +08:00
|
|
|
presentations: PropTypes.arrayOf(PropTypes.shape({
|
|
|
|
id: PropTypes.string.isRequired,
|
|
|
|
filename: PropTypes.string.isRequired,
|
|
|
|
isCurrent: PropTypes.bool.isRequired,
|
|
|
|
conversion: PropTypes.object,
|
|
|
|
upload: PropTypes.object,
|
|
|
|
})).isRequired,
|
2020-02-26 03:29:14 +08:00
|
|
|
isOpen: PropTypes.bool.isRequired,
|
2017-09-08 02:18:14 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
const defaultProps = {
|
|
|
|
};
|
|
|
|
|
2017-04-29 02:42:32 +08:00
|
|
|
const intlMessages = defineMessages({
|
2017-12-05 00:10:37 +08:00
|
|
|
current: {
|
|
|
|
id: 'app.presentationUploder.currentBadge',
|
|
|
|
},
|
2017-04-29 02:42:32 +08:00
|
|
|
title: {
|
|
|
|
id: 'app.presentationUploder.title',
|
2017-11-02 00:13:18 +08:00
|
|
|
description: 'title of the modal',
|
2017-04-29 02:42:32 +08:00
|
|
|
},
|
|
|
|
message: {
|
|
|
|
id: 'app.presentationUploder.message',
|
2017-11-02 00:13:18 +08:00
|
|
|
description: 'message warning the types of files accepted',
|
2017-04-29 02:42:32 +08:00
|
|
|
},
|
2019-05-29 05:18:49 +08:00
|
|
|
uploadLabel: {
|
|
|
|
id: 'app.presentationUploder.uploadLabel',
|
|
|
|
description: 'confirm label when presentations are to be uploaded',
|
2017-04-29 02:42:32 +08:00
|
|
|
},
|
|
|
|
confirmLabel: {
|
|
|
|
id: 'app.presentationUploder.confirmLabel',
|
2019-05-25 03:51:50 +08:00
|
|
|
description: 'confirm label when no presentations are to be uploaded',
|
2017-04-29 02:42:32 +08:00
|
|
|
},
|
|
|
|
confirmDesc: {
|
|
|
|
id: 'app.presentationUploder.confirmDesc',
|
2017-11-02 00:13:18 +08:00
|
|
|
description: 'description of the confirm',
|
2017-04-29 02:42:32 +08:00
|
|
|
},
|
|
|
|
dismissLabel: {
|
|
|
|
id: 'app.presentationUploder.dismissLabel',
|
2017-11-02 00:13:18 +08:00
|
|
|
description: 'used in the button that close modal',
|
2017-04-29 02:42:32 +08:00
|
|
|
},
|
|
|
|
dismissDesc: {
|
|
|
|
id: 'app.presentationUploder.dismissDesc',
|
2017-11-02 00:13:18 +08:00
|
|
|
description: 'description of the dismiss',
|
2017-04-29 02:42:32 +08:00
|
|
|
},
|
|
|
|
dropzoneLabel: {
|
|
|
|
id: 'app.presentationUploder.dropzoneLabel',
|
2017-11-02 00:13:18 +08:00
|
|
|
description: 'message warning where drop files for upload',
|
2017-04-29 02:42:32 +08:00
|
|
|
},
|
2022-06-25 00:47:17 +08:00
|
|
|
externalUploadTitle: {
|
|
|
|
id: 'app.presentationUploder.externalUploadTitle',
|
|
|
|
description: 'title for external upload area',
|
|
|
|
},
|
|
|
|
externalUploadLabel: {
|
|
|
|
id: 'app.presentationUploder.externalUploadLabel',
|
|
|
|
description: 'message of external upload button',
|
|
|
|
},
|
2018-12-17 17:30:32 +08:00
|
|
|
dropzoneImagesLabel: {
|
|
|
|
id: 'app.presentationUploder.dropzoneImagesLabel',
|
|
|
|
description: 'message warning where drop images for upload',
|
|
|
|
},
|
2017-04-29 02:42:32 +08:00
|
|
|
browseFilesLabel: {
|
|
|
|
id: 'app.presentationUploder.browseFilesLabel',
|
2017-11-02 00:13:18 +08:00
|
|
|
description: 'message use on the file browser',
|
2017-04-29 02:42:32 +08:00
|
|
|
},
|
2018-12-03 14:10:50 +08:00
|
|
|
browseImagesLabel: {
|
|
|
|
id: 'app.presentationUploder.browseImagesLabel',
|
|
|
|
description: 'message use on the image browser',
|
|
|
|
},
|
2017-05-06 04:17:38 +08:00
|
|
|
fileToUpload: {
|
|
|
|
id: 'app.presentationUploder.fileToUpload',
|
2017-11-02 00:13:18 +08:00
|
|
|
description: 'message used in the file selected for upload',
|
2017-05-06 04:17:38 +08:00
|
|
|
},
|
2022-01-20 03:45:24 +08:00
|
|
|
extraHint: {
|
|
|
|
id: 'app.presentationUploder.extraHint',
|
|
|
|
description: 'message used to indicate upload file max sizes',
|
|
|
|
},
|
2018-12-03 11:40:58 +08:00
|
|
|
rejectedError: {
|
|
|
|
id: 'app.presentationUploder.rejectedError',
|
|
|
|
description: 'some files rejected, please check the file mime types',
|
|
|
|
},
|
2022-02-22 02:01:55 +08:00
|
|
|
badConnectionError: {
|
|
|
|
id: 'app.presentationUploder.connectionClosedError',
|
|
|
|
description: 'message indicating that the connection was closed',
|
|
|
|
},
|
2017-09-08 02:18:14 +08:00
|
|
|
uploadProcess: {
|
|
|
|
id: 'app.presentationUploder.upload.progress',
|
2017-11-02 00:13:18 +08:00
|
|
|
description: 'message that indicates the percentage of the upload',
|
2017-09-08 02:18:14 +08:00
|
|
|
},
|
|
|
|
413: {
|
|
|
|
id: 'app.presentationUploder.upload.413',
|
2017-11-02 00:13:18 +08:00
|
|
|
description: 'error that file exceed the size limit',
|
2017-05-06 04:17:38 +08:00
|
|
|
},
|
2020-04-30 00:34:37 +08:00
|
|
|
408: {
|
|
|
|
id: 'app.presentationUploder.upload.408',
|
|
|
|
description: 'error for token request timeout',
|
|
|
|
},
|
|
|
|
404: {
|
|
|
|
id: 'app.presentationUploder.upload.404',
|
|
|
|
description: 'error not found',
|
|
|
|
},
|
|
|
|
401: {
|
|
|
|
id: 'app.presentationUploder.upload.401',
|
|
|
|
description: 'error for failed upload token request.',
|
|
|
|
},
|
2017-05-06 04:17:38 +08:00
|
|
|
conversionProcessingSlides: {
|
|
|
|
id: 'app.presentationUploder.conversion.conversionProcessingSlides',
|
2017-11-02 00:13:18 +08:00
|
|
|
description: 'indicates how many slides were converted',
|
2017-05-06 04:17:38 +08:00
|
|
|
},
|
2020-03-12 21:56:12 +08:00
|
|
|
genericError: {
|
|
|
|
id: 'app.presentationUploder.genericError',
|
|
|
|
description: 'generic error while uploading/converting',
|
|
|
|
},
|
2017-05-06 04:17:38 +08:00
|
|
|
genericConversionStatus: {
|
|
|
|
id: 'app.presentationUploder.conversion.genericConversionStatus',
|
2017-11-02 00:13:18 +08:00
|
|
|
description: 'indicates that file is being converted',
|
2017-05-06 04:17:38 +08:00
|
|
|
},
|
2017-11-28 01:44:45 +08:00
|
|
|
TIMEOUT: {
|
|
|
|
id: 'app.presentationUploder.conversion.timeout',
|
|
|
|
},
|
2022-10-18 04:05:16 +08:00
|
|
|
CONVERSION_TIMEOUT: {
|
|
|
|
id:'app.presentationUploder.conversion.conversionTimeout',
|
|
|
|
description: 'warns the user that the presentation timed out in the back-end in specific page of the document',
|
|
|
|
},
|
2017-05-06 04:17:38 +08:00
|
|
|
GENERATING_THUMBNAIL: {
|
|
|
|
id: 'app.presentationUploder.conversion.generatingThumbnail',
|
2017-11-28 01:44:45 +08:00
|
|
|
description: 'indicatess that it is generating thumbnails',
|
2017-05-06 04:17:38 +08:00
|
|
|
},
|
2017-09-27 03:45:33 +08:00
|
|
|
GENERATING_SVGIMAGES: {
|
|
|
|
id: 'app.presentationUploder.conversion.generatingSvg',
|
2017-11-02 00:13:18 +08:00
|
|
|
description: 'warns that it is generating svg images',
|
2017-09-27 03:45:33 +08:00
|
|
|
},
|
2017-05-06 04:17:38 +08:00
|
|
|
GENERATED_SLIDE: {
|
|
|
|
id: 'app.presentationUploder.conversion.generatedSlides',
|
2017-11-02 00:13:18 +08:00
|
|
|
description: 'warns that were slides generated',
|
2017-05-06 04:17:38 +08:00
|
|
|
},
|
2017-11-28 20:26:00 +08:00
|
|
|
PAGE_COUNT_EXCEEDED: {
|
|
|
|
id: 'app.presentationUploder.conversion.pageCountExceeded',
|
|
|
|
description: 'warns the user that the conversion failed because of the page count',
|
|
|
|
},
|
2019-10-16 15:37:03 +08:00
|
|
|
PDF_HAS_BIG_PAGE: {
|
|
|
|
id: 'app.presentationUploder.conversion.pdfHasBigPage',
|
|
|
|
description: 'warns the user that the conversion failed because of the pdf page siz that exceeds the allowed limit',
|
|
|
|
},
|
2021-04-28 03:45:14 +08:00
|
|
|
OFFICE_DOC_CONVERSION_INVALID: {
|
|
|
|
id: 'app.presentationUploder.conversion.officeDocConversionInvalid',
|
|
|
|
description: '',
|
|
|
|
},
|
|
|
|
OFFICE_DOC_CONVERSION_FAILED: {
|
|
|
|
id: 'app.presentationUploder.conversion.officeDocConversionFailed',
|
|
|
|
description: 'warns the user that the conversion failed because of wrong office file',
|
|
|
|
},
|
|
|
|
UNSUPPORTED_DOCUMENT: {
|
|
|
|
id: 'app.presentationUploder.conversion.unsupportedDocument',
|
|
|
|
description: 'warns the user that the file extension is not supported',
|
|
|
|
},
|
2019-02-21 06:44:44 +08:00
|
|
|
isDownloadable: {
|
|
|
|
id: 'app.presentationUploder.isDownloadableLabel',
|
2019-02-22 05:10:32 +08:00
|
|
|
description: 'presentation is available for downloading by all viewers',
|
2019-02-21 06:44:44 +08:00
|
|
|
},
|
|
|
|
isNotDownloadable: {
|
|
|
|
id: 'app.presentationUploder.isNotDownloadableLabel',
|
2019-02-22 05:10:32 +08:00
|
|
|
description: 'presentation is not available for downloading the viewers',
|
2019-02-21 06:44:44 +08:00
|
|
|
},
|
|
|
|
removePresentation: {
|
|
|
|
id: 'app.presentationUploder.removePresentationLabel',
|
|
|
|
description: 'select to delete this presentation',
|
|
|
|
},
|
2019-02-22 07:43:11 +08:00
|
|
|
setAsCurrentPresentation: {
|
|
|
|
id: 'app.presentationUploder.setAsCurrentPresentation',
|
|
|
|
description: 'set this presentation to be the current one',
|
|
|
|
},
|
2019-05-15 00:51:13 +08:00
|
|
|
status: {
|
|
|
|
id: 'app.presentationUploder.tableHeading.status',
|
|
|
|
description: 'aria label status table heading',
|
|
|
|
},
|
|
|
|
options: {
|
|
|
|
id: 'app.presentationUploder.tableHeading.options',
|
|
|
|
description: 'aria label for options table heading',
|
|
|
|
},
|
|
|
|
filename: {
|
|
|
|
id: 'app.presentationUploder.tableHeading.filename',
|
|
|
|
description: 'aria label for file name table heading',
|
|
|
|
},
|
2020-03-10 20:58:14 +08:00
|
|
|
uploading: {
|
|
|
|
id: 'app.presentationUploder.uploading',
|
|
|
|
description: 'uploading label for toast notification',
|
|
|
|
},
|
|
|
|
uploadStatus: {
|
|
|
|
id: 'app.presentationUploder.uploadStatus',
|
|
|
|
description: 'upload status for toast notification',
|
|
|
|
},
|
|
|
|
completed: {
|
|
|
|
id: 'app.presentationUploder.completed',
|
|
|
|
description: 'uploads complete label for toast notification',
|
|
|
|
},
|
|
|
|
item: {
|
|
|
|
id: 'app.presentationUploder.item',
|
|
|
|
description: 'single item label',
|
|
|
|
},
|
|
|
|
itemPlural: {
|
|
|
|
id: 'app.presentationUploder.itemPlural',
|
|
|
|
description: 'plural item label',
|
|
|
|
},
|
|
|
|
clearErrors: {
|
|
|
|
id: 'app.presentationUploder.clearErrors',
|
|
|
|
description: 'button label for clearing upload errors',
|
|
|
|
},
|
|
|
|
clearErrorsDesc: {
|
|
|
|
id: 'app.presentationUploder.clearErrorsDesc',
|
|
|
|
description: 'aria description for button clearing upload error',
|
|
|
|
},
|
2021-09-05 06:36:48 +08:00
|
|
|
uploadViewTitle: {
|
|
|
|
id: 'app.presentationUploder.uploadViewTitle',
|
|
|
|
description: 'view name apended to document title',
|
2022-07-20 03:36:00 +08:00
|
|
|
},
|
|
|
|
exportHint: {
|
|
|
|
id: 'app.presentationUploader.exportHint',
|
|
|
|
description: 'message to indicate the export presentation option',
|
|
|
|
},
|
|
|
|
exportToastHeader: {
|
|
|
|
id: 'app.presentationUploader.exportToastHeader',
|
|
|
|
description: 'exporting toast header',
|
|
|
|
},
|
|
|
|
exportToastHeaderPlural: {
|
|
|
|
id: 'app.presentationUploader.exportToastHeaderPlural',
|
|
|
|
description: 'exporting toast header in plural',
|
|
|
|
},
|
|
|
|
export: {
|
|
|
|
id: 'app.presentationUploader.export',
|
|
|
|
description: 'send presentation to chat',
|
|
|
|
},
|
|
|
|
exporting: {
|
|
|
|
id: 'app.presentationUploader.exporting',
|
|
|
|
description: 'presentation is being sent to chat',
|
|
|
|
},
|
|
|
|
currentLabel: {
|
|
|
|
id: 'app.presentationUploader.currentPresentationLabel',
|
|
|
|
description: 'current presentation label',
|
|
|
|
},
|
|
|
|
downloadLabel: {
|
|
|
|
id: 'app.presentation.downloadLabel',
|
|
|
|
description: 'download label',
|
|
|
|
},
|
2022-07-26 05:56:26 +08:00
|
|
|
sending: {
|
|
|
|
id: 'app.presentationUploader.sending',
|
|
|
|
description: 'sending label',
|
|
|
|
},
|
2022-08-24 21:31:20 +08:00
|
|
|
collecting: {
|
|
|
|
id: 'app.presentationUploader.collecting',
|
|
|
|
description: 'collecting label',
|
|
|
|
},
|
|
|
|
processing: {
|
|
|
|
id: 'app.presentationUploader.processing',
|
|
|
|
description: 'processing label',
|
|
|
|
},
|
2022-07-26 05:56:26 +08:00
|
|
|
sent: {
|
|
|
|
id: 'app.presentationUploader.sent',
|
|
|
|
description: 'sent label',
|
|
|
|
},
|
|
|
|
exportingTimeout: {
|
|
|
|
id: 'app.presentationUploader.exportingTimeout',
|
|
|
|
description: 'exporting timeout label',
|
|
|
|
},
|
2017-04-29 02:42:32 +08:00
|
|
|
});
|
|
|
|
|
2022-07-26 05:56:26 +08:00
|
|
|
const EXPORT_STATUSES = {
|
|
|
|
RUNNING: 'RUNNING',
|
2022-08-24 21:31:20 +08:00
|
|
|
COLLECTING: 'COLLECTING',
|
|
|
|
PROCESSING: 'PROCESSING',
|
2022-07-26 05:56:26 +08:00
|
|
|
TIMEOUT: 'TIMEOUT',
|
|
|
|
EXPORTED: 'EXPORTED',
|
|
|
|
};
|
|
|
|
|
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 = {
|
2020-02-26 03:29:14 +08:00
|
|
|
presentations: [],
|
2017-05-06 04:17:38 +08:00
|
|
|
disableActions: false,
|
2020-04-02 06:54:47 +08:00
|
|
|
toUploadCount: 0,
|
2022-07-26 05:56:26 +08:00
|
|
|
presExporting: new Set(),
|
2017-04-29 02:42:32 +08:00
|
|
|
};
|
|
|
|
|
2020-02-26 03:29:14 +08:00
|
|
|
this.toastId = null;
|
2020-03-12 21:56:12 +08:00
|
|
|
this.hasError = null;
|
2022-07-20 03:36:00 +08:00
|
|
|
this.exportToastId = null;
|
2020-02-26 03:29:14 +08:00
|
|
|
|
|
|
|
// handlers
|
2017-04-29 02:42:32 +08:00
|
|
|
this.handleFiledrop = this.handleFiledrop.bind(this);
|
|
|
|
this.handleConfirm = this.handleConfirm.bind(this);
|
|
|
|
this.handleDismiss = this.handleDismiss.bind(this);
|
|
|
|
this.handleRemove = this.handleRemove.bind(this);
|
2020-02-26 03:29:14 +08:00
|
|
|
this.handleCurrentChange = this.handleCurrentChange.bind(this);
|
2022-07-20 03:36:00 +08:00
|
|
|
this.handleSendToChat = this.handleSendToChat.bind(this);
|
2020-02-26 03:29:14 +08:00
|
|
|
// renders
|
|
|
|
this.renderDropzone = this.renderDropzone.bind(this);
|
2022-06-25 00:47:17 +08:00
|
|
|
this.renderExternalUpload = this.renderExternalUpload.bind(this);
|
2020-02-26 03:29:14 +08:00
|
|
|
this.renderPicDropzone = this.renderPicDropzone.bind(this);
|
|
|
|
this.renderPresentationList = this.renderPresentationList.bind(this);
|
|
|
|
this.renderPresentationItem = this.renderPresentationItem.bind(this);
|
2022-07-26 05:56:26 +08:00
|
|
|
this.renderExportToast = this.renderExportToast.bind(this);
|
|
|
|
this.renderToastExportItem = this.renderToastExportItem.bind(this);
|
|
|
|
this.renderExportationStatus = this.renderExportationStatus.bind(this);
|
2020-02-26 03:29:14 +08:00
|
|
|
// utilities
|
2017-09-27 03:45:33 +08:00
|
|
|
this.deepMergeUpdateFileKey = this.deepMergeUpdateFileKey.bind(this);
|
2020-02-26 03:29:14 +08:00
|
|
|
this.updateFileKey = this.updateFileKey.bind(this);
|
2022-07-26 05:56:26 +08:00
|
|
|
this.getPresentationsToShow = this.getPresentationsToShow.bind(this);
|
2019-03-29 22:48:22 +08:00
|
|
|
}
|
|
|
|
|
2020-02-26 03:29:14 +08:00
|
|
|
componentDidUpdate(prevProps) {
|
2021-09-05 06:36:48 +08:00
|
|
|
const { isOpen, presentations: propPresentations, intl } = this.props;
|
2020-02-26 03:29:14 +08:00
|
|
|
const { presentations } = this.state;
|
2022-06-29 00:33:54 +08:00
|
|
|
const { presentations: prevPropPresentations } = prevProps;
|
|
|
|
|
|
|
|
let shouldUpdateState = isOpen && !prevProps.isOpen;
|
|
|
|
const presState = Object.values({
|
2022-10-17 23:12:22 +08:00
|
|
|
...JSON.parse(JSON.stringify(propPresentations)),
|
|
|
|
...JSON.parse(JSON.stringify(presentations)),
|
2022-06-29 00:33:54 +08:00
|
|
|
});
|
2022-10-05 03:25:54 +08:00
|
|
|
if (propPresentations.length > prevPropPresentations.length) {
|
|
|
|
shouldUpdateState = true;
|
2022-10-17 23:12:22 +08:00
|
|
|
const propsDiffs = propPresentations.filter(p =>
|
|
|
|
!prevPropPresentations.some(presentation => p.id === presentation.id
|
2022-10-17 23:21:55 +08:00
|
|
|
|| p.temporaryPresentationId === presentation.temporaryPresentationId));
|
2022-10-05 03:25:54 +08:00
|
|
|
|
|
|
|
propsDiffs.forEach(p => {
|
|
|
|
const index = presState.findIndex(pres => {
|
|
|
|
return pres.temporaryPresentationId === p.temporaryPresentationId || pres.id === p.id;
|
2022-10-06 20:58:42 +08:00
|
|
|
});
|
2022-10-05 03:25:54 +08:00
|
|
|
if (index === -1) {
|
|
|
|
presState.push(p);
|
2022-10-06 20:58:42 +08:00
|
|
|
}
|
2022-10-05 03:25:54 +08:00
|
|
|
})
|
|
|
|
}
|
2022-08-24 00:42:28 +08:00
|
|
|
const presStateFiltered = presState.filter((presentation) => {
|
2022-08-12 00:29:48 +08:00
|
|
|
const currentPropPres = propPresentations.find((pres) => pres.id === presentation.id);
|
2022-08-25 00:34:50 +08:00
|
|
|
const prevPropPres = prevPropPresentations.find((pres) => pres.id === presentation.id);
|
2022-08-16 22:41:11 +08:00
|
|
|
const hasConversionError = presentation?.conversion?.error;
|
2022-08-24 00:42:28 +08:00
|
|
|
const finishedConversion = presentation?.conversion?.done || currentPropPres?.conversion?.done;
|
|
|
|
const hasTemporaryId = presentation.id.startsWith(presentation.filename);
|
2022-08-12 00:29:48 +08:00
|
|
|
|
2022-08-24 00:42:28 +08:00
|
|
|
if (hasConversionError || (!finishedConversion && hasTemporaryId)) return true;
|
2022-08-12 00:29:48 +08:00
|
|
|
if (!currentPropPres) return false;
|
|
|
|
|
2022-10-05 03:25:54 +08:00
|
|
|
if (presentation?.conversion?.done !== finishedConversion) {
|
2022-08-25 00:34:50 +08:00
|
|
|
shouldUpdateState = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (currentPropPres.isCurrent !== prevPropPres?.isCurrent) {
|
|
|
|
presentation.isCurrent = currentPropPres.isCurrent;
|
|
|
|
}
|
|
|
|
|
2022-08-12 00:29:48 +08:00
|
|
|
presentation.conversion = currentPropPres.conversion;
|
|
|
|
presentation.isRemovable = currentPropPres.isRemovable;
|
|
|
|
|
2022-08-24 00:42:28 +08:00
|
|
|
return true;
|
|
|
|
}).filter(presentation => {
|
|
|
|
const duplicated = presentations.find(
|
|
|
|
(pres) => pres.filename === presentation.filename
|
|
|
|
&& pres.id !== presentation.id
|
|
|
|
);
|
|
|
|
if (duplicated
|
|
|
|
&& duplicated.id.startsWith(presentation.filename)
|
|
|
|
&& !presentation.id.startsWith(presentation.filename)
|
|
|
|
&& presentation?.conversion?.done === duplicated?.conversion?.done) {
|
2022-10-05 03:25:54 +08:00
|
|
|
return false; // Prioritizing propPresentations (the one with id from back-end)
|
2022-08-24 00:42:28 +08:00
|
|
|
}
|
2022-08-12 00:29:48 +08:00
|
|
|
return true;
|
2022-06-29 00:33:54 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
if (shouldUpdateState) {
|
|
|
|
this.setState({
|
2022-08-24 00:42:28 +08:00
|
|
|
presentations: _.uniqBy(presStateFiltered, 'id')
|
2022-06-29 00:33:54 +08:00
|
|
|
});
|
|
|
|
}
|
2021-09-05 06:36:48 +08:00
|
|
|
|
|
|
|
if (!isOpen && prevProps.isOpen) {
|
|
|
|
unregisterTitleView();
|
|
|
|
}
|
|
|
|
|
2021-08-24 05:04:16 +08:00
|
|
|
// Updates presentation list when chat modal opens to avoid missing presentations
|
2021-05-07 22:09:30 +08:00
|
|
|
if (isOpen && !prevProps.isOpen) {
|
2021-09-05 06:36:48 +08:00
|
|
|
registerTitleView(intl.formatMessage(intlMessages.uploadViewTitle));
|
2021-08-15 08:09:46 +08:00
|
|
|
const focusableElements =
|
|
|
|
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
|
|
|
|
const modal = document.getElementById('upload-modal');
|
|
|
|
const firstFocusableElement = modal?.querySelectorAll(focusableElements)[0];
|
|
|
|
const focusableContent = modal?.querySelectorAll(focusableElements);
|
|
|
|
const lastFocusableElement = focusableContent[focusableContent.length - 1];
|
|
|
|
|
|
|
|
firstFocusableElement.focus();
|
|
|
|
|
|
|
|
modal.addEventListener('keydown', function(e) {
|
2021-08-30 08:53:06 +08:00
|
|
|
let tab = e.key === 'Tab' || e.keyCode === TAB;
|
2021-08-15 08:09:46 +08:00
|
|
|
if (!tab) return;
|
|
|
|
if (e.shiftKey) {
|
|
|
|
if (document.activeElement === firstFocusableElement) {
|
|
|
|
lastFocusableElement.focus();
|
|
|
|
e.preventDefault();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (document.activeElement === lastFocusableElement) {
|
|
|
|
firstFocusableElement.focus();
|
|
|
|
e.preventDefault();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2021-05-07 21:52:12 +08:00
|
|
|
}
|
|
|
|
|
2020-04-02 06:54:47 +08:00
|
|
|
if (presentations.length > 0) {
|
2021-05-07 22:06:03 +08:00
|
|
|
const selected = propPresentations.filter((p) => p.isCurrent);
|
2020-04-02 06:54:47 +08:00
|
|
|
if (selected.length > 0) Session.set('selectedToBeNextCurrent', selected[0].id);
|
2020-02-26 03:29:14 +08:00
|
|
|
}
|
2022-10-08 01:36:02 +08:00
|
|
|
|
|
|
|
if (this.exportToastId) {
|
|
|
|
if (!prevProps.isOpen && isOpen) {
|
|
|
|
this.handleDismissToast(this.exportToastId);
|
|
|
|
}
|
|
|
|
|
|
|
|
toast.update(this.exportToastId, {
|
|
|
|
render: this.renderExportToast(),
|
|
|
|
});
|
|
|
|
}
|
2017-09-27 03:45:33 +08:00
|
|
|
}
|
|
|
|
|
2021-06-12 03:33:15 +08:00
|
|
|
componentWillUnmount() {
|
|
|
|
Session.set('showUploadPresentationView', false);
|
|
|
|
}
|
|
|
|
|
2022-10-08 01:36:02 +08:00
|
|
|
handleDismissToast() {
|
|
|
|
return toast.dismiss(this.toastId);
|
|
|
|
}
|
|
|
|
|
2018-12-03 14:10:50 +08:00
|
|
|
handleFiledrop(files, files2) {
|
2019-02-16 00:35:44 +08:00
|
|
|
const { fileValidMimeTypes, intl } = this.props;
|
2020-04-02 06:54:47 +08:00
|
|
|
const { toUploadCount } = this.state;
|
2021-04-28 03:45:14 +08:00
|
|
|
const validMimes = fileValidMimeTypes.map((fileValid) => fileValid.mime);
|
|
|
|
const validExtentions = fileValidMimeTypes.map((fileValid) => fileValid.extension);
|
2019-02-16 00:35:44 +08:00
|
|
|
const [accepted, rejected] = _.partition(files
|
2021-04-28 03:45:14 +08:00
|
|
|
.concat(files2), (f) => (
|
2021-06-12 03:33:15 +08:00
|
|
|
validMimes.includes(f.type) || validExtentions.includes(`.${f.name.split('.').pop()}`)
|
|
|
|
));
|
2018-12-03 14:10:50 +08:00
|
|
|
|
|
|
|
const presentationsToUpload = accepted.map((file) => {
|
2017-11-22 22:47:27 +08:00
|
|
|
const id = _.uniqueId(file.name);
|
|
|
|
|
|
|
|
return {
|
|
|
|
file,
|
2019-02-23 05:04:35 +08:00
|
|
|
isDownloadable: false, // by default new presentations are set not to be downloadable
|
2022-02-11 02:27:44 +08:00
|
|
|
isRemovable: true,
|
2017-11-22 22:47:27 +08:00
|
|
|
id,
|
|
|
|
filename: file.name,
|
|
|
|
isCurrent: false,
|
|
|
|
conversion: { done: false, error: false },
|
|
|
|
upload: { done: false, error: false, progress: 0 },
|
2022-08-24 21:31:20 +08:00
|
|
|
exportation: { error: false },
|
2017-11-22 22:47:27 +08:00
|
|
|
onProgress: (event) => {
|
|
|
|
if (!event.lengthComputable) {
|
|
|
|
this.deepMergeUpdateFileKey(id, 'upload', {
|
|
|
|
progress: 100,
|
|
|
|
done: true,
|
|
|
|
});
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.deepMergeUpdateFileKey(id, 'upload', {
|
|
|
|
progress: (event.loaded / event.total) * 100,
|
|
|
|
done: event.loaded === event.total,
|
2017-09-23 04:45:31 +08:00
|
|
|
});
|
2017-11-22 22:47:27 +08:00
|
|
|
},
|
2017-11-28 01:44:45 +08:00
|
|
|
onConversion: (conversion) => {
|
|
|
|
this.deepMergeUpdateFileKey(id, 'conversion', conversion);
|
|
|
|
},
|
|
|
|
onUpload: (upload) => {
|
|
|
|
this.deepMergeUpdateFileKey(id, 'upload', upload);
|
|
|
|
},
|
|
|
|
onDone: (newId) => {
|
|
|
|
this.updateFileKey(id, 'id', newId);
|
2017-11-22 22:47:27 +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),
|
2020-04-02 06:54:47 +08:00
|
|
|
toUploadCount: (toUploadCount + presentationsToUpload.length),
|
2018-07-19 02:47:40 +08:00
|
|
|
}), () => {
|
|
|
|
// after the state is set (files have been dropped),
|
|
|
|
// make the first of the new presentations current
|
|
|
|
if (presentationsToUpload && presentationsToUpload.length) {
|
|
|
|
this.handleCurrentChange(presentationsToUpload[0].id);
|
|
|
|
}
|
|
|
|
});
|
2018-12-03 11:40:58 +08:00
|
|
|
|
|
|
|
if (rejected.length > 0) {
|
2019-02-16 00:35:44 +08:00
|
|
|
notify(intl.formatMessage(intlMessages.rejectedError), 'error');
|
2018-12-03 11:40:58 +08:00
|
|
|
}
|
2017-04-29 02:42:32 +08:00
|
|
|
}
|
|
|
|
|
2021-04-21 01:21:12 +08:00
|
|
|
handleRemove(item, withErr = false) {
|
|
|
|
if (withErr) {
|
|
|
|
const { presentations } = this.props;
|
|
|
|
this.hasError = false;
|
|
|
|
return this.setState({
|
|
|
|
presentations,
|
|
|
|
disableActions: false,
|
|
|
|
});
|
|
|
|
}
|
2020-02-26 03:29:14 +08:00
|
|
|
|
2021-04-21 01:21:12 +08:00
|
|
|
const { presentations } = this.state;
|
|
|
|
const toRemoveIndex = presentations.indexOf(item);
|
|
|
|
return this.setState({
|
|
|
|
presentations: update(presentations, {
|
|
|
|
$splice: [[toRemoveIndex, 1]],
|
|
|
|
}),
|
|
|
|
}, () => {
|
|
|
|
const { presentations: updatedPresentations, oldCurrentId } = this.state;
|
2021-08-24 05:04:16 +08:00
|
|
|
const commands = {};
|
|
|
|
|
2021-04-21 01:21:12 +08:00
|
|
|
const currentIndex = updatedPresentations.findIndex((p) => p.isCurrent);
|
|
|
|
const actualCurrentIndex = updatedPresentations.findIndex((p) => p.id === oldCurrentId);
|
2020-02-26 03:29:14 +08:00
|
|
|
|
2021-04-21 01:21:12 +08:00
|
|
|
if (currentIndex === -1 && updatedPresentations.length > 0) {
|
|
|
|
const newCurrentIndex = actualCurrentIndex === -1 ? 0 : actualCurrentIndex;
|
|
|
|
commands[newCurrentIndex] = {
|
|
|
|
$apply: (presentation) => {
|
|
|
|
const p = presentation;
|
|
|
|
p.isCurrent = true;
|
|
|
|
return p;
|
|
|
|
},
|
|
|
|
};
|
|
|
|
}
|
2021-08-24 05:04:16 +08:00
|
|
|
|
|
|
|
const updatedCurrent = update(updatedPresentations, commands);
|
|
|
|
this.setState({ presentations: updatedCurrent });
|
2021-04-21 01:21:12 +08:00
|
|
|
});
|
2020-02-26 03:29:14 +08:00
|
|
|
}
|
|
|
|
|
2021-04-21 01:21:12 +08:00
|
|
|
handleCurrentChange(id) {
|
|
|
|
const { presentations, disableActions } = this.state;
|
2020-02-26 03:29:14 +08:00
|
|
|
|
2021-04-21 01:21:12 +08:00
|
|
|
if (disableActions) return;
|
2020-02-26 03:29:14 +08:00
|
|
|
|
2021-04-21 01:21:12 +08:00
|
|
|
const currentIndex = presentations.findIndex((p) => p.isCurrent);
|
|
|
|
const newCurrentIndex = presentations.findIndex((p) => p.id === id);
|
2020-02-26 03:29:14 +08:00
|
|
|
const commands = {};
|
2021-04-21 01:21:12 +08:00
|
|
|
|
|
|
|
// we can end up without a current presentation
|
|
|
|
if (currentIndex !== -1) {
|
|
|
|
commands[currentIndex] = {
|
|
|
|
$apply: (presentation) => {
|
|
|
|
const p = presentation;
|
|
|
|
p.isCurrent = false;
|
|
|
|
return p;
|
|
|
|
},
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
commands[newCurrentIndex] = {
|
2020-02-26 03:29:14 +08:00
|
|
|
$apply: (presentation) => {
|
|
|
|
const p = presentation;
|
2021-04-21 01:21:12 +08:00
|
|
|
p.isCurrent = true;
|
2020-02-26 03:29:14 +08:00
|
|
|
return p;
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2021-04-21 01:21:12 +08:00
|
|
|
const presentationsUpdated = update(presentations, commands);
|
|
|
|
this.setState({ presentations: presentationsUpdated });
|
2020-02-26 03:29:14 +08:00
|
|
|
}
|
|
|
|
|
2021-04-21 01:21:12 +08:00
|
|
|
deepMergeUpdateFileKey(id, key, value) {
|
|
|
|
const applyValue = (toUpdate) => update(toUpdate, { $merge: value });
|
|
|
|
this.updateFileKey(id, key, applyValue, '$apply');
|
2020-03-12 20:45:51 +08:00
|
|
|
}
|
|
|
|
|
2022-08-09 23:24:44 +08:00
|
|
|
handleConfirm() {
|
2020-02-26 03:29:14 +08:00
|
|
|
const {
|
2021-08-24 05:04:16 +08:00
|
|
|
handleSave,
|
|
|
|
selectedToBeNextCurrent,
|
2021-08-23 21:23:09 +08:00
|
|
|
presentations: propPresentations,
|
|
|
|
dispatchTogglePresentationDownloadable,
|
2020-02-26 03:29:14 +08:00
|
|
|
} = this.props;
|
|
|
|
const { disableActions, presentations } = this.state;
|
|
|
|
const presentationsToSave = presentations;
|
|
|
|
|
|
|
|
this.setState({ disableActions: true });
|
|
|
|
|
2021-08-23 21:23:09 +08:00
|
|
|
presentations.forEach(item => {
|
|
|
|
if (item.upload.done) {
|
|
|
|
const didDownloadableStateChange = propPresentations.some(
|
|
|
|
(p) => p.id === item.id && p.isDownloadable !== item.isDownloadable
|
|
|
|
);
|
|
|
|
if (didDownloadableStateChange) {
|
|
|
|
dispatchTogglePresentationDownloadable(item, item.isDownloadable);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-02-26 03:29:14 +08:00
|
|
|
if (!disableActions) {
|
2020-03-10 20:58:14 +08:00
|
|
|
Session.set('showUploadPresentationView', false);
|
2020-02-26 03:29:14 +08:00
|
|
|
return handleSave(presentationsToSave)
|
|
|
|
.then(() => {
|
2021-04-21 01:21:12 +08:00
|
|
|
const hasError = presentations.some((p) => p.upload.error || p.conversion.error);
|
2020-02-26 03:29:14 +08:00
|
|
|
if (!hasError) {
|
|
|
|
this.setState({
|
|
|
|
disableActions: false,
|
2020-04-02 06:54:47 +08:00
|
|
|
toUploadCount: 0,
|
2020-02-26 03:29:14 +08:00
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// if there's error we don't want to close the modal
|
|
|
|
this.setState({
|
|
|
|
disableActions: true,
|
|
|
|
// preventClosing: true,
|
|
|
|
}, () => {
|
|
|
|
// if the selected current has error we revert back to the old one
|
2021-04-21 01:21:12 +08:00
|
|
|
const newCurrent = presentations.find((p) => p.isCurrent);
|
2020-02-26 03:29:14 +08:00
|
|
|
if (newCurrent.upload.error || newCurrent.conversion.error) {
|
2020-03-10 23:19:14 +08:00
|
|
|
this.handleCurrentChange(selectedToBeNextCurrent);
|
2020-02-26 03:29:14 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
})
|
|
|
|
.catch((error) => {
|
|
|
|
logger.error({
|
|
|
|
logCode: 'presentationuploader_component_save_error',
|
|
|
|
extraInfo: { error },
|
|
|
|
}, 'Presentation uploader catch error on confirm');
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-03-10 20:58:14 +08:00
|
|
|
Session.set('showUploadPresentationView', false);
|
2020-02-26 03:29:14 +08:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2021-04-21 01:21:12 +08:00
|
|
|
handleDismiss() {
|
|
|
|
const { presentations } = this.state;
|
|
|
|
const { presentations: propPresentations } = this.props;
|
|
|
|
const ids = new Set(propPresentations.map((d) => d.ID));
|
|
|
|
const merged = [
|
|
|
|
...presentations.filter((d) => !ids.has(d.ID)),
|
2022-03-05 03:40:59 +08:00
|
|
|
...propPresentations,
|
2021-04-21 01:21:12 +08:00
|
|
|
];
|
|
|
|
this.setState(
|
|
|
|
{ presentations: merged },
|
|
|
|
Session.set('showUploadPresentationView', false),
|
|
|
|
);
|
2020-02-26 03:29:14 +08:00
|
|
|
}
|
|
|
|
|
2022-07-26 05:56:26 +08:00
|
|
|
getPresentationsToShow() {
|
|
|
|
const { presentations, presExporting } = this.state;
|
2020-02-26 03:29:14 +08:00
|
|
|
|
2022-07-26 05:56:26 +08:00
|
|
|
return Array.from(presExporting)
|
|
|
|
.map((id) => presentations.find((p) => p.id === id))
|
|
|
|
.filter((p) => p);
|
|
|
|
}
|
2017-09-27 03:45:33 +08:00
|
|
|
|
2022-07-20 03:36:00 +08:00
|
|
|
handleSendToChat(item) {
|
|
|
|
const { exportPresentationToChat } = this.props;
|
2017-09-27 03:45:33 +08:00
|
|
|
|
2022-07-26 05:56:26 +08:00
|
|
|
const observer = (exportation) => {
|
2022-07-20 03:36:00 +08:00
|
|
|
this.deepMergeUpdateFileKey(item.id, 'exportation', exportation);
|
2022-08-24 21:31:20 +08:00
|
|
|
if ([EXPORT_STATUSES.RUNNING,
|
|
|
|
EXPORT_STATUSES.COLLECTING,
|
|
|
|
EXPORT_STATUSES.PROCESSING].includes(exportation.status)) {
|
2022-07-26 05:56:26 +08:00
|
|
|
this.setState((prevState) => {
|
|
|
|
prevState.presExporting.add(item.id);
|
|
|
|
return {
|
|
|
|
presExporting: prevState.presExporting,
|
|
|
|
};
|
|
|
|
}, () => {
|
|
|
|
if (this.exportToastId) {
|
|
|
|
toast.update(this.exportToastId, {
|
|
|
|
render: this.renderExportToast(),
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
this.exportToastId = toast.info(this.renderExportToast(), {
|
|
|
|
hideProgressBar: true,
|
|
|
|
autoClose: false,
|
|
|
|
newestOnTop: true,
|
|
|
|
closeOnClick: true,
|
|
|
|
onClose: () => {
|
|
|
|
this.exportToastId = null;
|
|
|
|
const presToShow = this.getPresentationsToShow();
|
|
|
|
const isAnyRunning = presToShow.some(
|
|
|
|
(p) => p.exportation.status === EXPORT_STATUSES.RUNNING
|
2022-08-24 21:31:20 +08:00
|
|
|
|| p.exportation.status === EXPORT_STATUSES.COLLECTING
|
|
|
|
|| p.exportation.status === EXPORT_STATUSES.PROCESSING,
|
2022-07-26 05:56:26 +08:00
|
|
|
);
|
|
|
|
if (!isAnyRunning) {
|
|
|
|
this.setState({ presExporting: new Set() });
|
|
|
|
}
|
|
|
|
},
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2017-04-29 02:42:32 +08:00
|
|
|
};
|
|
|
|
|
2022-07-20 03:36:00 +08:00
|
|
|
exportPresentationToChat(item.id, observer);
|
|
|
|
|
|
|
|
Session.set('showUploadPresentationView', false);
|
2021-04-21 01:21:12 +08:00
|
|
|
}
|
2017-09-27 03:45:33 +08:00
|
|
|
|
2021-04-21 01:21:12 +08:00
|
|
|
updateFileKey(id, key, value, operation = '$set') {
|
|
|
|
this.setState(({ presentations }) => {
|
|
|
|
const fileIndex = presentations.findIndex((f) => f.id === id);
|
2020-07-14 21:49:00 +08:00
|
|
|
|
2021-04-21 01:21:12 +08:00
|
|
|
return fileIndex === -1 ? false : {
|
|
|
|
presentations: update(presentations, {
|
|
|
|
[fileIndex]: {
|
|
|
|
$apply: (file) => update(file, {
|
|
|
|
[key]: {
|
|
|
|
[operation]: value,
|
|
|
|
},
|
|
|
|
}),
|
2020-07-14 21:49:00 +08:00
|
|
|
},
|
2021-04-21 01:21:12 +08:00
|
|
|
}),
|
|
|
|
};
|
2019-02-21 06:20:04 +08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-01-20 03:45:24 +08:00
|
|
|
renderExtraHint() {
|
|
|
|
const {
|
|
|
|
intl,
|
|
|
|
fileSizeMax,
|
|
|
|
filePagesMax,
|
|
|
|
} = this.props;
|
|
|
|
|
|
|
|
const options = {
|
2022-10-05 03:25:54 +08:00
|
|
|
0: fileSizeMax / 1000000,
|
2022-01-20 03:45:24 +08:00
|
|
|
1: filePagesMax,
|
|
|
|
};
|
|
|
|
|
|
|
|
return (
|
2022-01-26 00:56:52 +08:00
|
|
|
<Styled.ExtraHint>
|
2022-01-20 03:45:24 +08:00
|
|
|
{intl.formatMessage(intlMessages.extraHint, options)}
|
2022-01-26 00:56:52 +08:00
|
|
|
</Styled.ExtraHint>
|
2021-04-21 01:21:12 +08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-04-29 02:42:32 +08:00
|
|
|
renderPresentationList() {
|
2017-06-07 20:28:41 +08:00
|
|
|
const { presentations } = this.state;
|
2022-08-02 21:53:40 +08:00
|
|
|
const { intl, allowDownloadable } = this.props;
|
2017-04-29 02:42:32 +08:00
|
|
|
|
2021-11-30 20:18:44 +08:00
|
|
|
let presentationsSorted = presentations;
|
|
|
|
|
|
|
|
try {
|
|
|
|
presentationsSorted = presentations
|
|
|
|
.sort((a, b) => a.uploadTimestamp - b.uploadTimestamp)
|
|
|
|
.sort((a, b) => a.filename.localeCompare(b.filename))
|
|
|
|
.sort((a, b) => b.upload.progress - a.upload.progress)
|
|
|
|
.sort((a, b) => b.conversion.done - a.conversion.done)
|
|
|
|
.sort((a, b) => {
|
|
|
|
const aUploadNotTriggeredYet = !a.upload.done && a.upload.progress === 0;
|
|
|
|
const bUploadNotTriggeredYet = !b.upload.done && b.upload.progress === 0;
|
|
|
|
return bUploadNotTriggeredYet - aUploadNotTriggeredYet;
|
|
|
|
});
|
|
|
|
} catch (error) {
|
|
|
|
logger.error({
|
|
|
|
logCode: 'presentationuploader_component_render_error',
|
|
|
|
extraInfo: { error },
|
|
|
|
}, 'Presentation uploader catch error on render presentation list');
|
|
|
|
}
|
2017-04-29 02:42:32 +08:00
|
|
|
|
|
|
|
return (
|
2021-11-08 21:57:55 +08:00
|
|
|
<Styled.FileList>
|
|
|
|
<Styled.Table>
|
2019-05-15 03:45:12 +08:00
|
|
|
<thead>
|
|
|
|
<tr>
|
2022-07-22 04:20:03 +08:00
|
|
|
<Styled.VisuallyHidden>
|
|
|
|
{intl.formatMessage(intlMessages.setAsCurrentPresentation)}
|
|
|
|
</Styled.VisuallyHidden>
|
|
|
|
<Styled.VisuallyHidden colSpan={2}>
|
2019-05-31 01:46:05 +08:00
|
|
|
{intl.formatMessage(intlMessages.filename)}
|
2021-11-08 21:57:55 +08:00
|
|
|
</Styled.VisuallyHidden>
|
|
|
|
<Styled.VisuallyHidden>
|
|
|
|
{intl.formatMessage(intlMessages.status)}
|
|
|
|
</Styled.VisuallyHidden>
|
|
|
|
<Styled.VisuallyHidden>
|
|
|
|
{intl.formatMessage(intlMessages.options)}
|
|
|
|
</Styled.VisuallyHidden>
|
2019-05-15 03:45:12 +08:00
|
|
|
</tr>
|
2022-07-22 04:20:03 +08:00
|
|
|
<Styled.Head>
|
|
|
|
<th colSpan={4}>{intl.formatMessage(intlMessages.currentLabel)}</th>
|
2022-08-02 21:53:40 +08:00
|
|
|
{
|
|
|
|
allowDownloadable ? <th>{intl.formatMessage(intlMessages.downloadLabel)}</th> : null
|
|
|
|
}
|
2022-07-22 04:20:03 +08:00
|
|
|
</Styled.Head>
|
2019-05-15 03:45:12 +08:00
|
|
|
</thead>
|
2017-05-04 00:36:16 +08:00
|
|
|
<tbody>
|
2022-08-24 00:42:28 +08:00
|
|
|
{_.uniqBy(presentationsSorted, 'id').map((item) => this.renderPresentationItem(item))}
|
2017-05-04 00:36:16 +08:00
|
|
|
</tbody>
|
2021-11-08 21:57:55 +08:00
|
|
|
</Styled.Table>
|
|
|
|
</Styled.FileList>
|
2017-04-29 02:42:32 +08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-07-20 03:36:00 +08:00
|
|
|
renderExportToast() {
|
|
|
|
const { intl } = this.props;
|
2022-07-26 05:56:26 +08:00
|
|
|
const { presExporting } = this.state;
|
2022-07-20 03:36:00 +08:00
|
|
|
|
2022-07-26 05:56:26 +08:00
|
|
|
const presToShow = this.getPresentationsToShow();
|
2022-07-20 03:36:00 +08:00
|
|
|
|
2022-07-26 05:56:26 +08:00
|
|
|
const isAllExported = presToShow.every(
|
2022-08-24 21:31:20 +08:00
|
|
|
(p) => p.exportation.status === EXPORT_STATUSES.EXPORTED,
|
2022-07-26 05:56:26 +08:00
|
|
|
);
|
|
|
|
const shouldDismiss = isAllExported && this.exportToastId;
|
|
|
|
|
|
|
|
if (shouldDismiss) {
|
2022-07-20 03:36:00 +08:00
|
|
|
this.handleDismissToast(this.exportToastId);
|
2022-07-26 05:56:26 +08:00
|
|
|
|
|
|
|
if (presExporting.size) {
|
|
|
|
this.setState({ presExporting: new Set() });
|
|
|
|
}
|
|
|
|
return;
|
2022-07-20 03:36:00 +08:00
|
|
|
}
|
|
|
|
|
2022-07-26 05:56:26 +08:00
|
|
|
const presToShowSorted = [
|
|
|
|
...presToShow.filter((p) => p.exportation.status === EXPORT_STATUSES.RUNNING),
|
2022-08-24 21:31:20 +08:00
|
|
|
...presToShow.filter((p) => p.exportation.status === EXPORT_STATUSES.COLLECTING),
|
|
|
|
...presToShow.filter((p) => p.exportation.status === EXPORT_STATUSES.PROCESSING),
|
2022-07-26 05:56:26 +08:00
|
|
|
...presToShow.filter((p) => p.exportation.status === EXPORT_STATUSES.TIMEOUT),
|
|
|
|
...presToShow.filter((p) => p.exportation.status === EXPORT_STATUSES.EXPORTED),
|
|
|
|
];
|
|
|
|
|
|
|
|
const headerLabelId = presToShowSorted.length === 1
|
|
|
|
? 'exportToastHeader'
|
|
|
|
: 'exportToastHeaderPlural';
|
2022-07-20 03:36:00 +08:00
|
|
|
|
|
|
|
return (
|
2022-11-08 22:32:55 +08:00
|
|
|
<Styled.ToastWrapper data-test="downloadPresentationToast">
|
2022-07-20 03:36:00 +08:00
|
|
|
<Styled.UploadToastHeader>
|
|
|
|
<Styled.UploadIcon iconName="download" />
|
|
|
|
<Styled.UploadToastTitle>
|
2022-07-26 05:56:26 +08:00
|
|
|
{intl.formatMessage(intlMessages[headerLabelId], { 0: presToShowSorted.length })}
|
2022-07-20 03:36:00 +08:00
|
|
|
</Styled.UploadToastTitle>
|
|
|
|
</Styled.UploadToastHeader>
|
|
|
|
<Styled.InnerToast>
|
|
|
|
<div>
|
|
|
|
<div>
|
2022-07-26 05:56:26 +08:00
|
|
|
{presToShowSorted.map((item) => this.renderToastExportItem(item))}
|
2022-07-20 03:36:00 +08:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</Styled.InnerToast>
|
|
|
|
</Styled.ToastWrapper>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
renderToastExportItem(item) {
|
2022-07-26 05:56:26 +08:00
|
|
|
const { status } = item.exportation;
|
2022-08-24 21:31:20 +08:00
|
|
|
const loading = (status === EXPORT_STATUSES.RUNNING
|
|
|
|
|| status === EXPORT_STATUSES.COLLECTING
|
|
|
|
|| status === EXPORT_STATUSES.PROCESSING);
|
2022-07-26 05:56:26 +08:00
|
|
|
const done = status === EXPORT_STATUSES.EXPORTED;
|
|
|
|
let icon;
|
|
|
|
|
|
|
|
switch (status) {
|
|
|
|
case EXPORT_STATUSES.RUNNING:
|
2022-08-24 21:31:20 +08:00
|
|
|
icon = 'blank';
|
|
|
|
break;
|
|
|
|
case EXPORT_STATUSES.COLLECTING:
|
|
|
|
icon = 'blank';
|
|
|
|
break;
|
|
|
|
case EXPORT_STATUSES.PROCESSING:
|
|
|
|
icon = 'blank';
|
2022-07-26 05:56:26 +08:00
|
|
|
break;
|
|
|
|
case EXPORT_STATUSES.EXPORTED:
|
2022-08-24 21:31:20 +08:00
|
|
|
icon = 'check';
|
2022-07-26 05:56:26 +08:00
|
|
|
break;
|
|
|
|
case EXPORT_STATUSES.TIMEOUT:
|
2022-08-24 21:31:20 +08:00
|
|
|
icon = 'warning';
|
2022-07-26 05:56:26 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2022-07-20 03:36:00 +08:00
|
|
|
return (
|
2022-08-09 23:24:44 +08:00
|
|
|
<Styled.UploadRow
|
2022-09-03 02:24:29 +08:00
|
|
|
key={item.temporaryPresentationId}
|
2022-08-09 23:24:44 +08:00
|
|
|
>
|
2022-07-26 05:56:26 +08:00
|
|
|
<Styled.FileLine>
|
|
|
|
<span>
|
|
|
|
<Icon iconName="file" />
|
|
|
|
</span>
|
|
|
|
<Styled.ToastFileName>
|
|
|
|
<span>{item.filename}</span>
|
|
|
|
</Styled.ToastFileName>
|
|
|
|
<Styled.StatusIcon>
|
|
|
|
<Styled.ToastItemIcon
|
|
|
|
loading={loading}
|
|
|
|
done={done}
|
|
|
|
iconName={icon}
|
|
|
|
color="#0F70D7"
|
|
|
|
/>
|
|
|
|
</Styled.StatusIcon>
|
|
|
|
</Styled.FileLine>
|
|
|
|
<Styled.StatusInfo>
|
|
|
|
<Styled.StatusInfoSpan>
|
|
|
|
{this.renderExportationStatus(item)}
|
|
|
|
</Styled.StatusInfoSpan>
|
|
|
|
</Styled.StatusInfo>
|
|
|
|
</Styled.UploadRow>
|
2022-07-20 03:36:00 +08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-07-26 05:56:26 +08:00
|
|
|
renderExportationStatus(item) {
|
|
|
|
const { intl } = this.props;
|
|
|
|
|
|
|
|
switch (item.exportation.status) {
|
|
|
|
case EXPORT_STATUSES.RUNNING:
|
|
|
|
return intl.formatMessage(intlMessages.sending);
|
2022-08-24 21:31:20 +08:00
|
|
|
case EXPORT_STATUSES.COLLECTING:
|
|
|
|
return intl.formatMessage(intlMessages.collecting,
|
|
|
|
{ 0: item.exportation.pageNumber, 1: item.exportation.totalPages });
|
|
|
|
case EXPORT_STATUSES.PROCESSING:
|
|
|
|
return intl.formatMessage(intlMessages.processing,
|
|
|
|
{ 0: item.exportation.pageNumber, 1: item.exportation.totalPages });
|
2022-07-26 05:56:26 +08:00
|
|
|
case EXPORT_STATUSES.TIMEOUT:
|
|
|
|
return intl.formatMessage(intlMessages.exportingTimeout);
|
|
|
|
case EXPORT_STATUSES.EXPORTED:
|
|
|
|
return intl.formatMessage(intlMessages.sent);
|
|
|
|
default:
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-29 02:42:32 +08:00
|
|
|
renderPresentationItem(item) {
|
2021-09-01 19:48:46 +08:00
|
|
|
const { disableActions } = this.state;
|
2020-02-26 03:29:14 +08:00
|
|
|
const {
|
2021-08-24 05:04:16 +08:00
|
|
|
intl,
|
|
|
|
selectedToBeNextCurrent,
|
2021-09-18 04:55:31 +08:00
|
|
|
allowDownloadable
|
2020-02-26 03:29:14 +08:00
|
|
|
} = this.props;
|
2017-05-04 00:36:16 +08:00
|
|
|
|
2020-03-10 23:19:14 +08:00
|
|
|
const isActualCurrent = selectedToBeNextCurrent ? item.id === selectedToBeNextCurrent : item.isCurrent;
|
2017-11-28 20:26:00 +08:00
|
|
|
const isUploading = !item.upload.done && item.upload.progress > 0;
|
|
|
|
const isConverting = !item.conversion.done && item.upload.done;
|
|
|
|
const hasError = item.conversion.error || item.upload.error;
|
|
|
|
const isProcessing = (isUploading || isConverting) && !hasError;
|
|
|
|
|
2021-09-01 19:48:46 +08:00
|
|
|
if (hasError) {
|
2020-03-12 21:56:12 +08:00
|
|
|
this.hasError = true;
|
2020-02-26 03:29:14 +08:00
|
|
|
}
|
|
|
|
|
2022-07-20 03:36:00 +08:00
|
|
|
const { animations } = Settings.application;
|
2017-05-04 04:51:17 +08:00
|
|
|
|
2022-07-26 05:56:26 +08:00
|
|
|
const { isRemovable, exportation: { status } } = item;
|
2019-05-09 05:47:00 +08:00
|
|
|
|
2022-07-26 05:56:26 +08:00
|
|
|
const isExporting = status === 'RUNNING';
|
2020-02-26 03:29:14 +08:00
|
|
|
|
2022-07-20 03:36:00 +08:00
|
|
|
const shouldDisableExportButton = isExporting
|
|
|
|
|| !item.conversion.done
|
|
|
|
|| hasError
|
|
|
|
|| disableActions;
|
|
|
|
|
|
|
|
const formattedDownloadLabel = isExporting
|
|
|
|
? intl.formatMessage(intlMessages.exporting)
|
|
|
|
: intl.formatMessage(intlMessages.export);
|
2020-02-26 03:29:14 +08:00
|
|
|
|
2022-07-20 03:36:00 +08:00
|
|
|
const formattedDownloadAriaLabel = `${formattedDownloadLabel} ${item.filename}`;
|
2022-02-03 22:37:14 +08:00
|
|
|
|
2017-04-29 02:42:32 +08:00
|
|
|
return (
|
2021-11-08 21:57:55 +08:00
|
|
|
<Styled.PresentationItem
|
2017-05-04 00:36:16 +08:00
|
|
|
key={item.id}
|
2021-11-08 21:57:55 +08:00
|
|
|
isNew={item.id.indexOf(item.filename) !== -1}
|
|
|
|
uploading={isUploading}
|
|
|
|
converting={isConverting}
|
|
|
|
error={hasError}
|
|
|
|
animated={isProcessing}
|
|
|
|
animations={animations}
|
2017-04-29 02:42:32 +08:00
|
|
|
>
|
2022-07-20 03:36:00 +08:00
|
|
|
<Styled.SetCurrentAction>
|
|
|
|
<Checkbox
|
|
|
|
animations={animations}
|
|
|
|
ariaLabel={`${intl.formatMessage(intlMessages.setAsCurrentPresentation)} ${item.filename}`}
|
|
|
|
checked={item.isCurrent}
|
|
|
|
keyValue={item.id}
|
|
|
|
onChange={() => this.handleCurrentChange(item.id)}
|
|
|
|
disabled={disableActions || hasError}
|
|
|
|
/>
|
|
|
|
</Styled.SetCurrentAction>
|
|
|
|
<Styled.TableItemName colSpan={!isActualCurrent ? 2 : 0}>
|
|
|
|
<span>{item.filename}</span>
|
|
|
|
</Styled.TableItemName>
|
2017-12-05 00:10:37 +08:00
|
|
|
{
|
2018-12-06 01:42:31 +08:00
|
|
|
isActualCurrent
|
|
|
|
? (
|
2021-11-08 21:57:55 +08:00
|
|
|
<Styled.TableItemCurrent>
|
|
|
|
<Styled.CurrentLabel>
|
2019-02-16 00:35:44 +08:00
|
|
|
{intl.formatMessage(intlMessages.current)}
|
2021-11-08 21:57:55 +08:00
|
|
|
</Styled.CurrentLabel>
|
|
|
|
</Styled.TableItemCurrent>
|
2018-12-06 01:42:31 +08:00
|
|
|
)
|
|
|
|
: null
|
2017-12-05 00:10:37 +08:00
|
|
|
}
|
2021-11-08 21:57:55 +08:00
|
|
|
<Styled.TableItemStatus colSpan={hasError ? 2 : 0}>
|
2022-07-22 21:06:32 +08:00
|
|
|
{this.props.renderPresentationItemStatus(item, intl)}
|
2021-11-08 21:57:55 +08:00
|
|
|
</Styled.TableItemStatus>
|
2019-08-30 20:48:59 +08:00
|
|
|
{hasError ? null : (
|
2021-11-08 21:57:55 +08:00
|
|
|
<Styled.TableItemActions notDownloadable={!allowDownloadable}>
|
2021-09-18 04:55:31 +08:00
|
|
|
{allowDownloadable ? (
|
2021-11-08 21:57:55 +08:00
|
|
|
<Styled.DownloadButton
|
2022-07-20 03:36:00 +08:00
|
|
|
disabled={shouldDisableExportButton}
|
|
|
|
label={intl.formatMessage(intlMessages.export)}
|
|
|
|
data-test="exportPresentationToPublicChat"
|
|
|
|
aria-label={formattedDownloadAriaLabel}
|
2021-09-18 04:55:31 +08:00
|
|
|
size="sm"
|
2022-07-20 03:36:00 +08:00
|
|
|
color="primary"
|
|
|
|
onClick={() => this.handleSendToChat(item)}
|
2021-11-08 21:57:55 +08:00
|
|
|
animations={animations}
|
2021-09-18 04:55:31 +08:00
|
|
|
/>
|
2022-07-20 03:36:00 +08:00
|
|
|
) : null}
|
2022-02-03 22:37:14 +08:00
|
|
|
{isRemovable ? (
|
2022-02-03 23:03:26 +08:00
|
|
|
<Styled.RemoveButton
|
|
|
|
disabled={disableActions}
|
|
|
|
label={intl.formatMessage(intlMessages.removePresentation)}
|
|
|
|
data-test="removePresentation"
|
|
|
|
aria-label={`${intl.formatMessage(intlMessages.removePresentation)} ${item.filename}`}
|
|
|
|
size="sm"
|
|
|
|
icon="delete"
|
|
|
|
hideLabel
|
|
|
|
onClick={() => this.handleRemove(item)}
|
|
|
|
animations={animations}
|
2022-02-03 22:37:14 +08:00
|
|
|
/>
|
2022-02-03 23:03:26 +08:00
|
|
|
) : null
|
2022-02-03 22:37:14 +08:00
|
|
|
}
|
2021-11-08 21:57:55 +08:00
|
|
|
</Styled.TableItemActions>
|
2017-11-28 20:26:00 +08:00
|
|
|
)}
|
2021-11-08 21:57:55 +08:00
|
|
|
</Styled.PresentationItem>
|
2017-04-29 02:42:32 +08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-02-26 03:29:14 +08:00
|
|
|
renderDropzone() {
|
2018-12-03 14:10:50 +08:00
|
|
|
const {
|
|
|
|
intl,
|
2020-02-26 03:29:14 +08:00
|
|
|
fileValidMimeTypes,
|
2018-12-03 14:10:50 +08:00
|
|
|
} = this.props;
|
|
|
|
|
|
|
|
const { disableActions } = this.state;
|
|
|
|
|
2020-03-12 21:56:12 +08:00
|
|
|
if (disableActions && !this.hasError) return null;
|
2018-12-03 14:10:50 +08:00
|
|
|
|
2020-03-12 21:56:12 +08:00
|
|
|
return this.hasError ? (
|
2020-02-26 03:29:14 +08:00
|
|
|
<div>
|
|
|
|
<Button
|
|
|
|
color="danger"
|
|
|
|
onClick={() => this.handleRemove(null, true)}
|
|
|
|
label={intl.formatMessage(intlMessages.clearErrors)}
|
|
|
|
aria-describedby="clearErrorDesc"
|
|
|
|
/>
|
|
|
|
<div id="clearErrorDesc" style={{ display: 'none' }}>
|
|
|
|
{intl.formatMessage(intlMessages.clearErrorsDesc)}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
) : (
|
|
|
|
// Until the Dropzone package has fixed the mime type hover validation, the rejectClassName
|
|
|
|
// prop is being remove to prevent the error styles from being applied to valid file types.
|
|
|
|
// Error handling is being done in the onDrop prop.
|
2021-11-08 21:57:55 +08:00
|
|
|
<Styled.UploaderDropzone
|
2018-12-03 14:10:50 +08:00
|
|
|
multiple
|
2021-11-08 21:57:55 +08:00
|
|
|
activeClassName={"dropzoneActive"}
|
2021-04-21 01:21:12 +08:00
|
|
|
accept={fileValidMimeTypes.map((fileValid) => fileValid.extension)}
|
2020-02-26 03:29:14 +08:00
|
|
|
disablepreview="true"
|
2018-12-03 14:10:50 +08:00
|
|
|
onDrop={this.handleFiledrop}
|
|
|
|
>
|
2021-11-08 21:57:55 +08:00
|
|
|
<Styled.DropzoneIcon iconName="upload" />
|
|
|
|
<Styled.DropzoneMessage>
|
2020-02-26 03:29:14 +08:00
|
|
|
{intl.formatMessage(intlMessages.dropzoneLabel)}
|
2019-08-30 20:48:59 +08:00
|
|
|
|
2021-11-08 21:57:55 +08:00
|
|
|
<Styled.DropzoneLink>
|
2020-02-26 03:29:14 +08:00
|
|
|
{intl.formatMessage(intlMessages.browseFilesLabel)}
|
2021-11-08 21:57:55 +08:00
|
|
|
</Styled.DropzoneLink>
|
|
|
|
</Styled.DropzoneMessage>
|
|
|
|
</Styled.UploaderDropzone>
|
2018-12-03 14:10:50 +08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-06-25 00:47:17 +08:00
|
|
|
renderExternalUpload() {
|
|
|
|
const { externalUploadData, intl } = this.props;
|
|
|
|
|
|
|
|
const { uploadExternalDescription, uploadExternalUrl } = externalUploadData;
|
|
|
|
|
|
|
|
if (!uploadExternalDescription || !uploadExternalUrl) return null;
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Styled.ExternalUpload>
|
|
|
|
<div>
|
|
|
|
<Styled.ExternalUploadTitle>
|
|
|
|
{intl.formatMessage(intlMessages.externalUploadTitle)}
|
|
|
|
</Styled.ExternalUploadTitle>
|
|
|
|
|
|
|
|
<p>{uploadExternalDescription}</p>
|
|
|
|
</div>
|
|
|
|
<Styled.ExternalUploadButton
|
|
|
|
color="default"
|
|
|
|
onClick={() => window.open(`${uploadExternalUrl}`)}
|
|
|
|
label={intl.formatMessage(intlMessages.externalUploadLabel)}
|
|
|
|
aria-describedby={intl.formatMessage(intlMessages.externalUploadLabel)}
|
2022-09-03 03:07:21 +08:00
|
|
|
/>
|
2022-06-25 00:47:17 +08:00
|
|
|
</Styled.ExternalUpload>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2020-02-26 03:29:14 +08:00
|
|
|
renderPicDropzone() {
|
2017-05-04 00:36:16 +08:00
|
|
|
const {
|
|
|
|
intl,
|
|
|
|
} = this.props;
|
2017-04-29 02:42:32 +08:00
|
|
|
|
2017-05-06 04:17:38 +08:00
|
|
|
const { disableActions } = this.state;
|
|
|
|
|
2020-03-12 21:56:12 +08:00
|
|
|
if (disableActions && !this.hasError) return null;
|
2017-05-04 04:51:17 +08:00
|
|
|
|
2020-03-12 21:56:12 +08:00
|
|
|
return this.hasError ? (
|
2020-02-26 03:29:14 +08:00
|
|
|
<div>
|
|
|
|
<Button
|
|
|
|
color="danger"
|
|
|
|
onClick={() => this.handleRemove(null, true)}
|
|
|
|
label={intl.formatMessage(intlMessages.clearErrors)}
|
|
|
|
aria-describedby="clearErrorDesc"
|
|
|
|
/>
|
|
|
|
<div id="clearErrorDesc" style={{ display: 'none' }}>
|
|
|
|
{intl.formatMessage(intlMessages.clearErrorsDesc)}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
) : (
|
2021-11-08 21:57:55 +08:00
|
|
|
<Styled.UploaderDropzone
|
2017-09-08 02:18:14 +08:00
|
|
|
multiple
|
2020-02-26 03:29:14 +08:00
|
|
|
accept="image/*"
|
2018-12-06 01:42:31 +08:00
|
|
|
disablepreview="true"
|
2020-07-18 03:13:47 +08:00
|
|
|
data-test="fileUploadDropZone"
|
2017-04-29 02:42:32 +08:00
|
|
|
onDrop={this.handleFiledrop}
|
|
|
|
>
|
2021-11-08 21:57:55 +08:00
|
|
|
<Styled.DropzoneIcon iconName="upload" />
|
|
|
|
<Styled.DropzoneMessage>
|
2020-02-26 03:29:14 +08:00
|
|
|
{intl.formatMessage(intlMessages.dropzoneImagesLabel)}
|
2019-08-30 20:48:59 +08:00
|
|
|
|
2021-11-08 21:57:55 +08:00
|
|
|
<Styled.DropzoneLink>
|
2020-02-26 03:29:14 +08:00
|
|
|
{intl.formatMessage(intlMessages.browseImagesLabel)}
|
2021-11-08 21:57:55 +08:00
|
|
|
</Styled.DropzoneLink>
|
|
|
|
</Styled.DropzoneMessage>
|
|
|
|
</Styled.UploaderDropzone>
|
2017-04-29 02:42:32 +08:00
|
|
|
);
|
|
|
|
}
|
2017-06-07 20:28:41 +08:00
|
|
|
|
|
|
|
render() {
|
2019-05-29 05:18:49 +08:00
|
|
|
const {
|
2022-01-20 03:45:24 +08:00
|
|
|
isOpen,
|
|
|
|
isPresenter,
|
|
|
|
intl,
|
|
|
|
fileUploadConstraintsHint,
|
2020-02-26 03:29:14 +08:00
|
|
|
} = this.props;
|
2020-03-10 20:58:14 +08:00
|
|
|
if (!isPresenter) return null;
|
2020-02-26 03:29:14 +08:00
|
|
|
const { presentations, disableActions } = this.state;
|
|
|
|
|
|
|
|
let hasNewUpload = false;
|
2019-05-25 03:51:50 +08:00
|
|
|
|
2022-04-08 01:06:51 +08:00
|
|
|
presentations.forEach((item) => {
|
2020-02-26 03:29:14 +08:00
|
|
|
if (item.id.indexOf(item.filename) !== -1 && item.upload.progress === 0) hasNewUpload = true;
|
2019-05-25 03:51:50 +08:00
|
|
|
});
|
|
|
|
|
2022-08-03 04:25:15 +08:00
|
|
|
return (<>
|
2022-09-23 23:24:39 +08:00
|
|
|
<PresentationUploaderToast intl={intl} />
|
2022-08-03 04:25:15 +08:00
|
|
|
{isOpen ? (
|
|
|
|
<Styled.UploaderModal id="upload-modal">
|
|
|
|
<Styled.ModalInner>
|
|
|
|
<Styled.ModalHeader>
|
2022-11-11 02:09:21 +08:00
|
|
|
<Styled.Title>{intl.formatMessage(intlMessages.title)}</Styled.Title>
|
2022-08-03 04:25:15 +08:00
|
|
|
<Styled.ActionWrapper>
|
|
|
|
<Styled.DismissButton
|
|
|
|
color="secondary"
|
|
|
|
onClick={this.handleDismiss}
|
|
|
|
label={intl.formatMessage(intlMessages.dismissLabel)}
|
|
|
|
aria-describedby={intl.formatMessage(intlMessages.dismissDesc)}
|
|
|
|
/>
|
|
|
|
<Styled.ConfirmButton
|
|
|
|
data-test="confirmManagePresentation"
|
|
|
|
color="primary"
|
2022-08-09 23:24:44 +08:00
|
|
|
onClick={() => this.handleConfirm()}
|
2022-08-03 04:25:15 +08:00
|
|
|
disabled={disableActions}
|
|
|
|
label={hasNewUpload
|
|
|
|
? intl.formatMessage(intlMessages.uploadLabel)
|
|
|
|
: intl.formatMessage(intlMessages.confirmLabel)}
|
|
|
|
/>
|
|
|
|
</Styled.ActionWrapper>
|
|
|
|
</Styled.ModalHeader>
|
|
|
|
|
|
|
|
<Styled.ModalHint>
|
|
|
|
{`${intl.formatMessage(intlMessages.message)}`}
|
|
|
|
{fileUploadConstraintsHint ? this.renderExtraHint() : null}
|
|
|
|
</Styled.ModalHint>
|
2022-08-09 23:24:44 +08:00
|
|
|
{this.renderPresentationList()}
|
2022-08-03 22:12:55 +08:00
|
|
|
<Styled.ExportHint>
|
|
|
|
{intl.formatMessage(intlMessages.exportHint)}
|
|
|
|
</Styled.ExportHint>
|
2022-08-03 04:25:15 +08:00
|
|
|
{isMobile ? this.renderPicDropzone() : null}
|
|
|
|
{this.renderDropzone()}
|
2022-09-03 03:07:21 +08:00
|
|
|
{this.renderExternalUpload()}
|
2022-08-03 04:25:15 +08:00
|
|
|
</Styled.ModalInner>
|
|
|
|
</Styled.UploaderModal>
|
|
|
|
) : null
|
|
|
|
}</>)
|
2017-06-07 20:28:41 +08:00
|
|
|
}
|
|
|
|
}
|
2017-04-29 02:42:32 +08:00
|
|
|
|
2017-09-23 04:45:31 +08:00
|
|
|
PresentationUploader.propTypes = propTypes;
|
|
|
|
PresentationUploader.defaultProps = defaultProps;
|
|
|
|
|
2020-03-10 20:58:14 +08:00
|
|
|
export default injectIntl(PresentationUploader);
|