Implement polls

This commit is contained in:
Daniel Petri Rocha 2022-02-19 16:43:11 +01:00
parent 7d437e17f4
commit 4042890348
3 changed files with 61 additions and 23 deletions

View File

@ -8,7 +8,6 @@ export default function makePresentationWithAnnotationDownloadReqMsg() {
const REDIS_CONFIG = Meteor.settings.private.redis; const REDIS_CONFIG = Meteor.settings.private.redis;
const CHANNEL = REDIS_CONFIG.channels.toAkkaApps; const CHANNEL = REDIS_CONFIG.channels.toAkkaApps;
const EVENT_NAME = 'MakePresentationWithAnnotationDownloadReqMsg'; const EVENT_NAME = 'MakePresentationWithAnnotationDownloadReqMsg';
const SECOND_EVENT_NAME = 'ExportPresentationWithAnnotationReqMsg';
try { try {
const { meetingId, requesterUserId } = extractCredentials(this.userId); const { meetingId, requesterUserId } = extractCredentials(this.userId);
@ -18,23 +17,12 @@ export default function makePresentationWithAnnotationDownloadReqMsg() {
const payload = { const payload = {
presId: "", presId: "",
allPages: false, allPages: true,
pages: [2, 3, 8], pages: [],
}; };
const payload2 = {
parentMeetingId: "",
allPages: false,
};
Logger.warn('************');
Logger.warn(CHANNEL)
Logger.warn(EVENT_NAME)
Logger.warn(meetingId)
Logger.warn(requesterUserId)
Logger.warn('************');
return RedisPubSub.publishUserMessage(CHANNEL, EVENT_NAME, meetingId, requesterUserId, payload); return RedisPubSub.publishUserMessage(CHANNEL, EVENT_NAME, meetingId, requesterUserId, payload);
} catch (err) { } catch (err) {
Logger.error(`Exception while invoking method makePresentationWithAnnotationDownloadReqMsg ${err.stack}`); Logger.error(`Exception while invoking method makePresentationWithAnnotationDownloadReqMsg ${err.stack}`);
} }

View File

@ -169,7 +169,7 @@
"app.presentation.presentationToolbar.prevSlideDesc": "Change the presentation to the previous slide", "app.presentation.presentationToolbar.prevSlideDesc": "Change the presentation to the previous slide",
"app.presentation.presentationToolbar.nextSlideLabel": "Next slide", "app.presentation.presentationToolbar.nextSlideLabel": "Next slide",
"app.presentation.presentationToolbar.nextSlideDesc": "Change the presentation to the next slide", "app.presentation.presentationToolbar.nextSlideDesc": "Change the presentation to the next slide",
"app.presentation.presentationToolbar.downloadSlideWithAnnotations": "Download slide with annotations", "app.presentation.presentationToolbar.downloadSlideWithAnnotations": "Download slides with annotations",
"app.presentation.presentationToolbar.skipSlideLabel": "Skip slide", "app.presentation.presentationToolbar.skipSlideLabel": "Skip slide",
"app.presentation.presentationToolbar.skipSlideDesc": "Change the presentation to a specific slide", "app.presentation.presentationToolbar.skipSlideDesc": "Change the presentation to a specific slide",
"app.presentation.presentationToolbar.fitWidthLabel": "Fit to width", "app.presentation.presentationToolbar.fitWidthLabel": "Fit to width",

View File

@ -3,7 +3,7 @@ const config = require('../config');
const fs = require('fs'); const fs = require('fs');
const convert = require('xml-js'); const convert = require('xml-js');
const { create } = require('xmlbuilder2', { encoding: 'utf-8' }); const { create } = require('xmlbuilder2', { encoding: 'utf-8' });
const { exec } = require("child_process"); const { exec, execSync } = require("child_process");
const { workerData, parentPort } = require('worker_threads') const { workerData, parentPort } = require('worker_threads')
@ -126,6 +126,58 @@ function overlay_pencil(svg, annotation, w, h) {
} }
} }
function overlay_poll(svg, annotation, w, h) {
if (annotation.result.length == 0) {
return;
}
let poll_x = scale_shape(w, annotation.points[0]);
let poll_y = scale_shape(h, annotation.points[1]);
let poll_width = Math.round(scale_shape(w, annotation.points[2]));
let poll_height = Math.round(scale_shape(h, annotation.points[3]));
let pollId = annotation.id.replace(/\//g, '');
let pollSVG = `${dropbox}/poll-${pollId}.svg`
let pollJSON = `${dropbox}/poll-${pollId}.json`
// Rename 'numVotes' key to 'num_votes'
let pollJSONContent = annotation.result.map(result => {
result.num_votes = result.numVotes;
delete result.numVotes;
return result;
});
// Store the poll result in a JSON file
fs.writeFileSync(pollJSON, JSON.stringify(pollJSONContent), function(err) {
if(err) { return logger.error(err); }
});
// Create empty SVG poll
fs.writeFileSync(pollSVG, '', function(err) {
if(err) { return logger.error(err); }
});
// Render the poll SVG using gen_poll_svg script
execSync(`${config.genPollSVG.path} -i ${pollJSON} -w ${poll_width} -h ${poll_height} -n ${annotation.numResponders} -o ${pollSVG}`, (error, stderr) => {
if (error) {
logger.error(`Poll generation failed with error: ${error.message}`);
return;
}
if (stderr) {
logger.error(`Poll generation failed with stderr: ${stderr}`);
return;
}
});
// Add poll image element
svg.ele('image', {
'xlink:href': `file://${pollSVG}`,
x: poll_x,
y: poll_y,
width: poll_width,
height: poll_height,
})
}
function overlay_rectangle(svg, annotation, w, h) { function overlay_rectangle(svg, annotation, w, h) {
let shapeColor = Number(annotation.color).toString(16) let shapeColor = Number(annotation.color).toString(16)
let fill = annotation.fill ? `#${shapeColor}` : 'none'; let fill = annotation.fill ? `#${shapeColor}` : 'none';
@ -135,7 +187,7 @@ function overlay_rectangle(svg, annotation, w, h) {
let x2 = scale_shape(w, annotation.points[2]) let x2 = scale_shape(w, annotation.points[2])
let y2 = scale_shape(h, annotation.points[3]) let y2 = scale_shape(h, annotation.points[3])
let path = `M ${x1} ${y1} L ${x2} ${y1} L ${x2} ${y2} L ${x1} ${y2} Z` let path = `M${x1} ${y1} L${x2} ${y1} L${x2} ${y2} L${x1} ${y2} Z`
svg.ele('g', { svg.ele('g', {
style: `stroke:#${shapeColor};stroke-width:${scale_shape(w, annotation.thickness)};fill:${fill};stroke-linejoin:miter` style: `stroke:#${shapeColor};stroke-width:${scale_shape(w, annotation.thickness)};fill:${fill};stroke-linejoin:miter`
@ -200,8 +252,6 @@ function overlay_line(svg, annotation, w, h) {
} }
function overlay_annotations(svg, annotations, w, h) { function overlay_annotations(svg, annotations, w, h) {
console.log(annotations)
for(let i = 0; i < annotations.length; i++) { for(let i = 0; i < annotations.length; i++) {
switch (annotations[i].annotationType) { switch (annotations[i].annotationType) {
case 'ellipse': case 'ellipse':
@ -211,6 +261,7 @@ function overlay_annotations(svg, annotations, w, h) {
overlay_line(svg, annotations[i].annotationInfo, w, h); overlay_line(svg, annotations[i].annotationInfo, w, h);
break; break;
case 'poll_result': case 'poll_result':
overlay_poll(svg, annotations[i].annotationInfo, w, h);
break; break;
case 'pencil': case 'pencil':
overlay_pencil(svg, annotations[i].annotationInfo, w, h); overlay_pencil(svg, annotations[i].annotationInfo, w, h);
@ -233,7 +284,7 @@ function overlay_annotations(svg, annotations, w, h) {
// Process the presentation pages and annotations into a PDF file // Process the presentation pages and annotations into a PDF file
// 1. Get the job // 1. Get the job
let dropbox = `${config.shared.presAnnDropboxDir}/${jobId}` const dropbox = `${config.shared.presAnnDropboxDir}/${jobId}`
let job = fs.readFileSync(`${dropbox}/job`); let job = fs.readFileSync(`${dropbox}/job`);
let exportJob = JSON.parse(job); let exportJob = JSON.parse(job);
@ -293,7 +344,6 @@ for (let i = 0; i < pages.length; i++) {
overlay_annotations(svg, pages[i].annotations, slideWidth, slideHeight) overlay_annotations(svg, pages[i].annotations, slideWidth, slideHeight)
svg = svg.end({ prettyPrint: true }); svg = svg.end({ prettyPrint: true });
console.log (svg)
// Write annotated SVG file // Write annotated SVG file
let file = `${dropbox}/annotated-slide${pages[i].page}.svg` let file = `${dropbox}/annotated-slide${pages[i].page}.svg`
@ -308,7 +358,7 @@ for (let i = 0; i < pages.length; i++) {
// TODO: change presLocation so it doesn't point to the 'svgs' directory // TODO: change presLocation so it doesn't point to the 'svgs' directory
exec(`rsvg-convert ${rsvgConvertInput} -f pdf -o ${exportJob.presLocation}/../annotated_slides_${jobId}.pdf`, (error, stderr) => { exec(`rsvg-convert ${rsvgConvertInput} -f pdf -o ${exportJob.presLocation}/../annotated_slides_${jobId}.pdf`, (error, stderr) => {
if (error) { if (error) {
console.log(`SVG to PDF export failed with error: ${error.message}`); logger.error(`SVG to PDF export failed with error: ${error.message}`);
return; return;
} }
if (stderr) { if (stderr) {