diff --git a/CHANGELOG b/CHANGELOG
index 8b94e1b2f..565331646 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -21,6 +21,7 @@ Motions:
- Removed server side image to base64 transformation and
added local transformation [#3181]
- Added support for export motions in a zip archive [#3189].
+- Performance improvement for zip creation [#3251]
- Bugfix: changing motion line length did not invalidate cache [#3202]
- Bugfix: Added more distance in motion PDF for DEL-tags in new lines [#3211].
- Added warning message if an edit dialog was already opened by another
@@ -48,7 +49,7 @@ Core:
General:
- Switched from npm to Yarn [#3188].
- Several bugfixes and minor improvements.
-- Bugfixes for PDF creation [#3227]
+- Bugfixes for PDF creation [#3227, #3251]
Version 2.1.1 (2017-04-05)
diff --git a/openslides/core/static/js/core/pdf-worker.js b/openslides/core/static/js/core/pdf-worker.js
index 4300bb558..4d4d4b303 100644
--- a/openslides/core/static/js/core/pdf-worker.js
+++ b/openslides/core/static/js/core/pdf-worker.js
@@ -86,34 +86,46 @@ var replacePlaceholder = function (content) {
}
};
-
-// Create PDF on message and return the base64 decoded document
-self.addEventListener('message', function(e) {
- var data = JSON.parse(e.data);
-
- // Workaround for using dynamic footer with page number.
- // TODO: Needs improvement of pdfmake's web worker support.
- // see https://github.com/bpampuch/pdfmake/issues/38
- if (data.footerTpl) {
- data.footer = function (currentPage, pageCount) {
- for(var i = 0; i < data.footerTpl.columns.length; i++) {
- if (data.footerTpl.columns[i].text) {
- data.footerTpl.columns[i].text = data.footerTpl.columns[i].text
+// Workaround for using dynamic footer with page number.
+// TODO: Needs improvement of pdfmake's web worker support.
+// see https://github.com/bpampuch/pdfmake/issues/38
+var replaceFooter = function (doc) {
+ if (doc.footerTpl) {
+ doc.footer = function (currentPage, pageCount) {
+ // One way to clone arrays/objects in js, that are serilizeable.
+ var columns = JSON.parse(JSON.stringify(doc.footerTpl.columns));
+ for (var i = 0; i < columns.length; i++) {
+ if (columns[i].text) {
+ columns[i].text = columns[i].text
.replace('{{currentPage}}', currentPage)
.replace('{{pageCount}}', pageCount);
}
}
return {
- columns: data.footerTpl.columns,
- margin: data.footerTpl.margin,
+ columns: columns,
+ margin: doc.footerTpl.margin,
};
};
}
+};
- replacePlaceholder(data.content);
+// Create PDF on message and return the base64 decoded document
+self.addEventListener('message', function(e) {
+ var data = JSON.parse(e.data);
+ var doc = data.pdfDocument;
- var pdf = pdfMake.createPdf(data);
+ replaceFooter(doc);
+ replacePlaceholder(doc.content);
+
+ var pdf = pdfMake.createPdf(doc);
pdf.getBase64(function (base64) {
- self.postMessage(base64);
+ if (data.filename) {
+ self.postMessage(JSON.stringify({
+ filename: data.filename,
+ base64: base64
+ }));
+ } else {
+ self.postMessage(base64);
+ }
});
}, false);
diff --git a/openslides/core/static/js/core/pdf.js b/openslides/core/static/js/core/pdf.js
index c9f140f3c..9c4b693c0 100644
--- a/openslides/core/static/js/core/pdf.js
+++ b/openslides/core/static/js/core/pdf.js
@@ -1008,7 +1008,34 @@ angular.module('OpenSlidesApp.core.pdf', [])
pdfWorker.addEventListener('error', function (event) {
reject(event);
});
- pdfWorker.postMessage(JSON.stringify(pdfDocument));
+ pdfWorker.postMessage(JSON.stringify({
+ pdfDocument: pdfDocument
+ }));
+ });
+ },
+ // Struckture of pdfDocuments: { filname1: doc, filename2: doc, ...}
+ getBase64FromMultipleDocuments: function (pdfDocuments) {
+ return $q(function (resolve, reject) {
+ var pdfWorker = new Worker('/static/js/workers/pdf-worker.js');
+ var resultCount = 0;
+ var base64Map = {}; // Maps filename to base64
+ pdfWorker.addEventListener('message', function (event) {
+ resultCount++;
+ var data = JSON.parse(event.data);
+ base64Map[data.filename] = data.base64;
+ if (resultCount === _.keys(pdfDocuments).length) {
+ resolve(base64Map);
+ }
+ });
+ pdfWorker.addEventListener('error', function (event) {
+ reject(event);
+ });
+ _.forEach(pdfDocuments, function (doc, filename) {
+ pdfWorker.postMessage(JSON.stringify({
+ filename: filename,
+ pdfDocument: doc
+ }));
+ });
});
},
download: function (pdfDocument, filename) {
diff --git a/openslides/motions/static/js/motions/pdf.js b/openslides/motions/static/js/motions/pdf.js
index ae7f61312..e8ee416ce 100644
--- a/openslides/motions/static/js/motions/pdf.js
+++ b/openslides/motions/static/js/motions/pdf.js
@@ -723,9 +723,9 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
params.filename = void 0; // clear this, so we do not override the default filenames for each pdf.
var self = this;
- var pdfs = {};
var usedFilenames = [];
- var pdfPromises = _.map(motions, function (motion) {
+ var docMap = {};
+ var docPromises = _.map(motions, function (motion) {
var identifier = motion.identifier ? '-' + motion.identifier : '';
var filename = gettextCatalog.getString('Motion') + identifier;
@@ -742,36 +742,30 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
usedFilenames.push(filename);
filename += '.pdf';
- return $q(function (resolve, reject) {
+ return $q(function (resolve) {
// get documentProvider for every motion.
self.getDocumentProvider(motion, params, true).then(function (documentProvider) {
- var doc = documentProvider.getDocument();
-
- PdfCreate.getBase64FromDocument(doc).then(function (data) {
- pdfs[filename] = data;
- resolve();
- }, function (error) {
- reject(error);
- });
+ docMap[filename] = documentProvider.getDocument();
+ resolve();
});
});
});
-
- // Wait for all documents to be generated. Then put them into a zip and download it.
- $q.all(pdfPromises).then(function () {
- var zip = new JSZip();
- _.forEach(pdfs, function (data, filename) {
- zip.file(filename, data, {base64: true});
+ $q.all(docPromises).then(function () {
+ PdfCreate.getBase64FromMultipleDocuments(docMap).then(function (pdfMap) {
+ var zip = new JSZip();
+ _.forEach(pdfMap, function (data, filename) {
+ zip.file(filename, data, {base64: true});
+ });
+ Messaging.createOrEditMessage(messageId, '' +
+ gettextCatalog.getString('ZIP successfully generated.'), 'success', {timeout: 3000});
+ zip.generateAsync({type: 'blob'}).then(function (content) {
+ FileSaver.saveAs(content, zipFilename);
+ });
+ }, function (error) {
+ Messaging.createOrEditMessage(messageId, '' + gettextCatalog.getString('Error while generating ZIP file') +
+ ': ' + error + '
', 'error');
});
- Messaging.createOrEditMessage(messageId, '' +
- gettextCatalog.getString('ZIP successfully generated.'), 'success', {timeout: 3000});
- zip.generateAsync({type: 'blob'}).then(function (content) {
- FileSaver.saveAs(content, zipFilename);
- });
- }, function (error) {
- Messaging.createOrEditMessage(messageId, '' + gettextCatalog.getString('Error while generating ZIP file') +
- ': ' + error + '
', 'error');
});
},
createPollPdf: function (motion, version) {