Skip to content

Commit 667ba34

Browse files
committed
Legger til pdf-footer
1 parent 01b86b6 commit 667ba34

File tree

8 files changed

+57
-28
lines changed

8 files changed

+57
-28
lines changed

common/cms-documents/content.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ type ContentMetaData = {
3838
contentType?: string;
3939
contentTypeKey?: string;
4040

41-
created?: string;
42-
timestamp?: string;
41+
created: string;
42+
timestamp: string;
4343
publishFrom?: string;
4444
publishTo?: string;
4545

common/timestamp.ts

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export const formatTimestamp = (tsRaw: string) =>
2+
new Date(tsRaw).toLocaleString('no', { dateStyle: 'short', timeStyle: 'short' });

server/src/cms/CmsArchiveSite.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,8 @@ export class CmsArchiveSite {
171171
.send(data);
172172
});
173173

174-
router.get('/pdf/multi/:versionKeys', async (req, res, next) => {
175-
const result = await this.pdfGenerator.generatePdfFromVersions(
174+
router.get('/pdf/multi/:versionKeys', async (req, res) => {
175+
await this.pdfGenerator.pdfFromVersionsResponse(
176176
req.params.versionKeys.split(','),
177177
res,
178178
parseNumberParam(req.query.width)

server/src/pdf/PdfGenerator.ts

+22-13
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Browser } from 'puppeteer';
22
import { CmsArchiveContentService } from '../cms/CmsArchiveContentService';
3-
import { pixelWidthToA4Scale } from './pdf-scale';
4-
import { CmsContentDocument } from '../../../common/cms-documents/content';
3+
import { generatePdfFilename, generatePdfFooter, pixelWidthToA4Scale } from './pdf-utils';
4+
import { CmsContent } from '../../../common/cms-documents/content';
55
import archiver from 'archiver';
66
import { Response } from 'express';
77
import mime from 'mime';
@@ -28,7 +28,7 @@ export class PdfGenerator {
2828
this.contentService = contentService;
2929
}
3030

31-
public async generatePdfFromVersions(
31+
public async pdfFromVersionsResponse(
3232
versionKeys: string[],
3333
res: Response,
3434
width: number = DEFAULT_WIDTH_PX
@@ -66,7 +66,7 @@ export class PdfGenerator {
6666
continue;
6767
}
6868

69-
await this.generatePdf(content.html, width).then((pdf) => {
69+
await this.generateContentPdf(content, width).then((pdf) => {
7070
if (!pdf) {
7171
return;
7272
}
@@ -77,7 +77,7 @@ export class PdfGenerator {
7777
res.setHeader('Content-Length', pdf.length * contentVersions.length);
7878
}
7979

80-
const fileName = this.getPdfFilename(content);
80+
const fileName = generatePdfFilename(content);
8181

8282
archive.append(pdf, { name: fileName });
8383
});
@@ -95,18 +95,23 @@ export class PdfGenerator {
9595
return null;
9696
}
9797

98-
const data = await this.generatePdf(content.html, width);
98+
const data = await this.generateContentPdf(content, width);
9999
if (!data) {
100100
return null;
101101
}
102102

103103
return {
104104
data,
105-
filename: this.getPdfFilename(content),
105+
filename: generatePdfFilename(content),
106106
};
107107
}
108108

109-
private async generatePdf(html: string, width: number): Promise<Buffer | null> {
109+
private async generateContentPdf(content: CmsContent, width: number): Promise<Buffer | null> {
110+
const { html } = content;
111+
if (!html) {
112+
return null;
113+
}
114+
110115
const widthActual = width >= MIN_WIDTH_PX ? width : DEFAULT_WIDTH_PX;
111116

112117
// Ensures assets with relative urls are loaded from the correct origin
@@ -124,8 +129,16 @@ export class PdfGenerator {
124129

125130
const pdf = await page.pdf({
126131
printBackground: true,
127-
format: 'a4',
132+
format: 'A4',
128133
scale: pixelWidthToA4Scale(widthActual),
134+
displayHeaderFooter: true,
135+
footerTemplate: generatePdfFooter(content),
136+
margin: {
137+
top: '4px',
138+
right: '4px',
139+
bottom: '24px',
140+
left: '4px',
141+
},
129142
});
130143

131144
await page.close();
@@ -136,8 +149,4 @@ export class PdfGenerator {
136149
return null;
137150
}
138151
}
139-
140-
private getPdfFilename(content: CmsContentDocument) {
141-
return `${content.meta.timestamp}_${content.name}_${content.contentKey}-${content.versionKey}.pdf`;
142-
}
143152
}

server/src/pdf/pdf-scale.ts

-9
This file was deleted.

server/src/pdf/pdf-utils.ts

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { CmsContent, CmsContentDocument } from '../../../common/cms-documents/content';
2+
import { formatTimestamp } from '../../../common/timestamp';
3+
4+
const PUPPETEER_PDF_DPI = 96;
5+
const A4_INCH_WIDTH = 8.27;
6+
const SCALE_FACTOR = PUPPETEER_PDF_DPI * A4_INCH_WIDTH;
7+
8+
const MIN = 0.1;
9+
const MAX = 2;
10+
11+
export const pixelWidthToA4Scale = (pxWidth: number): number =>
12+
Math.max(MIN, Math.min(MAX, (1 / pxWidth) * SCALE_FACTOR));
13+
14+
export const generatePdfFooter = (content: CmsContent) => `
15+
<div style="font-size: 10px; margin-bottom:-16px; padding: 4px; width: 100%; display: flex; justify-content: space-between; flex-wrap: nowrap">
16+
<div style="white-space: nowrap; overflow-x: hidden; text-overflow: ellipsis; flex-shrink: 1">
17+
${content.displayName}
18+
</div>
19+
<div style="white-space: nowrap; flex-shrink: 0">
20+
[${formatTimestamp(content.meta.timestamp)} // version: ${content.versionKey}] - (<span class="pageNumber"></span>/<span class="totalPages"></span>)
21+
</div>
22+
</div>`;
23+
24+
export const generatePdfFilename = (content: CmsContentDocument) =>
25+
`${content.meta.timestamp}_${content.name}_${content.contentKey}-${content.versionKey}.pdf`;

src/components/main-section/content-view/html-exporter/HtmlExporter.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Button, Checkbox, CheckboxGroup, Heading, HelpText, Label } from '@navi
44
import { classNames } from '../../../../utils/classNames';
55
import { useAppState } from '../../../../context/app-state/useAppState';
66
import { ArrowDownRightIcon } from '@navikt/aksel-icons';
7+
import { formatTimestamp } from '../../../../../common/timestamp';
78

89
import style from './HtmlExporter.module.css';
910

@@ -113,7 +114,7 @@ export const HtmlExporter = ({ content, hidden }: Props) => {
113114
value={versionKeysSelected}
114115
>
115116
{versions.map((version, index) => {
116-
const dateTime = new Date(version.timestamp).toLocaleString('no');
117+
const dateTime = formatTimestamp(version.timestamp);
117118
return (
118119
<Checkbox
119120
onClick={onCheckboxClick(index)}

src/components/main-section/content-view/version-selector/VersionSelector.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Select } from '@navikt/ds-react';
33
import { CmsContent } from '../../../../../common/cms-documents/content';
44
import { useApiFetch } from '../../../../fetch/useApiFetch';
55
import { useAppState } from '../../../../context/app-state/useAppState';
6+
import { formatTimestamp } from '../../../../../common/timestamp';
67

78
const TITLE_MAX_LENGTH = 100;
89

@@ -35,7 +36,7 @@ export const VersionSelector = ({ content }: Props) => {
3536
}}
3637
>
3738
{content.versions.map((version) => {
38-
const dateTime = new Date(version.timestamp).toLocaleString('no');
39+
const dateTime = formatTimestamp(version.timestamp);
3940
return (
4041
<option value={version.key} key={version.key}>
4142
{`${pruneTitle(version.title)} - [${dateTime}]`}

0 commit comments

Comments
 (0)