Merge pull request #4210 from MaximilianKrambach/agendalistpdf
agenda pdf export
This commit is contained in:
commit
d705b2a137
@ -468,6 +468,14 @@ export class PdfDocumentService {
|
||||
tableHeader: {
|
||||
bold: true,
|
||||
fillColor: 'white'
|
||||
},
|
||||
listParent: {
|
||||
fontSize: 14,
|
||||
margin: [0, 5]
|
||||
},
|
||||
listChild: {
|
||||
fontSize: 12,
|
||||
margin: [0, 5]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -110,10 +110,17 @@
|
||||
<span translate>Sort</span>
|
||||
</button>
|
||||
</div>
|
||||
<!-- csv export -->
|
||||
<button mat-menu-item (click)="csvExportItemList()">
|
||||
<mat-icon>archive</mat-icon>
|
||||
<span translate>Export as CSV</span>
|
||||
</button>
|
||||
<!-- PDF export -->
|
||||
<button mat-menu-item (click)="onDownloadPdf()">
|
||||
<mat-icon>picture_as_pdf</mat-icon>
|
||||
<span translate>Export as PDF</span>
|
||||
</button>
|
||||
<!-- Import -->
|
||||
<button mat-menu-item *osPerms="'agenda.can_manage'" routerLink="import">
|
||||
<mat-icon>save_alt</mat-icon>
|
||||
<span translate>Import</span><span> ...</span>
|
||||
|
@ -11,9 +11,11 @@ import { PromptService } from '../../../../core/services/prompt.service';
|
||||
import { ViewItem } from '../../models/view-item';
|
||||
|
||||
import { AgendaCsvExportService } from '../../services/agenda-csv-export.service';
|
||||
import { AgendaPdfService } from '../../services/agenda-pdf.service';
|
||||
import { ConfigService } from 'app/core/services/config.service';
|
||||
import { DurationService } from 'app/core/services/duration.service';
|
||||
import { ItemInfoDialogComponent } from '../item-info-dialog/item-info-dialog.component';
|
||||
import { PdfDocumentService } from 'app/core/services/pdf-document.service';
|
||||
import { ViewportService } from 'app/core/services/viewport.service';
|
||||
|
||||
/**
|
||||
@ -52,6 +54,8 @@ export class AgendaListComponent extends ListViewBaseComponent<ViewItem> impleme
|
||||
* @param durationService Converts numbers to readable duration strings
|
||||
* @param csvExport Handles the exporting into csv
|
||||
* @param filterService: service for filtering data
|
||||
* @param agendaPdfService: service for preparing a pdf of the agenda
|
||||
* @param pdfService: Service for exporting a pdf
|
||||
*/
|
||||
public constructor(
|
||||
titleService: Title,
|
||||
@ -66,7 +70,9 @@ export class AgendaListComponent extends ListViewBaseComponent<ViewItem> impleme
|
||||
public vp: ViewportService,
|
||||
public durationService: DurationService,
|
||||
private csvExport: AgendaCsvExportService,
|
||||
public filterService: AgendaFilterListService
|
||||
public filterService: AgendaFilterListService,
|
||||
private agendaPdfService: AgendaPdfService,
|
||||
private pdfService: PdfDocumentService
|
||||
) {
|
||||
super(titleService, translate, matSnackBar);
|
||||
|
||||
@ -227,4 +233,13 @@ export class AgendaListComponent extends ListViewBaseComponent<ViewItem> impleme
|
||||
public csvExportItemList(): void {
|
||||
this.csvExport.exportItemList(this.dataSource.filteredData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the export of the agenda. Currently filtered items and 'hidden'
|
||||
* items will not be exported
|
||||
*/
|
||||
public onDownloadPdf(): void {
|
||||
const filename = this.translate.instant('Agenda');
|
||||
this.pdfService.download(this.agendaPdfService.agendaListToDocDef(this.dataSource.filteredData), filename);
|
||||
}
|
||||
}
|
||||
|
@ -67,10 +67,7 @@ export class ViewItem extends BaseViewModel {
|
||||
}
|
||||
|
||||
public get verboseCsvType(): string {
|
||||
if (this.item) {
|
||||
return this.item.verboseCsvType;
|
||||
}
|
||||
return '';
|
||||
return this.item ? this.item.verboseCsvType : '';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,17 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { AgendaPdfService } from './agenda-pdf.service';
|
||||
import { E2EImportsModule } from 'e2e-imports.module';
|
||||
|
||||
describe('AgendaPdfService', () => {
|
||||
beforeEach(() =>
|
||||
TestBed.configureTestingModule({
|
||||
imports: [E2EImportsModule]
|
||||
})
|
||||
);
|
||||
|
||||
it('should be created', () => {
|
||||
const service: AgendaPdfService = TestBed.get(AgendaPdfService);
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
103
client/src/app/site/agenda/services/agenda-pdf.service.ts
Normal file
103
client/src/app/site/agenda/services/agenda-pdf.service.ts
Normal file
@ -0,0 +1,103 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
import { TreeService, OSTreeNode } from 'app/core/services/tree.service';
|
||||
import { ViewItem } from '../models/view-item';
|
||||
|
||||
/**
|
||||
* pdfMake structure for a content line in the pdf document.
|
||||
*/
|
||||
interface AgendaTreePdfEntry {
|
||||
style: string;
|
||||
columns: { width?: number; text: string }[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a list of agenda items to pdf, indenting according to a hierarchy tree.
|
||||
* Provides the public method `agendaListToDocDef(items: ViewItems[])` which should be convenient to use.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const pdfMakeCompatibleDocDef = this.AgendaPdfService.agendaListToDocDef(this.dataSource.data);
|
||||
* ```
|
||||
*/
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class AgendaPdfService {
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param translate handle translations
|
||||
* @param treeService create hierarchy between items
|
||||
*/
|
||||
public constructor(private translate: TranslateService, private treeService: TreeService) {}
|
||||
|
||||
/**
|
||||
* Creates pdfMake definitions for a agenda list pdf from the given agenda items
|
||||
*
|
||||
* @param items A list of viewItems to be included in this agenda list. Items with the property 'hidden'
|
||||
* will be ignored, all other items will be sorted by their parents and weight
|
||||
* @returns definitions ready to be opened or exported via {@link PdfDocumentService}
|
||||
*/
|
||||
public agendaListToDocDef(items: ViewItem[]): object {
|
||||
const tree: OSTreeNode<ViewItem>[] = this.treeService.makeTree(items, 'weight', 'parent_id');
|
||||
const title = {
|
||||
text: this.translate.instant('Agenda'),
|
||||
style: 'title'
|
||||
};
|
||||
const entries = this.createEntries(tree);
|
||||
return [title, entries];
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverses the given nodeTree and creates an array of entries for all items
|
||||
*
|
||||
* @param tree
|
||||
* @returns hierarchical pdfMake definitions for topic entries
|
||||
*/
|
||||
private createEntries(tree: OSTreeNode<ViewItem>[]): AgendaTreePdfEntry[] {
|
||||
const content: AgendaTreePdfEntry[] = [];
|
||||
tree.forEach(treeitem => content.push(...this.parseItem(treeitem, 0)));
|
||||
return content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an entry line and triggers parsing of any children
|
||||
* (TODO: Check assumption: items with 'is_hidden' are not to be exported)
|
||||
*
|
||||
* @param nodeItem the item for the head line
|
||||
* @param level: The hierarchy index (beginning at 0 for top level agenda topics)
|
||||
* @returns pdfMake definitions for the number/title strings, indented according to hierarchy
|
||||
*/
|
||||
private parseItem(nodeItem: OSTreeNode<ViewItem>, level: number): AgendaTreePdfEntry[] {
|
||||
const itemList: AgendaTreePdfEntry[] = [];
|
||||
if (!nodeItem.item.item.is_hidden) {
|
||||
// don't include hidden items and their subitems
|
||||
const resultString: AgendaTreePdfEntry = {
|
||||
style: level ? 'listChild' : 'listParent',
|
||||
columns: [
|
||||
{
|
||||
width: level * 15,
|
||||
text: ''
|
||||
},
|
||||
{
|
||||
width: 60,
|
||||
text: nodeItem.item.itemNumber
|
||||
},
|
||||
{
|
||||
text: nodeItem.item.getTitle()
|
||||
}
|
||||
]
|
||||
};
|
||||
itemList.push(resultString);
|
||||
if (nodeItem.children && nodeItem.children.length) {
|
||||
nodeItem.children.forEach(child => {
|
||||
itemList.push(...this.parseItem(child, level + 1));
|
||||
});
|
||||
}
|
||||
}
|
||||
return itemList;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user