@flowselections/layout-maker 1.62.2 → 1.63.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-lib/components/AfdrukKnop.js +64 -64
- package/dist-lib/components/BevestigDialog.d.ts +9 -0
- package/dist-lib/components/BevestigDialog.d.ts.map +1 -0
- package/dist-lib/components/BevestigDialog.js +24 -0
- package/dist-lib/components/LogosPage.d.ts.map +1 -1
- package/dist-lib/components/LogosPage.js +27 -5
- package/dist-lib/components/NetwerkPrintersDialog.js +79 -79
- package/dist-lib/components/PrintenInstellenWizard.js +1 -1
- package/dist-lib/components/PrinterSetupWizard.d.ts.map +1 -1
- package/dist-lib/components/PrinterSetupWizard.js +3 -1
- package/dist-lib/components/PrintplekDetailPage.d.ts.map +1 -1
- package/dist-lib/components/PrintplekDetailPage.js +42 -4
- package/dist-lib/components/TestprintDialog.d.ts.map +1 -1
- package/dist-lib/components/TestprintDialog.js +15 -1
- package/dist-lib/components/WerkplekConfiguratiePage.js +2 -2
- package/dist-lib/components/WerkplekkenTab.d.ts.map +1 -1
- package/dist-lib/components/WerkplekkenTab.js +13 -6
- package/dist-lib/integrations/supabase/client.server.js +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +125 -0
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/afbeeldingMaat.d.ts +10 -0
- package/dist-lib/lib/afbeeldingMaat.d.ts.map +1 -0
- package/dist-lib/lib/afbeeldingMaat.js +39 -0
- package/dist-lib/lib/etiketControle.d.ts +9 -1
- package/dist-lib/lib/etiketControle.d.ts.map +1 -1
- package/dist-lib/lib/etiketControle.js +21 -4
- package/dist-lib/lib/htmlNaarPdf.server.d.ts +4 -0
- package/dist-lib/lib/htmlNaarPdf.server.d.ts.map +1 -1
- package/dist-lib/lib/htmlNaarPdf.server.js +5 -1
- package/dist-lib/lib/htmlPdf.server.d.ts +6 -0
- package/dist-lib/lib/htmlPdf.server.d.ts.map +1 -1
- package/dist-lib/lib/htmlPdf.server.js +46 -10
- package/dist-lib/lib/logoLibrary.d.ts +25 -0
- package/dist-lib/lib/logoLibrary.d.ts.map +1 -1
- package/dist-lib/lib/logoLibrary.js +73 -1
- package/dist-lib/lib/opmaakLimiet.d.ts +8 -0
- package/dist-lib/lib/opmaakLimiet.d.ts.map +1 -0
- package/dist-lib/lib/opmaakLimiet.js +25 -0
- package/dist-lib/lib/printQueue.server.d.ts.map +1 -1
- package/dist-lib/lib/printQueue.server.js +81 -20
- package/dist-lib/lib/printService.functions.js +2 -2
- package/dist-lib/lib/printplekken.d.ts +17 -1
- package/dist-lib/lib/printplekken.d.ts.map +1 -1
- package/dist-lib/lib/printplekken.js +42 -3
- package/dist-lib/lib/profielHtml.js +1 -1
- package/dist-lib/lib/shellPoort.d.ts +1 -1
- package/dist-lib/lib/shellPoort.js +1 -1
- package/dist-lib/lib/stickerFormaat.d.ts +21 -0
- package/dist-lib/lib/stickerFormaat.d.ts.map +1 -0
- package/dist-lib/lib/stickerFormaat.js +39 -0
- package/dist-lib/lib/testprint.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Meer pixels dan dit laadt de server niet (ruim genoeg voor 300 dpi op A4-breedte). */
|
|
2
|
+
export declare const MAX_BEELD_PIXELS = 4000000;
|
|
3
|
+
/** Tijdslimiet voor het ophalen van één bestand. */
|
|
4
|
+
export declare const OPHAAL_LIMIET_MS = 10000;
|
|
5
|
+
export declare function beeldAfmeting(b: Uint8Array): {
|
|
6
|
+
breedte: number;
|
|
7
|
+
hoogte: number;
|
|
8
|
+
} | null;
|
|
9
|
+
export declare function teGrootBeeld(b: Uint8Array): string | null;
|
|
10
|
+
//# sourceMappingURL=afbeeldingMaat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"afbeeldingMaat.d.ts","sourceRoot":"","sources":["../../src/lib/afbeeldingMaat.ts"],"names":[],"mappings":"AAMA,yFAAyF;AACzF,eAAO,MAAM,gBAAgB,UAAY,CAAC;AAE1C,oDAAoD;AACpD,eAAO,MAAM,gBAAgB,QAAS,CAAC;AAEvC,wBAAgB,aAAa,CAAC,CAAC,EAAE,UAAU,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAoBvF;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAMzD"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// src/lib/afbeeldingMaat.ts — afmeting (pixels) van een PNG/JPEG uit de kop,
|
|
3
|
+
// zonder het hele plaatje te decoderen. Een te groot plaatje (bijv. een logo
|
|
4
|
+
// van 5472 × 3648 px) laat de printronde op de server vastlopen.
|
|
5
|
+
// ============================================================================
|
|
6
|
+
/** Meer pixels dan dit laadt de server niet (ruim genoeg voor 300 dpi op A4-breedte). */
|
|
7
|
+
export const MAX_BEELD_PIXELS = 4000000;
|
|
8
|
+
/** Tijdslimiet voor het ophalen van één bestand. */
|
|
9
|
+
export const OPHAAL_LIMIET_MS = 10000;
|
|
10
|
+
export function beeldAfmeting(b) {
|
|
11
|
+
// PNG: 8 bytes handtekening, dan IHDR met breedte/hoogte.
|
|
12
|
+
if (b.length >= 24 && b[0] === 0x89 && b[1] === 0x50 && b[2] === 0x4e && b[3] === 0x47) {
|
|
13
|
+
const lees = (i) => ((b[i] << 24) | (b[i + 1] << 16) | (b[i + 2] << 8) | b[i + 3]) >>> 0;
|
|
14
|
+
return { breedte: lees(16), hoogte: lees(20) };
|
|
15
|
+
}
|
|
16
|
+
// JPEG: zoek het SOF-segment.
|
|
17
|
+
if (b.length > 4 && b[0] === 0xff && b[1] === 0xd8) {
|
|
18
|
+
let i = 2;
|
|
19
|
+
while (i + 9 < b.length) {
|
|
20
|
+
if (b[i] !== 0xff)
|
|
21
|
+
return null;
|
|
22
|
+
const m = b[i + 1];
|
|
23
|
+
const len = (b[i + 2] << 8) | b[i + 3];
|
|
24
|
+
if (m >= 0xc0 && m <= 0xcf && m !== 0xc4 && m !== 0xc8 && m !== 0xcc) {
|
|
25
|
+
return { hoogte: (b[i + 5] << 8) | b[i + 6], breedte: (b[i + 7] << 8) | b[i + 8] };
|
|
26
|
+
}
|
|
27
|
+
i += 2 + len;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
export function teGrootBeeld(b) {
|
|
33
|
+
const a = beeldAfmeting(b);
|
|
34
|
+
if (!a)
|
|
35
|
+
return null;
|
|
36
|
+
return a.breedte * a.hoogte > MAX_BEELD_PIXELS
|
|
37
|
+
? `Afbeelding te groot (${a.breedte} × ${a.hoogte} px); maximaal ${MAX_BEELD_PIXELS / 1000000} miljoen pixels`
|
|
38
|
+
: null;
|
|
39
|
+
}
|
|
@@ -3,7 +3,13 @@ export interface GeladenEtiket {
|
|
|
3
3
|
naam: string;
|
|
4
4
|
breedte_mm: number;
|
|
5
5
|
hoogte_mm: number;
|
|
6
|
+
/** Vaste maat uit de standaardlijst: de printer kent geen formaatnaam, dus geen `paper` meesturen. */
|
|
7
|
+
standaard?: boolean;
|
|
6
8
|
}
|
|
9
|
+
/** Vaste etiketmaten die altijd in de keuzelijst staan (naast wat de printer meldt). */
|
|
10
|
+
export declare const STANDAARD_ETIKETTEN: GeladenEtiket[];
|
|
11
|
+
/** Formaten van de printer plus de standaardmaten die de printer zelf niet meldt. */
|
|
12
|
+
export declare function etiketOptiesMetStandaard(papers: unknown): GeladenEtiket[];
|
|
7
13
|
export type EtiketUitkomst = {
|
|
8
14
|
ok: true;
|
|
9
15
|
paper: string;
|
|
@@ -35,7 +41,9 @@ export declare function etiketPast(doc: {
|
|
|
35
41
|
breedte_mm: number;
|
|
36
42
|
hoogte_mm: number;
|
|
37
43
|
soortLabel: string;
|
|
38
|
-
}, geladen: GeladenEtiket | null, printerNaam: string
|
|
44
|
+
}, geladen: GeladenEtiket | null, printerNaam: string,
|
|
45
|
+
/** Klantsticker: melding met maat, printer en wat je moet inleggen. */
|
|
46
|
+
sticker?: boolean): EtiketUitkomst;
|
|
39
47
|
/** Leest de paginagrootte (mm) van de eerste pagina uit een PDF (MediaBox). */
|
|
40
48
|
export declare function pdfPaginaMm(pdfBase64: string): {
|
|
41
49
|
breedte_mm: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"etiketControle.d.ts","sourceRoot":"","sources":["../../src/lib/etiketControle.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,aAAa;IAC5B,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"etiketControle.d.ts","sourceRoot":"","sources":["../../src/lib/etiketControle.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,aAAa;IAC5B,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,sGAAsG;IACtG,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,wFAAwF;AACxF,eAAO,MAAM,mBAAmB,EAAE,aAAa,EAG9C,CAAC;AAEF,qFAAqF;AACrF,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,OAAO,GAAG,aAAa,EAAE,CAMzE;AAED,MAAM,MAAM,cAAc,GACtB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,mBAAmB,GAAG,qBAAqB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAKtF,eAAO,MAAM,SAAS,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,WAA2B,CAAC;AAC1E,yDAAyD;AACzD,eAAO,MAAM,MAAM,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,WACmC,CAAC;AAC/E,iDAAiD;AACjD,eAAO,MAAM,WAAW,GAAI,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,WAC3B,CAAC;AAG5D,4DAA4D;AAC5D,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,OAAO,GAAG,aAAa,GAAG,IAAI,CAQlE;AAED,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,aAAa,EAAE,CAW7D;AAED;;;GAGG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,EAClE,OAAO,EAAE,aAAa,GAAG,IAAI,EAC7B,WAAW,EAAE,MAAM;AACnB,uEAAuE;AACvE,OAAO,UAAQ,GACd,cAAc,CAgChB;AAED,+EAA+E;AAC/E,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAa/F"}
|
|
@@ -6,6 +6,18 @@
|
|
|
6
6
|
// rol die er écht in zit. Daarom kiest de beheerder per labelprinter het
|
|
7
7
|
// "geladen etiket" en controleren we daartegen. Nooit stil schalen.
|
|
8
8
|
// ============================================================================
|
|
9
|
+
/** Vaste etiketmaten die altijd in de keuzelijst staan (naast wat de printer meldt). */
|
|
10
|
+
export const STANDAARD_ETIKETTEN = [
|
|
11
|
+
{ naam: "Etiket 40 × 40 mm", breedte_mm: 40, hoogte_mm: 40, standaard: true },
|
|
12
|
+
{ naam: "Etiket 50 × 50 mm", breedte_mm: 50, hoogte_mm: 50, standaard: true },
|
|
13
|
+
];
|
|
14
|
+
/** Formaten van de printer plus de standaardmaten die de printer zelf niet meldt. */
|
|
15
|
+
export function etiketOptiesMetStandaard(papers) {
|
|
16
|
+
const eigen = etiketOpties(papers);
|
|
17
|
+
const zelfde = (a, b) => (Math.abs(a.breedte_mm - b.breedte_mm) < 0.6 && Math.abs(a.hoogte_mm - b.hoogte_mm) < 0.6) ||
|
|
18
|
+
(Math.abs(a.breedte_mm - b.hoogte_mm) < 0.6 && Math.abs(a.hoogte_mm - b.breedte_mm) < 0.6);
|
|
19
|
+
return [...eigen, ...STANDAARD_ETIKETTEN.filter((s) => !eigen.some((e) => zelfde(e, s)))];
|
|
20
|
+
}
|
|
9
21
|
const MARGE_MM = 2;
|
|
10
22
|
const mm = (n) => Math.round(n * 10) / 10;
|
|
11
23
|
export const maatTekst = (b, h) => `${mm(b)}×${mm(h)} mm`;
|
|
@@ -24,7 +36,7 @@ export function leesGeladenEtiket(v) {
|
|
|
24
36
|
const naam = String(r.naam ?? "").trim();
|
|
25
37
|
if (!naam || !(b > 0) || !(h > 0))
|
|
26
38
|
return null;
|
|
27
|
-
return { naam, breedte_mm: b, hoogte_mm: h };
|
|
39
|
+
return r.standaard === true ? { naam, breedte_mm: b, hoogte_mm: h, standaard: true } : { naam, breedte_mm: b, hoogte_mm: h };
|
|
28
40
|
}
|
|
29
41
|
/** PrintNode-formaten (tienden mm) als keuzelijst in mm, zonder lege maten. */
|
|
30
42
|
export function etiketOpties(papers) {
|
|
@@ -46,7 +58,9 @@ export function etiketOpties(papers) {
|
|
|
46
58
|
* Past een document van breedte×hoogte (mm) op het geladen etiket? Draaien
|
|
47
59
|
* mag (liggend etiket, staande layout of andersom), schalen nooit.
|
|
48
60
|
*/
|
|
49
|
-
export function etiketPast(doc, geladen, printerNaam
|
|
61
|
+
export function etiketPast(doc, geladen, printerNaam,
|
|
62
|
+
/** Klantsticker: melding met maat, printer en wat je moet inleggen. */
|
|
63
|
+
sticker = false) {
|
|
50
64
|
if (!geladen) {
|
|
51
65
|
return {
|
|
52
66
|
ok: false,
|
|
@@ -61,7 +75,10 @@ export function etiketPast(doc, geladen, printerNaam) {
|
|
|
61
75
|
return {
|
|
62
76
|
ok: false,
|
|
63
77
|
code: "FORMAAT_PAST_NIET",
|
|
64
|
-
bericht:
|
|
78
|
+
bericht: sticker
|
|
79
|
+
? `Klantsticker ${heel(b, h)} past niet op het etiket in ${printerNaam} (${heel(geladen.breedte_mm, geladen.hoogte_mm)}). ` +
|
|
80
|
+
`Leg etiketten van minimaal ${heel(b, h)} in of kies een andere printer.`
|
|
81
|
+
: `Past niet op het etiket in de printer (${heel(b, h)} op ${heel(geladen.breedte_mm, geladen.hoogte_mm)}).`,
|
|
65
82
|
};
|
|
66
83
|
}
|
|
67
84
|
const docLiggend = b > h;
|
|
@@ -69,7 +86,7 @@ export function etiketPast(doc, geladen, printerNaam) {
|
|
|
69
86
|
const rotate = !recht || docLiggend !== etiketLiggend ? 90 : 0;
|
|
70
87
|
return {
|
|
71
88
|
ok: true,
|
|
72
|
-
paper: geladen.naam,
|
|
89
|
+
paper: geladen.standaard ? "" : geladen.naam,
|
|
73
90
|
rotate,
|
|
74
91
|
uitleg: `geladen etiket ${geladen.naam.trim()} (${maatTekst(geladen.breedte_mm, geladen.hoogte_mm)})${rotate ? ", gedraaid" : ""}`,
|
|
75
92
|
};
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { AfbeeldingInhoudFout } from "./htmlPdf.server.js";
|
|
2
|
+
export { AfbeeldingInhoudFout };
|
|
1
3
|
export declare class PdfRenderFout extends Error {
|
|
2
4
|
code: "niet_ingesteld" | "mislukt" | "afwijking";
|
|
3
5
|
constructor(code: "niet_ingesteld" | "mislukt" | "afwijking", boodschap: string);
|
|
@@ -8,6 +10,8 @@ export interface PdfOpties {
|
|
|
8
10
|
hoogteMm?: number;
|
|
9
11
|
margeMm?: number;
|
|
10
12
|
landschap?: boolean;
|
|
13
|
+
/** Melding per weggelaten decoratie-afbeelding (zoals een logo). */
|
|
14
|
+
bijOvergeslagen?: (src: string, reden: string) => void;
|
|
11
15
|
}
|
|
12
16
|
/** Levert de PDF als base64-tekst (zonder data:-prefix). */
|
|
13
17
|
export declare function htmlNaarPdfServer(opties: PdfOpties): Promise<string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"htmlNaarPdf.server.d.ts","sourceRoot":"","sources":["../../src/lib/htmlNaarPdf.server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"htmlNaarPdf.server.d.ts","sourceRoot":"","sources":["../../src/lib/htmlNaarPdf.server.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,oBAAoB,EAAqC,MAAM,kBAAkB,CAAC;AAC3F,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAEhC,qBAAa,aAAc,SAAQ,KAAK;IAE7B,IAAI,EAAE,gBAAgB,GAAG,SAAS,GAAG,WAAW;gBAAhD,IAAI,EAAE,gBAAgB,GAAG,SAAS,GAAG,WAAW,EACvD,SAAS,EAAE,MAAM;CAKpB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,oEAAoE;IACpE,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACxD;AAED,4DAA4D;AAC5D,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAuB1E"}
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
// Gebruikt de eigen documentmaker (src/lib/htmlPdf.server.ts). Geen externe
|
|
4
4
|
// dienst, geen browser en geen instellingen per shell nodig.
|
|
5
5
|
// ============================================================================
|
|
6
|
-
import { bytesNaarBase64, htmlNaarPdfBytes } from "./htmlPdf.server.js";
|
|
6
|
+
import { AfbeeldingInhoudFout, bytesNaarBase64, htmlNaarPdfBytes } from "./htmlPdf.server.js";
|
|
7
|
+
export { AfbeeldingInhoudFout };
|
|
7
8
|
export class PdfRenderFout extends Error {
|
|
8
9
|
constructor(code, boodschap) {
|
|
9
10
|
super(boodschap);
|
|
@@ -23,12 +24,15 @@ export async function htmlNaarPdfServer(opties) {
|
|
|
23
24
|
hoogteMm: opties.hoogteMm ?? 297,
|
|
24
25
|
margeMm: opties.margeMm ?? 10,
|
|
25
26
|
landschap: opties.landschap ?? false,
|
|
27
|
+
bijOvergeslagen: opties.bijOvergeslagen,
|
|
26
28
|
});
|
|
27
29
|
if (!bytes.length)
|
|
28
30
|
throw new Error("De PDF is leeg gebleven.");
|
|
29
31
|
return bytesNaarBase64(bytes);
|
|
30
32
|
}
|
|
31
33
|
catch (e) {
|
|
34
|
+
if (e instanceof AfbeeldingInhoudFout)
|
|
35
|
+
throw e;
|
|
32
36
|
const melding = e instanceof Error ? e.message : "PDF maken mislukte.";
|
|
33
37
|
throw new PdfRenderFout(melding.startsWith("Afdrukafwijking gevonden:") ? "afwijking" : "mislukt", melding.startsWith("Afdrukafwijking gevonden:") ? melding : `PDF maken mislukte: ${melding}`);
|
|
34
38
|
}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/** De afbeelding is de inhoud zelf en kon niet worden gebruikt: niet printen. */
|
|
2
|
+
export declare class AfbeeldingInhoudFout extends Error {
|
|
3
|
+
name: string;
|
|
4
|
+
}
|
|
1
5
|
import { type RGB } from "pdf-lib";
|
|
2
6
|
export declare const MM = 2.834645669291339;
|
|
3
7
|
export interface Knoop {
|
|
@@ -40,6 +44,8 @@ export interface DocumentPdfOpties {
|
|
|
40
44
|
landschap?: boolean;
|
|
41
45
|
/** Voettekst met paginanummers ("Pagina 1 van 3"). */
|
|
42
46
|
paginanummers?: boolean;
|
|
47
|
+
/** Melding per weggelaten decoratie-afbeelding (voor het logboek). */
|
|
48
|
+
bijOvergeslagen?: (src: string, reden: string) => void;
|
|
43
49
|
}
|
|
44
50
|
export interface PdfRenderDiagnostiek {
|
|
45
51
|
geldig: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"htmlPdf.server.d.ts","sourceRoot":"","sources":["../../src/lib/htmlPdf.server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"htmlPdf.server.d.ts","sourceRoot":"","sources":["../../src/lib/htmlPdf.server.ts"],"names":[],"mappings":"AAcA,iFAAiF;AACjF,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,IAAI,SAA0B;CAC/B;AACD,OAAO,EAOL,KAAK,GAAG,EACT,MAAM,SAAS,CAAC;AAEjB,eAAO,MAAM,EAAE,oBAAoB,CAAC;AAIpC,MAAM,WAAW,KAAK;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,QAAQ,EAAE,KAAK,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAuBD,kEAAkE;AAClE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAuC/C;AAUD,UAAU,SAAS;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AACD,UAAU,QAAQ;IAChB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,sEAAsE;AACtE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMpD;AA2BD,yFAAyF;AACzF,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,EAAE,CAgClD;AAqBD,6EAA6E;AAC7E,wBAAgB,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAiBlE;AAKD,MAAM,WAAW,KAAK;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,OAAO,CAAC;IACb,KAAK,EAAE,GAAG,CAAC;IACX,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IACxC,mDAAmD;IACnD,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAkrCD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,sDAAsD;IACtD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,sEAAsE;IACtE,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACxD;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,CA8BtE;AAED,+EAA+E;AAC/E,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,CAmFrF;AA0BD,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAQzD"}
|
|
@@ -9,6 +9,14 @@
|
|
|
9
9
|
// afbeeldingen, barcodes en QR-vlakken.
|
|
10
10
|
// ============================================================================
|
|
11
11
|
import { code128Bars } from "./code128.js";
|
|
12
|
+
import { OPHAAL_LIMIET_MS, teGrootBeeld } from "./afbeeldingMaat.js";
|
|
13
|
+
/** De afbeelding is de inhoud zelf en kon niet worden gebruikt: niet printen. */
|
|
14
|
+
export class AfbeeldingInhoudFout extends Error {
|
|
15
|
+
constructor() {
|
|
16
|
+
super(...arguments);
|
|
17
|
+
this.name = "AfbeeldingInhoudFout";
|
|
18
|
+
}
|
|
19
|
+
}
|
|
12
20
|
import { PDFDocument, StandardFonts, rgb, } from "pdf-lib";
|
|
13
21
|
export const MM = 2.834645669291339; // punten per millimeter
|
|
14
22
|
const LEEG = new Set(["img", "br", "hr", "col", "meta", "link", "input"]);
|
|
@@ -788,6 +796,8 @@ async function tekenAfbeelding(ctx, n, vak, s) {
|
|
|
788
796
|
const tk = ctx.tk;
|
|
789
797
|
const src = n.attrs["src"] ?? "";
|
|
790
798
|
const afb = ctx.afbeeldingen.get(src);
|
|
799
|
+
if (!afb && ctx.weglaten?.has(src))
|
|
800
|
+
return;
|
|
791
801
|
const hoogte = lengte(eig(n)["height"]) ?? 18 * MM;
|
|
792
802
|
if (!afb) {
|
|
793
803
|
// Een leeg vlak vertelt niemand dat er iets misging: melding op de afdruk.
|
|
@@ -1249,17 +1259,22 @@ function base64NaarBytes(b64) {
|
|
|
1249
1259
|
out[i] = bin.charCodeAt(i);
|
|
1250
1260
|
return out;
|
|
1251
1261
|
}
|
|
1252
|
-
function verzamelBronnen(n, uit) {
|
|
1253
|
-
if (n.tag === "img" && n.attrs["src"])
|
|
1262
|
+
function verzamelBronnen(n, uit, inhoud) {
|
|
1263
|
+
if (n.tag === "img" && n.attrs["src"]) {
|
|
1254
1264
|
uit.add(n.attrs["src"]);
|
|
1265
|
+
if (n.attrs["data-inhoud"] === "1")
|
|
1266
|
+
inhoud.add(n.attrs["src"]);
|
|
1267
|
+
}
|
|
1255
1268
|
for (const k of n.kinderen)
|
|
1256
|
-
verzamelBronnen(k, uit);
|
|
1269
|
+
verzamelBronnen(k, uit, inhoud);
|
|
1257
1270
|
}
|
|
1258
1271
|
async function laadAfbeeldingen(pdf, wortel) {
|
|
1259
1272
|
const bronnen = new Set();
|
|
1260
|
-
|
|
1273
|
+
const inhoud = new Set();
|
|
1274
|
+
verzamelBronnen(wortel, bronnen, inhoud);
|
|
1261
1275
|
const beelden = new Map();
|
|
1262
|
-
const
|
|
1276
|
+
const alleFouten = new Map();
|
|
1277
|
+
const fouten = { set: (s, r) => alleFouten.set(s, r) };
|
|
1263
1278
|
await Promise.all([...bronnen].slice(0, 20).map(async (src) => {
|
|
1264
1279
|
try {
|
|
1265
1280
|
let bytes;
|
|
@@ -1274,7 +1289,14 @@ async function laadAfbeeldingen(pdf, wortel) {
|
|
|
1274
1289
|
bytes = base64NaarBytes(src.slice(komma + 1));
|
|
1275
1290
|
}
|
|
1276
1291
|
else if (/^https?:/i.test(src)) {
|
|
1277
|
-
|
|
1292
|
+
let res;
|
|
1293
|
+
try {
|
|
1294
|
+
res = await fetch(src, { signal: AbortSignal.timeout(OPHAAL_LIMIET_MS) });
|
|
1295
|
+
}
|
|
1296
|
+
catch {
|
|
1297
|
+
fouten.set(src, `Afbeelding niet binnen ${OPHAAL_LIMIET_MS / 1000} seconden opgehaald`);
|
|
1298
|
+
return;
|
|
1299
|
+
}
|
|
1278
1300
|
if (!res.ok) {
|
|
1279
1301
|
fouten.set(src, `Afbeelding niet opgehaald (${res.status})`);
|
|
1280
1302
|
return;
|
|
@@ -1291,6 +1313,11 @@ async function laadAfbeeldingen(pdf, wortel) {
|
|
|
1291
1313
|
fouten.set(src, "Onbekende afbeeldingsbron");
|
|
1292
1314
|
return;
|
|
1293
1315
|
}
|
|
1316
|
+
const teGroot = teGrootBeeld(bytes);
|
|
1317
|
+
if (teGroot) {
|
|
1318
|
+
fouten.set(src, teGroot);
|
|
1319
|
+
return;
|
|
1320
|
+
}
|
|
1294
1321
|
const afb = png ? await pdf.embedPng(bytes) : await pdf.embedJpg(bytes);
|
|
1295
1322
|
beelden.set(src, afb);
|
|
1296
1323
|
}
|
|
@@ -1298,7 +1325,11 @@ async function laadAfbeeldingen(pdf, wortel) {
|
|
|
1298
1325
|
fouten.set(src, e instanceof Error ? `Afbeelding onleesbaar: ${e.message}` : "Afbeelding onleesbaar");
|
|
1299
1326
|
}
|
|
1300
1327
|
}));
|
|
1301
|
-
|
|
1328
|
+
const inhoudFouten = new Map();
|
|
1329
|
+
const overgeslagen = new Map();
|
|
1330
|
+
for (const [src, r] of alleFouten)
|
|
1331
|
+
(inhoud.has(src) ? inhoudFouten : overgeslagen).set(src, r);
|
|
1332
|
+
return { beelden, fouten: inhoudFouten, overgeslagen };
|
|
1302
1333
|
}
|
|
1303
1334
|
/**
|
|
1304
1335
|
* Bewaakt constructies die de eigen PDF-motor niet hetzelfde kan uitleggen als
|
|
@@ -1367,13 +1398,18 @@ export async function htmlNaarPdfBytes(opties) {
|
|
|
1367
1398
|
// De opmaak uit het <style>-blok wordt hier per element uitgerekend, zodat
|
|
1368
1399
|
// het document er hetzelfde uitziet als in het voorbeeld op het scherm.
|
|
1369
1400
|
stempelCss(wortel, ontleedCss(leesStylesheets(opties.html)));
|
|
1370
|
-
const { beelden: afbeeldingen, fouten: beeldFouten } = await laadAfbeeldingen(pdf, wortel);
|
|
1401
|
+
const { beelden: afbeeldingen, fouten: beeldFouten, overgeslagen } = await laadAfbeeldingen(pdf, wortel);
|
|
1371
1402
|
if (beeldFouten.size) {
|
|
1372
|
-
|
|
1403
|
+
// De afbeelding is de inhoud zelf (sticker, productfoto): niet printen.
|
|
1404
|
+
throw new AfbeeldingInhoudFout(`De afbeelding van dit document kon niet worden gebruikt; er is niets geprint. (${[...beeldFouten.values()].join(" ")})`);
|
|
1373
1405
|
}
|
|
1406
|
+
for (const [src, reden] of overgeslagen)
|
|
1407
|
+
opties.bijOvergeslagen?.(src, reden);
|
|
1408
|
+
// Decoratie (zoals een logo) wordt weggelaten in plaats van te blokkeren.
|
|
1409
|
+
const afbeeldingenWeg = new Set(overgeslagen.keys());
|
|
1374
1410
|
const basis = basisGrootte(opties.html);
|
|
1375
1411
|
const tk = new Tekenaar(pdf, breedte, hoogte, marge, normaal, vet);
|
|
1376
|
-
const ctx = { tk, afbeeldingen, beeldFouten };
|
|
1412
|
+
const ctx = { tk, afbeeldingen, beeldFouten, weglaten: afbeeldingenWeg };
|
|
1377
1413
|
const stijl = { grootte: basis, vet: false, kleur: DONKER, uitlijning: "left" };
|
|
1378
1414
|
// vaste paginavoet (bijv. totalen op elke pagina) — als volwaardig blok
|
|
1379
1415
|
const voetVak = { x: marge, breedte: breedte - marge * 2 };
|
|
@@ -33,6 +33,8 @@ export interface LogoModel {
|
|
|
33
33
|
transparant: boolean;
|
|
34
34
|
is_standaard: boolean;
|
|
35
35
|
hash: string | null;
|
|
36
|
+
/** pad van het bewaarde origineel na verkleinen (terug te zetten) */
|
|
37
|
+
origineel_pad?: string | null;
|
|
36
38
|
created_at: string;
|
|
37
39
|
updated_at: string;
|
|
38
40
|
/** tijdelijke, ondertekende weergave-URL */
|
|
@@ -76,6 +78,29 @@ export declare function maakLogo(input: UploadInput): Promise<LogoModel>;
|
|
|
76
78
|
export declare function werkLogoBij(id: string, patch: Partial<LogoModel>): Promise<void>;
|
|
77
79
|
/** Vervangt het bestand van een bestaand logo — alle layouts volgen automatisch. */
|
|
78
80
|
export declare function vervangLogoBestand(logo: LogoModel, file: File): Promise<void>;
|
|
81
|
+
/** Maximale breedte van een logo in de bibliotheek; groter is op papier niet nodig. */
|
|
82
|
+
export declare const LOGO_MAX_BREEDTE = 1500;
|
|
83
|
+
/** Nieuwe maat bij verkleinen, of null als het logo al klein genoeg is. */
|
|
84
|
+
export declare function berekenVerkleining(breedte: number, hoogte: number, max?: number): {
|
|
85
|
+
breedte: number;
|
|
86
|
+
hoogte: number;
|
|
87
|
+
} | null;
|
|
88
|
+
export interface LogoVerkleining {
|
|
89
|
+
bestand: File;
|
|
90
|
+
verkleind: boolean;
|
|
91
|
+
van?: {
|
|
92
|
+
breedte: number;
|
|
93
|
+
hoogte: number;
|
|
94
|
+
};
|
|
95
|
+
naar?: {
|
|
96
|
+
breedte: number;
|
|
97
|
+
hoogte: number;
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/** Verkleint een raster-logo (PNG/JPEG/WebP) tot maximaal 1500 px breed. SVG blijft ongewijzigd. */
|
|
101
|
+
export declare function verkleinLogoVoorUpload(file: File): Promise<LogoVerkleining>;
|
|
102
|
+
/** Zet het bewaarde originele bestand van een verkleind logo terug. */
|
|
103
|
+
export declare function zetOrigineelTerug(logo: LogoModel): Promise<void>;
|
|
79
104
|
export declare function verwijderLogo(logo: LogoModel): Promise<void>;
|
|
80
105
|
export declare function downloadLogo(logo: LogoModel): Promise<void>;
|
|
81
106
|
export declare function formatteerBytes(n: number): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logoLibrary.d.ts","sourceRoot":"","sources":["../../src/lib/logoLibrary.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,WAAW,iBAAiB,CAAC;AAE1C,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;EAOnB,CAAC;AAEX,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,UAE3C;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,EAAE,OAAO,CAAC;IACtB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAID,eAAO,MAAM,qBAAqB,UAA6D,CAAC;AAEhG,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAQlD;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAM7D;AAED,wBAAsB,cAAc,CAClC,IAAI,EAAE,IAAI,GACT,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,CAAC,CA2CpE;AAaD,wBAAsB,SAAS,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAOtD;AAED,wBAAgB,QAAQ;;;;EAmBvB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAGzE;AAED,eAAO,MAAM,gBAAgB,QAEiD,CAAC;AAE/E,6EAA6E;AAC7E,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,OAAO,GAAG,KAAK,CAUnD;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAInE;AAED,wBAAgB,aAAa,IAAI;IAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAa9F;AAcD,wBAAsB,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CA8BrE;AAUD,wBAAsB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,iBAOtE;AAED,oFAAoF;AACpF,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,iBAwBnE;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,SAAS,iBAKlD;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,SAAS,iBAUjD;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,UAKxC;AAsCD;;;;;GAKG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAC7C;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EAAE,CACvD,CAoBA"}
|
|
1
|
+
{"version":3,"file":"logoLibrary.d.ts","sourceRoot":"","sources":["../../src/lib/logoLibrary.ts"],"names":[],"mappings":"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"}
|
|
@@ -244,7 +244,79 @@ export async function vervangLogoBestand(logo, file) {
|
|
|
244
244
|
.eq("id", logo.id);
|
|
245
245
|
if (error)
|
|
246
246
|
throw error;
|
|
247
|
-
if (oud)
|
|
247
|
+
if (oud && oud !== logo.origineel_pad)
|
|
248
|
+
await supabase.storage.from(LOGO_BUCKET).remove([oud]);
|
|
249
|
+
}
|
|
250
|
+
/** Maximale breedte van een logo in de bibliotheek; groter is op papier niet nodig. */
|
|
251
|
+
export const LOGO_MAX_BREEDTE = 1500;
|
|
252
|
+
/** Nieuwe maat bij verkleinen, of null als het logo al klein genoeg is. */
|
|
253
|
+
export function berekenVerkleining(breedte, hoogte, max = LOGO_MAX_BREEDTE) {
|
|
254
|
+
if (!(breedte > max) || !(hoogte > 0))
|
|
255
|
+
return null;
|
|
256
|
+
return { breedte: max, hoogte: Math.max(1, Math.round((hoogte * max) / breedte)) };
|
|
257
|
+
}
|
|
258
|
+
/** Verkleint een raster-logo (PNG/JPEG/WebP) tot maximaal 1500 px breed. SVG blijft ongewijzigd. */
|
|
259
|
+
export async function verkleinLogoVoorUpload(file) {
|
|
260
|
+
if (file.type === "image/svg+xml" || typeof document === "undefined") {
|
|
261
|
+
return { bestand: file, verkleind: false };
|
|
262
|
+
}
|
|
263
|
+
const url = URL.createObjectURL(file);
|
|
264
|
+
try {
|
|
265
|
+
const img = await new Promise((resolve, reject) => {
|
|
266
|
+
const i = new Image();
|
|
267
|
+
i.onload = () => resolve(i);
|
|
268
|
+
i.onerror = () => reject(new Error("Afbeelding kon niet worden gelezen"));
|
|
269
|
+
i.src = url;
|
|
270
|
+
});
|
|
271
|
+
const van = { breedte: img.naturalWidth, hoogte: img.naturalHeight };
|
|
272
|
+
const naar = berekenVerkleining(van.breedte, van.hoogte);
|
|
273
|
+
if (!naar)
|
|
274
|
+
return { bestand: file, verkleind: false };
|
|
275
|
+
const c = document.createElement("canvas");
|
|
276
|
+
c.width = naar.breedte;
|
|
277
|
+
c.height = naar.hoogte;
|
|
278
|
+
const ctx = c.getContext("2d");
|
|
279
|
+
if (!ctx)
|
|
280
|
+
return { bestand: file, verkleind: false };
|
|
281
|
+
ctx.imageSmoothingQuality = "high";
|
|
282
|
+
ctx.drawImage(img, 0, 0, naar.breedte, naar.hoogte);
|
|
283
|
+
const type = file.type === "image/jpeg" || file.type === "image/webp" ? file.type : "image/png";
|
|
284
|
+
const blob = await new Promise((r) => c.toBlob(r, type, 0.92));
|
|
285
|
+
if (!blob)
|
|
286
|
+
return { bestand: file, verkleind: false };
|
|
287
|
+
return { bestand: new File([blob], file.name, { type }), verkleind: true, van, naar };
|
|
288
|
+
}
|
|
289
|
+
finally {
|
|
290
|
+
URL.revokeObjectURL(url);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
/** Zet het bewaarde originele bestand van een verkleind logo terug. */
|
|
294
|
+
export async function zetOrigineelTerug(logo) {
|
|
295
|
+
const pad = logo.origineel_pad;
|
|
296
|
+
if (!pad)
|
|
297
|
+
throw new Error("Er is geen origineel bewaard voor dit logo");
|
|
298
|
+
const { data, error } = await supabase.storage.from(LOGO_BUCKET).download(pad);
|
|
299
|
+
if (error || !data)
|
|
300
|
+
throw vertaalOpslagFout(error ?? new Error("Origineel niet gevonden"));
|
|
301
|
+
const file = new File([data], pad, { type: data.type || "image/png" });
|
|
302
|
+
const { breedte, hoogte, transparant } = await leesAfmetingen(file);
|
|
303
|
+
const oud = logo.bestandspad ?? logo.bestand_url;
|
|
304
|
+
const { error: e2 } = await supabase
|
|
305
|
+
.from("layout_logos")
|
|
306
|
+
.update({
|
|
307
|
+
bestand_url: pad,
|
|
308
|
+
bestandspad: pad,
|
|
309
|
+
breedte,
|
|
310
|
+
hoogte,
|
|
311
|
+
bestandsgrootte: file.size,
|
|
312
|
+
transparant,
|
|
313
|
+
hash: await bestandHash(file),
|
|
314
|
+
origineel_pad: null,
|
|
315
|
+
})
|
|
316
|
+
.eq("id", logo.id);
|
|
317
|
+
if (e2)
|
|
318
|
+
throw e2;
|
|
319
|
+
if (oud && oud !== pad)
|
|
248
320
|
await supabase.storage.from(LOGO_BUCKET).remove([oud]);
|
|
249
321
|
}
|
|
250
322
|
export async function verwijderLogo(logo) {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const OPMAAK_LIMIET_MS = 30000;
|
|
2
|
+
export declare const OPMAAK_TE_LANG_TEKST = "Het opmaken van dit document duurde te lang. Probeer het opnieuw; blijft het gebeuren, neem contact op met beheer.";
|
|
3
|
+
export declare class OpmaakTeLangFout extends Error {
|
|
4
|
+
name: string;
|
|
5
|
+
constructor();
|
|
6
|
+
}
|
|
7
|
+
export declare function metTijdslimiet<T>(ms: number, werk: () => Promise<T>): Promise<T>;
|
|
8
|
+
//# sourceMappingURL=opmaakLimiet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opmaakLimiet.d.ts","sourceRoot":"","sources":["../../src/lib/opmaakLimiet.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,gBAAgB,QAAS,CAAC;AAEvC,eAAO,MAAM,oBAAoB,uHACqF,CAAC;AAEvH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,IAAI,SAAsB;;CAI3B;AAED,wBAAsB,cAAc,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAUtF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// src/lib/opmaakLimiet.ts — het opmaken van één document mag niet langer dan
|
|
3
|
+
// 30 seconden duren. Daarna een duidelijke fout in plaats van 10 minuten stil.
|
|
4
|
+
// ============================================================================
|
|
5
|
+
export const OPMAAK_LIMIET_MS = 30000;
|
|
6
|
+
export const OPMAAK_TE_LANG_TEKST = "Het opmaken van dit document duurde te lang. Probeer het opnieuw; blijft het gebeuren, neem contact op met beheer.";
|
|
7
|
+
export class OpmaakTeLangFout extends Error {
|
|
8
|
+
constructor() {
|
|
9
|
+
super(OPMAAK_TE_LANG_TEKST);
|
|
10
|
+
this.name = "OpmaakTeLangFout";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export async function metTijdslimiet(ms, werk) {
|
|
14
|
+
let klok;
|
|
15
|
+
const grens = new Promise((_, weiger) => {
|
|
16
|
+
klok = setTimeout(() => weiger(new OpmaakTeLangFout()), ms);
|
|
17
|
+
});
|
|
18
|
+
try {
|
|
19
|
+
return await Promise.race([werk(), grens]);
|
|
20
|
+
}
|
|
21
|
+
finally {
|
|
22
|
+
if (klok)
|
|
23
|
+
clearTimeout(klok);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"printQueue.server.d.ts","sourceRoot":"","sources":["../../src/lib/printQueue.server.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"printQueue.server.d.ts","sourceRoot":"","sources":["../../src/lib/printQueue.server.ts"],"names":[],"mappings":"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"}
|