Merge pull request #4766 from GabrielInTheWorld/pdf-make-enhancement
Implementation of exporting submitters and recommendation
This commit is contained in:
commit
e2e5fe07d0
@ -151,9 +151,11 @@ _('Number of all delegates');
|
||||
_('Number of all participants');
|
||||
_('Use the following custom number');
|
||||
_('Custom number of ballot papers');
|
||||
// subgroup export
|
||||
_('Title for PDF and DOCX documents (all motions)');
|
||||
_('Preamble text for PDF and DOCX documents (all motions)');
|
||||
// subgroup PDF export
|
||||
_('PDF export');
|
||||
_('Title for PDF documents of motions');
|
||||
_('Preamble text for PDF documents of motions');
|
||||
_('Show submitters and recommendation in table of contents');
|
||||
_('Sort categories by');
|
||||
_('Sort motions by');
|
||||
_('Include the sequential number in PDF and DOCX');
|
||||
|
@ -13,9 +13,20 @@ import { HttpService } from '../core-services/http.service';
|
||||
*/
|
||||
export enum StyleType {
|
||||
DEFAULT = 'tocEntry',
|
||||
SUBTITLE = 'subtitle',
|
||||
SUB_ENTRY = 'tocSubEntry',
|
||||
CATEGORY_SECTION = 'tocCategorySection'
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumeration to describe the type of borders.
|
||||
*/
|
||||
export enum BorderType {
|
||||
DEFAULT = 'noBorders',
|
||||
LIGHT_HORIZONTAL_LINES = 'lightHorizontalLines',
|
||||
HEADER_ONLY = 'headerLineOnly'
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom PDF error class to handle errors in a safer way
|
||||
*/
|
||||
@ -445,9 +456,10 @@ export class PdfDocumentService {
|
||||
* @returns an object that contains all pdf styles
|
||||
*/
|
||||
private getStandardPaperStyles(): object {
|
||||
const pageSize = this.configService.instant('general_export_pdf_pagesize');
|
||||
return {
|
||||
title: {
|
||||
fontSize: 18,
|
||||
fontSize: pageSize === 'A5' ? 14 : 16,
|
||||
margin: [0, 0, 0, 20],
|
||||
bold: true
|
||||
},
|
||||
@ -475,12 +487,12 @@ export class PdfDocumentService {
|
||||
fontSize: 8
|
||||
},
|
||||
heading2: {
|
||||
fontSize: 14,
|
||||
fontSize: pageSize === 'A5' ? 12 : 14,
|
||||
margin: [0, 0, 0, 10],
|
||||
bold: true
|
||||
},
|
||||
heading3: {
|
||||
fontSize: 12,
|
||||
fontSize: pageSize === 'A5' ? 10 : 12,
|
||||
margin: [0, 10, 0, 0],
|
||||
bold: true
|
||||
},
|
||||
@ -498,17 +510,25 @@ export class PdfDocumentService {
|
||||
margin: [15, 5]
|
||||
},
|
||||
tocEntry: {
|
||||
fontSize: 12,
|
||||
fontSize: pageSize === 'A5' ? 10 : 11,
|
||||
margin: [0, 0, 0, 0],
|
||||
bold: false
|
||||
},
|
||||
tocHeaderRow: {
|
||||
fontSize: 8,
|
||||
italics: true
|
||||
},
|
||||
tocSubEntry: {
|
||||
fontSize: pageSize === 'A5' ? 9 : 10,
|
||||
color: '#404040'
|
||||
},
|
||||
tocCategoryEntry: {
|
||||
fontSize: 12,
|
||||
fontSize: pageSize === 'A5' ? 10 : 11,
|
||||
margin: [10, 0, 0, 0],
|
||||
bold: false
|
||||
},
|
||||
tocCategoryTitle: {
|
||||
fontSize: 12,
|
||||
fontSize: pageSize === 'A5' ? 10 : 11,
|
||||
margin: [0, 0, 0, 4],
|
||||
bold: true
|
||||
},
|
||||
@ -610,6 +630,7 @@ export class PdfDocumentService {
|
||||
*/
|
||||
public createTitle(configVariable: string): object {
|
||||
const titleText = this.translate.instant(this.configService.instant<string>(configVariable));
|
||||
|
||||
return {
|
||||
text: titleText,
|
||||
style: 'title'
|
||||
@ -647,13 +668,21 @@ export class PdfDocumentService {
|
||||
* @param tocBody the body of the table
|
||||
* @returns The table of contents as doc definition
|
||||
*/
|
||||
public createTocTableDef(tocBody: object, style: StyleType = StyleType.DEFAULT): object {
|
||||
public createTocTableDef(
|
||||
tocBody: object[],
|
||||
style: StyleType = StyleType.DEFAULT,
|
||||
borderStyle: BorderType = BorderType.DEFAULT,
|
||||
...header: object[]
|
||||
): object {
|
||||
return {
|
||||
table: {
|
||||
headerRows: header[0] ? header.length : 0,
|
||||
keepWithHeaderRows: header[0] ? header.length : 0,
|
||||
dontBreakRows: true,
|
||||
widths: ['auto', '*', 'auto'],
|
||||
body: tocBody
|
||||
body: header[0] ? [...header, ...tocBody] : tocBody
|
||||
},
|
||||
layout: 'noBorders',
|
||||
layout: borderStyle,
|
||||
style: style
|
||||
};
|
||||
}
|
||||
@ -672,15 +701,16 @@ export class PdfDocumentService {
|
||||
identifier: string,
|
||||
title: string,
|
||||
pageReference: string,
|
||||
style: StyleType = StyleType.DEFAULT
|
||||
): Object {
|
||||
style: StyleType = StyleType.DEFAULT,
|
||||
...subTitle: object[]
|
||||
): Array<Object> {
|
||||
return [
|
||||
{
|
||||
text: identifier,
|
||||
style: style
|
||||
},
|
||||
{
|
||||
text: title,
|
||||
text: [title, ...subTitle],
|
||||
style: 'tocEntry'
|
||||
},
|
||||
{
|
||||
@ -690,4 +720,19 @@ export class PdfDocumentService {
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to create an inline line in the toc.
|
||||
*
|
||||
* @param text The text for the line.
|
||||
* @param bold Optional boolean, if the text should be bold - defaults to `false`.
|
||||
*
|
||||
* @returns {Object} An object for `DocDefinition` for `pdf-make`.
|
||||
*/
|
||||
public createTocLineInline(text: string): Object {
|
||||
return {
|
||||
text: '\n' + text,
|
||||
style: StyleType.SUB_ENTRY
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,8 @@ import { ViewMotion, LineNumberingMode, ChangeRecoMode } from '../models/view-mo
|
||||
import { MotionPdfService, InfoToExport } from './motion-pdf.service';
|
||||
import { ConfigService } from 'app/core/ui-services/config.service';
|
||||
import { ViewCategory } from '../models/view-category';
|
||||
import { PdfError, PdfDocumentService, StyleType } from 'app/core/ui-services/pdf-document.service';
|
||||
import { PdfError, PdfDocumentService, StyleType, BorderType } from 'app/core/ui-services/pdf-document.service';
|
||||
import { MotionRepositoryService } from 'app/core/repositories/motions/motion-repository.service';
|
||||
|
||||
/**
|
||||
* Service to export a list of motions.
|
||||
@ -31,7 +32,8 @@ export class MotionPdfCatalogService {
|
||||
private translate: TranslateService,
|
||||
private configService: ConfigService,
|
||||
private motionPdfService: MotionPdfService,
|
||||
private pdfService: PdfDocumentService
|
||||
private pdfService: PdfDocumentService,
|
||||
private motionRepo: MotionRepositoryService
|
||||
) {}
|
||||
|
||||
/**
|
||||
@ -116,13 +118,15 @@ export class MotionPdfCatalogService {
|
||||
text: this.translate.instant('Table of contents'),
|
||||
style: 'heading2'
|
||||
};
|
||||
const exportSubmitterRecommendation = this.configService.instant<boolean>(
|
||||
'motions_export_submitter_recommendation'
|
||||
);
|
||||
|
||||
if (!sorting) {
|
||||
sorting = this.configService.instant<string>('motions_export_category_sorting');
|
||||
}
|
||||
const exportCategory = sorting === 'identifier' || sorting === 'prefix';
|
||||
// Initialize the header and the layout for border-style.
|
||||
const header = exportSubmitterRecommendation ? this.getTocHeaderDefinition() : undefined;
|
||||
const layout = exportSubmitterRecommendation ? BorderType.LIGHT_HORIZONTAL_LINES : BorderType.DEFAULT;
|
||||
|
||||
if (exportCategory && categories) {
|
||||
if (categories && categories.length) {
|
||||
const catTocBody = [];
|
||||
for (const category of categories) {
|
||||
// push the name of the category
|
||||
@ -138,27 +142,38 @@ export class MotionPdfCatalogService {
|
||||
]
|
||||
]
|
||||
},
|
||||
layout: 'noBorders'
|
||||
layout: exportSubmitterRecommendation ? 'lightHorizontalLines' : 'noBorders'
|
||||
});
|
||||
|
||||
const tocBody = motions
|
||||
.filter(motion => category === motion.category)
|
||||
.map(motion =>
|
||||
const tocBody = [];
|
||||
for (const motion of motions.filter(motionIn => category === motionIn.category)) {
|
||||
if (exportSubmitterRecommendation) {
|
||||
tocBody.push(this.appendSubmittersAndRecommendation(motion, StyleType.CATEGORY_SECTION));
|
||||
} else {
|
||||
tocBody.push(
|
||||
this.pdfService.createTocLine(
|
||||
`${motion.identifier}`,
|
||||
`${motion.identifier ? motion.identifier : ''}`,
|
||||
motion.title,
|
||||
`${motion.id}`,
|
||||
StyleType.CATEGORY_SECTION
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
catTocBody.push(this.pdfService.createTocTableDef(tocBody, StyleType.CATEGORY_SECTION));
|
||||
catTocBody.push(this.pdfService.createTocTableDef(tocBody, StyleType.CATEGORY_SECTION, layout, header));
|
||||
}
|
||||
|
||||
// handle those without category
|
||||
const uncatTocBody = motions
|
||||
.filter(motion => !motion.category)
|
||||
.map(motion => this.pdfService.createTocLine(`${motion.identifier}`, motion.title, `${motion.id}`));
|
||||
.map(motion =>
|
||||
this.pdfService.createTocLine(
|
||||
`${motion.identifier ? motion.identifier : ''}`,
|
||||
motion.title,
|
||||
`${motion.id}`
|
||||
)
|
||||
);
|
||||
|
||||
// only push this array if there is at least one entry
|
||||
if (uncatTocBody.length > 0) {
|
||||
@ -168,15 +183,46 @@ export class MotionPdfCatalogService {
|
||||
toc.push(catTocBody);
|
||||
} else {
|
||||
// all motions in the same table
|
||||
const tocBody = motions.map(motion =>
|
||||
this.pdfService.createTocLine(`${motion.identifier}`, motion.title, `${motion.id}`)
|
||||
const tocBody = [];
|
||||
for (const motion of motions) {
|
||||
if (exportSubmitterRecommendation) {
|
||||
tocBody.push(this.appendSubmittersAndRecommendation(motion));
|
||||
} else {
|
||||
tocBody.push(
|
||||
this.pdfService.createTocLine(
|
||||
`${motion.identifier ? motion.identifier : ''}`,
|
||||
motion.title,
|
||||
`${motion.id}`
|
||||
)
|
||||
);
|
||||
toc.push(this.pdfService.createTocTableDef(tocBody, StyleType.CATEGORY_SECTION));
|
||||
}
|
||||
}
|
||||
toc.push(this.pdfService.createTocTableDef(tocBody, StyleType.CATEGORY_SECTION, layout, header));
|
||||
}
|
||||
|
||||
return [tocTitle, toc, this.pdfService.getPageBreak()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to get the definition for the header
|
||||
* for exporting motion-list as PDF. Needed, if submitters
|
||||
* and recommendation should also be exported to the `Table of Contents`.
|
||||
*
|
||||
* @returns {object} The DocDefinition for `pdfmake.js`.
|
||||
*/
|
||||
private getTocHeaderDefinition(): object {
|
||||
return [
|
||||
{ text: this.translate.instant('Identifier'), style: 'tocHeaderRow' },
|
||||
{
|
||||
text: `${this.translate.instant('Title')} · ${this.translate.instant(
|
||||
'Submitters'
|
||||
)} · ${this.translate.instant('Recommendation')}`,
|
||||
style: 'tocHeaderRow'
|
||||
},
|
||||
{ text: this.translate.instant('Page'), style: 'tocHeaderRow', alignment: 'right' }
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the used categories from the given motion list.
|
||||
*
|
||||
@ -198,4 +244,31 @@ export class MotionPdfCatalogService {
|
||||
|
||||
return categories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates lines for the `Table of contents` containing submitters and recommendation.
|
||||
*
|
||||
* @param motion The motion containing the information
|
||||
* @param style Optional `StyleType`. Defaults to `tocEntry`.
|
||||
*
|
||||
* @returns {Array<Object>} An array containing the `DocDefinitions` for `pdf-make`.
|
||||
*/
|
||||
private appendSubmittersAndRecommendation(motion: ViewMotion, style: StyleType = StyleType.DEFAULT): Array<Object> {
|
||||
const recommendation = this.motionRepo.getExtendedRecommendationLabel(motion);
|
||||
let submitterList = '';
|
||||
for (let i = 0; i < motion.submitters.length; ++i) {
|
||||
submitterList +=
|
||||
i !== motion.submitters.length - 1
|
||||
? motion.submitters[i].getTitle() + ', '
|
||||
: motion.submitters[i].getTitle();
|
||||
}
|
||||
return this.pdfService.createTocLine(
|
||||
`${motion.identifier ? motion.identifier : ''}`,
|
||||
motion.title,
|
||||
`${motion.id}`,
|
||||
style,
|
||||
this.pdfService.createTocLineInline(submitterList),
|
||||
this.pdfService.createTocLineInline(recommendation)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -344,22 +344,32 @@ def get_config_variables():
|
||||
validators=(MinValueValidator(1),),
|
||||
)
|
||||
|
||||
# PDF and DOCX export
|
||||
# PDF export
|
||||
|
||||
yield ConfigVariable(
|
||||
name="motions_export_title",
|
||||
default_value="Motions",
|
||||
label="Title for PDF and DOCX documents (all motions)",
|
||||
label="Title for PDF document of motions",
|
||||
weight=370,
|
||||
group="Motions",
|
||||
subgroup="Export",
|
||||
subgroup="PDF export",
|
||||
)
|
||||
|
||||
yield ConfigVariable(
|
||||
name="motions_export_preamble",
|
||||
default_value="",
|
||||
label="Preamble text for PDF and DOCX documents (all motions)",
|
||||
label="Preamble text for PDF documents of motions",
|
||||
weight=375,
|
||||
group="Motions",
|
||||
subgroup="Export",
|
||||
subgroup="PDF export",
|
||||
)
|
||||
|
||||
yield ConfigVariable(
|
||||
name="motions_export_submitter_recommendation",
|
||||
default_value=False,
|
||||
label="Show submitters and recommendation in table of contents",
|
||||
input_type="boolean",
|
||||
weight=378,
|
||||
group="Motions",
|
||||
subgroup="PDF export",
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user