diff --git a/bigbluebutton-html5/imports/api/meetings/server/modifiers/clearMeetings.js b/bigbluebutton-html5/imports/api/meetings/server/modifiers/clearMeetings.js index 627b1491142927531b0726269441ce5c08d2a877..65e2e45fdc65e7986534990e60cb998e17e54d44 100755 --- a/bigbluebutton-html5/imports/api/meetings/server/modifiers/clearMeetings.js +++ b/bigbluebutton-html5/imports/api/meetings/server/modifiers/clearMeetings.js @@ -5,13 +5,12 @@ import removeMeeting from './removeMeeting'; import { clearUsersCollection } from '/imports/api/users/server/modifiers/clearUsersCollection'; import clearChats from '/imports/api/chat/server/modifiers/clearChats'; import { clearShapesCollection } from '/imports/api/shapes/server/modifiers/clearShapesCollection'; -import { clearSlidesCollection } from '/imports/api/slides/server/modifiers/clearSlidesCollection'; +import clearSlides from '/imports/api/slides/server/modifiers/clearSlides'; import { clearPollCollection } from '/imports/api/polls/server/modifiers/clearPollCollection'; import { clearCursorCollection } from '/imports/api/cursor/server/modifiers/clearCursorCollection'; import { clearCaptionsCollection } from '/imports/api/captions/server/modifiers/clearCaptionsCollection'; -import { clearPresentationsCollection } - from '/imports/api/presentations/server/modifiers/clearPresentationsCollection'; +import clearPresentations from '/imports/api/presentations/server/modifiers/clearPresentations'; export default function clearMeetings() { return Meetings.remove({}, (err) => { @@ -19,9 +18,9 @@ export default function clearMeetings() { clearChats(); clearCursorCollection(); clearPollCollection(); - clearPresentationsCollection(); + clearPresentations(); clearShapesCollection(); - clearSlidesCollection(); + clearSlides(); clearUsersCollection(); return Logger.info('Cleared Meetings (all)'); diff --git a/bigbluebutton-html5/imports/api/meetings/server/modifiers/removeMeeting.js b/bigbluebutton-html5/imports/api/meetings/server/modifiers/removeMeeting.js index 2fc7118f68df219f22593d9911f144e522454154..d3379a15f9bf197316763e50adf5245b9ee169ee 100755 --- a/bigbluebutton-html5/imports/api/meetings/server/modifiers/removeMeeting.js +++ b/bigbluebutton-html5/imports/api/meetings/server/modifiers/removeMeeting.js @@ -5,13 +5,12 @@ import Logger from '/imports/startup/server/logger'; import { clearUsersCollection } from '/imports/api/users/server/modifiers/clearUsersCollection'; import clearChats from '/imports/api/chat/server/modifiers/clearChats'; import { clearShapesCollection } from '/imports/api/shapes/server/modifiers/clearShapesCollection'; -import { clearSlidesCollection } from '/imports/api/slides/server/modifiers/clearSlidesCollection'; +import clearSlides from '/imports/api/slides/server/modifiers/clearSlides'; import { clearPollCollection } from '/imports/api/polls/server/modifiers/clearPollCollection'; import { clearCursorCollection } from '/imports/api/cursor/server/modifiers/clearCursorCollection'; import { clearCaptionsCollection } from '/imports/api/captions/server/modifiers/clearCaptionsCollection'; -import { clearPresentationsCollection } - from '/imports/api/presentations/server/modifiers/clearPresentationsCollection'; +import clearPresentations from '/imports/api/presentations/server/modifiers/clearPresentations'; export default function removeMeeting(meetingId) { check(meetingId, String); @@ -30,9 +29,9 @@ export default function removeMeeting(meetingId) { clearChats(meetingId); clearCursorCollection(meetingId); clearPollCollection(meetingId); - clearPresentationsCollection(meetingId); + clearPresentations(meetingId); clearShapesCollection(meetingId); - clearSlidesCollection(meetingId); + clearSlides(meetingId); clearUsersCollection(meetingId); return Logger.info(`Removed meeting id=${meetingId}`); diff --git a/bigbluebutton-html5/imports/api/presentations/server/eventHandlers.js b/bigbluebutton-html5/imports/api/presentations/server/eventHandlers.js new file mode 100644 index 0000000000000000000000000000000000000000..aebbffb09bdc455412ef6b1b0b45060eb4481b88 --- /dev/null +++ b/bigbluebutton-html5/imports/api/presentations/server/eventHandlers.js @@ -0,0 +1,8 @@ +import RedisPubSub from '/imports/startup/server/redis'; +import handlePresentationRemove from './handlers/presentationRemove'; +import handlePresentationChange from './handlers/presentationChange'; +import handlePresentationInfoReply from './handlers/presentationInfoReply'; + +RedisPubSub.on('presentation_removed_message', handlePresentationRemove); +RedisPubSub.on('presentation_shared_message', handlePresentationChange); +RedisPubSub.on('get_presentation_info_reply', handlePresentationInfoReply); diff --git a/bigbluebutton-html5/imports/api/presentations/server/handlers/presentationChange.js b/bigbluebutton-html5/imports/api/presentations/server/handlers/presentationChange.js new file mode 100644 index 0000000000000000000000000000000000000000..3c1731aa1d3f4d4a3cee285a37791b9eb4537ef7 --- /dev/null +++ b/bigbluebutton-html5/imports/api/presentations/server/handlers/presentationChange.js @@ -0,0 +1,44 @@ +import { check } from 'meteor/check'; +import Logger from '/imports/startup/server/logger'; +import Presentations from '/imports/api/presentations'; + +import addPresentation from '../modifiers/addPresentation'; + +const clearCurrentPresentation = (meetingId, presentationId) => { + let selector = { + meetingId, + presentationId: { $ne: presentationId }, + 'presentation.current': true, + }; + + let modifier = { + $set: { 'presentation.current': false }, + }; + + let cb = (err, numChanged) => { + if (err) { + return Logger.error(`Unsetting the current presentation: ${err}`); + } + + if (numChanged) { + return Logger.info(`Unsetted as current presentation`); + } + }; + + return Presentations.update(selector, modifier, cb); +}; + +export default function handlePresentationChange({ payload }) { + const meetingId = payload.meeting_id; + const presentation = payload.presentation; + + check(meetingId, String); + check(presentation, Object); + + // We need to clear the flag of the older current presentation ¯\_(ツ)_/¯ + if (presentation.current) { + clearCurrentPresentation(meetingId, presentation.id); + } + + return addPresentation(meetingId, presentation); +}; diff --git a/bigbluebutton-html5/imports/api/presentations/server/handlers/presentationInfoReply.js b/bigbluebutton-html5/imports/api/presentations/server/handlers/presentationInfoReply.js new file mode 100644 index 0000000000000000000000000000000000000000..0b42afd2db713c7447a664ca502e4d6a6b797d7d --- /dev/null +++ b/bigbluebutton-html5/imports/api/presentations/server/handlers/presentationInfoReply.js @@ -0,0 +1,24 @@ +import Logger from '/imports/startup/server/logger'; +import { check } from 'meteor/check'; +import { inReplyToHTML5Client } from '/imports/api/common/server/helpers'; + +import addPresentation from '../modifiers/addPresentation'; + +export default function handlePresentationInfoReply({ payload }) { + if (!inReplyToHTML5Client({ payload })) { + return; + } + + const meetingId = payload.meeting_id; + const presentations = payload.presentations; + + check(meetingId, String); + check(presentations, Array); + + let presentationsAdded = []; + presentations.forEach(presentation => { + presentationsAdded.push(addPresentation(meetingId, presentation)); + }); + + return presentationsAdded; +}; diff --git a/bigbluebutton-html5/imports/api/presentations/server/handlers/presentationRemove.js b/bigbluebutton-html5/imports/api/presentations/server/handlers/presentationRemove.js new file mode 100644 index 0000000000000000000000000000000000000000..ba589c6484ad4375e0a6d926ba736b15c8f309c2 --- /dev/null +++ b/bigbluebutton-html5/imports/api/presentations/server/handlers/presentationRemove.js @@ -0,0 +1,14 @@ +import Logger from '/imports/startup/server/logger'; +import { check } from 'meteor/check'; + +import removePresentation from '../modifiers/removePresentation'; + +export default function handlePresentationRemove({ payload }) { + const meetingId = payload.meeting_id; + const presentationId = payload.presentation_id; + + check(meetingId, String); + check(presentationId, String); + + return removePresentation(meetingId, presentationId); +}; diff --git a/bigbluebutton-html5/imports/api/presentations/server/index.js b/bigbluebutton-html5/imports/api/presentations/server/index.js new file mode 100644 index 0000000000000000000000000000000000000000..92451ac76bf27410726e8f3cd2eebac46cd7b83e --- /dev/null +++ b/bigbluebutton-html5/imports/api/presentations/server/index.js @@ -0,0 +1,3 @@ +import './eventHandlers'; +import './methods'; +import './publishers'; diff --git a/bigbluebutton-html5/imports/api/presentations/server/methods.js b/bigbluebutton-html5/imports/api/presentations/server/methods.js new file mode 100644 index 0000000000000000000000000000000000000000..1ce65c369863cac02b7c5224a46ab766a38cf8b3 --- /dev/null +++ b/bigbluebutton-html5/imports/api/presentations/server/methods.js @@ -0,0 +1,4 @@ +import { Meteor } from 'meteor/meteor'; + +Meteor.methods({ +}); diff --git a/bigbluebutton-html5/imports/api/presentations/server/modifiers/addPresentation.js b/bigbluebutton-html5/imports/api/presentations/server/modifiers/addPresentation.js new file mode 100755 index 0000000000000000000000000000000000000000..e87c110988f1f54a453921670c0be3074965af59 --- /dev/null +++ b/bigbluebutton-html5/imports/api/presentations/server/modifiers/addPresentation.js @@ -0,0 +1,55 @@ +import { check } from 'meteor/check'; +import Presentations from '/imports/api/presentations'; +import Logger from '/imports/startup/server/logger'; + +import addSlide from '/imports/api/slides/server/modifiers/addSlide'; + +const addSlides = (meetingId, presentationId, slides) => { + let slidesAdded = []; + + slides.forEach(slide => { + slidesAdded.push(addSlide(meetingId, presentationId, slide)); + }); + + return slidesAdded; +}; + +export default function addPresentation(meetingId, presentation) { + check(meetingId, String); + check(presentation, Object); + + const selector = { + meetingId, + 'presentation.id': presentation.id, + }; + + const modifier = { + $set: { + meetingId, + presentation: { + id: presentation.id, + name: presentation.name, + current: presentation.current, + }, + }, + }; + + const cb = (err, numChanged) => { + if (err) { + return Logger.error(`Adding presentation to collection: ${err}`); + } + + addSlides(meetingId, presentation.id, presentation.pages); + + const { insertedId } = numChanged; + if (insertedId) { + return Logger.info(`Added presentation id=${presentation.id} meeting=${meetingId}`); + } + + if (numChanged) { + return Logger.info(`Upserted presentation id=${presentation.id} meeting=${meetingId}`); + } + }; + + return Presentations.upsert(selector, modifier, cb); +}; diff --git a/bigbluebutton-html5/imports/api/presentations/server/modifiers/addPresentationToCollection.js b/bigbluebutton-html5/imports/api/presentations/server/modifiers/addPresentationToCollection.js deleted file mode 100755 index 7ee32531da9fb7654ea37f287dfac3a928165e81..0000000000000000000000000000000000000000 --- a/bigbluebutton-html5/imports/api/presentations/server/modifiers/addPresentationToCollection.js +++ /dev/null @@ -1,23 +0,0 @@ -import Presentations from '/imports/api/presentations'; - -export function addPresentationToCollection(meetingId, presentationObject) { - //check if the presentation is already in the collection - const presentationObj = Presentations.findOne({ - meetingId: meetingId, - 'presentation.id': presentationObject.id, - }); - if (presentationObj == null) { - const entry = { - meetingId: meetingId, - presentation: { - id: presentationObject.id, - name: presentationObject.name, - current: presentationObject.current, - }, - }; - return Presentations.insert(entry); - - //logger.info "presentation added id =[#{id}]:#{presentationObject.id} in #{meetingId}. - // Presentations.size is now #{Presentations.find({meetingId: meetingId}).count()}" - } -}; diff --git a/bigbluebutton-html5/imports/api/presentations/server/modifiers/changeCurrentPresentation.js b/bigbluebutton-html5/imports/api/presentations/server/modifiers/changeCurrentPresentation.js new file mode 100644 index 0000000000000000000000000000000000000000..8657e563aa397511e34c4c608b2ebf39fd0681b2 --- /dev/null +++ b/bigbluebutton-html5/imports/api/presentations/server/modifiers/changeCurrentPresentation.js @@ -0,0 +1,53 @@ +import { check } from 'meteor/check'; +import Presentations from '/imports/api/presentations'; +import Logger from '/imports/startup/server/logger'; + +export default function changeCurrentPresentation(meetingId, presentationId) { + check(meetingId, String); + check(presentationId, String); + + const oldCurrent = { + selector: { + meetingId, + 'presentation.current': true, + }, + modifier: { + $set: { 'presentation.current': false }, + }, + callback: (err) => { + if (err) { + return Logger.error(`Unsetting the current presentation: ${err}`); + } + + return Logger.info(`Unsetted as current presentation`); + }, + }; + + const newCurrent = { + selector: { + meetingId, + 'presentation.id': presentationId, + }, + modifier: { + $set: { 'presentation.current': true }, + }, + callback: (err) => { + if (err) { + return Logger.error(`Setting as current presentation id=${presentationId}: ${err}`); + } + + return Logger.info(`Setted as current presentation id=${presentationId}`); + }, + }; + + const oldPresentation = Presentations.findOne(oldCurrent.selector); + const newPresentation = Presentations.findOne(newCurrent.selector); + + if (newPresentation) { + Presentations.update(newPresentation._id, newCurrent.modifier, newCurrent.callback); + } + + if (oldPresentation) { + Presentations.update(oldPresentation._id, oldCurrent.modifier, oldCurrent.callback); + } +}; diff --git a/bigbluebutton-html5/imports/api/presentations/server/modifiers/clearPresentations.js b/bigbluebutton-html5/imports/api/presentations/server/modifiers/clearPresentations.js new file mode 100755 index 0000000000000000000000000000000000000000..4301e5185679553571e6c9010ab3e2f76cf22c4c --- /dev/null +++ b/bigbluebutton-html5/imports/api/presentations/server/modifiers/clearPresentations.js @@ -0,0 +1,11 @@ +import Presentations from '/imports/api/slides'; +import Logger from '/imports/startup/server/logger'; + +export default function clearPresentations(meetingId) { + if (meetingId) { + return Presentations.remove({ meetingId: meetingId }, + Logger.info(`Cleared Presentations (${meetingId})`)); + } else { + return Presentations.remove({}, Logger.info('Cleared Presentations (all)')); + } +}; diff --git a/bigbluebutton-html5/imports/api/presentations/server/modifiers/clearPresentationsCollection.js b/bigbluebutton-html5/imports/api/presentations/server/modifiers/clearPresentationsCollection.js deleted file mode 100755 index 2fb5af1d18dfd8a450e5847699d8c05e143a5c16..0000000000000000000000000000000000000000 --- a/bigbluebutton-html5/imports/api/presentations/server/modifiers/clearPresentationsCollection.js +++ /dev/null @@ -1,14 +0,0 @@ -import Presentations from '/imports/api/presentations'; -import { logger } from '/imports/startup/server/logger'; - -// called on server start and meeting end -export function clearPresentationsCollection() { - const meetingId = arguments[0]; - if (meetingId != null) { - return Presentations.remove({ - meetingId: meetingId, - }, logger.info(`cleared Presentations Collection (meetingId: ${meetingId}!`)); - } else { - return Presentations.remove({}, logger.info('cleared Presentations Collection(all meetings)!')); - } -}; diff --git a/bigbluebutton-html5/imports/api/presentations/server/modifiers/eventHandlers.js b/bigbluebutton-html5/imports/api/presentations/server/modifiers/eventHandlers.js deleted file mode 100755 index 1808939f76a9e900eba3706e34cb62449e0f40f8..0000000000000000000000000000000000000000 --- a/bigbluebutton-html5/imports/api/presentations/server/modifiers/eventHandlers.js +++ /dev/null @@ -1,96 +0,0 @@ -import { eventEmitter } from '/imports/startup/server'; -import { removePresentationFromCollection } from './removePresentationFromCollection'; -import { addPresentationToCollection } from './addPresentationToCollection'; -import { appendMessageHeader, publish, inReplyToHTML5Client } - from '/imports/api/common/server/helpers'; -import addSlideToCollection from '/imports/api/slides/server/modifiers/addSlideToCollection'; -import Slides from '/imports/api/slides'; -import Presentations from '/imports/api/presentations'; -import { logger } from '/imports/startup/server/logger'; - -eventEmitter.on('presentation_removed_message', function (arg) { - const meetingId = arg.payload.meeting_id; - const presentationId = arg.payload.presentation_id; - if (meetingId != null && presentationId != null) { - removePresentationFromCollection(meetingId, presentationId); - } - - return arg.callback(); -}); - -eventEmitter.on('presentation_shared_message', function (arg) { - const payload = arg.payload; - const meetingId = payload.meeting_id; - if (payload.presentation != null && payload.presentation.id != null && meetingId != null) { - const presentationId = payload.presentation.id; - - // change the currently displayed presentation to presentation.current = false - Presentations.update({ - 'presentation.current': true, - meetingId: meetingId, - }, { - $set: { - 'presentation.current': false, - }, - }); - - //update(if already present) entirely the presentation with the fresh data - removePresentationFromCollection(meetingId, presentationId); - addPresentationToCollection(meetingId, payload.presentation); - const pages = payload.presentation.pages; - for (j = 0; j < pages.length; j++) { - const slide = pages[j]; - addSlideToCollection( - meetingId, - presentationId, - slide - ); - } - } - - return arg.callback(); -}); - -eventEmitter.on('get_presentation_info_reply', function (arg) { - const REDIS_CONFIG = Meteor.settings.redis; - - if (inReplyToHTML5Client(arg)) { - const payload = arg.payload; - const meetingId = payload.meeting_id; - const presentations = payload.presentations; - for (let k = 0; k < payload.presentations.length; k++) { - const presentation = presentations[k]; - addPresentationToCollection(meetingId, presentation); - const pages = presentation.pages; - for (let l = 0; l < pages.length; l++) { - const page = pages[l]; - - //add the slide to the collection - addSlideToCollection(meetingId, presentation.id, page); - - //request for shapes - const whiteboardId = `${presentation.id}/${page.num}`; - - //logger.info "the whiteboard_id here is:" + whiteboardId - - const replyTo = `${meetingId}/nodeJSapp`; - let message = { - payload: { - meeting_id: meetingId, - requester_id: 'nodeJSapp', - whiteboard_id: whiteboardId, - reply_to: replyTo, - }, - }; - if (!!whiteboardId && !!meetingId) { - message = appendMessageHeader('request_whiteboard_annotation_history_request', message); - publish(REDIS_CONFIG.channels.toBBBApps.whiteboard, message); - } else { - logger.info('did not have enough information to send a user_leaving_request'); - } - } - } - } - - return arg.callback(); -}); diff --git a/bigbluebutton-html5/imports/api/presentations/server/modifiers/removePresentation.js b/bigbluebutton-html5/imports/api/presentations/server/modifiers/removePresentation.js new file mode 100644 index 0000000000000000000000000000000000000000..5af60c05c38fe2818210111b2d54daa16c65afb8 --- /dev/null +++ b/bigbluebutton-html5/imports/api/presentations/server/modifiers/removePresentation.js @@ -0,0 +1,28 @@ +import { check } from 'meteor/check'; +import Presentations from '/imports/api/presentations'; +import Logger from '/imports/startup/server/logger'; + +import clearSlidesPresentation from '/imports/api/slides/server/modifiers/clearSlidesPresentation'; + +export default function removePresentation(meetingId, presentationId) { + check(meetingId, String); + check(presentationId, String); + + const selector = { + meetingId, + presentationId, + }; + + const cb = (err, numChanged) => { + if (err) { + return Logger.error(`Removing presentation from collection: ${err}`); + } + + if (numChanged) { + clearSlidesPresentation(meetingId, presentationId); + return Logger.info(`Removed presentation id=${presentationId} meeting=${meetingId}`); + } + }; + + return Presentations.remove(selector, cb); +}; diff --git a/bigbluebutton-html5/imports/api/presentations/server/modifiers/removePresentationFromCollection.js b/bigbluebutton-html5/imports/api/presentations/server/modifiers/removePresentationFromCollection.js deleted file mode 100755 index d0c74e774379382db54cfd1f16faacf924ac60ed..0000000000000000000000000000000000000000 --- a/bigbluebutton-html5/imports/api/presentations/server/modifiers/removePresentationFromCollection.js +++ /dev/null @@ -1,17 +0,0 @@ -import Slides from '/imports/api/slides'; -import Presentations from '/imports/api/presentations'; -import { logger } from '/imports/startup/server/logger'; - -export function removePresentationFromCollection(meetingId, presentationId) { - const presentationObject = Presentations.findOne({ - meetingId: meetingId, - 'presentation.id': presentationId, - }); - if (presentationObject != null) { - Slides.remove({ - presentationId: presentationId, - }, logger.info(`cleared Slides Collection (presentationId: ${presentationId}!`)); - Presentations.remove(presentationObject._id); - return logger.info(`----removed presentation[${presentationId}] from ${meetingId}`); - } -}; diff --git a/bigbluebutton-html5/imports/api/presentations/server/publications.js b/bigbluebutton-html5/imports/api/presentations/server/publications.js deleted file mode 100755 index ba6d95022f16969aaae3f2c1f5909d42af44637a..0000000000000000000000000000000000000000 --- a/bigbluebutton-html5/imports/api/presentations/server/publications.js +++ /dev/null @@ -1,10 +0,0 @@ -import Presentations from '/imports/api/presentations'; -import { logger } from '/imports/startup/server/logger'; - -Meteor.publish('presentations', function (credentials) { - const { meetingId } = credentials; - logger.info(`publishing presentations for ${meetingId}`); - return Presentations.find({ - meetingId: meetingId, - }); -}); diff --git a/bigbluebutton-html5/imports/api/presentations/server/publishers.js b/bigbluebutton-html5/imports/api/presentations/server/publishers.js new file mode 100644 index 0000000000000000000000000000000000000000..cd6be803fdd53ced02ccdcd6c9b382df88202d40 --- /dev/null +++ b/bigbluebutton-html5/imports/api/presentations/server/publishers.js @@ -0,0 +1,22 @@ +import { Meteor } from 'meteor/meteor'; +import { check } from 'meteor/check'; +import Presentations from '/imports/api/presentations'; +import Logger from '/imports/startup/server/logger'; +import { isAllowedTo } from '/imports/startup/server/userPermissions'; + +Meteor.publish('presentations', (credentials) => { + // TODO: Some publishers have ACL and others dont + // if (!isAllowedTo('@@@', credentials)) { + // this.error(new Meteor.Error(402, "The user was not authorized to subscribe for 'presentations'")); + // } + + const { meetingId, requesterUserId, requesterToken } = credentials; + + check(meetingId, String); + check(requesterUserId, String); + check(requesterToken, String); + + Logger.info(`Publishing Presentations for ${meetingId} ${requesterUserId} ${requesterToken}`); + + return Presentations.find({ meetingId }); +}); diff --git a/bigbluebutton-html5/imports/api/slides/server/modifiers/addSlideToCollection.js b/bigbluebutton-html5/imports/api/slides/server/modifiers/addSlide.js similarity index 52% rename from bigbluebutton-html5/imports/api/slides/server/modifiers/addSlideToCollection.js rename to bigbluebutton-html5/imports/api/slides/server/modifiers/addSlide.js index 020ae8c8bbf5982e87b505375a48ba77b9b4270c..93b1e0571c72632af2dc9fbfe8abc96381e72e3f 100755 --- a/bigbluebutton-html5/imports/api/slides/server/modifiers/addSlideToCollection.js +++ b/bigbluebutton-html5/imports/api/slides/server/modifiers/addSlide.js @@ -1,12 +1,29 @@ import probe from 'probe-image-size'; +import { Meteor } from 'meteor/meteor'; import { check } from 'meteor/check'; +import RedisPubSub from '/imports/startup/server/redis'; import Slides from '/imports/api/slides'; import Logger from '/imports/startup/server/logger'; import { SVG, PNG } from '/imports/utils/mimeTypes'; +const requestWhiteboardHistory = (meetingId, slideId) => { + const REDIS_CONFIG = Meteor.settings.redis; + const CHANNEL = REDIS_CONFIG.channels.toBBBApps.whiteboard; + const EVENT_NAME = 'request_whiteboard_annotation_history_request'; + + let payload = { + meeting_id: meetingId, + requester_id: 'nodeJSapp', + whiteboard_id: slideId, + reply_to: `${meetingId}/nodeJSapp`, + }; + + return RedisPubSub.publish(CHANNEL, EVENT_NAME, payload); +}; + const SUPPORTED_TYPES = [SVG, PNG]; -export default function addSlideToCollection(meetingId, presentationId, slide) { +export default function addSlide(meetingId, presentationId, slide) { check(meetingId, String); check(presentationId, String); check(slide, Object); @@ -21,9 +38,10 @@ export default function addSlideToCollection(meetingId, presentationId, slide) { const modifier = { $set: { - meetingId: meetingId, - presentationId: presentationId, + meetingId, + presentationId, slide: { + id: slide.id, height_ratio: slide.height_ratio, y_offset: slide.y_offset, num: slide.num, @@ -31,7 +49,6 @@ export default function addSlideToCollection(meetingId, presentationId, slide) { current: slide.current, img_uri: imageUri, txt_uri: slide.txt_uri, - id: slide.id, width_ratio: slide.width_ratio, swf_uri: slide.swf_uri, thumb_uri: slide.thumb_uri, @@ -49,27 +66,37 @@ export default function addSlideToCollection(meetingId, presentationId, slide) { const { insertedId } = numChanged; if (insertedId) { - fetchImageSizes(insertedId, imageUri); - return Logger.info(`Added slide id=${insertedId} to presentation=${presentationId}`); + requestWhiteboardHistory(meetingId, slide.id); + return Logger.info(`Added slide id=${slide.id} to presentation=${presentationId}`); + } + + if (numChanged) { + return Logger.info(`Upserted slide id=${slide.id} to presentation=${presentationId}`); } }; - return Slides.upsert(selector, modifier, cb); + return fetchImageSizes(imageUri) + .then(({ width, height }) => { + modifier.$set.slide.width = width; + modifier.$set.slide.height = height; + + return Slides.upsert(selector, modifier, cb); + }) + .catch(reason => + Logger.error(`Error parsing image size. ${reason}. slide=${slide.id} uri=${imageUri}`)); }; -const fetchImageSizes = (slideId, imageUri) => +const fetchImageSizes = (imageUri) => probe(imageUri) .then(result => { if (!SUPPORTED_TYPES.includes(result.mime)) { throw `Invalid image type, received ${result.mime} expecting ${SUPPORTED_TYPES.join()}`; } - return Slides.update(slideId, { - $set: { - width: result.width, - height: result.height, - }, - }); + return { + width: result.width, + height: result.height, + }; }) .catch(reason => { Logger.error(`Error parsing image size. ${reason}. slide=${slide.id} uri=${imageUri}`); diff --git a/bigbluebutton-html5/imports/api/slides/server/modifiers/changeCurrentSlide.js b/bigbluebutton-html5/imports/api/slides/server/modifiers/changeCurrentSlide.js index f3b6db32e7f5519efc96ea4f4eba50fe4b9b396f..c022d5f042f3952aa34ca579088fad7dd3ea9472 100755 --- a/bigbluebutton-html5/imports/api/slides/server/modifiers/changeCurrentSlide.js +++ b/bigbluebutton-html5/imports/api/slides/server/modifiers/changeCurrentSlide.js @@ -21,7 +21,7 @@ export default function changeCurrentSlide(meetingId, presentationId, slideId) { return Logger.error(`Unsetting the current slide: ${err}`); } - return Logger.info(`Unsetted as current slide`); + return Logger.info(`Unsetted the current slide`); }, }; @@ -47,10 +47,10 @@ export default function changeCurrentSlide(meetingId, presentationId, slideId) { const newSlide = Slides.findOne(newCurrent.selector); if (newSlide) { - Slides.update(newSlide.id, newCurrent.modifier, newCurrent.callback); + Slides.update(newSlide._id, newCurrent.modifier, newCurrent.callback); } if (oldSlide) { - Slides.update(oldSlide.id, oldCurrent.modifier, oldCurrent.callback); + Slides.update(oldSlide._id, oldCurrent.modifier, oldCurrent.callback); } }; diff --git a/bigbluebutton-html5/imports/api/slides/server/modifiers/clearSlidesCollection.js b/bigbluebutton-html5/imports/api/slides/server/modifiers/clearSlides.js similarity index 83% rename from bigbluebutton-html5/imports/api/slides/server/modifiers/clearSlidesCollection.js rename to bigbluebutton-html5/imports/api/slides/server/modifiers/clearSlides.js index 9de4c1f04f7eaee32d3ed2d8edcc3398f1a16da0..868290d952268eff20ea244d83ed90ab40b0e945 100755 --- a/bigbluebutton-html5/imports/api/slides/server/modifiers/clearSlidesCollection.js +++ b/bigbluebutton-html5/imports/api/slides/server/modifiers/clearSlides.js @@ -1,7 +1,7 @@ import Slides from '/imports/api/slides'; import Logger from '/imports/startup/server/logger'; -export default function clearSlidesCollection(meetingId) { +export default function clearSlides(meetingId) { if (meetingId) { return Slides.remove({ meetingId: meetingId }, Logger.info(`Cleared Slides (${meetingId})`)); } else { diff --git a/bigbluebutton-html5/imports/api/slides/server/modifiers/clearSlidesPresentation.js b/bigbluebutton-html5/imports/api/slides/server/modifiers/clearSlidesPresentation.js index ff7be924fec446cf4356bf35dcd730e361321adc..4d65bab039ea40c351c76ca9b9eacdc832db190c 100644 --- a/bigbluebutton-html5/imports/api/slides/server/modifiers/clearSlidesPresentation.js +++ b/bigbluebutton-html5/imports/api/slides/server/modifiers/clearSlidesPresentation.js @@ -2,10 +2,12 @@ import Slides from '/imports/api/slides'; import Logger from '/imports/startup/server/logger'; import { check } from 'meteor/check'; -export default function clearSlidesPresentation(presentationId) { +export default function clearSlidesPresentation(meetingId, presentationId) { + check(meetingId, String); check(presentationId, String); const selector = { + meetingId, presentationId, }; diff --git a/bigbluebutton-html5/imports/api/slides/server/modifiers/resizeSlide.js b/bigbluebutton-html5/imports/api/slides/server/modifiers/resizeSlide.js index 80a5ebed30997dd0f3c26ff1f65d54b8c3b13dd3..6eae4cdc3cd19399e626fff1cf8a7f408e12b00f 100644 --- a/bigbluebutton-html5/imports/api/slides/server/modifiers/resizeSlide.js +++ b/bigbluebutton-html5/imports/api/slides/server/modifiers/resizeSlide.js @@ -17,21 +17,21 @@ export default function resizeSlide(meetingId, presentationId, slideId, slide) { const modifier = { $set: { - slide: { - width_ratio: slide.width_ratio, - height_ratio: slide.height_ratio, - x_offset: slide.x_offset, - y_offset: slide.y_offset, - }, + 'slide.width_ratio': slide.width_ratio, + 'slide.height_ratio': slide.height_ratio, + 'slide.x_offset': slide.x_offset, + 'slide.y_offset': slide.y_offset, }, }; - const cb = (err) => { + const cb = (err, numChanged) => { if (err) { return Logger.error(`Resizing slide id=${slideId}: ${err}`); } - return Logger.info(`Resized slide id=${slideId}`); + if (numChanged) { + return Logger.info(`Resized slide id=${slideId}`); + } }; return Slides.update(selector, modifier, cb); diff --git a/bigbluebutton-html5/imports/api/slides/server/publishers.js b/bigbluebutton-html5/imports/api/slides/server/publishers.js index d1c68318a583b0ced4bedaa1b0f0ca56a5538045..0c121386e08a7fea207a68b57c3d6704338c6689 100644 --- a/bigbluebutton-html5/imports/api/slides/server/publishers.js +++ b/bigbluebutton-html5/imports/api/slides/server/publishers.js @@ -18,5 +18,5 @@ Meteor.publish('slides', (credentials) => { Logger.info(`Publishing Slides for ${meetingId} ${requesterUserId} ${requesterToken}`); - return Slides.find({ meetingId: meetingId }); + return Slides.find({ meetingId }); }); diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/container.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/container.jsx index 09b93f2688622b75473983752470493c4215db92..3f26411e353f320913c7f3fcabfaf8bc6e23535d 100755 --- a/bigbluebutton-html5/imports/ui/components/whiteboard/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/whiteboard/container.jsx @@ -17,7 +17,9 @@ class WhiteboardContainer extends Component { } } -export default createContainer(() => { - const data = WhiteboardService.getWhiteboardData(); - return data; -}, WhiteboardContainer); +export default createContainer(() => ({ + currentSlide: WhiteboardService.getCurrentSlide(), + shapes: WhiteboardService.getCurrentShapes(), + cursor: WhiteboardService.getCurrentCursor(), + userIsPresenter: WhiteboardService.isPresenter(), +}), WhiteboardContainer); diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/service.js b/bigbluebutton-html5/imports/ui/components/whiteboard/service.js index 2bb735ab8207c9a62410f8cd827eca51f5be8d04..9d1b3cc356c76e5f7c3ee51692d3a411f3220131 100755 --- a/bigbluebutton-html5/imports/ui/components/whiteboard/service.js +++ b/bigbluebutton-html5/imports/ui/components/whiteboard/service.js @@ -3,48 +3,47 @@ import Shapes from '/imports/api/shapes'; import Slides from '/imports/api/slides'; import Cursor from '/imports/api/cursor'; import Users from '/imports/api/users'; -import AuthSingleton from '/imports/ui/services/auth/index.js'; - -let getWhiteboardData = () => { - let currentSlide; - let shapes; - let cursor; - let userIsPresenter; - let currentPresentation = Presentations.findOne({ - 'presentation.current': true, - }); - - if (currentPresentation != null) { - currentSlide = Slides.findOne({ - presentationId: currentPresentation.presentation.id, - 'slide.current': true, - }); +import Auth from '/imports/ui/services/auth'; + +const getCurrentPresentation = () => Presentations.findOne({ + 'presentation.current': true, +}); + +const getCurrentSlide = () => { + const currentPresentation = getCurrentPresentation(); + + if (!currentPresentation) { + return null; } - if (currentSlide != null) { - shapes = Shapes.find({ - whiteboardId: currentSlide.slide.id, - }).fetch(); + return Slides.findOne({ + presentationId: currentPresentation.presentation.id, + 'slide.current': true, + }); +}; - cursor = Cursor.findOne({ - meetingId: currentSlide.meetingId, - }); +const getCurrentShapes = () => { + const currentSlide = getCurrentSlide(); - // Get user to check if they are the presenter - userIsPresenter = Users.findOne({ - meetingId: currentSlide.meetingId, - userId: AuthSingleton.getCredentials().requesterUserId, - }).user.presenter; + if (!currentSlide) { + return null; } - return { - currentSlide: currentSlide, - shapes: shapes, - cursor: cursor, - userIsPresenter: userIsPresenter, - }; + return Shapes.find({ + whiteboardId: currentSlide.slide.id, + }).fetch(); }; +const getCurrentCursor = () => Cursor.findOne({}); + +const isPresenter = () => Users.findOne({ + userId: Auth.userID, +}).user.presenter; + export default { - getWhiteboardData, + getCurrentPresentation, + getCurrentSlide, + getCurrentShapes, + getCurrentCursor, + isPresenter, }; diff --git a/bigbluebutton-html5/server/main.js b/bigbluebutton-html5/server/main.js index f0d0eca31a9ce6bde0aacfba78664a7a923b65b8..6d0a06ca788dcd2ab505c32a22fe2cf2b6971d67 100755 --- a/bigbluebutton-html5/server/main.js +++ b/bigbluebutton-html5/server/main.js @@ -24,11 +24,7 @@ import '/imports/api/polls/server/modifiers/clearPollCollection'; import '/imports/api/polls/server/modifiers/updatePollCollection'; import '/imports/api/polls/server/modifiers/eventHandlers'; -import '/imports/api/presentations/server/publications'; -import '/imports/api/presentations/server/modifiers/addPresentationToCollection'; -import '/imports/api/presentations/server/modifiers/clearPresentationsCollection'; -import '/imports/api/presentations/server/modifiers/removePresentationFromCollection'; -import '/imports/api/presentations/server/modifiers/eventHandlers'; +import '/imports/api/presentations/server'; import '/imports/api/shapes/server/publications'; import '/imports/api/shapes/server/modifiers/addShapeToCollection';