Merge pull request #4154 from Klauswk/slides-refactor-2x
[HTML5 2.0] Refactor Code to reflect AkkaApps collections
This commit is contained in:
commit
9252371948
@ -1,8 +1,3 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import mapToAcl from '/imports/startup/mapToAcl';
|
||||
import switchSlide from './methods/switchSlide';
|
||||
|
||||
Meteor.methods(mapToAcl(['methods.switchSlide', 'methods.switchSlideMessage'], {
|
||||
switchSlide,
|
||||
switchSlideMessage: switchSlide, // legacy
|
||||
}));
|
||||
Meteor.methods();
|
||||
|
1
bigbluebutton-html5/imports/api/2.0/annotations/index.js
Executable file
1
bigbluebutton-html5/imports/api/2.0/annotations/index.js
Executable file
@ -0,0 +1 @@
|
||||
export default new Mongo.Collection('annotations');
|
@ -2,7 +2,9 @@ import RedisPubSub from '/imports/startup/server/redis2x';
|
||||
import handleWhiteboardCleared from './handlers/whiteboardCleared';
|
||||
import handleWhiteboardUndo from './handlers/whiteboardUndo';
|
||||
import handleWhiteboardSend from './handlers/whiteboardSend';
|
||||
import handleWhiteboardAnnotations from './handlers/whiteboardAnnotations';
|
||||
|
||||
RedisPubSub.on('ClearWhiteboardEvtMsg', handleWhiteboardCleared);
|
||||
RedisPubSub.on('UndoWhiteboardEvtMsg', handleWhiteboardUndo);
|
||||
RedisPubSub.on('SendWhiteboardAnnotationEvtMsg', handleWhiteboardSend);
|
||||
RedisPubSub.on('GetWhiteboardAnnotationsRespMsg', handleWhiteboardAnnotations);
|
@ -0,0 +1,30 @@
|
||||
import _ from 'lodash';
|
||||
import { check } from 'meteor/check';
|
||||
import Annotations from '/imports/api/2.0/annotations';
|
||||
import addAnnotation from '../modifiers/addAnnotation';
|
||||
import removeAnnotation from '../modifiers/removeAnnotation';
|
||||
|
||||
export default function handleWhiteboardAnnotations({ body }, meetingId) {
|
||||
check(meetingId, String);
|
||||
check(body, Object);
|
||||
|
||||
const { annotations, whiteboardId } = body;
|
||||
const annotationIds = annotations.map(a => a.id);
|
||||
const annotationsToRemove = Annotations.find({
|
||||
meetingId,
|
||||
wbId: whiteboardId,
|
||||
'annotationInfo.id': { $nin: annotationIds },
|
||||
}).fetch();
|
||||
|
||||
_.each(annotationsToRemove, (annotation) => {
|
||||
removeAnnotation(meetingId, annotation.whiteboardId, annotation.annotationInfo.id);
|
||||
});
|
||||
|
||||
const annotationsAdded = [];
|
||||
_.each(annotations, (annotation) => {
|
||||
const { wbId, userId } = annotation;
|
||||
annotationsAdded.push(addAnnotation(meetingId, wbId, userId, annotation));
|
||||
});
|
||||
|
||||
return annotationsAdded;
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
import { check } from 'meteor/check';
|
||||
|
||||
import clearShapesWhiteboard from '../modifiers/clearShapesWhiteboard';
|
||||
import clearAnnotations from '../modifiers/clearAnnotations';
|
||||
|
||||
export default function handleWhiteboardCleared({ body }, meetingId) {
|
||||
const whiteboardId = body.whiteboardId;
|
||||
|
||||
check(whiteboardId, String);
|
||||
|
||||
return clearShapesWhiteboard(meetingId, whiteboardId);
|
||||
return clearAnnotations(meetingId, whiteboardId);
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
import { check } from 'meteor/check';
|
||||
|
||||
import addAnnotation from '../modifiers/addAnnotation';
|
||||
|
||||
export default function handleWhiteboardSend({ header, body }, meetingId) {
|
||||
const userId = header.userId;
|
||||
const annotation = body.annotation;
|
||||
|
||||
check(userId, String);
|
||||
check(annotation, Object);
|
||||
|
||||
const whiteboardId = annotation.wbId;
|
||||
|
||||
check(whiteboardId, String);
|
||||
|
||||
return addAnnotation(meetingId, whiteboardId, userId, annotation);
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import { check } from 'meteor/check';
|
||||
|
||||
import removeShape from '../modifiers/removeShape';
|
||||
import removeAnnotation from '../modifiers/removeAnnotation';
|
||||
|
||||
export default function handleWhiteboardUndo({ body }, meetingId) {
|
||||
const whiteboardId = body.whiteboardId;
|
||||
@ -9,5 +9,5 @@ export default function handleWhiteboardUndo({ body }, meetingId) {
|
||||
check(whiteboardId, String);
|
||||
check(shapeId, String);
|
||||
|
||||
return removeShape(meetingId, whiteboardId, shapeId);
|
||||
return removeAnnotation(meetingId, whiteboardId, shapeId);
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import mapToAcl from '/imports/startup/mapToAcl';
|
||||
|
||||
Meteor.methods();
|
@ -0,0 +1,101 @@
|
||||
import { Match, check } from 'meteor/check';
|
||||
import Logger from '/imports/startup/server/logger';
|
||||
import Annotations from '/imports/api/2.0/annotations';
|
||||
|
||||
const ANNOTATION_TYPE_TEXT = 'text';
|
||||
const ANNOTATION_TYPE_PENCIL = 'pencil';
|
||||
|
||||
export default function addAnnotation(meetingId, whiteboardId, userId, annotation) {
|
||||
check(meetingId, String);
|
||||
check(whiteboardId, String);
|
||||
check(annotation, {
|
||||
id: String,
|
||||
status: String,
|
||||
annotationType: String,
|
||||
annotationInfo: {
|
||||
x: Match.Maybe(Number), // Text Annotation Only.
|
||||
y: Match.Maybe(Number), // Text Annotation Only.
|
||||
text: Match.Maybe(String), // Text Annotation Only.
|
||||
fontColor: Match.Maybe(Number), // Text Annotation Only.
|
||||
calcedFontSize: Match.Maybe(Number), // Text Annotation Only.
|
||||
textBoxWidth: Match.Maybe(Number), // Text Annotation Only.
|
||||
textBoxHeight: Match.Maybe(Number), // Text Annotation Only.
|
||||
fontSize: Match.Maybe(Number), // Text Annotation Only.
|
||||
dataPoints: Match.Maybe(String), // Text Annotation Only.
|
||||
color: Match.Maybe(Number), // Draw Annotation Only.
|
||||
thickness: Match.Maybe(Number), // Draw Annotation Only.
|
||||
transparency: Match.Maybe(Boolean), // Draw Annotation Only.
|
||||
points: Match.Maybe([Number]), // Draw and Poll Annotation Only.
|
||||
numResponders: Match.Maybe(Number), // Poll Only Annotation.
|
||||
result: Match.Maybe([{
|
||||
id: Number,
|
||||
key: String,
|
||||
numVotes: Number,
|
||||
}]), // Poll Only Annotation.
|
||||
numRespondents: Match.Maybe(Number), // Poll Only Annotation.
|
||||
id: String,
|
||||
whiteboardId: String,
|
||||
status: String,
|
||||
type: String,
|
||||
commands: Match.Maybe([Number]),
|
||||
},
|
||||
wbId: String,
|
||||
userId: String,
|
||||
position: Number,
|
||||
});
|
||||
|
||||
const { id, status, annotationType, annotationInfo, wbId, position } = annotation;
|
||||
|
||||
const selector = {
|
||||
meetingId,
|
||||
id: annotation.id,
|
||||
userId,
|
||||
};
|
||||
|
||||
const modifier = {
|
||||
$set: {
|
||||
whiteboardId,
|
||||
meetingId,
|
||||
id,
|
||||
status,
|
||||
annotationType,
|
||||
annotationInfo,
|
||||
wbId,
|
||||
position,
|
||||
},
|
||||
};
|
||||
|
||||
const shapeType = annotation.annotationType;
|
||||
|
||||
switch (shapeType) {
|
||||
case ANNOTATION_TYPE_TEXT:
|
||||
modifier.$set.annotationInfo.text = annotation.annotationInfo.text.replace(/[\r]/g, '\n');
|
||||
break;
|
||||
case ANNOTATION_TYPE_PENCIL:
|
||||
// On the draw_end he send us all the points, we don't need to push, we can simple
|
||||
// set the new points.
|
||||
if (annotation.status !== 'DRAW_END') {
|
||||
// We don't want it to be update twice.
|
||||
delete modifier.$set.annotationInfo;
|
||||
modifier.$push = { 'annotationInfo.points': { $each: annotation.annotationInfo.points } };
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const cb = (err, numChanged) => {
|
||||
if (err) {
|
||||
return Logger.error(`Adding annotation2x to collection: ${err}`);
|
||||
}
|
||||
|
||||
const { insertedId } = numChanged;
|
||||
if (insertedId) {
|
||||
return Logger.info(`Added annotation2x id=${annotation.id} whiteboard=${whiteboardId}`);
|
||||
}
|
||||
|
||||
return Logger.info(`Upserted annotation2x id=${annotation.id} whiteboard=${whiteboardId}`);
|
||||
};
|
||||
|
||||
return Annotations.upsert(selector, modifier, cb);
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
import Annotations from '/imports/api/2.0/annotations';
|
||||
import Logger from '/imports/startup/server/logger';
|
||||
|
||||
export default function clearAnnotations(meetingId, whiteboardId) {
|
||||
if (meetingId && whiteboardId) {
|
||||
return Annotations.remove({ meetingId, whiteboardId }, Logger.info(`Cleared Annotations from whiteboard ${whiteboardId} (${meetingId})`));
|
||||
} else if (meetingId) {
|
||||
return Annotations.remove({ meetingId }, Logger.info(`Cleared Annotations (${meetingId})`));
|
||||
}
|
||||
|
||||
return Annotations.remove({}, Logger.info('Cleared Annotations (all)'));
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
import { check } from 'meteor/check';
|
||||
import Annotations from '/imports/api/2.0/annotations';
|
||||
import Logger from '/imports/startup/server/logger';
|
||||
|
||||
export default function removeAnnotation(meetingId, whiteboardId, shapeId) {
|
||||
check(meetingId, String);
|
||||
check(whiteboardId, String);
|
||||
check(shapeId, String);
|
||||
|
||||
const selector = {
|
||||
meetingId,
|
||||
whiteboardId,
|
||||
id: shapeId,
|
||||
};
|
||||
|
||||
const cb = (err) => {
|
||||
if (err) {
|
||||
return Logger.error(`Removing annotation from collection: ${err}`);
|
||||
}
|
||||
|
||||
return Logger.info(`Removed annotation id=${shapeId} whiteboard=${whiteboardId}`);
|
||||
};
|
||||
|
||||
return Annotations.remove(selector, cb);
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import Annotations from '/imports/api/2.0/annotations';
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { check } from 'meteor/check';
|
||||
import Logger from '/imports/startup/server/logger';
|
||||
import mapToAcl from '/imports/startup/mapToAcl';
|
||||
|
||||
function annotations(credentials) {
|
||||
const { meetingId, requesterUserId, requesterToken } = credentials;
|
||||
|
||||
check(meetingId, String);
|
||||
check(requesterUserId, String);
|
||||
check(requesterToken, String);
|
||||
|
||||
Logger.info(`Publishing Annotations2x for ${meetingId} ${requesterUserId} ${requesterToken}`);
|
||||
|
||||
return Annotations.find({ meetingId });
|
||||
}
|
||||
|
||||
function publish(...args) {
|
||||
const boundAnnotations = annotations.bind(this);
|
||||
return mapToAcl('subscriptions.annotations', boundAnnotations)(args);
|
||||
}
|
||||
|
||||
Meteor.publish('annotations', publish);
|
@ -11,7 +11,7 @@ class BBB {
|
||||
}
|
||||
|
||||
getUsername() {
|
||||
return Users.findOne({ userId: this.getUserId() }).user.name;
|
||||
return Users.findOne({ userId: this.getUserId() }).name;
|
||||
}
|
||||
|
||||
getExtension() {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { check } from 'meteor/check';
|
||||
import Logger from '/imports/startup/server/logger';
|
||||
import Breakouts from '/imports/api/2.0/breakouts';
|
||||
import flat from 'flat';
|
||||
|
||||
export default function addBreakout(breakout) {
|
||||
const {
|
||||
@ -16,11 +17,8 @@ export default function addBreakout(breakout) {
|
||||
const selector = { breakoutMeetingId };
|
||||
|
||||
const modifier = {
|
||||
$set: {
|
||||
breakoutMeetingId,
|
||||
parentId,
|
||||
name,
|
||||
},
|
||||
$set:
|
||||
flat(breakout, { safe: true }),
|
||||
};
|
||||
|
||||
const cb = (err, numChanged) => {
|
||||
|
@ -1,6 +1,4 @@
|
||||
import Logger from '/imports/startup/server/logger';
|
||||
// FIX ME, ADD THIS METHOD TO THE MEETING 2.0
|
||||
import removeMeeting from '/imports/api/1.1/meetings/server/modifiers/removeMeeting';
|
||||
import Breakouts from '/imports/api/2.0/breakouts';
|
||||
|
||||
export default function clearBreakouts(breakoutMeetingId) {
|
||||
@ -9,12 +7,7 @@ export default function clearBreakouts(breakoutMeetingId) {
|
||||
breakoutMeetingId,
|
||||
};
|
||||
|
||||
const cb = () => {
|
||||
Logger.info(`Cleared Breakouts (${breakoutMeetingId})`);
|
||||
removeMeeting(breakoutMeetingId);
|
||||
};
|
||||
|
||||
return Breakouts.remove(selector, cb);
|
||||
return Breakouts.remove(selector);
|
||||
}
|
||||
|
||||
return Breakouts.remove({}, Logger.info('Cleared Breakouts (all)'));
|
||||
|
@ -1,17 +1,26 @@
|
||||
import { check } from 'meteor/check';
|
||||
import { Match, check } from 'meteor/check';
|
||||
import Captions from '/imports/api/2.0/captions';
|
||||
import Logger from '/imports/startup/server/logger';
|
||||
|
||||
export default function addCaption(meetingId, locale, captionHistory, id = false) {
|
||||
check(meetingId, String);
|
||||
check(locale, String);
|
||||
check(captionHistory, Object);
|
||||
|
||||
check(captionHistory, {
|
||||
ownerId: String,
|
||||
index: Number,
|
||||
captions: String,
|
||||
locale: Match.Maybe(String),
|
||||
localeCode: Match.Maybe(String),
|
||||
next: Match.OneOf(Number, undefined, null),
|
||||
});
|
||||
|
||||
const selector = {
|
||||
meetingId,
|
||||
locale,
|
||||
};
|
||||
|
||||
|
||||
if (id) {
|
||||
selector._id = id;
|
||||
} else {
|
||||
@ -22,11 +31,7 @@ export default function addCaption(meetingId, locale, captionHistory, id = false
|
||||
$set: {
|
||||
meetingId,
|
||||
locale,
|
||||
'captionHistory.locale': locale,
|
||||
'captionHistory.ownerId': captionHistory.ownerId,
|
||||
'captionHistory.captions': captionHistory.captions,
|
||||
'captionHistory.next': captionHistory.next,
|
||||
'captionHistory.index': captionHistory.index,
|
||||
captionHistory,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import flat from 'flat';
|
||||
import Chat from '/imports/api/2.0/chat';
|
||||
import Logger from '/imports/startup/server/logger';
|
||||
import { check } from 'meteor/check';
|
||||
import { Match, check } from 'meteor/check';
|
||||
import { BREAK_LINE } from '/imports/utils/lineEndings';
|
||||
|
||||
const parseMessage = (message) => {
|
||||
@ -18,6 +18,17 @@ const parseMessage = (message) => {
|
||||
};
|
||||
|
||||
export default function addChat(meetingId, message) {
|
||||
check(message, {
|
||||
message: String,
|
||||
fromColor: String,
|
||||
toUserId: String,
|
||||
toUsername: String,
|
||||
fromUserId: String,
|
||||
fromUsername: Match.Maybe(String),
|
||||
fromTime: Number,
|
||||
fromTimezoneOffset: Match.Maybe(Number),
|
||||
});
|
||||
|
||||
const parsedMessage = message;
|
||||
parsedMessage.message = parseMessage(message.message);
|
||||
|
||||
@ -27,17 +38,15 @@ export default function addChat(meetingId, message) {
|
||||
check(fromUserId, String);
|
||||
check(toUserId, String);
|
||||
|
||||
const selector = {
|
||||
meetingId,
|
||||
'message.fromTime': parsedMessage.fromTime,
|
||||
'message.fromUserId': parsedMessage.fromUserId,
|
||||
'message.toUserId': parsedMessage.toUserId,
|
||||
};
|
||||
const selector = Object.assign(
|
||||
{ meetingId },
|
||||
flat(message),
|
||||
);
|
||||
|
||||
const modifier = {
|
||||
$set: {
|
||||
meetingId,
|
||||
message: flat(parsedMessage),
|
||||
message: flat(parsedMessage, { safe: true }),
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -7,8 +7,59 @@ import initializeCursor from '/imports/api/1.1/cursor/server/modifiers/initializ
|
||||
export default function addMeeting(meeting) {
|
||||
const meetingId = meeting.meetingProp.intId;
|
||||
|
||||
check(meeting, Object);
|
||||
check(meetingId, String);
|
||||
check(meeting, {
|
||||
breakoutProps: {
|
||||
sequence: Number,
|
||||
breakoutRooms: Array,
|
||||
parentId: String,
|
||||
},
|
||||
meetingProp: {
|
||||
intId: String,
|
||||
extId: String,
|
||||
isBreakout: Boolean,
|
||||
name: String,
|
||||
},
|
||||
usersProp: {
|
||||
webcamsOnlyForModerator: Boolean,
|
||||
guestPolicy: String,
|
||||
maxUsers: Number,
|
||||
},
|
||||
durationProps: {
|
||||
createdTime: Number,
|
||||
duration: Number,
|
||||
createdDate: String,
|
||||
maxInactivityTimeoutMinutes: Number,
|
||||
warnMinutesBeforeMax: Number,
|
||||
meetingExpireIfNoUserJoinedInMinutes: Number,
|
||||
meetingExpireWhenLastUserLeftInMinutes: Number,
|
||||
},
|
||||
welcomeProp: {
|
||||
welcomeMsg: String,
|
||||
modOnlyMessage: String,
|
||||
welcomeMsgTemplate: String,
|
||||
},
|
||||
recordProp: {
|
||||
allowStartStopRecording: Boolean,
|
||||
autoStartRecording: Boolean,
|
||||
record: Boolean,
|
||||
},
|
||||
password: {
|
||||
viewerPass: String,
|
||||
moderatorPass: String,
|
||||
},
|
||||
voiceProp: {
|
||||
voiceConf: String,
|
||||
dialNumber: String,
|
||||
telVoice: String,
|
||||
},
|
||||
screenshareProps: {
|
||||
red5ScreenshareIp: String,
|
||||
red5ScreenshareApp: String,
|
||||
screenshareConf: String,
|
||||
},
|
||||
metadataProp: Object,
|
||||
});
|
||||
|
||||
const selector = {
|
||||
meetingId,
|
||||
@ -17,7 +68,7 @@ export default function addMeeting(meeting) {
|
||||
const modifier = {
|
||||
$set: Object.assign(
|
||||
{ meetingId },
|
||||
flat(meeting),
|
||||
flat(meeting, { safe: true }),
|
||||
),
|
||||
};
|
||||
|
||||
|
@ -4,7 +4,7 @@ import Logger from '/imports/startup/server/logger';
|
||||
import clearUsers from '/imports/api/2.0/users/server/modifiers/clearUsers';
|
||||
import clearChats from '/imports/api/2.0/chat/server/modifiers/clearChats';
|
||||
import clearBreakouts from '/imports/api/2.0/breakouts/server/modifiers/clearBreakouts';
|
||||
import clearShapes from '/imports/api/2.0/shapes/server/modifiers/clearShapes';
|
||||
import clearAnnotations from '/imports/api/2.0/annotations/server/modifiers/clearAnnotations';
|
||||
import clearSlides from '/imports/api/2.0/slides/server/modifiers/clearSlides';
|
||||
import clearPolls from '/imports/api/2.0/polls/server/modifiers/clearPolls';
|
||||
import clearCursor from '/imports/api/2.0/cursor/server/modifiers/clearCursor';
|
||||
@ -20,7 +20,7 @@ export default function removeMeeting(meetingId) {
|
||||
clearPresentations(meetingId);
|
||||
clearBreakouts(meetingId);
|
||||
clearPolls(meetingId);
|
||||
clearShapes(meetingId);
|
||||
clearAnnotations(meetingId);
|
||||
clearSlides(meetingId);
|
||||
clearUsers(meetingId);
|
||||
clearVoiceUsers(meetingId);
|
||||
|
@ -3,7 +3,7 @@ import { check } from 'meteor/check';
|
||||
import Polls from '/imports/api/2.0/polls';
|
||||
import Logger from '/imports/startup/server/logger';
|
||||
|
||||
export default function publishVote(credentials, pollId, pollAnswerId) { // TODO discuss location
|
||||
export default function publishVote(credentials, id, pollAnswerId) { // TODO discuss location
|
||||
const REDIS_CONFIG = Meteor.settings.redis;
|
||||
const CHANNEL = REDIS_CONFIG.channels.toAkkaApps;
|
||||
const EVENT_NAME = 'RespondToPollReqMsg';
|
||||
@ -13,8 +13,8 @@ export default function publishVote(credentials, pollId, pollAnswerId) { // TODO
|
||||
const currentPoll = Polls.findOne({
|
||||
users: requesterUserId,
|
||||
meetingId,
|
||||
'poll.answers.id': pollAnswerId,
|
||||
'poll.id': pollId,
|
||||
'answers.id': pollAnswerId,
|
||||
id,
|
||||
});
|
||||
|
||||
check(meetingId, String);
|
||||
@ -24,7 +24,7 @@ export default function publishVote(credentials, pollId, pollAnswerId) { // TODO
|
||||
|
||||
const payload = {
|
||||
requesterId: requesterUserId,
|
||||
pollId: currentPoll.poll.id,
|
||||
pollId: currentPoll.id,
|
||||
questionId: 0,
|
||||
answerId: pollAnswerId,
|
||||
};
|
||||
@ -38,7 +38,7 @@ export default function publishVote(credentials, pollId, pollAnswerId) { // TODO
|
||||
const selector = {
|
||||
users: requesterUserId,
|
||||
meetingId,
|
||||
'poll.answers.id': pollAnswerId,
|
||||
'answers.id': pollAnswerId,
|
||||
};
|
||||
|
||||
const modifier = {
|
||||
@ -53,7 +53,7 @@ export default function publishVote(credentials, pollId, pollAnswerId) { // TODO
|
||||
}
|
||||
|
||||
return Logger.info(`Updating Polls2x collection (meetingId: ${meetingId},
|
||||
pollId: ${currentPoll.poll.id}!)`);
|
||||
pollId: ${currentPoll.id}!)`);
|
||||
};
|
||||
|
||||
Polls.update(selector, modifier, cb);
|
||||
|
@ -1,40 +1,50 @@
|
||||
import Users from '/imports/api/2.0/users';
|
||||
import Polls from '/imports/api/2.0/polls';
|
||||
import Logger from '/imports/startup/server/logger';
|
||||
import flat from 'flat';
|
||||
import { check } from 'meteor/check';
|
||||
|
||||
export default function addPoll(meetingId, requesterId, poll) {
|
||||
check(poll, Object);
|
||||
check(requesterId, String);
|
||||
check(meetingId, String);
|
||||
|
||||
check(poll, {
|
||||
id: String,
|
||||
answers: [
|
||||
{
|
||||
id: Number,
|
||||
key: String,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
let selector = {
|
||||
meetingId,
|
||||
};
|
||||
|
||||
const options = {
|
||||
fields: {
|
||||
'user.userid': 1,
|
||||
userId: 1,
|
||||
_id: 0,
|
||||
},
|
||||
};
|
||||
|
||||
const userIds = Users.find(selector, options)
|
||||
.fetch()
|
||||
.map(user => user.user.userid);
|
||||
.fetch()
|
||||
.map(user => user.userId);
|
||||
|
||||
selector = {
|
||||
meetingId,
|
||||
requester: requesterId,
|
||||
'poll.id': poll.id,
|
||||
id: poll.id,
|
||||
};
|
||||
|
||||
const modifier = {
|
||||
meetingId,
|
||||
poll,
|
||||
requester: requesterId,
|
||||
users: userIds,
|
||||
};
|
||||
const modifier = Object.assign(
|
||||
{ meetingId },
|
||||
{ requester: requesterId },
|
||||
{ users: userIds },
|
||||
flat(poll, { safe: true }),
|
||||
);
|
||||
|
||||
const cb = (err, numChanged) => {
|
||||
if (err != null) {
|
||||
|
@ -2,13 +2,13 @@ import Polls from '/imports/api/2.0/polls';
|
||||
import { check } from 'meteor/check';
|
||||
import Logger from '/imports/startup/server/logger';
|
||||
|
||||
export default function removePoll(meetingId, pollId) {
|
||||
export default function removePoll(meetingId, id) {
|
||||
check(meetingId, String);
|
||||
check(pollId, String);
|
||||
check(id, String);
|
||||
|
||||
const selector = {
|
||||
meetingId,
|
||||
'poll.id': pollId,
|
||||
id,
|
||||
};
|
||||
|
||||
const cb = (err) => {
|
||||
@ -16,7 +16,7 @@ export default function removePoll(meetingId, pollId) {
|
||||
return Logger.error(`Removing Poll2x from collection: ${err}`);
|
||||
}
|
||||
|
||||
return Logger.info(`Removed Poll2x id=${pollId}`);
|
||||
return Logger.info(`Removed Poll2x id=${id}`);
|
||||
};
|
||||
|
||||
return Polls.remove(selector, cb);
|
||||
|
@ -1,6 +1,7 @@
|
||||
import Polls from '/imports/api/2.0/polls';
|
||||
import { check } from 'meteor/check';
|
||||
import Logger from '/imports/startup/server/logger';
|
||||
import flat from 'flat';
|
||||
|
||||
export default function updateVotes(poll, meetingId, requesterId) {
|
||||
check(meetingId, String);
|
||||
@ -24,19 +25,14 @@ export default function updateVotes(poll, meetingId, requesterId) {
|
||||
const selector = {
|
||||
meetingId,
|
||||
requester: requesterId,
|
||||
'poll.id': id,
|
||||
id,
|
||||
};
|
||||
|
||||
const modifier = {
|
||||
$set: {
|
||||
requester: requesterId,
|
||||
poll: {
|
||||
answers,
|
||||
num_responders: numResponders,
|
||||
num_respondents: numRespondents,
|
||||
id,
|
||||
},
|
||||
},
|
||||
$set: Object.assign(
|
||||
{ requester: requesterId },
|
||||
flat(poll, { safe: true }),
|
||||
),
|
||||
};
|
||||
|
||||
const cb = (err) => {
|
||||
|
@ -8,11 +8,11 @@ const clearCurrentPresentation = (meetingId, presentationId) => {
|
||||
const selector = {
|
||||
meetingId,
|
||||
presentationId: { $ne: presentationId },
|
||||
'presentation.current': true,
|
||||
current: true,
|
||||
};
|
||||
|
||||
const modifier = {
|
||||
$set: { 'presentation.current': false },
|
||||
$set: { current: false },
|
||||
};
|
||||
|
||||
const cb = (err, numChanged) => {
|
||||
|
@ -13,10 +13,10 @@ export default function handlePresentationInfoReply({ body }, meetingId) {
|
||||
|
||||
const presentationsToRemove = Presentations.find({
|
||||
meetingId,
|
||||
'presentation.id': { $nin: presentationsIds },
|
||||
id: { $nin: presentationsIds },
|
||||
}).fetch();
|
||||
|
||||
presentationsToRemove.forEach(p => removePresentation(meetingId, p.presentation.id));
|
||||
presentationsToRemove.forEach(p => removePresentation(meetingId, p.id));
|
||||
|
||||
const presentationsAdded = [];
|
||||
presentations.forEach((presentation) => {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { check } from 'meteor/check';
|
||||
import Presentations from '/imports/api/2.0/presentations';
|
||||
import Logger from '/imports/startup/server/logger';
|
||||
import flat from 'flat';
|
||||
|
||||
import addSlide from '/imports/api/2.0/slides/server/modifiers/addSlide';
|
||||
|
||||
@ -15,21 +16,36 @@ const addSlides = (meetingId, presentationId, slides) => {
|
||||
};
|
||||
|
||||
export default function addPresentation(meetingId, presentation) {
|
||||
check(presentation, Object);
|
||||
check(presentation, {
|
||||
id: String,
|
||||
name: String,
|
||||
current: Boolean,
|
||||
pages: [{
|
||||
id: String,
|
||||
num: Number,
|
||||
thumbUri: String,
|
||||
swfUri: String,
|
||||
txtUri: String,
|
||||
svgUri: String,
|
||||
current: Boolean,
|
||||
xOffset: Number,
|
||||
yOffset: Number,
|
||||
widthRatio: Number,
|
||||
heightRatio: Number,
|
||||
}],
|
||||
downloadable: Boolean,
|
||||
});
|
||||
|
||||
const selector = {
|
||||
meetingId,
|
||||
'presentation.id': presentation.id,
|
||||
id: presentation.id,
|
||||
};
|
||||
|
||||
const modifier = {
|
||||
$set: {
|
||||
meetingId,
|
||||
'presentation.id': presentation.id,
|
||||
'presentation.name': presentation.name,
|
||||
'presentation.current': presentation.current,
|
||||
'presentation.downloadable': presentation.downloadable,
|
||||
},
|
||||
$set: Object.assign(
|
||||
{ meetingId },
|
||||
flat(presentation, { safe: true }),
|
||||
),
|
||||
};
|
||||
|
||||
const cb = (err, numChanged) => {
|
||||
|
@ -9,10 +9,10 @@ export default function changeCurrentPresentation(meetingId, presentationId) {
|
||||
const oldCurrent = {
|
||||
selector: {
|
||||
meetingId,
|
||||
'presentation.current': true,
|
||||
current: true,
|
||||
},
|
||||
modifier: {
|
||||
$set: { 'presentation.current': false },
|
||||
$set: { current: false },
|
||||
},
|
||||
callback: (err) => {
|
||||
if (err) {
|
||||
@ -26,10 +26,10 @@ export default function changeCurrentPresentation(meetingId, presentationId) {
|
||||
const newCurrent = {
|
||||
selector: {
|
||||
meetingId,
|
||||
'presentation.id': presentationId,
|
||||
id: presentationId,
|
||||
},
|
||||
modifier: {
|
||||
$set: { 'presentation.current': true },
|
||||
$set: { current: true },
|
||||
},
|
||||
callback: (err) => {
|
||||
if (err) {
|
||||
|
@ -10,7 +10,7 @@ export default function removePresentation(meetingId, presentationId) {
|
||||
|
||||
const selector = {
|
||||
meetingId,
|
||||
'presentation.id': presentationId,
|
||||
id: presentationId,
|
||||
};
|
||||
|
||||
const cb = (err, numChanged) => {
|
||||
|
@ -1 +0,0 @@
|
||||
export default new Mongo.Collection('shapes2x');
|
@ -1,17 +0,0 @@
|
||||
import { check } from 'meteor/check';
|
||||
|
||||
import addShape from '../modifiers/addShape';
|
||||
|
||||
export default function handleWhiteboardSend({ header, body }, meetingId) {
|
||||
const userId = header.userId;
|
||||
const shape = body.annotation;
|
||||
|
||||
check(userId, String);
|
||||
check(shape, Object);
|
||||
|
||||
const whiteboardId = shape.wbId;
|
||||
|
||||
check(whiteboardId, String);
|
||||
|
||||
return addShape(meetingId, whiteboardId, userId, shape);
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
||||
Meteor.methods({
|
||||
});
|
@ -1,84 +0,0 @@
|
||||
import { check } from 'meteor/check';
|
||||
import Logger from '/imports/startup/server/logger';
|
||||
import Shapes from '/imports/api/2.0/shapes';
|
||||
|
||||
const SHAPE_TYPE_TEXT = 'text';
|
||||
const SHAPE_TYPE_PENCIL = 'pencil';
|
||||
|
||||
export default function addShape(meetingId, whiteboardId, userId, shape) {
|
||||
check(meetingId, String);
|
||||
check(whiteboardId, String);
|
||||
check(shape, Object);
|
||||
|
||||
const selector = {
|
||||
meetingId,
|
||||
'shape.id': shape.id,
|
||||
userId,
|
||||
};
|
||||
|
||||
const modifier = {
|
||||
$set: {
|
||||
userId,
|
||||
meetingId,
|
||||
whiteboardId,
|
||||
'shape.id': shape.id,
|
||||
'shape.wb_id': shape.wbId,
|
||||
'shape.shape_type': shape.annotationType,
|
||||
'shape.status': shape.status,
|
||||
'shape.shape.type': shape.annotationInfo.type,
|
||||
'shape.shape.status': shape.annotationInfo.status,
|
||||
},
|
||||
};
|
||||
|
||||
const shapeType = shape.annotationType;
|
||||
|
||||
switch (shapeType) {
|
||||
case SHAPE_TYPE_TEXT:
|
||||
modifier.$set = Object.assign(modifier.$set, {
|
||||
'shape.shape.x': shape.annotationInfo.x,
|
||||
'shape.shape.y': shape.annotationInfo.y,
|
||||
'shape.shape.fontColor': shape.annotationInfo.fontColor,
|
||||
'shape.shape.calcedFontSize': shape.annotationInfo.calcedFontSize,
|
||||
'shape.shape.textBoxWidth': shape.annotationInfo.textBoxWidth,
|
||||
'shape.shape.text': shape.annotationInfo.text.replace(/[\r]/g, '\n'),
|
||||
'shape.shape.textBoxHeight': shape.annotationInfo.textBoxHeight,
|
||||
'shape.shape.id': shape.annotationInfo.id,
|
||||
'shape.shape.whiteboardId': shape.annotationInfo.whiteboardId,
|
||||
'shape.shape.fontSize': shape.annotationInfo.fontSize,
|
||||
'shape.shape.dataPoints': shape.annotationInfo.dataPoints,
|
||||
});
|
||||
break;
|
||||
case SHAPE_TYPE_PENCIL:
|
||||
modifier.$push = { 'shape.shape.points': { $each: shape.annotationInfo.points } };
|
||||
break;
|
||||
default:
|
||||
modifier.$set = Object.assign(modifier.$set, {
|
||||
'shape.shape.points': shape.annotationInfo.points,
|
||||
'shape.shape.whiteboardId': shape.annotationInfo.whiteboardId,
|
||||
'shape.shape.id': shape.annotationInfo.id,
|
||||
'shape.shape.square': shape.annotationInfo.square,
|
||||
'shape.shape.transparency': shape.annotationInfo.transparency,
|
||||
'shape.shape.thickness': shape.annotationInfo.thickness * 10,
|
||||
'shape.shape.color': shape.annotationInfo.color,
|
||||
'shape.shape.result': shape.annotationInfo.result,
|
||||
'shape.shape.num_respondents': shape.annotationInfo.numRespondents,
|
||||
'shape.shape.num_responders': shape.annotationInfo.numResponders,
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
const cb = (err, numChanged) => {
|
||||
if (err) {
|
||||
return Logger.error(`Adding shape to collection: ${err}`);
|
||||
}
|
||||
|
||||
const { insertedId } = numChanged;
|
||||
if (insertedId) {
|
||||
return Logger.info(`Added shape id=${shape.id} whiteboard=${whiteboardId}`);
|
||||
}
|
||||
|
||||
return Logger.info(`Upserted shape id=${shape.id} whiteboard=${whiteboardId}`);
|
||||
};
|
||||
|
||||
return Shapes.upsert(selector, modifier, cb);
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
import Shapes from '/imports/api/2.0/shapes';
|
||||
import Logger from '/imports/startup/server/logger';
|
||||
|
||||
export default function clearShapes(meetingId) {
|
||||
if (meetingId) {
|
||||
return Shapes.remove({ meetingId }, Logger.info(`Cleared Shapes (${meetingId})`));
|
||||
}
|
||||
|
||||
return Shapes.remove({}, Logger.info('Cleared Shapes (all)'));
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
import Shapes from '/imports/api/2.0/shapes';
|
||||
import Logger from '/imports/startup/server/logger';
|
||||
import { check } from 'meteor/check';
|
||||
|
||||
export default function clearShapesWhiteboard(meetingId, whiteboardId) {
|
||||
check(meetingId, String);
|
||||
check(whiteboardId, String);
|
||||
|
||||
const selector = {
|
||||
meetingId,
|
||||
whiteboardId,
|
||||
};
|
||||
|
||||
const cb = (err) => {
|
||||
if (err) {
|
||||
return Logger.error(`Removing Shapes2x from collection: ${err}`);
|
||||
}
|
||||
|
||||
return Logger.info(`Removed Shapes2x where whiteboard=${whiteboardId}`);
|
||||
};
|
||||
|
||||
return Shapes.remove(selector, cb);
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
import { check } from 'meteor/check';
|
||||
import Shapes from '/imports/api/2.0/shapes';
|
||||
import Logger from '/imports/startup/server/logger';
|
||||
|
||||
export default function removeShape(meetingId, whiteboardId, shapeId) {
|
||||
check(meetingId, String);
|
||||
check(whiteboardId, String);
|
||||
check(shapeId, String);
|
||||
|
||||
const selector = {
|
||||
meetingId,
|
||||
whiteboardId,
|
||||
'shape.id': shapeId,
|
||||
};
|
||||
|
||||
const cb = (err) => {
|
||||
if (err) {
|
||||
return Logger.error(`Removing shape2x from collection: ${err}`);
|
||||
}
|
||||
|
||||
return Logger.info(`Removed shape2x id=${shapeId} whiteboard=${whiteboardId}`);
|
||||
};
|
||||
|
||||
return Shapes.remove(selector, cb);
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
import Shapes from '/imports/api/2.0/shapes';
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { check } from 'meteor/check';
|
||||
import Logger from '/imports/startup/server/logger';
|
||||
import mapToAcl from '/imports/startup/mapToAcl';
|
||||
|
||||
function shapes(credentials) {
|
||||
const { meetingId, requesterUserId, requesterToken } = credentials;
|
||||
|
||||
check(meetingId, String);
|
||||
check(requesterUserId, String);
|
||||
check(requesterToken, String);
|
||||
|
||||
Logger.info(`Publishing Shapes2x for ${meetingId} ${requesterUserId} ${requesterToken}`);
|
||||
|
||||
return Shapes.find({ meetingId });
|
||||
}
|
||||
|
||||
function publish(...args) {
|
||||
const boundShapes = shapes.bind(this);
|
||||
return mapToAcl('subscriptions.shapes', boundShapes)(args);
|
||||
}
|
||||
|
||||
Meteor.publish('shapes2x', publish);
|
@ -2,7 +2,6 @@ import { Meteor } from 'meteor/meteor';
|
||||
import mapToAcl from '/imports/startup/mapToAcl';
|
||||
import switchSlide from './methods/switchSlide';
|
||||
|
||||
Meteor.methods(mapToAcl(['methods.switchSlide', 'methods.switchSlideMessage'], {
|
||||
// switchSlide,
|
||||
// switchSlideMessage: switchSlide, // legacy
|
||||
Meteor.methods(mapToAcl(['methods.switchSlide'], {
|
||||
switchSlide,
|
||||
}));
|
||||
|
@ -7,8 +7,8 @@ import RedisPubSub from '/imports/startup/server/redis2x';
|
||||
export default function switchSlide(credentials, slideNumber) {
|
||||
const REDIS_CONFIG = Meteor.settings.redis;
|
||||
|
||||
const CHANNEL = REDIS_CONFIG.channels.toBBBApps.presentation;
|
||||
const EVENT_NAME = 'go_to_slide';
|
||||
const CHANNEL = REDIS_CONFIG.channels.toAkkaApps;
|
||||
const EVENT_NAME = 'SetCurrentPagePubMsg';
|
||||
|
||||
const { meetingId, requesterUserId, requesterToken } = credentials;
|
||||
|
||||
@ -17,10 +17,12 @@ export default function switchSlide(credentials, slideNumber) {
|
||||
check(requesterToken, String);
|
||||
check(slideNumber, Number);
|
||||
|
||||
const Presentation = Presentations.findOne({
|
||||
const selector = {
|
||||
meetingId,
|
||||
'presentation.current': true,
|
||||
});
|
||||
current: true,
|
||||
};
|
||||
|
||||
const Presentation = Presentations.findOne(selector);
|
||||
|
||||
if (!Presentation) {
|
||||
throw new Meteor.Error(
|
||||
@ -29,8 +31,8 @@ export default function switchSlide(credentials, slideNumber) {
|
||||
|
||||
const Slide = Slides.findOne({
|
||||
meetingId,
|
||||
presentationId: Presentation.presentation.id,
|
||||
'slide.num': parseInt(slideNumber, 2),
|
||||
presentationId: Presentation.id,
|
||||
num: slideNumber,
|
||||
});
|
||||
|
||||
if (!Slide) {
|
||||
@ -38,10 +40,12 @@ export default function switchSlide(credentials, slideNumber) {
|
||||
'slide-not-found', `Slide number ${slideNumber} not found in the current presentation`);
|
||||
}
|
||||
|
||||
const header = { name: EVENT_NAME, meetingId, userId: requesterUserId };
|
||||
|
||||
const payload = {
|
||||
page: Slide.slide.id,
|
||||
meeting_id: meetingId,
|
||||
pageId: Slide.id,
|
||||
presentationId: Presentation.id,
|
||||
};
|
||||
|
||||
return RedisPubSub.publish(CHANNEL, EVENT_NAME, payload);
|
||||
return RedisPubSub.publish(CHANNEL, EVENT_NAME, meetingId, payload, header);
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import probe from 'probe-image-size';
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { check } from 'meteor/check';
|
||||
import flat from 'flat';
|
||||
import RedisPubSub from '/imports/startup/server/redis2x';
|
||||
import Slides from '/imports/api/2.0/slides';
|
||||
import Logger from '/imports/startup/server/logger';
|
||||
@ -8,17 +9,16 @@ 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';
|
||||
const CHANNEL = REDIS_CONFIG.channels.toAkkaApps;
|
||||
const EVENT_NAME = 'GetWhiteboardAnnotationsReqMsg';
|
||||
|
||||
const header = { name: EVENT_NAME, meetingId, userId: 'nodeJSapp' };
|
||||
|
||||
const payload = {
|
||||
meeting_id: meetingId,
|
||||
requester_id: 'nodeJSapp',
|
||||
whiteboard_id: slideId,
|
||||
reply_to: `${meetingId}/nodeJSapp`,
|
||||
whiteboardId: slideId,
|
||||
};
|
||||
|
||||
return RedisPubSub.publish(CHANNEL, EVENT_NAME, payload);
|
||||
return RedisPubSub.publish(CHANNEL, EVENT_NAME, meetingId, payload, header);
|
||||
};
|
||||
|
||||
const SUPPORTED_TYPES = [SVG, PNG];
|
||||
@ -42,39 +42,35 @@ const fetchImageSizes = imageUri =>
|
||||
|
||||
export default function addSlide(meetingId, presentationId, slide) {
|
||||
check(presentationId, String);
|
||||
check(slide, Object);
|
||||
|
||||
check(slide, {
|
||||
id: String,
|
||||
num: Number,
|
||||
thumbUri: String,
|
||||
swfUri: String,
|
||||
txtUri: String,
|
||||
svgUri: String,
|
||||
current: Boolean,
|
||||
xOffset: Number,
|
||||
yOffset: Number,
|
||||
widthRatio: Number,
|
||||
heightRatio: Number,
|
||||
});
|
||||
|
||||
const selector = {
|
||||
meetingId,
|
||||
presentationId,
|
||||
'slide.id': slide.id,
|
||||
id: slide.id,
|
||||
};
|
||||
|
||||
const imageUri = slide.svgUri || slide.pngUri;
|
||||
|
||||
const modifier = {
|
||||
$set: {
|
||||
meetingId,
|
||||
presentationId,
|
||||
slide: {
|
||||
id: slide.id,
|
||||
num: slide.num,
|
||||
thumb_uri: slide.thumbUri,
|
||||
swf_uri: slide.swfUri,
|
||||
txt_uri: slide.txtUri,
|
||||
// svgUri or pngUri is represented by imageUri
|
||||
current: slide.current,
|
||||
x_offset: slide.xOffset,
|
||||
y_offset: slide.yOffset,
|
||||
width_ratio: slide.widthRatio,
|
||||
height_ratio: slide.heightRatio,
|
||||
img_uri: imageUri,
|
||||
|
||||
// width and height are additionally calculated, they are not received
|
||||
width: slide.width,
|
||||
height: slide.height,
|
||||
},
|
||||
},
|
||||
$set: Object.assign(
|
||||
{ meetingId },
|
||||
{ presentationId },
|
||||
flat(slide, { safe: true }),
|
||||
),
|
||||
};
|
||||
|
||||
const cb = (err, numChanged) => {
|
||||
@ -90,15 +86,13 @@ export default function addSlide(meetingId, presentationId, slide) {
|
||||
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 Logger.info(`Upserted slide id=${slide.id} to presentation=${presentationId}`);
|
||||
};
|
||||
|
||||
return fetchImageSizes(imageUri)
|
||||
.then(({ width, height }) => {
|
||||
modifier.$set.slide.width = width;
|
||||
modifier.$set.slide.height = height;
|
||||
modifier.$set.width = width;
|
||||
modifier.$set.height = height;
|
||||
|
||||
return Slides.upsert(selector, modifier, cb);
|
||||
})
|
||||
|
@ -11,10 +11,10 @@ export default function changeCurrentSlide(meetingId, presentationId, slideId) {
|
||||
selector: {
|
||||
meetingId,
|
||||
presentationId,
|
||||
'slide.current': true,
|
||||
current: true,
|
||||
},
|
||||
modifier: {
|
||||
$set: { 'slide.current': false },
|
||||
$set: { current: false },
|
||||
},
|
||||
callback: (err) => {
|
||||
if (err) {
|
||||
@ -29,10 +29,10 @@ export default function changeCurrentSlide(meetingId, presentationId, slideId) {
|
||||
selector: {
|
||||
meetingId,
|
||||
presentationId,
|
||||
'slide.id': slideId,
|
||||
id: slideId,
|
||||
},
|
||||
modifier: {
|
||||
$set: { 'slide.current': true },
|
||||
$set: { current: true },
|
||||
},
|
||||
callback: (err) => {
|
||||
if (err) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import Slides from '/imports/api/2.0/slides';
|
||||
import Logger from '/imports/startup/server/logger';
|
||||
import { check } from 'meteor/check';
|
||||
import clearShapesWhiteboard from '/imports/api/2.0/shapes/server/modifiers/clearShapesWhiteboard';
|
||||
import clearAnnotations from '/imports/api/2.0/annotations/server/modifiers/clearAnnotations';
|
||||
|
||||
export default function clearSlidesPresentation(meetingId, presentationId) {
|
||||
check(meetingId, String);
|
||||
@ -12,18 +12,16 @@ export default function clearSlidesPresentation(meetingId, presentationId) {
|
||||
presentationId,
|
||||
};
|
||||
|
||||
const whiteboardIds = Slides.find(selector).map(row => row.slide.id);
|
||||
const whiteboardIds = Slides.find(selector).map(row => row.id);
|
||||
|
||||
const cb = (err, numChanged) => {
|
||||
const cb = (err) => {
|
||||
if (err) {
|
||||
return Logger.error(`Removing Slides from collection: ${err}`);
|
||||
}
|
||||
|
||||
if (numChanged) {
|
||||
whiteboardIds.forEach(whiteboardId => clearShapesWhiteboard(meetingId, whiteboardId));
|
||||
whiteboardIds.forEach(whiteboardId => clearAnnotations(meetingId, whiteboardId));
|
||||
|
||||
return Logger.info(`Removed Slides where presentationId=${presentationId}`);
|
||||
}
|
||||
return Logger.info(`Removed Slides where presentationId=${presentationId}`);
|
||||
};
|
||||
|
||||
return Slides.remove(selector, cb);
|
||||
|
@ -6,20 +6,20 @@ export default function resizeSlide(meetingId, slide) {
|
||||
check(meetingId, String);
|
||||
|
||||
const { presentationId } = slide;
|
||||
const { pageId } = slide;
|
||||
const { pageId, widthRatio, heightRatio, xOffset, yOffset } = slide;
|
||||
|
||||
const selector = {
|
||||
meetingId,
|
||||
presentationId,
|
||||
'slide.id': pageId,
|
||||
id: pageId,
|
||||
};
|
||||
|
||||
const modifier = {
|
||||
$set: {
|
||||
'slide.width_ratio': slide.widthRatio,
|
||||
'slide.height_ratio': slide.heightRatio,
|
||||
'slide.x_offset': slide.xOffset,
|
||||
'slide.y_offset': slide.yOffset,
|
||||
widthRatio,
|
||||
heightRatio,
|
||||
xOffset,
|
||||
yOffset,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -15,8 +15,8 @@ export default function handleEmojiStatus({ body }, meetingId) {
|
||||
|
||||
const modifier = {
|
||||
$set: {
|
||||
'user.set_emoji_time': (new Date()).getTime(),
|
||||
'user.emoji': emoji,
|
||||
emojiTime: (new Date()).getTime(),
|
||||
emoji,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -6,15 +6,15 @@ const unassignCurrentPresenter = (meetingId, presenterId) => {
|
||||
const selector = {
|
||||
meetingId,
|
||||
userId: { $ne: presenterId },
|
||||
'user.presenter': true,
|
||||
presenter: true,
|
||||
};
|
||||
|
||||
const modifier = {
|
||||
$set: {
|
||||
'user.presenter': false,
|
||||
presenter: false,
|
||||
},
|
||||
$pop: {
|
||||
'user.roles': 'presenter',
|
||||
roles: 'presenter',
|
||||
},
|
||||
};
|
||||
|
||||
@ -41,10 +41,10 @@ export default function handlePresenterAssigned({ body }, meetingId) {
|
||||
|
||||
const modifier = {
|
||||
$set: {
|
||||
'user.presenter': true,
|
||||
presenter: true,
|
||||
},
|
||||
$push: {
|
||||
'user.roles': 'presenter',
|
||||
roles: 'presenter',
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -33,7 +33,7 @@ export default function assignPresenter(credentials, userId) {
|
||||
|
||||
const payload = {
|
||||
newPresenterId: userId,
|
||||
newPresenterName: User.user.name,
|
||||
newPresenterName: User.name,
|
||||
assignedBy: requesterUserId,
|
||||
requesterId: requesterUserId,
|
||||
};
|
||||
|
@ -28,7 +28,7 @@ export default function userLeaving(credentials, userId) {
|
||||
'user-not-found', `Could not find ${userId} in ${meetingId}: cannot complete userLeaving`);
|
||||
}
|
||||
|
||||
if (User.user.connection_status === OFFLINE_CONNECTION_STATUS) {
|
||||
if (User.connectionStatus === OFFLINE_CONNECTION_STATUS) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,26 @@
|
||||
import { check } from 'meteor/check';
|
||||
import Logger from '/imports/startup/server/logger';
|
||||
import Users from '/imports/api/2.0/users';
|
||||
import flat from 'flat';
|
||||
import addVoiceUser from '/imports/api/2.0/voice-users/server/modifiers/addVoiceUser';
|
||||
|
||||
export default function addUser(meetingId, user) {
|
||||
check(user, Object);
|
||||
check(meetingId, String);
|
||||
|
||||
check(user, {
|
||||
intId: String,
|
||||
extId: String,
|
||||
name: String,
|
||||
role: String,
|
||||
guest: Boolean,
|
||||
authed: Boolean,
|
||||
waitingForAcceptance: Boolean,
|
||||
emoji: String,
|
||||
presenter: Boolean,
|
||||
locked: Boolean,
|
||||
avatar: String,
|
||||
});
|
||||
|
||||
const userId = user.intId;
|
||||
check(userId, String);
|
||||
|
||||
@ -42,23 +56,13 @@ export default function addUser(meetingId, user) {
|
||||
userRoles = userRoles.filter(Boolean);
|
||||
|
||||
const modifier = {
|
||||
$set: {
|
||||
meetingId,
|
||||
userId,
|
||||
'user.connection_status': 'online',
|
||||
'user.userid': userId,
|
||||
'user.extId': user.extId,
|
||||
'user.role': user.role,
|
||||
'user.roles': userRoles,
|
||||
'user.name': user.name,
|
||||
'user._sort_name': user.name.trim().toLowerCase(),
|
||||
'user.avatarURL': user.avatar,
|
||||
'user.set_emoji_time': user.set_emoji_time || (new Date()).getTime(),
|
||||
'user.joiningTime': (new Date()).getTime(),
|
||||
'user.emoji': user.emoji,
|
||||
'user.presenter': user.presenter,
|
||||
'user.locked': user.locked,
|
||||
},
|
||||
$set: Object.assign(
|
||||
{ meetingId },
|
||||
{ connectionStatus: 'online' },
|
||||
{ roles: userRoles },
|
||||
{ sortName: user.name.trim().toLowerCase() },
|
||||
flat(user),
|
||||
),
|
||||
};
|
||||
|
||||
addVoiceUser(meetingId, {
|
||||
|
@ -16,12 +16,12 @@ export default function removeUser(meetingId, userId) {
|
||||
|
||||
const modifier = {
|
||||
$set: {
|
||||
'user.connection_status': 'offline',
|
||||
'user.time_of_joining': 0,
|
||||
'user.validated': false,
|
||||
'user.emoji': 'none',
|
||||
'user.presenter': false,
|
||||
'user.role': 'VIEWER',
|
||||
connectionStatus: 'offline',
|
||||
listenOnly: false,
|
||||
validated: false,
|
||||
emoji: 'none',
|
||||
presenter: false,
|
||||
role: 'VIEWER',
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -22,7 +22,7 @@ export default function setConnectionStatus(meetingId, userId, status = 'online'
|
||||
|
||||
const modifier = {
|
||||
$set: {
|
||||
'user.connection_status': status,
|
||||
connectionStatus: status,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -52,7 +52,7 @@ export class Acl {
|
||||
const containRole = Acl.containsRole(user);
|
||||
|
||||
if (containRole) {
|
||||
const roles = user.user.roles;
|
||||
const roles = user.roles;
|
||||
let permissions = {};
|
||||
|
||||
roles.forEach((role) => {
|
||||
@ -66,7 +66,6 @@ export class Acl {
|
||||
|
||||
static containsRole(user) {
|
||||
return Match.test(user, Object) &&
|
||||
Match.test(user.user, Object) &&
|
||||
Match.test(user.user.roles, Array);
|
||||
Match.test(user.roles, Array);
|
||||
}
|
||||
}
|
||||
|
@ -87,9 +87,7 @@ Base.propTypes = propTypes;
|
||||
Base.defaultProps = defaultProps;
|
||||
|
||||
const SUBSCRIPTIONS_NAME = [
|
||||
'users2x', 'users', 'chat', 'chat2x', 'cursor', 'cursor2x', 'screenshare', 'meetings', 'meetings2x',
|
||||
'polls', 'polls2x', 'presentations', 'presentations2x', 'shapes', 'shapes2x', 'slides', 'slides2x', 'captions',
|
||||
'captions2x', 'breakouts', 'breakouts2x', 'voiceUsers',
|
||||
'users2x', 'chat2x', 'cursor2x', 'meetings2x', 'polls2x', 'presentations2x', 'annotations', 'slides2x', 'captions2x', 'breakouts2x', 'voiceUsers',
|
||||
];
|
||||
|
||||
const BaseContainer = createContainer(({ params }) => {
|
||||
|
@ -11,7 +11,7 @@ const getEmojiData = () => {
|
||||
const userEmojiStatus = Users.findOne({
|
||||
meetingId: Auth.meetingID,
|
||||
userId: Auth.userID,
|
||||
}).user.emoji;
|
||||
}).emoji;
|
||||
|
||||
return {
|
||||
userEmojiStatus,
|
||||
|
@ -4,7 +4,7 @@ import Users from '/imports/api/2.0/users';
|
||||
|
||||
const isUserPresenter = () => Users.findOne({
|
||||
userId: Auth.userID,
|
||||
}).user.presenter;
|
||||
}).presenter;
|
||||
|
||||
export default {
|
||||
isUserPresenter,
|
||||
|
@ -6,7 +6,7 @@ import Meetings from '/imports/api/2.0/meetings';
|
||||
const init = () => {
|
||||
const userId = Auth.userID;
|
||||
const User = Users.findOne({ userId });
|
||||
const username = User.user.name;
|
||||
const username = User.name;
|
||||
const Meeting = Meetings.findOne({ meetingId: User.meetingId });
|
||||
const voiceBridge = Meeting.voiceProp.voiceConf;
|
||||
|
||||
|
@ -30,7 +30,7 @@ const getUser = (userID) => {
|
||||
return null;
|
||||
}
|
||||
|
||||
return mapUser(user.user);
|
||||
return mapUser(user);
|
||||
};
|
||||
|
||||
const mapMessage = (messagePayload) => {
|
||||
|
@ -3,7 +3,7 @@ import { isVideoBroadcasting } from '/imports/ui/components/screenshare/service'
|
||||
|
||||
const getPresentationInfo = () => {
|
||||
const currentPresentation = Presentations.findOne({
|
||||
'presentation.current': true,
|
||||
current: true,
|
||||
});
|
||||
|
||||
return {
|
||||
|
@ -7,12 +7,12 @@ const mapPolls = function () {
|
||||
return { pollExists: false };
|
||||
}
|
||||
|
||||
const amIRequester = poll.requester != 'userId';
|
||||
const amIRequester = poll.requester !== 'userId';
|
||||
|
||||
return {
|
||||
poll: {
|
||||
answers: poll.poll.answers,
|
||||
pollId: poll.poll.id,
|
||||
answers: poll.answers,
|
||||
pollId: poll.id,
|
||||
},
|
||||
pollExists: true,
|
||||
amIRequester,
|
||||
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import CSSTransitionGroup from 'react-transition-group/CSSTransitionGroup';
|
||||
import PollingContainer from '/imports/ui/components/polling/container';
|
||||
import ShapeGroupContainer from '../whiteboard/shape-group/container';
|
||||
import AnnotationGroupContainer from '../whiteboard/annotation-group/container';
|
||||
import Cursor from './cursor/component';
|
||||
import PresentationToolbarContainer from './presentation-toolbar/container';
|
||||
import Slide from './slide/component';
|
||||
@ -17,11 +17,11 @@ export default class PresentationArea extends React.Component {
|
||||
let slideObj = this.props.currentSlide;
|
||||
|
||||
if (this.props.currentSlide) {
|
||||
slideObj = this.props.currentSlide.slide;
|
||||
const x = -slideObj.x_offset * 2 * slideObj.width / 100;
|
||||
const y = -slideObj.y_offset * 2 * slideObj.height / 100;
|
||||
const viewBoxWidth = slideObj.width * slideObj.width_ratio / 100;
|
||||
const viewBoxHeight = slideObj.height * slideObj.height_ratio / 100;
|
||||
slideObj = this.props.currentSlide;
|
||||
const x = -slideObj.xOffset * 2 * slideObj.width / 100;
|
||||
const y = -slideObj.yOffset * 2 * slideObj.height / 100;
|
||||
const viewBoxWidth = slideObj.width * slideObj.widthRatio / 100;
|
||||
const viewBoxHeight = slideObj.height * slideObj.heightRatio / 100;
|
||||
return (
|
||||
<CSSTransitionGroup
|
||||
transitionName={{
|
||||
@ -54,7 +54,7 @@ export default class PresentationArea extends React.Component {
|
||||
</defs>
|
||||
<g clipPath="url(#viewBox)">
|
||||
<Slide id="slideComponent" currentSlide={this.props.currentSlide} />
|
||||
<ShapeGroupContainer
|
||||
<AnnotationGroupContainer
|
||||
width={slideObj.width}
|
||||
height={slideObj.height}
|
||||
whiteboardId={slideObj.id}
|
||||
@ -65,7 +65,7 @@ export default class PresentationArea extends React.Component {
|
||||
viewBoxHeight={viewBoxHeight}
|
||||
viewBoxX={x}
|
||||
viewBoxY={y}
|
||||
widthRatio={slideObj.width_ratio}
|
||||
widthRatio={slideObj.widthRatio}
|
||||
cursorX={this.props.cursor.x}
|
||||
cursorY={this.props.cursor.y}
|
||||
/>
|
||||
@ -82,7 +82,7 @@ export default class PresentationArea extends React.Component {
|
||||
if (this.props.currentSlide) {
|
||||
return (
|
||||
<PresentationToolbarContainer
|
||||
currentSlideNum={this.props.currentSlide.slide.num}
|
||||
currentSlideNum={this.props.currentSlide.num}
|
||||
presentationId={this.props.currentSlide.presentationId}
|
||||
/>
|
||||
);
|
||||
|
@ -4,7 +4,7 @@ import Slides from '/imports/api/2.0/slides';
|
||||
import { makeCall } from '/imports/ui/services/api';
|
||||
|
||||
const getSlideData = (params) => {
|
||||
const { currentSlideNum, presentationId } = params;
|
||||
const { presentationId } = params;
|
||||
|
||||
// Get userId and meetingId
|
||||
const userId = AuthSingleton.userID;
|
||||
@ -17,8 +17,8 @@ const getSlideData = (params) => {
|
||||
});
|
||||
|
||||
let userIsPresenter;
|
||||
if (currentUser && currentUser.user) {
|
||||
userIsPresenter = currentUser.user.presenter;
|
||||
if (currentUser) {
|
||||
userIsPresenter = currentUser.presenter;
|
||||
}
|
||||
|
||||
// Get total number of slides in this presentation
|
||||
@ -35,19 +35,19 @@ const getSlideData = (params) => {
|
||||
|
||||
const previousSlide = (currentSlideNum) => {
|
||||
if (currentSlideNum > 1) {
|
||||
makeCall('switchSlideMessage', currentSlideNum - 1);
|
||||
makeCall('switchSlide', currentSlideNum - 1);
|
||||
}
|
||||
};
|
||||
|
||||
const nextSlide = (currentSlideNum, numberOfSlides) => {
|
||||
if (currentSlideNum < numberOfSlides) {
|
||||
makeCall('switchSlideMessage', currentSlideNum + 1);
|
||||
makeCall('switchSlide', currentSlideNum + 1);
|
||||
}
|
||||
};
|
||||
|
||||
const skipToSlide = (event) => {
|
||||
const requestedSlideNum = parseInt(event.target.value);
|
||||
makeCall('switchSlideMessage', requestedSlideNum);
|
||||
makeCall('switchSlide', requestedSlideNum);
|
||||
};
|
||||
|
||||
export default {
|
||||
|
@ -5,7 +5,7 @@ import Users from '/imports/api/2.0/users';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
|
||||
const getCurrentPresentation = () => Presentations.findOne({
|
||||
'presentation.current': true,
|
||||
current: true,
|
||||
});
|
||||
|
||||
const getCurrentSlide = () => {
|
||||
@ -16,8 +16,8 @@ const getCurrentSlide = () => {
|
||||
}
|
||||
|
||||
return Slides.findOne({
|
||||
presentationId: currentPresentation.presentation.id,
|
||||
'slide.current': true,
|
||||
presentationId: currentPresentation.id,
|
||||
current: true,
|
||||
});
|
||||
};
|
||||
|
||||
@ -26,8 +26,8 @@ const getCurrentCursor = () => Cursor.findOne({});
|
||||
const isPresenter = () => {
|
||||
const currentUser = Users.findOne({ userId: Auth.userID });
|
||||
|
||||
if (currentUser && currentUser.user) {
|
||||
return currentUser.user.presenter;
|
||||
if (currentUser) {
|
||||
return currentUser.presenter;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -7,6 +7,9 @@ export default class Slide extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
const imageUri = this.props.currentSlide.svgUri || this.props.currentSlide.pngUri;
|
||||
|
||||
return (
|
||||
<g>
|
||||
{this.props.currentSlide ?
|
||||
@ -14,19 +17,20 @@ export default class Slide extends React.Component {
|
||||
<rect
|
||||
x="0"
|
||||
y="0"
|
||||
width={this.props.currentSlide.slide.width}
|
||||
height={this.props.currentSlide.slide.height}
|
||||
width={this.props.currentSlide.width}
|
||||
height={this.props.currentSlide.height}
|
||||
fill="white"
|
||||
/>
|
||||
<image
|
||||
x="0" y="0"
|
||||
width={this.props.currentSlide.slide.width}
|
||||
height={this.props.currentSlide.slide.height}
|
||||
xlinkHref={this.props.currentSlide.slide.img_uri}
|
||||
x="0"
|
||||
y="0"
|
||||
width={this.props.currentSlide.width}
|
||||
height={this.props.currentSlide.height}
|
||||
xlinkHref={imageUri}
|
||||
strokeWidth="0.8"
|
||||
/>
|
||||
</g>
|
||||
: null }
|
||||
: null}
|
||||
</g>
|
||||
);
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ const getClosedCaptionLocales = () => {
|
||||
const getUserRoles = () => {
|
||||
const user = Users.findOne({
|
||||
userId: Auth.userID,
|
||||
}).user;
|
||||
});
|
||||
|
||||
return user.role;
|
||||
};
|
||||
|
@ -133,20 +133,19 @@ const sortChats = (a, b) => {
|
||||
};
|
||||
|
||||
const userFindSorting = {
|
||||
'user.set_emoji_time': 1,
|
||||
'user.role': 1,
|
||||
'user.phone_user': 1,
|
||||
'user._sort_name': 1,
|
||||
'user.userid': 1,
|
||||
emojiTime: 1,
|
||||
role: 1,
|
||||
phoneUser: 1,
|
||||
sortName: 1,
|
||||
userId: 1,
|
||||
};
|
||||
|
||||
const getUsers = () => {
|
||||
const users = Users
|
||||
.find({ 'user.connection_status': 'online' }, userFindSorting)
|
||||
.find({ connectionStatus: 'online' }, userFindSorting)
|
||||
.fetch();
|
||||
|
||||
return users
|
||||
.map(u => u.user)
|
||||
.map(mapUser)
|
||||
.sort(sortUsers);
|
||||
};
|
||||
@ -164,8 +163,7 @@ const getOpenChats = (chatID) => {
|
||||
openChats = _.uniq(openChats);
|
||||
|
||||
openChats = Users
|
||||
.find({ 'user.userid': { $in: openChats } })
|
||||
.map(u => u.user)
|
||||
.find({ userId: { $in: openChats } })
|
||||
.map(mapUser)
|
||||
.map((op) => {
|
||||
const openChat = op;
|
||||
@ -207,9 +205,9 @@ const getOpenChats = (chatID) => {
|
||||
|
||||
const getCurrentUser = () => {
|
||||
const currentUserId = Auth.userID;
|
||||
const currentUser = Users.findOne({ 'user.userid': currentUserId });
|
||||
const currentUser = Users.findOne({ userId: currentUserId });
|
||||
|
||||
return (currentUser) ? mapUser(currentUser.user) : null;
|
||||
return (currentUser) ? mapUser(currentUser) : null;
|
||||
};
|
||||
|
||||
export default {
|
||||
|
@ -0,0 +1,45 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Ellipse from '../annotations/ellipse/component.jsx';
|
||||
import Line from '../annotations/line/component.jsx';
|
||||
import Poll from '../annotations/poll/component.jsx';
|
||||
import Rectangle from '../annotations/rectangle/component.jsx';
|
||||
import Text from '../annotations/text/component.jsx';
|
||||
import Triangle from '../annotations/triangle/component.jsx';
|
||||
import Pencil from '../annotations/pencil/component.jsx';
|
||||
|
||||
export default class WhiteboardAnnotationModel extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render() {
|
||||
const Component = this.props.annotations[this.props.annotation.annotationType];
|
||||
if (Component != null) {
|
||||
return (
|
||||
<Component
|
||||
annotation={this.props.annotation.annotationInfo}
|
||||
widthRatio={this.props.widthRatio}
|
||||
heightRatio={this.props.heightRatio}
|
||||
slideWidth={this.props.slideWidth}
|
||||
slideHeight={this.props.slideHeight}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<g />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
WhiteboardAnnotationModel.defaultProps = {
|
||||
annotations: {
|
||||
ellipse: Ellipse,
|
||||
line: Line,
|
||||
poll_result: Poll,
|
||||
rectangle: Rectangle,
|
||||
text: Text,
|
||||
triangle: Triangle,
|
||||
pencil: Pencil,
|
||||
},
|
||||
};
|
@ -1,34 +1,34 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import WhiteboardShapeModel from '../shape-factory/component';
|
||||
import WhiteboardAnnotationModel from '../annotation-factory/component';
|
||||
|
||||
const propTypes = {
|
||||
// initial width and height of the slide are required to calculate the coordinates for each shape
|
||||
// initial width and height of the slide are required to calculate the coordinates for each annotation
|
||||
width: PropTypes.number.isRequired,
|
||||
height: PropTypes.number.isRequired,
|
||||
|
||||
// array of shapes, optional
|
||||
shapes: PropTypes.array,
|
||||
// array of annotations, optional
|
||||
annotations: PropTypes.array,
|
||||
};
|
||||
|
||||
export default class ShapeGroup extends React.Component {
|
||||
export default class AnnotationGroup extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
shapes,
|
||||
annotations,
|
||||
width,
|
||||
height,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<g>
|
||||
{shapes ? shapes.map(shape =>
|
||||
(<WhiteboardShapeModel
|
||||
shape={shape.shape}
|
||||
key={shape.shape.id}
|
||||
{annotations ? annotations.map(annotation =>
|
||||
(<WhiteboardAnnotationModel
|
||||
annotation={annotation}
|
||||
key={annotation.id}
|
||||
slideWidth={width}
|
||||
slideHeight={height}
|
||||
/>),
|
||||
@ -39,4 +39,4 @@ export default class ShapeGroup extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
ShapeGroup.propTypes = propTypes;
|
||||
AnnotationGroup.propTypes = propTypes;
|
@ -2,30 +2,30 @@ import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { createContainer } from 'meteor/react-meteor-data';
|
||||
|
||||
import ShapeGroupService from './service';
|
||||
import ShapeGroup from './component';
|
||||
import AnnotationGroupService from './service';
|
||||
import AnnotationGroup from './component';
|
||||
|
||||
const propTypes = {
|
||||
// the id is required to fetch the shapes
|
||||
// the id is required to fetch the annotations
|
||||
whiteboardId: PropTypes.string.isRequired,
|
||||
|
||||
// initial width and height of the slide are required to calculate the coordinates for each shape
|
||||
// initial width and height of the slide are required to calculate the coordinates for each annotation
|
||||
width: PropTypes.number.isRequired,
|
||||
height: PropTypes.number.isRequired,
|
||||
|
||||
// array of shapes, optional
|
||||
shapes: PropTypes.array,
|
||||
// array of annotations, optional
|
||||
annotations: PropTypes.array,
|
||||
};
|
||||
|
||||
class ShapeGroupContainer extends React.Component {
|
||||
class AnnotationGroupContainer extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<ShapeGroup
|
||||
shapes={this.props.shapes}
|
||||
<AnnotationGroup
|
||||
annotations={this.props.annotations}
|
||||
width={this.props.width}
|
||||
height={this.props.height}
|
||||
/>
|
||||
@ -35,13 +35,13 @@ class ShapeGroupContainer extends React.Component {
|
||||
|
||||
export default createContainer((params) => {
|
||||
const { whiteboardId, width, height } = params;
|
||||
const shapes = ShapeGroupService.getCurrentShapes(whiteboardId);
|
||||
const annotations = AnnotationGroupService.getCurrentAnnotations(whiteboardId);
|
||||
|
||||
return {
|
||||
shapes,
|
||||
annotations,
|
||||
width,
|
||||
height,
|
||||
};
|
||||
}, ShapeGroupContainer);
|
||||
}, AnnotationGroupContainer);
|
||||
|
||||
ShapeGroupContainer.propTypes = propTypes;
|
||||
AnnotationGroupContainer.propTypes = propTypes;
|
@ -0,0 +1,15 @@
|
||||
import Annotations from '/imports/api/2.0/annotations';
|
||||
|
||||
const getCurrentAnnotations = (whiteboardId) => {
|
||||
if (!whiteboardId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Annotations.find({
|
||||
whiteboardId,
|
||||
}).fetch();
|
||||
};
|
||||
|
||||
export default {
|
||||
getCurrentAnnotations,
|
||||
};
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ShapeHelpers from '../helpers.js';
|
||||
import AnnotationHelpers from '../helpers.js';
|
||||
|
||||
export default class EllipseDrawComponent extends React.Component {
|
||||
constructor(props) {
|
||||
@ -10,10 +10,10 @@ export default class EllipseDrawComponent extends React.Component {
|
||||
getCoordinates() {
|
||||
// x1 and y1 - coordinates of the ellipse's top left corner
|
||||
// x2 and y2 - coordinates of the ellipse's bottom right corner
|
||||
const x1 = this.props.shape.points[0];
|
||||
const y1 = this.props.shape.points[1];
|
||||
const x2 = this.props.shape.points[2];
|
||||
const y2 = this.props.shape.points[3];
|
||||
const x1 = this.props.annotation.points[0];
|
||||
const y1 = this.props.annotation.points[1];
|
||||
const x2 = this.props.annotation.points[2];
|
||||
const y2 = this.props.annotation.points[3];
|
||||
|
||||
// rx - horizontal radius
|
||||
// ry - vertical radius
|
||||
@ -42,8 +42,8 @@ export default class EllipseDrawComponent extends React.Component {
|
||||
rx={results.rx}
|
||||
ry={results.ry}
|
||||
fill="none"
|
||||
stroke={ShapeHelpers.formatColor(this.props.shape.color)}
|
||||
strokeWidth={this.props.shape.thickness}
|
||||
stroke={AnnotationHelpers.formatColor(this.props.annotation.color)}
|
||||
strokeWidth={this.props.annotation.thickness}
|
||||
style={this.props.style}
|
||||
/>
|
||||
);
|
@ -7,7 +7,7 @@ const zoomStroke = (thickness, widthRatio, heightRatio) => {
|
||||
};
|
||||
|
||||
const formatColor = (color) => {
|
||||
// let color = this.props.shape.shape.shape.color;
|
||||
// let color = this.props.annotation.annotation.annotation.color;
|
||||
if (!color) {
|
||||
color = '0'; // default value
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ShapeHelpers from '../helpers.js';
|
||||
import AnnotationHelpers from '../helpers.js';
|
||||
|
||||
export default class LineDrawComponent extends React.Component {
|
||||
constructor(props) {
|
||||
@ -8,10 +8,10 @@ export default class LineDrawComponent extends React.Component {
|
||||
}
|
||||
|
||||
getCoordinates() {
|
||||
const x1 = this.props.shape.points[0] / 100 * this.props.slideWidth;
|
||||
const y1 = this.props.shape.points[1] / 100 * this.props.slideHeight;
|
||||
const x2 = this.props.shape.points[2] / 100 * this.props.slideWidth;
|
||||
const y2 = this.props.shape.points[3] / 100 * this.props.slideHeight;
|
||||
const x1 = this.props.annotation.points[0] / 100 * this.props.slideWidth;
|
||||
const y1 = this.props.annotation.points[1] / 100 * this.props.slideHeight;
|
||||
const x2 = this.props.annotation.points[2] / 100 * this.props.slideWidth;
|
||||
const y2 = this.props.annotation.points[3] / 100 * this.props.slideHeight;
|
||||
|
||||
return {
|
||||
x1,
|
||||
@ -29,10 +29,10 @@ export default class LineDrawComponent extends React.Component {
|
||||
y1={results.y1}
|
||||
x2={results.x2}
|
||||
y2={results.y2}
|
||||
stroke={ShapeHelpers.formatColor(this.props.shape.color)}
|
||||
stroke={AnnotationHelpers.formatColor(this.props.annotation.color)}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={this.props.shape.thickness}
|
||||
strokeWidth={this.props.annotation.thickness}
|
||||
style={this.props.style}
|
||||
/>
|
||||
);
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ShapeHelpers from '../helpers.js';
|
||||
import AnnotationHelpers from '../helpers.js';
|
||||
|
||||
export default class PencilDrawComponent extends React.Component {
|
||||
constructor(props) {
|
||||
@ -10,7 +10,7 @@ export default class PencilDrawComponent extends React.Component {
|
||||
getCoordinates() {
|
||||
let i = 2;
|
||||
let path = '';
|
||||
const points = this.props.shape.points;
|
||||
const points = this.props.annotation.points;
|
||||
if (points && points.length >= 2) {
|
||||
path = `${path}M${points[0] / 100 * this.props.slideWidth
|
||||
}, ${points[1] / 100 * this.props.slideHeight}`;
|
||||
@ -29,9 +29,9 @@ export default class PencilDrawComponent extends React.Component {
|
||||
return (
|
||||
<path
|
||||
fill="none"
|
||||
stroke={ShapeHelpers.formatColor(this.props.shape.color)}
|
||||
stroke={AnnotationHelpers.formatColor(this.props.annotation.color)}
|
||||
d={path}
|
||||
strokeWidth={this.props.shape.thickness}
|
||||
strokeWidth={this.props.annotation.thickness}
|
||||
strokeLinejoin="round"
|
||||
strokeLinecap="round"
|
||||
style={this.props.style}
|
@ -6,7 +6,7 @@ export default class PollDrawComponent extends React.Component {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
// flag indicating whether we need to continue calculating the sizes or display the shape
|
||||
// flag indicating whether we need to continue calculating the sizes or display the annotation
|
||||
prepareToDisplay: true,
|
||||
|
||||
// outer (white) rectangle's coordinates and sizes (calculated in componentWillMount)
|
||||
@ -55,16 +55,16 @@ export default class PollDrawComponent extends React.Component {
|
||||
// calculating only the parts which have to be done just once and don't require
|
||||
// rendering / rerendering the text objects
|
||||
|
||||
// x1 and y1 - coordinates of the top left corner of the shape
|
||||
// initial width and height are the width and height of the shape
|
||||
// x1 and y1 - coordinates of the top left corner of the annotation
|
||||
// initial width and height are the width and height of the annotation
|
||||
// all the points are given as percentages of the slide
|
||||
const x1 = this.props.shape.points[0];
|
||||
const y1 = this.props.shape.points[1];
|
||||
const initialWidth = this.props.shape.points[2];
|
||||
const initialHeight = this.props.shape.points[3];
|
||||
const x1 = this.props.annotation.points[0];
|
||||
const y1 = this.props.annotation.points[1];
|
||||
const initialWidth = this.props.annotation.points[2];
|
||||
const initialHeight = this.props.annotation.points[3];
|
||||
|
||||
// calculating the data for the outer rectangle
|
||||
// 0.001 is needed to accomodate bottom and right borders of the shape
|
||||
// 0.001 is needed to accomodate bottom and right borders of the annotation
|
||||
const x = x1 / 100 * this.props.slideWidth;
|
||||
const y = y1 / 100 * this.props.slideHeight;
|
||||
const width = (initialWidth - 0.001) / 100 * this.props.slideWidth;
|
||||
@ -75,7 +75,7 @@ export default class PollDrawComponent extends React.Component {
|
||||
const textArray = [];
|
||||
|
||||
// counting the total number of votes, finding the biggest number of votes
|
||||
this.props.shape.result.reduce((previousValue, currentValue, currentIndex, array) => {
|
||||
this.props.annotation.result.reduce((previousValue, currentValue, currentIndex, array) => {
|
||||
votesTotal = previousValue + currentValue.numVotes;
|
||||
if (maxNumVotes < currentValue.numVotes) {
|
||||
maxNumVotes = currentValue.numVotes;
|
||||
@ -87,10 +87,10 @@ export default class PollDrawComponent extends React.Component {
|
||||
// filling the textArray with data to display
|
||||
// adding value of the iterator to each line needed to create unique
|
||||
// keys while rendering at the end
|
||||
const arrayLength = this.props.shape.result.length;
|
||||
const arrayLength = this.props.annotation.result.length;
|
||||
for (let i = 0; i < arrayLength; ++i) {
|
||||
const _tempArray = [];
|
||||
const _result = this.props.shape.result[i];
|
||||
const _result = this.props.annotation.result[i];
|
||||
_tempArray.push(_result.key, `${_result.numVotes}`);
|
||||
if (votesTotal === 0) {
|
||||
_tempArray.push('0%');
|
||||
@ -158,9 +158,9 @@ export default class PollDrawComponent extends React.Component {
|
||||
|
||||
// calculating the font size in this if / else block
|
||||
if (this.state.fontSizeDirection != 0) {
|
||||
const key = `${this.props.shape.id}_key_${this.state.currentLine}`;
|
||||
const votes = `${this.props.shape.id}_votes_${this.state.currentLine}`;
|
||||
const percent = `${this.props.shape.id}_percent_${this.state.currentLine}`;
|
||||
const key = `${this.props.annotation.id}_key_${this.state.currentLine}`;
|
||||
const votes = `${this.props.annotation.id}_votes_${this.state.currentLine}`;
|
||||
const percent = `${this.props.annotation.id}_percent_${this.state.currentLine}`;
|
||||
const keySizes = findDOMNode(this[key]).getBBox();
|
||||
const voteSizes = findDOMNode(this[votes]).getBBox();
|
||||
const percSizes = findDOMNode(this[percent]).getBBox();
|
||||
@ -214,8 +214,8 @@ export default class PollDrawComponent extends React.Component {
|
||||
let maxRightWidth = 0;
|
||||
maxLineHeight = 0;
|
||||
for (let i = 0; i < this.state.textArray.length; ++i) {
|
||||
const key = `${this.props.shape.id}_key_${i}`;
|
||||
const percent = `${this.props.shape.id}_percent_${i}`;
|
||||
const key = `${this.props.annotation.id}_key_${i}`;
|
||||
const percent = `${this.props.annotation.id}_percent_${i}`;
|
||||
const keySizes = findDOMNode(this[key]).getBBox();
|
||||
const percSizes = findDOMNode(this[percent]).getBBox();
|
||||
|
||||
@ -236,7 +236,7 @@ export default class PollDrawComponent extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
const digitRef = `${this.props.shape.id}_digit`;
|
||||
const digitRef = `${this.props.annotation.id}_digit`;
|
||||
const maxDigitWidth = findDOMNode(this[digitRef]).getBBox().width;
|
||||
const maxDigitHeight = findDOMNode(this[digitRef]).getBBox().height;
|
||||
|
||||
@ -293,10 +293,10 @@ export default class PollDrawComponent extends React.Component {
|
||||
let yNumVotes = this.state.innerRect.y + verticalPadding - magicNumber;
|
||||
const extendedTextArray = [];
|
||||
for (let i = 0; i < this.state.textArray.length; i++) {
|
||||
if (this.state.maxNumVotes == 0 || this.props.shape.result[i].numVotes === 0) {
|
||||
if (this.state.maxNumVotes == 0 || this.props.annotation.result[i].numVotes === 0) {
|
||||
barWidth = 1;
|
||||
} else {
|
||||
barWidth = this.props.shape.result[i].numVotes / this.state.maxNumVotes * maxBarWidth;
|
||||
barWidth = this.props.annotation.result[i].numVotes / this.state.maxNumVotes * maxBarWidth;
|
||||
}
|
||||
|
||||
// coordinates and color of the text inside the line bar
|
||||
@ -320,30 +320,30 @@ export default class PollDrawComponent extends React.Component {
|
||||
}
|
||||
|
||||
extendedTextArray[i] =
|
||||
{
|
||||
key: `${this.props.shape.id}_${this.state.textArray[i][3]}`,
|
||||
keyColumn: {
|
||||
keyString: this.state.textArray[i][0],
|
||||
xLeft,
|
||||
yLeft,
|
||||
},
|
||||
barColumn: {
|
||||
votesString: this.state.textArray[i][1],
|
||||
xBar,
|
||||
yBar,
|
||||
barWidth,
|
||||
barHeight,
|
||||
yNumVotes,
|
||||
xNumVotes,
|
||||
color,
|
||||
numVotes: this.props.shape.result[i].numVotes,
|
||||
},
|
||||
percentColumn: {
|
||||
xRight,
|
||||
yRight,
|
||||
percentString: this.state.textArray[i][2],
|
||||
},
|
||||
};
|
||||
{
|
||||
key: `${this.props.annotation.id}_${this.state.textArray[i][3]}`,
|
||||
keyColumn: {
|
||||
keyString: this.state.textArray[i][0],
|
||||
xLeft,
|
||||
yLeft,
|
||||
},
|
||||
barColumn: {
|
||||
votesString: this.state.textArray[i][1],
|
||||
xBar,
|
||||
yBar,
|
||||
barWidth,
|
||||
barHeight,
|
||||
yNumVotes,
|
||||
xNumVotes,
|
||||
color,
|
||||
numVotes: this.props.annotation.result[i].numVotes,
|
||||
},
|
||||
percentColumn: {
|
||||
xRight,
|
||||
yRight,
|
||||
percentString: this.state.textArray[i][2],
|
||||
},
|
||||
};
|
||||
|
||||
// changing the Y coordinate for all the objects
|
||||
yBar = yBar + barHeight + verticalPadding;
|
||||
@ -447,11 +447,11 @@ export default class PollDrawComponent extends React.Component {
|
||||
renderLine(line) {
|
||||
// this func just renders the strings for one line
|
||||
return (
|
||||
<g key={`${this.props.shape.id}_line_${line[3]}`}>
|
||||
<g key={`${this.props.annotation.id}_line_${line[3]}`}>
|
||||
<text
|
||||
fontFamily="Arial"
|
||||
fontSize={this.state.calcFontSize}
|
||||
ref={(ref) => { this[`${this.props.shape.id}_key_${line[3]}`] = ref; }}
|
||||
ref={(ref) => { this[`${this.props.annotation.id}_key_${line[3]}`] = ref; }}
|
||||
>
|
||||
<tspan>
|
||||
{line[0]}
|
||||
@ -460,7 +460,7 @@ export default class PollDrawComponent extends React.Component {
|
||||
<text
|
||||
fontFamily="Arial"
|
||||
fontSize={this.state.calcFontSize}
|
||||
ref={(ref) => { this[`${this.props.shape.id}_votes_${line[3]}`] = ref; }}
|
||||
ref={(ref) => { this[`${this.props.annotation.id}_votes_${line[3]}`] = ref; }}
|
||||
>
|
||||
<tspan>
|
||||
{line[1]}
|
||||
@ -469,7 +469,7 @@ export default class PollDrawComponent extends React.Component {
|
||||
<text
|
||||
fontFamily="Arial"
|
||||
fontSize={this.state.calcFontSize}
|
||||
ref={(ref) => { this[`${this.props.shape.id}_percent_${line[3]}`] = ref; }}
|
||||
ref={(ref) => { this[`${this.props.annotation.id}_percent_${line[3]}`] = ref; }}
|
||||
>
|
||||
<tspan>
|
||||
{line[2]}
|
||||
@ -495,7 +495,7 @@ export default class PollDrawComponent extends React.Component {
|
||||
<text
|
||||
fontFamily="Arial"
|
||||
fontSize={this.state.calcFontSize}
|
||||
ref={(ref) => { this[`${this.props.shape.id}_digit`] = ref; }}
|
||||
ref={(ref) => { this[`${this.props.annotation.id}_digit`] = ref; }}
|
||||
>
|
||||
<tspan>
|
||||
0
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ShapeHelpers from '../helpers.js';
|
||||
import AnnotationHelpers from '../helpers.js';
|
||||
|
||||
export default class RectangleDrawComponent extends React.Component {
|
||||
constructor(props) {
|
||||
@ -8,23 +8,23 @@ export default class RectangleDrawComponent extends React.Component {
|
||||
}
|
||||
|
||||
getCoordinates() {
|
||||
// x1 and y1 are the coordinates of the top left corner of the shape
|
||||
// x2 and y2 are the coordinates of the bottom right corner of the shape
|
||||
let x1 = this.props.shape.points[0];
|
||||
let y1 = this.props.shape.points[1];
|
||||
let x2 = this.props.shape.points[2];
|
||||
let y2 = this.props.shape.points[3];
|
||||
// x1 and y1 are the coordinates of the top left corner of the annotation
|
||||
// x2 and y2 are the coordinates of the bottom right corner of the annotation
|
||||
let x1 = this.props.annotation.points[0];
|
||||
let y1 = this.props.annotation.points[1];
|
||||
let x2 = this.props.annotation.points[2];
|
||||
let y2 = this.props.annotation.points[3];
|
||||
|
||||
// Presenter pulled rectangle to the left
|
||||
if (x2 < x1) {
|
||||
x1 = this.props.shape.points[2];
|
||||
x2 = this.props.shape.points[0];
|
||||
x1 = this.props.annotation.points[2];
|
||||
x2 = this.props.annotation.points[0];
|
||||
}
|
||||
|
||||
// Presenter pulled Rectangle to the top
|
||||
if (y2 < y1) {
|
||||
y1 = this.props.shape.points[3];
|
||||
y2 = this.props.shape.points[1];
|
||||
y1 = this.props.annotation.points[3];
|
||||
y2 = this.props.annotation.points[1];
|
||||
}
|
||||
|
||||
const x = x1 / 100 * this.props.slideWidth;
|
||||
@ -51,8 +51,8 @@ export default class RectangleDrawComponent extends React.Component {
|
||||
rx="1"
|
||||
ry="1"
|
||||
fill="none"
|
||||
stroke={ShapeHelpers.formatColor(this.props.shape.color)}
|
||||
strokeWidth={this.props.shape.thickness}
|
||||
stroke={AnnotationHelpers.formatColor(this.props.annotation.color)}
|
||||
strokeWidth={this.props.annotation.thickness}
|
||||
style={this.props.style}
|
||||
/>
|
||||
);
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ShapeHelpers from '../helpers.js';
|
||||
import AnnotationHelpers from '../helpers.js';
|
||||
|
||||
export default class TextDrawComponent extends React.Component {
|
||||
constructor(props) {
|
||||
@ -8,14 +8,14 @@ export default class TextDrawComponent extends React.Component {
|
||||
}
|
||||
|
||||
getCoordinates() {
|
||||
const x = this.props.shape.x / 100 * this.props.slideWidth;
|
||||
const y = this.props.shape.y / 100 * this.props.slideHeight;
|
||||
const width = this.props.shape.textBoxWidth / 100 * this.props.slideWidth;
|
||||
const height = this.props.shape.textBoxHeight / 100 * this.props.slideHeight;
|
||||
const fontColor = ShapeHelpers.formatColor(this.props.shape.fontColor);
|
||||
const fontSize = this.props.shape.fontSize;
|
||||
const calcedFontSize = this.props.shape.calcedFontSize / 100 * this.props.slideHeight;
|
||||
const text = this.props.shape.text;
|
||||
const x = this.props.annotation.x / 100 * this.props.slideWidth;
|
||||
const y = this.props.annotation.y / 100 * this.props.slideHeight;
|
||||
const width = this.props.annotation.textBoxWidth / 100 * this.props.slideWidth;
|
||||
const height = this.props.annotation.textBoxHeight / 100 * this.props.slideHeight;
|
||||
const fontColor = AnnotationHelpers.formatColor(this.props.annotation.fontColor);
|
||||
const fontSize = this.props.annotation.fontSize;
|
||||
const calcedFontSize = this.props.annotation.calcedFontSize / 100 * this.props.slideHeight;
|
||||
const text = this.props.annotation.text;
|
||||
|
||||
return {
|
||||
x,
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ShapeHelpers from '../helpers.js';
|
||||
import AnnotationHelpers from '../helpers.js';
|
||||
|
||||
export default class TriangleDrawComponent extends React.Component {
|
||||
constructor(props) {
|
||||
@ -10,14 +10,14 @@ export default class TriangleDrawComponent extends React.Component {
|
||||
getCoordinates() {
|
||||
let path = '';
|
||||
|
||||
// points[0] and points[1] are x and y coordinates of the top left corner of the shape obj
|
||||
// points[2] and points[3] are x and y coordinates of the bottom right corner of the shape obj
|
||||
const xBottomLeft = this.props.shape.points[0];
|
||||
const yBottomLeft = this.props.shape.points[3];
|
||||
const xBottomRight = this.props.shape.points[2];
|
||||
const yBottomRight = this.props.shape.points[3];
|
||||
// points[0] and points[1] are x and y coordinates of the top left corner of the annotation obj
|
||||
// points[2] and points[3] are x and y coordinates of the bottom right corner of the annotation obj
|
||||
const xBottomLeft = this.props.annotation.points[0];
|
||||
const yBottomLeft = this.props.annotation.points[3];
|
||||
const xBottomRight = this.props.annotation.points[2];
|
||||
const yBottomRight = this.props.annotation.points[3];
|
||||
const xTop = ((xBottomRight - xBottomLeft) / 2) + xBottomLeft;
|
||||
const yTop = this.props.shape.points[1];
|
||||
const yTop = this.props.annotation.points[1];
|
||||
|
||||
path = `${path}M${xTop / 100 * this.props.slideWidth
|
||||
},${yTop / 100 * this.props.slideHeight
|
||||
@ -36,9 +36,9 @@ export default class TriangleDrawComponent extends React.Component {
|
||||
<path
|
||||
style={this.props.style}
|
||||
fill="none"
|
||||
stroke={ShapeHelpers.formatColor(this.props.shape.color)}
|
||||
stroke={AnnotationHelpers.formatColor(this.props.annotation.color)}
|
||||
d={path}
|
||||
strokeWidth={this.props.shape.thickness}
|
||||
strokeWidth={this.props.annotation.thickness}
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
);
|
@ -1,45 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Ellipse from '../shapes/ellipse/component.jsx';
|
||||
import Line from '../shapes/line/component.jsx';
|
||||
import Poll from '../shapes/poll/component.jsx';
|
||||
import Rectangle from '../shapes/rectangle/component.jsx';
|
||||
import Text from '../shapes/text/component.jsx';
|
||||
import Triangle from '../shapes/triangle/component.jsx';
|
||||
import Pencil from '../shapes/pencil/component.jsx';
|
||||
|
||||
export default class WhiteboardShapeModel extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render() {
|
||||
const Component = this.props.shapes[this.props.shape.shape_type];
|
||||
if (Component != null) {
|
||||
return (
|
||||
<Component
|
||||
shape={this.props.shape.shape}
|
||||
widthRatio={this.props.widthRatio}
|
||||
heightRatio={this.props.heightRatio}
|
||||
slideWidth={this.props.slideWidth}
|
||||
slideHeight={this.props.slideHeight}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<g />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
WhiteboardShapeModel.defaultProps = {
|
||||
shapes: {
|
||||
ellipse: Ellipse,
|
||||
line: Line,
|
||||
poll_result: Poll,
|
||||
rectangle: Rectangle,
|
||||
text: Text,
|
||||
triangle: Triangle,
|
||||
pencil: Pencil,
|
||||
},
|
||||
};
|
@ -1,15 +0,0 @@
|
||||
import Shapes from '/imports/api/2.0/shapes';
|
||||
|
||||
const getCurrentShapes = (whiteboardId) => {
|
||||
if (!whiteboardId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Shapes.find({
|
||||
whiteboardId,
|
||||
}).fetch();
|
||||
};
|
||||
|
||||
export default {
|
||||
getCurrentShapes,
|
||||
};
|
@ -6,26 +6,26 @@ const ROLE_MODERATOR = USER_CONFIG.role_moderator;
|
||||
|
||||
const mapUser = (user) => {
|
||||
const userId = Auth.userID;
|
||||
const voiceUser = VoiceUsers.findOne({ intId: user.userid });
|
||||
const voiceUser = VoiceUsers.findOne({ intId: user.userId });
|
||||
const { muted, talking, listenOnly } = voiceUser;
|
||||
|
||||
const mappedUser = {
|
||||
id: user.userid,
|
||||
id: user.userId,
|
||||
name: user.name,
|
||||
emoji: {
|
||||
status: user.emoji,
|
||||
changedAt: user.set_emoji_time,
|
||||
changedAt: user.emojiTime,
|
||||
},
|
||||
isPresenter: user.presenter,
|
||||
isModerator: user.role === ROLE_MODERATOR,
|
||||
isCurrent: user.userid === userId,
|
||||
isCurrent: user.userId === userId,
|
||||
isVoiceUser: listenOnly || talking,
|
||||
isMuted: muted,
|
||||
isTalking: talking,
|
||||
isListenOnly: listenOnly,
|
||||
isSharingWebcam: 0,
|
||||
isPhoneUser: user.phone_user,
|
||||
isOnline: user.connection_status === 'online',
|
||||
isOnline: user.connectionStatus === 'online',
|
||||
isLocked: user.locked,
|
||||
};
|
||||
|
||||
|
@ -8,7 +8,7 @@ acl:
|
||||
- 'polls'
|
||||
- 'chat'
|
||||
- 'presentations'
|
||||
- 'shapes'
|
||||
- 'annotations'
|
||||
- 'slides'
|
||||
- 'captions'
|
||||
- 'breakouts'
|
||||
@ -29,4 +29,3 @@ acl:
|
||||
methods:
|
||||
- 'assignPresenter'
|
||||
- 'switchSlide'
|
||||
- 'switchSlideMessage'
|
||||
|
@ -1,20 +1,9 @@
|
||||
import '/imports/startup/server';
|
||||
import '/imports/api/1.1/chat/server';
|
||||
import '/imports/api/1.1/cursor/server';
|
||||
import '/imports/api/1.1/deskshare/server';
|
||||
import '/imports/api/1.1/meetings/server';
|
||||
import '/imports/api/1.1/polls/server';
|
||||
import '/imports/api/1.1/breakouts/server';
|
||||
import '/imports/api/1.1/presentations/server';
|
||||
import '/imports/api/1.1/shapes/server';
|
||||
import '/imports/api/1.1/slides/server';
|
||||
import '/imports/api/1.1/captions/server';
|
||||
import '/imports/api/1.1/users/server';
|
||||
|
||||
// 2x
|
||||
import '/imports/api/2.0/meetings/server';
|
||||
import '/imports/api/2.0/users/server';
|
||||
import '/imports/api/2.0/shapes/server';
|
||||
import '/imports/api/2.0/annotations/server';
|
||||
import '/imports/api/2.0/cursor/server';
|
||||
import '/imports/api/2.0/polls/server';
|
||||
import '/imports/api/2.0/captions/server';
|
||||
|
Loading…
Reference in New Issue
Block a user