Creates the Election documents using PdfMake
This commit is contained in:
parent
dc1c958e0f
commit
14ca655aa2
446
openslides/assignments/static/js/assignments/pdf.js
Normal file
446
openslides/assignments/static/js/assignments/pdf.js
Normal file
@ -0,0 +1,446 @@
|
||||
(function () {
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('OpenSlidesApp.assignments.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
|
||||
.factory('AssignmentContentProvider', [
|
||||
'gettextCatalog',
|
||||
'PdfPredefinedFunctions',
|
||||
function(gettextCatalog, PdfPredefinedFunctions) {
|
||||
|
||||
var createInstance = function(scope, polls) {
|
||||
|
||||
//use the Predefined Functions to create the title
|
||||
var title = PdfPredefinedFunctions.createTitle(
|
||||
gettextCatalog.getString("Election") + ": " + scope.assignment.title);
|
||||
|
||||
//create the preamble
|
||||
var createPreamble = function() {
|
||||
var preambleText = gettextCatalog.getString("Number of posts to be elected") + ": ";
|
||||
var memberNumber = ""+scope.assignment.open_posts;
|
||||
var preamble = {
|
||||
text: [
|
||||
{
|
||||
text: preambleText,
|
||||
bold: true,
|
||||
style: 'textItem'
|
||||
},
|
||||
{
|
||||
text: memberNumber,
|
||||
style: 'textItem'
|
||||
}
|
||||
]
|
||||
};
|
||||
return preamble;
|
||||
};
|
||||
|
||||
//adds the description if present in the assignment
|
||||
var createDescription = function() {
|
||||
if (scope.assignment.description) {
|
||||
var descriptionText = gettextCatalog.getString("Description") + ":";
|
||||
var description = [
|
||||
{
|
||||
text: descriptionText,
|
||||
bold: true,
|
||||
style: 'textItem'
|
||||
},
|
||||
{
|
||||
text: scope.assignment.description,
|
||||
style: 'textItem',
|
||||
margin: [10, 0, 0, 0]
|
||||
}
|
||||
];
|
||||
return description;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
//creates the candidate list in columns if the assignment phase is 'voting'
|
||||
var createCandidateList = function() {
|
||||
if (scope.assignment.phase != 2) {
|
||||
var candidatesText = gettextCatalog.getString("Candidates") + ": ";
|
||||
var userList = [];
|
||||
|
||||
angular.forEach(scope.assignment.assignment_related_users, function(assignmentsRelatedUser) {
|
||||
userList.push({
|
||||
text: assignmentsRelatedUser.user.get_full_name(),
|
||||
margin: [0, 0, 0, 10],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
var cadidateList = {
|
||||
columns: [
|
||||
{
|
||||
text: candidatesText,
|
||||
bold: true,
|
||||
width: "25%",
|
||||
style: 'textItem'
|
||||
},
|
||||
{
|
||||
ol: userList,
|
||||
style: 'textItem'
|
||||
}
|
||||
]
|
||||
};
|
||||
return cadidateList;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
//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)
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
text: candidateName,
|
||||
style: PdfPredefinedFunctions.flipTableRowStyle(pollTableBody.length)
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
//creates the pull result table
|
||||
var createPollResultTable = function() {
|
||||
var resultBody = [];
|
||||
angular.forEach(polls, function(poll, pollIndex) {
|
||||
if (poll.published) {
|
||||
var voteNrTotal = poll.votescast;
|
||||
var voteNrValid = poll.votesvalid;
|
||||
var voteNrInVal = poll.votesinvalid;
|
||||
var pollTableBody = [];
|
||||
|
||||
resultBody.push({
|
||||
text: gettextCatalog.getString("Ballot") + " " + (pollIndex+1),
|
||||
bold: true,
|
||||
style: 'textItem',
|
||||
margin: [0,15,0,0]
|
||||
});
|
||||
|
||||
pollTableBody.push([
|
||||
{
|
||||
text: gettextCatalog.getString("Candidates"),
|
||||
style: 'tableHeader',
|
||||
},
|
||||
{
|
||||
text: gettextCatalog.getString("Votes"),
|
||||
style: 'tableHeader',
|
||||
}
|
||||
]);
|
||||
|
||||
angular.forEach(poll.options, function(pollOption, optionIndex) {
|
||||
var candidateName = pollOption.candidate.get_full_name();
|
||||
var votes = pollOption.getVotes(); // 0 = yes, 1 = no, 2 = abstain
|
||||
var candidateLine;
|
||||
|
||||
if (poll.pollmethod == 'votes') {
|
||||
pollTableBody.push([
|
||||
electedCandidateLine(candidateName, pollOption, pollTableBody),
|
||||
{
|
||||
text: votes[0].value + " " + votes[0].percentStr,
|
||||
style: PdfPredefinedFunctions.flipTableRowStyle(pollTableBody.length)
|
||||
}
|
||||
]);
|
||||
} else if (poll.pollmethod == 'yn') {
|
||||
pollTableBody.push([
|
||||
{
|
||||
text: candidateName,
|
||||
style: PdfPredefinedFunctions.flipTableRowStyle(pollTableBody.length)
|
||||
},
|
||||
{
|
||||
text: [
|
||||
{
|
||||
text: votes[0].label + ": " + votes[0].value + " " + votes[0].percentStr + "\n"
|
||||
},
|
||||
{
|
||||
text: votes[1].label + ": " + votes[1].value + " " + votes[1].percentStr
|
||||
}
|
||||
],
|
||||
style: PdfPredefinedFunctions.flipTableRowStyle(pollTableBody.length)
|
||||
}
|
||||
]);
|
||||
} else if (poll.pollmethod == 'yna') {
|
||||
pollTableBody.push([
|
||||
{
|
||||
text: candidateName,
|
||||
style: PdfPredefinedFunctions.flipTableRowStyle(pollTableBody.length)
|
||||
},
|
||||
{
|
||||
text: [
|
||||
{
|
||||
text: votes[0].label + ": " + votes[0].value + " " + votes[0].percentStr + "\n"
|
||||
},
|
||||
{
|
||||
text: votes[1].label + ": " + votes[1].value + " " + votes[1].percentStr + "\n"
|
||||
},
|
||||
{
|
||||
text: votes[2].label + ": " + votes[2].value + " " + votes[2].percentStr
|
||||
}
|
||||
],
|
||||
style: PdfPredefinedFunctions.flipTableRowStyle(pollTableBody.length)
|
||||
}
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
//it is technically possible to make a single push-statement
|
||||
//however, the flipTableRowStyle-function needs the current table size
|
||||
if (voteNrValid) {
|
||||
pollTableBody.push([
|
||||
{
|
||||
text: gettextCatalog.getString("Valid ballots"),
|
||||
style: 'tableConclude'
|
||||
},
|
||||
{
|
||||
text: ""+voteNrValid,
|
||||
style: 'tableConclude'
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
if (voteNrInVal) {
|
||||
pollTableBody.push([
|
||||
{
|
||||
text: gettextCatalog.getString("Invalid ballots"),
|
||||
style: 'tableConclude'
|
||||
},
|
||||
{
|
||||
text: ""+voteNrInVal,
|
||||
style: 'tableConclude'
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
if (voteNrTotal) {
|
||||
pollTableBody.push([
|
||||
{
|
||||
text: gettextCatalog.getString("Casted ballots"),
|
||||
style: 'tableConclude'
|
||||
},
|
||||
{
|
||||
text: ""+voteNrTotal,
|
||||
style: 'tableConclude'
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
var resultTableJsonSting = {
|
||||
table: {
|
||||
widths: ['64%','33%'],
|
||||
headerRows: 1,
|
||||
body: pollTableBody,
|
||||
},
|
||||
layout: 'headerLineOnly',
|
||||
};
|
||||
|
||||
resultBody.push(resultTableJsonSting);
|
||||
}
|
||||
});
|
||||
|
||||
//Add the Legend to the result body
|
||||
resultBody.push({
|
||||
text: "* = " + gettextCatalog.getString("is elected"),
|
||||
margin: [0,5,0,0],
|
||||
});
|
||||
|
||||
return resultBody;
|
||||
};
|
||||
|
||||
var getContent = function() {
|
||||
return [
|
||||
title,
|
||||
createPreamble(),
|
||||
createDescription(),
|
||||
createCandidateList(),
|
||||
createPollResultTable()
|
||||
];
|
||||
};
|
||||
|
||||
return {
|
||||
getContent: getContent
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
createInstance: createInstance
|
||||
};
|
||||
}])
|
||||
|
||||
.factory('BallotContentProvider', [
|
||||
'gettextCatalog',
|
||||
'PdfPredefinedFunctions',
|
||||
function(gettextCatalog, PdfPredefinedFunctions) {
|
||||
|
||||
var createInstance = function(scope, poll, pollNumber) {
|
||||
|
||||
// use the Predefined Functions to create the title
|
||||
var createTitle = function() {
|
||||
return {
|
||||
text: gettextCatalog.getString("Election") + ": " + scope.assignment.title,
|
||||
style: 'title',
|
||||
};
|
||||
};
|
||||
|
||||
//function to create the poll hint
|
||||
var createPollHint = function() {
|
||||
return {
|
||||
text: gettextCatalog.getString("Ballot") + " " + pollNumber + ": " + poll.description,
|
||||
style: 'description',
|
||||
};
|
||||
};
|
||||
|
||||
//function to create the selection entries
|
||||
var createYNBallotEntry = function(decision) {
|
||||
var YNColumn = [
|
||||
{
|
||||
width: "auto",
|
||||
stack: [
|
||||
PdfPredefinedFunctions.createBallotEntry(gettextCatalog.getString("Yes"))
|
||||
]
|
||||
},
|
||||
{
|
||||
width: "auto",
|
||||
stack: [
|
||||
PdfPredefinedFunctions.createBallotEntry(gettextCatalog.getString("No"))
|
||||
]
|
||||
},
|
||||
];
|
||||
|
||||
if (poll.pollmethod == 'yna') {
|
||||
YNColumn.push({
|
||||
width: "auto",
|
||||
stack: [
|
||||
PdfPredefinedFunctions.createBallotEntry(gettextCatalog.getString("Abstain"))
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
text: decision,
|
||||
margin: [40, 10, 0, 0],
|
||||
},
|
||||
{
|
||||
columns: YNColumn
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
var createSelectionField = function() {
|
||||
var candidateBallotList = [];
|
||||
|
||||
if (poll.pollmethod == 'votes') {
|
||||
angular.forEach(poll.options, function(option) {
|
||||
var candidate = option.candidate.get_full_name();
|
||||
candidateBallotList.push(PdfPredefinedFunctions.createBallotEntry(candidate));
|
||||
});
|
||||
} else {
|
||||
angular.forEach(poll.options, function(option) {
|
||||
var candidate = option.candidate.get_full_name();
|
||||
candidateBallotList.push(createYNBallotEntry(candidate));
|
||||
});
|
||||
}
|
||||
return candidateBallotList;
|
||||
};
|
||||
|
||||
var createSection = function(marginTop) {
|
||||
|
||||
// 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 : [
|
||||
{
|
||||
width: 1,
|
||||
margin: [0,marginTop],
|
||||
text: ""
|
||||
},
|
||||
{
|
||||
width: '*',
|
||||
stack: [
|
||||
createTitle(),
|
||||
createPollHint(),
|
||||
createSelectionField(),
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
};
|
||||
|
||||
var createTableBody = function(numberOfRows, sheetend) {
|
||||
var tableBody = [];
|
||||
for (var i = 0; i < numberOfRows; i++) {
|
||||
tableBody.push([createSection(sheetend), createSection(sheetend)]);
|
||||
}
|
||||
return tableBody;
|
||||
};
|
||||
|
||||
var createContentTable = function() {
|
||||
|
||||
var tableBody = [];
|
||||
var sheetend;
|
||||
|
||||
if (poll.pollmethod == 'votes') {
|
||||
if (poll.options.length <= 4) {
|
||||
sheetend = 105;
|
||||
tableBody = createTableBody(4, sheetend);
|
||||
} else if (poll.options.length <= 8) {
|
||||
sheetend = 140;
|
||||
tableBody = tableBody = createTableBody(3, sheetend);
|
||||
} else if (poll.options.length <= 12) {
|
||||
sheetend = 210;
|
||||
tableBody = tableBody = createTableBody(2, sheetend);
|
||||
}
|
||||
else { //works untill ~30 people
|
||||
sheetend = 418;
|
||||
tableBody = createTableBody(1, sheetend);
|
||||
}
|
||||
} else {
|
||||
if (poll.options.length <= 2) {
|
||||
sheetend = 105;
|
||||
tableBody = createTableBody(4, sheetend);
|
||||
} else if (poll.options.length <= 4) {
|
||||
sheetend = 140;
|
||||
tableBody = createTableBody(3, sheetend);
|
||||
} else if (poll.options.length <= 6) {
|
||||
sheetend = 210;
|
||||
tableBody = createTableBody(2, sheetend);
|
||||
} else {
|
||||
sheetend = 418;
|
||||
tableBody = createTableBody(1, sheetend);
|
||||
}
|
||||
}
|
||||
|
||||
return [{
|
||||
table: {
|
||||
headerRows: 1,
|
||||
widths: ['50%', '50%'],
|
||||
body: tableBody
|
||||
},
|
||||
layout: PdfPredefinedFunctions.getBallotLayoutLines()
|
||||
}];
|
||||
};
|
||||
|
||||
var getContent = function() {
|
||||
return createContentTable();
|
||||
};
|
||||
|
||||
return {
|
||||
getContent: getContent
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
createInstance: createInstance
|
||||
};
|
||||
|
||||
}]);
|
||||
|
||||
}());
|
@ -2,7 +2,11 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments'])
|
||||
angular.module('OpenSlidesApp.assignments.site', [
|
||||
'OpenSlidesApp.assignments',
|
||||
'OpenSlidesApp.core.pdf',
|
||||
'OpenSlidesApp.assignments.pdf'
|
||||
])
|
||||
|
||||
.config([
|
||||
'mainMenuProvider',
|
||||
@ -351,8 +355,14 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments'])
|
||||
'phases',
|
||||
'Projector',
|
||||
'ProjectionDefault',
|
||||
'AssignmentContentProvider',
|
||||
'BallotContentProvider',
|
||||
'PdfMakeDocumentProvider',
|
||||
'PdfMakeBallotPaperProvider',
|
||||
'gettextCatalog',
|
||||
function($scope, $http, filterFilter, gettext, ngDialog, AssignmentForm, operator, Assignment, User,
|
||||
assignment, phases, Projector, ProjectionDefault) {
|
||||
assignment, phases, Projector, ProjectionDefault, AssignmentContentProvider, BallotContentProvider,
|
||||
PdfMakeDocumentProvider, PdfMakeBallotPaperProvider, gettextCatalog) {
|
||||
User.bindAll({}, $scope, 'users');
|
||||
Assignment.bindOne(assignment.id, $scope, 'assignment');
|
||||
Assignment.loadRelations(assignment, 'agenda_item');
|
||||
@ -512,6 +522,30 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments'])
|
||||
|
||||
};
|
||||
|
||||
//creates the document as pdf
|
||||
$scope.makePDF_singleAssignment = function() {
|
||||
var filename = gettextCatalog.getString("Election") + " " + $scope.assignment.title + ".pdf";
|
||||
var assignmentContentProvider = AssignmentContentProvider.createInstance($scope, assignment.polls);
|
||||
var documentProvider = PdfMakeDocumentProvider.createInstance(assignmentContentProvider);
|
||||
pdfMake.createPdf(documentProvider.getDocument()).download(filename);
|
||||
};
|
||||
|
||||
//creates the ballotpaper as pdf
|
||||
$scope.makePDF_assignmentpoll = function(pollID) {
|
||||
var thePoll;
|
||||
var pollNumber;
|
||||
angular.forEach(assignment.polls, function(poll, pollIndex) {
|
||||
if (poll.id == pollID) {
|
||||
thePoll = poll;
|
||||
pollNumber = pollIndex+1;
|
||||
}
|
||||
});
|
||||
var filename = gettextCatalog.getString("Ballot") + " " + pollNumber + " " + $scope.assignment.title + ".pdf";
|
||||
var ballotContentProvider = BallotContentProvider.createInstance($scope, thePoll, pollNumber);
|
||||
var documentProvider = PdfMakeBallotPaperProvider.createInstance(ballotContentProvider);
|
||||
pdfMake.createPdf(documentProvider.getDocument()).download(filename);
|
||||
};
|
||||
|
||||
// Just mark some vote value strings for translation.
|
||||
gettext('Yes');
|
||||
gettext('No');
|
||||
|
@ -21,7 +21,7 @@
|
||||
<i class="fa fa-pencil"></i>
|
||||
</a>
|
||||
<!-- pdf -->
|
||||
<a ui-sref="assignments_single_pdf({pk: assignment.id})" target="_blank" class="btn btn-default btn-sm">
|
||||
<a ng-click="makePDF_singleAssignment()" target="_blank" class="btn btn-default btn-sm">
|
||||
<i class="fa fa-file-pdf-o fa-lg"></i>
|
||||
<translate>PDF</translate>
|
||||
</a>
|
||||
@ -143,8 +143,7 @@
|
||||
<!-- angular requires to open the link in new tab with "target='_blank'".
|
||||
Otherwise the pdf url can't be open in same window; angular redirects to "/". -->
|
||||
<!-- PDF -->
|
||||
<a ui-sref="assignmentpoll_pdf({poll_pk: poll.id})" target="_blank"
|
||||
class="btn btn-default btn-sm">
|
||||
<a ng-click="makePDF_assignmentpoll(poll.id)" target="_blank" class="btn btn-default btn-sm">
|
||||
<i class="fa fa-file-pdf-o"></i>
|
||||
<translate>Print ballot paper</translate>
|
||||
</a>
|
||||
|
@ -7,6 +7,10 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
||||
.factory('PdfPredefinedFunctions', [
|
||||
function() {
|
||||
var PdfPredefinedFunctions = {};
|
||||
var BallotCircleDimensions = {
|
||||
yDistance: 6,
|
||||
size: 8
|
||||
};
|
||||
|
||||
PdfPredefinedFunctions.createTitle = function(titleString) {
|
||||
return {
|
||||
@ -15,6 +19,62 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
||||
};
|
||||
};
|
||||
|
||||
PdfPredefinedFunctions.flipTableRowStyle = function(currentTableSize) {
|
||||
if (currentTableSize % 2 === 0) {
|
||||
return "tableEven";
|
||||
} else {
|
||||
return "tableOdd";
|
||||
}
|
||||
};
|
||||
|
||||
//draws a circle
|
||||
PdfPredefinedFunctions.drawCircle = function(y, size) {
|
||||
return [
|
||||
{
|
||||
type: 'ellipse',
|
||||
x: 0,
|
||||
y: y,
|
||||
lineColor: 'black',
|
||||
r1: size,
|
||||
r2: size
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
//Returns an entry in the ballot with a circle to draw into
|
||||
PdfPredefinedFunctions.createBallotEntry = function(decision) {
|
||||
return {
|
||||
margin: [40+BallotCircleDimensions.size, 10, 0, 0],
|
||||
columns: [
|
||||
{
|
||||
width: 15,
|
||||
canvas: PdfPredefinedFunctions.drawCircle(BallotCircleDimensions.yDistance, BallotCircleDimensions.size)
|
||||
},
|
||||
{
|
||||
width: "auto",
|
||||
text: decision
|
||||
}
|
||||
],
|
||||
};
|
||||
};
|
||||
|
||||
PdfPredefinedFunctions.getBallotLayoutLines = function() {
|
||||
return {
|
||||
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.5;
|
||||
},
|
||||
hLineColor: function(i, node) {
|
||||
return (i === 0 || i === node.table.body.length) ? 'none' : 'gray';
|
||||
},
|
||||
vLineColor: function(i, node) {
|
||||
return (i === 0 || i === node.table.widths.length) ? 'none' : 'gray';
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
return PdfPredefinedFunctions;
|
||||
}
|
||||
])
|
||||
@ -113,6 +173,10 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
||||
margin: [0,0,0,20],
|
||||
bold: true
|
||||
},
|
||||
textItem: {
|
||||
fontSize: 11,
|
||||
margin: [0,7]
|
||||
},
|
||||
heading: {
|
||||
fontSize: 16,
|
||||
margin: [0,0,0,10],
|
||||
@ -131,13 +195,18 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
||||
margin: [0,5]
|
||||
},
|
||||
tableHeader: {
|
||||
bold: true
|
||||
bold: true,
|
||||
fillColor: 'white'
|
||||
},
|
||||
tableEven: {
|
||||
fillColor: 'white'
|
||||
},
|
||||
tableOdd: {
|
||||
fillColor: '#e7e7e7'
|
||||
fillColor: '#eee'
|
||||
},
|
||||
tableConclude: {
|
||||
fillColor: '#ddd',
|
||||
bold: true
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -152,6 +221,54 @@ angular.module('OpenSlidesApp.core.pdf', [])
|
||||
}
|
||||
])
|
||||
|
||||
.factory('PdfMakeBallotPaperProvider', [
|
||||
'gettextCatalog',
|
||||
'Config',
|
||||
function(gettextCatalog, Config) {
|
||||
/**
|
||||
* 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 the document(definition) for pdfMake
|
||||
* @function
|
||||
*/
|
||||
var getDocument = function() {
|
||||
var content = contentProvider.getContent();
|
||||
return {
|
||||
pageSize: 'A4',
|
||||
pageMargins: [0, 0, 0, 0],
|
||||
defaultStyle: {
|
||||
font: defaultFont,
|
||||
fontSize: 10
|
||||
},
|
||||
content: content,
|
||||
styles: {
|
||||
title: {
|
||||
fontSize: 14,
|
||||
bold: true,
|
||||
margin: [30, 30, 0, 0]
|
||||
},
|
||||
description: {
|
||||
fontSize: 11,
|
||||
margin: [30, 0, 0, 0]
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
return {
|
||||
getDocument: getDocument
|
||||
};
|
||||
};
|
||||
return {
|
||||
createInstance: createInstance
|
||||
};
|
||||
}
|
||||
])
|
||||
|
||||
.factory('PdfMakeConverter', [
|
||||
'HTMLValidizer',
|
||||
function(HTMLValidizer) {
|
||||
|
@ -10,12 +10,13 @@ angular.module('OpenSlidesApp.motions.motionservices', ['OpenSlidesApp.motions',
|
||||
'User',
|
||||
'PdfMakeConverter',
|
||||
'PdfMakeDocumentProvider',
|
||||
'PdfMakeBallotPaperProvider',
|
||||
'MotionContentProvider',
|
||||
'PollContentProvider',
|
||||
'gettextCatalog',
|
||||
'$http',
|
||||
function (HTMLValidizer, Motion, User, PdfMakeConverter, PdfMakeDocumentProvider, MotionContentProvider,
|
||||
PollContentProvider, gettextCatalog, $http) {
|
||||
function (HTMLValidizer, Motion, User, PdfMakeConverter, PdfMakeDocumentProvider, PdfMakeBallotPaperProvider,
|
||||
MotionContentProvider, PollContentProvider, gettextCatalog, $http) {
|
||||
var obj = {};
|
||||
|
||||
var $scope;
|
||||
@ -39,12 +40,12 @@ angular.module('OpenSlidesApp.motions.motionservices', ['OpenSlidesApp.motions',
|
||||
|
||||
//make PDF for polls
|
||||
obj.createPoll = function() {
|
||||
var id = $scope.motion.identifier.replace(" ", ""),
|
||||
title = $scope.motion.getTitle($scope.version),
|
||||
filename = gettextCatalog.getString("Motion") + "-" + id + "-" + gettextCatalog.getString("ballot-paper") + ".pdf",
|
||||
content = PollContentProvider.createInstance(title, id, gettextCatalog);
|
||||
|
||||
pdfMake.createPdf(content).download(filename);
|
||||
var id = $scope.motion.identifier.replace(" ", "");
|
||||
var title = $scope.motion.getTitle($scope.version);
|
||||
var filename = gettextCatalog.getString("Motion") + "-" + id + "-" + gettextCatalog.getString("ballot-paper") + ".pdf";
|
||||
var pollContentProvider = PollContentProvider.createInstance(title, id, gettextCatalog);
|
||||
var documentProvider = PdfMakeBallotPaperProvider.createInstance(pollContentProvider);
|
||||
pdfMake.createPdf(documentProvider.getDocument()).download(filename);
|
||||
};
|
||||
|
||||
obj.init = function (_scope) {
|
||||
|
@ -184,7 +184,9 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
};
|
||||
}])
|
||||
|
||||
.factory('PollContentProvider', function() {
|
||||
.factory('PollContentProvider', [
|
||||
'PdfPredefinedFunctions',
|
||||
function(PdfPredefinedFunctions) {
|
||||
/**
|
||||
* Generates a content provider for polls
|
||||
* @constructor
|
||||
@ -192,84 +194,25 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
* @param {string} id - if of poll
|
||||
* @param {object} gettextCatalog - for translation
|
||||
*/
|
||||
var createInstance = function(title, id, gettextCatalog){
|
||||
|
||||
//left and top margin for a single sheet
|
||||
var space = {
|
||||
left: 30,
|
||||
top: 30,
|
||||
bottom: 10
|
||||
},
|
||||
//size and position of the signing circle
|
||||
circle = {
|
||||
yDistance: 6,
|
||||
size: 8
|
||||
},
|
||||
//margin for the decision
|
||||
singleItemMargin = 10,
|
||||
//space between circle and dicision
|
||||
columnwidth = 20,
|
||||
//defines the space under a single sheet
|
||||
sheetend = 65,
|
||||
//defines the used fontsize
|
||||
fontSize = 14;
|
||||
|
||||
/**
|
||||
* draws a single circle
|
||||
* @function
|
||||
* @param {int} y - the relative y coordinate
|
||||
* @param {int} size - size of the circle in px
|
||||
*/
|
||||
var drawCircle = function(y, size) {
|
||||
return [
|
||||
{
|
||||
type: 'ellipse',
|
||||
x: 0,
|
||||
y: y,
|
||||
lineColor: 'black',
|
||||
r1: size,
|
||||
r2: size
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns an entry in the ballot with a circle to draw into
|
||||
* @function
|
||||
* @param {string} decision - the name of an entry to decide between, e.g. 'yes' or 'no'
|
||||
*/
|
||||
var createBallotEntry = function(decision) {
|
||||
return {
|
||||
margin: [space.left+circle.size, singleItemMargin, 0, 0],
|
||||
columns: [
|
||||
{
|
||||
width: columnwidth,
|
||||
canvas: drawCircle(circle.yDistance, circle.size)
|
||||
},
|
||||
{
|
||||
text: decision
|
||||
}
|
||||
],
|
||||
};
|
||||
};
|
||||
var createInstance = function(title, id, gettextCatalog) {
|
||||
|
||||
/**
|
||||
* Returns a single section on the ballot paper
|
||||
* @function
|
||||
*/
|
||||
var createSection = function() {
|
||||
var sheetend = 75;
|
||||
return {
|
||||
stack: [{
|
||||
text: gettextCatalog.getString("Motion") + " " + id,
|
||||
style: 'header',
|
||||
margin: [space.left, space.top, 0, 0]
|
||||
style: 'title',
|
||||
}, {
|
||||
text: title,
|
||||
margin: [space.left, 0, 0, space.bottom]
|
||||
style: 'description'
|
||||
},
|
||||
createBallotEntry(gettextCatalog.getString("Yes")),
|
||||
createBallotEntry(gettextCatalog.getString("No")),
|
||||
createBallotEntry(gettextCatalog.getString("Abstain")),
|
||||
PdfPredefinedFunctions.createBallotEntry(gettextCatalog.getString("Yes")),
|
||||
PdfPredefinedFunctions.createBallotEntry(gettextCatalog.getString("No")),
|
||||
PdfPredefinedFunctions.createBallotEntry(gettextCatalog.getString("Abstain")),
|
||||
],
|
||||
margin: [0, 0, 0, sheetend]
|
||||
};
|
||||
@ -280,8 +223,9 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
* @function
|
||||
* @param {string} id - if of poll
|
||||
*/
|
||||
return {
|
||||
content: [{
|
||||
|
||||
var getContent = function() {
|
||||
return [{
|
||||
table: {
|
||||
headerRows: 1,
|
||||
widths: ['*', '*'],
|
||||
@ -292,27 +236,18 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
[createSection(), createSection()]
|
||||
],
|
||||
},
|
||||
layout: {
|
||||
hLineWidth: function() {return 0.5;},
|
||||
vLineWidth: function() {return 0.5;},
|
||||
hLineColor: function() {return 'gray';},
|
||||
vLineColor: function() {return 'gray';},
|
||||
}
|
||||
}],
|
||||
pageSize: 'A4',
|
||||
pageMargins: [0, 0, 0, 0],
|
||||
styles: {
|
||||
header: {
|
||||
fontSize: fontSize,
|
||||
bold: true
|
||||
}
|
||||
},
|
||||
layout: PdfPredefinedFunctions.getBallotLayoutLines()
|
||||
}];
|
||||
};
|
||||
|
||||
return {
|
||||
getContent: getContent,
|
||||
};
|
||||
};
|
||||
return {
|
||||
createInstance: createInstance
|
||||
};
|
||||
})
|
||||
}])
|
||||
|
||||
.factory('MotionCatalogContentProvider', [
|
||||
'gettextCatalog',
|
||||
|
@ -20,14 +20,6 @@ angular.module('OpenSlidesApp.users.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
|
||||
angular.forEach(userList, function (user, counter) {
|
||||
|
||||
//check if the row is even or odd
|
||||
var rowStyle = [];
|
||||
if (counter % 2 === 0) {
|
||||
rowStyle = 'tableEven';
|
||||
} else {
|
||||
rowStyle = 'tableOdd';
|
||||
}
|
||||
|
||||
//parse for the group names
|
||||
var userGroups = [];
|
||||
angular.forEach(user.groups_id, function (id) {
|
||||
@ -43,19 +35,19 @@ angular.module('OpenSlidesApp.users.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
var userJsonObj = [
|
||||
{
|
||||
text: "" + (counter+1),
|
||||
style: rowStyle
|
||||
style: PdfPredefinedFunctions.flipTableRowStyle(userJsonList.length)
|
||||
},
|
||||
{
|
||||
text: user.short_name,
|
||||
style: rowStyle
|
||||
style: PdfPredefinedFunctions.flipTableRowStyle(userJsonList.length)
|
||||
},
|
||||
{
|
||||
text: user.structure_level,
|
||||
style: rowStyle
|
||||
style: PdfPredefinedFunctions.flipTableRowStyle(userJsonList.length)
|
||||
},
|
||||
{
|
||||
text: userGroups.join(" "),
|
||||
style: rowStyle
|
||||
style: PdfPredefinedFunctions.flipTableRowStyle(userJsonList.length)
|
||||
}
|
||||
];
|
||||
userJsonList.push(userJsonObj);
|
||||
|
Loading…
Reference in New Issue
Block a user