From 94fc8a4d41c71662c119fd295a3ff7a1a8e073e0 Mon Sep 17 00:00:00 2001 From: Daniel Petri Rocha Date: Wed, 24 Aug 2022 15:31:20 +0200 Subject: [PATCH] Toast messages in front-end --- bbb-export-annotations/workers/collector.js | 2 +- bbb-export-annotations/workers/process.js | 4 +- .../api/presentations/server/eventHandlers.js | 2 + .../handlers/presentationExportToastUpdate.js | 21 ++++++++ .../modifiers/setPresentationExporting.js | 3 +- .../setPresentationExportingProgress.js | 27 +++++++++++ .../presentation-uploader/component.jsx | 48 ++++++++++++++----- .../presentation-uploader/service.js | 4 +- bigbluebutton-html5/public/locales/en.json | 2 + 9 files changed, 95 insertions(+), 18 deletions(-) create mode 100644 bigbluebutton-html5/imports/api/presentations/server/handlers/presentationExportToastUpdate.js create mode 100644 bigbluebutton-html5/imports/api/presentations/server/modifiers/setPresentationExportingProgress.js diff --git a/bbb-export-annotations/workers/collector.js b/bbb-export-annotations/workers/collector.js index eefcf072a5..fd5f349b52 100644 --- a/bbb-export-annotations/workers/collector.js +++ b/bbb-export-annotations/workers/collector.js @@ -82,7 +82,7 @@ const exportJob = JSON.parse(job); presId: exportJob.presId, pageNumber: 1, totalPages: pages.length, - status: 'collecting', + status: 'COLLECTING', error: false, }, }, diff --git a/bbb-export-annotations/workers/process.js b/bbb-export-annotations/workers/process.js index 126a45607d..940b86a206 100644 --- a/bbb-export-annotations/workers/process.js +++ b/bbb-export-annotations/workers/process.js @@ -14,7 +14,7 @@ const [jobId, statusUpdate] = workerData; const logger = new Logger('presAnn Process Worker'); logger.info('Processing PDF for job ' + jobId); -statusUpdate.core.body.status = 'processing'; +statusUpdate.core.body.status = 'PROCESSING'; const kickOffNotifierWorker = (jobType, filename) => { return new Promise((resolve, reject) => { @@ -787,7 +787,7 @@ async function process_presentation_annotations() { await client.connect(); - client.on('error', (err) => console.log('Redis Client Error', err)); + client.on('error', (err) => logger.info('Redis Client Error', err)); // 1. Get the job const job = fs.readFileSync(path.join(dropbox, 'job')); diff --git a/bigbluebutton-html5/imports/api/presentations/server/eventHandlers.js b/bigbluebutton-html5/imports/api/presentations/server/eventHandlers.js index f7f453186d..f2052f6fb5 100644 --- a/bigbluebutton-html5/imports/api/presentations/server/eventHandlers.js +++ b/bigbluebutton-html5/imports/api/presentations/server/eventHandlers.js @@ -5,6 +5,7 @@ import handlePresentationCurrentSet from './handlers/presentationCurrentSet'; import handlePresentationConversionUpdate from './handlers/presentationConversionUpdate'; import handlePresentationDownloadableSet from './handlers/presentationDownloadableSet'; import handlePresentationExport from './handlers/presentationExport'; +import handlePresentationExportToastUpdate from './handlers/presentationExportToastUpdate'; RedisPubSub.on('PdfConversionInvalidErrorEvtMsg', handlePresentationConversionUpdate); RedisPubSub.on('PresentationPageGeneratedEvtMsg', handlePresentationConversionUpdate); @@ -16,3 +17,4 @@ RedisPubSub.on('RemovePresentationEvtMsg', handlePresentationRemove); RedisPubSub.on('SetCurrentPresentationEvtMsg', handlePresentationCurrentSet); RedisPubSub.on('SetPresentationDownloadableEvtMsg', handlePresentationDownloadableSet); RedisPubSub.on('NewPresAnnFileAvailableEvtMsg', handlePresentationExport); +RedisPubSub.on('PresAnnStatusEvtMsg', handlePresentationExportToastUpdate); diff --git a/bigbluebutton-html5/imports/api/presentations/server/handlers/presentationExportToastUpdate.js b/bigbluebutton-html5/imports/api/presentations/server/handlers/presentationExportToastUpdate.js new file mode 100644 index 0000000000..6263b01359 --- /dev/null +++ b/bigbluebutton-html5/imports/api/presentations/server/handlers/presentationExportToastUpdate.js @@ -0,0 +1,21 @@ +import { check } from 'meteor/check'; +import setPresentationExportingProgress from '/imports/api/presentations/server/modifiers/setPresentationExportingProgress'; + +export default function handlePresentationExportToastUpdate({ body }, meetingId) { + check(body, Object); + check(meetingId, String); + + const { + presId, pageNumber, totalPages, status, error, + } = body; + + check(presId, String); + check(pageNumber, Number); + check(totalPages, Number); + check(status, String); + check(error, Boolean); + + setPresentationExportingProgress(meetingId, presId, { + pageNumber, totalPages, status, error, + }); +} diff --git a/bigbluebutton-html5/imports/api/presentations/server/modifiers/setPresentationExporting.js b/bigbluebutton-html5/imports/api/presentations/server/modifiers/setPresentationExporting.js index ac80baaa24..b72554d9ba 100644 --- a/bigbluebutton-html5/imports/api/presentations/server/modifiers/setPresentationExporting.js +++ b/bigbluebutton-html5/imports/api/presentations/server/modifiers/setPresentationExporting.js @@ -22,8 +22,7 @@ export default function setPresentationExporting(meetingId, presentationId, expo const { numberAffected } = Presentations.upsert(selector, modifier); if (numberAffected) { - const status = `isRunning=${exportation.isRunning} error=${exportation.error}`; - Logger.info(`Set exporting status on presentation ${presentationId} in meeting ${meetingId} ${status}`); + Logger.info(`Set exporting status on presentation ${presentationId} in meeting ${meetingId} status=${exportation.status}`); } } catch (err) { Logger.error(`Could not set exporting status on pres ${presentationId} in meeting ${meetingId} ${err}`); diff --git a/bigbluebutton-html5/imports/api/presentations/server/modifiers/setPresentationExportingProgress.js b/bigbluebutton-html5/imports/api/presentations/server/modifiers/setPresentationExportingProgress.js new file mode 100644 index 0000000000..8700b3a484 --- /dev/null +++ b/bigbluebutton-html5/imports/api/presentations/server/modifiers/setPresentationExportingProgress.js @@ -0,0 +1,27 @@ +import { check } from 'meteor/check'; +import Presentations from '/imports/api/presentations'; +import Logger from '/imports/startup/server/logger'; + +export default function setPresentationExportingProgress(meetingId, presentationId, exportation) { + check(meetingId, String); + check(presentationId, String); + check(exportation, Object); + + const selector = { + meetingId, + id: presentationId, + }; + + const modifier = { + $set: { + exportation, + }, + }; + + try { + Presentations.upsert(selector, modifier); + } catch (err) { + const state = `pageNumber=${exportation.pageNumber} totalPages=${exportation.totalPages} status=${exportation.status} error=${exportation.error}`; + Logger.error(`Could not update exporting progress for presentation ${presentationId} in meeting ${meetingId} ${state} ${err}`); + } +} diff --git a/bigbluebutton-html5/imports/ui/components/presentation/presentation-uploader/component.jsx b/bigbluebutton-html5/imports/ui/components/presentation/presentation-uploader/component.jsx index 13e217ae64..20e027345f 100755 --- a/bigbluebutton-html5/imports/ui/components/presentation/presentation-uploader/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/presentation/presentation-uploader/component.jsx @@ -253,6 +253,14 @@ const intlMessages = defineMessages({ id: 'app.presentationUploader.sending', description: 'sending label', }, + collecting: { + id: 'app.presentationUploader.collecting', + description: 'collecting label', + }, + processing: { + id: 'app.presentationUploader.processing', + description: 'processing label', + }, sent: { id: 'app.presentationUploader.sent', description: 'sent label', @@ -265,6 +273,8 @@ const intlMessages = defineMessages({ const EXPORT_STATUSES = { RUNNING: 'RUNNING', + COLLECTING: 'COLLECTING', + PROCESSING: 'PROCESSING', TIMEOUT: 'TIMEOUT', EXPORTED: 'EXPORTED', }; @@ -427,7 +437,7 @@ class PresentationUploader extends Component { isCurrent: false, conversion: { done: false, error: false }, upload: { done: false, error: false, progress: 0 }, - exportation: { isRunning: false, error: false }, + exportation: { error: false }, onProgress: (event) => { if (!event.lengthComputable) { this.deepMergeUpdateFileKey(id, 'upload', { @@ -647,8 +657,9 @@ class PresentationUploader extends Component { const observer = (exportation) => { this.deepMergeUpdateFileKey(item.id, 'exportation', exportation); - - if (exportation.status === EXPORT_STATUSES.RUNNING) { + if ([EXPORT_STATUSES.RUNNING, + EXPORT_STATUSES.COLLECTING, + EXPORT_STATUSES.PROCESSING].includes(exportation.status)) { this.setState((prevState) => { prevState.presExporting.add(item.id); return { @@ -667,12 +678,12 @@ class PresentationUploader extends Component { closeOnClick: true, onClose: () => { this.exportToastId = null; - const presToShow = this.getPresentationsToShow(); const isAnyRunning = presToShow.some( (p) => p.exportation.status === EXPORT_STATUSES.RUNNING + || p.exportation.status === EXPORT_STATUSES.COLLECTING + || p.exportation.status === EXPORT_STATUSES.PROCESSING, ); - if (!isAnyRunning) { this.setState({ presExporting: new Set() }); } @@ -894,7 +905,7 @@ class PresentationUploader extends Component { const presToShow = this.getPresentationsToShow(); const isAllExported = presToShow.every( - (p) => p.exportation.status === EXPORT_STATUSES.EXPORTED + (p) => p.exportation.status === EXPORT_STATUSES.EXPORTED, ); const shouldDismiss = isAllExported && this.exportToastId; @@ -904,12 +915,13 @@ class PresentationUploader extends Component { if (presExporting.size) { this.setState({ presExporting: new Set() }); } - return; } const presToShowSorted = [ ...presToShow.filter((p) => p.exportation.status === EXPORT_STATUSES.RUNNING), + ...presToShow.filter((p) => p.exportation.status === EXPORT_STATUSES.COLLECTING), + ...presToShow.filter((p) => p.exportation.status === EXPORT_STATUSES.PROCESSING), ...presToShow.filter((p) => p.exportation.status === EXPORT_STATUSES.TIMEOUT), ...presToShow.filter((p) => p.exportation.status === EXPORT_STATUSES.EXPORTED), ]; @@ -939,19 +951,27 @@ class PresentationUploader extends Component { renderToastExportItem(item) { const { status } = item.exportation; - const loading = status === EXPORT_STATUSES.RUNNING; + const loading = (status === EXPORT_STATUSES.RUNNING + || status === EXPORT_STATUSES.COLLECTING + || status === EXPORT_STATUSES.PROCESSING); const done = status === EXPORT_STATUSES.EXPORTED; let icon; switch (status) { case EXPORT_STATUSES.RUNNING: - icon = 'blank' + icon = 'blank'; + break; + case EXPORT_STATUSES.COLLECTING: + icon = 'blank'; + break; + case EXPORT_STATUSES.PROCESSING: + icon = 'blank'; break; case EXPORT_STATUSES.EXPORTED: - icon = 'check' + icon = 'check'; break; case EXPORT_STATUSES.TIMEOUT: - icon = 'warning' + icon = 'warning'; break; default: break; @@ -990,6 +1010,12 @@ class PresentationUploader extends Component { switch (item.exportation.status) { case EXPORT_STATUSES.RUNNING: return intl.formatMessage(intlMessages.sending); + 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 }); case EXPORT_STATUSES.TIMEOUT: return intl.formatMessage(intlMessages.exportingTimeout); case EXPORT_STATUSES.EXPORTED: diff --git a/bigbluebutton-html5/imports/ui/components/presentation/presentation-uploader/service.js b/bigbluebutton-html5/imports/ui/components/presentation/presentation-uploader/service.js index c085f7389d..384e162f78 100644 --- a/bigbluebutton-html5/imports/ui/components/presentation/presentation-uploader/service.js +++ b/bigbluebutton-html5/imports/ui/components/presentation/presentation-uploader/service.js @@ -60,7 +60,7 @@ const getPresentations = () => Presentations isRemovable: removable, conversion: conversion || { done: true, error: false }, uploadTimestamp, - exportation: exportation || { isRunning: false, error: false }, + exportation: exportation || { error: false }, }; }); @@ -277,7 +277,7 @@ const exportPresentationToChat = (presentationId, observer) => { const cursor = Presentations.find({ id: presentationId }); const checkStatus = (exportation) => { - const shouldStop = lastStatus.status === 'RUNNING' && exportation.status !== 'RUNNING'; + const shouldStop = lastStatus.status === 'PROCESSING' && exportation.status === 'EXPORTED'; if (shouldStop) { observer(exportation, true); diff --git a/bigbluebutton-html5/public/locales/en.json b/bigbluebutton-html5/public/locales/en.json index c2a168c2ef..8ffa34d7d9 100755 --- a/bigbluebutton-html5/public/locales/en.json +++ b/bigbluebutton-html5/public/locales/en.json @@ -236,6 +236,8 @@ "app.presentationUploader.exportToastHeaderPlural": "Sending to chat ({0} items)", "app.presentationUploader.exporting": "Sending to chat", "app.presentationUploader.sending": "Sending...", + "app.presentationUploader.collecting": "Extracting slide {0} of {1}...", + "app.presentationUploader.processing": "Annotating slide {0} of {1}...", "app.presentationUploader.sent": "Sent", "app.presentationUploader.exportingTimeout": "The export is taking too long...", "app.presentationUploader.export": "Send to chat",