From 1949a00ee73b64ec7a01aabc3994153522bb1ba2 Mon Sep 17 00:00:00 2001 From: FinnStutzenstein Date: Mon, 5 Mar 2018 11:51:35 +0100 Subject: [PATCH] Moved image sources to the virtual filesystem --- openslides/core/static/js/core/pdf.js | 79 ++++++++++++++++----- openslides/motions/static/js/motions/pdf.js | 63 +++++++++++----- openslides/topics/static/js/topics/site.js | 4 +- 3 files changed, 109 insertions(+), 37 deletions(-) diff --git a/openslides/core/static/js/core/pdf.js b/openslides/core/static/js/core/pdf.js index 1c10ea65b..40492045b 100644 --- a/openslides/core/static/js/core/pdf.js +++ b/openslides/core/static/js/core/pdf.js @@ -87,7 +87,7 @@ angular.module('OpenSlidesApp.core.pdf', []) return '{{ballot-placeholder-to-insert-functions-here}}'; }; - // returns a promise for converting an image in data URL format + // returns a promise for converting an image in data URL format with size information PDFLayout.imageURLtoBase64 = function(url) { var promise = new Promise(function(resolve) { var img = new Image(); @@ -170,15 +170,18 @@ angular.module('OpenSlidesApp.core.pdf', []) // Logo urls var logoHeaderUrl = Config.get('logo_pdf_header').value.path, logoFooterUrl = Config.get('logo_pdf_footer').value.path; - var imageMap = {}; + var imageMap = contentProvider.getImageMap(); // PDF header var getHeader = function() { var columns = []; if (logoHeaderUrl) { + if (logoHeaderUrl.indexOf('/') === 0) { + logoHeaderUrl = logoHeaderUrl.substr(1); // remove trailing / + } columns.push({ - image: imageMap[logoHeaderUrl].data, + image: logoHeaderUrl, fit: [180, 40], width: '20%' }); @@ -216,8 +219,11 @@ angular.module('OpenSlidesApp.core.pdf', []) var columns = []; if (logoFooterUrl) { + if (logoFooterUrl.indexOf('/') === 0) { + logoFooterUrl = logoFooterUrl.substr(1); // remove trailing / + } columns.push({ - image: imageMap[logoFooterUrl].data, + image: logoFooterUrl, fit: [400,50], width: '80%' }); @@ -338,15 +344,24 @@ angular.module('OpenSlidesApp.core.pdf', []) }; }; + var getImageMap = function () { + return imageMap; + }; + return $q(function (resolve) { var imageSources = [ logoHeaderUrl, logoFooterUrl ]; ImageConverter.toBase64(imageSources).then(function (_imageMap) { - imageMap = _imageMap; + _.forEach(_imageMap, function (data, path) { + if (!imageMap[path]) { + imageMap[path] = data; + } + }); resolve({ - getDocument: getDocument + getDocument: getDocument, + getImageMap: getImageMap, }); }); }); @@ -393,8 +408,14 @@ angular.module('OpenSlidesApp.core.pdf', []) } }; }; + + var getImageMap = function() { + return contentProvider.getImageMap(); + }; + return { - getDocument: getDocument + getDocument: getDocument, + getImageMap: getImageMap, }; }; return { @@ -937,8 +958,12 @@ angular.module('OpenSlidesApp.core.pdf', []) imageSize.width *= scaleByHeight; imageSize.height *= scaleByHeight; } + var path = element.getAttribute("src"); + if (path.indexOf('/') === 0) { + path = path.substr(1); // remove trailing / + } alreadyConverted.push({ - image: images[element.getAttribute("src")].data, + image: path, width: imageSize.width, height: imageSize.height }); @@ -1064,8 +1089,8 @@ angular.module('OpenSlidesApp.core.pdf', []) var imageMap = {}; var imagePromises = _.map(imageSources, function (imageSource) { if (imageSource) { - return PDFLayout.imageURLtoBase64(imageSource).then(function (base64Str) { - imageMap[imageSource] = base64Str; + return PDFLayout.imageURLtoBase64(imageSource).then(function (imgInfo) { + imageMap[imageSource] = imgInfo; }); } }); @@ -1127,10 +1152,17 @@ angular.module('OpenSlidesApp.core.pdf', []) /* * Create the virtual filesystem needed by PdfMake for the fonts. Gets the url * mapping and loads all fonts via get requests or the urlCache. + * Adds all image sources to the vfs given by the imageMap. */ - var getVfs = function () { + var getVfs = function (imageMap) { + var vfs = {}; + _.forEach(imageMap || {}, function (data, path) { + if (path.indexOf('/') === 0) { + path = path.substr(1); // remove trailing / + } + vfs[path] = data.data.split(',')[1]; + }); return $q(function (resolve, reject) { - var vfs = {}; var urls = getUrlMapping(); var promises = _.chain(urls) .map(function (filenames, url) { @@ -1209,9 +1241,9 @@ angular.module('OpenSlidesApp.core.pdf', []) }, 1); }; return { - getBase64FromDocument: function (pdfDocument) { + getBase64FromDocument: function (documentProvider) { return $q(function (resolve, reject) { - PdfVfs.get().then(function (vfs) { + PdfVfs.get(documentProvider.getImageMap()).then(function (vfs) { var pdfWorker = new Worker('/static/js/workers/pdf-worker.js'); pdfWorker.addEventListener('message', function (event) { resolve(event.data); @@ -1220,7 +1252,7 @@ angular.module('OpenSlidesApp.core.pdf', []) reject(event); }); pdfWorker.postMessage(JSON.stringify({ - pdfDocument: pdfDocument, + pdfDocument: documentProvider.getDocument(), vfs: vfs, })); }); @@ -1228,8 +1260,17 @@ angular.module('OpenSlidesApp.core.pdf', []) }, // Struckture of pdfDocuments: { filname1: doc, filename2: doc, ...} getBase64FromMultipleDocuments: function (pdfDocuments) { + // concat all image sources together + var imageMap = {}; + _.forEach(pdfDocuments, function (doc) { + _.forEach(doc.getImageMap(), function (data, path) { + if (!imageMap[path]) { + imageMap[path] = data; + } + }); + }); return $q(function (resolve, reject) { - PdfVfs.get().then(function (vfs) { + PdfVfs.get(imageMap).then(function (vfs) { var pdfWorker = new Worker('/static/js/workers/pdf-worker.js'); var resultCount = 0; var base64Map = {}; // Maps filename to base64 @@ -1247,17 +1288,17 @@ angular.module('OpenSlidesApp.core.pdf', []) _.forEach(pdfDocuments, function (doc, filename) { pdfWorker.postMessage(JSON.stringify({ filename: filename, - pdfDocument: doc, + pdfDocument: doc.getDocument(), vfs: vfs, })); }); }); }); }, - download: function (pdfDocument, filename) { + download: function (documentProvider, filename) { stateChange('info', filename); - this.getBase64FromDocument(pdfDocument).then(function (data) { + this.getBase64FromDocument(documentProvider).then(function (data) { var blob = b64toBlob(data); stateChange('success', filename); FileSaver.saveAs(blob, filename); diff --git a/openslides/motions/static/js/motions/pdf.js b/openslides/motions/static/js/motions/pdf.js index 11d543945..844366eca 100644 --- a/openslides/motions/static/js/motions/pdf.js +++ b/openslides/motions/static/js/motions/pdf.js @@ -42,7 +42,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf']) includeComments: {}, }); - var converter; + var converter, imageMap = {}; // Query all image sources from motion text and reason var getImageSources = function () { @@ -426,14 +426,20 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf']) return motion.category; }; + var getImageMap = function() { + return imageMap; + }; + return $q(function (resolve) { - ImageConverter.toBase64(getImageSources()).then(function (imageMap) { - converter = PdfMakeConverter.createInstance(imageMap); + ImageConverter.toBase64(getImageSources()).then(function (_imageMap) { + imageMap = _imageMap; + converter = PdfMakeConverter.createInstance(_imageMap); resolve({ getContent: getContent, getTitle: getTitle, getIdentifier: getIdentifier, - getCategory: getCategory + getCategory: getCategory, + getImageMap: getImageMap, }); }); }); @@ -461,7 +467,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf']) * */ var createInstance = function (motion, content) { - var converter; + var converter, imageMap = {}; // Query all image sources from the content var getImageSources = function () { @@ -593,11 +599,17 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf']) return pdfContent; }; + var getImageMap = function () { + return imageMap; + }; + return $q(function (resolve) { - ImageConverter.toBase64(getImageSources()).then(function (imageMap) { - converter = PdfMakeConverter.createInstance(imageMap); + ImageConverter.toBase64(getImageSources()).then(function (_imageMap) { + imageMap = _imageMap; + converter = PdfMakeConverter.createInstance(_imageMap); resolve({ getContent: getContent, + getImageMap: getImageMap, }); }); }); @@ -643,7 +655,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf']) // logo if (logoBallotPaperUrl) { columns.push({ - image: imageMap[logoBallotPaperUrl].data, + image: logoBallotPaperUrl, fit: [90,25], alignment: 'right', width: '40%' @@ -750,6 +762,10 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf']) return content; }; + var getImageMap = function () { + return imageMap; + }; + return $q(function (resolve) { var imageSources = [ logoBallotPaperUrl, @@ -757,7 +773,8 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf']) ImageConverter.toBase64(imageSources).then(function (_imageMap) { imageMap = _imageMap; resolve({ - getContent: getContent + getContent: getContent, + getImageMap: getImageMap, }); }); }); @@ -881,7 +898,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf']) // returns the pure content of the motion, parseable by pdfmake var getContent = function() { var motionContent = []; - angular.forEach(allMotions, function(motion, key) { + _.forEach(allMotions, function(motion, key) { motionContent.push(motion.getContent()); if (key < allMotions.length - 1) { motionContent.push(PDFLayout.addPageBreak()); @@ -900,8 +917,22 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf']) content.push(motionContent); return content; }; + + var getImageMap = function () { + var imageMap = {}; + _.forEach(allMotions, function (motion) { + _.forEach(motion.getImageMap(), function (data, path) { + if (!imageMap[path]) { + imageMap[path] = data; + } + }); + }); + return imageMap; + }; + return { - getContent: getContent + getContent: getContent, + getImageMap: getImageMap, }; }; @@ -992,7 +1023,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf']) }); this.getDocumentProvider(motions, params, singleMotion).then( function (documentProvider) { - PdfCreate.download(documentProvider.getDocument(), params.filename); + PdfCreate.download(documentProvider, params.filename); } ); }, @@ -1025,7 +1056,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf']) return $q(function (resolve) { // get documentProvider for every motion. self.getDocumentProvider(motion, params, true).then(function (documentProvider) { - docMap[filename] = documentProvider.getDocument(); + docMap[filename] = documentProvider; resolve(); }); }); @@ -1054,7 +1085,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf']) var filename = gettextCatalog.getString('Motion') + '-' + id + '-' + gettextCatalog.getString('ballot-paper') + '.pdf'; PollContentProvider.createInstance(title, id).then(function (pollContentProvider) { var documentProvider = PdfMakeBallotPaperProvider.createInstance(pollContentProvider); - PdfCreate.download(documentProvider.getDocument(), filename); + PdfCreate.download(documentProvider, filename); }); }, exportPersonalNote: function (motion, filename) { @@ -1065,7 +1096,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf']) }]; MotionPartialContentProvider.createInstance(motion, content).then(function (contentProvider) { PdfMakeDocumentProvider.createInstance(contentProvider).then(function (documentProvider) { - PdfCreate.download(documentProvider.getDocument(), filename); + PdfCreate.download(documentProvider, filename); }); }); }, @@ -1082,7 +1113,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf']) }]; MotionPartialContentProvider.createInstance(motion, content).then(function (contentProvider) { PdfMakeDocumentProvider.createInstance(contentProvider).then(function (documentProvider) { - PdfCreate.download(documentProvider.getDocument(), filename); + PdfCreate.download(documentProvider, filename); }); }); } diff --git a/openslides/topics/static/js/topics/site.js b/openslides/topics/static/js/topics/site.js index e8ddc1929..ff4922aa8 100644 --- a/openslides/topics/static/js/topics/site.js +++ b/openslides/topics/static/js/topics/site.js @@ -257,9 +257,9 @@ angular.module('OpenSlidesApp.topics.site', ['OpenSlidesApp.topics', 'OpenSlides // import from textarea $scope.importByLine = function () { if ($scope.itemlist) { - $scope.titleItems = $scope.itemlist[0].split("\n"); + $scope.titleItems = _.filter($scope.itemlist[0].split("\n")); $scope.importcounter = 0; - $scope.titleItems.forEach(function(title, index) { + _.forEach($scope.titleItems, function(title, index) { var item = {title: title}; item.agenda_type = 1; // The new topic is not hidden. item.agenda_weight = 1000 + index;