[issue-17531] - prevent user from exporting annotations when there is no annotation

This commit is contained in:
GuiLeme 2023-05-04 08:48:32 -03:00
parent f3969c083a
commit f650ade561
9 changed files with 47 additions and 28 deletions

View File

@ -151,7 +151,7 @@ trait MakePresentationDownloadReqMsgHdlr extends RightsManagementTrait {
val annotationCount: Int = storeAnnotationPages.map(_.annotations.size).sum val annotationCount: Int = storeAnnotationPages.map(_.annotations.size).sum
val isOriginalPresentationType = m.body.typeOfExport == "Original" val isOriginalPresentationType = m.body.typeOfExport == "Original"
if (annotationCount > 0 && !isOriginalPresentationType) { if (!isOriginalPresentationType && annotationCount > 0) {
// Send Export Job to Redis // Send Export Job to Redis
val job = buildStoreExportJobInRedisSysMsg(exportJob, liveMeeting) val job = buildStoreExportJobInRedisSysMsg(exportJob, liveMeeting)
bus.outGW.send(job) bus.outGW.send(job)
@ -159,7 +159,9 @@ trait MakePresentationDownloadReqMsgHdlr extends RightsManagementTrait {
// Send Annotations to Redis // Send Annotations to Redis
val annotations = StoredAnnotations(jobId, presId, storeAnnotationPages) val annotations = StoredAnnotations(jobId, presId, storeAnnotationPages)
bus.outGW.send(buildStoreAnnotationsInRedisSysMsg(annotations, liveMeeting)) bus.outGW.send(buildStoreAnnotationsInRedisSysMsg(annotations, liveMeeting))
} else { } else if (!isOriginalPresentationType && annotationCount == 0) {
log.error("There is no annotations for presentation with Id {}... Ignoring", presId)
} else if (isOriginalPresentationType) {
// Return existing uploaded file directly // Return existing uploaded file directly
val convertedFileName = currentPres.get.presentationConvertedName val convertedFileName = currentPres.get.presentationConvertedName
val filename = if (convertedFileName == "") currentPres.get.name else convertedFileName val filename = if (convertedFileName == "") currentPres.get.name else convertedFileName

View File

@ -14,7 +14,7 @@ export default async function handlePresentationExport({ body }, meetingId) {
check(typeOfExport, Match.Maybe(String)); check(typeOfExport, Match.Maybe(String));
if (typeOfExport === "Original") { if (typeOfExport === "Original") {
setOriginalUriDownload(meetingId, presId, fileURI) await setOriginalUriDownload(meetingId, presId, fileURI)
} else { } else {
await sendExportedPresentationChatMsg(meetingId, presId, fileURI, typeOfExport); await sendExportedPresentationChatMsg(meetingId, presId, fileURI, typeOfExport);
} }

View File

@ -3,12 +3,12 @@ import removePresentation from './methods/removePresentation';
import setPresentationRenderedInToast from './methods/setPresentationRenderedInToast'; import setPresentationRenderedInToast from './methods/setPresentationRenderedInToast';
import setPresentation from './methods/setPresentation'; import setPresentation from './methods/setPresentation';
import setPresentationDownloadable from './methods/setPresentationDownloadable'; import setPresentationDownloadable from './methods/setPresentationDownloadable';
import exportPresentationToChat from './methods/exportPresentationToChat'; import exportPresentation from './methods/exportPresentation';
Meteor.methods({ Meteor.methods({
removePresentation, removePresentation,
setPresentation, setPresentation,
setPresentationDownloadable, setPresentationDownloadable,
exportPresentationToChat, exportPresentation,
setPresentationRenderedInToast, setPresentationRenderedInToast,
}); });

View File

@ -7,7 +7,7 @@ import Presentations from '/imports/api/presentations';
const EXPORTING_THRESHOLD_PER_SLIDE = 2500; const EXPORTING_THRESHOLD_PER_SLIDE = 2500;
export default async function exportPresentationToChat(presentationId, type) { export default async function exportPresentation(presentationId, type) {
const REDIS_CONFIG = Meteor.settings.private.redis; const REDIS_CONFIG = Meteor.settings.private.redis;
const CHANNEL = REDIS_CONFIG.channels.toAkkaApps; const CHANNEL = REDIS_CONFIG.channels.toAkkaApps;
const EVENT_NAME = 'MakePresentationDownloadReqMsg'; const EVENT_NAME = 'MakePresentationDownloadReqMsg';
@ -56,6 +56,6 @@ export default async function exportPresentationToChat(presentationId, type) {
RedisPubSub.publishUserMessage(CHANNEL, EVENT_NAME, meetingId, requesterUserId, payload); RedisPubSub.publishUserMessage(CHANNEL, EVENT_NAME, meetingId, requesterUserId, payload);
} catch (err) { } catch (err) {
Logger.error(`Exception while invoking method exportPresentationToChat ${err.stack}`); Logger.error(`Exception while invoking method exportPresentation ${err.stack}`);
} }
} }

View File

@ -46,7 +46,8 @@ const propTypes = {
presentationUploadExternalUrl: PropTypes.string.isRequired, presentationUploadExternalUrl: PropTypes.string.isRequired,
}).isRequired, }).isRequired,
isPresenter: PropTypes.bool.isRequired, isPresenter: PropTypes.bool.isRequired,
exportPresentationToChat: PropTypes.func.isRequired, exportPresentation: PropTypes.func.isRequired,
getHasAnnotations: PropTypes.func.isRequired,
}; };
const defaultProps = { const defaultProps = {
@ -687,7 +688,7 @@ class PresentationUploader extends Component {
handleDownloadingOfPresentation(item, type) { handleDownloadingOfPresentation(item, type) {
const { const {
exportPresentationToChat, exportPresentation,
intl, intl,
} = this.props; } = this.props;
@ -743,7 +744,7 @@ class PresentationUploader extends Component {
} }
}; };
exportPresentationToChat(item.id, observer, type); exportPresentation(item.id, observer, type);
} }
getPresentationsToShow() { getPresentationsToShow() {
@ -1003,6 +1004,7 @@ class PresentationUploader extends Component {
selectedToBeNextCurrent, selectedToBeNextCurrent,
allowDownloadable, allowDownloadable,
renderPresentationItemStatus, renderPresentationItemStatus,
getHasAnnotations,
} = this.props; } = this.props;
const isActualCurrent = selectedToBeNextCurrent const isActualCurrent = selectedToBeNextCurrent
@ -1034,6 +1036,7 @@ class PresentationUploader extends Component {
const formattedDownloadAriaLabel = `${formattedDownloadLabel} ${item.filename}`; const formattedDownloadAriaLabel = `${formattedDownloadLabel} ${item.filename}`;
const hasAnnotations = getHasAnnotations(item.id);
return ( return (
<Styled.PresentationItem <Styled.PresentationItem
key={item.id} key={item.id}
@ -1075,9 +1078,10 @@ class PresentationUploader extends Component {
hasError ? null : ( hasError ? null : (
<Styled.TableItemActions notDownloadable={!allowDownloadable}> <Styled.TableItemActions notDownloadable={!allowDownloadable}>
{allowDownloadable ? ( {allowDownloadable ? (
<PresentationDownloadDropdown <PresentationDownloadDropdown
hasAnnotations={hasAnnotations}
disabled={shouldDisableExportButton} disabled={shouldDisableExportButton}
data-test="exportPresentationToPublicChat" data-test="exportPresentation"
aria-label={formattedDownloadAriaLabel} aria-label={formattedDownloadAriaLabel}
color="primary" color="primary"
isDownloadable={isDownloadable} isDownloadable={isDownloadable}

View File

@ -9,6 +9,7 @@ import PresentationUploader from './component';
import { UsersContext } from '/imports/ui/components/components-data/users-context/context'; import { UsersContext } from '/imports/ui/components/components-data/users-context/context';
import Auth from '/imports/ui/services/auth'; import Auth from '/imports/ui/services/auth';
import { isDownloadPresentationWithAnnotationsEnabled, isPresentationEnabled } from '/imports/ui/services/features'; import { isDownloadPresentationWithAnnotationsEnabled, isPresentationEnabled } from '/imports/ui/services/features';
import { getHasAnnotations } from '/imports/ui/components/whiteboard/service'
const PRESENTATION_CONFIG = Meteor.settings.public.presentation; const PRESENTATION_CONFIG = Meteor.settings.public.presentation;
@ -31,7 +32,7 @@ export default withTracker(() => {
dispatchDisableDownloadable, dispatchDisableDownloadable,
dispatchEnableDownloadable, dispatchEnableDownloadable,
dispatchTogglePresentationDownloadable, dispatchTogglePresentationDownloadable,
exportPresentationToChat, exportPresentation,
} = Service; } = Service;
const isOpen = isPresentationEnabled() && (Session.get('showUploadPresentationView') || false); const isOpen = isPresentationEnabled() && (Session.get('showUploadPresentationView') || false);
@ -49,10 +50,11 @@ export default withTracker(() => {
dispatchDisableDownloadable, dispatchDisableDownloadable,
dispatchEnableDownloadable, dispatchEnableDownloadable,
dispatchTogglePresentationDownloadable, dispatchTogglePresentationDownloadable,
exportPresentationToChat, exportPresentation,
isOpen, isOpen,
selectedToBeNextCurrent: Session.get('selectedToBeNextCurrent') || null, selectedToBeNextCurrent: Session.get('selectedToBeNextCurrent') || null,
externalUploadData: Service.getExternalUploadData(), externalUploadData: Service.getExternalUploadData(),
handleFiledrop: Service.handleFiledrop, handleFiledrop: Service.handleFiledrop,
getHasAnnotations,
}; };
})(PresentationUploaderContainer); })(PresentationUploaderContainer);

View File

@ -51,6 +51,7 @@ class PresentationDownloadDropdown extends PureComponent {
isDownloadable, isDownloadable,
item, item,
closeModal, closeModal,
hasAnnotations
} = this.props; } = this.props;
this.menuItems = []; this.menuItems = [];
@ -83,18 +84,20 @@ class PresentationDownloadDropdown extends PureComponent {
); );
} }
this.menuItems.push( if (hasAnnotations) {
{ this.menuItems.push(
key: this.actionsKey[1], {
id: 'sendAnnotatedDocument', key: this.actionsKey[1],
dataTest: 'sendAnnotatedDocument', id: 'sendAnnotatedDocument',
label: intl.formatMessage(intlMessages.sendAnnotatedDocument), dataTest: 'sendAnnotatedDocument',
onClick: () => { label: intl.formatMessage(intlMessages.sendAnnotatedDocument),
closeModal(); onClick: () => {
handleDownloadingOfPresentation("Annotated"); closeModal();
handleDownloadingOfPresentation("Annotated");
},
}, },
}, );
); }
return this.menuItems; return this.menuItems;
} }

View File

@ -378,7 +378,7 @@ const getExternalUploadData = () => {
}; };
}; };
const exportPresentationToChat = (presentationId, observer, type) => { const exportPresentation = (presentationId, observer, type) => {
let lastStatus = {}; let lastStatus = {};
Tracker.autorun((c) => { Tracker.autorun((c) => {
@ -407,7 +407,7 @@ const exportPresentationToChat = (presentationId, observer, type) => {
}); });
}); });
makeCall('exportPresentationToChat', presentationId, type); makeCall('exportPresentation', presentationId, type);
}; };
function handleFiledrop(files, files2, that, intl, intlMessages) { function handleFiledrop(files, files2, that, intl, intlMessages) {
@ -487,7 +487,7 @@ export default {
setPresentation, setPresentation,
requestPresentationUploadToken, requestPresentationUploadToken,
getExternalUploadData, getExternalUploadData,
exportPresentationToChat, exportPresentation,
uploadAndConvertPresentation, uploadAndConvertPresentation,
handleFiledrop, handleFiledrop,
}; };

View File

@ -38,6 +38,13 @@ async function handleAddedAnnotation({
Annotations.upsert(query.selector, query.modifier); Annotations.upsert(query.selector, query.modifier);
} }
const getHasAnnotations = (presentationId) => {
const ann = Annotations.find(
{},
).fetch();
return ann.filter(a => a.whiteboardId.includes(presentationId)).length > 0;
}
function handleRemovedAnnotation({ function handleRemovedAnnotation({
meetingId, whiteboardId, userId, shapeId, meetingId, whiteboardId, userId, shapeId,
}) { }) {
@ -388,4 +395,5 @@ export {
changeCurrentSlide, changeCurrentSlide,
notifyNotAllowedChange, notifyNotAllowedChange,
notifyShapeNumberExceeded, notifyShapeNumberExceeded,
getHasAnnotations,
}; };