@flowselections/layout-maker 1.7.3 → 1.8.1
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/README.md +132 -69
- package/dist-lib/components/LogosPage.d.ts.map +1 -1
- package/dist-lib/components/LogosPage.js +3 -2
- package/dist-lib/components/PrinterSetupWizard.js +1 -1
- package/dist-lib/index.d.ts +3 -3
- package/dist-lib/index.d.ts.map +1 -1
- package/dist-lib/index.js +3 -3
- package/dist-lib/integrations/supabase/auth-middleware.d.ts +393 -13
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.d.ts +393 -13
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +409 -14
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.js +3 -0
- package/dist-lib/lib/aiLayout.functions.d.ts +393 -13
- package/dist-lib/lib/aiLayout.functions.d.ts.map +1 -1
- package/dist-lib/lib/aiLayout.server.js +9 -9
- package/dist-lib/lib/browserPrint.js +5 -5
- package/dist-lib/lib/documentProfiles.d.ts.map +1 -1
- package/dist-lib/lib/documentProfiles.js +3 -0
- package/dist-lib/lib/documentTypes.d.ts +1 -1
- package/dist-lib/lib/documentTypes.d.ts.map +1 -1
- package/dist-lib/lib/documentTypes.js +3 -0
- package/dist-lib/lib/layoutPreview.js +7 -7
- package/dist-lib/lib/logoLibrary.d.ts +12 -0
- package/dist-lib/lib/logoLibrary.d.ts.map +1 -1
- package/dist-lib/lib/logoLibrary.js +39 -1
- package/dist-lib/lib/pakbonHtml.js +50 -50
- package/dist-lib/lib/printApi.d.ts +71 -0
- package/dist-lib/lib/printApi.d.ts.map +1 -1
- package/dist-lib/lib/printApi.js +152 -12
- package/dist-lib/lib/printService.functions.d.ts +1572 -52
- package/dist-lib/lib/printService.functions.d.ts.map +1 -1
- package/dist-lib/lib/productiebonHtml.js +15 -15
- package/dist-lib/lib/profielHtml.js +18 -18
- package/dist-lib/lib/supabaseAdmin.server.d.ts +5 -5
- package/dist-lib/lib/supabaseAdmin.server.js +43 -43
- package/dist-lib/lib/testpagina.js +1 -1
- package/package.json +1 -1
|
@@ -428,6 +428,9 @@ export const DOCUMENT_PROFIELEN = [
|
|
|
428
428
|
generiek("magazijnlijst", "Magazijnlijst", "Verzamellijst voor het magazijn."),
|
|
429
429
|
generiek("controlelijst", "Controlelijst", "Afvinklijst voor controle."),
|
|
430
430
|
generiek("transportdocument", "Transportdocument", "Document voor de rit."),
|
|
431
|
+
generiek("veilingbon", "Veilingbon", "Bon voor de veiling, per kar of partij."),
|
|
432
|
+
generiek("afleverbrief", "Afleverbrief", "Afleverbrief bij een levering."),
|
|
433
|
+
generiek("veilingbrief", "Veilingbrief", "Begeleidende brief voor de veiling."),
|
|
431
434
|
generiek("vrij", "Vrij document", "Lege layout zonder vooraf ingestelde onderdelen."),
|
|
432
435
|
];
|
|
433
436
|
export function documentProfiel(id) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type DocumentType = "pakbon" | "sticker" | "productiebon" | "factuur" | "offerte" | "orderbevestiging" | "etiket" | "verzendlabel" | "productlabel" | "barcode_label" | "magazijnlijst" | "controlelijst" | "transportdocument" | "vrij";
|
|
1
|
+
export type DocumentType = "pakbon" | "sticker" | "productiebon" | "factuur" | "offerte" | "orderbevestiging" | "etiket" | "verzendlabel" | "productlabel" | "barcode_label" | "magazijnlijst" | "controlelijst" | "transportdocument" | "veilingbon" | "afleverbrief" | "veilingbrief" | "vrij";
|
|
2
2
|
export declare const DOCUMENT_TYPES: {
|
|
3
3
|
value: DocumentType;
|
|
4
4
|
label: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"documentTypes.d.ts","sourceRoot":"","sources":["../../src/lib/documentTypes.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,YAAY,GACpB,QAAQ,GACR,SAAS,GACT,cAAc,GACd,SAAS,GACT,SAAS,GACT,kBAAkB,GAClB,QAAQ,GACR,cAAc,GACd,cAAc,GACd,eAAe,GACf,eAAe,GACf,eAAe,GACf,mBAAmB,GACnB,MAAM,CAAC;AAEX,eAAO,MAAM,cAAc,EAAE;IAAE,KAAK,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"documentTypes.d.ts","sourceRoot":"","sources":["../../src/lib/documentTypes.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,6 +15,9 @@ export const DOCUMENT_TYPES = [
|
|
|
15
15
|
{ value: "magazijnlijst", label: "Magazijnlijst" },
|
|
16
16
|
{ value: "controlelijst", label: "Controlelijst" },
|
|
17
17
|
{ value: "transportdocument", label: "Transportdocument" },
|
|
18
|
+
{ value: "veilingbon", label: "Veilingbon" },
|
|
19
|
+
{ value: "afleverbrief", label: "Afleverbrief" },
|
|
20
|
+
{ value: "veilingbrief", label: "Veilingbrief" },
|
|
18
21
|
{ value: "vrij", label: "Vrij document" },
|
|
19
22
|
];
|
|
20
23
|
export function documentTypeLabel(value) {
|
|
@@ -79,8 +79,8 @@ function elementHtml(el, ctx) {
|
|
|
79
79
|
case "cirkel":
|
|
80
80
|
return `<div style="${base};border-radius:50%;border:${s.randbreedte || 0.3}mm solid ${s.randkleur ?? "#111827"}"></div>`;
|
|
81
81
|
case "barcode":
|
|
82
|
-
return `<div style="${base};display:flex;flex-direction:column;justify-content:center;align-items:center;font-family:monospace">
|
|
83
|
-
<div style="width:100%;height:70%;background:repeating-linear-gradient(90deg,#111 0 1.2px,#fff 1.2px 3px)"></div>
|
|
82
|
+
return `<div style="${base};display:flex;flex-direction:column;justify-content:center;align-items:center;font-family:monospace">
|
|
83
|
+
<div style="width:100%;height:70%;background:repeating-linear-gradient(90deg,#111 0 1.2px,#fff 1.2px 3px)"></div>
|
|
84
84
|
<div style="font-size:7pt">${esc(inhoud)}</div></div>`;
|
|
85
85
|
case "qrcode":
|
|
86
86
|
return `<div style="${base};background:repeating-conic-gradient(#111 0% 25%, #fff 0% 50%) 0 0/22% 22%"></div>`;
|
|
@@ -125,10 +125,10 @@ export function bouwDocumentHtml(layout, elementen, gegevens) {
|
|
|
125
125
|
const body = zichtbaar.map((e) => elementHtml(e, ctx)).join("");
|
|
126
126
|
const b = layout.orientatie === "landscape" ? layout.hoogte_mm : layout.breedte_mm;
|
|
127
127
|
const h = layout.orientatie === "landscape" ? layout.breedte_mm : layout.hoogte_mm;
|
|
128
|
-
return `<!doctype html><html lang="nl"><head><meta charset="utf-8"><title>${esc(layout.naam)}</title>
|
|
129
|
-
<style>@page{size:${b}mm ${h}mm;margin:0}
|
|
130
|
-
body{margin:0;background:#e5e7eb}
|
|
131
|
-
.pagina{position:relative;width:${b}mm;height:${h}mm;background:#fff;margin:0 auto;overflow:hidden}
|
|
132
|
-
@media print{body{background:#fff}}</style></head>
|
|
128
|
+
return `<!doctype html><html lang="nl"><head><meta charset="utf-8"><title>${esc(layout.naam)}</title>
|
|
129
|
+
<style>@page{size:${b}mm ${h}mm;margin:0}
|
|
130
|
+
body{margin:0;background:#e5e7eb}
|
|
131
|
+
.pagina{position:relative;width:${b}mm;height:${h}mm;background:#fff;margin:0 auto;overflow:hidden}
|
|
132
|
+
@media print{body{background:#fff}}</style></head>
|
|
133
133
|
<body><div class="pagina">${body}</div></body></html>`;
|
|
134
134
|
}
|
|
@@ -60,6 +60,18 @@ export interface UploadInput {
|
|
|
60
60
|
is_standaard: boolean;
|
|
61
61
|
}
|
|
62
62
|
export declare function bestaatHash(hash: string): Promise<LogoModel | null>;
|
|
63
|
+
export declare const OPSLAG_ONTBREEKT: string;
|
|
64
|
+
/** Vertaalt technische opslagfouten naar begrijpelijke Nederlandse tekst. */
|
|
65
|
+
export declare function vertaalOpslagFout(e: unknown): Error;
|
|
66
|
+
/**
|
|
67
|
+
* Controleert of de logo-opslag bestaat en bereikbaar is.
|
|
68
|
+
* Geeft `null` bij goed, anders een uitlegbare melding.
|
|
69
|
+
*/
|
|
70
|
+
export declare function controleerLogoOpslag(): Promise<string | null>;
|
|
71
|
+
export declare function useLogoOpslag(): {
|
|
72
|
+
opslagFout: string | null;
|
|
73
|
+
controleer: () => Promise<void>;
|
|
74
|
+
};
|
|
63
75
|
export declare function maakLogo(input: UploadInput): Promise<LogoModel>;
|
|
64
76
|
export declare function werkLogoBij(id: string, patch: Partial<LogoModel>): Promise<void>;
|
|
65
77
|
/** Vervangt het bestand van een bestaand logo — alle layouts volgen automatisch. */
|
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"logoLibrary.d.ts","sourceRoot":"","sources":["../../src/lib/logoLibrary.ts"],"names":[],"mappings":"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"}
|
|
@@ -123,6 +123,44 @@ export async function bestaatHash(hash) {
|
|
|
123
123
|
const { data } = await supabase.from("layout_logos").select("*").eq("hash", hash).maybeSingle();
|
|
124
124
|
return data ?? null;
|
|
125
125
|
}
|
|
126
|
+
export const OPSLAG_ONTBREEKT = `De logo-opslag ("${LOGO_BUCKET}") bestaat nog niet in deze shell. ` +
|
|
127
|
+
"Draai sql/print-schema.sql opnieuw in de Supabase-database van deze shell.";
|
|
128
|
+
/** Vertaalt technische opslagfouten naar begrijpelijke Nederlandse tekst. */
|
|
129
|
+
export function vertaalOpslagFout(e) {
|
|
130
|
+
const tekst = e instanceof Error ? e.message : String(e ?? "");
|
|
131
|
+
if (/bucket not found/i.test(tekst))
|
|
132
|
+
return new Error(OPSLAG_ONTBREEKT);
|
|
133
|
+
if (/row-level security|not authorized|403/i.test(tekst)) {
|
|
134
|
+
return new Error("Geen rechten op de logo-opslag. Draai sql/print-schema.sql opnieuw zodat de " +
|
|
135
|
+
"toegangsregels voor logo's zijn ingesteld.");
|
|
136
|
+
}
|
|
137
|
+
return e instanceof Error ? e : new Error("Opslagfout");
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Controleert of de logo-opslag bestaat en bereikbaar is.
|
|
141
|
+
* Geeft `null` bij goed, anders een uitlegbare melding.
|
|
142
|
+
*/
|
|
143
|
+
export async function controleerLogoOpslag() {
|
|
144
|
+
const { error } = await supabase.storage.from(LOGO_BUCKET).list("", { limit: 1 });
|
|
145
|
+
if (!error)
|
|
146
|
+
return null;
|
|
147
|
+
return vertaalOpslagFout(error).message;
|
|
148
|
+
}
|
|
149
|
+
export function useLogoOpslag() {
|
|
150
|
+
const [opslagFout, setOpslagFout] = useState(null);
|
|
151
|
+
const controleer = useCallback(async () => {
|
|
152
|
+
try {
|
|
153
|
+
setOpslagFout(await controleerLogoOpslag());
|
|
154
|
+
}
|
|
155
|
+
catch (e) {
|
|
156
|
+
setOpslagFout(vertaalOpslagFout(e).message);
|
|
157
|
+
}
|
|
158
|
+
}, []);
|
|
159
|
+
useEffect(() => {
|
|
160
|
+
void controleer();
|
|
161
|
+
}, [controleer]);
|
|
162
|
+
return { opslagFout, controleer };
|
|
163
|
+
}
|
|
126
164
|
async function uploadBestand(file) {
|
|
127
165
|
const ext = bestandstypeVan(file);
|
|
128
166
|
const pad = `${crypto.randomUUID()}.${ext}`;
|
|
@@ -131,7 +169,7 @@ async function uploadBestand(file) {
|
|
|
131
169
|
upsert: false,
|
|
132
170
|
});
|
|
133
171
|
if (error)
|
|
134
|
-
throw error;
|
|
172
|
+
throw vertaalOpslagFout(error);
|
|
135
173
|
return pad;
|
|
136
174
|
}
|
|
137
175
|
export async function maakLogo(input) {
|
|
@@ -640,56 +640,56 @@ export function renderPakbonDocument(config, order, opties = {}) {
|
|
|
640
640
|
const font = opties.lettertype ?? 'Arial, Helvetica, "Segoe UI", sans-serif';
|
|
641
641
|
const grootte = opties.lettergrootte ?? 8.5;
|
|
642
642
|
const body = renderPakbonBody(config, order, opties);
|
|
643
|
-
return `<!doctype html><html lang="nl"><head><meta charset="utf-8" />
|
|
644
|
-
<title>${esc(opties.titel ?? "Pakbon")}</title>
|
|
645
|
-
<style>
|
|
646
|
-
@page { size: ${b}mm ${h}mm; margin: ${marge}mm; }
|
|
647
|
-
* { box-sizing: border-box; }
|
|
648
|
-
html, body { margin: 0; padding: 0; }
|
|
649
|
-
body { font-family: ${font}; font-size: ${grootte}pt; color: #111827; line-height: 1.35; }
|
|
650
|
-
.blok { margin-bottom: 2mm; }
|
|
651
|
-
.sectitel { font-size: 90%; font-weight: 600; text-transform: uppercase; color: #6b7280; margin-bottom: 0.6mm; }
|
|
652
|
-
.vet { font-weight: 600; }
|
|
653
|
-
.kv { display: flex; justify-content: space-between; gap: 3mm; }
|
|
654
|
-
.kv .k { color: #6b7280; }
|
|
655
|
-
.kv .v { font-weight: 500; }
|
|
656
|
-
.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 6mm; }
|
|
657
|
-
.kader { border: 0.25mm solid #d1d5db; border-radius: 1mm; padding: 1.5mm; }
|
|
658
|
-
table.regels { width: 100%; border-collapse: collapse; }
|
|
659
|
-
table.regels.vast { table-layout: fixed; }
|
|
660
|
-
table.regels.vast td, table.regels.vast th { overflow-wrap: anywhere; }
|
|
661
|
-
table.regels th, table.regels td { padding: 0.7mm 1mm; vertical-align: top; }
|
|
662
|
-
table.regels th { font-size: 90%; text-transform: uppercase; color: #6b7280; font-weight: 600; text-align: left; }
|
|
663
|
-
.rand { border: 0.2mm solid #d1d5db; }
|
|
664
|
-
.onder { border-bottom: 0.2mm solid #d1d5db; }
|
|
665
|
-
table.regels.compact th, table.regels.compact td { padding: 0.3mm 0.8mm; }
|
|
666
|
-
tr.zebra td { background: #f3f4f6; }
|
|
667
|
-
.plijst { margin: 0; padding-left: 4mm; }
|
|
668
|
-
.groep { margin-bottom: 1.5mm; }
|
|
669
|
-
.regelrij { display: flex; gap: 2mm; }
|
|
670
|
-
.tweekolom { display: grid; grid-template-columns: 1fr 1fr; gap: 3mm; }
|
|
671
|
-
.karblok { margin-bottom: 2mm; }
|
|
672
|
-
.karblok.omkaderd { border: 0.25mm solid #d1d5db; border-radius: 1mm; padding: 1.5mm; }
|
|
673
|
-
.karkop { display: flex; justify-content: space-between; align-items: center; padding: 0.8mm 1.5mm; border-radius: 1mm; margin-bottom: 1mm; }
|
|
674
|
-
.bundel { display: inline-block; border: 0.3mm dashed #6b7280; border-radius: 1mm; padding: 0.4mm 1.5mm; margin-bottom: 1mm; font-weight: 700; text-transform: uppercase; letter-spacing: 0.2mm; font-size: 90%; }
|
|
675
|
-
.laag { margin-bottom: 1.5mm; }
|
|
676
|
-
.laagkop { display: flex; justify-content: space-between; font-weight: 500; border-bottom: 0.2mm solid #d1d5db; padding-bottom: 0.4mm; margin-bottom: 0.6mm; }
|
|
677
|
-
.laagkop.compact { border-bottom: none; }
|
|
678
|
-
.meta { display: flex; gap: 3mm; font-size: 88%; font-weight: 400; color: #4b5563; }
|
|
679
|
-
.totalen { display: flex; flex-wrap: wrap; gap: 5mm; border-top: 0.25mm solid #d1d5db; padding-top: 1.2mm; font-weight: 500; }
|
|
680
|
-
.paginavoet { position: fixed; bottom: 0; left: 0; right: 0; background: #fff; }
|
|
681
|
-
.handtekening { margin-top: 3mm; }
|
|
682
|
-
.lijnveld { margin-top: 4mm; border-bottom: 0.25mm solid #6b7280; padding-bottom: 3mm; }
|
|
683
|
-
.lijnveld.hoog { padding-bottom: 10mm; }
|
|
684
|
-
.lijn { border-top: 0.25mm solid #d1d5db; margin: 1.5mm 0; }
|
|
685
|
-
.balk { height: 1mm; background: #374151; margin: 1.5mm 0; }
|
|
686
|
-
.qr { border: 0.25mm dashed #9ca3af; }
|
|
687
|
-
.streepjes { width: 45mm; background: repeating-linear-gradient(to right, #111827 0 2px, transparent 2px 5px); }
|
|
688
|
-
.klein { font-size: 85%; color: #6b7280; }
|
|
689
|
-
.breekvoor { break-before: page; page-break-before: always; }
|
|
690
|
-
.heelhouden { break-inside: avoid; page-break-inside: avoid; }
|
|
691
|
-
img { max-width: 100%; }
|
|
692
|
-
</style></head>
|
|
643
|
+
return `<!doctype html><html lang="nl"><head><meta charset="utf-8" />
|
|
644
|
+
<title>${esc(opties.titel ?? "Pakbon")}</title>
|
|
645
|
+
<style>
|
|
646
|
+
@page { size: ${b}mm ${h}mm; margin: ${marge}mm; }
|
|
647
|
+
* { box-sizing: border-box; }
|
|
648
|
+
html, body { margin: 0; padding: 0; }
|
|
649
|
+
body { font-family: ${font}; font-size: ${grootte}pt; color: #111827; line-height: 1.35; }
|
|
650
|
+
.blok { margin-bottom: 2mm; }
|
|
651
|
+
.sectitel { font-size: 90%; font-weight: 600; text-transform: uppercase; color: #6b7280; margin-bottom: 0.6mm; }
|
|
652
|
+
.vet { font-weight: 600; }
|
|
653
|
+
.kv { display: flex; justify-content: space-between; gap: 3mm; }
|
|
654
|
+
.kv .k { color: #6b7280; }
|
|
655
|
+
.kv .v { font-weight: 500; }
|
|
656
|
+
.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 6mm; }
|
|
657
|
+
.kader { border: 0.25mm solid #d1d5db; border-radius: 1mm; padding: 1.5mm; }
|
|
658
|
+
table.regels { width: 100%; border-collapse: collapse; }
|
|
659
|
+
table.regels.vast { table-layout: fixed; }
|
|
660
|
+
table.regels.vast td, table.regels.vast th { overflow-wrap: anywhere; }
|
|
661
|
+
table.regels th, table.regels td { padding: 0.7mm 1mm; vertical-align: top; }
|
|
662
|
+
table.regels th { font-size: 90%; text-transform: uppercase; color: #6b7280; font-weight: 600; text-align: left; }
|
|
663
|
+
.rand { border: 0.2mm solid #d1d5db; }
|
|
664
|
+
.onder { border-bottom: 0.2mm solid #d1d5db; }
|
|
665
|
+
table.regels.compact th, table.regels.compact td { padding: 0.3mm 0.8mm; }
|
|
666
|
+
tr.zebra td { background: #f3f4f6; }
|
|
667
|
+
.plijst { margin: 0; padding-left: 4mm; }
|
|
668
|
+
.groep { margin-bottom: 1.5mm; }
|
|
669
|
+
.regelrij { display: flex; gap: 2mm; }
|
|
670
|
+
.tweekolom { display: grid; grid-template-columns: 1fr 1fr; gap: 3mm; }
|
|
671
|
+
.karblok { margin-bottom: 2mm; }
|
|
672
|
+
.karblok.omkaderd { border: 0.25mm solid #d1d5db; border-radius: 1mm; padding: 1.5mm; }
|
|
673
|
+
.karkop { display: flex; justify-content: space-between; align-items: center; padding: 0.8mm 1.5mm; border-radius: 1mm; margin-bottom: 1mm; }
|
|
674
|
+
.bundel { display: inline-block; border: 0.3mm dashed #6b7280; border-radius: 1mm; padding: 0.4mm 1.5mm; margin-bottom: 1mm; font-weight: 700; text-transform: uppercase; letter-spacing: 0.2mm; font-size: 90%; }
|
|
675
|
+
.laag { margin-bottom: 1.5mm; }
|
|
676
|
+
.laagkop { display: flex; justify-content: space-between; font-weight: 500; border-bottom: 0.2mm solid #d1d5db; padding-bottom: 0.4mm; margin-bottom: 0.6mm; }
|
|
677
|
+
.laagkop.compact { border-bottom: none; }
|
|
678
|
+
.meta { display: flex; gap: 3mm; font-size: 88%; font-weight: 400; color: #4b5563; }
|
|
679
|
+
.totalen { display: flex; flex-wrap: wrap; gap: 5mm; border-top: 0.25mm solid #d1d5db; padding-top: 1.2mm; font-weight: 500; }
|
|
680
|
+
.paginavoet { position: fixed; bottom: 0; left: 0; right: 0; background: #fff; }
|
|
681
|
+
.handtekening { margin-top: 3mm; }
|
|
682
|
+
.lijnveld { margin-top: 4mm; border-bottom: 0.25mm solid #6b7280; padding-bottom: 3mm; }
|
|
683
|
+
.lijnveld.hoog { padding-bottom: 10mm; }
|
|
684
|
+
.lijn { border-top: 0.25mm solid #d1d5db; margin: 1.5mm 0; }
|
|
685
|
+
.balk { height: 1mm; background: #374151; margin: 1.5mm 0; }
|
|
686
|
+
.qr { border: 0.25mm dashed #9ca3af; }
|
|
687
|
+
.streepjes { width: 45mm; background: repeating-linear-gradient(to right, #111827 0 2px, transparent 2px 5px); }
|
|
688
|
+
.klein { font-size: 85%; color: #6b7280; }
|
|
689
|
+
.breekvoor { break-before: page; page-break-before: always; }
|
|
690
|
+
.heelhouden { break-inside: avoid; page-break-inside: avoid; }
|
|
691
|
+
img { max-width: 100%; }
|
|
692
|
+
</style></head>
|
|
693
693
|
<body>${body}</body></html>`;
|
|
694
694
|
}
|
|
695
695
|
/** Handig voor testen: het document met de voorbeeldgegevens. */
|
|
@@ -18,11 +18,82 @@ export interface PrintDocumentResult {
|
|
|
18
18
|
layoutId: string;
|
|
19
19
|
printerId: string | null;
|
|
20
20
|
}
|
|
21
|
+
/** Fout wanneer een identieke aanvraag kort geleden al is aangemaakt. */
|
|
22
|
+
export declare class DubbeleAanvraagFout extends Error {
|
|
23
|
+
name: string;
|
|
24
|
+
constructor();
|
|
25
|
+
}
|
|
21
26
|
/**
|
|
22
27
|
* Zet een document in de printwachtrij. Bedoeld voor gebruik vanuit andere
|
|
23
28
|
* modules binnen dezelfde shell en database.
|
|
24
29
|
*/
|
|
25
30
|
export declare function printDocument(input: PrintDocumentInput): Promise<PrintDocumentResult>;
|
|
31
|
+
/**
|
|
32
|
+
* De printer die aan een documentsoort hangt: eerst de standaard (of nieuwste
|
|
33
|
+
* actieve) layout voor die soort, dan de printerkoppeling op die layout, anders
|
|
34
|
+
* de koppeling op papierformaat. Geeft `null` als er niets gekoppeld is.
|
|
35
|
+
*/
|
|
36
|
+
export declare function printerVoorDocumenttype(documenttype: DocumentType | string, papierformaat?: string): Promise<string | null>;
|
|
37
|
+
export interface PrintPdfInput {
|
|
38
|
+
/** Documentsoort, alleen voor overzicht en printerkeuze. */
|
|
39
|
+
documenttype: DocumentType | string;
|
|
40
|
+
documentnaam: string;
|
|
41
|
+
/** PDF als base64 (met of zonder data:-voorvoegsel) óf een webadres. */
|
|
42
|
+
pdfBase64?: string;
|
|
43
|
+
pdfUrl?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Optioneel. Zonder printer wordt de printer bepaald via de gekoppelde
|
|
46
|
+
* layout of het papierformaat van de documentsoort.
|
|
47
|
+
*/
|
|
48
|
+
printerId?: string;
|
|
49
|
+
kopieen?: number;
|
|
50
|
+
papierformaat?: string;
|
|
51
|
+
payload?: Record<string, unknown>;
|
|
52
|
+
isHerprint?: boolean;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Print een kant-en-klare PDF (klantsticker, Floriday-document, factuur van een
|
|
56
|
+
* externe dienst). De PDF gaat ongewijzigd naar de printer; er wordt geen
|
|
57
|
+
* layout gebruikt om het document op te bouwen.
|
|
58
|
+
*/
|
|
59
|
+
export declare function printPdf(input: PrintPdfInput): Promise<{
|
|
60
|
+
jobId: string;
|
|
61
|
+
}>;
|
|
62
|
+
export interface PrintHtmlInput {
|
|
63
|
+
documenttype: DocumentType | string;
|
|
64
|
+
documentnaam: string;
|
|
65
|
+
/** De opmaak die exact zo afgedrukt moet worden. */
|
|
66
|
+
html: string;
|
|
67
|
+
/** Verplicht: zonder layout kan de wachtrij zelf geen printer afleiden. */
|
|
68
|
+
printerId: string;
|
|
69
|
+
kopieen?: number;
|
|
70
|
+
payload?: Record<string, unknown>;
|
|
71
|
+
isHerprint?: boolean;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Print eigen opmaak. Er wordt bewust géén layout meegegeven: een gekoppelde
|
|
75
|
+
* layout wint altijd van meegestuurde HTML.
|
|
76
|
+
*/
|
|
77
|
+
export declare function printHtml(input: PrintHtmlInput): Promise<{
|
|
78
|
+
jobId: string;
|
|
79
|
+
}>;
|
|
80
|
+
/**
|
|
81
|
+
* De printer die bij een werkplek hoort. Een werkplek is de naam van de
|
|
82
|
+
* computer waarop het printprogramma draait; printers worden daaraan gekoppeld
|
|
83
|
+
* via hun locatie of systeemnaam.
|
|
84
|
+
*/
|
|
85
|
+
export declare function printerVoorWerkplek(werkplek: string, papierformaat?: string): Promise<string | null>;
|
|
86
|
+
export interface JobStatus {
|
|
87
|
+
id: string;
|
|
88
|
+
status: string;
|
|
89
|
+
documentnaam: string;
|
|
90
|
+
foutmelding: string | null;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Volgt één printopdracht live. Geeft een functie terug om te stoppen.
|
|
94
|
+
* Zo hoeft geen enkele andere module zelf een realtime-abonnement te bouwen.
|
|
95
|
+
*/
|
|
96
|
+
export declare function volgJobStatus(jobId: string, cb: (status: JobStatus) => void): () => void;
|
|
26
97
|
/** Alle beschikbare layouts voor een documentsoort (voor keuzelijsten elders). */
|
|
27
98
|
export declare function beschikbareLayouts(documenttype?: string): Promise<{
|
|
28
99
|
id: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"printApi.d.ts","sourceRoot":"","sources":["../../src/lib/printApi.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAIpD,MAAM,WAAW,kBAAkB;IACjC,uDAAuD;IACvD,YAAY,EAAE,YAAY,GAAG,MAAM,CAAC;IACpC,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;
|
|
1
|
+
{"version":3,"file":"printApi.d.ts","sourceRoot":"","sources":["../../src/lib/printApi.ts"],"names":[],"mappings":"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"}
|
package/dist-lib/lib/printApi.js
CHANGED
|
@@ -48,6 +48,29 @@ async function bepaalPrinter(documenttype, layoutId, papierformaat) {
|
|
|
48
48
|
}
|
|
49
49
|
return null;
|
|
50
50
|
}
|
|
51
|
+
/** Rij in de wachtrij zetten. Geeft null als de dubbelbeveiliging hem tegenhield. */
|
|
52
|
+
async function zetInWachtrij(rij) {
|
|
53
|
+
const { data, error } = await supabase
|
|
54
|
+
.from("print_jobs")
|
|
55
|
+
.insert({ status: "wachtend", ...rij })
|
|
56
|
+
.select("id")
|
|
57
|
+
.maybeSingle();
|
|
58
|
+
if (error)
|
|
59
|
+
throw error;
|
|
60
|
+
const id = data?.id ?? null;
|
|
61
|
+
// Direct laten verwerken; wacht niet op de cron-ronde. Mislukt dit, dan
|
|
62
|
+
// blijft de opdracht gewoon wachtend staan voor een volgende poging.
|
|
63
|
+
if (id)
|
|
64
|
+
void startWachtrijVerwerking();
|
|
65
|
+
return id;
|
|
66
|
+
}
|
|
67
|
+
/** Fout wanneer een identieke aanvraag kort geleden al is aangemaakt. */
|
|
68
|
+
export class DubbeleAanvraagFout extends Error {
|
|
69
|
+
constructor() {
|
|
70
|
+
super("Dit document stond al in de printwachtrij; de dubbele aanvraag is genegeerd.");
|
|
71
|
+
this.name = "DubbeleAanvraagFout";
|
|
72
|
+
}
|
|
73
|
+
}
|
|
51
74
|
/**
|
|
52
75
|
* Zet een document in de printwachtrij. Bedoeld voor gebruik vanuit andere
|
|
53
76
|
* modules binnen dezelfde shell en database.
|
|
@@ -58,9 +81,7 @@ export async function printDocument(input) {
|
|
|
58
81
|
throw new Error(`Geen layout gevonden voor documenttype "${input.documenttype}"`);
|
|
59
82
|
const printerId = input.printerId ??
|
|
60
83
|
(await bepaalPrinter(input.documenttype, layout.id, layout.papierformaat ?? null));
|
|
61
|
-
const
|
|
62
|
-
.from("print_jobs")
|
|
63
|
-
.insert({
|
|
84
|
+
const jobId = await zetInWachtrij({
|
|
64
85
|
layout_id: layout.id,
|
|
65
86
|
printer_id: printerId,
|
|
66
87
|
documenttype: input.documenttype,
|
|
@@ -68,16 +89,135 @@ export async function printDocument(input) {
|
|
|
68
89
|
kopieen: input.kopieen ?? 1,
|
|
69
90
|
payload: input.payload ?? {},
|
|
70
91
|
is_herprint: input.isHerprint ?? false,
|
|
71
|
-
|
|
92
|
+
});
|
|
93
|
+
if (!jobId)
|
|
94
|
+
throw new DubbeleAanvraagFout();
|
|
95
|
+
return { jobId, layoutId: layout.id, printerId };
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* De printer die aan een documentsoort hangt: eerst de standaard (of nieuwste
|
|
99
|
+
* actieve) layout voor die soort, dan de printerkoppeling op die layout, anders
|
|
100
|
+
* de koppeling op papierformaat. Geeft `null` als er niets gekoppeld is.
|
|
101
|
+
*/
|
|
102
|
+
export async function printerVoorDocumenttype(documenttype, papierformaat) {
|
|
103
|
+
const layout = await bepaalLayout(documenttype);
|
|
104
|
+
if (!layout) {
|
|
105
|
+
if (!papierformaat)
|
|
106
|
+
return null;
|
|
107
|
+
const { data } = await supabase
|
|
108
|
+
.from("document_formaat_printers")
|
|
109
|
+
.select("printer_id")
|
|
110
|
+
.eq("documenttype", documenttype)
|
|
111
|
+
.eq("formaat_code", papierformaat)
|
|
112
|
+
.maybeSingle();
|
|
113
|
+
return data?.printer_id ?? null;
|
|
114
|
+
}
|
|
115
|
+
return bepaalPrinter(documenttype, layout.id, papierformaat ?? layout.papierformaat ?? null);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Print een kant-en-klare PDF (klantsticker, Floriday-document, factuur van een
|
|
119
|
+
* externe dienst). De PDF gaat ongewijzigd naar de printer; er wordt geen
|
|
120
|
+
* layout gebruikt om het document op te bouwen.
|
|
121
|
+
*/
|
|
122
|
+
export async function printPdf(input) {
|
|
123
|
+
const base64 = (input.pdfBase64 ?? "").replace(/^data:application\/pdf;base64,/i, "").trim();
|
|
124
|
+
if (!base64 && !input.pdfUrl)
|
|
125
|
+
throw new Error("Geef een PDF mee via pdfBase64 of pdfUrl.");
|
|
126
|
+
const printerId = input.printerId ??
|
|
127
|
+
(await printerVoorDocumenttype(input.documenttype, input.papierformaat));
|
|
128
|
+
if (!printerId) {
|
|
129
|
+
throw new Error(`Geen printer gekoppeld voor ${input.documenttype} — stel dit in bij Layouts en printers.`);
|
|
130
|
+
}
|
|
131
|
+
const jobId = await zetInWachtrij({
|
|
132
|
+
layout_id: null,
|
|
133
|
+
printer_id: printerId,
|
|
134
|
+
documenttype: input.documenttype,
|
|
135
|
+
documentnaam: input.documentnaam,
|
|
136
|
+
kopieen: input.kopieen ?? 1,
|
|
137
|
+
payload: input.payload ?? {},
|
|
138
|
+
is_herprint: input.isHerprint ?? false,
|
|
139
|
+
...(base64 ? { pdf_base64: base64 } : {}),
|
|
140
|
+
...(input.pdfUrl ? { pdf_url: input.pdfUrl } : {}),
|
|
141
|
+
});
|
|
142
|
+
if (!jobId)
|
|
143
|
+
throw new DubbeleAanvraagFout();
|
|
144
|
+
return { jobId };
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Print eigen opmaak. Er wordt bewust géén layout meegegeven: een gekoppelde
|
|
148
|
+
* layout wint altijd van meegestuurde HTML.
|
|
149
|
+
*/
|
|
150
|
+
export async function printHtml(input) {
|
|
151
|
+
if (!input.html || input.html.trim().length < 40)
|
|
152
|
+
throw new Error("Er is geen opmaak meegegeven.");
|
|
153
|
+
if (!input.printerId)
|
|
154
|
+
throw new Error("Kies een printer: een HTML-opdracht heeft geen layout.");
|
|
155
|
+
const jobId = await zetInWachtrij({
|
|
156
|
+
layout_id: null,
|
|
157
|
+
printer_id: input.printerId,
|
|
158
|
+
documenttype: input.documenttype,
|
|
159
|
+
documentnaam: input.documentnaam,
|
|
160
|
+
kopieen: input.kopieen ?? 1,
|
|
161
|
+
payload: input.payload ?? {},
|
|
162
|
+
is_herprint: input.isHerprint ?? false,
|
|
163
|
+
render_html: input.html,
|
|
164
|
+
});
|
|
165
|
+
if (!jobId)
|
|
166
|
+
throw new DubbeleAanvraagFout();
|
|
167
|
+
return { jobId };
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* De printer die bij een werkplek hoort. Een werkplek is de naam van de
|
|
171
|
+
* computer waarop het printprogramma draait; printers worden daaraan gekoppeld
|
|
172
|
+
* via hun locatie of systeemnaam.
|
|
173
|
+
*/
|
|
174
|
+
export async function printerVoorWerkplek(werkplek, papierformaat) {
|
|
175
|
+
const naam = (werkplek ?? "").trim();
|
|
176
|
+
if (!naam)
|
|
177
|
+
return null;
|
|
178
|
+
const { data } = await supabase
|
|
179
|
+
.from("printers")
|
|
180
|
+
.select("id, naam, locatie, systeemnaam, papierformaat, actief")
|
|
181
|
+
.eq("actief", true)
|
|
182
|
+
.order("naam");
|
|
183
|
+
const kandidaten = arr(data).filter((p) => (p.locatie ?? "").trim().toLowerCase() === naam.toLowerCase() ||
|
|
184
|
+
(p.systeemnaam ?? "").trim().toLowerCase() === naam.toLowerCase());
|
|
185
|
+
if (!kandidaten.length)
|
|
186
|
+
return null;
|
|
187
|
+
if (papierformaat) {
|
|
188
|
+
const match = kandidaten.find((p) => p.papierformaat === papierformaat);
|
|
189
|
+
if (match)
|
|
190
|
+
return match.id;
|
|
191
|
+
}
|
|
192
|
+
return kandidaten[0].id;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Volgt één printopdracht live. Geeft een functie terug om te stoppen.
|
|
196
|
+
* Zo hoeft geen enkele andere module zelf een realtime-abonnement te bouwen.
|
|
197
|
+
*/
|
|
198
|
+
export function volgJobStatus(jobId, cb) {
|
|
199
|
+
let gestopt = false;
|
|
200
|
+
const lees = async () => {
|
|
201
|
+
const { data } = await supabase
|
|
202
|
+
.from("print_jobs")
|
|
203
|
+
.select("id, status, documentnaam, foutmelding")
|
|
204
|
+
.eq("id", jobId)
|
|
205
|
+
.maybeSingle();
|
|
206
|
+
if (data && !gestopt)
|
|
207
|
+
cb(data);
|
|
208
|
+
};
|
|
209
|
+
void lees();
|
|
210
|
+
const kanaal = supabase
|
|
211
|
+
.channel(`print_job_${jobId}`)
|
|
212
|
+
.on("postgres_changes", { event: "UPDATE", schema: "public", table: "print_jobs", filter: `id=eq.${jobId}` }, (payload) => {
|
|
213
|
+
if (!gestopt)
|
|
214
|
+
cb(payload.new);
|
|
72
215
|
})
|
|
73
|
-
.
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
// blijft de opdracht gewoon wachtend staan voor een volgende poging.
|
|
79
|
-
void startWachtrijVerwerking();
|
|
80
|
-
return { jobId: data.id, layoutId: layout.id, printerId };
|
|
216
|
+
.subscribe();
|
|
217
|
+
return () => {
|
|
218
|
+
gestopt = true;
|
|
219
|
+
void supabase.removeChannel(kanaal);
|
|
220
|
+
};
|
|
81
221
|
}
|
|
82
222
|
/** Zet de wachtrijverwerking op de achtergrond in gang (best effort). */
|
|
83
223
|
async function startWachtrijVerwerking() {
|