[apply-toast-shared-notes] - Removed some of the comments and separated toast controller
This commit is contained in:
parent
93b51ded53
commit
246153e62c
@ -0,0 +1,320 @@
|
||||
import Presentations from '/imports/api/presentations';
|
||||
import React from 'react';
|
||||
import { useTracker } from 'meteor/react-meteor-data';
|
||||
import Icon from '/imports/ui/components/common/icon/component';
|
||||
import { makeCall } from '/imports/ui/services/api';
|
||||
import Styled from '/imports/ui/components/presentation/presentation-uploader/styles';
|
||||
import { toast } from 'react-toastify';
|
||||
import { defineMessages } from 'react-intl';
|
||||
import _ from 'lodash';
|
||||
import { UploadingPresentations } from '/imports/api/presentations';
|
||||
|
||||
const intlMessages = defineMessages({
|
||||
|
||||
item: {
|
||||
id: 'app.presentationUploder.item',
|
||||
description: 'single item label',
|
||||
},
|
||||
itemPlural: {
|
||||
id: 'app.presentationUploder.itemPlural',
|
||||
description: 'plural item label',
|
||||
},
|
||||
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',
|
||||
},
|
||||
GENERATING_THUMBNAIL: {
|
||||
id: 'app.presentationUploder.conversion.generatingThumbnail',
|
||||
description: 'indicatess that it is generating thumbnails',
|
||||
},
|
||||
GENERATING_SVGIMAGES: {
|
||||
id: 'app.presentationUploder.conversion.generatingSvg',
|
||||
description: 'warns that it is generating svg images',
|
||||
},
|
||||
GENERATED_SLIDE: {
|
||||
id: 'app.presentationUploder.conversion.generatedSlides',
|
||||
description: 'warns that were slides generated',
|
||||
},
|
||||
PAGE_COUNT_EXCEEDED: {
|
||||
id: 'app.presentationUploder.conversion.pageCountExceeded',
|
||||
description: 'warns the user that the conversion failed because of the page count',
|
||||
},
|
||||
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',
|
||||
},
|
||||
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',
|
||||
},
|
||||
fileToUpload: {
|
||||
id: 'app.presentationUploder.fileToUpload',
|
||||
description: 'message used in the file selected for upload',
|
||||
},
|
||||
uploadProcess: {
|
||||
id: 'app.presentationUploder.upload.progress',
|
||||
description: 'message that indicates the percentage of the upload',
|
||||
},
|
||||
badConnectionError: {
|
||||
id: 'app.presentationUploder.connectionClosedError',
|
||||
description: 'message indicating that the connection was closed',
|
||||
},
|
||||
conversionProcessingSlides: {
|
||||
id: 'app.presentationUploder.conversion.conversionProcessingSlides',
|
||||
description: 'indicates how many slides were converted',
|
||||
},
|
||||
genericError: {
|
||||
id: 'app.presentationUploder.genericError',
|
||||
description: 'generic error while uploading/converting',
|
||||
},
|
||||
genericConversionStatus: {
|
||||
id: 'app.presentationUploder.conversion.genericConversionStatus',
|
||||
description: 'indicates that file is being converted',
|
||||
},
|
||||
});
|
||||
|
||||
function renderPresentationItemStatus(item, intl) {
|
||||
if ((("progress" in item) && item.progress === 0) || (("conversion" in item && !item.conversion.done && !item.conversion.error))) {
|
||||
return intl.formatMessage(intlMessages.fileToUpload);
|
||||
}
|
||||
|
||||
if (("progress" in item) && item.progress < 100 && !("conversion" in item)) {
|
||||
return intl.formatMessage(intlMessages.uploadProcess, {
|
||||
0: Math.floor(item.progress).toString(),
|
||||
});
|
||||
}
|
||||
|
||||
const constraint = {};
|
||||
|
||||
if (("upload" in item) && (item.upload.done && item.upload.error)) {
|
||||
if (item.conversion.status === 'FILE_TOO_LARGE') {
|
||||
constraint['0'] = ((item.conversion.maxFileSize) / 1000 / 1000).toFixed(2);
|
||||
}
|
||||
|
||||
if (item.progress < 100) {
|
||||
const errorMessage = intlMessages.badConnectionError;
|
||||
return intl.formatMessage(errorMessage);
|
||||
}
|
||||
|
||||
const errorMessage = intlMessages[item.upload.status] || intlMessages.genericError;
|
||||
return intl.formatMessage(errorMessage, constraint);
|
||||
}
|
||||
|
||||
if (("conversion" in item) && (!item.conversion.done && item.conversion.error)) {
|
||||
const errorMessage = intlMessages[item.conversion.status] || intlMessages.genericConversionStatus;
|
||||
|
||||
switch (item.conversion.status) {
|
||||
case 'PAGE_COUNT_EXCEEDED':
|
||||
constraint['0'] = item.conversion.maxNumberPages;
|
||||
break;
|
||||
case 'PDF_HAS_BIG_PAGE':
|
||||
constraint['0'] = (item.conversion.bigPageSize / 1000 / 1000).toFixed(2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return intl.formatMessage(errorMessage, constraint);
|
||||
}
|
||||
|
||||
if ((("conversion" in item) && (!item.conversion.done && !item.conversion.error)) || (("progress" in item) && item.progress == 100)) {
|
||||
let conversionStatusMessage
|
||||
if ("conversion" in item) {
|
||||
if (item.conversion.pagesCompleted < item.conversion.numPages) {
|
||||
return intl.formatMessage(intlMessages.conversionProcessingSlides, {
|
||||
0: item.conversion.pagesCompleted,
|
||||
1: item.conversion.numPages,
|
||||
});
|
||||
}
|
||||
|
||||
conversionStatusMessage = intlMessages[item.conversion.status]
|
||||
|| intlMessages.genericConversionStatus;
|
||||
} else {
|
||||
conversionStatusMessage = intlMessages.genericConversionStatus;
|
||||
}
|
||||
return intl.formatMessage(conversionStatusMessage);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function renderToastItem(item, intl) {
|
||||
|
||||
const isUploading = ("progress" in item) && item.progress <= 100;
|
||||
const isConverting = ("conversion" in item) && !item.conversion.done;
|
||||
const hasError = ((("conversion" in item) && item.conversion.error) || (("upload" in item) && item.upload.error));
|
||||
const isProcessing = (isUploading || isConverting) && !hasError;
|
||||
|
||||
let icon = isProcessing ? 'blank' : 'check';
|
||||
if (hasError) icon = 'circle_close';
|
||||
|
||||
return (
|
||||
<Styled.UploadRow
|
||||
key={item.tmpPresId}
|
||||
onClick={() => {
|
||||
if (hasError || isProcessing) Session.set('showUploadPresentationView', true);
|
||||
}}
|
||||
>
|
||||
<Styled.FileLine>
|
||||
<span>
|
||||
<Icon iconName="file" />
|
||||
</span>
|
||||
<Styled.ToastFileName>
|
||||
<span>{item.filename || item.name}</span>
|
||||
</Styled.ToastFileName>
|
||||
<Styled.StatusIcon>
|
||||
<Styled.ToastItemIcon
|
||||
done={!isProcessing && !hasError}
|
||||
error={hasError}
|
||||
loading={ isProcessing }
|
||||
iconName={icon}
|
||||
/>
|
||||
</Styled.StatusIcon>
|
||||
</Styled.FileLine>
|
||||
<Styled.StatusInfo>
|
||||
<Styled.StatusInfoSpan data-test="presentationStatusInfo" styles={hasError ? 'error' : 'info'}>
|
||||
{renderPresentationItemStatus(item, intl)}
|
||||
</Styled.StatusInfoSpan>
|
||||
</Styled.StatusInfo>
|
||||
</Styled.UploadRow>
|
||||
);
|
||||
}
|
||||
|
||||
const renderToastList = (presentations, intl) => {
|
||||
|
||||
let converted = 0;
|
||||
|
||||
let presentationsSorted = presentations
|
||||
.sort((a, b) => a.uploadTimestamp - b.uploadTimestamp)
|
||||
.sort((a, b) => {
|
||||
const presADone = a.conversion ? a.conversion.done : false;
|
||||
const presBDone = b.conversion ? b.conversion.done : false;
|
||||
|
||||
return presADone - presBDone
|
||||
});
|
||||
|
||||
presentationsSorted
|
||||
.forEach((p) => {
|
||||
const presDone = p.conversion ? p.conversion.done : false;
|
||||
if (presDone) converted += 1;
|
||||
return p;
|
||||
});
|
||||
|
||||
let toastHeading = '';
|
||||
const itemLabel = presentationsSorted.length > 1
|
||||
? intl.formatMessage(intlMessages.itemPlural)
|
||||
: intl.formatMessage(intlMessages.item);
|
||||
|
||||
if (converted === 0) {
|
||||
toastHeading = intl.formatMessage(intlMessages.uploading, {
|
||||
0: presentationsSorted.length,
|
||||
1: itemLabel,
|
||||
});
|
||||
}
|
||||
|
||||
if (converted > 0 && converted !== presentationsSorted.length) {
|
||||
toastHeading = intl.formatMessage(intlMessages.uploadStatus, {
|
||||
0: converted,
|
||||
1: presentationsSorted.length,
|
||||
});
|
||||
}
|
||||
|
||||
if (converted === presentationsSorted.length) {
|
||||
toastHeading = intl.formatMessage(intlMessages.completed, {
|
||||
0: converted,
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<Styled.ToastWrapper>
|
||||
<Styled.UploadToastHeader>
|
||||
<Styled.UploadIcon iconName="upload" />
|
||||
<Styled.UploadToastTitle>{toastHeading}</Styled.UploadToastTitle>
|
||||
</Styled.UploadToastHeader>
|
||||
<Styled.InnerToast>
|
||||
<div>
|
||||
<div>
|
||||
{presentationsSorted.map((item) => renderToastItem(item, intl))}
|
||||
</div>
|
||||
</div>
|
||||
</Styled.InnerToast>
|
||||
</Styled.ToastWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function handleDismissToast(toastId) {
|
||||
return toast.dismiss(toastId);
|
||||
}
|
||||
|
||||
export const ToastController = ({ intl }) => {
|
||||
|
||||
useTracker(() => {
|
||||
|
||||
const presentationsRenderedFalseAndConversionFalse = Presentations.find({ $or: [{renderedInToast: false}, {"conversion.done": false}] }).fetch();
|
||||
const convertingPresentations = presentationsRenderedFalseAndConversionFalse.filter(p => !p.renderedInToast )
|
||||
let tmpIdconvertingPresentations = presentationsRenderedFalseAndConversionFalse.filter(p => !p.conversion.done)
|
||||
.map(p => p.tmpPresId)
|
||||
// tmpIdconvertingPresentations = UploadingPresentations.find({}).fetch().filter(p => tmpIdconvertingPresentations.includes(p.tmpPresId))
|
||||
// .map(p => p.tmpPresId)
|
||||
UploadingPresentations.find({}).fetch().filter(p => tmpIdconvertingPresentations.includes(p.tmpPresId))
|
||||
.map(p => UploadingPresentations.remove({tmpPresId: p.tmpPresId}));
|
||||
// Remove all presentations from the uploading collection if they are already
|
||||
// converting.
|
||||
// UploadingPresentations.remove({tmpPresId: {$all: tmpIdconvertingPresentations}});
|
||||
const uploadingPresentations = UploadingPresentations.find().fetch();
|
||||
let presentationsToConvert = convertingPresentations.concat(uploadingPresentations);
|
||||
|
||||
let activeToast = Session.get("presentationUploaderToastId");
|
||||
const showToast = presentationsToConvert.length > 0;
|
||||
if (showToast && !activeToast) {
|
||||
activeToast = toast.info(() => renderToastList(presentationsToConvert, intl), {
|
||||
hideProgressBar: true,
|
||||
autoClose: false,
|
||||
newestOnTop: true,
|
||||
closeOnClick: true,
|
||||
onClose: () => {
|
||||
Session.set("presentationUploaderToastId", null);
|
||||
presentationsToConvert = [];
|
||||
},
|
||||
});
|
||||
Session.set("presentationUploaderToastId", activeToast);
|
||||
} else if (!showToast && activeToast) {
|
||||
handleDismissToast(activeToast);
|
||||
Session.set("presentationUploaderToastId", null);
|
||||
} else {
|
||||
toast.update(activeToast, {
|
||||
render: renderToastList(presentationsToConvert, intl),
|
||||
});
|
||||
}
|
||||
|
||||
let tmpPresIdListToSetAsRendered = presentationsToConvert.filter(p =>
|
||||
("conversion" in p && (p.conversion.done || p.conversion.error)))
|
||||
|
||||
tmpPresIdListToSetAsRendered = tmpPresIdListToSetAsRendered.map(p => p.tmpPresId);
|
||||
|
||||
makeCall('setPresentationRenderedInToast', tmpPresIdListToSetAsRendered);
|
||||
}, [])
|
||||
return null;
|
||||
}
|
||||
|
||||
export default {
|
||||
handleDismissToast,
|
||||
renderPresentationItemStatus,
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import { ToastController } from './service';
|
||||
import { ToastController } from '/imports/ui/components/presentation/presentation-toast/presentation-toast-controller';
|
||||
import { TAB } from '/imports/utils/keyCodes';
|
||||
import deviceInfo from '/imports/utils/deviceInfo';
|
||||
import Button from '/imports/ui/components/common/button/component';
|
||||
@ -385,32 +385,12 @@ class PresentationUploader extends Component {
|
||||
const selected = propPresentations.filter((p) => p.isCurrent);
|
||||
if (selected.length > 0) Session.set('selectedToBeNextCurrent', selected[0].id);
|
||||
}
|
||||
|
||||
const toastId = Session.get("presentationUploaderToastId");
|
||||
// toast.update(this.toastId, {
|
||||
// render: this.renderToastList(),
|
||||
// });
|
||||
// }
|
||||
|
||||
// if (this.exportToastId) {
|
||||
// if (!prevProps.isOpen && isOpen) {
|
||||
// this.handleDismissToast(this.exportToastId);
|
||||
// }
|
||||
//
|
||||
// toast.update(this.exportToastId, {
|
||||
// render: this.renderExportToast(),
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
Session.set('showUploadPresentationView', false);
|
||||
}
|
||||
|
||||
// handleDismissToast(toastId) {
|
||||
// return toast.dismiss(toastId);
|
||||
// }
|
||||
|
||||
handleFiledrop(files, files2) {
|
||||
const { fileValidMimeTypes, intl } = this.props;
|
||||
const { toUploadCount } = this.state;
|
||||
@ -553,7 +533,7 @@ class PresentationUploader extends Component {
|
||||
this.updateFileKey(id, key, applyValue, '$apply');
|
||||
}
|
||||
|
||||
handleConfirm(hasNewUpload) {
|
||||
handleConfirm() {
|
||||
const {
|
||||
handleSave,
|
||||
selectedToBeNextCurrent,
|
||||
@ -576,18 +556,6 @@ class PresentationUploader extends Component {
|
||||
}
|
||||
});
|
||||
|
||||
// if (hasNewUpload) {
|
||||
// this.toastId = toast.info(this.renderToastList(), {
|
||||
// hideProgressBar: true,
|
||||
// autoClose: false,
|
||||
// newestOnTop: true,
|
||||
// closeOnClick: true,
|
||||
// onClose: () => {
|
||||
// this.toastId = null;
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
|
||||
if (!disableActions) {
|
||||
Session.set('showUploadPresentationView', false);
|
||||
return handleSave(presentationsToSave)
|
||||
@ -711,47 +679,6 @@ class PresentationUploader extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
// renderToastItem(item) {
|
||||
// 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;
|
||||
|
||||
// let icon = isProcessing ? 'blank' : 'check';
|
||||
// if (hasError) icon = 'circle_close';
|
||||
|
||||
// return (
|
||||
// <Styled.UploadRow
|
||||
// key={item.id}
|
||||
// onClick={() => {
|
||||
// if (hasError || isProcessing) Session.set('showUploadPresentationView', true);
|
||||
// }}
|
||||
// >
|
||||
// <Styled.FileLine>
|
||||
// <span>
|
||||
// <Icon iconName="file" />
|
||||
// </span>
|
||||
// <Styled.ToastFileName>
|
||||
// <span>{item.filename}</span>
|
||||
// </Styled.ToastFileName>
|
||||
// <Styled.StatusIcon>
|
||||
// <Styled.ToastItemIcon
|
||||
// done={!isProcessing && !hasError}
|
||||
// error={hasError}
|
||||
// loading={isProcessing}
|
||||
// iconName={icon}
|
||||
// />
|
||||
// </Styled.StatusIcon>
|
||||
// </Styled.FileLine>
|
||||
// <Styled.StatusInfo>
|
||||
// <Styled.StatusInfoSpan data-test="presentationStatusInfo" styles={hasError ? 'error' : 'info'}>
|
||||
// {this.renderPresentationItemStatus(item)}
|
||||
// </Styled.StatusInfoSpan>
|
||||
// </Styled.StatusInfo>
|
||||
// </Styled.UploadRow>
|
||||
// );
|
||||
// }
|
||||
|
||||
renderExtraHint() {
|
||||
const {
|
||||
intl,
|
||||
@ -826,70 +753,6 @@ class PresentationUploader extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
// renderToastList() {
|
||||
// const { presentations, toUploadCount } = this.state;
|
||||
|
||||
// if (toUploadCount === 0) {
|
||||
// return this.handleDismissToast(this.toastId);
|
||||
// }
|
||||
|
||||
// const { intl } = this.props;
|
||||
// let converted = 0;
|
||||
|
||||
// let presentationsSorted = presentations
|
||||
// .filter((p) => (p.upload.progress || p.conversion.status) && p.file)
|
||||
// .sort((a, b) => a.uploadTimestamp - b.uploadTimestamp)
|
||||
// .sort((a, b) => a.conversion.done - b.conversion.done);
|
||||
|
||||
// presentationsSorted = presentationsSorted
|
||||
// .splice(0, toUploadCount)
|
||||
// .map((p) => {
|
||||
// if (p.conversion.done) converted += 1;
|
||||
// return p;
|
||||
// });
|
||||
|
||||
// let toastHeading = '';
|
||||
// const itemLabel = presentationsSorted.length > 1
|
||||
// ? intl.formatMessage(intlMessages.itemPlural)
|
||||
// : intl.formatMessage(intlMessages.item);
|
||||
|
||||
// if (converted === 0) {
|
||||
// toastHeading = intl.formatMessage(intlMessages.uploading, {
|
||||
// 0: presentationsSorted.length,
|
||||
// 1: itemLabel,
|
||||
// });
|
||||
// }
|
||||
|
||||
// if (converted > 0 && converted !== presentationsSorted.length) {
|
||||
// toastHeading = intl.formatMessage(intlMessages.uploadStatus, {
|
||||
// 0: converted,
|
||||
// 1: presentationsSorted.length,
|
||||
// });
|
||||
// }
|
||||
|
||||
// if (converted === presentationsSorted.length) {
|
||||
// toastHeading = intl.formatMessage(intlMessages.completed, {
|
||||
// 0: converted,
|
||||
// });
|
||||
// }
|
||||
|
||||
// return (
|
||||
// <Styled.ToastWrapper>
|
||||
// <Styled.UploadToastHeader>
|
||||
// <Styled.UploadIcon iconName="upload" />
|
||||
// <Styled.UploadToastTitle>{toastHeading}</Styled.UploadToastTitle>
|
||||
// </Styled.UploadToastHeader>
|
||||
// <Styled.InnerToast>
|
||||
// <div>
|
||||
// <div>
|
||||
// {presentationsSorted.map((item) => this.renderToastItem(item))}
|
||||
// </div>
|
||||
// </div>
|
||||
// </Styled.InnerToast>
|
||||
// </Styled.ToastWrapper>
|
||||
// );
|
||||
// }
|
||||
|
||||
renderExportToast() {
|
||||
const { intl } = this.props;
|
||||
const { presExporting } = this.state;
|
||||
@ -961,7 +824,9 @@ class PresentationUploader extends Component {
|
||||
}
|
||||
|
||||
return (
|
||||
<Styled.UploadRow>
|
||||
<Styled.UploadRow
|
||||
key={item.tmpPresId}
|
||||
>
|
||||
<Styled.FileLine>
|
||||
<span>
|
||||
<Icon iconName="file" />
|
||||
@ -1194,67 +1059,6 @@ class PresentationUploader extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
// renderPresentationItemStatus(item) {
|
||||
// const { intl } = this.props;
|
||||
// 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, {
|
||||
// 0: Math.floor(item.upload.progress).toString(),
|
||||
// });
|
||||
// }
|
||||
|
||||
// const constraint = {};
|
||||
|
||||
// if (item.upload.done && item.upload.error) {
|
||||
// if (item.conversion.status === 'FILE_TOO_LARGE') {
|
||||
// constraint['0'] = ((item.conversion.maxFileSize) / 1000 / 1000).toFixed(2);
|
||||
// }
|
||||
|
||||
// if (item.upload.progress < 100) {
|
||||
// const errorMessage = intlMessages.badConnectionError;
|
||||
// return intl.formatMessage(errorMessage);
|
||||
// }
|
||||
|
||||
// const errorMessage = intlMessages[item.upload.status] || intlMessages.genericError;
|
||||
// return intl.formatMessage(errorMessage, constraint);
|
||||
// }
|
||||
|
||||
// if (!item.conversion.done && item.conversion.error) {
|
||||
// const errorMessage = intlMessages[item.conversion.status] || intlMessages.genericConversionStatus;
|
||||
|
||||
// switch (item.conversion.status) {
|
||||
// case 'PAGE_COUNT_EXCEEDED':
|
||||
// constraint['0'] = item.conversion.maxNumberPages;
|
||||
// break;
|
||||
// case 'PDF_HAS_BIG_PAGE':
|
||||
// constraint['0'] = (item.conversion.bigPageSize / 1000 / 1000).toFixed(2);
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
|
||||
// return intl.formatMessage(errorMessage, constraint);
|
||||
// }
|
||||
|
||||
// if (!item.conversion.done && !item.conversion.error) {
|
||||
// if (item.conversion.pagesCompleted < item.conversion.numPages) {
|
||||
// return intl.formatMessage(intlMessages.conversionProcessingSlides, {
|
||||
// 0: item.conversion.pagesCompleted,
|
||||
// 1: item.conversion.numPages,
|
||||
// });
|
||||
// }
|
||||
|
||||
// const conversionStatusMessage = intlMessages[item.conversion.status]
|
||||
// || intlMessages.genericConversionStatus;
|
||||
// return intl.formatMessage(conversionStatusMessage);
|
||||
// }
|
||||
|
||||
// return null;
|
||||
// }
|
||||
|
||||
render() {
|
||||
const {
|
||||
isOpen,
|
||||
@ -1288,7 +1092,7 @@ class PresentationUploader extends Component {
|
||||
<Styled.ConfirmButton
|
||||
data-test="confirmManagePresentation"
|
||||
color="primary"
|
||||
onClick={() => this.handleConfirm(hasNewUpload)}
|
||||
onClick={() => this.handleConfirm()}
|
||||
disabled={disableActions}
|
||||
label={hasNewUpload
|
||||
? intl.formatMessage(intlMessages.uploadLabel)
|
||||
@ -1301,7 +1105,7 @@ class PresentationUploader extends Component {
|
||||
{`${intl.formatMessage(intlMessages.message)}`}
|
||||
{fileUploadConstraintsHint ? this.renderExtraHint() : null}
|
||||
</Styled.ModalHint>
|
||||
{this.renderPresentationList()}
|
||||
{this.renderPresentationList()}
|
||||
<Styled.ExportHint>
|
||||
{intl.formatMessage(intlMessages.exportHint)}
|
||||
</Styled.ExportHint>
|
||||
|
@ -4,6 +4,7 @@ import { withTracker } from 'meteor/react-meteor-data';
|
||||
import ErrorBoundary from '/imports/ui/components/common/error-boundary/component';
|
||||
import FallbackModal from '/imports/ui/components/common/fallback-errors/fallback-modal/component';
|
||||
import Service from './service';
|
||||
import PresUploaderController from '/imports/ui/components/presentation/presentation-toast/presentation-toast-controller';
|
||||
import PresentationUploader from './component';
|
||||
import { UsersContext } from '/imports/ui/components/components-data/users-context/context';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
@ -40,9 +41,9 @@ export default withTracker(() => {
|
||||
fileValidMimeTypes: PRESENTATION_CONFIG.uploadValidMimeTypes,
|
||||
allowDownloadable: PRESENTATION_CONFIG.allowDownloadable,
|
||||
handleSave: Service.handleSavePresentation,
|
||||
handleDismissToast: Service.handleDismissToast,
|
||||
handleDismissToast: PresUploaderController.handleDismissToast,
|
||||
renderToastList: Service.renderToastList,
|
||||
renderPresentationItemStatus: Service.renderPresentationItemStatus,
|
||||
renderPresentationItemStatus: PresUploaderController.renderPresentationItemStatus,
|
||||
dispatchDisableDownloadable,
|
||||
dispatchEnableDownloadable,
|
||||
dispatchTogglePresentationDownloadable,
|
||||
|
@ -1,16 +1,10 @@
|
||||
import Presentations from '/imports/api/presentations';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useTracker } from 'meteor/react-meteor-data';
|
||||
import Icon from '/imports/ui/components/common/icon/component';
|
||||
import PresentationUploadToken from '/imports/api/presentation-upload-token';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import Poll from '/imports/api/polls/';
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { defineMessages, injectIntl, useIntl } from 'react-intl';
|
||||
import { makeCall } from '/imports/ui/services/api';
|
||||
import logger from '/imports/startup/client/logger';
|
||||
import Styled from './styles';
|
||||
import { toast } from 'react-toastify';
|
||||
import _ from 'lodash';
|
||||
import update from 'immutability-helper';
|
||||
import { Random } from 'meteor/random';
|
||||
@ -20,87 +14,6 @@ const CONVERSION_TIMEOUT = 300000;
|
||||
const TOKEN_TIMEOUT = 5000;
|
||||
const PRESENTATION_CONFIG = Meteor.settings.public.presentation;
|
||||
|
||||
const intlMessages = defineMessages({
|
||||
|
||||
item: {
|
||||
id: 'app.presentationUploder.item',
|
||||
description: 'single item label',
|
||||
},
|
||||
itemPlural: {
|
||||
id: 'app.presentationUploder.itemPlural',
|
||||
description: 'plural item label',
|
||||
},
|
||||
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',
|
||||
},
|
||||
GENERATING_THUMBNAIL: {
|
||||
id: 'app.presentationUploder.conversion.generatingThumbnail',
|
||||
description: 'indicatess that it is generating thumbnails',
|
||||
},
|
||||
GENERATING_SVGIMAGES: {
|
||||
id: 'app.presentationUploder.conversion.generatingSvg',
|
||||
description: 'warns that it is generating svg images',
|
||||
},
|
||||
GENERATED_SLIDE: {
|
||||
id: 'app.presentationUploder.conversion.generatedSlides',
|
||||
description: 'warns that were slides generated',
|
||||
},
|
||||
PAGE_COUNT_EXCEEDED: {
|
||||
id: 'app.presentationUploder.conversion.pageCountExceeded',
|
||||
description: 'warns the user that the conversion failed because of the page count',
|
||||
},
|
||||
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',
|
||||
},
|
||||
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',
|
||||
},
|
||||
fileToUpload: {
|
||||
id: 'app.presentationUploder.fileToUpload',
|
||||
description: 'message used in the file selected for upload',
|
||||
},
|
||||
uploadProcess: {
|
||||
id: 'app.presentationUploder.upload.progress',
|
||||
description: 'message that indicates the percentage of the upload',
|
||||
},
|
||||
badConnectionError: {
|
||||
id: 'app.presentationUploder.connectionClosedError',
|
||||
description: 'message indicating that the connection was closed',
|
||||
},
|
||||
conversionProcessingSlides: {
|
||||
id: 'app.presentationUploder.conversion.conversionProcessingSlides',
|
||||
description: 'indicates how many slides were converted',
|
||||
},
|
||||
genericError: {
|
||||
id: 'app.presentationUploder.genericError',
|
||||
description: 'generic error while uploading/converting',
|
||||
},
|
||||
genericConversionStatus: {
|
||||
id: 'app.presentationUploder.conversion.genericConversionStatus',
|
||||
description: 'indicates that file is being converted',
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
// fetch doesn't support progress. So we use xhr which support progress.
|
||||
const futch = (url, opts = {}, onProgress) => new Promise((res, rej) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
@ -341,230 +254,6 @@ const removePresentations = (
|
||||
podId,
|
||||
) => Promise.all(presentationsToRemove.map((p) => removePresentation(p.id, podId)));
|
||||
|
||||
function renderPresentationItemStatus(item, intl) {
|
||||
if ((("progress" in item) && item.progress === 0) || (("conversion" in item && !item.conversion.done && !item.conversion.error))) {
|
||||
return intl.formatMessage(intlMessages.fileToUpload);
|
||||
}
|
||||
|
||||
if (("progress" in item) && item.progress < 100 && !("conversion" in item)) {
|
||||
return intl.formatMessage(intlMessages.uploadProcess, {
|
||||
0: Math.floor(item.progress).toString(),
|
||||
});
|
||||
}
|
||||
|
||||
const constraint = {};
|
||||
|
||||
if (("upload" in item) && (item.upload.done && item.upload.error)) {
|
||||
if (item.conversion.status === 'FILE_TOO_LARGE') {
|
||||
constraint['0'] = ((item.conversion.maxFileSize) / 1000 / 1000).toFixed(2);
|
||||
}
|
||||
|
||||
if (item.progress < 100) {
|
||||
const errorMessage = intlMessages.badConnectionError;
|
||||
return intl.formatMessage(errorMessage);
|
||||
}
|
||||
|
||||
const errorMessage = intlMessages[item.upload.status] || intlMessages.genericError;
|
||||
return intl.formatMessage(errorMessage, constraint);
|
||||
}
|
||||
|
||||
if (("conversion" in item) && (!item.conversion.done && item.conversion.error)) {
|
||||
const errorMessage = intlMessages[item.conversion.status] || intlMessages.genericConversionStatus;
|
||||
|
||||
switch (item.conversion.status) {
|
||||
case 'PAGE_COUNT_EXCEEDED':
|
||||
constraint['0'] = item.conversion.maxNumberPages;
|
||||
break;
|
||||
case 'PDF_HAS_BIG_PAGE':
|
||||
constraint['0'] = (item.conversion.bigPageSize / 1000 / 1000).toFixed(2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return intl.formatMessage(errorMessage, constraint);
|
||||
}
|
||||
|
||||
if ((("conversion" in item) && (!item.conversion.done && !item.conversion.error)) || (("progress" in item) && item.progress == 100)) {
|
||||
let conversionStatusMessage
|
||||
if ("conversion" in item) {
|
||||
if (item.conversion.pagesCompleted < item.conversion.numPages) {
|
||||
return intl.formatMessage(intlMessages.conversionProcessingSlides, {
|
||||
0: item.conversion.pagesCompleted,
|
||||
1: item.conversion.numPages,
|
||||
});
|
||||
}
|
||||
|
||||
conversionStatusMessage = intlMessages[item.conversion.status]
|
||||
|| intlMessages.genericConversionStatus;
|
||||
} else {
|
||||
conversionStatusMessage = intlMessages.genericConversionStatus;
|
||||
}
|
||||
return intl.formatMessage(conversionStatusMessage);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function renderToastItem(item, intl) {
|
||||
const isUploading = ("progress" in item) && item.progress <= 100;
|
||||
const isConverting = ("conversion" in item) && !item.conversion.done;
|
||||
const hasError = ((("conversion" in item) && item.conversion.error) || (("upload" in item) && item.upload.error));
|
||||
const isProcessing = (isUploading || isConverting) && !hasError;
|
||||
|
||||
let icon = isProcessing ? 'blank' : 'check';
|
||||
if (hasError) icon = 'circle_close';
|
||||
|
||||
return (
|
||||
<Styled.UploadRow
|
||||
key={item.id}
|
||||
onClick={() => {
|
||||
if (hasError || isProcessing) Session.set('showUploadPresentationView', true);
|
||||
}}
|
||||
>
|
||||
<Styled.FileLine>
|
||||
<span>
|
||||
<Icon iconName="file" />
|
||||
</span>
|
||||
<Styled.ToastFileName>
|
||||
<span>{item.filename || item.name}</span>
|
||||
</Styled.ToastFileName>
|
||||
<Styled.StatusIcon>
|
||||
<Styled.ToastItemIcon
|
||||
done={!isProcessing && !hasError}
|
||||
error={hasError}
|
||||
loading={isProcessing}
|
||||
iconName={icon}
|
||||
/>
|
||||
</Styled.StatusIcon>
|
||||
</Styled.FileLine>
|
||||
<Styled.StatusInfo>
|
||||
<Styled.StatusInfoSpan data-test="presentationStatusInfo" styles={hasError ? 'error' : 'info'}>
|
||||
{renderPresentationItemStatus(item, intl)}
|
||||
</Styled.StatusInfoSpan>
|
||||
</Styled.StatusInfo>
|
||||
</Styled.UploadRow>
|
||||
);
|
||||
}
|
||||
|
||||
const renderToastList = (presentations, intl) => {
|
||||
|
||||
let converted = 0;
|
||||
|
||||
let presentationsSorted = presentations
|
||||
.sort((a, b) => a.uploadTimestamp - b.uploadTimestamp)
|
||||
.sort((a, b) => {
|
||||
const presADone = a.conversion ? a.conversion.done : false;
|
||||
const presBDone = b.conversion ? b.conversion.done : false;
|
||||
|
||||
return presADone - presBDone
|
||||
});
|
||||
|
||||
presentationsSorted
|
||||
.forEach((p) => {
|
||||
const presDone = p.conversion ? p.conversion.done : false;
|
||||
if (presDone) converted += 1;
|
||||
return p;
|
||||
});
|
||||
|
||||
let toastHeading = '';
|
||||
const itemLabel = presentationsSorted.length > 1
|
||||
? intl.formatMessage(intlMessages.itemPlural)
|
||||
: intl.formatMessage(intlMessages.item);
|
||||
|
||||
if (converted === 0) {
|
||||
toastHeading = intl.formatMessage(intlMessages.uploading, {
|
||||
0: presentationsSorted.length,
|
||||
1: itemLabel,
|
||||
});
|
||||
}
|
||||
|
||||
if (converted > 0 && converted !== presentationsSorted.length) {
|
||||
toastHeading = intl.formatMessage(intlMessages.uploadStatus, {
|
||||
0: converted,
|
||||
1: presentationsSorted.length,
|
||||
});
|
||||
}
|
||||
|
||||
if (converted === presentationsSorted.length) {
|
||||
toastHeading = intl.formatMessage(intlMessages.completed, {
|
||||
0: converted,
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<Styled.ToastWrapper>
|
||||
<Styled.UploadToastHeader>
|
||||
<Styled.UploadIcon iconName="upload" />
|
||||
<Styled.UploadToastTitle>{toastHeading}</Styled.UploadToastTitle>
|
||||
</Styled.UploadToastHeader>
|
||||
<Styled.InnerToast>
|
||||
<div>
|
||||
<div>
|
||||
{presentationsSorted.map((item) => renderToastItem(item, intl))}
|
||||
</div>
|
||||
</div>
|
||||
</Styled.InnerToast>
|
||||
</Styled.ToastWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function handleDismissToast(toastId) {
|
||||
return toast.dismiss(toastId);
|
||||
}
|
||||
|
||||
export const ToastController = ({ intl }) => {
|
||||
|
||||
|
||||
useTracker(() => {
|
||||
const presentationsRenderedFalseAndConversionFalse = Presentations.find({ $or: [{renderedInToast: false}, {"conversion.done": false}] }).fetch();
|
||||
const convertingPresentations = presentationsRenderedFalseAndConversionFalse.filter(p => !p.renderedInToast )
|
||||
let tmpIdconvertingPresentations = presentationsRenderedFalseAndConversionFalse.filter(p => !p.conversion.done)
|
||||
.map(p => p.tmpPresId)
|
||||
// tmpIdconvertingPresentations = UploadingPresentations.find({}).fetch().filter(p => tmpIdconvertingPresentations.includes(p.tmpPresId))
|
||||
// .map(p => p.tmpPresId)
|
||||
UploadingPresentations.find({}).fetch().filter(p => tmpIdconvertingPresentations.includes(p.tmpPresId))
|
||||
.map(p => UploadingPresentations.remove({tmpPresId: p.tmpPresId}));
|
||||
// Remove all presentations from the uploading collection if they are already
|
||||
// converting.
|
||||
// UploadingPresentations.remove({tmpPresId: {$all: tmpIdconvertingPresentations}});
|
||||
const uploadingPresentations = UploadingPresentations.find().fetch();
|
||||
let presentationsToConvert = convertingPresentations.concat(uploadingPresentations);
|
||||
|
||||
let activeToast = Session.get("presentationUploaderToastId");
|
||||
const showToast = presentationsToConvert.length > 0;
|
||||
if (showToast && !activeToast) {
|
||||
activeToast = toast.info(() => renderToastList(presentationsToConvert, intl), {
|
||||
hideProgressBar: true,
|
||||
autoClose: false,
|
||||
newestOnTop: true,
|
||||
closeOnClick: true,
|
||||
onClose: () => {
|
||||
Session.set("presentationUploaderToastId", null);
|
||||
presentationsToConvert = [];
|
||||
},
|
||||
});
|
||||
Session.set("presentationUploaderToastId", activeToast);
|
||||
} else if (!showToast && activeToast) {
|
||||
handleDismissToast(activeToast);
|
||||
Session.set("presentationUploaderToastId", null);
|
||||
} else {
|
||||
toast.update(activeToast, {
|
||||
render: renderToastList(presentationsToConvert, intl),
|
||||
});
|
||||
}
|
||||
|
||||
let tmpPresIdListToSetAsRendered = presentationsToConvert.filter(p =>
|
||||
("conversion" in p && (p.conversion.done || p.conversion.error)))
|
||||
|
||||
tmpPresIdListToSetAsRendered = tmpPresIdListToSetAsRendered.map(p => p.tmpPresId);
|
||||
|
||||
makeCall('setPresentationRenderedInToast', tmpPresIdListToSetAsRendered);
|
||||
}, [])
|
||||
return null;
|
||||
}
|
||||
|
||||
const persistPresentationChanges = (oldState, newState, uploadEndpoint, podId) => {
|
||||
const presentationsToUpload = newState.filter((p) => !p.upload.done);
|
||||
|
||||
@ -667,8 +356,5 @@ export default {
|
||||
setPresentation,
|
||||
requestPresentationUploadToken,
|
||||
exportPresentationToChat,
|
||||
renderToastList,
|
||||
handleDismissToast,
|
||||
renderPresentationItemStatus,
|
||||
uploadAndConvertPresentation,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user