Added page numbers and categories in TOC of motion PDF.

This commit is contained in:
Sean Engelhardt 2018-06-21 15:46:59 +02:00 committed by Emanuel Schütze
parent 166d287a75
commit 6e4665041e
5 changed files with 144 additions and 77 deletions

View File

@ -14,6 +14,8 @@ Motions:
and list views for amendments) [#3637].
- New feature to customize workflows and states [#3772].
- New config options to show logos on the right side in PDF [#3768].
- New table of contents with page numbers and categories in PDF [#3766].
- Updated pdfMake to 0.1.37 [#3766].
Version 2.2 (2018-06-06)

View File

@ -37,7 +37,7 @@
"ngstorage": "~0.3.11",
"ngBootbox": "~0.1.3",
"papaparse": "~4.1.2",
"pdfmake": "0.1.33",
"pdfmake": "0.1.37",
"roboto-fontface": "~0.6.0"
},
"overrides": {

View File

@ -360,9 +360,23 @@ angular.module('OpenSlidesApp.core.pdf', [])
fontSize: 12,
margin: [15,5]
},
tableofcontent: {
tocEntry: {
fontSize: 12,
margin: [0,3]
margin: [0,0,0,0],
bold: false
},
tocCategoryEntry: {
fontSize: 12,
margin: [10,0,0,0],
bold: false
},
tocCategoryTitle: {
fontSize: 12,
margin: [0,0,0,0],
bold: true,
},
tocCategorySection: {
margin: [0,0,0,10],
},
listParent: {
fontSize: 12,

View File

@ -460,6 +460,10 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
return motion.identifier ? motion.identifier : '';
};
var getId = function() {
return motion.id;
};
var getCategory = function() {
return motion.category;
};
@ -476,6 +480,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
getContent: getContent,
getTitle: getTitle,
getIdentifier: getIdentifier,
getId: getId,
getCategory: getCategory,
getImageMap: getImageMap,
});
@ -833,8 +838,9 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
* Constructor
* @function
* @param {object} allMotions - A sorted array of all motions to parse
* @param {string} sorting - The way the catalog has been sorted. Necessary for ToC
*/
var createInstance = function(allMotions) {
var createInstance = function(allMotions, sorting) {
var title = PDFLayout.createTitle(
Config.translate(Config.get('motions_export_title').value)
@ -853,84 +859,130 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
};
var createTOContent = function() {
var heading = {
text: gettextCatalog.getString("Table of contents"),
style: "heading2"
var toc = [];
var exportCategory = (sorting === 'identifier' || sorting === 'category.prefix');
var uniqueCategories = getUniqueCategories();
var tocTitle = {
text: gettextCatalog.getString('Table of contents'),
style: 'heading2'
};
var toc = [];
angular.forEach(allMotions, function(motion) {
var identifier = motion.getIdentifier() ? motion.getIdentifier() : '';
toc.push(
// all motions need a page ID. We use the motion identifier for that
_.forEach(allMotions, function (motion) {
motion.getContent()[0].id = ''+motion.getId();
});
if (exportCategory && uniqueCategories) {
// own table per category
var catTocBody = [];
_.forEach(uniqueCategories, function (category) {
// push the name of the category
// make a table for correct alignment
catTocBody.push({
table: {
body: [
[
{
columns: [
text: category.prefix + ' - ' + category.name,
style: 'tocCategoryTitle'
}
],
]
},
layout: 'noBorders',
});
var tocBody = [];
_.forEach(allMotions, function (motion) {
if (motion.getCategory() && category.name === motion.getCategory().name) {
tocBody.push(tocLine(motion, 'tocCategoryEntry'));
}
});
catTocBody.push(tocTable(tocBody));
});
//handle thouse without category
var uncatTocBody = [];
_.forEach(allMotions, function (motion) {
if (!motion.getCategory()) {
uncatTocBody.push(tocLine(motion, 'tocEntry'));
}
});
// only push this array if there is at least one entry
if (uncatTocBody.length > 0) {
catTocBody.push(tocTable(uncatTocBody));
}
toc.push(catTocBody);
} else {
// all categories in the same table
var tocBody = [];
_.forEach(allMotions, function (motion) {
tocBody.push(tocLine(motion, 'tocEntry'));
});
toc.push(tocTable(tocBody));
}
return [
tocTitle,
toc,
PDFLayout.addPageBreak()
];
};
// creates a new table of contents table body
var tocTable = function (tocBody) {
return {
table: {
widths: ['auto', '*', 'auto'],
body: tocBody
},
layout: 'noBorders',
style: 'tocCategorySection'
};
};
// generates a line in the toc as list-object
var tocLine = function (motion, style) {
var firstColumn = "";
if (motion.getIdentifier()) {
firstColumn = motion.getIdentifier();
}
return [
{
text: identifier,
style: 'tableofcontent',
width: 70
text: firstColumn,
style: style
},
{
text: motion.getTitle(),
style: 'tableofcontent'
}
]
}
);
});
return [
heading,
toc,
PDFLayout.addPageBreak()
];
};
// function to create the table of catergories (if any)
var createTOCategories = function() {
var categories = [];
_.forEach(allMotions, function (motion) {
var category = motion.getCategory();
if (category) {
categories.push(category);
}
});
var sortKey = Config.get('motions_export_category_sorting').value;
categories = _.orderBy(_.uniqBy(categories, 'id'), [sortKey]);
if (categories.length > 1) {
var heading = {
text: gettextCatalog.getString('Categories'),
style: 'heading2',
};
var toc = [];
angular.forEach(categories, function(cat) {
toc.push(
{
columns: [
{
text: cat.prefix,
style: 'tableofcontent',
width: 50
style: 'tocEntry'
},
{
text: cat.name,
style: 'tableofcontent'
}
]
pageReference: ''+motion.getId(),
style: 'tocEntry',
alignment: 'right'
},
];
};
// returns a list of unique category names
// necessary to create a ToC with categories
// if a motions without category is found,
// a corresponding entry should be added aswell
var getUniqueCategories = function() {
var categories = [];
_.forEach(allMotions, function (motion) {
if (motion.getCategory()) {
categories.push(
{
name: motion.getCategory().name,
prefix: motion.getCategory().prefix
}
);
});
return [
heading,
toc,
PDFLayout.addPageBreak()
];
} else {
// if there are no categories, return "empty string"
// pdfmake takes "null" literally and throws an error
return "";
}
});
return _.uniqBy(categories, 'name');
};
// returns the pure content of the motion, parseable by pdfmake
@ -948,7 +1000,6 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
content.push(
title,
createPreamble(),
createTOCategories(),
createTOContent()
);
}
@ -1253,7 +1304,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
if (singleMotion) {
documentProviderPromise = PdfMakeDocumentProvider.createInstance(motionContentProviderArray[0]);
} else {
var motionCatalogContentProvider = MotionCatalogContentProvider.createInstance(motionContentProviderArray);
var motionCatalogContentProvider = MotionCatalogContentProvider.createInstance(motionContentProviderArray, params.column);
documentProviderPromise = PdfMakeDocumentProvider.createInstance(motionCatalogContentProvider);
}
documentProviderPromise.then(function (documentProvider) {

View File

@ -1454,7 +1454,7 @@ angular.module('OpenSlidesApp.motions.site', [
};
// Export dialog
$scope.openExportDialog = function (motions) {
ngDialog.open(MotionExportForm.getDialog(motions));
ngDialog.open(MotionExportForm.getDialog(motions, $scope.sort));
};
$scope.pdfExport = function (motions) {
MotionPdfExport.export(motions);