@flowselections/layout-maker 1.38.4 → 1.45.9
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/AfleverbriefBuilderPage.d.ts +10 -0
- package/dist-lib/components/AfleverbriefBuilderPage.d.ts.map +1 -0
- package/dist-lib/components/AfleverbriefBuilderPage.js +101 -0
- package/dist-lib/components/BlokOntwerperPage.d.ts.map +1 -1
- package/dist-lib/components/BlokOntwerperPage.js +8 -3
- package/dist-lib/components/ComputersLijst.d.ts.map +1 -1
- package/dist-lib/components/ComputersLijst.js +1 -1
- package/dist-lib/components/FustKolomVolgorde.d.ts +11 -0
- package/dist-lib/components/FustKolomVolgorde.d.ts.map +1 -0
- package/dist-lib/components/FustKolomVolgorde.js +52 -0
- package/dist-lib/components/LayoutsPage.d.ts.map +1 -1
- package/dist-lib/components/LayoutsPage.js +10 -9
- package/dist-lib/components/PakbonBuilderPage.d.ts.map +1 -1
- package/dist-lib/components/PakbonBuilderPage.js +32 -14
- package/dist-lib/components/PakbonPreview.d.ts.map +1 -1
- package/dist-lib/components/PakbonPreview.js +21 -14
- package/dist-lib/components/PakbonSectiesPanel.d.ts +4 -2
- package/dist-lib/components/PakbonSectiesPanel.d.ts.map +1 -1
- package/dist-lib/components/PakbonSectiesPanel.js +5 -3
- package/dist-lib/components/PdfMapToestemmingBanner.d.ts +2 -1
- package/dist-lib/components/PdfMapToestemmingBanner.d.ts.map +1 -1
- package/dist-lib/components/PdfMapToestemmingBanner.js +124 -18
- package/dist-lib/components/PdfVoorbeeld.d.ts +20 -0
- package/dist-lib/components/PdfVoorbeeld.d.ts.map +1 -0
- package/dist-lib/components/PdfVoorbeeld.js +95 -0
- package/dist-lib/components/PrintProgrammaUitleg.d.ts.map +1 -1
- package/dist-lib/components/PrintProgrammaUitleg.js +1 -1
- package/dist-lib/components/PrintQueuePage.d.ts.map +1 -1
- package/dist-lib/components/PrintQueuePage.js +81 -43
- package/dist-lib/components/PrintplekDetailPage.d.ts.map +1 -1
- package/dist-lib/components/PrintplekDetailPage.js +2 -2
- package/dist-lib/components/PrintplekWizard.d.ts.map +1 -1
- package/dist-lib/components/PrintplekWizard.js +6 -2
- package/dist-lib/components/ProductiebonBuilderPage.d.ts.map +1 -1
- package/dist-lib/components/ProductiebonBuilderPage.js +13 -7
- package/dist-lib/index.d.ts +13 -5
- package/dist-lib/index.d.ts.map +1 -1
- package/dist-lib/index.js +10 -5
- package/dist-lib/integrations/supabase/auth-middleware.d.ts +2280 -198
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.d.ts +2280 -198
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.js +1 -1
- package/dist-lib/integrations/supabase/moduleClient.d.ts +2280 -198
- package/dist-lib/integrations/supabase/moduleClient.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +2306 -182
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.js +1 -0
- package/dist-lib/lib/aiLayout.functions.d.ts +2280 -198
- package/dist-lib/lib/aiLayout.functions.d.ts.map +1 -1
- package/dist-lib/lib/documentVoorbeeld.functions.d.ts +23 -0
- package/dist-lib/lib/documentVoorbeeld.functions.d.ts.map +1 -0
- package/dist-lib/lib/documentVoorbeeld.functions.js +37 -0
- package/dist-lib/lib/fontMetrics.d.ts +15 -0
- package/dist-lib/lib/fontMetrics.d.ts.map +1 -0
- package/dist-lib/lib/fontMetrics.js +118 -0
- package/dist-lib/lib/htmlNaarPdf.server.d.ts +2 -2
- package/dist-lib/lib/htmlNaarPdf.server.d.ts.map +1 -1
- package/dist-lib/lib/htmlNaarPdf.server.js +2 -1
- package/dist-lib/lib/htmlPdf.server.d.ts +11 -0
- package/dist-lib/lib/htmlPdf.server.d.ts.map +1 -1
- package/dist-lib/lib/htmlPdf.server.js +118 -15
- package/dist-lib/lib/orderData.server.d.ts.map +1 -1
- package/dist-lib/lib/orderData.server.js +43 -16
- package/dist-lib/lib/pakbonBarcodeVerzoek.d.ts +39 -0
- package/dist-lib/lib/pakbonBarcodeVerzoek.d.ts.map +1 -0
- package/dist-lib/lib/pakbonBarcodeVerzoek.js +80 -0
- package/dist-lib/lib/pakbonBuilder.d.ts +62 -3
- package/dist-lib/lib/pakbonBuilder.d.ts.map +1 -1
- package/dist-lib/lib/pakbonBuilder.js +386 -50
- package/dist-lib/lib/pakbonContent.d.ts +41 -0
- package/dist-lib/lib/pakbonContent.d.ts.map +1 -0
- package/dist-lib/lib/pakbonContent.js +668 -0
- package/dist-lib/lib/pakbonDocument.d.ts +199 -0
- package/dist-lib/lib/pakbonDocument.d.ts.map +1 -0
- package/dist-lib/lib/pakbonDocument.js +735 -0
- package/dist-lib/lib/pakbonHtml.d.ts +7 -0
- package/dist-lib/lib/pakbonHtml.d.ts.map +1 -1
- package/dist-lib/lib/pakbonHtml.js +89 -73
- package/dist-lib/lib/pakbonPresentation.d.ts +8 -0
- package/dist-lib/lib/pakbonPresentation.d.ts.map +1 -0
- package/dist-lib/lib/pakbonPresentation.js +31 -0
- package/dist-lib/lib/pakbonScan.d.ts.map +1 -1
- package/dist-lib/lib/pakbonScan.js +20 -38
- package/dist-lib/lib/pdfJobSaver.d.ts +10 -6
- package/dist-lib/lib/pdfJobSaver.d.ts.map +1 -1
- package/dist-lib/lib/pdfJobSaver.js +302 -99
- package/dist-lib/lib/pdfMap.d.ts +37 -2
- package/dist-lib/lib/pdfMap.d.ts.map +1 -1
- package/dist-lib/lib/pdfMap.js +120 -7
- package/dist-lib/lib/pdfOpslagStatus.d.ts +23 -0
- package/dist-lib/lib/pdfOpslagStatus.d.ts.map +1 -0
- package/dist-lib/lib/pdfOpslagStatus.js +74 -0
- package/dist-lib/lib/printApi.d.ts +31 -0
- package/dist-lib/lib/printApi.d.ts.map +1 -1
- package/dist-lib/lib/printApi.js +62 -1
- package/dist-lib/lib/printQueue.server.d.ts +6 -0
- package/dist-lib/lib/printQueue.server.d.ts.map +1 -1
- package/dist-lib/lib/printQueue.server.js +450 -94
- package/dist-lib/lib/printService.functions.d.ts +8857 -529
- package/dist-lib/lib/printService.functions.d.ts.map +1 -1
- package/dist-lib/lib/profielHtml.d.ts.map +1 -1
- package/dist-lib/lib/profielHtml.js +8 -1
- package/dist-lib/lib/useDocumentData.d.ts +8 -0
- package/dist-lib/lib/useDocumentData.d.ts.map +1 -1
- package/dist-lib/lib/useDocumentData.js +1 -1
- package/dist-lib/lib/voorbeeldPrint.d.ts +3 -0
- package/dist-lib/lib/voorbeeldPrint.d.ts.map +1 -1
- package/dist-lib/lib/voorbeeldPrint.js +65 -17
- package/package.json +9 -2
|
@@ -10,16 +10,63 @@ import { Button, toast } from "@flowselections/core";
|
|
|
10
10
|
import { FolderCheck, FolderOpen, ShieldAlert, ShieldCheck } from "lucide-react";
|
|
11
11
|
import { usePrinters } from "../lib/useDocumentData.js";
|
|
12
12
|
import { zorgVoorPdfPrinter } from "../lib/pdfPrinter.js";
|
|
13
|
-
import {
|
|
14
|
-
|
|
13
|
+
import { supabase } from "../lib/supabaseClient.js";
|
|
14
|
+
import { draaitInIframe, herstelPdfMapToestemming, kiesPdfMap, mapKiezenMogelijk, openInEigenTabblad, lokalePdfPrintplek, pdfMapKoppeling, pdfMapNaam, pdfMapToestemming, } from "../lib/pdfMap.js";
|
|
15
|
+
export function PdfMapToestemmingBanner({ alleenActieNodig = false, zwevend = false, printplekId, } = {}) {
|
|
15
16
|
const { printers, reload } = usePrinters();
|
|
16
17
|
const pdfPrinter = printers.find((p) => p.afdrukmethode === "pdf");
|
|
18
|
+
// De balk is alleen nuttig als "Opslaan als PDF" nog ergens als
|
|
19
|
+
// afdrukmethode is ingesteld (printplek-regel, layoutkoppeling of
|
|
20
|
+
// formaatregel). Zodra nergens meer een PDF-printer is gekozen, verdwijnt
|
|
21
|
+
// de balk en wordt de virtuele printer ook niet meer vanzelf aangemaakt.
|
|
22
|
+
const [inGebruik, setInGebruik] = useState(null);
|
|
23
|
+
const meetGebruik = useCallback(async (printerId) => {
|
|
24
|
+
const tabellen = [
|
|
25
|
+
supabase.from("document_printplek_printers").select("print_plek_id").eq("printer_id", printerId).limit(1),
|
|
26
|
+
supabase.from("printer_mappings").select("layout_id").eq("printer_id", printerId).limit(1),
|
|
27
|
+
supabase.from("document_formaat_printers").select("documenttype").eq("printer_id", printerId).limit(1),
|
|
28
|
+
];
|
|
29
|
+
try {
|
|
30
|
+
const resultaten = await Promise.all(tabellen);
|
|
31
|
+
return resultaten.some((r) => Array.isArray(r.data) && r.data.length > 0);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// Bij een leesfout liever tonen dan stil verbergen.
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
}, []);
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (!pdfPrinter) {
|
|
40
|
+
setInGebruik(null);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
let actief = true;
|
|
44
|
+
void meetGebruik(pdfPrinter.id).then((gebruikt) => {
|
|
45
|
+
if (actief)
|
|
46
|
+
setInGebruik(gebruikt);
|
|
47
|
+
});
|
|
48
|
+
return () => {
|
|
49
|
+
actief = false;
|
|
50
|
+
};
|
|
51
|
+
}, [pdfPrinter?.id, meetGebruik]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
17
52
|
const [naam, setNaam] = useState(null);
|
|
18
53
|
const [toestand, setToestand] = useState("laden");
|
|
19
|
-
|
|
20
|
-
|
|
54
|
+
const [gekoppeldePrintplek, setGekoppeldePrintplek] = useState(null);
|
|
55
|
+
const [persistent, setPersistent] = useState(null);
|
|
56
|
+
const [instellingOpen, setInstellingOpen] = useState(false);
|
|
57
|
+
const [aangevraagdePrintplek, setAangevraagdePrintplek] = useState(null);
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
const params = new URLSearchParams(window.location.search);
|
|
60
|
+
const gevraagd = params.get("pdf-printplek")?.trim() || null;
|
|
61
|
+
setInstellingOpen(params.get("pdf-map-instellen") === "1");
|
|
62
|
+
setAangevraagdePrintplek(gevraagd);
|
|
63
|
+
void lokalePdfPrintplek().then((lokaal) => setGekoppeldePrintplek(gevraagd ?? lokaal));
|
|
64
|
+
}, []);
|
|
65
|
+
// Maak de virtuele PDF-printer alleen aan wanneer expliciet om het instellen
|
|
66
|
+
// van de map gevraagd wordt (?pdf-map-instellen=1). Zonder die vraag én
|
|
67
|
+
// zonder bestaande PDF-printer is er niets om toestemming voor te geven.
|
|
21
68
|
useEffect(() => {
|
|
22
|
-
if (pdfPrinter)
|
|
69
|
+
if (pdfPrinter || !instellingOpen)
|
|
23
70
|
return;
|
|
24
71
|
let actief = true;
|
|
25
72
|
void (async () => {
|
|
@@ -35,7 +82,7 @@ export function PdfMapToestemmingBanner({ alleenActieNodig = false, zwevend = fa
|
|
|
35
82
|
return () => {
|
|
36
83
|
actief = false;
|
|
37
84
|
};
|
|
38
|
-
}, [pdfPrinter, reload]);
|
|
85
|
+
}, [pdfPrinter, instellingOpen, reload]);
|
|
39
86
|
const laad = useCallback(async () => {
|
|
40
87
|
if (!pdfPrinter) {
|
|
41
88
|
setNaam(null);
|
|
@@ -44,7 +91,26 @@ export function PdfMapToestemmingBanner({ alleenActieNodig = false, zwevend = fa
|
|
|
44
91
|
}
|
|
45
92
|
setNaam(await pdfMapNaam(pdfPrinter.id));
|
|
46
93
|
setToestand(await pdfMapToestemming(pdfPrinter.id));
|
|
47
|
-
|
|
94
|
+
const koppeling = await pdfMapKoppeling();
|
|
95
|
+
let doelPrintplek = printplekId ?? aangevraagdePrintplek ?? koppeling?.printPlekId ?? null;
|
|
96
|
+
if (!doelPrintplek) {
|
|
97
|
+
const { data } = await supabase
|
|
98
|
+
.from("document_printplek_printers")
|
|
99
|
+
.select("print_plek_id")
|
|
100
|
+
.eq("printer_id", pdfPrinter.id);
|
|
101
|
+
const ids = [
|
|
102
|
+
...new Set((Array.isArray(data) ? data : [])
|
|
103
|
+
.map((rij) => String(rij.print_plek_id ?? "").trim())
|
|
104
|
+
.filter(Boolean)),
|
|
105
|
+
];
|
|
106
|
+
doelPrintplek = ids.length === 1 ? ids[0] ?? null : null;
|
|
107
|
+
}
|
|
108
|
+
setGekoppeldePrintplek(doelPrintplek);
|
|
109
|
+
setPersistent(koppeling?.persistent ?? null);
|
|
110
|
+
// Opnieuw meten of PDF nog ergens is ingesteld: kiest de gebruiker bij
|
|
111
|
+
// alle documenten een echte printer, dan verdwijnt de balk direct.
|
|
112
|
+
setInGebruik(await meetGebruik(pdfPrinter.id));
|
|
113
|
+
}, [aangevraagdePrintplek, meetGebruik, pdfPrinter, printplekId]);
|
|
48
114
|
useEffect(() => {
|
|
49
115
|
void laad();
|
|
50
116
|
}, [laad]);
|
|
@@ -58,14 +124,33 @@ export function PdfMapToestemmingBanner({ alleenActieNodig = false, zwevend = fa
|
|
|
58
124
|
document.removeEventListener("visibilitychange", h);
|
|
59
125
|
};
|
|
60
126
|
}, [laad]);
|
|
61
|
-
|
|
127
|
+
// In een iframe (o.a. de Lovable-preview) heeft de balk geen nut: de
|
|
128
|
+
// mappenverkenner werkt daar niet en de gebruiker kan alleen via "Open in
|
|
129
|
+
// eigen tabblad" verder. De balk daar niet tonen houdt de preview schoon;
|
|
130
|
+
// in een eigen tabblad blijft hij volledig zichtbaar.
|
|
131
|
+
const inIframe = draaitInIframe();
|
|
132
|
+
if (inIframe)
|
|
62
133
|
return null;
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
|
|
66
|
-
if (
|
|
134
|
+
// Is "Opslaan als PDF" nergens meer ingesteld (geen printplek-, layout- of
|
|
135
|
+
// formaatregel met deze printer), dan is de balk overbodig en verbergen we
|
|
136
|
+
// hem volledig. Alleen bij een expliciete instelvraag blijft hij zichtbaar.
|
|
137
|
+
if (!instellingOpen) {
|
|
138
|
+
if (!pdfPrinter)
|
|
139
|
+
return null;
|
|
140
|
+
if (inGebruik === false)
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
// De balk is op dit punt alleen nog zichtbaar als "Opslaan als PDF"
|
|
144
|
+
// daadwerkelijk ergens is ingesteld (of de gebruiker expliciet aan het
|
|
145
|
+
// instellen is); anders is hierboven al `null` teruggegeven.
|
|
146
|
+
const vereistePrintplek = printplekId ?? aangevraagdePrintplek ?? gekoppeldePrintplek;
|
|
147
|
+
const inOrde = !!pdfPrinter &&
|
|
148
|
+
toestand === "granted" &&
|
|
149
|
+
!!naam &&
|
|
150
|
+
!!gekoppeldePrintplek &&
|
|
151
|
+
(!vereistePrintplek || gekoppeldePrintplek === vereistePrintplek);
|
|
152
|
+
if (alleenActieNodig && !instellingOpen && (!pdfPrinter ? false : toestand === "laden" || inOrde))
|
|
67
153
|
return null;
|
|
68
|
-
const inIframe = draaitInIframe();
|
|
69
154
|
const ondersteund = mapKiezenMogelijk();
|
|
70
155
|
const geefToestemming = async () => {
|
|
71
156
|
if (!pdfPrinter)
|
|
@@ -94,13 +179,14 @@ export function PdfMapToestemmingBanner({ alleenActieNodig = false, zwevend = fa
|
|
|
94
179
|
description: "Open de app in een eigen tabblad om de mappenverkenner te gebruiken.",
|
|
95
180
|
action: {
|
|
96
181
|
label: "Open in eigen tabblad",
|
|
97
|
-
onClick: openInEigenTabblad,
|
|
182
|
+
onClick: () => openInEigenTabblad(printplekId ?? gekoppeldePrintplek ?? undefined),
|
|
98
183
|
},
|
|
99
184
|
duration: 15000,
|
|
100
185
|
});
|
|
101
186
|
return;
|
|
102
187
|
}
|
|
103
|
-
const
|
|
188
|
+
const doelPrintplek = printplekId ?? gekoppeldePrintplek ?? undefined;
|
|
189
|
+
const uitkomst = await kiesPdfMap(pdfPrinter.id, doelPrintplek);
|
|
104
190
|
if (uitkomst.status === "gekozen") {
|
|
105
191
|
toast.success("Map gekozen", { description: `PDF's worden opgeslagen in “${uitkomst.naam}”.` });
|
|
106
192
|
await laad();
|
|
@@ -113,7 +199,10 @@ export function PdfMapToestemmingBanner({ alleenActieNodig = false, zwevend = fa
|
|
|
113
199
|
else if (uitkomst.status === "iframe-geblokkeerd") {
|
|
114
200
|
toast.error("Map kiezen werkt niet in een iframe", {
|
|
115
201
|
description: "Open de app in een eigen tabblad.",
|
|
116
|
-
action: {
|
|
202
|
+
action: {
|
|
203
|
+
label: "Open in eigen tabblad",
|
|
204
|
+
onClick: () => openInEigenTabblad(printplekId ?? gekoppeldePrintplek ?? undefined),
|
|
205
|
+
},
|
|
117
206
|
duration: 15000,
|
|
118
207
|
});
|
|
119
208
|
}
|
|
@@ -121,12 +210,27 @@ export function PdfMapToestemmingBanner({ alleenActieNodig = false, zwevend = fa
|
|
|
121
210
|
toast.error("Map kiezen is mislukt", { description: uitkomst.melding });
|
|
122
211
|
}
|
|
123
212
|
};
|
|
124
|
-
const icoon =
|
|
213
|
+
const icoon = inOrde
|
|
125
214
|
? ShieldCheck
|
|
126
215
|
: toestand === "denied"
|
|
127
216
|
? ShieldAlert
|
|
128
217
|
: FolderOpen;
|
|
129
218
|
const Icoon = icoon;
|
|
219
|
+
if (!pdfPrinter) {
|
|
220
|
+
return (_jsxs("div", { role: "status", "aria-live": "polite", className: `${zwevend ? "fixed inset-x-4 top-4 z-[100] mx-auto max-w-4xl shadow-lg" : ""} flex flex-wrap items-center justify-between gap-3 rounded-lg border border-amber-300/60 bg-amber-50 p-3 dark:border-amber-700/60 dark:bg-amber-950/30`, children: [_jsxs("div", { className: "flex items-center gap-2 text-sm", children: [_jsx(ShieldAlert, { className: "h-4 w-4 text-amber-600 dark:text-amber-400" }), _jsx("span", { className: "font-medium", children: "PDF-maptoestemming" }), _jsx("span", { className: "text-muted-foreground", children: "De virtuele \u201COpslaan als PDF\u201D-printer wordt aangemaakt of kon nog niet worden geladen." })] }), _jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
|
|
221
|
+
void (async () => {
|
|
222
|
+
try {
|
|
223
|
+
await zorgVoorPdfPrinter();
|
|
224
|
+
await reload(true);
|
|
225
|
+
}
|
|
226
|
+
catch (fout) {
|
|
227
|
+
toast.error("PDF-printer kon niet worden aangemaakt", {
|
|
228
|
+
description: fout instanceof Error ? fout.message : undefined,
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
})();
|
|
232
|
+
}, children: [_jsx(FolderOpen, { className: "mr-2 h-4 w-4" }), " PDF-printer aanmaken"] })] }));
|
|
233
|
+
}
|
|
130
234
|
return (_jsxs("div", { role: "status", "aria-live": "polite", className: `${inOrde
|
|
131
235
|
? "border-emerald-300/60 bg-emerald-50 dark:border-emerald-700/60 dark:bg-emerald-950/30"
|
|
132
236
|
: "border-amber-300/60 bg-amber-50 dark:border-amber-700/60 dark:bg-amber-950/30"} ${zwevend
|
|
@@ -135,5 +239,7 @@ export function PdfMapToestemmingBanner({ alleenActieNodig = false, zwevend = fa
|
|
|
135
239
|
? "h-4 w-4 text-emerald-600 dark:text-emerald-400"
|
|
136
240
|
: "h-4 w-4 text-amber-600 dark:text-amber-400" }), _jsx("span", { className: "font-medium", children: "PDF-maptoestemming" }), _jsxs("span", { className: "text-muted-foreground", children: [naam
|
|
137
241
|
? `Map “${naam}” — toestemming ${toestand === "granted" ? "verleend" : "vereist vernieuwen"}`
|
|
138
|
-
: "Nog geen map gekozen op deze computer", !ondersteund ? " (browser ondersteunt geen mapkeuze)" : ""
|
|
242
|
+
: "Nog geen map gekozen op deze computer", !ondersteund ? " (browser ondersteunt geen mapkeuze)" : "", inIframe
|
|
243
|
+
? " — de preview draait in een iframe; de mapkeuze geldt per webadres en moet hier opnieuw worden gezet"
|
|
244
|
+
: "", !inIframe && gekoppeldePrintplek ? " — gekoppeld aan deze printplek" : "", !inIframe && persistent === false ? " — browseropslag is niet permanent gegarandeerd" : ""] })] }), _jsxs("div", { className: "flex gap-2", children: [naam ? (_jsxs(Button, { size: "sm", variant: inOrde ? "outline" : "default", onClick: () => void geefToestemming(), children: [_jsx(FolderCheck, { className: "mr-2 h-4 w-4" }), inOrde ? "Toestemming controleren" : "Maptoestemming geven"] })) : null, _jsxs(Button, { size: "sm", variant: "outline", onClick: () => void kiesNieuweMap(), children: [_jsx(FolderOpen, { className: "mr-2 h-4 w-4" }), " ", naam ? "Andere map kiezen" : "Map kiezen"] }), inIframe ? (_jsx(Button, { size: "sm", variant: "outline", onClick: () => openInEigenTabblad(printplekId ?? gekoppeldePrintplek ?? undefined), children: "Open in eigen tabblad" })) : null] })] }));
|
|
139
245
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
/** Print-HTML, exact zoals die ook naar de printwachtrij gaat. */
|
|
3
|
+
html: string;
|
|
4
|
+
breedteMm: number;
|
|
5
|
+
hoogteMm: number;
|
|
6
|
+
margeMm: number;
|
|
7
|
+
onControle?: (status: "controleren" | "gereed" | "afwijking", fout?: string) => void;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Toont het voorbeeld altijd: de print-HTML wordt direct getoond op ware
|
|
11
|
+
* papiergrootte (werkt ook binnen een shell-iframe, waar Chrome ingesloten
|
|
12
|
+
* PDF's blokkeert). De echte print-PDF blijft opvraagbaar in een eigen tabblad.
|
|
13
|
+
*
|
|
14
|
+
* Pagina's stapelen verticaal; het hele kader wordt met een CSS-schaling op
|
|
15
|
+
* de beschikbare breedte passend gemaakt, zodat het document altijd volledig
|
|
16
|
+
* zichtbaar is (met verticaal scrollen bij meerdere pagina's).
|
|
17
|
+
*/
|
|
18
|
+
export declare function PdfVoorbeeld({ html, breedteMm, hoogteMm, margeMm, onControle }: Props): import("react").JSX.Element;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=PdfVoorbeeld.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PdfVoorbeeld.d.ts","sourceRoot":"","sources":["../../src/components/PdfVoorbeeld.tsx"],"names":[],"mappings":"AAKA,UAAU,KAAK;IACb,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,GAAG,QAAQ,GAAG,WAAW,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CACtF;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,KAAK,+BAyGrF"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef, useState } from "react";
|
|
3
|
+
import { Button } from "@flowselections/core";
|
|
4
|
+
import { AlertTriangle, ExternalLink, Loader2 } from "lucide-react";
|
|
5
|
+
import { maakVoorbeeldPdf } from "../lib/documentVoorbeeld.functions.js";
|
|
6
|
+
/**
|
|
7
|
+
* Toont het voorbeeld altijd: de print-HTML wordt direct getoond op ware
|
|
8
|
+
* papiergrootte (werkt ook binnen een shell-iframe, waar Chrome ingesloten
|
|
9
|
+
* PDF's blokkeert). De echte print-PDF blijft opvraagbaar in een eigen tabblad.
|
|
10
|
+
*
|
|
11
|
+
* Pagina's stapelen verticaal; het hele kader wordt met een CSS-schaling op
|
|
12
|
+
* de beschikbare breedte passend gemaakt, zodat het document altijd volledig
|
|
13
|
+
* zichtbaar is (met verticaal scrollen bij meerdere pagina's).
|
|
14
|
+
*/
|
|
15
|
+
export function PdfVoorbeeld({ html, breedteMm, hoogteMm, margeMm, onControle }) {
|
|
16
|
+
const renderVolgorde = useRef(0);
|
|
17
|
+
const controleCallback = useRef(onControle);
|
|
18
|
+
const [paginas, setPaginas] = useState([]);
|
|
19
|
+
const [bezigPdf, setBezigPdf] = useState(false);
|
|
20
|
+
const [fout, setFout] = useState(null);
|
|
21
|
+
const [pdfBase64, setPdfBase64] = useState(null);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
controleCallback.current = onControle;
|
|
24
|
+
}, [onControle]);
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
const volgorde = ++renderVolgorde.current;
|
|
27
|
+
const timer = window.setTimeout(() => {
|
|
28
|
+
setBezigPdf(true);
|
|
29
|
+
setFout(null);
|
|
30
|
+
controleCallback.current?.("controleren");
|
|
31
|
+
void maakVoorbeeldPdf({ data: { html, breedteMm, hoogteMm, margeMm } })
|
|
32
|
+
.then(async (res) => {
|
|
33
|
+
if (volgorde !== renderVolgorde.current)
|
|
34
|
+
return;
|
|
35
|
+
const bin = atob(res.pdfBase64);
|
|
36
|
+
const bytes = new Uint8Array(bin.length);
|
|
37
|
+
for (let i = 0; i < bin.length; i += 1)
|
|
38
|
+
bytes[i] = bin.charCodeAt(i);
|
|
39
|
+
const pdfjs = await import("pdfjs-dist");
|
|
40
|
+
pdfjs.GlobalWorkerOptions.workerSrc = new URL("pdfjs-dist/build/pdf.worker.min.mjs", import.meta.url).toString();
|
|
41
|
+
const taak = pdfjs.getDocument({ data: bytes });
|
|
42
|
+
const pdf = await taak.promise;
|
|
43
|
+
const nieuw = [];
|
|
44
|
+
for (let nummer = 1; nummer <= pdf.numPages; nummer += 1) {
|
|
45
|
+
const pagina = await pdf.getPage(nummer);
|
|
46
|
+
const viewport = pagina.getViewport({ scale: 1.5 });
|
|
47
|
+
const canvas = document.createElement("canvas");
|
|
48
|
+
canvas.width = viewport.width;
|
|
49
|
+
canvas.height = viewport.height;
|
|
50
|
+
const context = canvas.getContext("2d");
|
|
51
|
+
if (!context)
|
|
52
|
+
throw new Error("De afdrukpagina kon niet worden getoond.");
|
|
53
|
+
await pagina.render({ canvas, canvasContext: context, viewport }).promise;
|
|
54
|
+
nieuw.push(canvas.toDataURL("image/png"));
|
|
55
|
+
}
|
|
56
|
+
if (volgorde !== renderVolgorde.current)
|
|
57
|
+
return;
|
|
58
|
+
setPaginas(nieuw);
|
|
59
|
+
setPdfBase64(res.pdfBase64);
|
|
60
|
+
controleCallback.current?.("gereed");
|
|
61
|
+
})
|
|
62
|
+
.catch((e) => {
|
|
63
|
+
if (volgorde !== renderVolgorde.current)
|
|
64
|
+
return;
|
|
65
|
+
const melding = e instanceof Error ? e.message : "Afdrukcontrole mislukt";
|
|
66
|
+
setPaginas([]);
|
|
67
|
+
setPdfBase64(null);
|
|
68
|
+
setFout(melding);
|
|
69
|
+
controleCallback.current?.("afwijking", melding);
|
|
70
|
+
})
|
|
71
|
+
.finally(() => {
|
|
72
|
+
if (volgorde === renderVolgorde.current)
|
|
73
|
+
setBezigPdf(false);
|
|
74
|
+
});
|
|
75
|
+
}, 350);
|
|
76
|
+
return () => window.clearTimeout(timer);
|
|
77
|
+
}, [html, breedteMm, hoogteMm, margeMm]);
|
|
78
|
+
const openPdf = async () => {
|
|
79
|
+
if (!pdfBase64)
|
|
80
|
+
return;
|
|
81
|
+
try {
|
|
82
|
+
const bin = atob(pdfBase64);
|
|
83
|
+
const bytes = new Uint8Array(bin.length);
|
|
84
|
+
for (let i = 0; i < bin.length; i += 1)
|
|
85
|
+
bytes[i] = bin.charCodeAt(i);
|
|
86
|
+
const url = URL.createObjectURL(new Blob([bytes], { type: "application/pdf" }));
|
|
87
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
88
|
+
setTimeout(() => URL.revokeObjectURL(url), 60000);
|
|
89
|
+
}
|
|
90
|
+
catch (e) {
|
|
91
|
+
setFout(e instanceof Error ? e.message : "PDF kon niet worden geopend");
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
return (_jsxs("div", { className: "relative h-full w-full overflow-hidden", children: [_jsx("div", { className: "h-full w-full overflow-y-auto overflow-x-hidden rounded-md bg-muted p-3", children: _jsxs("div", { className: "mx-auto flex max-w-full flex-col items-center gap-4", children: [paginas.map((src, index) => (_jsx("img", { src: src, alt: `Afdrukpagina ${index + 1}`, className: "h-auto max-w-full border bg-background shadow-sm" }, `${index}-${src.length}`))), bezigPdf ? _jsx(Loader2, { className: "mt-8 h-6 w-6 animate-spin text-muted-foreground" }) : null, fout ? _jsxs("div", { className: "mt-8 flex max-w-md items-start gap-2 text-sm text-destructive", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-4 w-4 shrink-0" }), fout] }) : null] }) }), _jsx("div", { className: "pointer-events-none absolute right-3 top-3 flex flex-col items-end gap-2", children: _jsxs(Button, { size: "sm", variant: "outline", className: "pointer-events-auto", onClick: () => void openPdf(), disabled: bezigPdf || !pdfBase64, children: [bezigPdf ? (_jsx(Loader2, { className: "mr-2 h-3 w-3 animate-spin" })) : (_jsx(ExternalLink, { className: "mr-2 h-3 w-3" })), "Print-PDF openen"] }) })] }));
|
|
95
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PrintProgrammaUitleg.d.ts","sourceRoot":"","sources":["../../src/components/PrintProgrammaUitleg.tsx"],"names":[],"mappings":"AAgBA,wBAAgB,oBAAoB,CAAC,EAAE,OAAe,EAAE,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,+BAmC9E;AAED,wBAAgB,YAAY,
|
|
1
|
+
{"version":3,"file":"PrintProgrammaUitleg.d.ts","sourceRoot":"","sources":["../../src/components/PrintProgrammaUitleg.tsx"],"names":[],"mappings":"AAgBA,wBAAgB,oBAAoB,CAAC,EAAE,OAAe,EAAE,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,+BAmC9E;AAED,wBAAgB,YAAY,gCAc3B"}
|
|
@@ -15,5 +15,5 @@ export function PrintProgrammaUitleg({ compact = false }) {
|
|
|
15
15
|
return (_jsxs("div", { className: "bg-muted/40 space-y-4 rounded-xl border p-5", children: [!compact && (_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "bg-background rounded-lg border p-2", children: _jsx(MonitorSmartphone, { className: "text-muted-foreground h-5 w-5" }) }), _jsxs("div", { children: [_jsx("p", { className: "text-sm font-medium", children: "We zien nog geen printers" }), _jsx("p", { className: "text-muted-foreground text-sm", children: "Zet de computer klaar in drie korte stappen." })] })] })), _jsx("ol", { className: "space-y-3", children: STAPPEN.map((tekst, i) => (_jsxs("li", { className: "flex gap-3", children: [_jsx("span", { className: "bg-background text-foreground flex h-6 w-6 shrink-0 items-center justify-center rounded-full border text-xs font-medium", children: i + 1 }), _jsx("span", { className: "text-sm", children: tekst })] }, tekst))) }), _jsx(Button, { asChild: true, variant: "outline", children: _jsxs("a", { href: DOWNLOAD_URL, target: "_blank", rel: "noreferrer", children: [_jsx(Download, { className: "mr-2 h-4 w-4" }), " Printprogramma downloaden"] }) })] }));
|
|
16
16
|
}
|
|
17
17
|
export function WerktHetNiet() {
|
|
18
|
-
return (_jsxs("details", { className: "group rounded-lg border p-3", children: [_jsxs("summary", { className: "flex cursor-pointer items-center gap-2 text-sm font-medium", children: [_jsx(HelpCircle, { className: "text-muted-foreground h-4 w-4" }), " Werkt het niet?"] }), _jsxs("ul", { className: "text-muted-foreground mt-3 space-y-2 text-sm", children: [_jsx("li", { children: "De computer staat uit
|
|
18
|
+
return (_jsxs("details", { className: "group rounded-lg border p-3", children: [_jsxs("summary", { className: "flex cursor-pointer items-center gap-2 text-sm font-medium", children: [_jsx(HelpCircle, { className: "text-muted-foreground h-4 w-4" }), " Werkt het niet?"] }), _jsxs("ul", { className: "text-muted-foreground mt-3 space-y-2 text-sm", children: [_jsx("li", { children: "De computer staat uit, is in slaapstand of heeft geen internet." }), _jsx("li", { children: "Het printprogramma is nog niet gestart op die computer." }), _jsx("li", { children: "Er is ingelogd met een eigen/ander PrintNode-account in plaats van de beheerdergegevens \u2014 alleen computers onder het gekoppelde account verschijnen hier." }), _jsx("li", { children: "De computer heet anders dan je verwacht: de naam in de lijst is de naam zoals macOS die aan PrintNode doorgeeft." })] })] }));
|
|
19
19
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PrintQueuePage.d.ts","sourceRoot":"","sources":["../../src/components/PrintQueuePage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PrintQueuePage.d.ts","sourceRoot":"","sources":["../../src/components/PrintQueuePage.tsx"],"names":[],"mappings":"AAuFA,wBAAgB,cAAc,gCA2X7B"}
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useMemo, useRef, useState } from "react";
|
|
3
3
|
import { Badge, Button, Card, CardContent, CardDescription, CardHeader, CardTitle, Input, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, toast, } from "@flowselections/core";
|
|
4
|
-
import { FileDown, RotateCcw, Search, XCircle } from "lucide-react";
|
|
4
|
+
import { FileDown, FolderOpen, RotateCcw, Save, Search, XCircle } from "lucide-react";
|
|
5
5
|
import { bijgewerktTekst, useAutoRefresh } from "../lib/useAutoRefresh.js";
|
|
6
6
|
import { PrintStatusBanner } from "./PrintStatusBanner.js";
|
|
7
7
|
import { maakPrintJob, updateJobStatus, useLayouts, usePrinters, usePrintJobs, usePrintPlekNamen, } from "../lib/useDocumentData.js";
|
|
8
8
|
import { printStatus } from "../lib/printService.functions.js";
|
|
9
9
|
import { vraagWachtrijRonde } from "../lib/queueTickClient.js";
|
|
10
10
|
import { documentTypeLabel } from "../lib/documentTypes.js";
|
|
11
|
-
import { jobPlekLabel } from "../lib/printQueue.js";
|
|
12
|
-
import {
|
|
11
|
+
import { jobPlekLabel, jobPrintPlekId } from "../lib/printQueue.js";
|
|
12
|
+
import { kiesPdfMap, openInEigenTabblad } from "../lib/pdfMap.js";
|
|
13
|
+
import { bewaarPdfJobOpnieuw, downloadPdfJob } from "../lib/pdfJobSaver.js";
|
|
14
|
+
import { pdfOpslagLabel, isOpslagFout } from "../lib/pdfOpslagStatus.js";
|
|
13
15
|
import { PdfMapAutoSaver } from "./PdfMapAutoSaver.js";
|
|
14
16
|
import { PdfMapToestemmingBanner } from "./PdfMapToestemmingBanner.js";
|
|
15
|
-
import { supabase } from "../lib/supabaseClient.js";
|
|
16
17
|
const STATUS_VARIANT = {
|
|
17
18
|
wachtend: "outline",
|
|
18
19
|
bezig: "secondary",
|
|
@@ -27,14 +28,6 @@ const BRON_LABEL = {
|
|
|
27
28
|
render_html: "meegestuurde opmaak",
|
|
28
29
|
klantlayout: "klantlayout",
|
|
29
30
|
};
|
|
30
|
-
const LOKALE_PDF_LABEL = {
|
|
31
|
-
gereed: "PDF gereed — lokaal opslaan",
|
|
32
|
-
opgeslagen: "opgeslagen op Mac",
|
|
33
|
-
map_ontbreekt: "PDF-map ontbreekt",
|
|
34
|
-
toestemming_nodig: "maptoestemming nodig",
|
|
35
|
-
schrijffout: "opslaan mislukt",
|
|
36
|
-
timeout: "wachten op PDF verlopen",
|
|
37
|
-
};
|
|
38
31
|
/**
|
|
39
32
|
* Heeft deze opdracht een kenmerk waarmee hij van andere orders te
|
|
40
33
|
* onderscheiden is? Zo niet, dan valt de dubbelbescherming terug op het
|
|
@@ -44,10 +37,15 @@ function heeftOrderKenmerk(job) {
|
|
|
44
37
|
const p = (job.payload ?? {});
|
|
45
38
|
if (typeof p !== "object" || p === null)
|
|
46
39
|
return false;
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return
|
|
50
|
-
}
|
|
40
|
+
const gevuld = (w) => (typeof w === "string" && w.trim() !== "") || typeof w === "number";
|
|
41
|
+
if (["queue_item_id", "order_id", "ordernummer", "order_number", "orderId"].some((k) => gevuld(p[k]))) {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
// Modules kunnen de order ook genest meesturen als payload.order / payload.data.order.
|
|
45
|
+
const genest = [p.order, p.data?.order];
|
|
46
|
+
return genest.some((o) => o !== null &&
|
|
47
|
+
typeof o === "object" &&
|
|
48
|
+
["id", "order_id", "orderNumber", "ordernummer", "nummer"].some((k) => gevuld(o[k])));
|
|
51
49
|
}
|
|
52
50
|
export function PrintQueuePage() {
|
|
53
51
|
const { jobs, loading, reload } = usePrintJobs();
|
|
@@ -56,9 +54,43 @@ export function PrintQueuePage() {
|
|
|
56
54
|
const [zoek, setZoek] = useState("");
|
|
57
55
|
const [status, setStatus] = useState("alle");
|
|
58
56
|
const [plekFilter, setPlekFilter] = useState("alle");
|
|
57
|
+
const [opslagFilter, setOpslagFilter] = useState("alle");
|
|
59
58
|
const [tickFout, setTickFout] = useState(null);
|
|
60
59
|
const plekNamen = usePrintPlekNamen();
|
|
61
60
|
const printerNaam = useMemo(() => new Map(printers.map((p) => [p.id, p.naam])), [printers]);
|
|
61
|
+
const pdfPrinter = printers.find((p) => p.afdrukmethode === "pdf");
|
|
62
|
+
/** Kies direct vanuit een foute opdracht de PDF-map op deze werkplek. */
|
|
63
|
+
const stelMapIn = async (printplekId) => {
|
|
64
|
+
if (!pdfPrinter) {
|
|
65
|
+
toast.error("Er is nog geen “Opslaan als PDF”-printer aangemaakt");
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const uitkomst = await kiesPdfMap(pdfPrinter.id, printplekId);
|
|
69
|
+
if (uitkomst.status === "gekozen") {
|
|
70
|
+
toast.success("Map gekozen", {
|
|
71
|
+
description: `PDF's worden opgeslagen in “${uitkomst.naam}”. De opdracht wordt opnieuw opgeslagen.`,
|
|
72
|
+
});
|
|
73
|
+
void reload(true);
|
|
74
|
+
}
|
|
75
|
+
else if (uitkomst.status === "iframe-geblokkeerd") {
|
|
76
|
+
toast.error("Map kiezen werkt niet in een iframe", {
|
|
77
|
+
description: "Open de app in een eigen tabblad.",
|
|
78
|
+
action: {
|
|
79
|
+
label: "Open in eigen tabblad",
|
|
80
|
+
onClick: () => openInEigenTabblad(printplekId),
|
|
81
|
+
},
|
|
82
|
+
duration: 15000,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
else if (uitkomst.status === "niet-ondersteund") {
|
|
86
|
+
toast.error("Deze browser ondersteunt geen mapkeuze", {
|
|
87
|
+
description: "Gebruik Chrome, Edge of Safari op desktop.",
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
else if (uitkomst.status === "fout") {
|
|
91
|
+
toast.error("Map kiezen is mislukt", { description: uitkomst.melding });
|
|
92
|
+
}
|
|
93
|
+
};
|
|
62
94
|
const layoutNaam = useMemo(() => new Map(layouts.map((l) => [l.id, l.naam])), [layouts]);
|
|
63
95
|
/** Herkomstlabel per opdracht: printplek, anders pickstation of werkplek. */
|
|
64
96
|
const plekPerJob = useMemo(() => {
|
|
@@ -76,6 +108,13 @@ export function PrintQueuePage() {
|
|
|
76
108
|
return false;
|
|
77
109
|
if (plekFilter !== "alle" && (plekPerJob.get(j.id) || "—") !== plekFilter)
|
|
78
110
|
return false;
|
|
111
|
+
if (opslagFilter === "fout" && !isOpslagFout(j.lokale_pdf_status))
|
|
112
|
+
return false;
|
|
113
|
+
if (opslagFilter === "opgeslagen" && j.lokale_pdf_status !== "opgeslagen")
|
|
114
|
+
return false;
|
|
115
|
+
if (opslagFilter === "wacht" &&
|
|
116
|
+
!["wachtend", "genereren", "gereed", "bezig"].includes(j.lokale_pdf_status ?? ""))
|
|
117
|
+
return false;
|
|
79
118
|
return true;
|
|
80
119
|
});
|
|
81
120
|
const tellingen = useMemo(() => {
|
|
@@ -115,38 +154,31 @@ export function PrintQueuePage() {
|
|
|
115
154
|
await reload(true);
|
|
116
155
|
};
|
|
117
156
|
const bijgewerkt = useAutoRefresh(ronde, lopende ? 5000 : 20000);
|
|
118
|
-
return (_jsxs("main", { className: "space-y-6 p-6", children: [_jsx(PdfMapAutoSaver, {}), _jsx(PdfMapToestemmingBanner, {}), _jsxs("div", { className: "flex flex-wrap items-end justify-between gap-4", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-xl font-semibold", children: "Printwachtrij" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Volg printopdrachten, herstart mislukte prints en print documenten opnieuw." })] }), _jsx("span", { className: "text-muted-foreground text-xs", children: bijgewerktTekst(bijgewerkt) })] }), _jsx(PrintStatusBanner, { fout: tickFout }), _jsx("div", { className: "grid gap-4 md:grid-cols-4", children: ["wachtend", "bezig", "voltooid", "mislukt"].map((s) => (_jsx(Card, { children: _jsxs(CardHeader, { className: "pb-2", children: [_jsx(CardDescription, { className: "capitalize", children: s }), _jsx(CardTitle, { className: "text-2xl", children: tellingen[s] ?? 0 })] }) }, s))) }), _jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsx(CardTitle, { className: "text-base", children: "Opdrachten" }), _jsx(CardDescription, { children: loading ? "Laden…" : `${gefilterd.length} opdrachten` })] }), _jsxs(CardContent, { className: "space-y-4", children: [_jsxs("div", { className: "grid gap-3 md:grid-cols-
|
|
157
|
+
return (_jsxs("main", { className: "space-y-6 p-6", children: [_jsx(PdfMapAutoSaver, {}), _jsx(PdfMapToestemmingBanner, {}), _jsxs("div", { className: "flex flex-wrap items-end justify-between gap-4", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-xl font-semibold", children: "Printwachtrij" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Volg printopdrachten, herstart mislukte prints en print documenten opnieuw." })] }), _jsx("span", { className: "text-muted-foreground text-xs", children: bijgewerktTekst(bijgewerkt) })] }), _jsx(PrintStatusBanner, { fout: tickFout }), _jsx("div", { className: "grid gap-4 md:grid-cols-4", children: ["wachtend", "bezig", "voltooid", "mislukt"].map((s) => (_jsx(Card, { children: _jsxs(CardHeader, { className: "pb-2", children: [_jsx(CardDescription, { className: "capitalize", children: s }), _jsx(CardTitle, { className: "text-2xl", children: tellingen[s] ?? 0 })] }) }, s))) }), _jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsx(CardTitle, { className: "text-base", children: "Opdrachten" }), _jsx(CardDescription, { children: loading ? "Laden…" : `${gefilterd.length} opdrachten` })] }), _jsxs(CardContent, { className: "space-y-4", children: [_jsxs("div", { className: "grid gap-3 md:grid-cols-5", children: [_jsxs("div", { className: "relative md:col-span-2", children: [_jsx(Search, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }), _jsx(Input, { className: "pl-9", placeholder: "Zoek op document of gebruiker", value: zoek, onChange: (e) => setZoek(e.target.value) })] }), _jsxs(Select, { value: status, onValueChange: setStatus, children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "alle", children: "Alle statussen" }), ["wachtend", "bezig", "voltooid", "mislukt", "geannuleerd"].map((s) => (_jsx(SelectItem, { value: s, children: s }, s)))] })] }), _jsxs(Select, { value: plekFilter, onValueChange: setPlekFilter, children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "alle", children: "Alle printplekken" }), plekOpties.map((p) => (_jsx(SelectItem, { value: p, children: p }, p))), _jsx(SelectItem, { value: "\u2014", children: "Zonder printplek" })] })] }), _jsxs(Select, { value: opslagFilter, onValueChange: setOpslagFilter, children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "alle", children: "Alle PDF-opslag" }), _jsx(SelectItem, { value: "fout", children: "Opslag mislukt" }), _jsx(SelectItem, { value: "wacht", children: "Wacht op werkplek" }), _jsx(SelectItem, { value: "opgeslagen", children: "Opgeslagen in map" })] })] })] }), _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: "Document" }), _jsx(TableHead, { children: "Printplek" }), _jsx(TableHead, { children: "Layout (aangeleverd \u2192 gebruikt)" }), _jsx(TableHead, { children: "Printer" }), _jsx(TableHead, { children: "Status" }), _jsx(TableHead, { children: "Tijdstip" }), _jsx(TableHead, { className: "text-right", children: "Acties" })] }) }), _jsxs(TableBody, { children: [gefilterd.length === 0 && (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 7, className: "py-10 text-center text-sm text-muted-foreground", children: "Geen printopdrachten." }) })), gefilterd.map((j) => (_jsxs(TableRow, { children: [_jsxs(TableCell, { children: [_jsx("span", { className: "font-medium", children: j.documentnaam ?? documentTypeLabel(j.documenttype) }), j.is_herprint && (_jsx(Badge, { variant: "outline", className: "ml-2", children: "herprint" })), !heeftOrderKenmerk(j) && (_jsx(Badge, { variant: "outline", className: "ml-2 text-amber-600", children: "geen orderkenmerk" })), j.foutmelding && (_jsx("span", { className: "block text-xs text-destructive", children: j.foutmelding })), j.lokale_pdf_fout && (_jsx("span", { className: "block text-xs text-destructive", children: j.lokale_pdf_fout })), (["map_ontbreekt", "geen_rechten", "toestemming_nodig"].includes(j.lokale_pdf_status ?? "") ||
|
|
158
|
+
(j.lokale_pdf_status === "gereed" && !j.lokale_pdf_print_plek_id)) && (_jsxs(Button, { variant: "outline", size: "sm", className: "mt-1", onClick: () => void stelMapIn(jobPrintPlekId(j) || undefined), children: [_jsx(FolderOpen, { className: "mr-2 h-4 w-4" }), " Map instellen"] }))] }), _jsx(TableCell, { className: "text-sm text-muted-foreground", children: plekPerJob.get(j.id) || "—" }), _jsxs(TableCell, { className: "text-sm text-muted-foreground", children: [_jsx("span", { title: "Aangeleverd door de module", children: j.layout_id ? layoutNaam.get(j.layout_id) ?? "Onbekende layout" : "geen" }), _jsxs("span", { className: "block text-xs", children: ["\u2192", " ", _jsx("span", { title: "Layout die de wachtrij gebruikte", children: j.gebruikte_layout_id
|
|
119
159
|
? layoutNaam.get(j.gebruikte_layout_id) ?? "Onbekende layout"
|
|
120
160
|
: j.gebruikte_bron
|
|
121
161
|
? "geen layout"
|
|
122
|
-
: "nog niet verwerkt" }), j.gebruikte_bron && (_jsx(Badge, { variant: "outline", className: "ml-2", children: BRON_LABEL[j.gebruikte_bron] ?? j.gebruikte_bron }))] })] }), _jsx(TableCell, { className: "text-sm text-muted-foreground", children: j.printer_id ? printerNaam.get(j.printer_id) ?? "—" : "—" }), _jsx(TableCell, { children: _jsx(Badge, { variant: STATUS_VARIANT[j.status] ?? "outline", children: (j.lokale_pdf_status
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
?
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
toast.success("PDF opgeslagen in de ingestelde map");
|
|
162
|
+
: "nog niet verwerkt" }), j.gebruikte_bron && (_jsx(Badge, { variant: "outline", className: "ml-2", children: BRON_LABEL[j.gebruikte_bron] ?? j.gebruikte_bron }))] })] }), _jsx(TableCell, { className: "text-sm text-muted-foreground", children: j.printer_id ? printerNaam.get(j.printer_id) ?? "—" : "—" }), _jsx(TableCell, { children: _jsx(Badge, { variant: STATUS_VARIANT[j.status] ?? "outline", children: pdfOpslagLabel(j.lokale_pdf_status, Boolean(j.lokale_pdf_print_plek_id)) ?? j.status }) }), _jsx(TableCell, { className: "text-sm text-muted-foreground", children: new Date(j.created_at).toLocaleString("nl-NL") }), _jsx(TableCell, { className: "text-right", children: _jsxs("div", { className: "flex justify-end gap-1", children: [(j.artefact_pad || j.resultaat_pdf_base64) && (_jsxs(Button, { variant: "ghost", size: "sm", title: "Bewaar de opgemaakte PDF", onClick: async () => {
|
|
163
|
+
try {
|
|
164
|
+
await downloadPdfJob(j.id, j.documentnaam ?? "document");
|
|
165
|
+
}
|
|
166
|
+
catch (fout) {
|
|
167
|
+
toast.error(fout instanceof Error ? fout.message : "PDF downloaden mislukt");
|
|
168
|
+
}
|
|
169
|
+
}, children: [_jsx(FileDown, { className: "mr-2 h-4 w-4" }), " PDF"] })), j.lokale_pdf_status !== "opgeslagen" &&
|
|
170
|
+
(j.artefact_pad || j.resultaat_pdf_base64) && (_jsxs(Button, { variant: "ghost", size: "sm", title: "Bewaar de bestaande PDF opnieuw in de ingestelde map", onClick: async () => {
|
|
171
|
+
try {
|
|
172
|
+
await bewaarPdfJobOpnieuw(j.id);
|
|
173
|
+
toast.success("De bestaande PDF wordt opnieuw in de ingestelde map opgeslagen");
|
|
174
|
+
}
|
|
175
|
+
catch (fout) {
|
|
176
|
+
toast.error(fout instanceof Error ? fout.message : "Opnieuw opslaan mislukt");
|
|
177
|
+
}
|
|
178
|
+
finally {
|
|
140
179
|
void reload(true);
|
|
141
|
-
return;
|
|
142
180
|
}
|
|
143
|
-
|
|
144
|
-
const a = document.createElement("a");
|
|
145
|
-
a.href = url;
|
|
146
|
-
a.download = bestandsnaam;
|
|
147
|
-
a.click();
|
|
148
|
-
URL.revokeObjectURL(url);
|
|
149
|
-
}, children: [_jsx(FileDown, { className: "mr-2 h-4 w-4" }), " PDF"] })), _jsxs(Button, { variant: "ghost", size: "sm", onClick: async () => {
|
|
181
|
+
}, children: [_jsx(Save, { className: "mr-2 h-4 w-4" }), " Opslag opnieuw"] })), _jsxs(Button, { variant: "ghost", size: "sm", onClick: async () => {
|
|
150
182
|
if (!j.layout_id)
|
|
151
183
|
return;
|
|
152
184
|
try {
|
|
@@ -157,6 +189,12 @@ export function PrintQueuePage() {
|
|
|
157
189
|
documentnaam: j.documentnaam ?? "Herprint",
|
|
158
190
|
kopieen: j.kopieen ?? 1,
|
|
159
191
|
is_herprint: true,
|
|
192
|
+
bron_job_id: j.id,
|
|
193
|
+
payload: {
|
|
194
|
+
...(j.payload && typeof j.payload === "object" ? j.payload : {}),
|
|
195
|
+
is_herprint: true,
|
|
196
|
+
bron_job_id: j.id,
|
|
197
|
+
},
|
|
160
198
|
});
|
|
161
199
|
toast.success("Opnieuw in de wachtrij gezet");
|
|
162
200
|
void reload();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PrintplekDetailPage.d.ts","sourceRoot":"","sources":["../../src/components/PrintplekDetailPage.tsx"],"names":[],"mappings":"AAiDA,wBAAgB,mBAAmB,
|
|
1
|
+
{"version":3,"file":"PrintplekDetailPage.d.ts","sourceRoot":"","sources":["../../src/components/PrintplekDetailPage.tsx"],"names":[],"mappings":"AAiDA,wBAAgB,mBAAmB,gCA0YlC"}
|
|
@@ -86,7 +86,7 @@ export function PrintplekDetailPage() {
|
|
|
86
86
|
if (!plek) {
|
|
87
87
|
return (_jsxs("main", { className: "space-y-4 p-6", children: [_jsx(Button, { variant: "ghost", asChild: true, children: _jsxs(Link, { to: "/layouts-printers/printplekken", children: [_jsx(ArrowLeft, { className: "mr-2 h-4 w-4" }), " Terug"] }) }), _jsx("p", { className: "text-muted-foreground text-sm", children: "Deze printplek bestaat niet (meer)." })] }));
|
|
88
88
|
}
|
|
89
|
-
return (_jsxs("main", { className: "space-y-6 p-6", children: [_jsx(PdfMapAutoSaver, {}), _jsx(PdfMapToestemmingBanner, {}), _jsxs("div", { className: "flex flex-wrap items-start justify-between gap-4", children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Button, { variant: "ghost", size: "sm", asChild: true, className: "-ml-2", children: _jsxs(Link, { to: "/layouts-printers/printplekken", children: [_jsx(ArrowLeft, { className: "mr-2 h-4 w-4" }), " Alle printplekken"] }) }), naamBewerken ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Input, { value: naam, onChange: (e) => setNaam(e.target.value), className: "w-64" }), _jsx(Button, { size: "icon", onClick: async () => {
|
|
89
|
+
return (_jsxs("main", { className: "space-y-6 p-6", children: [_jsx(PdfMapAutoSaver, {}), _jsx(PdfMapToestemmingBanner, { printplekId: plekId }), _jsxs("div", { className: "flex flex-wrap items-start justify-between gap-4", children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Button, { variant: "ghost", size: "sm", asChild: true, className: "-ml-2", children: _jsxs(Link, { to: "/layouts-printers/printplekken", children: [_jsx(ArrowLeft, { className: "mr-2 h-4 w-4" }), " Alle printplekken"] }) }), naamBewerken ? (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Input, { value: naam, onChange: (e) => setNaam(e.target.value), className: "w-64" }), _jsx(Button, { size: "icon", onClick: async () => {
|
|
90
90
|
await bewerkPrintplek(plek.id, { naam: naam.trim() });
|
|
91
91
|
setNaamBewerken(false);
|
|
92
92
|
await reload(true);
|
|
@@ -116,6 +116,6 @@ export function PrintplekDetailPage() {
|
|
|
116
116
|
printers.find((p) => p.id === regel?.printer_id) ??
|
|
117
117
|
null;
|
|
118
118
|
const isPdf = printer?.afdrukmethode === "pdf";
|
|
119
|
-
return (_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3 rounded-lg border p-2", children: [_jsx("div", { className: "text-sm font-medium", children: documentTypeLabel(d.value) }), printer ? (_jsxs("span", { className: "text-muted-foreground text-sm", children: [printer.naam, isPdf
|
|
119
|
+
return (_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3 rounded-lg border p-2", children: [_jsx("div", { className: "text-sm font-medium", children: documentTypeLabel(d.value) }), printer ? (_jsxs("span", { className: "text-muted-foreground text-sm", children: [printer.naam, isPdf ? (_jsxs("span", { className: "ml-2 inline-flex items-center gap-1 rounded-full bg-amber-100 px-2 py-0.5 text-xs font-medium text-amber-900", children: [_jsx(AlertTriangle, { className: "h-3 w-3" }), "Wordt niet geprint, maar opgeslagen als PDF", pdfMap ? ` in “${pdfMap}”` : ""] })) : null] })) : (_jsxs("span", { className: "text-destructive flex items-center gap-1 text-xs", children: [_jsx(AlertTriangle, { className: "h-3.5 w-3.5" }), " Geen printer"] }))] }, d.value));
|
|
120
120
|
}), !alleDocumenten && overige.length > 0 ? (_jsxs("p", { className: "text-muted-foreground text-xs", children: [overige.length, " documentsoort", overige.length === 1 ? "" : "en", " nog niet ingesteld."] })) : null] })] }), _jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsxs(CardTitle, { className: "flex items-center gap-2 text-base", children: [_jsx(Link2, { className: "h-4 w-4" }), " Gekoppeld aan"] }), _jsx(CardDescription, { children: "Andere modules (bijvoorbeeld pickstations) kunnen zich aan deze printplek koppelen." })] }), _jsxs(CardContent, { className: "space-y-4", children: [bronnen.length === 0 ? (_jsx("p", { className: "text-muted-foreground text-sm", children: "Nog niets gekoppeld. Kies deze printplek in de andere module (bijvoorbeeld bij een pickstation); de koppeling verschijnt hier vanzelf." })) : (_jsx("div", { className: "space-y-2", children: bronnen.map((b) => (_jsxs("div", { className: "flex flex-wrap items-center gap-3 rounded-lg border px-3 py-2 text-sm", children: [_jsx(Badge, { variant: "secondary", children: b.bron }), _jsxs("span", { className: "min-w-0 flex-1 truncate", children: [b.label ?? b.bron_id, _jsx("span", { className: "text-muted-foreground ml-2 text-xs", children: b.bron_id })] }), _jsxs(Button, { variant: "ghost", size: "sm", onClick: () => void ontkoppel(b.bron, b.bron_id), children: [_jsx(X, { className: "mr-1 h-3.5 w-3.5" }), " Ontkoppelen"] })] }, b.id))) })), weeskoppelingen.length > 0 ? (_jsxs("div", { className: "space-y-2 rounded-lg border border-dashed p-3", children: [_jsxs("p", { className: "text-muted-foreground flex items-center gap-2 text-xs", children: [_jsx(AlertTriangle, { className: "h-3.5 w-3.5" }), " Koppelingen zonder bestaande printplek:"] }), weeskoppelingen.map((b) => (_jsxs("div", { className: "flex flex-wrap items-center gap-3 text-sm", children: [_jsx("span", { className: "min-w-0 flex-1 truncate", children: b.label ?? `${b.bron} ${b.bron_id}` }), _jsxs(Button, { variant: "ghost", size: "sm", onClick: () => void ontkoppel(b.bron, b.bron_id), children: [_jsx(Trash2, { className: "mr-1 h-3.5 w-3.5" }), " Opruimen"] })] }, b.id)))] })) : null] })] })] }));
|
|
121
121
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PrintplekWizard.d.ts","sourceRoot":"","sources":["../../src/components/PrintplekWizard.tsx"],"names":[],"mappings":"AAiEA,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,YAAY,EACZ,WAAW,EACX,OAAO,GACR,EAAE;IACD,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,sEAAsE;IACtE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,OAAO,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC,+
|
|
1
|
+
{"version":3,"file":"PrintplekWizard.d.ts","sourceRoot":"","sources":["../../src/components/PrintplekWizard.tsx"],"names":[],"mappings":"AAiEA,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,YAAY,EACZ,WAAW,EACX,OAAO,GACR,EAAE;IACD,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,sEAAsE;IACtE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,OAAO,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC,+BA0jBA"}
|