Updated PDF layout
- use default font for pdf from vfs_font.js remove base64 encoding function on server side - use recommendation config value in motion detail template
This commit is contained in:
parent
18accc58ae
commit
4e1fdc6b22
@ -40,7 +40,10 @@
|
||||
},
|
||||
"overrides": {
|
||||
"pdfmake-dist-dist": {
|
||||
"main": "build/pdfmake.min.js"
|
||||
"main": [
|
||||
"build/pdfmake.min.js",
|
||||
"build/vfs_fonts.js"
|
||||
]
|
||||
},
|
||||
"pdfjs-dist": {
|
||||
"main": "build/pdf.combined.js"
|
||||
|
@ -6,15 +6,15 @@ angular.module('OpenSlidesApp.agenda.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
|
||||
.factory('AgendaContentProvider', [
|
||||
'gettextCatalog',
|
||||
'PdfPredefinedFunctions',
|
||||
function(gettextCatalog, PdfPredefinedFunctions) {
|
||||
'PDFLayout',
|
||||
function(gettextCatalog, PDFLayout) {
|
||||
|
||||
var createInstance = function(items) {
|
||||
|
||||
//use the Predefined Functions to create the title
|
||||
var title = PdfPredefinedFunctions.createTitle(gettextCatalog.getString("Agenda"));
|
||||
// page title
|
||||
var title = PDFLayout.createTitle(gettextCatalog.getString("Agenda"));
|
||||
|
||||
//function to generate the item list out of the given "items" object
|
||||
// generate the item list with all subitems
|
||||
var createItemList = function() {
|
||||
var agenda_items = [];
|
||||
angular.forEach(items, function (item) {
|
||||
|
@ -315,7 +315,7 @@ angular.module('OpenSlidesApp.agenda.site', [
|
||||
};
|
||||
|
||||
$scope.makePDF = function() {
|
||||
var filename = gettextCatalog.getString("Agenda")+".pdf";
|
||||
var filename = gettextCatalog.getString('Agenda') + '.pdf';
|
||||
var agendaContentProvider = AgendaContentProvider.createInstance($scope.items);
|
||||
var documentProvider = PdfMakeDocumentProvider.createInstance(agendaContentProvider);
|
||||
pdfMake.createPdf(documentProvider.getDocument()).download(filename);
|
||||
|
@ -6,15 +6,15 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
|
||||
.factory('AssignmentContentProvider', [
|
||||
'gettextCatalog',
|
||||
'PdfPredefinedFunctions',
|
||||
function(gettextCatalog, PdfPredefinedFunctions) {
|
||||
'PDFLayout',
|
||||
function(gettextCatalog, PDFLayout) {
|
||||
|
||||
var createInstance = function(assignment) {
|
||||
|
||||
//use the Predefined Functions to create the title
|
||||
var title = PdfPredefinedFunctions.createTitle(assignment.title);
|
||||
// page title
|
||||
var title = PDFLayout.createTitle(assignment.title);
|
||||
|
||||
//create the preamble
|
||||
// number of posts
|
||||
var createPreamble = function() {
|
||||
var preambleText = gettextCatalog.getString("Number of posts to be elected") + ": ";
|
||||
var memberNumber = ""+assignment.open_posts;
|
||||
@ -34,7 +34,7 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
return preamble;
|
||||
};
|
||||
|
||||
//adds the description if present in the assignment
|
||||
// description
|
||||
var createDescription = function() {
|
||||
if (assignment.description) {
|
||||
var descriptionText = gettextCatalog.getString("Description") + ":";
|
||||
@ -56,7 +56,7 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
}
|
||||
};
|
||||
|
||||
//creates the candidate list in columns if the assignment phase is 'voting'
|
||||
// show candidate list (if assignment phase is not 'finished')
|
||||
var createCandidateList = function() {
|
||||
if (assignment.phase != 2) {
|
||||
var candidatesText = gettextCatalog.getString("Candidates") + ": ";
|
||||
@ -90,23 +90,23 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
}
|
||||
};
|
||||
|
||||
//handles the case if a candidate is elected or not
|
||||
// handles the case if a candidate is elected or not
|
||||
var electedCandidateLine = function(candidateName, pollOption, pollTableBody) {
|
||||
if (pollOption.is_elected) {
|
||||
return {
|
||||
text: candidateName + "*",
|
||||
bold: true,
|
||||
style: PdfPredefinedFunctions.flipTableRowStyle(pollTableBody.length)
|
||||
style: PDFLayout.flipTableRowStyle(pollTableBody.length)
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
text: candidateName,
|
||||
style: PdfPredefinedFunctions.flipTableRowStyle(pollTableBody.length)
|
||||
style: PDFLayout.flipTableRowStyle(pollTableBody.length)
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
//creates the pull result table
|
||||
// creates the election result table
|
||||
var createPollResultTable = function() {
|
||||
var resultBody = [];
|
||||
angular.forEach(assignment.polls, function(poll, pollIndex) {
|
||||
@ -144,7 +144,7 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
electedCandidateLine(candidateName, pollOption, pollTableBody),
|
||||
{
|
||||
text: votes[0].value + " " + votes[0].percentStr,
|
||||
style: PdfPredefinedFunctions.flipTableRowStyle(pollTableBody.length)
|
||||
style: PDFLayout.flipTableRowStyle(pollTableBody.length)
|
||||
}
|
||||
]);
|
||||
} else if (poll.pollmethod == 'yn') {
|
||||
@ -163,7 +163,7 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
votes[1].percentStr
|
||||
}
|
||||
],
|
||||
style: PdfPredefinedFunctions.flipTableRowStyle(pollTableBody.length)
|
||||
style: PDFLayout.flipTableRowStyle(pollTableBody.length)
|
||||
}
|
||||
]);
|
||||
} else if (poll.pollmethod == 'yna') {
|
||||
@ -187,7 +187,7 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
votes[2].percentStr
|
||||
}
|
||||
],
|
||||
style: PdfPredefinedFunctions.flipTableRowStyle(pollTableBody.length)
|
||||
style: PDFLayout.flipTableRowStyle(pollTableBody.length)
|
||||
}
|
||||
]);
|
||||
}
|
||||
@ -247,7 +247,7 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
}
|
||||
});
|
||||
|
||||
//Add the legend to the result body
|
||||
// add the legend to the result body
|
||||
if (assignment.polls.length > 0) {
|
||||
resultBody.push({
|
||||
text: "* = " + gettextCatalog.getString("is elected"),
|
||||
@ -281,12 +281,12 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
|
||||
.factory('BallotContentProvider', [
|
||||
'gettextCatalog',
|
||||
'PdfPredefinedFunctions',
|
||||
function(gettextCatalog, PdfPredefinedFunctions) {
|
||||
'PDFLayout',
|
||||
function(gettextCatalog, PDFLayout) {
|
||||
|
||||
var createInstance = function(scope, poll, pollNumber) {
|
||||
|
||||
// use the Predefined Functions to create the title
|
||||
// page title
|
||||
var createTitle = function() {
|
||||
return {
|
||||
text: scope.assignment.title,
|
||||
@ -294,7 +294,7 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
};
|
||||
};
|
||||
|
||||
//function to create the poll hint
|
||||
// poll description
|
||||
var createPollHint = function() {
|
||||
var description = poll.description ? ': ' + poll.description : '';
|
||||
return {
|
||||
@ -303,19 +303,19 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
};
|
||||
};
|
||||
|
||||
//function to create the selection entries
|
||||
// election entries
|
||||
var createYNBallotEntry = function(decision) {
|
||||
var YNColumn = [
|
||||
{
|
||||
width: "auto",
|
||||
stack: [
|
||||
PdfPredefinedFunctions.createBallotEntry(gettextCatalog.getString("Yes"))
|
||||
PDFLayout.createBallotEntry(gettextCatalog.getString("Yes"))
|
||||
]
|
||||
},
|
||||
{
|
||||
width: "auto",
|
||||
stack: [
|
||||
PdfPredefinedFunctions.createBallotEntry(gettextCatalog.getString("No"))
|
||||
PDFLayout.createBallotEntry(gettextCatalog.getString("No"))
|
||||
]
|
||||
},
|
||||
];
|
||||
@ -324,7 +324,7 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
YNColumn.push({
|
||||
width: "auto",
|
||||
stack: [
|
||||
PdfPredefinedFunctions.createBallotEntry(gettextCatalog.getString("Abstain"))
|
||||
PDFLayout.createBallotEntry(gettextCatalog.getString("Abstain"))
|
||||
]
|
||||
});
|
||||
}
|
||||
@ -346,7 +346,7 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
if (poll.pollmethod == 'votes') {
|
||||
angular.forEach(poll.options, function(option) {
|
||||
var candidate = option.candidate.get_full_name();
|
||||
candidateBallotList.push(PdfPredefinedFunctions.createBallotEntry(candidate));
|
||||
candidateBallotList.push(PDFLayout.createBallotEntry(candidate));
|
||||
});
|
||||
} else {
|
||||
angular.forEach(poll.options, function(option) {
|
||||
@ -361,7 +361,6 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
|
||||
// since it is not possible to give a column a fixed height, we draw an "empty" column
|
||||
// with a one px width and a fixed top-margin
|
||||
|
||||
return {
|
||||
columns : [
|
||||
{
|
||||
@ -431,7 +430,7 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
widths: ['50%', '50%'],
|
||||
body: tableBody
|
||||
},
|
||||
layout: PdfPredefinedFunctions.getBallotLayoutLines()
|
||||
layout: PDFLayout.getBallotLayoutLines()
|
||||
}];
|
||||
};
|
||||
|
||||
@ -451,13 +450,13 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
|
||||
.factory('AssignmentCatalogContentProvider', [
|
||||
'gettextCatalog',
|
||||
'PdfPredefinedFunctions',
|
||||
'PDFLayout',
|
||||
'Config',
|
||||
function(gettextCatalog, PdfPredefinedFunctions, Config) {
|
||||
function(gettextCatalog, PDFLayout, Config) {
|
||||
|
||||
var createInstance = function(allAssignmnets) {
|
||||
|
||||
var title = PdfPredefinedFunctions.createTitle(
|
||||
var title = PDFLayout.createTitle(
|
||||
gettextCatalog.getString(Config.get('assignments_pdf_title').value)
|
||||
);
|
||||
|
||||
@ -476,7 +475,7 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
var createTOContent = function(assignmentTitles) {
|
||||
var heading = {
|
||||
text: gettextCatalog.getString("Table of contents"),
|
||||
style: "heading",
|
||||
style: "heading2",
|
||||
};
|
||||
|
||||
var toc = [];
|
||||
@ -490,7 +489,7 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
return [
|
||||
heading,
|
||||
toc,
|
||||
PdfPredefinedFunctions.addPageBreak()
|
||||
PDFLayout.addPageBreak()
|
||||
];
|
||||
};
|
||||
|
||||
@ -503,7 +502,7 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
assignmentTitles.push(assignment.title);
|
||||
assignmentContent.push(assignment.getContent());
|
||||
if (key < allAssignmnets.length - 1) {
|
||||
assignmentContent.push(PdfPredefinedFunctions.addPageBreak());
|
||||
assignmentContent.push(PDFLayout.addPageBreak());
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -4,23 +4,51 @@
|
||||
|
||||
angular.module('OpenSlidesApp.core.pdf', [])
|
||||
|
||||
.factory('PdfPredefinedFunctions', [
|
||||
/*
|
||||
* General layout functions for building PDFs with pdfmake.
|
||||
*/
|
||||
.factory('PDFLayout', [
|
||||
function() {
|
||||
var PdfPredefinedFunctions = {};
|
||||
var PDFLayout = {};
|
||||
var BallotCircleDimensions = {
|
||||
yDistance: 6,
|
||||
size: 8
|
||||
};
|
||||
|
||||
PdfPredefinedFunctions.createTitle = function(titleString) {
|
||||
// Set and return default font family.
|
||||
//
|
||||
// To use custom ttf font files you have to replace the vfs_fonts.js file.
|
||||
// See https://github.com/pdfmake/pdfmake/wiki/Custom-Fonts---client-side
|
||||
PDFLayout.getFontName = function() {
|
||||
pdfMake.fonts = {
|
||||
Roboto: {
|
||||
normal: 'Roboto-Regular.ttf',
|
||||
bold: 'Roboto-Medium.ttf',
|
||||
italics: 'Roboto-Italic.ttf',
|
||||
bolditalics: 'Roboto-Italic.ttf'
|
||||
}
|
||||
};
|
||||
return "Roboto";
|
||||
};
|
||||
|
||||
// page title
|
||||
PDFLayout.createTitle = function(title) {
|
||||
return {
|
||||
text: titleString,
|
||||
text: title,
|
||||
style: "title"
|
||||
};
|
||||
};
|
||||
|
||||
// function to apply a pagebreak-keyword
|
||||
PdfPredefinedFunctions.addPageBreak = function() {
|
||||
// page subtitle
|
||||
PDFLayout.createSubtitle = function(subtitle) {
|
||||
return {
|
||||
text: subtitle,
|
||||
style: "subtitle"
|
||||
};
|
||||
};
|
||||
|
||||
// pagebreak
|
||||
PDFLayout.addPageBreak = function() {
|
||||
return [
|
||||
{
|
||||
text: '',
|
||||
@ -29,7 +57,8 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
||||
];
|
||||
};
|
||||
|
||||
PdfPredefinedFunctions.flipTableRowStyle = function(currentTableSize) {
|
||||
// table row style
|
||||
PDFLayout.flipTableRowStyle = function(currentTableSize) {
|
||||
if (currentTableSize % 2 === 0) {
|
||||
return "tableEven";
|
||||
} else {
|
||||
@ -37,8 +66,8 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
||||
}
|
||||
};
|
||||
|
||||
//draws a circle
|
||||
PdfPredefinedFunctions.drawCircle = function(y, size) {
|
||||
// draws a circle
|
||||
PDFLayout.drawCircle = function(y, size) {
|
||||
return [
|
||||
{
|
||||
type: 'ellipse',
|
||||
@ -51,14 +80,15 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
||||
];
|
||||
};
|
||||
|
||||
//Returns an entry in the ballot with a circle to draw into
|
||||
PdfPredefinedFunctions.createBallotEntry = function(decision) {
|
||||
// returns an entry in the ballot with a circle to draw into
|
||||
PDFLayout.createBallotEntry = function(decision) {
|
||||
return {
|
||||
margin: [40+BallotCircleDimensions.size, 10, 0, 0],
|
||||
columns: [
|
||||
{
|
||||
width: 15,
|
||||
canvas: PdfPredefinedFunctions.drawCircle(BallotCircleDimensions.yDistance, BallotCircleDimensions.size)
|
||||
canvas: PDFLayout.drawCircle(BallotCircleDimensions.yDistance,
|
||||
BallotCircleDimensions.size)
|
||||
},
|
||||
{
|
||||
width: "auto",
|
||||
@ -68,7 +98,8 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
||||
};
|
||||
};
|
||||
|
||||
PdfPredefinedFunctions.getBallotLayoutLines = function() {
|
||||
// crop marks for ballot papers
|
||||
PDFLayout.getBallotLayoutLines = function() {
|
||||
return {
|
||||
hLineWidth: function(i, node) {
|
||||
return (i === 0 || i === node.table.body.length) ? 0 : 0.5;
|
||||
@ -85,10 +116,11 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
||||
};
|
||||
};
|
||||
|
||||
return PdfPredefinedFunctions;
|
||||
return PDFLayout;
|
||||
}
|
||||
])
|
||||
|
||||
|
||||
.factory('HTMLValidizer', function() {
|
||||
var HTMLValidizer = {};
|
||||
|
||||
@ -111,138 +143,163 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
||||
return HTMLValidizer;
|
||||
})
|
||||
|
||||
|
||||
.factory('PdfMakeDocumentProvider', [
|
||||
'gettextCatalog',
|
||||
'Config',
|
||||
function(gettextCatalog, Config) {
|
||||
'PDFLayout',
|
||||
function(gettextCatalog, Config, PDFLayout) {
|
||||
/**
|
||||
* Provides the global Document
|
||||
* Provides the global document
|
||||
* @constructor
|
||||
* @param {object} contentProvider - Object with on method `getContent`, which returns an array for content
|
||||
* @param {string} defaultFont - Default font for the document
|
||||
* @param {object} contentProvider - Object with on method `getContent`, which
|
||||
* returns an array for content
|
||||
*/
|
||||
var createInstance = function(contentProvider, defaultFont) {
|
||||
/**
|
||||
* Generates header for PDF
|
||||
* @constructor
|
||||
*/
|
||||
var createInstance = function(contentProvider) {
|
||||
// PDF header
|
||||
var header = function() {
|
||||
var date = new Date();
|
||||
return {
|
||||
// alignment: 'center',
|
||||
color: '#555',
|
||||
fontSize: 10,
|
||||
margin: [80, 50, 80, 0], //margin: [left, top, right, bottom]
|
||||
columns: [
|
||||
{
|
||||
text: Config.get('general_event_name').value + ' · ' + Config.get('general_event_description').value ,
|
||||
fontSize:10,
|
||||
width: '70%'
|
||||
},
|
||||
{
|
||||
fontSize: 6,
|
||||
width: '30%',
|
||||
text: gettextCatalog.getString('As of') + " " + date.toLocaleDateString() + " " + date.toLocaleTimeString(),
|
||||
alignment: 'right'
|
||||
}]
|
||||
};
|
||||
},
|
||||
/**
|
||||
* Generates footer line
|
||||
* @function
|
||||
* @param {object} currentPage - An object representing the current page
|
||||
* @param {number} pageCount - number for pages
|
||||
*/
|
||||
footer = function(currentPage, pageCount) {
|
||||
return {
|
||||
alignment: 'center',
|
||||
fontSize: 8,
|
||||
color: '#555',
|
||||
text: gettextCatalog.getString('Page') + ' ' + currentPage.toString() + ' / ' + pageCount.toString()
|
||||
};
|
||||
},
|
||||
/**
|
||||
* Generates the document(definition) for pdfMake
|
||||
* @function
|
||||
*/
|
||||
getDocument = function() {
|
||||
var content = contentProvider.getContent();
|
||||
return {
|
||||
pageSize: 'A4',
|
||||
pageMargins: [80, 90, 80, 60],
|
||||
defaultStyle: {
|
||||
font: defaultFont,
|
||||
fontSize: 10
|
||||
},
|
||||
header: header,
|
||||
footer: footer,
|
||||
content: content,
|
||||
styles: {
|
||||
title: {
|
||||
fontSize: 30,
|
||||
margin: [0,0,0,20],
|
||||
bold: true
|
||||
},
|
||||
preamble: {
|
||||
fontSize: 12,
|
||||
margin: [0,0,0,10],
|
||||
},
|
||||
userDataTitle: {
|
||||
fontSize: 26,
|
||||
margin: [0,0,0,0],
|
||||
bold: true
|
||||
},
|
||||
textItem: {
|
||||
fontSize: 11,
|
||||
margin: [0,7]
|
||||
},
|
||||
heading: {
|
||||
fontSize: 16,
|
||||
margin: [0,0,0,10],
|
||||
bold: true
|
||||
},
|
||||
userDataHeading: {
|
||||
fontSize: 14,
|
||||
margin: [0,10],
|
||||
bold: true
|
||||
},
|
||||
userDataTopic: {
|
||||
fontSize: 12,
|
||||
margin: [0,5]
|
||||
},
|
||||
userDataValue: {
|
||||
fontSize: 12,
|
||||
margin: [15,5]
|
||||
},
|
||||
tableofcontent: {
|
||||
fontSize: 12,
|
||||
margin: [0,3]
|
||||
},
|
||||
listParent: {
|
||||
fontSize: 14,
|
||||
margin: [0,5]
|
||||
},
|
||||
listChild: {
|
||||
fontSize: 11,
|
||||
margin: [0,5]
|
||||
},
|
||||
tableHeader: {
|
||||
bold: true,
|
||||
fillColor: 'white'
|
||||
},
|
||||
tableEven: {
|
||||
fillColor: 'white'
|
||||
},
|
||||
tableOdd: {
|
||||
fillColor: '#eee'
|
||||
},
|
||||
tableConclude: {
|
||||
fillColor: '#ddd',
|
||||
bold: true
|
||||
}
|
||||
}
|
||||
};
|
||||
var date = new Date();
|
||||
var columns = [];
|
||||
|
||||
// add here your custom logo (which has to be added to a custom vfs_fonts.js)
|
||||
// see https://github.com/pdfmake/pdfmake/wiki/Custom-Fonts---client-side
|
||||
/*
|
||||
columns.push({
|
||||
image: 'logo.png',
|
||||
fit: [180,40]
|
||||
});*/
|
||||
|
||||
var line1 = [
|
||||
Config.get('general_event_name').value,
|
||||
Config.get('general_event_description').value
|
||||
].join(' – ');
|
||||
var line2 = [
|
||||
Config.get('general_event_location').value,
|
||||
Config.get('general_event_date').value
|
||||
].join(', ');
|
||||
var text = [line1, line2].join('\n');
|
||||
columns.push({
|
||||
text: text,
|
||||
fontSize:10,
|
||||
width: '100%'
|
||||
});
|
||||
return {
|
||||
color: '#555',
|
||||
fontSize: 9,
|
||||
margin: [80, 30, 80, 10], // [left, top, right, bottom]
|
||||
columns: columns,
|
||||
columnGap: 10
|
||||
};
|
||||
};
|
||||
|
||||
// PDF footer
|
||||
var footer = function(currentPage, pageCount) {
|
||||
return {
|
||||
alignment: 'center',
|
||||
fontSize: 8,
|
||||
color: '#555',
|
||||
text: gettextCatalog.getString('Page') + ' ' + currentPage.toString() +
|
||||
' / ' + pageCount.toString()
|
||||
};
|
||||
};
|
||||
// Generates the document(definition) for pdfMake
|
||||
var getDocument = function() {
|
||||
var content = contentProvider.getContent();
|
||||
return {
|
||||
pageSize: 'A4',
|
||||
pageMargins: [80, 90, 80, 60],
|
||||
defaultStyle: {
|
||||
font: PDFLayout.getFontName(),
|
||||
fontSize: 10
|
||||
},
|
||||
header: header,
|
||||
footer: footer,
|
||||
content: content,
|
||||
styles: {
|
||||
title: {
|
||||
fontSize: 18,
|
||||
margin: [0,0,0,20],
|
||||
bold: true
|
||||
},
|
||||
subtitle: {
|
||||
fontSize: 9,
|
||||
margin: [0,-20,0,20],
|
||||
},
|
||||
preamble: {
|
||||
fontSize: 10,
|
||||
margin: [0,0,0,10],
|
||||
},
|
||||
userDataTitle: {
|
||||
fontSize: 26,
|
||||
margin: [0,0,0,0],
|
||||
bold: true
|
||||
},
|
||||
textItem: {
|
||||
fontSize: 11,
|
||||
margin: [0,7]
|
||||
},
|
||||
heading2: {
|
||||
fontSize: 14,
|
||||
margin: [0,0,0,10],
|
||||
bold: true
|
||||
},
|
||||
heading3: {
|
||||
fontSize: 12,
|
||||
margin: [0,10,0,0],
|
||||
bold: true
|
||||
},
|
||||
userDataHeading: {
|
||||
fontSize: 14,
|
||||
margin: [0,10],
|
||||
bold: true
|
||||
},
|
||||
userDataTopic: {
|
||||
fontSize: 12,
|
||||
margin: [0,5]
|
||||
},
|
||||
userDataValue: {
|
||||
fontSize: 12,
|
||||
margin: [15,5]
|
||||
},
|
||||
tableofcontent: {
|
||||
fontSize: 12,
|
||||
margin: [0,3]
|
||||
},
|
||||
listParent: {
|
||||
fontSize: 12,
|
||||
margin: [0,5]
|
||||
},
|
||||
listChild: {
|
||||
fontSize: 10,
|
||||
margin: [0,5]
|
||||
},
|
||||
tableHeader: {
|
||||
bold: true,
|
||||
fillColor: 'white'
|
||||
},
|
||||
tableEven: {
|
||||
fillColor: 'white'
|
||||
},
|
||||
tableOdd: {
|
||||
fillColor: '#eee'
|
||||
},
|
||||
tableConclude: {
|
||||
fillColor: '#ddd',
|
||||
bold: true
|
||||
},
|
||||
grey: {
|
||||
fillColor: '#ddd',
|
||||
},
|
||||
lightgrey: {
|
||||
fillColor: '#aaa',
|
||||
},
|
||||
bold: {
|
||||
bold: true,
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
getDocument: getDocument
|
||||
};
|
||||
@ -256,14 +313,14 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
||||
.factory('PdfMakeBallotPaperProvider', [
|
||||
'gettextCatalog',
|
||||
'Config',
|
||||
function(gettextCatalog, Config) {
|
||||
'PDFLayout',
|
||||
function(gettextCatalog, Config, PDFLayout) {
|
||||
/**
|
||||
* Provides the global Document
|
||||
* @constructor
|
||||
* @param {object} contentProvider - Object with on method `getContent`, which returns an array for content
|
||||
* @param {string} defaultFont - Default font for the document
|
||||
*/
|
||||
var createInstance = function(contentProvider, defaultFont) {
|
||||
var createInstance = function(contentProvider) {
|
||||
/**
|
||||
* Generates the document(definition) for pdfMake
|
||||
* @function
|
||||
@ -274,7 +331,7 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
||||
pageSize: 'A4',
|
||||
pageMargins: [0, 0, 0, 0],
|
||||
defaultStyle: {
|
||||
font: defaultFont,
|
||||
font: PDFLayout.getFontName(),
|
||||
fontSize: 10
|
||||
},
|
||||
content: content,
|
||||
@ -308,10 +365,9 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
||||
* Converter component for HTML->JSON for pdfMake
|
||||
* @constructor
|
||||
* @param {object} images - Key-Value structure representing image.src/BASE64 of images
|
||||
* @param {object} fonts - Key-Value structure representing fonts (detailed description below)
|
||||
* @param {object} pdfMake - the converter component enhances pdfMake
|
||||
*/
|
||||
var createInstance = function(images, fonts, pdfMake) {
|
||||
var createInstance = function(images, pdfMake) {
|
||||
var slice = Function.prototype.call.bind([].slice),
|
||||
map = Function.prototype.call.bind([].map),
|
||||
|
||||
@ -319,47 +375,6 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
||||
DIFF_MODE_INSERT = 1,
|
||||
DIFF_MODE_DELETE = 2,
|
||||
|
||||
/**
|
||||
* Adds a custom font to pdfMake.vfs
|
||||
* @function
|
||||
* @param {object} fontFiles - object with Files to add to pdfMake.vfs
|
||||
* {
|
||||
* normal: $Filename
|
||||
* bold: $Filename
|
||||
* italics: $Filename
|
||||
* bolditalics: $Filename
|
||||
* }
|
||||
*/
|
||||
addFontToVfs = function(fontFiles) {
|
||||
Object.keys(fontFiles).forEach(function(name) {
|
||||
var file = fontFiles[name];
|
||||
pdfMake.vfs[file.name] = file.content;
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Adds custom fonts to pdfMake
|
||||
* @function
|
||||
* @param {object} fontInfo - Font configuration from Backend
|
||||
* {
|
||||
* $FontName : {
|
||||
* normal: $Filename
|
||||
* bold: $Filename
|
||||
* italics: $Filename
|
||||
* bolditalics: $Filename
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
registerFont = function(fontInfo) {
|
||||
Object.keys(fontInfo).forEach(function(name) {
|
||||
var font = fontInfo[name];
|
||||
addFontToVfs(font);
|
||||
pdfMake.fonts = pdfMake.fonts || {};
|
||||
pdfMake.fonts[name] = Object.keys(font).reduce(function(fontDefinition, style) {
|
||||
fontDefinition[style] = font[style].name;
|
||||
return fontDefinition;
|
||||
}, {});
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Convertes HTML for use with pdfMake
|
||||
* @function
|
||||
@ -726,9 +741,6 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
||||
o[name] = content;
|
||||
return o;
|
||||
};
|
||||
fonts.forEach(function(fontInfo) {
|
||||
registerFont(fontInfo);
|
||||
});
|
||||
return {
|
||||
convertHTML: convertHTML,
|
||||
createElement: create
|
||||
|
@ -788,22 +788,12 @@ class MediaEncoder(utils_views.APIView):
|
||||
Takes an array of IMG.src - Paths
|
||||
Retrieves the according images
|
||||
Encodes the images to BASE64
|
||||
Add configured fonts
|
||||
Puts it into a key-value structure
|
||||
|
||||
{
|
||||
"images": {
|
||||
"media/file/ubuntu.png":"$ENCODED_IMAGE"
|
||||
},
|
||||
"fonts": [{
|
||||
$FontName : {
|
||||
normal: $Filename
|
||||
bold: $Filename
|
||||
italics: $Filename
|
||||
bolditalics: $Filename
|
||||
}
|
||||
}],
|
||||
"default_font": "$DEFAULTFONT"
|
||||
}
|
||||
}
|
||||
|
||||
:param request:
|
||||
@ -818,86 +808,10 @@ class MediaEncoder(utils_views.APIView):
|
||||
body_unicode = request.body.decode('utf-8')
|
||||
file_paths = json.loads(body_unicode)
|
||||
images = {file_path: self.encode_image_from(file_path) for file_path in file_paths}
|
||||
fonts = self.encoded_fonts()
|
||||
default_font = self.get_default_font()
|
||||
return Response({
|
||||
"images": images,
|
||||
"fonts": fonts,
|
||||
"defaultFont": default_font
|
||||
"images": images
|
||||
})
|
||||
|
||||
def get_default_font(self):
|
||||
"""
|
||||
Returns the default font for pdfMake.
|
||||
|
||||
Note: For development purposes this is hard coded.
|
||||
|
||||
:return: the name of the default Font
|
||||
"""
|
||||
return 'OpenSans'
|
||||
|
||||
def encoded_fonts(self):
|
||||
"""
|
||||
Generate font encoding for pdfMake
|
||||
:return: list of Font Encodings
|
||||
"""
|
||||
fonts = self.get_configured_fonts()
|
||||
enc_fonts = [self.encode_font(name, files) for name, files in fonts.items()]
|
||||
return enc_fonts
|
||||
|
||||
def get_configured_fonts(self):
|
||||
"""
|
||||
Returns the configured fonts
|
||||
|
||||
Note: For development purposes, the current font definition is hard coded
|
||||
|
||||
The form is {
|
||||
$FontName : {
|
||||
normal: $Filename
|
||||
bold: $Filename
|
||||
italics: $Filename
|
||||
bolditalics: $Filename
|
||||
}
|
||||
}
|
||||
This structure is required according to PDFMake specs.
|
||||
:return:
|
||||
"""
|
||||
fonts = {
|
||||
'OpenSans': {
|
||||
'normal': 'OpenSans-Regular.ttf',
|
||||
'bold': 'OpenSans-Bold.ttf',
|
||||
'italics': 'OpenSans-Italic.ttf',
|
||||
'bolditalics': 'OpenSans-BoldItalic.ttf'
|
||||
}
|
||||
}
|
||||
return fonts
|
||||
|
||||
def encode_font(self, font_name, font_files):
|
||||
"""
|
||||
Responsible to encode a single font
|
||||
:param fontName: name of the font
|
||||
:param font_files: files for different weighs
|
||||
:return: dictionary with encoded font
|
||||
"""
|
||||
encoded_files = {type: self.encode_font_from(file_path) for type, file_path in font_files.items()}
|
||||
return {font_name: encoded_files}
|
||||
|
||||
def encode_font_from(self, file_path):
|
||||
"""
|
||||
Returns the BASE64 encoded version of an image-file for a given path
|
||||
:param file_path:
|
||||
:return: dictionary with the string representation (content) and the name of the file
|
||||
for the pdfMake.vfs structure
|
||||
"""
|
||||
path = os.path.join(settings.MODULE_DIR, 'static', 'fonts', os.path.basename(file_path))
|
||||
try:
|
||||
with open(path, "rb") as file:
|
||||
string_representation = "{}".format(base64.b64encode(file.read()).decode())
|
||||
except:
|
||||
return ""
|
||||
else:
|
||||
return {"content": string_representation, "name": file_path}
|
||||
|
||||
def encode_image_from(self, file_path):
|
||||
"""
|
||||
Returns the BASE64 encoded version of an image-file for a given path
|
||||
|
@ -109,7 +109,7 @@ angular.module('OpenSlidesApp.motions', [
|
||||
}
|
||||
// calculate percent value
|
||||
var config = Config.get('motions_poll_100_percent_base').value;
|
||||
var percentStr;
|
||||
var percentStr = '';
|
||||
var percentNumber = null;
|
||||
var base = null;
|
||||
if (!impossible) {
|
||||
@ -137,7 +137,8 @@ angular.module('OpenSlidesApp.motions', [
|
||||
return {
|
||||
'value': value,
|
||||
'percentStr': percentStr,
|
||||
'percentNumber': percentNumber
|
||||
'percentNumber': percentNumber,
|
||||
'display': value + ' ' + percentStr
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -30,9 +30,9 @@ angular.module('OpenSlidesApp.motions.motionservices', ['OpenSlidesApp.motions',
|
||||
});
|
||||
|
||||
$http.post('/core/encode_media/', JSON.stringify(image_sources)).success(function(data) {
|
||||
var converter = PdfMakeConverter.createInstance(data.images, data.fonts, pdfMake);
|
||||
var converter = PdfMakeConverter.createInstance(data.images, pdfMake);
|
||||
var motionContentProvider = MotionContentProvider.createInstance(converter, $scope.motion, $scope, User, $http);
|
||||
var documentProvider = PdfMakeDocumentProvider.createInstance(motionContentProvider, data.defaultFont);
|
||||
var documentProvider = PdfMakeDocumentProvider.createInstance(motionContentProvider);
|
||||
var filename = gettextCatalog.getString("Motion") + "-" + $scope.motion.identifier + ".pdf";
|
||||
pdfMake.createPdf(documentProvider.getDocument()).download(filename);
|
||||
});
|
||||
|
@ -6,21 +6,199 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
|
||||
.factory('MotionContentProvider', [
|
||||
'gettextCatalog',
|
||||
'PdfPredefinedFunctions',
|
||||
function(gettextCatalog, PdfPredefinedFunctions) {
|
||||
'PDFLayout',
|
||||
'Category',
|
||||
'Config',
|
||||
function(gettextCatalog, PDFLayout, Category, Config) {
|
||||
/**
|
||||
* Provides the content as JS objects for Motions in pdfMake context
|
||||
* @constructor
|
||||
*/
|
||||
|
||||
var createInstance = function(converter, motion, $scope, User) {
|
||||
var createInstance = function(converter, motion, $scope) {
|
||||
|
||||
// title
|
||||
var identifier = motion.identifier ? ' ' + motion.identifier : '';
|
||||
var header = PdfPredefinedFunctions.createTitle(gettextCatalog.getString("Motion") + identifier +
|
||||
': ' + motion.getTitle($scope.version));
|
||||
var title = PDFLayout.createTitle(
|
||||
gettextCatalog.getString('Motion') + identifier + ': ' +
|
||||
motion.getTitle($scope.version)
|
||||
);
|
||||
|
||||
// generates the text of the motion. Also septerates between line-numbers
|
||||
var textContent = function() {
|
||||
// subtitle
|
||||
var subtitle = PDFLayout.createSubtitle(
|
||||
gettextCatalog.getString('Sequential number') + ': ' + motion.id
|
||||
);
|
||||
|
||||
// meta data table
|
||||
var metaTable = function() {
|
||||
var metaTableBody = [];
|
||||
|
||||
// submitters
|
||||
var submitters = _.map(motion.submitters, function (submitter) {
|
||||
return submitter.get_full_name();
|
||||
}).join(', ');
|
||||
metaTableBody.push([
|
||||
{
|
||||
text: gettextCatalog.getString('Submitters') + ':',
|
||||
style: ['bold', 'grey']
|
||||
},
|
||||
{
|
||||
text: submitters,
|
||||
style: 'grey'
|
||||
}
|
||||
]);
|
||||
|
||||
// state
|
||||
metaTableBody.push([
|
||||
{
|
||||
text: gettextCatalog.getString('State') + ':',
|
||||
style: ['bold', 'grey']
|
||||
},
|
||||
{
|
||||
text: motion.getStateName(),
|
||||
style: 'grey'
|
||||
}
|
||||
]);
|
||||
|
||||
// recommendation
|
||||
if (motion.getRecommendationName()) {
|
||||
metaTableBody.push([
|
||||
{
|
||||
text: Config.get('motions_recommendations_by').value + ':',
|
||||
style: ['bold', 'grey']
|
||||
},
|
||||
{
|
||||
text: motion.getRecommendationName(),
|
||||
style: 'grey'
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
// category
|
||||
if (motion.category) {
|
||||
metaTableBody.push([
|
||||
{
|
||||
text: gettextCatalog.getString('Category') + ':',
|
||||
style: ['bold', 'grey']
|
||||
},
|
||||
{
|
||||
text: motion.category.name,
|
||||
style: 'grey'
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
// voting result
|
||||
var column1 = [];
|
||||
var column2 = [];
|
||||
var column3 = [];
|
||||
motion.polls.map(function(poll, index) {
|
||||
var votenumber = '';
|
||||
if (motion.polls.length > 1) {
|
||||
votenumber = index + 1 + '. ' + gettextCatalog.getString('Vote');
|
||||
}
|
||||
|
||||
// yes
|
||||
var yes = poll.getVote(poll.yes, 'yes');
|
||||
column1.push(gettextCatalog.getString('Yes') + ':');
|
||||
column2.push(yes.value);
|
||||
column3.push(yes.percentStr);
|
||||
// no
|
||||
var no = poll.getVote(poll.no, 'no');
|
||||
column1.push(gettextCatalog.getString('No') + ':');
|
||||
column2.push(no.value);
|
||||
column3.push(no.percentStr);
|
||||
// abstain
|
||||
var abstain = poll.getVote(poll.abstain, 'abstain');
|
||||
column1.push(gettextCatalog.getString('Abstain') + ':');
|
||||
column2.push(abstain.value);
|
||||
column3.push(abstain.percentStr);
|
||||
// votes valid
|
||||
if (poll.votesvalid) {
|
||||
var valid = poll.getVote(poll.votesvalid, 'votesvalid');
|
||||
column1.push(gettextCatalog.getString('Valid votes') + ':');
|
||||
column2.push(valid.value);
|
||||
column3.push(valid.percentStr);
|
||||
}
|
||||
// votes invalid
|
||||
if (poll.votesvalid) {
|
||||
var invalid = poll.getVote(poll.votesinvalid, 'votesinvalid');
|
||||
column1.push(gettextCatalog.getString('Invalid votes') + ':');
|
||||
column2.push(invalid.value);
|
||||
column3.push(invalid.percentStr);
|
||||
}
|
||||
// votes cast
|
||||
if (poll.votescast) {
|
||||
var cast = poll.getVote(poll.votescast, 'votescast');
|
||||
column1.push(gettextCatalog.getString('Votes cast') + ':');
|
||||
column2.push(cast.value);
|
||||
column3.push(cast.percentStr);
|
||||
}
|
||||
});
|
||||
metaTableBody.push([
|
||||
{
|
||||
text: gettextCatalog.getString('Voting result') + ':',
|
||||
style: ['bold', 'grey']
|
||||
},
|
||||
{
|
||||
columns: [
|
||||
{
|
||||
text: column1.join('\n'),
|
||||
width: 'auto'
|
||||
},
|
||||
{
|
||||
text: column2.join('\n'),
|
||||
width: 'auto',
|
||||
alignment: 'right'
|
||||
},
|
||||
{
|
||||
text: column3.join('\n'),
|
||||
width: 'auto',
|
||||
alignment: 'right'
|
||||
},
|
||||
],
|
||||
columnGap: 7,
|
||||
style: 'grey'
|
||||
}
|
||||
]);
|
||||
|
||||
|
||||
// build table
|
||||
var metaTableJsonString = {
|
||||
table: {
|
||||
widths: ['30%','70%'],
|
||||
body: metaTableBody,
|
||||
},
|
||||
margin: [0, 0, 0, 20],
|
||||
layout: {
|
||||
hLineWidth: function(i, node) {
|
||||
return (i === 0 || i === node.table.body.length) ? 0 : 0.5;
|
||||
},
|
||||
vLineWidth: function(i, node) {
|
||||
return (i === 0 || i === node.table.widths.length) ? 0 : 0;
|
||||
},
|
||||
hLineColor: function(i, node) {
|
||||
return (i === 0 || i === node.table.body.length) ? '' : 'white';
|
||||
},
|
||||
vLineColor: function(i, node) {
|
||||
return (i === 0 || i === node.table.widths.length) ? '' : 'white';
|
||||
}
|
||||
}
|
||||
};
|
||||
return metaTableJsonString;
|
||||
};
|
||||
|
||||
// motion title
|
||||
var motionTitle = function() {
|
||||
return [{
|
||||
text: motion.getTitle($scope.version),
|
||||
style: 'heading3'
|
||||
}];
|
||||
};
|
||||
|
||||
|
||||
// motion text (with line-numbers)
|
||||
var motionText = function() {
|
||||
if ($scope.lineNumberMode == "inline" || $scope.lineNumberMode == "outside") {
|
||||
/* in order to distinguish between the line-number-types we need to pass the scope
|
||||
* to the convertHTML function.
|
||||
@ -35,109 +213,18 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
}
|
||||
};
|
||||
|
||||
// Generate text of reason
|
||||
var reasonContent = function() {
|
||||
return converter.convertHTML(motion.getReason($scope.version), $scope);
|
||||
// motion reason heading
|
||||
var motionReason = function() {
|
||||
var reason = [{
|
||||
text: gettextCatalog.getString('Reason'),
|
||||
style: 'heading3'
|
||||
}];
|
||||
reason.push(converter.convertHTML(motion.getReason($scope.version), $scope));
|
||||
return reason;
|
||||
};
|
||||
|
||||
// Generate text of signment
|
||||
var signment = function() {
|
||||
var label = converter.createElement("text", gettextCatalog.getString('Submitter') + ':\nStatus:');
|
||||
var state = converter.createElement("text", User.get(motion.submitters_id[0]).full_name + '\n' + motion.getStateName());
|
||||
state.width = "70%";
|
||||
label.width = "30%";
|
||||
label.bold = true;
|
||||
var signment = converter.createElement("columns", [label, state]);
|
||||
signment.margin = [10, 20, 0, 10];
|
||||
signment.lineHeight = 2.5;
|
||||
return signment;
|
||||
};
|
||||
|
||||
// Generates polls
|
||||
var polls = function() {
|
||||
if (!motion.polls.length) return {};
|
||||
var pollLabel = converter.createElement("text", gettextCatalog.getString('Voting result') + ":"),
|
||||
results = function() {
|
||||
return motion.polls.map(function(poll, index) {
|
||||
var id = index + 1,
|
||||
yes = poll.yes ? poll.yes : '-', // if no poll.yes is given set it to '-'
|
||||
yesRelative = poll.getVote(poll.yes, 'yes').percentStr,
|
||||
no = poll.no ? poll.no : '-',
|
||||
noRelative = poll.getVote(poll.no, 'no').percentStr,
|
||||
abstain = poll.abstain ? poll.abstain : '-',
|
||||
abstainrelativeGet = poll.getVote(poll.abstain, 'abstain').percentStr,
|
||||
abstainRelative = abstainrelativeGet ? abstainrelativeGet : '',
|
||||
valid = poll.votesvalid ? poll.votesvalid : '-',
|
||||
validRelative = poll.getVote(poll.votesvalid, 'votesvalid').percentStr,
|
||||
number = {
|
||||
text: id + ".",
|
||||
width: "5%"
|
||||
},
|
||||
headerText = {
|
||||
text: gettextCatalog.getString('Vote'),
|
||||
width: "15%"
|
||||
},
|
||||
/**
|
||||
* Generates a part (consisting of different columns) of the polls
|
||||
*
|
||||
* Example Ja 100 ( 90% )
|
||||
*
|
||||
* @function
|
||||
* @param {string} name - E.g. "Ja"
|
||||
* @param {number} value - E.g.100
|
||||
* @param {number} relValue - E.g. 90
|
||||
*/
|
||||
createPart = function(name, value, relValue) {
|
||||
var indexColumn = converter.createElement("text");
|
||||
var nameColumn = converter.createElement("text", "" + name);
|
||||
var valueColumn = converter.createElement("text", "" + value);
|
||||
var relColumn = converter.createElement("text", relValue);
|
||||
valueColumn.width = "40%";
|
||||
indexColumn.width = "5%";
|
||||
valueColumn.width = "5%";
|
||||
valueColumn.alignment = "right";
|
||||
relColumn.margin = [5, 0, 0, 0];
|
||||
return [indexColumn, nameColumn, valueColumn, relColumn];
|
||||
},
|
||||
yesPart = converter.createElement("columns", createPart(gettextCatalog.getString("Yes"), yes, yesRelative)),
|
||||
noPart = converter.createElement("columns", createPart(gettextCatalog.getString("No"), no, noRelative)),
|
||||
abstainPart = converter.createElement("columns", createPart(gettextCatalog.getString("Abstain"), abstain, abstainRelative)),
|
||||
totalPart = converter.createElement("columns", createPart(gettextCatalog.getString("Valid votes"), valid, validRelative)),
|
||||
heading = converter.createElement("columns", [number, headerText]),
|
||||
pollResult = converter.createElement("stack", [
|
||||
heading, yesPart, noPart, abstainPart, totalPart
|
||||
]);
|
||||
|
||||
return pollResult;
|
||||
}, {});
|
||||
};
|
||||
pollLabel.width = '35%';
|
||||
pollLabel.bold = true;
|
||||
var result = converter.createElement("columns", [pollLabel, results()]);
|
||||
result.margin = [10, 0, 0, 10];
|
||||
result.lineHeight = 1;
|
||||
return result;
|
||||
};
|
||||
|
||||
//Generates title section for motion
|
||||
var titleSection = function() {
|
||||
var title = converter.createElement("text", motion.getTitle($scope.version));
|
||||
title.bold = true;
|
||||
title.fontSize = 14;
|
||||
title.margin = [0, 0, 0, 10];
|
||||
return title;
|
||||
};
|
||||
|
||||
// Generates reason section for polls
|
||||
var reason = function() {
|
||||
var r = converter.createElement("text", gettextCatalog.getString("Reason") + ":");
|
||||
r.bold = true;
|
||||
r.fontSize = 14;
|
||||
r.margin = [0, 30, 0, 10];
|
||||
return r;
|
||||
};
|
||||
|
||||
//getters
|
||||
// getters
|
||||
var getTitle = function() {
|
||||
return motion.getTitle($scope.verion);
|
||||
};
|
||||
@ -152,25 +239,17 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
|
||||
// Generates content as a pdfmake consumable
|
||||
var getContent = function() {
|
||||
if (reasonContent().length === 0 ) {
|
||||
return [
|
||||
header,
|
||||
signment(),
|
||||
polls(),
|
||||
titleSection(),
|
||||
textContent(),
|
||||
];
|
||||
} else {
|
||||
return [
|
||||
header,
|
||||
signment(),
|
||||
polls(),
|
||||
titleSection(),
|
||||
textContent(),
|
||||
reason(),
|
||||
reasonContent()
|
||||
];
|
||||
var content = [
|
||||
title,
|
||||
subtitle,
|
||||
metaTable(),
|
||||
motionTitle(),
|
||||
motionText(),
|
||||
];
|
||||
if (motionReason()) {
|
||||
content.push(motionReason());
|
||||
}
|
||||
return content;
|
||||
};
|
||||
return {
|
||||
getContent: getContent,
|
||||
@ -186,8 +265,8 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
}])
|
||||
|
||||
.factory('PollContentProvider', [
|
||||
'PdfPredefinedFunctions',
|
||||
function(PdfPredefinedFunctions) {
|
||||
'PDFLayout',
|
||||
function(PDFLayout) {
|
||||
/**
|
||||
* Generates a content provider for polls
|
||||
* @constructor
|
||||
@ -211,9 +290,9 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
text: title,
|
||||
style: 'description'
|
||||
},
|
||||
PdfPredefinedFunctions.createBallotEntry(gettextCatalog.getString("Yes")),
|
||||
PdfPredefinedFunctions.createBallotEntry(gettextCatalog.getString("No")),
|
||||
PdfPredefinedFunctions.createBallotEntry(gettextCatalog.getString("Abstain")),
|
||||
PDFLayout.createBallotEntry(gettextCatalog.getString("Yes")),
|
||||
PDFLayout.createBallotEntry(gettextCatalog.getString("No")),
|
||||
PDFLayout.createBallotEntry(gettextCatalog.getString("Abstain")),
|
||||
],
|
||||
margin: [0, 0, 0, sheetend]
|
||||
};
|
||||
@ -237,7 +316,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
[createSection(), createSection()]
|
||||
],
|
||||
},
|
||||
layout: PdfPredefinedFunctions.getBallotLayoutLines()
|
||||
layout: PDFLayout.getBallotLayoutLines()
|
||||
}];
|
||||
};
|
||||
|
||||
@ -252,20 +331,20 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
|
||||
.factory('MotionCatalogContentProvider', [
|
||||
'gettextCatalog',
|
||||
'PdfPredefinedFunctions',
|
||||
'PDFLayout',
|
||||
'Category',
|
||||
'Config',
|
||||
function(gettextCatalog, PdfPredefinedFunctions, Config) {
|
||||
function(gettextCatalog, PDFLayout, Category, Config) {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @function
|
||||
* @param {object} allMotions - A sorted array of all motions to parse
|
||||
* @param {object} $scope - Current $scope
|
||||
* @param {object} User - Current user
|
||||
*/
|
||||
var createInstance = function(allMotions, $scope, User, Category) {
|
||||
var createInstance = function(allMotions, $scope) {
|
||||
|
||||
var title = PdfPredefinedFunctions.createTitle(
|
||||
var title = PDFLayout.createTitle(
|
||||
gettextCatalog.getString(Config.get('motions_export_title').value)
|
||||
);
|
||||
|
||||
@ -284,7 +363,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
var createTOContent = function() {
|
||||
var heading = {
|
||||
text: gettextCatalog.getString("Table of contents"),
|
||||
style: "heading"
|
||||
style: "heading2"
|
||||
};
|
||||
|
||||
var toc = [];
|
||||
@ -310,7 +389,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
return [
|
||||
heading,
|
||||
toc,
|
||||
PdfPredefinedFunctions.addPageBreak()
|
||||
PDFLayout.addPageBreak()
|
||||
];
|
||||
};
|
||||
|
||||
@ -319,7 +398,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
if (Category.getAll().length > 0) {
|
||||
var heading = {
|
||||
text: gettextCatalog.getString("Categories"),
|
||||
style: "heading"
|
||||
style: "heading2"
|
||||
};
|
||||
|
||||
var toc = [];
|
||||
@ -344,7 +423,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
return [
|
||||
heading,
|
||||
toc,
|
||||
PdfPredefinedFunctions.addPageBreak()
|
||||
PDFLayout.addPageBreak()
|
||||
];
|
||||
} else {
|
||||
// if there are no categories, return "empty string"
|
||||
@ -359,7 +438,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
angular.forEach(allMotions, function(motion, key) {
|
||||
motionContent.push(motion.getContent());
|
||||
if (key < allMotions.length - 1) {
|
||||
motionContent.push(PdfPredefinedFunctions.addPageBreak());
|
||||
motionContent.push(PDFLayout.addPageBreak());
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -926,7 +926,7 @@ angular.module('OpenSlidesApp.motions.site', [
|
||||
|
||||
//post-request to convert the images. Async.
|
||||
$http.post('/core/encode_media/', JSON.stringify(image_sources)).success(function(data) {
|
||||
var converter = PdfMakeConverter.createInstance(data.images, data.fonts, pdfMake);
|
||||
var converter = PdfMakeConverter.createInstance(data.images, pdfMake);
|
||||
var motionContentProviderArray = [];
|
||||
|
||||
//convert the filtered motions to motionContentProviders
|
||||
@ -934,7 +934,7 @@ angular.module('OpenSlidesApp.motions.site', [
|
||||
motionContentProviderArray.push(MotionContentProvider.createInstance(converter, motion, $scope, User, $http));
|
||||
});
|
||||
var motionCatalogContentProvider = MotionCatalogContentProvider.createInstance(motionContentProviderArray, $scope, User, Category);
|
||||
var documentProvider = PdfMakeDocumentProvider.createInstance(motionCatalogContentProvider, data.defaultFont);
|
||||
var documentProvider = PdfMakeDocumentProvider.createInstance(motionCatalogContentProvider);
|
||||
pdfMake.createPdf(documentProvider.getDocument()).download(filename);
|
||||
});
|
||||
};
|
||||
|
@ -132,11 +132,13 @@
|
||||
|
||||
<!-- Recommendation -->
|
||||
<div ng-if="config('motions_recommendations_by') != ''">
|
||||
<h3 ng-if="!motion.isAllowed('change_recommendation')" class="heading" translate>Recommendation</h3>
|
||||
<h3 ng-if="!motion.isAllowed('change_recommendation')" class="heading">
|
||||
{{ config('motions_recommendations_by') }}
|
||||
</h3>
|
||||
<div ng-if="motion.isAllowed('change_recommendation')" class="heading">
|
||||
<span uib-dropdown>
|
||||
<a href id="recommendation-dropdown" class="drop-down-name" uib-dropdown-toggle>
|
||||
<translate>Recommendation</translate>
|
||||
{{ config('motions_recommendations_by') }}
|
||||
<i class="fa fa-cog"></i>
|
||||
</a>
|
||||
<ul uib-dropdown-menu class="dropdown-menu" aria-labelledby="recommendation-dropdown">
|
||||
|
@ -6,13 +6,13 @@ angular.module('OpenSlidesApp.users.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
|
||||
.factory('UserListContentProvider', [
|
||||
'gettextCatalog',
|
||||
'PdfPredefinedFunctions',
|
||||
function(gettextCatalog, PdfPredefinedFunctions) {
|
||||
'PDFLayout',
|
||||
function(gettextCatalog, PDFLayout) {
|
||||
|
||||
var createInstance = function(userList, groups) {
|
||||
|
||||
//use the Predefined Functions to create the title
|
||||
var title = PdfPredefinedFunctions.createTitle(gettextCatalog.getString("List of participants"));
|
||||
var title = PDFLayout.createTitle(gettextCatalog.getString("List of participants"));
|
||||
|
||||
//function to generate the user list
|
||||
var createUserList = function() {
|
||||
@ -35,19 +35,19 @@ angular.module('OpenSlidesApp.users.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
var userJsonObj = [
|
||||
{
|
||||
text: "" + (counter+1),
|
||||
style: PdfPredefinedFunctions.flipTableRowStyle(userJsonList.length)
|
||||
style: PDFLayout.flipTableRowStyle(userJsonList.length)
|
||||
},
|
||||
{
|
||||
text: user.short_name,
|
||||
style: PdfPredefinedFunctions.flipTableRowStyle(userJsonList.length)
|
||||
style: PDFLayout.flipTableRowStyle(userJsonList.length)
|
||||
},
|
||||
{
|
||||
text: user.structure_level,
|
||||
style: PdfPredefinedFunctions.flipTableRowStyle(userJsonList.length)
|
||||
style: PDFLayout.flipTableRowStyle(userJsonList.length)
|
||||
},
|
||||
{
|
||||
text: userGroups.join(" "),
|
||||
style: PdfPredefinedFunctions.flipTableRowStyle(userJsonList.length)
|
||||
style: PDFLayout.flipTableRowStyle(userJsonList.length)
|
||||
}
|
||||
];
|
||||
userJsonList.push(userJsonObj);
|
||||
@ -107,8 +107,8 @@ angular.module('OpenSlidesApp.users.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
|
||||
.factory('UserAccessDataListContentProvider', [
|
||||
'gettextCatalog',
|
||||
'PdfPredefinedFunctions',
|
||||
function(gettextCatalog, PdfPredefinedFunctions) {
|
||||
'PDFLayout',
|
||||
function(gettextCatalog, PDFLayout) {
|
||||
|
||||
var createInstance = function(userList, groups, Config) {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user