1444 lines
59 KiB
JavaScript
1444 lines
59 KiB
JavaScript
(function () {
|
|
|
|
"use strict";
|
|
|
|
angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
|
|
|
.factory('MotionContentProvider', [
|
|
'$q',
|
|
'$filter',
|
|
'operator',
|
|
'gettextCatalog',
|
|
'PDFLayout',
|
|
'PdfMakeConverter',
|
|
'ImageConverter',
|
|
'HTMLValidizer',
|
|
'Category',
|
|
'Config',
|
|
'Motion',
|
|
'MotionComment',
|
|
'OpenSlidesSettings',
|
|
function($q, $filter, operator, gettextCatalog, PDFLayout, PdfMakeConverter, ImageConverter,
|
|
HTMLValidizer, Category, Config, Motion, MotionComment, OpenSlidesSettings) {
|
|
/**
|
|
* Provides the content as JS objects for Motions in pdfMake context
|
|
* @constructor
|
|
*/
|
|
|
|
var createInstance = function(motion, motionVersion, params) {
|
|
params = _.clone(params || {}); // Clone this to avoid sideeffects.
|
|
_.defaults(params, {
|
|
changeRecommendationMode: Config.get('motions_recommendation_text_mode').value,
|
|
lineNumberMode: Config.get('motions_default_line_numbering').value,
|
|
include: {
|
|
text: true,
|
|
reason: true,
|
|
state: true,
|
|
submitters: true,
|
|
votingresult: true,
|
|
motionBlock: true,
|
|
origin: true,
|
|
recommendation: true,
|
|
},
|
|
includeComments: {},
|
|
});
|
|
|
|
var converter, imageMap = {};
|
|
|
|
// Query all image sources from motion text and reason
|
|
var getImageSources = function () {
|
|
var text = motion.getTextByMode(params.changeRecommendationMode, null);
|
|
var reason = motion.getReason();
|
|
var comments = '';
|
|
_.forEach(params.includeComments, function (ok, id) {
|
|
if (ok && motion.comments[id]) {
|
|
comments += HTMLValidizer.validize(motion.comments[id]);
|
|
}
|
|
});
|
|
var content = HTMLValidizer.validize(text) + HTMLValidizer.validize(motion.getReason()) + comments;
|
|
var map = Function.prototype.call.bind([].map);
|
|
return map($(content).find('img'), function(element) {
|
|
return element.getAttribute('src');
|
|
});
|
|
};
|
|
|
|
// title
|
|
var identifier = motion.identifier ? ' ' + motion.identifier : '';
|
|
var titlePlain = motion.getTitleWithChanges(params.changeRecommendationMode, motionVersion);
|
|
var title = PDFLayout.createTitle(gettextCatalog.getString('Motion') + identifier + ': ' + titlePlain);
|
|
|
|
// subtitle and sequential number
|
|
var subtitleLines = [];
|
|
if (motion.parent_id) {
|
|
var parentMotion = Motion.get(motion.parent_id);
|
|
subtitleLines.push(
|
|
gettextCatalog.getString('Amendment to motion') + ': ' +
|
|
(parentMotion.identifier ? parentMotion.identifier : parentMotion.getTitle())
|
|
);
|
|
}
|
|
if (Config.get('motions_export_sequential_number').value) {
|
|
subtitleLines.push(gettextCatalog.getString('Sequential number') + ': ' +
|
|
motion.getSequentialNumber());
|
|
}
|
|
var subtitle = PDFLayout.createSubtitle(subtitleLines);
|
|
|
|
// meta data table
|
|
var metaTable = function() {
|
|
var metaTableBody = [];
|
|
|
|
// submitters
|
|
var submitters = _.map(
|
|
$filter('orderBy')(motion.submitters, 'weight'), function (submitter) {
|
|
return submitter.user.get_full_name();
|
|
}
|
|
).join(', ');
|
|
if (params.include.submitters) {
|
|
metaTableBody.push([
|
|
{
|
|
text: gettextCatalog.getString('Submitters') + ':',
|
|
style: ['bold', 'grey'],
|
|
},
|
|
{
|
|
text: submitters,
|
|
style: 'grey'
|
|
}
|
|
]);
|
|
}
|
|
|
|
// state
|
|
if (params.include.state) {
|
|
metaTableBody.push([
|
|
{
|
|
text: gettextCatalog.getString('State') + ':',
|
|
style: ['bold', 'grey']
|
|
},
|
|
{
|
|
text: motion.getStateName(),
|
|
style: 'grey'
|
|
}
|
|
]);
|
|
}
|
|
|
|
// recommendation
|
|
if (params.include.recommendation && 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.prefix + ' - ' + motion.category.name,
|
|
style: 'grey'
|
|
}
|
|
]);
|
|
}
|
|
|
|
// motion block
|
|
if (params.include.motionBlock && motion.motionBlock) {
|
|
metaTableBody.push([
|
|
{
|
|
text: gettextCatalog.getString('Motion block') + ':',
|
|
style: ['bold', 'grey'] },
|
|
{
|
|
text: motion.motionBlock.title,
|
|
style: 'grey'
|
|
}
|
|
]);
|
|
}
|
|
|
|
// origin
|
|
if (params.include.origin && motion.origin) {
|
|
metaTableBody.push([
|
|
{
|
|
text: gettextCatalog.getString('Origin') + ':',
|
|
style: ['bold', 'grey'] },
|
|
{
|
|
text: motion.origin,
|
|
style: 'grey'
|
|
}
|
|
]);
|
|
}
|
|
|
|
// voting result
|
|
if (params.include.votingresult && motion.polls.length > 0 && motion.polls[0].has_votes) {
|
|
var column1 = [];
|
|
var column2 = [];
|
|
var column3 = [];
|
|
motion.polls.map(function(poll, index) {
|
|
if (poll.has_votes) {
|
|
// votenumber
|
|
if (motion.polls.length > 1) {
|
|
column1.push(index + 1 + '. ' + gettextCatalog.getString('Vote'));
|
|
column2.push('');
|
|
column3.push('');
|
|
}
|
|
// 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'
|
|
}
|
|
]);
|
|
}
|
|
|
|
// summary of change recommendations (for motion diff version only)
|
|
if (params.changeRecommendationMode === 'diff' && motion.changeRecommendations.length) {
|
|
var columnLineNumbers = [];
|
|
var columnChangeType = [];
|
|
angular.forEach(_.orderBy(motion.changeRecommendations, ['line_from']), function(change) {
|
|
if (change.isTitleRecommendation()) {
|
|
columnLineNumbers.push(
|
|
gettextCatalog.getString('Title') + ': '
|
|
);
|
|
} else {
|
|
// line numbers column
|
|
var line;
|
|
if (change.line_from >= change.line_to - 1) {
|
|
line = change.line_from;
|
|
} else {
|
|
line = change.line_from + ' - ' + (change.line_to - 1);
|
|
}
|
|
columnLineNumbers.push(
|
|
gettextCatalog.getString('Line') + ' ' + line + ': '
|
|
);
|
|
}
|
|
// change type column
|
|
if (change.getType(motion.getVersion(motionVersion).text) === 0) {
|
|
columnChangeType.push(gettextCatalog.getString("Replacement"));
|
|
} else if (change.getType(motion.getVersion(motionVersion).text) === 1) {
|
|
columnChangeType.push(gettextCatalog.getString("Insertion"));
|
|
} else if (change.getType(motion.getVersion(motionVersion).text) === 2) {
|
|
columnChangeType.push(gettextCatalog.getString("Deletion"));
|
|
} else if (change.getType(motion.getVersion(motionVersion).text) === 3) {
|
|
columnChangeType.push(change.other_description);
|
|
}
|
|
});
|
|
metaTableBody.push([
|
|
{
|
|
text: gettextCatalog.getString('Summary of change recommendations'),
|
|
style: ['bold', 'grey']
|
|
},
|
|
{
|
|
columns: [
|
|
{
|
|
text: columnLineNumbers.join('\n'),
|
|
width: 'auto'
|
|
},
|
|
{
|
|
text: columnChangeType.join('\n'),
|
|
width: 'auto'
|
|
}
|
|
],
|
|
columnGap: 7,
|
|
style: 'grey'
|
|
}
|
|
]);
|
|
}
|
|
|
|
if (metaTableBody.length) {
|
|
// build table
|
|
// Used placeholder for 'layout' functions whiche are
|
|
// replaced by lineWitdh/lineColor function in pfd-worker.js.
|
|
// TODO: Remove placeholder and us static values for LineWidth and LineColor
|
|
// if pdfmake has fixed this.
|
|
var metaTable = {
|
|
table: {
|
|
widths: ['35%','65%'],
|
|
body: metaTableBody,
|
|
},
|
|
margin: [0, 0, 0, 20],
|
|
layout: '{{motion-placeholder-to-insert-functions-here}}'
|
|
};
|
|
return metaTable;
|
|
} else {
|
|
return {};
|
|
}
|
|
};
|
|
|
|
// motion title
|
|
var motionTitle = function() {
|
|
if (params.include.text && !motion.isParagraphBasedAmendment()) {
|
|
return [{
|
|
text: titlePlain,
|
|
style: 'heading3'
|
|
}];
|
|
}
|
|
};
|
|
|
|
// motion preamble
|
|
var motionPreamble = function () {
|
|
return {
|
|
text: Config.translate(Config.get('motions_preamble').value),
|
|
margin: [0, 10, 0, 0]
|
|
};
|
|
};
|
|
|
|
var escapeHtml = function(text) {
|
|
return text.replace(/&/, '&').replace(/</, '<').replace(/>/, '>');
|
|
};
|
|
|
|
// motion text (with line-numbers)
|
|
var motionText = function() {
|
|
var content = [];
|
|
if (params.include.text) {
|
|
var motionTextContent = '';
|
|
if (motion.isParagraphBasedAmendment()) {
|
|
// paragraph based amendment
|
|
var diffs = motion.getAmendmentParagraphsLinesDiff();
|
|
if (diffs.length) {
|
|
content.push(motionPreamble());
|
|
_.forEach(diffs, function (diff) {
|
|
motionTextContent += diff.textPre + diff.text + diff.textPost;
|
|
});
|
|
} else {
|
|
motionTextContent += gettextCatalog.getString('No changes at the text.');
|
|
}
|
|
} else {
|
|
// lead motion or normal amendment
|
|
content.push(motionPreamble());
|
|
var titleChange = motion.getTitleChangeRecommendation();
|
|
if (params.changeRecommendationMode === 'diff' && titleChange) {
|
|
motionTextContent += '<p><strong>' + gettextCatalog.getString('New title') + ':</strong> ' +
|
|
escapeHtml(titleChange.text) + '</p>';
|
|
}
|
|
motionTextContent += motion.getTextByMode(params.changeRecommendationMode, motionVersion);
|
|
}
|
|
content.push(converter.convertHTML(motionTextContent, params.lineNumberMode));
|
|
}
|
|
return content;
|
|
};
|
|
|
|
// motion reason heading
|
|
var motionReason = function() {
|
|
if (params.include.reason) {
|
|
var reason = [];
|
|
if (motion.getReason(motionVersion)) {
|
|
reason.push({
|
|
text: gettextCatalog.getString('Reason'),
|
|
style: 'heading3',
|
|
marginTop: 25,
|
|
});
|
|
var width;
|
|
if (params.lineNumberMode == 'outside') {
|
|
width = '80%';
|
|
} else {
|
|
width = '100%';
|
|
}
|
|
reason.push({
|
|
columns: [
|
|
{
|
|
width: width,
|
|
stack: converter.convertHTML(motion.getReason(motionVersion), 'none'),
|
|
},
|
|
]
|
|
});
|
|
}
|
|
return reason;
|
|
}
|
|
};
|
|
|
|
// motion comments handling
|
|
var motionComments = function () {
|
|
if (_.keys(params.includeComments).length !== 0) {
|
|
var fields = MotionComment.getNoSpecialCommentsFields();
|
|
var comments = [];
|
|
_.forEach(params.includeComments, function (ok, id) {
|
|
if (ok && motion.comments[id]) {
|
|
var title = fields[id].name;
|
|
if (!fields[id].public) {
|
|
title += ' (' + gettextCatalog.getString('internal') + ')';
|
|
}
|
|
comments.push({
|
|
text: title,
|
|
style: 'heading3',
|
|
marginTop: 25,
|
|
});
|
|
comments.push(converter.convertHTML(motion.comments[id]));
|
|
}
|
|
});
|
|
return comments;
|
|
}
|
|
};
|
|
|
|
// Generates content as a pdfmake consumable
|
|
var getContent = function() {
|
|
var content = [
|
|
title,
|
|
subtitle,
|
|
metaTable(),
|
|
motionTitle()
|
|
];
|
|
content = content.concat(motionText());
|
|
|
|
var reason = motionReason();
|
|
if (reason) {
|
|
content.push(reason);
|
|
}
|
|
var comments = motionComments();
|
|
if (comments) {
|
|
content.push(comments);
|
|
}
|
|
return content;
|
|
};
|
|
|
|
// getters
|
|
var getTitle = function() {
|
|
return motion.getTitle(motionVersion);
|
|
};
|
|
|
|
var getIdentifier = function() {
|
|
return motion.identifier ? motion.identifier : '';
|
|
};
|
|
|
|
var getId = function() {
|
|
return motion.id;
|
|
};
|
|
|
|
var getCategory = function() {
|
|
return motion.category;
|
|
};
|
|
|
|
var getImageMap = function() {
|
|
return imageMap;
|
|
};
|
|
|
|
return $q(function (resolve, reject) {
|
|
ImageConverter.toBase64(getImageSources()).then(function (_imageMap) {
|
|
imageMap = _imageMap;
|
|
converter = PdfMakeConverter.createInstance(_imageMap);
|
|
resolve({
|
|
getContent: getContent,
|
|
getTitle: getTitle,
|
|
getIdentifier: getIdentifier,
|
|
getId: getId,
|
|
getCategory: getCategory,
|
|
getImageMap: getImageMap,
|
|
});
|
|
}, reject);
|
|
});
|
|
};
|
|
|
|
return {
|
|
createInstance: createInstance
|
|
};
|
|
}
|
|
])
|
|
|
|
.factory('MotionPartialContentProvider', [
|
|
'$q',
|
|
'gettextCatalog',
|
|
'Config',
|
|
'PDFLayout',
|
|
'PdfMakeConverter',
|
|
'ImageConverter',
|
|
'HTMLValidizer',
|
|
function ($q, gettextCatalog, Config, PDFLayout, PdfMakeConverter, ImageConverter, HTMLValidizer) {
|
|
/*
|
|
* content should be an array of content blocks. Each content is an object providing a
|
|
* heading and a text. E.g.
|
|
* [{heading: 'comment1', text: '<html in here>'}, {heading: ...}, ...]
|
|
* */
|
|
var createInstance = function (motion, content) {
|
|
|
|
var converter, imageMap = {};
|
|
|
|
// Query all image sources from the content
|
|
var getImageSources = function () {
|
|
var imageSources = [];
|
|
_.forEach(content, function (contentBlock) {
|
|
var html = HTMLValidizer.validize(contentBlock.text);
|
|
imageSources = imageSources.concat(_.map($(html).find('img'), function(element) {
|
|
return element.getAttribute('src');
|
|
}));
|
|
});
|
|
return imageSources;
|
|
};
|
|
|
|
// title
|
|
var identifier = motion.identifier ? ' ' + motion.identifier : '';
|
|
var title = PDFLayout.createTitle(
|
|
gettextCatalog.getString('Motion') + identifier + ': ' + motion.getTitle()
|
|
);
|
|
|
|
// subtitle and sequential number
|
|
var subtitleLines = [];
|
|
if (motion.parent_id) {
|
|
var parentMotion = Motion.get(motion.parent_id);
|
|
subtitleLines.push(
|
|
gettextCatalog.getString('Amendment to motion') + ': ' +
|
|
(parentMotion.identifier ? parentMotion.identifier : parentMotion.getTitle())
|
|
);
|
|
}
|
|
if (Config.get('motions_export_sequential_number').value) {
|
|
subtitleLines.push(gettextCatalog.getString('Sequential number') + ': ' + motion.id);
|
|
}
|
|
var subtitle = PDFLayout.createSubtitle(subtitleLines);
|
|
|
|
// meta data table
|
|
var metaTable = function() {
|
|
var metaTableBody = [];
|
|
|
|
// submitters
|
|
var submitters = _.map(motion.submitters, function (submitter) {
|
|
return submitter.user.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.prefix + ' - ' + motion.category.name,
|
|
style: 'grey'
|
|
}
|
|
]);
|
|
}
|
|
|
|
// build table
|
|
// Used placeholder for 'layout' functions whiche are
|
|
// replaced by lineWitdh/lineColor function in pfd-worker.js.
|
|
// TODO: Remove placeholder and us static values for LineWidth and LineColor
|
|
// if pdfmake has fixed this.
|
|
var metaTableJsonString = {
|
|
table: {
|
|
widths: ['30%','70%'],
|
|
body: metaTableBody,
|
|
},
|
|
margin: [0, 0, 0, 20],
|
|
layout: '{{motion-placeholder-to-insert-functions-here}}'
|
|
};
|
|
return metaTableJsonString;
|
|
};
|
|
|
|
var getContentBlockData = function (block) {
|
|
var data = [];
|
|
data.push({
|
|
text: block.heading,
|
|
style: 'heading3',
|
|
marginTop: 25,
|
|
});
|
|
data.push(converter.convertHTML(block.text));
|
|
return data;
|
|
};
|
|
|
|
// Generates content as a pdfmake consumable
|
|
var getContent = function() {
|
|
var pdfContent = [
|
|
title,
|
|
subtitle,
|
|
metaTable(),
|
|
];
|
|
_.forEach(content, function (contentBlock) {
|
|
pdfContent.push(getContentBlockData(contentBlock));
|
|
});
|
|
return pdfContent;
|
|
};
|
|
|
|
var getImageMap = function () {
|
|
return imageMap;
|
|
};
|
|
|
|
return $q(function (resolve, reject) {
|
|
ImageConverter.toBase64(getImageSources()).then(function (_imageMap) {
|
|
imageMap = _imageMap;
|
|
converter = PdfMakeConverter.createInstance(_imageMap);
|
|
resolve({
|
|
getContent: getContent,
|
|
getImageMap: getImageMap,
|
|
});
|
|
}, reject);
|
|
});
|
|
};
|
|
|
|
return {
|
|
createInstance: createInstance
|
|
};
|
|
}
|
|
])
|
|
|
|
.factory('PollContentProvider', [
|
|
'$q',
|
|
'PDFLayout',
|
|
'gettextCatalog',
|
|
'Config',
|
|
'User',
|
|
'ImageConverter',
|
|
function($q, PDFLayout, gettextCatalog, Config, User, ImageConverter) {
|
|
/**
|
|
* Generates a content provider for polls
|
|
* @constructor
|
|
* @param {string} title - title of poll
|
|
* @param {string} id - if of poll
|
|
*/
|
|
var createInstance = function(title, id) {
|
|
|
|
var logoBallotPaperUrl = Config.get('logo_pdf_ballot_paper').value.path;
|
|
var imageMap = {};
|
|
|
|
// PDF header
|
|
var header = function() {
|
|
var columns = [];
|
|
|
|
var text = Config.get('general_event_name').value;
|
|
columns.push({
|
|
text: text,
|
|
fontSize: 8,
|
|
alignment: 'left',
|
|
width: '60%'
|
|
});
|
|
|
|
// logo
|
|
if (logoBallotPaperUrl) {
|
|
columns.push({
|
|
image: logoBallotPaperUrl,
|
|
fit: [90,25],
|
|
alignment: 'right',
|
|
width: '40%'
|
|
});
|
|
}
|
|
return {
|
|
color: '#555',
|
|
fontSize: 10,
|
|
margin: [30, 10, 10, -10], // [left, top, right, bottom]
|
|
columns: columns,
|
|
columnGap: 5
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Returns a single section on the ballot paper
|
|
* @function
|
|
*/
|
|
var createSection = function() {
|
|
var sheetend = 40;
|
|
return {
|
|
stack: [
|
|
header(),
|
|
{
|
|
text: gettextCatalog.getString('Motion') + ' ' + id,
|
|
style: 'title',
|
|
},
|
|
{
|
|
text: title,
|
|
style: 'description'
|
|
},
|
|
PDFLayout.createBallotEntry(gettextCatalog.getString('Yes')),
|
|
PDFLayout.createBallotEntry(gettextCatalog.getString('No')),
|
|
PDFLayout.createBallotEntry(gettextCatalog.getString('Abstain')),
|
|
],
|
|
margin: [0, 0, 0, sheetend],
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Returns Content for single motion
|
|
* @function
|
|
* @param {string} id - if of poll
|
|
*/
|
|
var getContent = function() {
|
|
var content = [];
|
|
var amount;
|
|
var amount_method = Config.get('motions_pdf_ballot_papers_selection').value;
|
|
switch (amount_method) {
|
|
case 'NUMBER_OF_ALL_PARTICIPANTS':
|
|
amount = User.getAll().length;
|
|
break;
|
|
case 'NUMBER_OF_DELEGATES':
|
|
//TODO: assumption that DELEGATES is always group id 2. This may not be true
|
|
var group_id = 2;
|
|
amount = User.filter({where: {'groups_id': {contains:group_id} }}).length;
|
|
break;
|
|
case 'CUSTOM_NUMBER':
|
|
amount = Config.get('motions_pdf_ballot_papers_number').value;
|
|
break;
|
|
default:
|
|
// should not happen.
|
|
amount = 0;
|
|
}
|
|
var fullpages = Math.floor(amount / 8);
|
|
|
|
for (var i=0; i < fullpages; i++) {
|
|
content.push({
|
|
table: {
|
|
headerRows: 1,
|
|
widths: ['*', '*'],
|
|
body: [
|
|
[createSection(), createSection()],
|
|
[createSection(), createSection()],
|
|
[createSection(), createSection()],
|
|
[createSection(), createSection()]
|
|
],
|
|
pageBreak: 'after'
|
|
},
|
|
layout: PDFLayout.getBallotLayoutLines(),
|
|
rowsperpage: 4
|
|
});
|
|
}
|
|
amount = amount - (fullpages * 8);
|
|
if (amount > 0) {
|
|
var partialpagebody = [];
|
|
while (amount > 1) {
|
|
partialpagebody.push([createSection(), createSection()]);
|
|
amount -=2;
|
|
}
|
|
if (amount == 1) {
|
|
partialpagebody.push([createSection(), '']);
|
|
}
|
|
content.push({
|
|
table: {
|
|
headerRows: 1,
|
|
widths: ['50%', '50%'],
|
|
body: partialpagebody
|
|
},
|
|
layout: PDFLayout.getBallotLayoutLines(),
|
|
rowsperpage: 4
|
|
});
|
|
}
|
|
return content;
|
|
};
|
|
|
|
var getImageMap = function () {
|
|
return imageMap;
|
|
};
|
|
|
|
return $q(function (resolve, reject) {
|
|
var imageSources = [
|
|
logoBallotPaperUrl,
|
|
];
|
|
ImageConverter.toBase64(imageSources).then(function (_imageMap) {
|
|
imageMap = _imageMap;
|
|
resolve({
|
|
getContent: getContent,
|
|
getImageMap: getImageMap,
|
|
});
|
|
}, reject);
|
|
});
|
|
};
|
|
return {
|
|
createInstance: createInstance
|
|
};
|
|
}
|
|
])
|
|
|
|
.factory('MotionCatalogContentProvider', [
|
|
'gettextCatalog',
|
|
'PDFLayout',
|
|
'Category',
|
|
'Config',
|
|
function(gettextCatalog, PDFLayout, Category, Config) {
|
|
/**
|
|
* Constructor
|
|
* @function
|
|
* @param {object} allMotions - A sorted array of all motions to parse
|
|
* @param {string} sorting - The way the catalog has been sorted. Necessary for ToC
|
|
*/
|
|
var createInstance = function(allMotions, sorting) {
|
|
|
|
var title = PDFLayout.createTitle(
|
|
Config.translate(Config.get('motions_export_title').value)
|
|
);
|
|
|
|
var createPreamble = function() {
|
|
var preambleText = Config.get('motions_export_preamble').value;
|
|
if (preambleText) {
|
|
return {
|
|
text: preambleText,
|
|
style: "preamble"
|
|
};
|
|
} else {
|
|
return "";
|
|
}
|
|
};
|
|
|
|
var createTOContent = function() {
|
|
var toc = [];
|
|
var exportCategory = (sorting === 'identifier' || sorting === 'category.prefix');
|
|
var uniqueCategories = getUniqueCategories();
|
|
var tocTitle = {
|
|
text: gettextCatalog.getString('Table of contents'),
|
|
style: 'heading2'
|
|
};
|
|
|
|
// all motions need a page ID. We use the motion identifier for that
|
|
_.forEach(allMotions, function (motion) {
|
|
motion.getContent()[0].id = ''+motion.getId();
|
|
});
|
|
|
|
if (exportCategory && uniqueCategories) {
|
|
// own table per category
|
|
var catTocBody = [];
|
|
_.forEach(uniqueCategories, function (category) {
|
|
// push the name of the category
|
|
// make a table for correct alignment
|
|
catTocBody.push({
|
|
table: {
|
|
body: [
|
|
[
|
|
{
|
|
text: category.prefix + ' - ' + category.name,
|
|
style: 'tocCategoryTitle'
|
|
}
|
|
],
|
|
]
|
|
},
|
|
layout: 'noBorders',
|
|
});
|
|
|
|
var tocBody = [];
|
|
_.forEach(allMotions, function (motion) {
|
|
if (motion.getCategory() && category.name === motion.getCategory().name) {
|
|
tocBody.push(tocLine(motion, 'tocCategoryEntry'));
|
|
}
|
|
});
|
|
catTocBody.push(tocTable(tocBody));
|
|
});
|
|
|
|
//handle thouse without category
|
|
var uncatTocBody = [];
|
|
_.forEach(allMotions, function (motion) {
|
|
if (!motion.getCategory()) {
|
|
uncatTocBody.push(tocLine(motion, 'tocEntry'));
|
|
}
|
|
});
|
|
|
|
// only push this array if there is at least one entry
|
|
if (uncatTocBody.length > 0) {
|
|
catTocBody.push(tocTable(uncatTocBody));
|
|
}
|
|
|
|
toc.push(catTocBody);
|
|
} else {
|
|
// all categories in the same table
|
|
var tocBody = [];
|
|
_.forEach(allMotions, function (motion) {
|
|
tocBody.push(tocLine(motion, 'tocEntry'));
|
|
});
|
|
toc.push(tocTable(tocBody));
|
|
}
|
|
|
|
return [
|
|
tocTitle,
|
|
toc,
|
|
PDFLayout.addPageBreak()
|
|
];
|
|
};
|
|
|
|
// creates a new table of contents table body
|
|
var tocTable = function (tocBody) {
|
|
return {
|
|
table: {
|
|
widths: ['auto', '*', 'auto'],
|
|
body: tocBody
|
|
},
|
|
layout: 'noBorders',
|
|
style: 'tocCategorySection'
|
|
};
|
|
};
|
|
|
|
// generates a line in the toc as list-object
|
|
var tocLine = function (motion, style) {
|
|
var firstColumn = "";
|
|
if (motion.getIdentifier()) {
|
|
firstColumn = motion.getIdentifier();
|
|
}
|
|
return [
|
|
{
|
|
text: firstColumn,
|
|
style: style
|
|
},
|
|
{
|
|
text: motion.getTitle(),
|
|
style: 'tocEntry'
|
|
},
|
|
{
|
|
pageReference: ''+motion.getId(),
|
|
style: 'tocEntry',
|
|
alignment: 'right'
|
|
},
|
|
];
|
|
};
|
|
|
|
// returns a list of unique category names
|
|
// necessary to create a ToC with categories
|
|
// if a motions without category is found,
|
|
// a corresponding entry should be added aswell
|
|
var getUniqueCategories = function() {
|
|
var categories = [];
|
|
_.forEach(allMotions, function (motion) {
|
|
if (motion.getCategory()) {
|
|
categories.push(
|
|
{
|
|
name: motion.getCategory().name,
|
|
prefix: motion.getCategory().prefix
|
|
}
|
|
);
|
|
}
|
|
});
|
|
return _.uniqBy(categories, 'name');
|
|
};
|
|
|
|
// returns the pure content of the motion, parseable by pdfmake
|
|
var getContent = function() {
|
|
var motionContent = [];
|
|
_.forEach(allMotions, function(motion, key) {
|
|
motionContent.push(motion.getContent());
|
|
if (key < allMotions.length - 1) {
|
|
motionContent.push(PDFLayout.addPageBreak());
|
|
}
|
|
});
|
|
var content = [];
|
|
// print extra data (title, preamble, categories, toc) only for more than 1 motion
|
|
if (allMotions.length > 1) {
|
|
content.push(
|
|
title,
|
|
createPreamble(),
|
|
createTOContent()
|
|
);
|
|
}
|
|
content.push(motionContent);
|
|
return content;
|
|
};
|
|
|
|
var getImageMap = function () {
|
|
var imageMap = {};
|
|
_.forEach(allMotions, function (motion) {
|
|
_.forEach(motion.getImageMap(), function (data, path) {
|
|
if (!imageMap[path]) {
|
|
imageMap[path] = data;
|
|
}
|
|
});
|
|
});
|
|
return imageMap;
|
|
};
|
|
|
|
return {
|
|
getContent: getContent,
|
|
getImageMap: getImageMap,
|
|
};
|
|
};
|
|
|
|
return {
|
|
createInstance: createInstance
|
|
};
|
|
}
|
|
])
|
|
|
|
.factory('AmendmentContentProvider', [
|
|
'$q',
|
|
'ImageConverter',
|
|
'PdfMakeConverter',
|
|
'HTMLValidizer',
|
|
'PDFLayout',
|
|
'Config',
|
|
'gettextCatalog',
|
|
function ($q, ImageConverter, PdfMakeConverter, HTMLValidizer, PDFLayout, Config, gettextCatalog) {
|
|
var createInstance = function (motions) {
|
|
motions = _.filter(motions, function (motion) {
|
|
return motion.parent_id;
|
|
});
|
|
|
|
var converter, imageMap = {};
|
|
|
|
// Query all image sources from motion text and reason
|
|
var getImageSources = function () {
|
|
var sources = [];
|
|
_.forEach(motions, function (motion) {
|
|
var text = motion.getText();
|
|
var reason = motion.getReason();
|
|
var content = HTMLValidizer.validize(text) + HTMLValidizer.validize(motion.getReason());
|
|
_.forEach($(content).find('img'), function (element) {
|
|
sources.push(element.getAttribute('src'));
|
|
});
|
|
});
|
|
return _.uniq(sources);
|
|
};
|
|
|
|
var createBundleContent = function (bundle) {
|
|
return _.flatten(_.map(bundle, function (motion) {
|
|
var content = [];
|
|
|
|
// get diffs and title of the changed motions
|
|
var motionText;
|
|
var title = motion.identifier ? gettextCatalog.getString('Motion') + ' ' + motion.identifier : motion.getTitle();
|
|
if (motion.isParagraphBasedAmendment()) {
|
|
// get changed parts
|
|
var paragraphs = motion.getAmendmentParagraphsLinesDiff();
|
|
if (paragraphs.length) {
|
|
// Put the changed lines into the info column
|
|
var p = paragraphs[0];
|
|
title += ' (' + gettextCatalog.getString('Line') + ' ';
|
|
if (p.diffLineTo === p.diffLineFrom + 1) {
|
|
title += p.diffLineFrom;
|
|
} else {
|
|
title += p.diffLineFrom + '-' + p.diffLineTo;
|
|
}
|
|
title += ')';
|
|
|
|
// get the diff
|
|
motionText = p.text;
|
|
} else {
|
|
motionText = gettextCatalog.getString('No changes at the text.');
|
|
}
|
|
} else { // 'normal' amendment
|
|
motionText = motion.getText();
|
|
}
|
|
content.push({
|
|
text: title,
|
|
style: 'heading3',
|
|
marginTop: 15,
|
|
});
|
|
|
|
// submitters
|
|
var submitters = _.map(motion.submitters, function (submitter) {
|
|
return submitter.user.get_full_name();
|
|
}).join(', ');
|
|
content.push({
|
|
text: gettextCatalog.getString('Submitters') + ': ' + submitters,
|
|
});
|
|
|
|
// state
|
|
content.push({
|
|
text: gettextCatalog.getString('State') + ': ' + motion.getStateName(),
|
|
});
|
|
|
|
// recommendation
|
|
var recommendations_by = Config.get('motions_recommendations_by').value;
|
|
var recommendation = motion.getRecommendationName();
|
|
if (recommendations_by && recommendation) {
|
|
content.push({
|
|
text: recommendations_by + ': ' + recommendation,
|
|
});
|
|
}
|
|
|
|
return _.concat(content, converter.convertHTML(motionText, 'outside'));
|
|
}));
|
|
};
|
|
|
|
var getBundleContent = function (bundle) {
|
|
var leadMotion = bundle[0].getParentMotion();
|
|
// title
|
|
var title = leadMotion.identifier ? ' ' + leadMotion.identifier : '';
|
|
title += ': ' + leadMotion.getTitle();
|
|
title = PDFLayout.createTitle(gettextCatalog.getString('Amendments to motion') + title);
|
|
|
|
var content = [title],
|
|
foundAmendments = [];
|
|
|
|
var headings = leadMotion.getTextHeadings().map(function(heading) {
|
|
heading.amendments = [];
|
|
return heading;
|
|
});
|
|
bundle.forEach(function(amendment) {
|
|
var headingIdx = null;
|
|
var changes = amendment.getAmendmentParagraphsByMode('diff');
|
|
if (changes.length === 0) {
|
|
return;
|
|
}
|
|
var amendmentLineNumber = changes[0].lineFrom;
|
|
for (var i = 0; i < headings.length; i++) {
|
|
if (headings[i].lineNumber <= amendmentLineNumber) {
|
|
headingIdx = i;
|
|
}
|
|
}
|
|
if (headingIdx !== null) {
|
|
headings[headingIdx].amendments.push(amendment);
|
|
foundAmendments.push(amendment.id);
|
|
}
|
|
});
|
|
|
|
headings.forEach(function(heading) {
|
|
if (heading.amendments.length === 0) {
|
|
return;
|
|
}
|
|
content.push({
|
|
text: heading.text,
|
|
style: "heading2",
|
|
marginTop: 25,
|
|
});
|
|
content = _.concat(content, createBundleContent(heading.amendments));
|
|
});
|
|
|
|
// If there was an amendment that did not have a heading, we append it at the bottom
|
|
var missedAmendments = [];
|
|
bundle.forEach(function(amendment) {
|
|
if (foundAmendments.indexOf(amendment.id) === -1) {
|
|
missedAmendments.push(amendment);
|
|
}
|
|
});
|
|
if (missedAmendments.length > 0) {
|
|
content = _.concat(content, createBundleContent(missedAmendments));
|
|
}
|
|
|
|
return content;
|
|
};
|
|
|
|
// Generates content as a pdfmake consumable
|
|
var getContent = function() {
|
|
if (motions.length === 0) {
|
|
return [];
|
|
}
|
|
|
|
// Creates bundles of motions. All motions with the same parent are bundled together
|
|
// respecting the order, in which they are sorted.
|
|
// motionBundles is an array containing Arrays of motions with the same parent.
|
|
var parentId = motions[0].parent_id;
|
|
var motionBundles = [];
|
|
var currentBundle = [];
|
|
_.forEach(motions, function (motion) {
|
|
if (motion.parent_id === parentId) {
|
|
currentBundle.push(motion);
|
|
} else {
|
|
motionBundles.push(currentBundle);
|
|
currentBundle = [motion];
|
|
parentId = motion.parent_id;
|
|
}
|
|
});
|
|
motionBundles.push(currentBundle);
|
|
|
|
// Make the amendment table for each motion bundle.
|
|
return _.map(motionBundles, function (bundle, index) {
|
|
var content = getBundleContent(bundle);
|
|
if (index < motionBundles.length - 1) {
|
|
content.push(PDFLayout.addPageBreak());
|
|
}
|
|
return content;
|
|
});
|
|
};
|
|
|
|
var getImageMap = function() {
|
|
return imageMap;
|
|
};
|
|
|
|
return $q(function (resolve) {
|
|
ImageConverter.toBase64(getImageSources()).then(function (_imageMap) {
|
|
imageMap = _imageMap;
|
|
converter = PdfMakeConverter.createInstance(_imageMap);
|
|
resolve({
|
|
getContent: getContent,
|
|
getImageMap: getImageMap,
|
|
});
|
|
});
|
|
});
|
|
};
|
|
|
|
return {
|
|
createInstance: createInstance,
|
|
};
|
|
}
|
|
])
|
|
|
|
.factory('MotionPdfExport', [
|
|
'$http',
|
|
'$q',
|
|
'operator',
|
|
'Config',
|
|
'gettextCatalog',
|
|
'MotionChangeRecommendation',
|
|
'HTMLValidizer',
|
|
'PdfMakeConverter',
|
|
'MotionContentProvider',
|
|
'MotionCatalogContentProvider',
|
|
'PdfMakeDocumentProvider',
|
|
'PollContentProvider',
|
|
'PdfMakeBallotPaperProvider',
|
|
'MotionPartialContentProvider',
|
|
'AmendmentContentProvider',
|
|
'PdfCreate',
|
|
'PDFLayout',
|
|
'PersonalNoteManager',
|
|
'MotionComment',
|
|
'Messaging',
|
|
'FileSaver',
|
|
function ($http, $q, operator, Config, gettextCatalog, MotionChangeRecommendation, HTMLValidizer,
|
|
PdfMakeConverter, MotionContentProvider, MotionCatalogContentProvider, PdfMakeDocumentProvider,
|
|
PollContentProvider, PdfMakeBallotPaperProvider, MotionPartialContentProvider, AmendmentContentProvider,
|
|
PdfCreate, PDFLayout, PersonalNoteManager, MotionComment, Messaging, FileSaver) {
|
|
return {
|
|
getDocumentProvider: function (motions, params, singleMotion) {
|
|
params = _.clone(params || {}); // Clone this to avoid sideeffects.
|
|
|
|
if (singleMotion) {
|
|
_.defaults(params, {
|
|
version: motions.active_version,
|
|
});
|
|
motions = [motions];
|
|
}
|
|
|
|
//save the arrays of all motions to an array
|
|
angular.forEach(motions, function (motion) {
|
|
if (singleMotion) {
|
|
motion.changeRecommendations = MotionChangeRecommendation.filter({
|
|
'where': {'motion_version_id': {'==': params.version}}
|
|
});
|
|
} else {
|
|
motion.changeRecommendations = MotionChangeRecommendation.filter({
|
|
'where': {'motion_version_id': {'==': motion.active_version}}
|
|
});
|
|
}
|
|
});
|
|
|
|
var motionContentProviderArray = [];
|
|
var motionContentProviderPromises = _.map(motions, function (motion) {
|
|
var version = (singleMotion ? params.version : motion.active_version);
|
|
return $q(function (resolve, reject) {
|
|
MotionContentProvider.createInstance(
|
|
motion, version, params
|
|
).then(function (contentProvider) {
|
|
motionContentProviderArray.push(contentProvider);
|
|
resolve();
|
|
}, reject);
|
|
});
|
|
});
|
|
|
|
return $q(function (resolve, reject) {
|
|
$q.all(motionContentProviderPromises).then(function() {
|
|
var documentProviderPromise;
|
|
if (singleMotion) {
|
|
documentProviderPromise = PdfMakeDocumentProvider.createInstance(motionContentProviderArray[0]);
|
|
} else {
|
|
var motionCatalogContentProvider = MotionCatalogContentProvider.createInstance(motionContentProviderArray, params.column);
|
|
documentProviderPromise = PdfMakeDocumentProvider.createInstance(motionCatalogContentProvider);
|
|
}
|
|
documentProviderPromise.then(function (documentProvider) {
|
|
resolve(documentProvider);
|
|
}, reject);
|
|
}, reject);
|
|
});
|
|
},
|
|
export: function (motions, params, singleMotion) {
|
|
params = params || {};
|
|
_.defaults(params, {
|
|
filename: gettextCatalog.getString('motions') + '.pdf',
|
|
});
|
|
this.getDocumentProvider(motions, params, singleMotion).then(
|
|
function (documentProvider) {
|
|
PdfCreate.download(documentProvider, params.filename);
|
|
}, function (error) {
|
|
Messaging.addMessage(error.msg, 'error');
|
|
}
|
|
);
|
|
},
|
|
exportZip: function (motions, params) {
|
|
var messageId = Messaging.addMessage('<i class="fa fa-spinner fa-pulse fa-lg spacer-right"></i>' +
|
|
gettextCatalog.getString('Generating PDFs and ZIP archive') + ' ...', 'info');
|
|
var zipFilename = params.filename || gettextCatalog.getString('motions') + '.zip';
|
|
params.filename = void 0; // clear this, so we do not override the default filenames for each pdf.
|
|
|
|
var self = this;
|
|
var usedFilenames = [];
|
|
var docMap = {};
|
|
var docPromises = _.map(motions, function (motion) {
|
|
var identifier = motion.identifier ? '-' + motion.identifier : '';
|
|
var filename = gettextCatalog.getString('Motion') + identifier;
|
|
|
|
// If the filename is already in use, try to append a number to it (like '(2)')
|
|
if (_.includes(usedFilenames, filename)) {
|
|
var i = 1;
|
|
var filenameWithNumber = filename;
|
|
while(_.includes(usedFilenames, filenameWithNumber)) {
|
|
filenameWithNumber = filename + ' (' + i + ')';
|
|
i++;
|
|
}
|
|
filename = filenameWithNumber;
|
|
}
|
|
usedFilenames.push(filename);
|
|
filename += '.pdf';
|
|
|
|
return $q(function (resolve, reject) {
|
|
// get documentProvider for every motion.
|
|
self.getDocumentProvider(motion, params, true).then(function (documentProvider) {
|
|
docMap[filename] = documentProvider;
|
|
resolve();
|
|
}, reject);
|
|
});
|
|
});
|
|
$q.all(docPromises).then(function () {
|
|
PdfCreate.getBase64FromMultipleDocuments(docMap).then(function (pdfMap) {
|
|
var zip = new JSZip();
|
|
_.forEach(pdfMap, function (data, filename) {
|
|
zip.file(filename, data, {base64: true});
|
|
});
|
|
Messaging.createOrEditMessage(messageId, '<i class="fa fa-check fa-lg spacer-right"></i>' +
|
|
gettextCatalog.getString('ZIP successfully generated.'), 'success', {timeout: 3000});
|
|
zip.generateAsync({type: 'blob'}).then(function (content) {
|
|
FileSaver.saveAs(content, zipFilename);
|
|
});
|
|
}, function (error) {
|
|
Messaging.createOrEditMessage(messageId, '<i class="fa fa-exclamation-triangle fa-lg ' +
|
|
'spacer-right"></i>' + gettextCatalog.getString('Error while generating ZIP file') +
|
|
': <code>' + error + '</code>', 'error');
|
|
});
|
|
}, function (error) {
|
|
Messaging.createOrEditMessage(messageId, error.msg, 'error');
|
|
});
|
|
},
|
|
createPollPdf: function (motion, version) {
|
|
var id = motion.identifier.replace(' ', '');
|
|
var title = motion.getTitle(version);
|
|
var filename = gettextCatalog.getString('Motion') + '-' + id + '-' + gettextCatalog.getString('ballot-paper') + '.pdf';
|
|
PollContentProvider.createInstance(title, id).then(function (pollContentProvider) {
|
|
var documentProvider = PdfMakeBallotPaperProvider.createInstance(pollContentProvider);
|
|
PdfCreate.download(documentProvider, filename);
|
|
}, function (error) {
|
|
Messaging.addMessage(error.msg, 'error');
|
|
});
|
|
},
|
|
exportPersonalNote: function (motion, filename) {
|
|
var personalNote = PersonalNoteManager.getNote(motion);
|
|
var content = [{
|
|
heading: gettextCatalog.getString('Personal note'),
|
|
text: personalNote ? personalNote.note : '',
|
|
}];
|
|
MotionPartialContentProvider.createInstance(motion, content).then(function (contentProvider) {
|
|
PdfMakeDocumentProvider.createInstance(contentProvider).then(function (documentProvider) {
|
|
PdfCreate.download(documentProvider, filename);
|
|
}, function (error) {
|
|
Messaging.addMessage(error.msg, 'error');
|
|
});
|
|
}, function (error) {
|
|
Messaging.addMessage(error.msg, 'error');
|
|
});
|
|
},
|
|
exportComment: function (motion, commentId, filename) {
|
|
var field = MotionComment.getNoSpecialCommentsFields()[commentId];
|
|
if (field && motion.comments[commentId]) {
|
|
var title = field.name;
|
|
if (!field.public) {
|
|
title += ' (' + gettextCatalog.getString('internal') + ')';
|
|
}
|
|
var content = [{
|
|
heading: title,
|
|
text: motion.comments[commentId],
|
|
}];
|
|
MotionPartialContentProvider.createInstance(motion, content).then(function (contentProvider) {
|
|
PdfMakeDocumentProvider.createInstance(contentProvider).then(function (documentProvider) {
|
|
PdfCreate.download(documentProvider, filename);
|
|
}, function (error) {
|
|
Messaging.addMessage(error.msg, 'error');
|
|
});
|
|
}, function (error) {
|
|
Messaging.addMessage(error.msg, 'error');
|
|
});
|
|
}
|
|
},
|
|
exportAmendments: function (motions, filename) {
|
|
AmendmentContentProvider.createInstance(motions).then(function (contentProvider) {
|
|
PdfMakeDocumentProvider.createInstance(contentProvider).then(function (documentProvider) {
|
|
PdfCreate.download(documentProvider, filename);
|
|
});
|
|
});
|
|
},
|
|
};
|
|
}
|
|
]);
|
|
|
|
}());
|