@flowselections/layout-maker 1.55.1 → 1.57.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/dist-lib/components/LayoutVerwijzingenKaart.d.ts +4 -0
- package/dist-lib/components/LayoutVerwijzingenKaart.d.ts.map +1 -0
- package/dist-lib/components/LayoutVerwijzingenKaart.js +59 -0
- package/dist-lib/components/LayoutsPage.d.ts.map +1 -1
- package/dist-lib/components/LayoutsPage.js +4 -13
- package/dist-lib/components/PrintQueuePage.d.ts.map +1 -1
- package/dist-lib/components/PrintQueuePage.js +16 -1
- package/dist-lib/components/PrintenInstellenWizard.d.ts +6 -0
- package/dist-lib/components/PrintenInstellenWizard.d.ts.map +1 -0
- package/dist-lib/components/PrintenInstellenWizard.js +89 -0
- package/dist-lib/components/PrintenPage.d.ts +3 -1
- package/dist-lib/components/PrintenPage.d.ts.map +1 -1
- package/dist-lib/components/PrintenPage.js +4 -2
- package/dist-lib/components/PrintplekDetailPage.d.ts.map +1 -1
- package/dist-lib/components/PrintplekDetailPage.js +2 -0
- package/dist-lib/components/TestprintDialog.js +2 -2
- package/dist-lib/components/WerkplekOmzettingStap.d.ts +10 -0
- package/dist-lib/components/WerkplekOmzettingStap.d.ts.map +1 -0
- package/dist-lib/components/WerkplekOmzettingStap.js +46 -0
- package/dist-lib/components/WerkplekVraag.d.ts +4 -0
- package/dist-lib/components/WerkplekVraag.d.ts.map +1 -0
- package/dist-lib/components/WerkplekVraag.js +26 -0
- package/dist-lib/components/WerkplekkenTab.d.ts +7 -0
- package/dist-lib/components/WerkplekkenTab.d.ts.map +1 -0
- package/dist-lib/components/WerkplekkenTab.js +143 -0
- package/dist-lib/index.d.ts +15 -0
- package/dist-lib/index.d.ts.map +1 -1
- package/dist-lib/index.js +12 -0
- package/dist-lib/integrations/supabase/types.d.ts +415 -0
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/beheerder.d.ts +2 -0
- package/dist-lib/lib/beheerder.d.ts.map +1 -0
- package/dist-lib/lib/beheerder.js +18 -0
- package/dist-lib/lib/etiketControle.d.ts +36 -0
- package/dist-lib/lib/etiketControle.d.ts.map +1 -0
- package/dist-lib/lib/etiketControle.js +89 -0
- package/dist-lib/lib/layoutVerwijzingen.d.ts +50 -0
- package/dist-lib/lib/layoutVerwijzingen.d.ts.map +1 -0
- package/dist-lib/lib/layoutVerwijzingen.js +101 -0
- package/dist-lib/lib/papierFormaten.d.ts +3 -3
- package/dist-lib/lib/papierFormaten.d.ts.map +1 -1
- package/dist-lib/lib/papierFormaten.js +6 -6
- 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 +149 -23
- package/dist-lib/lib/printRoutering.d.ts +14 -1
- package/dist-lib/lib/printRoutering.d.ts.map +1 -1
- package/dist-lib/lib/printRoutering.js +6 -0
- package/dist-lib/lib/printnodeStatusTekst.d.ts +2 -0
- package/dist-lib/lib/printnodeStatusTekst.d.ts.map +1 -0
- package/dist-lib/lib/printnodeStatusTekst.js +13 -0
- package/dist-lib/lib/productiebonHtml.js +1 -1
- package/dist-lib/lib/testprint.d.ts +6 -0
- package/dist-lib/lib/testprint.d.ts.map +1 -1
- package/dist-lib/lib/testprint.js +11 -7
- package/dist-lib/lib/waaromPrinter.d.ts +7 -0
- package/dist-lib/lib/waaromPrinter.d.ts.map +1 -0
- package/dist-lib/lib/waaromPrinter.js +35 -0
- package/dist-lib/lib/werkplekOmzetting.d.ts +22 -0
- package/dist-lib/lib/werkplekOmzetting.d.ts.map +1 -0
- package/dist-lib/lib/werkplekOmzetting.js +42 -0
- package/dist-lib/lib/werkplekken.d.ts +73 -0
- package/dist-lib/lib/werkplekken.d.ts.map +1 -0
- package/dist-lib/lib/werkplekken.js +156 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LayoutVerwijzingenKaart.d.ts","sourceRoot":"","sources":["../../src/components/LayoutVerwijzingenKaart.tsx"],"names":[],"mappings":"AAwBA,wBAAgB,uBAAuB,CAAC,EAAE,WAAW,EAAE,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;CAAE,sCAqFpF"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
// ============================================================================
|
|
3
|
+
// src/components/LayoutVerwijzingenKaart.tsx — per documentsoort met meerdere
|
|
4
|
+
// actieve layouts of verschillende verwijzingen: welke instellingen naar welke
|
|
5
|
+
// layout wijzen en hoe vaak hij de laatste 30 dagen is gebruikt. De beheerder
|
|
6
|
+
// kiest zelf een standaard; instellingen van andere modules worden nooit
|
|
7
|
+
// gewijzigd, alleen getoond met een link.
|
|
8
|
+
// ============================================================================
|
|
9
|
+
import { useState } from "react";
|
|
10
|
+
import { Badge, Button, Card, CardContent, CardDescription, CardHeader, CardTitle, toast } from "@flowselections/core";
|
|
11
|
+
import { AlertTriangle, ExternalLink } from "lucide-react";
|
|
12
|
+
import { documentTypeLabel } from "../lib/documentTypes.js";
|
|
13
|
+
import { maakStandaardLayout } from "../lib/useDocumentData.js";
|
|
14
|
+
import { leesbareFout } from "../lib/foutTekst.js";
|
|
15
|
+
import { useIsBeheerder } from "../lib/beheerder.js";
|
|
16
|
+
import { BRON_LABEL, isEigenVerwijzing, plekVanVerwijzing, useLayoutVerwijzingen, zetVerwijzingOm, } from "../lib/layoutVerwijzingen.js";
|
|
17
|
+
export function LayoutVerwijzingenKaart({ onGewijzigd }) {
|
|
18
|
+
const { overzicht, fout, reload } = useLayoutVerwijzingen();
|
|
19
|
+
const beheerder = useIsBeheerder() === true;
|
|
20
|
+
const [bezig, setBezig] = useState(null);
|
|
21
|
+
const safe = Array.isArray(overzicht) ? overzicht : [];
|
|
22
|
+
if (fout)
|
|
23
|
+
return _jsxs("p", { className: "text-destructive text-sm", children: ["Overzicht van verwijzingen laden mislukt: ", fout] });
|
|
24
|
+
if (!safe.length)
|
|
25
|
+
return null;
|
|
26
|
+
const klaar = () => { void reload(); onGewijzigd?.(); };
|
|
27
|
+
return (_jsxs(Card, { className: "border-destructive/50", children: [_jsxs(CardHeader, { className: "pb-2", children: [_jsxs(CardTitle, { className: "flex items-center gap-2 text-base", children: [_jsx(AlertTriangle, { className: "text-destructive h-4 w-4" }), " Meerdere layouts voor dezelfde documentsoort"] }), _jsx(CardDescription, { children: "Per layout zie je welke instellingen hem gebruiken en hoe vaak hij de laatste 30 dagen is geprint. Kies zelf \u00E9\u00E9n standaard. Instellingen van andere modules pas je aan in die module." })] }), _jsx(CardContent, { className: "space-y-3", children: safe.map((s) => (_jsxs("div", { className: "space-y-2 rounded-lg border p-2 text-sm", "data-soort": s.documenttype, children: [_jsx("div", { className: "font-medium", children: documentTypeLabel(s.documenttype) }), s.layouts.map((l) => {
|
|
28
|
+
const standaard = s.layouts.find((x) => x.is_standaard && x.actief && x.bron === l.bron && x.id !== l.id);
|
|
29
|
+
return (_jsxs("div", { className: "rounded border p-2", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx("span", { className: "font-medium", children: l.naam }), _jsx(Badge, { variant: "outline", children: l.bron === "floriday" ? "Floriday" : "eigen" }), l.is_standaard ? _jsx(Badge, { children: "standaard" }) : null, !l.actief ? _jsx(Badge, { variant: "secondary", children: "niet actief" }) : null, _jsxs("span", { className: "text-muted-foreground text-xs", children: ["30 dagen: ", l.totaal30, "\u00D7", Object.entries(l.gebruik).map(([b, n]) => ` · ${BRON_LABEL[b] ?? b} ${n}×`).join("")] }), l.actief && !l.is_standaard ? (_jsx(Button, { size: "sm", variant: "outline", className: "ml-auto", disabled: !beheerder || bezig === l.id, title: beheerder ? undefined : "Alleen beheerders kunnen dit wijzigen", onClick: async () => {
|
|
30
|
+
setBezig(l.id);
|
|
31
|
+
try {
|
|
32
|
+
await maakStandaardLayout(l.id);
|
|
33
|
+
toast.success(`${l.naam} is nu de standaard`);
|
|
34
|
+
klaar();
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
toast.error(leesbareFout(e, "Standaard maken mislukt"));
|
|
38
|
+
}
|
|
39
|
+
finally {
|
|
40
|
+
setBezig(null);
|
|
41
|
+
}
|
|
42
|
+
}, children: "Maak standaard" })) : null] }), l.verwijzingen.length ? (_jsx("ul", { className: "mt-1 space-y-1", children: l.verwijzingen.map((v) => (_jsx(VerwijzingRegel, { v: v, naarStandaard: isEigenVerwijzing(v) && standaard ? standaard : null, beheerder: beheerder, onKlaar: klaar }, `${v.tabel}-${v.rij_id}-${v.pad.join(".")}`))) })) : (_jsx("p", { className: "text-muted-foreground mt-1 text-xs", children: "Geen instelling verwijst naar deze layout." }))] }, l.id));
|
|
43
|
+
})] }, s.documenttype))) })] }));
|
|
44
|
+
}
|
|
45
|
+
function VerwijzingRegel({ v, naarStandaard, beheerder, onKlaar, }) {
|
|
46
|
+
const plek = plekVanVerwijzing(v);
|
|
47
|
+
return (_jsxs("li", { className: "flex flex-wrap items-center gap-2 text-xs", children: [_jsxs("span", { children: [plek.module, " \u203A ", plek.scherm, v.rij_naam ? ` (${v.rij_naam}${v.rij_actief === false ? ", niet actief" : ""})` : v.rij_actief === false ? " (niet actief)" : ""] }), !isEigenVerwijzing(v) && plek.link ? (_jsxs("a", { href: plek.link, className: "text-primary inline-flex items-center gap-1 underline", children: ["Openen ", _jsx(ExternalLink, { className: "h-3 w-3" })] })) : null, naarStandaard ? (_jsxs(Button, { size: "sm", variant: "ghost", disabled: !beheerder, title: beheerder ? undefined : "Alleen beheerders kunnen dit wijzigen", onClick: async () => {
|
|
48
|
+
if (!window.confirm(`Deze regel laten wijzen naar "${naarStandaard.naam}"?`))
|
|
49
|
+
return;
|
|
50
|
+
try {
|
|
51
|
+
await zetVerwijzingOm(v, naarStandaard.id);
|
|
52
|
+
toast.success("Verwijzing omgezet");
|
|
53
|
+
onKlaar();
|
|
54
|
+
}
|
|
55
|
+
catch (e) {
|
|
56
|
+
toast.error(leesbareFout(e, "Omzetten mislukt"));
|
|
57
|
+
}
|
|
58
|
+
}, children: ["Naar standaard \"", naarStandaard.naam, "\""] })) : null] }));
|
|
59
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LayoutsPage.d.ts","sourceRoot":"","sources":["../../src/components/LayoutsPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"LayoutsPage.d.ts","sourceRoot":"","sources":["../../src/components/LayoutsPage.tsx"],"names":[],"mappings":"AA4EA,wBAAgB,WAAW,CAAC,EAAE,OAAe,EAAE,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,+BAomB1E"}
|
|
@@ -3,8 +3,9 @@ import { useMemo, useState } from "react";
|
|
|
3
3
|
import { useAutoRefresh } from "../lib/useAutoRefresh.js";
|
|
4
4
|
import { Link, useNavigate } from "@tanstack/react-router";
|
|
5
5
|
import { Badge, Button, Card, CardContent, CardDescription, CardHeader, CardTitle, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, Input, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Separator, Switch, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Textarea, toast, } from "@flowselections/core";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { Copy, FileText, Pencil, Plus, Search, Settings2, Trash2 } from "lucide-react";
|
|
7
|
+
import { LayoutVerwijzingenKaart } from "./LayoutVerwijzingenKaart.js";
|
|
8
|
+
import { maakStandaardLayout } from "../lib/useDocumentData.js";
|
|
8
9
|
import { dupliceerLayout, maakLayout, updateLayout, useLayouts, verwijderLayout, } from "../lib/useDocumentData.js";
|
|
9
10
|
import { LayoutPrinterSelect } from "./LayoutPrinterSelect.js";
|
|
10
11
|
import { DOCUMENT_TYPES, FLORIDAY_LAYOUT_TOELICHTING, PAPIERFORMATEN, documentTypeLabel, isFloridayLayout, } from "../lib/documentTypes.js";
|
|
@@ -25,7 +26,6 @@ function klantOntwerpLayout(l) {
|
|
|
25
26
|
}
|
|
26
27
|
export function LayoutsPage({ ingebed = false } = {}) {
|
|
27
28
|
const { layouts, loading, reload } = useLayouts();
|
|
28
|
-
const conflicten = useMemo(() => layoutConflicten(layouts), [layouts]);
|
|
29
29
|
useAutoRefresh(() => {
|
|
30
30
|
void reload(true);
|
|
31
31
|
}, 30000);
|
|
@@ -156,16 +156,7 @@ export function LayoutsPage({ ingebed = false } = {}) {
|
|
|
156
156
|
}
|
|
157
157
|
};
|
|
158
158
|
const Wrapper = ingebed ? "div" : "main";
|
|
159
|
-
return (_jsxs(Wrapper, { className: ingebed ? "space-y-6" : "p-6 space-y-6", children: [_jsxs("div", { className: "flex flex-wrap items-end justify-between gap-4", children: [!ingebed && (_jsxs("div", { children: [_jsx("h1", { className: "text-xl font-semibold", children: "Documentlayouts" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Ontwerp pakbonnen, facturen, etiketten en alle andere documenten." })] })), _jsx("div", { className: "ml-auto flex gap-2", children: _jsxs(Button, { onClick: () => setWizardOpen(true), children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), " Nieuwe layout"] }) })] }),
|
|
160
|
-
try {
|
|
161
|
-
await maakStandaardLayout(l.id);
|
|
162
|
-
toast.success(`${l.naam} is nu de standaard`);
|
|
163
|
-
}
|
|
164
|
-
catch {
|
|
165
|
-
toast.error("Standaard maken mislukt");
|
|
166
|
-
}
|
|
167
|
-
void reload();
|
|
168
|
-
}, children: ["Maak \"", l.naam, "\" standaard"] }, l.id))) })] }, `${c.documenttype}-${c.bron}`))) })] })), _jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsx(CardTitle, { className: "text-base", children: "Overzicht" }), _jsx(CardDescription, { children: loading ? "Laden…" : `${gefilterd.length} van ${layouts.length} layouts` })] }), _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 naam of omschrijving", value: zoek, onChange: (e) => setZoek(e.target.value) })] }), _jsxs(Select, { value: typeFilter, onValueChange: setTypeFilter, children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, { placeholder: "Documenttype" }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "alle", children: "Alle documenttypes" }), DOCUMENT_TYPES.map((d) => (_jsx(SelectItem, { value: d.value, children: d.label }, d.value)))] })] }), _jsxs(Select, { value: statusFilter, onValueChange: setStatusFilter, children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, { placeholder: "Status" }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "alle", children: "Alle statussen" }), _jsx(SelectItem, { value: "actief", children: "Actief" }), _jsx(SelectItem, { value: "inactief", children: "Inactief" })] })] }), _jsxs(Select, { value: bronFilter, onValueChange: setBronFilter, children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, { placeholder: "Herkomst" }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "alle", children: "Alle herkomsten" }), _jsx(SelectItem, { value: "eigen", children: "Eigen ontwerp" }), _jsx(SelectItem, { value: "floriday", children: "Uit Floriday" })] })] })] }), _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: "Naam" }), _jsx(TableHead, { children: "Documenttype" }), _jsx(TableHead, { children: "Formaat" }), _jsxs(TableHead, { children: [_jsx("div", { children: "Printer nu" }), _jsxs("div", { className: "text-xs font-normal", children: ["bedrijfsstandaard, in te stellen op", " ", _jsx(Link, { to: "/layouts-printers/printplekken", className: "text-primary underline", children: "Printen" })] })] }), _jsx(TableHead, { children: "Actief" }), _jsx(TableHead, { className: "text-right", children: "Acties" })] }) }), _jsxs(TableBody, { children: [gefilterd.length === 0 && (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 6, className: "py-10 text-center text-sm text-muted-foreground", children: "Geen layouts gevonden." }) })), gefilterd.map((l) => (_jsxs(TableRow, { children: [_jsxs(TableCell, { children: [_jsxs("div", { className: "flex items-center gap-2 font-medium", children: [_jsx(FileText, { className: "h-4 w-4 text-muted-foreground" }), l.naam, l.is_standaard && _jsx(Badge, { variant: "secondary", children: "Standaard" }), isFloridayLayout(l) && _jsx(Badge, { variant: "outline", children: "Uit Floriday" })] }), (l.omschrijving || isFloridayLayout(l)) && (_jsx("span", { className: "text-xs text-muted-foreground", children: isFloridayLayout(l) ? FLORIDAY_LAYOUT_TOELICHTING : l.omschrijving }))] }), _jsx(TableCell, { children: documentTypeLabel(l.documenttype) }), _jsxs(TableCell, { className: "text-sm text-muted-foreground", children: [l.papierformaat, " \u00B7 ", Number(l.breedte_mm), " \u00D7 ", Number(l.hoogte_mm), " mm"] }), _jsx(TableCell, { className: "min-w-52", children: _jsx(LayoutPrinterSelect, { layoutId: l.id, documenttype: l.documenttype }) }), _jsx(TableCell, { children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Switch, { checked: l.actief, onCheckedChange: async (v) => {
|
|
159
|
+
return (_jsxs(Wrapper, { className: ingebed ? "space-y-6" : "p-6 space-y-6", children: [_jsxs("div", { className: "flex flex-wrap items-end justify-between gap-4", children: [!ingebed && (_jsxs("div", { children: [_jsx("h1", { className: "text-xl font-semibold", children: "Documentlayouts" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Ontwerp pakbonnen, facturen, etiketten en alle andere documenten." })] })), _jsx("div", { className: "ml-auto flex gap-2", children: _jsxs(Button, { onClick: () => setWizardOpen(true), children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), " Nieuwe layout"] }) })] }), _jsx(LayoutVerwijzingenKaart, { onGewijzigd: () => void reload() }), _jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsx(CardTitle, { className: "text-base", children: "Overzicht" }), _jsx(CardDescription, { children: loading ? "Laden…" : `${gefilterd.length} van ${layouts.length} layouts` })] }), _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 naam of omschrijving", value: zoek, onChange: (e) => setZoek(e.target.value) })] }), _jsxs(Select, { value: typeFilter, onValueChange: setTypeFilter, children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, { placeholder: "Documenttype" }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "alle", children: "Alle documenttypes" }), DOCUMENT_TYPES.map((d) => (_jsx(SelectItem, { value: d.value, children: d.label }, d.value)))] })] }), _jsxs(Select, { value: statusFilter, onValueChange: setStatusFilter, children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, { placeholder: "Status" }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "alle", children: "Alle statussen" }), _jsx(SelectItem, { value: "actief", children: "Actief" }), _jsx(SelectItem, { value: "inactief", children: "Inactief" })] })] }), _jsxs(Select, { value: bronFilter, onValueChange: setBronFilter, children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, { placeholder: "Herkomst" }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "alle", children: "Alle herkomsten" }), _jsx(SelectItem, { value: "eigen", children: "Eigen ontwerp" }), _jsx(SelectItem, { value: "floriday", children: "Uit Floriday" })] })] })] }), _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: "Naam" }), _jsx(TableHead, { children: "Documenttype" }), _jsx(TableHead, { children: "Formaat" }), _jsxs(TableHead, { children: [_jsx("div", { children: "Printer nu" }), _jsxs("div", { className: "text-xs font-normal", children: ["bedrijfsstandaard, in te stellen op", " ", _jsx(Link, { to: "/layouts-printers/printplekken", className: "text-primary underline", children: "Printen" })] })] }), _jsx(TableHead, { children: "Actief" }), _jsx(TableHead, { className: "text-right", children: "Acties" })] }) }), _jsxs(TableBody, { children: [gefilterd.length === 0 && (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 6, className: "py-10 text-center text-sm text-muted-foreground", children: "Geen layouts gevonden." }) })), gefilterd.map((l) => (_jsxs(TableRow, { children: [_jsxs(TableCell, { children: [_jsxs("div", { className: "flex items-center gap-2 font-medium", children: [_jsx(FileText, { className: "h-4 w-4 text-muted-foreground" }), l.naam, l.is_standaard && _jsx(Badge, { variant: "secondary", children: "Standaard" }), isFloridayLayout(l) && _jsx(Badge, { variant: "outline", children: "Uit Floriday" })] }), (l.omschrijving || isFloridayLayout(l)) && (_jsx("span", { className: "text-xs text-muted-foreground", children: isFloridayLayout(l) ? FLORIDAY_LAYOUT_TOELICHTING : l.omschrijving }))] }), _jsx(TableCell, { children: documentTypeLabel(l.documenttype) }), _jsxs(TableCell, { className: "text-sm text-muted-foreground", children: [l.papierformaat, " \u00B7 ", Number(l.breedte_mm), " \u00D7 ", Number(l.hoogte_mm), " mm"] }), _jsx(TableCell, { className: "min-w-52", children: _jsx(LayoutPrinterSelect, { layoutId: l.id, documenttype: l.documenttype }) }), _jsx(TableCell, { children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Switch, { checked: l.actief, onCheckedChange: async (v) => {
|
|
169
160
|
await updateLayout(l.id, { actief: v });
|
|
170
161
|
void reload();
|
|
171
162
|
} }), !l.is_standaard && (_jsx(Button, { variant: "ghost", size: "sm", onClick: async () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PrintQueuePage.d.ts","sourceRoot":"","sources":["../../src/components/PrintQueuePage.tsx"],"names":[],"mappings":"AAoFA,wBAAgB,cAAc,
|
|
1
|
+
{"version":3,"file":"PrintQueuePage.d.ts","sourceRoot":"","sources":["../../src/components/PrintQueuePage.tsx"],"names":[],"mappings":"AAoFA,wBAAgB,cAAc,gCAqZ7B"}
|
|
@@ -193,7 +193,22 @@ export function PrintQueuePage() {
|
|
|
193
193
|
return null;
|
|
194
194
|
const s = scanLabel(scan, j.gestart_op ?? j.created_at);
|
|
195
195
|
return s === "gescand" ? (_jsx(Badge, { variant: "default", className: "ml-2", children: "Gescand" })) : (_jsx(Badge, { variant: "secondary", className: "ml-2", children: "Kar eerder gescand" }));
|
|
196
|
-
})(), j.printnode_bericht && j.status === "mislukt" && (_jsx("span", { className: "block text-xs text-destructive", children: j.printnode_bericht }))] }), _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: [
|
|
196
|
+
})(), j.printnode_bericht && j.status === "mislukt" && (_jsx("span", { className: "block text-xs text-destructive", children: j.printnode_bericht }))] }), _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: [_jsx(Button, { variant: "ghost", size: "sm", onClick: async () => {
|
|
197
|
+
const { data } = await supabase
|
|
198
|
+
.from("print_job_logs")
|
|
199
|
+
.select("gebeurtenis, detail, created_at")
|
|
200
|
+
.eq("job_id", j.id)
|
|
201
|
+
.in("gebeurtenis", ["waarom", "etiket", "route"])
|
|
202
|
+
.order("created_at", { ascending: true });
|
|
203
|
+
const regels = (Array.isArray(data) ? data : []).map((r) => r.detail).filter(Boolean);
|
|
204
|
+
toast.message("Waarom deze printer?", {
|
|
205
|
+
description: regels.length
|
|
206
|
+
? regels.join("\n")
|
|
207
|
+
: j.status === "mislukt"
|
|
208
|
+
? (j.foutmelding ?? "Er is niets geprint.")
|
|
209
|
+
: "Nog niet bepaald: de opdracht is nog niet verwerkt.",
|
|
210
|
+
});
|
|
211
|
+
}, children: "Waarom?" }), opnieuwActie(j) && (_jsxs(Button, { variant: "ghost", size: "sm", onClick: async () => {
|
|
197
212
|
const pr = j.printer_id ? printerById.get(j.printer_id) : null;
|
|
198
213
|
if (pr && !pr.online) {
|
|
199
214
|
const door = window.confirm(`Printer "${pr.naam}" (of de computer) is nu offline. De opdracht blijft wachten tot hij weer aan staat, en verloopt anders. Toch versturen?`);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PrintenInstellenWizard.d.ts","sourceRoot":"","sources":["../../src/components/PrintenInstellenWizard.tsx"],"names":[],"mappings":"AAsBA,wBAAgB,sBAAsB,CAAC,EACrC,IAAI,EACJ,YAAY,EACZ,OAAO,GACR,EAAE;IACD,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB,+BA0JA"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// ============================================================================
|
|
3
|
+
// src/components/PrintenInstellenWizard.tsx — "Printen instellen" voor een
|
|
4
|
+
// nieuwe klant: computers zoeken, per werkplek de A4-printer en labelprinter
|
|
5
|
+
// (met geladen etiket) kiezen, een testpagina per printer, klaar.
|
|
6
|
+
// ============================================================================
|
|
7
|
+
import { useEffect, useState } from "react";
|
|
8
|
+
import { Badge, Button, Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, Input, toast } from "@flowselections/core";
|
|
9
|
+
import { Check, Loader2, RefreshCw } from "lucide-react";
|
|
10
|
+
import { useComputers } from "./ComputersLijst.js";
|
|
11
|
+
import { GeladenEtiketKeuze } from "./WerkplekkenTab.js";
|
|
12
|
+
import { printHtml, volgJobStatus } from "../lib/printApi.js";
|
|
13
|
+
import { leesbareFout } from "../lib/foutTekst.js";
|
|
14
|
+
import { testHtml } from "../lib/testprint.js";
|
|
15
|
+
import { printTitelVoorStatus } from "../lib/printnodeStatusTekst.js";
|
|
16
|
+
import { printerTitel, slaWerkplekOp, usePrinterLijst } from "../lib/werkplekken.js";
|
|
17
|
+
import { haalOmzettingVoorstel } from "../lib/werkplekOmzetting.js";
|
|
18
|
+
import { useIsBeheerder } from "../lib/beheerder.js";
|
|
19
|
+
import { WerkplekOmzettingStap } from "./WerkplekOmzettingStap.js";
|
|
20
|
+
const selectKlasse = "border-input bg-background rounded-md border px-2 py-1 text-sm";
|
|
21
|
+
export function PrintenInstellenWizard({ open, onOpenChange, onKlaar, }) {
|
|
22
|
+
const [stap, setStap] = useState(1);
|
|
23
|
+
const { computers, loading, reload } = useComputers();
|
|
24
|
+
const { printers, reload: reloadPrinters } = usePrinterLijst();
|
|
25
|
+
const [naam, setNaam] = useState("Kantoor");
|
|
26
|
+
const [a4, setA4] = useState(null);
|
|
27
|
+
const [label, setLabel] = useState(null);
|
|
28
|
+
const [status, setStatus] = useState({});
|
|
29
|
+
const bruikbaar = printers.filter((p) => !p.verborgen && !p.is_virtueel && p.actief !== false);
|
|
30
|
+
const labelPrinter = printers.find((p) => p.id === label) ?? null;
|
|
31
|
+
const beheerder = useIsBeheerder() === true;
|
|
32
|
+
const [voorstel, setVoorstel] = useState(null);
|
|
33
|
+
// Bestaande Shell: begin met het voorstel uit de huidige instellingen.
|
|
34
|
+
// Lege Shell: geen voorstel, de wizard begint gewoon bij stap 1.
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
if (!open)
|
|
37
|
+
return;
|
|
38
|
+
let weg = false;
|
|
39
|
+
haalOmzettingVoorstel()
|
|
40
|
+
.then((v) => { if (!weg) {
|
|
41
|
+
setVoorstel(v);
|
|
42
|
+
if (v.length)
|
|
43
|
+
setStap(0);
|
|
44
|
+
} })
|
|
45
|
+
.catch(() => { if (!weg)
|
|
46
|
+
setVoorstel([]); });
|
|
47
|
+
return () => { weg = true; };
|
|
48
|
+
}, [open]);
|
|
49
|
+
const test = async (printerId, soort) => {
|
|
50
|
+
setStatus((s) => ({ ...s, [printerId]: "wachtend" }));
|
|
51
|
+
try {
|
|
52
|
+
const p = printers.find((x) => x.id === printerId);
|
|
53
|
+
const { jobId } = await printHtml({
|
|
54
|
+
documenttype: soort,
|
|
55
|
+
documentnaam: `Testpagina ${printerTitel(p)}`,
|
|
56
|
+
html: testHtml({
|
|
57
|
+
Documentsoort: soort === "sticker" ? "Testetiket" : "Testpagina A4",
|
|
58
|
+
Werkplek: naam,
|
|
59
|
+
Printer: printerTitel(p),
|
|
60
|
+
Tijdstip: new Date().toLocaleString("nl-NL"),
|
|
61
|
+
}),
|
|
62
|
+
printerId,
|
|
63
|
+
payload: { is_testprint: true },
|
|
64
|
+
});
|
|
65
|
+
volgJobStatus(jobId, (j) => setStatus((s) => ({ ...s, [printerId]: j.foutmelding ? `mislukt: ${j.foutmelding}` : j.status })));
|
|
66
|
+
}
|
|
67
|
+
catch (e) {
|
|
68
|
+
setStatus((s) => ({ ...s, [printerId]: `mislukt: ${leesbareFout(e, "versturen mislukt")}` }));
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { className: "max-h-[85vh] max-w-2xl overflow-y-auto", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: stap === 0 ? "Printen instellen — voorstel uit huidige instellingen" : `Printen instellen — stap ${stap} van 4` }), _jsx(DialogDescription, { children: "In een paar minuten weet je zeker waar het papier uitkomt." })] }), stap === 0 && voorstel?.length ? (_jsx(WerkplekOmzettingStap, { voorstel: voorstel, printers: printers, beheerder: beheerder, onOverslaan: () => setStap(1), onKlaar: () => { void reloadPrinters(); onKlaar?.(); setNaam(voorstel[0]?.naam ?? naam); setStap(3); } })) : null, stap === 1 ? (_jsxs("div", { className: "space-y-2 text-sm", children: [_jsx("p", { children: "Op deze computers draait het printprogramma:" }), computers.map((c) => (_jsxs("div", { className: "flex items-center gap-2 rounded border p-2", children: [_jsx("span", { className: "font-medium", children: c.naam }), _jsx(Badge, { variant: c.online ? "secondary" : "destructive", children: c.online ? "online" : "offline" }), _jsxs("span", { className: "text-muted-foreground text-xs", children: [c.aantalGevonden, " printers"] })] }, c.id))), !loading && !computers.length ? _jsx("p", { className: "text-muted-foreground", children: "Nog geen computers gevonden. Installeer het printprogramma op de computer met de printers." }) : null, _jsxs(Button, { size: "sm", variant: "outline", onClick: () => { void reload(); void reloadPrinters(); }, children: [loading ? _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : _jsx(RefreshCw, { className: "mr-2 h-4 w-4" }), " Opnieuw zoeken"] })] })) : null, stap === 2 ? (_jsxs("div", { className: "grid gap-2 text-sm sm:grid-cols-[9rem_1fr]", children: [_jsx("span", { children: "Naam werkplek" }), _jsx(Input, { value: naam, onChange: (e) => setNaam(e.target.value) }), _jsx("span", { children: "A4-printer" }), _jsxs("select", { className: selectKlasse, value: a4 ?? "", onChange: (e) => setA4(e.target.value || null), children: [_jsx("option", { value: "", children: "\u2014 geen \u2014" }), bruikbaar.map((p) => _jsxs("option", { value: p.id, children: [printerTitel(p), p.locatie ? ` · ${p.locatie}` : ""] }, p.id))] }), _jsx("span", { children: "Labelprinter" }), _jsxs("select", { className: selectKlasse, value: label ?? "", onChange: (e) => setLabel(e.target.value || null), children: [_jsx("option", { value: "", children: "\u2014 geen \u2014" }), bruikbaar.map((p) => _jsxs("option", { value: p.id, children: [printerTitel(p), p.locatie ? ` · ${p.locatie}` : ""] }, p.id))] }), labelPrinter ? (_jsx("div", { className: "sm:col-span-2", children: _jsx(GeladenEtiketKeuze, { printer: labelPrinter, onGewijzigd: () => void reloadPrinters() }) })) : null] })) : null, stap === 3 ? (_jsx("div", { className: "space-y-2 text-sm", children: [a4 ? { id: a4, soort: "vrij" } : null, label ? { id: label, soort: "sticker" } : null]
|
|
72
|
+
.filter(Boolean)
|
|
73
|
+
.map((r) => {
|
|
74
|
+
const p = printers.find((x) => x.id === r.id);
|
|
75
|
+
const st = status[r.id];
|
|
76
|
+
return (_jsxs("div", { className: "flex flex-wrap items-center gap-2 rounded border p-2", children: [_jsx("span", { className: "font-medium", children: printerTitel(p) }), st ? _jsx(Badge, { variant: st.startsWith("mislukt") ? "destructive" : "secondary", children: printTitelVoorStatus(st) }) : null, _jsx(Button, { size: "sm", variant: "outline", className: "ml-auto", onClick: () => void test(r.id, r.soort), children: r.soort === "sticker" ? "Testetiket" : "Testpagina" })] }, r.id));
|
|
77
|
+
}) })) : null, stap === 4 ? (_jsxs("p", { className: "flex items-center gap-2 text-sm", children: [_jsx(Check, { className: "h-4 w-4" }), " Werkplek ", naam, " is klaar. Documenten kiezen nu automatisch de A4-printer of de labelprinter op hun papierformaat."] })) : null, stap > 0 ? _jsxs("div", { className: "flex justify-between pt-2", children: [_jsx(Button, { variant: "ghost", disabled: stap === 1 && !voorstel?.length, onClick: () => setStap((s) => s - 1), children: "Terug" }), stap < 4 ? (_jsx(Button, { disabled: stap === 2 && (!naam.trim() || (!a4 && !label)), onClick: async () => {
|
|
78
|
+
if (stap === 2) {
|
|
79
|
+
try {
|
|
80
|
+
await slaWerkplekOp({ naam, a4_printer_id: a4, label_printer_id: label });
|
|
81
|
+
}
|
|
82
|
+
catch (e) {
|
|
83
|
+
toast.error(leesbareFout(e, "Werkplek opslaan mislukt"));
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
setStap((s) => s + 1);
|
|
88
|
+
}, children: "Volgende" })) : (_jsx(Button, { onClick: () => { onKlaar?.(); onOpenChange(false); setStap(1); }, children: "Klaar" }))] }) : null] }) }));
|
|
89
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PrintenPage.d.ts","sourceRoot":"","sources":["../../src/components/PrintenPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PrintenPage.d.ts","sourceRoot":"","sources":["../../src/components/PrintenPage.tsx"],"names":[],"mappings":"AAaA,KAAK,GAAG,GAAG,cAAc,GAAG,aAAa,GAAG,WAAW,CAAC;AAYxD,wBAAgB,WAAW,CAAC,EAC1B,GAAoB,GACrB,EAAE;IACD,GAAG,CAAC,EAAE,GAAG,CAAC;CACX,+BAyBA"}
|
|
@@ -4,20 +4,22 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
4
4
|
// printplekken (plekken, computers en printers samen) en standaardregels.
|
|
5
5
|
// ============================================================================
|
|
6
6
|
import { useState } from "react";
|
|
7
|
-
import { MapPin, Route as RouteIcon } from "lucide-react";
|
|
7
|
+
import { Laptop, MapPin, Route as RouteIcon } from "lucide-react";
|
|
8
8
|
import { ModuleTabs } from "./ModuleTabs.js";
|
|
9
9
|
import { PrintplekkenPage } from "./PrintplekkenPage.js";
|
|
10
10
|
import { DocumentRouteringPage } from "./DocumentRouteringPage.js";
|
|
11
11
|
import { LivePrintstatusRegel } from "./LivePrintstatusRegel.js";
|
|
12
|
+
import { WerkplekkenTab } from "./WerkplekkenTab.js";
|
|
12
13
|
const TABS = [
|
|
13
14
|
{
|
|
14
15
|
id: "printplekken",
|
|
15
16
|
label: "Printplekken",
|
|
16
17
|
icon: MapPin,
|
|
17
18
|
},
|
|
19
|
+
{ id: "werkplekken", label: "Werkplekken", icon: Laptop },
|
|
18
20
|
{ id: "routering", label: "Standaardregels", icon: RouteIcon },
|
|
19
21
|
];
|
|
20
22
|
export function PrintenPage({ tab = "printplekken", }) {
|
|
21
23
|
const [actiefTab, setActiefTab] = useState(tab);
|
|
22
|
-
return (_jsx(_Fragment, { children: _jsxs(ModuleTabs, { titel: "Printen", omschrijving: "Stel per plek in het bedrijf in welke computers, printers en documenten daar horen.", tabs: TABS, actiefTab: actiefTab, onTabWijzig: (nieuwTab) => setActiefTab(nieuwTab === "routering"
|
|
24
|
+
return (_jsx(_Fragment, { children: _jsxs(ModuleTabs, { titel: "Printen", omschrijving: "Stel per plek in het bedrijf in welke computers, printers en documenten daar horen.", tabs: TABS, actiefTab: actiefTab, onTabWijzig: (nieuwTab) => setActiefTab(nieuwTab === "routering" || nieuwTab === "werkplekken" ? nieuwTab : "printplekken"), children: [_jsx(LivePrintstatusRegel, {}), actiefTab === "werkplekken" ? (_jsx(WerkplekkenTab, {})) : actiefTab === "routering" ? (_jsx(DocumentRouteringPage, { ingebed: true })) : (_jsx(PrintplekkenPage, { ingebed: true }))] }) }));
|
|
23
25
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PrintplekDetailPage.d.ts","sourceRoot":"","sources":["../../src/components/PrintplekDetailPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PrintplekDetailPage.d.ts","sourceRoot":"","sources":["../../src/components/PrintplekDetailPage.tsx"],"names":[],"mappings":"AAiEA,wBAAgB,mBAAmB,gCAooBlC"}
|
|
@@ -22,6 +22,8 @@ import { leesbareFout } from "../lib/foutTekst.js";
|
|
|
22
22
|
import { supabase } from "../lib/supabaseClient.js";
|
|
23
23
|
import { useRouteringOverzicht } from "../lib/printRoutering.js";
|
|
24
24
|
const BRON_LABEL = {
|
|
25
|
+
werkplek_formaat: "Werkplek (papierformaat)",
|
|
26
|
+
werkplek_afwijking: "Werkplek (afwijking)",
|
|
25
27
|
printplek: "Printplek-eigen",
|
|
26
28
|
werkplek: "Werkplek-uitzondering",
|
|
27
29
|
layout: "Standaardprinter (layout)",
|
|
@@ -11,8 +11,8 @@ import { volgJobStatus } from "../lib/printApi.js";
|
|
|
11
11
|
import { bepaalTestOverzicht, verstuurTestprint, } from "../lib/testprint.js";
|
|
12
12
|
const STATUS_LABEL = {
|
|
13
13
|
wachtend: "In de wachtrij",
|
|
14
|
-
bezig: "
|
|
15
|
-
voltooid: "
|
|
14
|
+
bezig: "Naar de printer",
|
|
15
|
+
voltooid: "Bij printer afgeleverd",
|
|
16
16
|
mislukt: "Mislukt",
|
|
17
17
|
geannuleerd: "Geannuleerd",
|
|
18
18
|
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type PrinterRij } from "../lib/werkplekken.js";
|
|
2
|
+
import { type WerkplekVoorstel } from "../lib/werkplekOmzetting.js";
|
|
3
|
+
export declare function WerkplekOmzettingStap({ voorstel: begin, printers, beheerder, onKlaar, onOverslaan, }: {
|
|
4
|
+
voorstel: WerkplekVoorstel[];
|
|
5
|
+
printers: PrinterRij[];
|
|
6
|
+
beheerder: boolean;
|
|
7
|
+
onKlaar: () => void;
|
|
8
|
+
onOverslaan: () => void;
|
|
9
|
+
}): import("react").JSX.Element;
|
|
10
|
+
//# sourceMappingURL=WerkplekOmzettingStap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WerkplekOmzettingStap.d.ts","sourceRoot":"","sources":["../../src/components/WerkplekOmzettingStap.tsx"],"names":[],"mappings":"AAQA,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAA+B,KAAK,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAW9F,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EAAE,KAAK,EACf,QAAQ,EACR,SAAS,EACT,OAAO,EACP,WAAW,GACZ,EAAE;IACD,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,WAAW,EAAE,MAAM,IAAI,CAAC;CACzB,+BAuFA"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// Eerste stap van "Printen instellen" in een Shell die al printplekken of
|
|
3
|
+
// standaardregels heeft: per werkplek de printer van nu en die van na de
|
|
4
|
+
// omzetting, met de bron en de verschillen gemarkeerd.
|
|
5
|
+
import { useState } from "react";
|
|
6
|
+
import { Badge, Button, Input, toast } from "@flowselections/core";
|
|
7
|
+
import { documentTypeLabel } from "../lib/documentTypes.js";
|
|
8
|
+
import { leesbareFout } from "../lib/foutTekst.js";
|
|
9
|
+
import { printerTitel } from "../lib/werkplekken.js";
|
|
10
|
+
import { herbereken, pasOmzettingToe } from "../lib/werkplekOmzetting.js";
|
|
11
|
+
const selectKlasse = "border-input bg-background rounded-md border px-2 py-1 text-sm";
|
|
12
|
+
const BRON = {
|
|
13
|
+
printplek: "printplek",
|
|
14
|
+
werkplek: "computer-uitzondering",
|
|
15
|
+
layout: "layout-koppeling",
|
|
16
|
+
standaard: "standaardregel",
|
|
17
|
+
geen: "geen regel",
|
|
18
|
+
};
|
|
19
|
+
export function WerkplekOmzettingStap({ voorstel: begin, printers, beheerder, onKlaar, onOverslaan, }) {
|
|
20
|
+
const [voorstel, setVoorstel] = useState(begin);
|
|
21
|
+
const [bezig, setBezig] = useState(false);
|
|
22
|
+
const titel = (id) => (id ? printerTitel(printers.find((p) => p.id === id)) : "—");
|
|
23
|
+
const bruikbaar = printers.filter((p) => !p.verborgen && !p.is_virtueel && p.actief !== false);
|
|
24
|
+
const wijzig = (i, patch) => setVoorstel((v) => v.map((w, j) => (j === i ? herbereken({ ...w, ...patch }) : w)));
|
|
25
|
+
const nieuw = voorstel.filter((w) => !w.bestaat);
|
|
26
|
+
return (_jsxs("div", { className: "space-y-3 text-sm", children: [_jsx("p", { children: "Op basis van de huidige instellingen stelt de module deze werkplekken voor. Controleer per documentsoort de printer van nu en die van na de omzetting. Er wordt pas iets aangemaakt als je bevestigt." }), voorstel.map((w, i) => {
|
|
27
|
+
const etiket = printers.find((p) => p.id === w.label_printer_id)?.geladen_etiket;
|
|
28
|
+
const verschillen = w.soorten.filter((s) => s.verschil).length;
|
|
29
|
+
return (_jsxs("div", { className: "space-y-2 rounded border p-2", "data-werkplek-voorstel": w.print_plek_id ?? "kantoor", children: [_jsxs("div", { className: "grid gap-2 sm:grid-cols-[8rem_1fr]", children: [_jsx("span", { children: "Naam" }), _jsx(Input, { value: w.naam, disabled: w.bestaat || !beheerder, onChange: (e) => wijzig(i, { naam: e.target.value }) }), _jsx("span", { children: "A4-printer" }), _jsxs("select", { className: selectKlasse, disabled: w.bestaat || !beheerder, value: w.a4_printer_id ?? "", onChange: (e) => wijzig(i, { a4_printer_id: e.target.value || null }), children: [_jsx("option", { value: "", children: "\u2014 geen \u2014" }), bruikbaar.map((p) => _jsx("option", { value: p.id, children: printerTitel(p) }, p.id))] }), _jsx("span", { children: "Labelprinter" }), _jsxs("select", { className: selectKlasse, disabled: w.bestaat || !beheerder, value: w.label_printer_id ?? "", onChange: (e) => wijzig(i, { label_printer_id: e.target.value || null }), children: [_jsx("option", { value: "", children: "\u2014 geen \u2014" }), bruikbaar.map((p) => _jsx("option", { value: p.id, children: printerTitel(p) }, p.id))] }), _jsx("span", { children: "Geladen etiket" }), _jsx("span", { className: etiket ? "" : "text-destructive", children: etiket ? JSON.stringify(etiket) : "nog niet ingesteld — stel het in bij Werkplekken" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [w.print_plek_id ? _jsx(Badge, { variant: "outline", children: "gekoppeld aan printplek" }) : _jsx(Badge, { variant: "outline", children: "op basis van standaardregels" }), w.bestaat ? _jsx(Badge, { variant: "secondary", children: "bestaat al \u2014 wordt overgeslagen" }) : null, _jsxs(Badge, { variant: verschillen ? "destructive" : "secondary", children: [verschillen, " verschillen"] })] }), _jsxs("table", { className: "w-full text-xs", children: [_jsx("thead", { children: _jsxs("tr", { className: "text-muted-foreground text-left", children: [_jsx("th", { className: "py-0.5", children: "Documentsoort" }), _jsx("th", { children: "Nu" }), _jsx("th", { children: "Bron nu" }), _jsx("th", { children: "Na omzetting" })] }) }), _jsx("tbody", { children: w.soorten.map((s) => (_jsxs("tr", { className: s.verschil ? "bg-destructive/10 font-medium" : "", "data-verschil": s.verschil ? "ja" : "nee", children: [_jsx("td", { className: "py-0.5", children: documentTypeLabel(s.documenttype) }), _jsx("td", { children: titel(s.printer_id) }), _jsx("td", { children: BRON[s.bron ?? "geen"] ?? s.bron }), _jsxs("td", { children: [titel(s.na_printer_id), s.klasse === "label" ? " (label)" : " (A4)"] })] }, s.documenttype))) })] })] }, `${w.print_plek_id ?? "kantoor"}`));
|
|
30
|
+
}), !beheerder ? _jsx("p", { className: "text-muted-foreground", children: "Alleen beheerders kunnen dit wijzigen." }) : null, _jsxs("div", { className: "flex justify-between", children: [_jsx(Button, { variant: "ghost", onClick: onOverslaan, children: "Overslaan, zelf instellen" }), _jsx(Button, { disabled: !beheerder || bezig || !nieuw.length || nieuw.some((w) => !w.naam.trim() || (!w.a4_printer_id && !w.label_printer_id)), onClick: async () => {
|
|
31
|
+
if (!window.confirm(`${nieuw.length} werkplek(ken) aanmaken? De verschillen hierboven gaan dan gelden voor wie deze werkplek kiest.`))
|
|
32
|
+
return;
|
|
33
|
+
setBezig(true);
|
|
34
|
+
try {
|
|
35
|
+
await pasOmzettingToe(voorstel);
|
|
36
|
+
toast.success("Werkplekken aangemaakt");
|
|
37
|
+
onKlaar();
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
toast.error(leesbareFout(e, "Aanmaken mislukt"));
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
setBezig(false);
|
|
44
|
+
}
|
|
45
|
+
}, children: "Bevestigen en aanmaken" })] })] }));
|
|
46
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WerkplekVraag.d.ts","sourceRoot":"","sources":["../../src/components/WerkplekVraag.tsx"],"names":[],"mappings":"AAWA,wBAAgB,aAAa,CAAC,EAAE,WAAmB,EAAE,EAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,+BAuC/E"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// ============================================================================
|
|
3
|
+
// src/components/WerkplekVraag.tsx — vraagt een ingelogde gebruiker één keer
|
|
4
|
+
// op welke werkplek hij werkt (Afhandeling, Facturen…) en onthoudt dat.
|
|
5
|
+
// Pickstations en scanners gebruiken dit niet: die hangen aan hun printplek.
|
|
6
|
+
// ============================================================================
|
|
7
|
+
import { useState } from "react";
|
|
8
|
+
import { Button, Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, toast } from "@flowselections/core";
|
|
9
|
+
import { leesbareFout } from "../lib/foutTekst.js";
|
|
10
|
+
import { useMijnWerkplek, useWerkplekken } from "../lib/werkplekken.js";
|
|
11
|
+
export function WerkplekVraag({ altijdTonen = false }) {
|
|
12
|
+
const { werkplekId, laden, kies } = useMijnWerkplek();
|
|
13
|
+
const { werkplekken } = useWerkplekken();
|
|
14
|
+
const [keuze, setKeuze] = useState("");
|
|
15
|
+
const [dicht, setDicht] = useState(false);
|
|
16
|
+
const open = !dicht && !laden && werkplekken.length > 0 && (altijdTonen || !werkplekId);
|
|
17
|
+
return (_jsx(Dialog, { open: open, onOpenChange: (v) => !v && setDicht(true), children: _jsxs(DialogContent, { children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Op welke werkplek werk je?" }), _jsx(DialogDescription, { children: "Dit vragen we \u00E9\u00E9n keer. Je documenten komen dan uit de printers van die werkplek." })] }), _jsxs("select", { className: "border-input bg-background rounded-md border px-2 py-2 text-sm", value: keuze || werkplekId || "", onChange: (e) => setKeuze(e.target.value), children: [_jsx("option", { value: "", children: "\u2014 kies een werkplek \u2014" }), werkplekken.filter((w) => w.actief).map((w) => (_jsx("option", { value: w.id, children: w.naam }, w.id)))] }), _jsx(Button, { disabled: !keuze, onClick: async () => {
|
|
18
|
+
try {
|
|
19
|
+
await kies(keuze);
|
|
20
|
+
setDicht(true);
|
|
21
|
+
}
|
|
22
|
+
catch (e) {
|
|
23
|
+
toast.error(leesbareFout(e, "Opslaan mislukt"));
|
|
24
|
+
}
|
|
25
|
+
}, children: "Onthouden" })] }) }));
|
|
26
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type PrinterRij } from "../lib/werkplekken.js";
|
|
2
|
+
export declare function GeladenEtiketKeuze({ printer, onGewijzigd }: {
|
|
3
|
+
printer: PrinterRij;
|
|
4
|
+
onGewijzigd: () => void;
|
|
5
|
+
}): import("react").JSX.Element;
|
|
6
|
+
export declare function WerkplekkenTab(): import("react").JSX.Element;
|
|
7
|
+
//# sourceMappingURL=WerkplekkenTab.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WerkplekkenTab.d.ts","sourceRoot":"","sources":["../../src/components/WerkplekkenTab.tsx"],"names":[],"mappings":"AAcA,OAAO,EAUL,KAAK,UAAU,EAEhB,MAAM,oBAAoB,CAAC;AAM5B,wBAAgB,kBAAkB,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE;IAAE,OAAO,EAAE,UAAU,CAAC;IAAC,WAAW,EAAE,MAAM,IAAI,CAAA;CAAE,+BAmC5G;AAqPD,wBAAgB,cAAc,gCA4E7B"}
|