Merge pull request #3251 from FinnStutzenstein/PdfZipPerformance
Improve zip creation and fixing page numbers
This commit is contained in:
commit
70dd9647b4
@ -21,6 +21,7 @@ Motions:
|
|||||||
- Removed server side image to base64 transformation and
|
- Removed server side image to base64 transformation and
|
||||||
added local transformation [#3181]
|
added local transformation [#3181]
|
||||||
- Added support for export motions in a zip archive [#3189].
|
- 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: changing motion line length did not invalidate cache [#3202]
|
||||||
- Bugfix: Added more distance in motion PDF for DEL-tags in new lines [#3211].
|
- 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
|
- Added warning message if an edit dialog was already opened by another
|
||||||
@ -48,7 +49,7 @@ Core:
|
|||||||
General:
|
General:
|
||||||
- Switched from npm to Yarn [#3188].
|
- Switched from npm to Yarn [#3188].
|
||||||
- Several bugfixes and minor improvements.
|
- Several bugfixes and minor improvements.
|
||||||
- Bugfixes for PDF creation [#3227]
|
- Bugfixes for PDF creation [#3227, #3251]
|
||||||
|
|
||||||
|
|
||||||
Version 2.1.1 (2017-04-05)
|
Version 2.1.1 (2017-04-05)
|
||||||
|
@ -86,34 +86,46 @@ var replacePlaceholder = function (content) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Workaround for using dynamic footer with page number.
|
||||||
// Create PDF on message and return the base64 decoded document
|
// TODO: Needs improvement of pdfmake's web worker support.
|
||||||
self.addEventListener('message', function(e) {
|
// see https://github.com/bpampuch/pdfmake/issues/38
|
||||||
var data = JSON.parse(e.data);
|
var replaceFooter = function (doc) {
|
||||||
|
if (doc.footerTpl) {
|
||||||
// Workaround for using dynamic footer with page number.
|
doc.footer = function (currentPage, pageCount) {
|
||||||
// TODO: Needs improvement of pdfmake's web worker support.
|
// One way to clone arrays/objects in js, that are serilizeable.
|
||||||
// see https://github.com/bpampuch/pdfmake/issues/38
|
var columns = JSON.parse(JSON.stringify(doc.footerTpl.columns));
|
||||||
if (data.footerTpl) {
|
for (var i = 0; i < columns.length; i++) {
|
||||||
data.footer = function (currentPage, pageCount) {
|
if (columns[i].text) {
|
||||||
for(var i = 0; i < data.footerTpl.columns.length; i++) {
|
columns[i].text = columns[i].text
|
||||||
if (data.footerTpl.columns[i].text) {
|
|
||||||
data.footerTpl.columns[i].text = data.footerTpl.columns[i].text
|
|
||||||
.replace('{{currentPage}}', currentPage)
|
.replace('{{currentPage}}', currentPage)
|
||||||
.replace('{{pageCount}}', pageCount);
|
.replace('{{pageCount}}', pageCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
columns: data.footerTpl.columns,
|
columns: columns,
|
||||||
margin: data.footerTpl.margin,
|
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) {
|
pdf.getBase64(function (base64) {
|
||||||
self.postMessage(base64);
|
if (data.filename) {
|
||||||
|
self.postMessage(JSON.stringify({
|
||||||
|
filename: data.filename,
|
||||||
|
base64: base64
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
self.postMessage(base64);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}, false);
|
}, false);
|
||||||
|
@ -1008,7 +1008,34 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
|||||||
pdfWorker.addEventListener('error', function (event) {
|
pdfWorker.addEventListener('error', function (event) {
|
||||||
reject(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) {
|
download: function (pdfDocument, filename) {
|
||||||
|
@ -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.
|
params.filename = void 0; // clear this, so we do not override the default filenames for each pdf.
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
var pdfs = {};
|
|
||||||
var usedFilenames = [];
|
var usedFilenames = [];
|
||||||
var pdfPromises = _.map(motions, function (motion) {
|
var docMap = {};
|
||||||
|
var docPromises = _.map(motions, function (motion) {
|
||||||
var identifier = motion.identifier ? '-' + motion.identifier : '';
|
var identifier = motion.identifier ? '-' + motion.identifier : '';
|
||||||
var filename = gettextCatalog.getString('Motion') + identifier;
|
var filename = gettextCatalog.getString('Motion') + identifier;
|
||||||
|
|
||||||
@ -742,36 +742,30 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
usedFilenames.push(filename);
|
usedFilenames.push(filename);
|
||||||
filename += '.pdf';
|
filename += '.pdf';
|
||||||
|
|
||||||
return $q(function (resolve, reject) {
|
return $q(function (resolve) {
|
||||||
// get documentProvider for every motion.
|
// get documentProvider for every motion.
|
||||||
self.getDocumentProvider(motion, params, true).then(function (documentProvider) {
|
self.getDocumentProvider(motion, params, true).then(function (documentProvider) {
|
||||||
var doc = documentProvider.getDocument();
|
docMap[filename] = documentProvider.getDocument();
|
||||||
|
resolve();
|
||||||
PdfCreate.getBase64FromDocument(doc).then(function (data) {
|
|
||||||
pdfs[filename] = data;
|
|
||||||
resolve();
|
|
||||||
}, function (error) {
|
|
||||||
reject(error);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
$q.all(docPromises).then(function () {
|
||||||
// Wait for all documents to be generated. Then put them into a zip and download it.
|
PdfCreate.getBase64FromMultipleDocuments(docMap).then(function (pdfMap) {
|
||||||
$q.all(pdfPromises).then(function () {
|
var zip = new JSZip();
|
||||||
var zip = new JSZip();
|
_.forEach(pdfMap, function (data, filename) {
|
||||||
_.forEach(pdfs, function (data, filename) {
|
zip.file(filename, data, {base64: true});
|
||||||
zip.file(filename, data, {base64: true});
|
});
|
||||||
|
Messaging.createOrEditMessage(messageId, '<i class="fa fa-check fa-lg spacer-right"></i>' +
|
||||||
|
gettextCatalog.getString('ZIP successfully generated.'), 'success', {timeout: 3000});
|
||||||
|
zip.generateAsync({type: 'blob'}).then(function (content) {
|
||||||
|
FileSaver.saveAs(content, zipFilename);
|
||||||
|
});
|
||||||
|
}, function (error) {
|
||||||
|
Messaging.createOrEditMessage(messageId, '<i class="fa fa-exclamation-triangle fa-lg ' +
|
||||||
|
'spacer-right"></i>' + gettextCatalog.getString('Error while generating ZIP file') +
|
||||||
|
': <code>' + error + '</code>', 'error');
|
||||||
});
|
});
|
||||||
Messaging.createOrEditMessage(messageId, '<i class="fa fa-check fa-lg spacer-right"></i>' +
|
|
||||||
gettextCatalog.getString('ZIP successfully generated.'), 'success', {timeout: 3000});
|
|
||||||
zip.generateAsync({type: 'blob'}).then(function (content) {
|
|
||||||
FileSaver.saveAs(content, zipFilename);
|
|
||||||
});
|
|
||||||
}, function (error) {
|
|
||||||
Messaging.createOrEditMessage(messageId, '<i class="fa fa-exclamation-triangle fa-lg ' +
|
|
||||||
'spacer-right"></i>' + gettextCatalog.getString('Error while generating ZIP file') +
|
|
||||||
': <code>' + error + '</code>', 'error');
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
createPollPdf: function (motion, version) {
|
createPollPdf: function (motion, version) {
|
||||||
|
Loading…
Reference in New Issue
Block a user