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": {
|
"overrides": {
|
||||||
"pdfmake-dist-dist": {
|
"pdfmake-dist-dist": {
|
||||||
"main": "build/pdfmake.min.js"
|
"main": [
|
||||||
|
"build/pdfmake.min.js",
|
||||||
|
"build/vfs_fonts.js"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"pdfjs-dist": {
|
"pdfjs-dist": {
|
||||||
"main": "build/pdf.combined.js"
|
"main": "build/pdf.combined.js"
|
||||||
|
@ -6,15 +6,15 @@ angular.module('OpenSlidesApp.agenda.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
|
|
||||||
.factory('AgendaContentProvider', [
|
.factory('AgendaContentProvider', [
|
||||||
'gettextCatalog',
|
'gettextCatalog',
|
||||||
'PdfPredefinedFunctions',
|
'PDFLayout',
|
||||||
function(gettextCatalog, PdfPredefinedFunctions) {
|
function(gettextCatalog, PDFLayout) {
|
||||||
|
|
||||||
var createInstance = function(items) {
|
var createInstance = function(items) {
|
||||||
|
|
||||||
//use the Predefined Functions to create the title
|
// page title
|
||||||
var title = PdfPredefinedFunctions.createTitle(gettextCatalog.getString("Agenda"));
|
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 createItemList = function() {
|
||||||
var agenda_items = [];
|
var agenda_items = [];
|
||||||
angular.forEach(items, function (item) {
|
angular.forEach(items, function (item) {
|
||||||
|
@ -315,7 +315,7 @@ angular.module('OpenSlidesApp.agenda.site', [
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.makePDF = function() {
|
$scope.makePDF = function() {
|
||||||
var filename = gettextCatalog.getString("Agenda")+".pdf";
|
var filename = gettextCatalog.getString('Agenda') + '.pdf';
|
||||||
var agendaContentProvider = AgendaContentProvider.createInstance($scope.items);
|
var agendaContentProvider = AgendaContentProvider.createInstance($scope.items);
|
||||||
var documentProvider = PdfMakeDocumentProvider.createInstance(agendaContentProvider);
|
var documentProvider = PdfMakeDocumentProvider.createInstance(agendaContentProvider);
|
||||||
pdfMake.createPdf(documentProvider.getDocument()).download(filename);
|
pdfMake.createPdf(documentProvider.getDocument()).download(filename);
|
||||||
|
@ -6,15 +6,15 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
|
|
||||||
.factory('AssignmentContentProvider', [
|
.factory('AssignmentContentProvider', [
|
||||||
'gettextCatalog',
|
'gettextCatalog',
|
||||||
'PdfPredefinedFunctions',
|
'PDFLayout',
|
||||||
function(gettextCatalog, PdfPredefinedFunctions) {
|
function(gettextCatalog, PDFLayout) {
|
||||||
|
|
||||||
var createInstance = function(assignment) {
|
var createInstance = function(assignment) {
|
||||||
|
|
||||||
//use the Predefined Functions to create the title
|
// page title
|
||||||
var title = PdfPredefinedFunctions.createTitle(assignment.title);
|
var title = PDFLayout.createTitle(assignment.title);
|
||||||
|
|
||||||
//create the preamble
|
// number of posts
|
||||||
var createPreamble = function() {
|
var createPreamble = function() {
|
||||||
var preambleText = gettextCatalog.getString("Number of posts to be elected") + ": ";
|
var preambleText = gettextCatalog.getString("Number of posts to be elected") + ": ";
|
||||||
var memberNumber = ""+assignment.open_posts;
|
var memberNumber = ""+assignment.open_posts;
|
||||||
@ -34,7 +34,7 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
return preamble;
|
return preamble;
|
||||||
};
|
};
|
||||||
|
|
||||||
//adds the description if present in the assignment
|
// description
|
||||||
var createDescription = function() {
|
var createDescription = function() {
|
||||||
if (assignment.description) {
|
if (assignment.description) {
|
||||||
var descriptionText = gettextCatalog.getString("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() {
|
var createCandidateList = function() {
|
||||||
if (assignment.phase != 2) {
|
if (assignment.phase != 2) {
|
||||||
var candidatesText = gettextCatalog.getString("Candidates") + ": ";
|
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) {
|
var electedCandidateLine = function(candidateName, pollOption, pollTableBody) {
|
||||||
if (pollOption.is_elected) {
|
if (pollOption.is_elected) {
|
||||||
return {
|
return {
|
||||||
text: candidateName + "*",
|
text: candidateName + "*",
|
||||||
bold: true,
|
bold: true,
|
||||||
style: PdfPredefinedFunctions.flipTableRowStyle(pollTableBody.length)
|
style: PDFLayout.flipTableRowStyle(pollTableBody.length)
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
text: candidateName,
|
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 createPollResultTable = function() {
|
||||||
var resultBody = [];
|
var resultBody = [];
|
||||||
angular.forEach(assignment.polls, function(poll, pollIndex) {
|
angular.forEach(assignment.polls, function(poll, pollIndex) {
|
||||||
@ -144,7 +144,7 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
electedCandidateLine(candidateName, pollOption, pollTableBody),
|
electedCandidateLine(candidateName, pollOption, pollTableBody),
|
||||||
{
|
{
|
||||||
text: votes[0].value + " " + votes[0].percentStr,
|
text: votes[0].value + " " + votes[0].percentStr,
|
||||||
style: PdfPredefinedFunctions.flipTableRowStyle(pollTableBody.length)
|
style: PDFLayout.flipTableRowStyle(pollTableBody.length)
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
} else if (poll.pollmethod == 'yn') {
|
} else if (poll.pollmethod == 'yn') {
|
||||||
@ -163,7 +163,7 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
votes[1].percentStr
|
votes[1].percentStr
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
style: PdfPredefinedFunctions.flipTableRowStyle(pollTableBody.length)
|
style: PDFLayout.flipTableRowStyle(pollTableBody.length)
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
} else if (poll.pollmethod == 'yna') {
|
} else if (poll.pollmethod == 'yna') {
|
||||||
@ -187,7 +187,7 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
votes[2].percentStr
|
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) {
|
if (assignment.polls.length > 0) {
|
||||||
resultBody.push({
|
resultBody.push({
|
||||||
text: "* = " + gettextCatalog.getString("is elected"),
|
text: "* = " + gettextCatalog.getString("is elected"),
|
||||||
@ -281,12 +281,12 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
|
|
||||||
.factory('BallotContentProvider', [
|
.factory('BallotContentProvider', [
|
||||||
'gettextCatalog',
|
'gettextCatalog',
|
||||||
'PdfPredefinedFunctions',
|
'PDFLayout',
|
||||||
function(gettextCatalog, PdfPredefinedFunctions) {
|
function(gettextCatalog, PDFLayout) {
|
||||||
|
|
||||||
var createInstance = function(scope, poll, pollNumber) {
|
var createInstance = function(scope, poll, pollNumber) {
|
||||||
|
|
||||||
// use the Predefined Functions to create the title
|
// page title
|
||||||
var createTitle = function() {
|
var createTitle = function() {
|
||||||
return {
|
return {
|
||||||
text: scope.assignment.title,
|
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 createPollHint = function() {
|
||||||
var description = poll.description ? ': ' + poll.description : '';
|
var description = poll.description ? ': ' + poll.description : '';
|
||||||
return {
|
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 createYNBallotEntry = function(decision) {
|
||||||
var YNColumn = [
|
var YNColumn = [
|
||||||
{
|
{
|
||||||
width: "auto",
|
width: "auto",
|
||||||
stack: [
|
stack: [
|
||||||
PdfPredefinedFunctions.createBallotEntry(gettextCatalog.getString("Yes"))
|
PDFLayout.createBallotEntry(gettextCatalog.getString("Yes"))
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
width: "auto",
|
width: "auto",
|
||||||
stack: [
|
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({
|
YNColumn.push({
|
||||||
width: "auto",
|
width: "auto",
|
||||||
stack: [
|
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') {
|
if (poll.pollmethod == 'votes') {
|
||||||
angular.forEach(poll.options, function(option) {
|
angular.forEach(poll.options, function(option) {
|
||||||
var candidate = option.candidate.get_full_name();
|
var candidate = option.candidate.get_full_name();
|
||||||
candidateBallotList.push(PdfPredefinedFunctions.createBallotEntry(candidate));
|
candidateBallotList.push(PDFLayout.createBallotEntry(candidate));
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
angular.forEach(poll.options, function(option) {
|
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
|
// 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
|
// with a one px width and a fixed top-margin
|
||||||
|
|
||||||
return {
|
return {
|
||||||
columns : [
|
columns : [
|
||||||
{
|
{
|
||||||
@ -431,7 +430,7 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
widths: ['50%', '50%'],
|
widths: ['50%', '50%'],
|
||||||
body: tableBody
|
body: tableBody
|
||||||
},
|
},
|
||||||
layout: PdfPredefinedFunctions.getBallotLayoutLines()
|
layout: PDFLayout.getBallotLayoutLines()
|
||||||
}];
|
}];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -451,13 +450,13 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
|
|
||||||
.factory('AssignmentCatalogContentProvider', [
|
.factory('AssignmentCatalogContentProvider', [
|
||||||
'gettextCatalog',
|
'gettextCatalog',
|
||||||
'PdfPredefinedFunctions',
|
'PDFLayout',
|
||||||
'Config',
|
'Config',
|
||||||
function(gettextCatalog, PdfPredefinedFunctions, Config) {
|
function(gettextCatalog, PDFLayout, Config) {
|
||||||
|
|
||||||
var createInstance = function(allAssignmnets) {
|
var createInstance = function(allAssignmnets) {
|
||||||
|
|
||||||
var title = PdfPredefinedFunctions.createTitle(
|
var title = PDFLayout.createTitle(
|
||||||
gettextCatalog.getString(Config.get('assignments_pdf_title').value)
|
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 createTOContent = function(assignmentTitles) {
|
||||||
var heading = {
|
var heading = {
|
||||||
text: gettextCatalog.getString("Table of contents"),
|
text: gettextCatalog.getString("Table of contents"),
|
||||||
style: "heading",
|
style: "heading2",
|
||||||
};
|
};
|
||||||
|
|
||||||
var toc = [];
|
var toc = [];
|
||||||
@ -490,7 +489,7 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
return [
|
return [
|
||||||
heading,
|
heading,
|
||||||
toc,
|
toc,
|
||||||
PdfPredefinedFunctions.addPageBreak()
|
PDFLayout.addPageBreak()
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -503,7 +502,7 @@ angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
assignmentTitles.push(assignment.title);
|
assignmentTitles.push(assignment.title);
|
||||||
assignmentContent.push(assignment.getContent());
|
assignmentContent.push(assignment.getContent());
|
||||||
if (key < allAssignmnets.length - 1) {
|
if (key < allAssignmnets.length - 1) {
|
||||||
assignmentContent.push(PdfPredefinedFunctions.addPageBreak());
|
assignmentContent.push(PDFLayout.addPageBreak());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -4,23 +4,51 @@
|
|||||||
|
|
||||||
angular.module('OpenSlidesApp.core.pdf', [])
|
angular.module('OpenSlidesApp.core.pdf', [])
|
||||||
|
|
||||||
.factory('PdfPredefinedFunctions', [
|
/*
|
||||||
|
* General layout functions for building PDFs with pdfmake.
|
||||||
|
*/
|
||||||
|
.factory('PDFLayout', [
|
||||||
function() {
|
function() {
|
||||||
var PdfPredefinedFunctions = {};
|
var PDFLayout = {};
|
||||||
var BallotCircleDimensions = {
|
var BallotCircleDimensions = {
|
||||||
yDistance: 6,
|
yDistance: 6,
|
||||||
size: 8
|
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 {
|
return {
|
||||||
text: titleString,
|
text: title,
|
||||||
style: "title"
|
style: "title"
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// function to apply a pagebreak-keyword
|
// page subtitle
|
||||||
PdfPredefinedFunctions.addPageBreak = function() {
|
PDFLayout.createSubtitle = function(subtitle) {
|
||||||
|
return {
|
||||||
|
text: subtitle,
|
||||||
|
style: "subtitle"
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// pagebreak
|
||||||
|
PDFLayout.addPageBreak = function() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
text: '',
|
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) {
|
if (currentTableSize % 2 === 0) {
|
||||||
return "tableEven";
|
return "tableEven";
|
||||||
} else {
|
} else {
|
||||||
@ -37,8 +66,8 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//draws a circle
|
// draws a circle
|
||||||
PdfPredefinedFunctions.drawCircle = function(y, size) {
|
PDFLayout.drawCircle = function(y, size) {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
type: 'ellipse',
|
type: 'ellipse',
|
||||||
@ -51,14 +80,15 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
//Returns an entry in the ballot with a circle to draw into
|
// returns an entry in the ballot with a circle to draw into
|
||||||
PdfPredefinedFunctions.createBallotEntry = function(decision) {
|
PDFLayout.createBallotEntry = function(decision) {
|
||||||
return {
|
return {
|
||||||
margin: [40+BallotCircleDimensions.size, 10, 0, 0],
|
margin: [40+BallotCircleDimensions.size, 10, 0, 0],
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
width: 15,
|
width: 15,
|
||||||
canvas: PdfPredefinedFunctions.drawCircle(BallotCircleDimensions.yDistance, BallotCircleDimensions.size)
|
canvas: PDFLayout.drawCircle(BallotCircleDimensions.yDistance,
|
||||||
|
BallotCircleDimensions.size)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
width: "auto",
|
width: "auto",
|
||||||
@ -68,7 +98,8 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
PdfPredefinedFunctions.getBallotLayoutLines = function() {
|
// crop marks for ballot papers
|
||||||
|
PDFLayout.getBallotLayoutLines = function() {
|
||||||
return {
|
return {
|
||||||
hLineWidth: function(i, node) {
|
hLineWidth: function(i, node) {
|
||||||
return (i === 0 || i === node.table.body.length) ? 0 : 0.5;
|
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() {
|
.factory('HTMLValidizer', function() {
|
||||||
var HTMLValidizer = {};
|
var HTMLValidizer = {};
|
||||||
|
|
||||||
@ -111,67 +143,73 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
|||||||
return HTMLValidizer;
|
return HTMLValidizer;
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
.factory('PdfMakeDocumentProvider', [
|
.factory('PdfMakeDocumentProvider', [
|
||||||
'gettextCatalog',
|
'gettextCatalog',
|
||||||
'Config',
|
'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
|
|
||||||
*/
|
|
||||||
var createInstance = function(contentProvider, defaultFont) {
|
|
||||||
/**
|
|
||||||
* Generates header for PDF
|
|
||||||
* @constructor
|
* @constructor
|
||||||
|
* @param {object} contentProvider - Object with on method `getContent`, which
|
||||||
|
* returns an array for content
|
||||||
*/
|
*/
|
||||||
|
var createInstance = function(contentProvider) {
|
||||||
|
// PDF header
|
||||||
var header = function() {
|
var header = function() {
|
||||||
var date = new Date();
|
var date = new Date();
|
||||||
return {
|
var columns = [];
|
||||||
// alignment: 'center',
|
|
||||||
color: '#555',
|
// add here your custom logo (which has to be added to a custom vfs_fonts.js)
|
||||||
fontSize: 10,
|
// see https://github.com/pdfmake/pdfmake/wiki/Custom-Fonts---client-side
|
||||||
margin: [80, 50, 80, 0], //margin: [left, top, right, bottom]
|
/*
|
||||||
columns: [
|
columns.push({
|
||||||
{
|
image: 'logo.png',
|
||||||
text: Config.get('general_event_name').value + ' · ' + Config.get('general_event_description').value ,
|
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,
|
fontSize:10,
|
||||||
width: '70%'
|
width: '100%'
|
||||||
},
|
});
|
||||||
{
|
return {
|
||||||
fontSize: 6,
|
color: '#555',
|
||||||
width: '30%',
|
fontSize: 9,
|
||||||
text: gettextCatalog.getString('As of') + " " + date.toLocaleDateString() + " " + date.toLocaleTimeString(),
|
margin: [80, 30, 80, 10], // [left, top, right, bottom]
|
||||||
alignment: 'right'
|
columns: columns,
|
||||||
}]
|
columnGap: 10
|
||||||
};
|
};
|
||||||
},
|
};
|
||||||
/**
|
|
||||||
* Generates footer line
|
// PDF footer
|
||||||
* @function
|
var footer = function(currentPage, pageCount) {
|
||||||
* @param {object} currentPage - An object representing the current page
|
|
||||||
* @param {number} pageCount - number for pages
|
|
||||||
*/
|
|
||||||
footer = function(currentPage, pageCount) {
|
|
||||||
return {
|
return {
|
||||||
alignment: 'center',
|
alignment: 'center',
|
||||||
fontSize: 8,
|
fontSize: 8,
|
||||||
color: '#555',
|
color: '#555',
|
||||||
text: gettextCatalog.getString('Page') + ' ' + currentPage.toString() + ' / ' + pageCount.toString()
|
text: gettextCatalog.getString('Page') + ' ' + currentPage.toString() +
|
||||||
|
' / ' + pageCount.toString()
|
||||||
};
|
};
|
||||||
},
|
};
|
||||||
/**
|
// Generates the document(definition) for pdfMake
|
||||||
* Generates the document(definition) for pdfMake
|
var getDocument = function() {
|
||||||
* @function
|
|
||||||
*/
|
|
||||||
getDocument = function() {
|
|
||||||
var content = contentProvider.getContent();
|
var content = contentProvider.getContent();
|
||||||
return {
|
return {
|
||||||
pageSize: 'A4',
|
pageSize: 'A4',
|
||||||
pageMargins: [80, 90, 80, 60],
|
pageMargins: [80, 90, 80, 60],
|
||||||
defaultStyle: {
|
defaultStyle: {
|
||||||
font: defaultFont,
|
font: PDFLayout.getFontName(),
|
||||||
fontSize: 10
|
fontSize: 10
|
||||||
},
|
},
|
||||||
header: header,
|
header: header,
|
||||||
@ -179,12 +217,16 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
|||||||
content: content,
|
content: content,
|
||||||
styles: {
|
styles: {
|
||||||
title: {
|
title: {
|
||||||
fontSize: 30,
|
fontSize: 18,
|
||||||
margin: [0,0,0,20],
|
margin: [0,0,0,20],
|
||||||
bold: true
|
bold: true
|
||||||
},
|
},
|
||||||
|
subtitle: {
|
||||||
|
fontSize: 9,
|
||||||
|
margin: [0,-20,0,20],
|
||||||
|
},
|
||||||
preamble: {
|
preamble: {
|
||||||
fontSize: 12,
|
fontSize: 10,
|
||||||
margin: [0,0,0,10],
|
margin: [0,0,0,10],
|
||||||
},
|
},
|
||||||
userDataTitle: {
|
userDataTitle: {
|
||||||
@ -196,11 +238,16 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
|||||||
fontSize: 11,
|
fontSize: 11,
|
||||||
margin: [0,7]
|
margin: [0,7]
|
||||||
},
|
},
|
||||||
heading: {
|
heading2: {
|
||||||
fontSize: 16,
|
fontSize: 14,
|
||||||
margin: [0,0,0,10],
|
margin: [0,0,0,10],
|
||||||
bold: true
|
bold: true
|
||||||
},
|
},
|
||||||
|
heading3: {
|
||||||
|
fontSize: 12,
|
||||||
|
margin: [0,10,0,0],
|
||||||
|
bold: true
|
||||||
|
},
|
||||||
userDataHeading: {
|
userDataHeading: {
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
margin: [0,10],
|
margin: [0,10],
|
||||||
@ -219,11 +266,11 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
|||||||
margin: [0,3]
|
margin: [0,3]
|
||||||
},
|
},
|
||||||
listParent: {
|
listParent: {
|
||||||
fontSize: 14,
|
fontSize: 12,
|
||||||
margin: [0,5]
|
margin: [0,5]
|
||||||
},
|
},
|
||||||
listChild: {
|
listChild: {
|
||||||
fontSize: 11,
|
fontSize: 10,
|
||||||
margin: [0,5]
|
margin: [0,5]
|
||||||
},
|
},
|
||||||
tableHeader: {
|
tableHeader: {
|
||||||
@ -239,10 +286,20 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
|||||||
tableConclude: {
|
tableConclude: {
|
||||||
fillColor: '#ddd',
|
fillColor: '#ddd',
|
||||||
bold: true
|
bold: true
|
||||||
|
},
|
||||||
|
grey: {
|
||||||
|
fillColor: '#ddd',
|
||||||
|
},
|
||||||
|
lightgrey: {
|
||||||
|
fillColor: '#aaa',
|
||||||
|
},
|
||||||
|
bold: {
|
||||||
|
bold: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getDocument: getDocument
|
getDocument: getDocument
|
||||||
};
|
};
|
||||||
@ -256,14 +313,14 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
|||||||
.factory('PdfMakeBallotPaperProvider', [
|
.factory('PdfMakeBallotPaperProvider', [
|
||||||
'gettextCatalog',
|
'gettextCatalog',
|
||||||
'Config',
|
'Config',
|
||||||
function(gettextCatalog, Config) {
|
'PDFLayout',
|
||||||
|
function(gettextCatalog, Config, PDFLayout) {
|
||||||
/**
|
/**
|
||||||
* Provides the global Document
|
* Provides the global Document
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {object} contentProvider - Object with on method `getContent`, which returns an array for content
|
* @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
|
* Generates the document(definition) for pdfMake
|
||||||
* @function
|
* @function
|
||||||
@ -274,7 +331,7 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
|||||||
pageSize: 'A4',
|
pageSize: 'A4',
|
||||||
pageMargins: [0, 0, 0, 0],
|
pageMargins: [0, 0, 0, 0],
|
||||||
defaultStyle: {
|
defaultStyle: {
|
||||||
font: defaultFont,
|
font: PDFLayout.getFontName(),
|
||||||
fontSize: 10
|
fontSize: 10
|
||||||
},
|
},
|
||||||
content: content,
|
content: content,
|
||||||
@ -308,10 +365,9 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
|||||||
* Converter component for HTML->JSON for pdfMake
|
* Converter component for HTML->JSON for pdfMake
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {object} images - Key-Value structure representing image.src/BASE64 of images
|
* @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
|
* @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),
|
var slice = Function.prototype.call.bind([].slice),
|
||||||
map = Function.prototype.call.bind([].map),
|
map = Function.prototype.call.bind([].map),
|
||||||
|
|
||||||
@ -319,47 +375,6 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
|||||||
DIFF_MODE_INSERT = 1,
|
DIFF_MODE_INSERT = 1,
|
||||||
DIFF_MODE_DELETE = 2,
|
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
|
* Convertes HTML for use with pdfMake
|
||||||
* @function
|
* @function
|
||||||
@ -726,9 +741,6 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
|||||||
o[name] = content;
|
o[name] = content;
|
||||||
return o;
|
return o;
|
||||||
};
|
};
|
||||||
fonts.forEach(function(fontInfo) {
|
|
||||||
registerFont(fontInfo);
|
|
||||||
});
|
|
||||||
return {
|
return {
|
||||||
convertHTML: convertHTML,
|
convertHTML: convertHTML,
|
||||||
createElement: create
|
createElement: create
|
||||||
|
@ -788,22 +788,12 @@ class MediaEncoder(utils_views.APIView):
|
|||||||
Takes an array of IMG.src - Paths
|
Takes an array of IMG.src - Paths
|
||||||
Retrieves the according images
|
Retrieves the according images
|
||||||
Encodes the images to BASE64
|
Encodes the images to BASE64
|
||||||
Add configured fonts
|
|
||||||
Puts it into a key-value structure
|
Puts it into a key-value structure
|
||||||
|
|
||||||
{
|
{
|
||||||
"images": {
|
"images": {
|
||||||
"media/file/ubuntu.png":"$ENCODED_IMAGE"
|
"media/file/ubuntu.png":"$ENCODED_IMAGE"
|
||||||
},
|
|
||||||
"fonts": [{
|
|
||||||
$FontName : {
|
|
||||||
normal: $Filename
|
|
||||||
bold: $Filename
|
|
||||||
italics: $Filename
|
|
||||||
bolditalics: $Filename
|
|
||||||
}
|
}
|
||||||
}],
|
|
||||||
"default_font": "$DEFAULTFONT"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:param request:
|
:param request:
|
||||||
@ -818,86 +808,10 @@ class MediaEncoder(utils_views.APIView):
|
|||||||
body_unicode = request.body.decode('utf-8')
|
body_unicode = request.body.decode('utf-8')
|
||||||
file_paths = json.loads(body_unicode)
|
file_paths = json.loads(body_unicode)
|
||||||
images = {file_path: self.encode_image_from(file_path) for file_path in file_paths}
|
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({
|
return Response({
|
||||||
"images": images,
|
"images": images
|
||||||
"fonts": fonts,
|
|
||||||
"defaultFont": default_font
|
|
||||||
})
|
})
|
||||||
|
|
||||||
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):
|
def encode_image_from(self, file_path):
|
||||||
"""
|
"""
|
||||||
Returns the BASE64 encoded version of an image-file for a given 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
|
// calculate percent value
|
||||||
var config = Config.get('motions_poll_100_percent_base').value;
|
var config = Config.get('motions_poll_100_percent_base').value;
|
||||||
var percentStr;
|
var percentStr = '';
|
||||||
var percentNumber = null;
|
var percentNumber = null;
|
||||||
var base = null;
|
var base = null;
|
||||||
if (!impossible) {
|
if (!impossible) {
|
||||||
@ -137,7 +137,8 @@ angular.module('OpenSlidesApp.motions', [
|
|||||||
return {
|
return {
|
||||||
'value': value,
|
'value': value,
|
||||||
'percentStr': percentStr,
|
'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) {
|
$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 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";
|
var filename = gettextCatalog.getString("Motion") + "-" + $scope.motion.identifier + ".pdf";
|
||||||
pdfMake.createPdf(documentProvider.getDocument()).download(filename);
|
pdfMake.createPdf(documentProvider.getDocument()).download(filename);
|
||||||
});
|
});
|
||||||
|
@ -6,21 +6,199 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
|
|
||||||
.factory('MotionContentProvider', [
|
.factory('MotionContentProvider', [
|
||||||
'gettextCatalog',
|
'gettextCatalog',
|
||||||
'PdfPredefinedFunctions',
|
'PDFLayout',
|
||||||
function(gettextCatalog, PdfPredefinedFunctions) {
|
'Category',
|
||||||
|
'Config',
|
||||||
|
function(gettextCatalog, PDFLayout, Category, Config) {
|
||||||
/**
|
/**
|
||||||
* Provides the content as JS objects for Motions in pdfMake context
|
* Provides the content as JS objects for Motions in pdfMake context
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var createInstance = function(converter, motion, $scope, User) {
|
var createInstance = function(converter, motion, $scope) {
|
||||||
|
|
||||||
|
// title
|
||||||
var identifier = motion.identifier ? ' ' + motion.identifier : '';
|
var identifier = motion.identifier ? ' ' + motion.identifier : '';
|
||||||
var header = PdfPredefinedFunctions.createTitle(gettextCatalog.getString("Motion") + identifier +
|
var title = PDFLayout.createTitle(
|
||||||
': ' + motion.getTitle($scope.version));
|
gettextCatalog.getString('Motion') + identifier + ': ' +
|
||||||
|
motion.getTitle($scope.version)
|
||||||
|
);
|
||||||
|
|
||||||
// generates the text of the motion. Also septerates between line-numbers
|
// subtitle
|
||||||
var textContent = function() {
|
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") {
|
if ($scope.lineNumberMode == "inline" || $scope.lineNumberMode == "outside") {
|
||||||
/* in order to distinguish between the line-number-types we need to pass the scope
|
/* in order to distinguish between the line-number-types we need to pass the scope
|
||||||
* to the convertHTML function.
|
* to the convertHTML function.
|
||||||
@ -35,109 +213,18 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Generate text of reason
|
// motion reason heading
|
||||||
var reasonContent = function() {
|
var motionReason = function() {
|
||||||
return converter.convertHTML(motion.getReason($scope.version), $scope);
|
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
|
// getters
|
||||||
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
|
|
||||||
var getTitle = function() {
|
var getTitle = function() {
|
||||||
return motion.getTitle($scope.verion);
|
return motion.getTitle($scope.verion);
|
||||||
};
|
};
|
||||||
@ -152,25 +239,17 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
|
|
||||||
// Generates content as a pdfmake consumable
|
// Generates content as a pdfmake consumable
|
||||||
var getContent = function() {
|
var getContent = function() {
|
||||||
if (reasonContent().length === 0 ) {
|
var content = [
|
||||||
return [
|
title,
|
||||||
header,
|
subtitle,
|
||||||
signment(),
|
metaTable(),
|
||||||
polls(),
|
motionTitle(),
|
||||||
titleSection(),
|
motionText(),
|
||||||
textContent(),
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
return [
|
|
||||||
header,
|
|
||||||
signment(),
|
|
||||||
polls(),
|
|
||||||
titleSection(),
|
|
||||||
textContent(),
|
|
||||||
reason(),
|
|
||||||
reasonContent()
|
|
||||||
];
|
];
|
||||||
|
if (motionReason()) {
|
||||||
|
content.push(motionReason());
|
||||||
}
|
}
|
||||||
|
return content;
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
getContent: getContent,
|
getContent: getContent,
|
||||||
@ -186,8 +265,8 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
}])
|
}])
|
||||||
|
|
||||||
.factory('PollContentProvider', [
|
.factory('PollContentProvider', [
|
||||||
'PdfPredefinedFunctions',
|
'PDFLayout',
|
||||||
function(PdfPredefinedFunctions) {
|
function(PDFLayout) {
|
||||||
/**
|
/**
|
||||||
* Generates a content provider for polls
|
* Generates a content provider for polls
|
||||||
* @constructor
|
* @constructor
|
||||||
@ -211,9 +290,9 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
text: title,
|
text: title,
|
||||||
style: 'description'
|
style: 'description'
|
||||||
},
|
},
|
||||||
PdfPredefinedFunctions.createBallotEntry(gettextCatalog.getString("Yes")),
|
PDFLayout.createBallotEntry(gettextCatalog.getString("Yes")),
|
||||||
PdfPredefinedFunctions.createBallotEntry(gettextCatalog.getString("No")),
|
PDFLayout.createBallotEntry(gettextCatalog.getString("No")),
|
||||||
PdfPredefinedFunctions.createBallotEntry(gettextCatalog.getString("Abstain")),
|
PDFLayout.createBallotEntry(gettextCatalog.getString("Abstain")),
|
||||||
],
|
],
|
||||||
margin: [0, 0, 0, sheetend]
|
margin: [0, 0, 0, sheetend]
|
||||||
};
|
};
|
||||||
@ -237,7 +316,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
[createSection(), createSection()]
|
[createSection(), createSection()]
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
layout: PdfPredefinedFunctions.getBallotLayoutLines()
|
layout: PDFLayout.getBallotLayoutLines()
|
||||||
}];
|
}];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -252,20 +331,20 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
|
|
||||||
.factory('MotionCatalogContentProvider', [
|
.factory('MotionCatalogContentProvider', [
|
||||||
'gettextCatalog',
|
'gettextCatalog',
|
||||||
'PdfPredefinedFunctions',
|
'PDFLayout',
|
||||||
|
'Category',
|
||||||
'Config',
|
'Config',
|
||||||
function(gettextCatalog, PdfPredefinedFunctions, Config) {
|
function(gettextCatalog, PDFLayout, Category, Config) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
* @function
|
* @function
|
||||||
* @param {object} allMotions - A sorted array of all motions to parse
|
* @param {object} allMotions - A sorted array of all motions to parse
|
||||||
* @param {object} $scope - Current $scope
|
* @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)
|
gettextCatalog.getString(Config.get('motions_export_title').value)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -284,7 +363,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
var createTOContent = function() {
|
var createTOContent = function() {
|
||||||
var heading = {
|
var heading = {
|
||||||
text: gettextCatalog.getString("Table of contents"),
|
text: gettextCatalog.getString("Table of contents"),
|
||||||
style: "heading"
|
style: "heading2"
|
||||||
};
|
};
|
||||||
|
|
||||||
var toc = [];
|
var toc = [];
|
||||||
@ -310,7 +389,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
return [
|
return [
|
||||||
heading,
|
heading,
|
||||||
toc,
|
toc,
|
||||||
PdfPredefinedFunctions.addPageBreak()
|
PDFLayout.addPageBreak()
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -319,7 +398,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
if (Category.getAll().length > 0) {
|
if (Category.getAll().length > 0) {
|
||||||
var heading = {
|
var heading = {
|
||||||
text: gettextCatalog.getString("Categories"),
|
text: gettextCatalog.getString("Categories"),
|
||||||
style: "heading"
|
style: "heading2"
|
||||||
};
|
};
|
||||||
|
|
||||||
var toc = [];
|
var toc = [];
|
||||||
@ -344,7 +423,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
return [
|
return [
|
||||||
heading,
|
heading,
|
||||||
toc,
|
toc,
|
||||||
PdfPredefinedFunctions.addPageBreak()
|
PDFLayout.addPageBreak()
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
// if there are no categories, return "empty string"
|
// 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) {
|
angular.forEach(allMotions, function(motion, key) {
|
||||||
motionContent.push(motion.getContent());
|
motionContent.push(motion.getContent());
|
||||||
if (key < allMotions.length - 1) {
|
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.
|
//post-request to convert the images. Async.
|
||||||
$http.post('/core/encode_media/', JSON.stringify(image_sources)).success(function(data) {
|
$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 = [];
|
var motionContentProviderArray = [];
|
||||||
|
|
||||||
//convert the filtered motions to motionContentProviders
|
//convert the filtered motions to motionContentProviders
|
||||||
@ -934,7 +934,7 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
motionContentProviderArray.push(MotionContentProvider.createInstance(converter, motion, $scope, User, $http));
|
motionContentProviderArray.push(MotionContentProvider.createInstance(converter, motion, $scope, User, $http));
|
||||||
});
|
});
|
||||||
var motionCatalogContentProvider = MotionCatalogContentProvider.createInstance(motionContentProviderArray, $scope, User, Category);
|
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);
|
pdfMake.createPdf(documentProvider.getDocument()).download(filename);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -132,11 +132,13 @@
|
|||||||
|
|
||||||
<!-- Recommendation -->
|
<!-- Recommendation -->
|
||||||
<div ng-if="config('motions_recommendations_by') != ''">
|
<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">
|
<div ng-if="motion.isAllowed('change_recommendation')" class="heading">
|
||||||
<span uib-dropdown>
|
<span uib-dropdown>
|
||||||
<a href id="recommendation-dropdown" class="drop-down-name" uib-dropdown-toggle>
|
<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>
|
<i class="fa fa-cog"></i>
|
||||||
</a>
|
</a>
|
||||||
<ul uib-dropdown-menu class="dropdown-menu" aria-labelledby="recommendation-dropdown">
|
<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', [
|
.factory('UserListContentProvider', [
|
||||||
'gettextCatalog',
|
'gettextCatalog',
|
||||||
'PdfPredefinedFunctions',
|
'PDFLayout',
|
||||||
function(gettextCatalog, PdfPredefinedFunctions) {
|
function(gettextCatalog, PDFLayout) {
|
||||||
|
|
||||||
var createInstance = function(userList, groups) {
|
var createInstance = function(userList, groups) {
|
||||||
|
|
||||||
//use the Predefined Functions to create the title
|
//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
|
//function to generate the user list
|
||||||
var createUserList = function() {
|
var createUserList = function() {
|
||||||
@ -35,19 +35,19 @@ angular.module('OpenSlidesApp.users.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
var userJsonObj = [
|
var userJsonObj = [
|
||||||
{
|
{
|
||||||
text: "" + (counter+1),
|
text: "" + (counter+1),
|
||||||
style: PdfPredefinedFunctions.flipTableRowStyle(userJsonList.length)
|
style: PDFLayout.flipTableRowStyle(userJsonList.length)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: user.short_name,
|
text: user.short_name,
|
||||||
style: PdfPredefinedFunctions.flipTableRowStyle(userJsonList.length)
|
style: PDFLayout.flipTableRowStyle(userJsonList.length)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: user.structure_level,
|
text: user.structure_level,
|
||||||
style: PdfPredefinedFunctions.flipTableRowStyle(userJsonList.length)
|
style: PDFLayout.flipTableRowStyle(userJsonList.length)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: userGroups.join(" "),
|
text: userGroups.join(" "),
|
||||||
style: PdfPredefinedFunctions.flipTableRowStyle(userJsonList.length)
|
style: PDFLayout.flipTableRowStyle(userJsonList.length)
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
userJsonList.push(userJsonObj);
|
userJsonList.push(userJsonObj);
|
||||||
@ -107,8 +107,8 @@ angular.module('OpenSlidesApp.users.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
|
|
||||||
.factory('UserAccessDataListContentProvider', [
|
.factory('UserAccessDataListContentProvider', [
|
||||||
'gettextCatalog',
|
'gettextCatalog',
|
||||||
'PdfPredefinedFunctions',
|
'PDFLayout',
|
||||||
function(gettextCatalog, PdfPredefinedFunctions) {
|
function(gettextCatalog, PDFLayout) {
|
||||||
|
|
||||||
var createInstance = function(userList, groups, Config) {
|
var createInstance = function(userList, groups, Config) {
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user