feat: add label preview functionality to barcode templates with backend rendering and UI modal
Build and Push Multi-Platform Images / build-and-push (push) Successful in 33s

This commit is contained in:
2026-05-07 23:52:39 +02:00
parent 71502df7b4
commit 71b447154d
4 changed files with 107 additions and 4 deletions
@@ -5,4 +5,9 @@ export const labelPrintAgentApi = {
api
.post<{ jobId: string }>('/api/label-print-agent/jobs', { templateId, fieldValues })
.then((r) => r.data),
previewLabel: async (templateId: number, fieldValues: Record<string, string>): Promise<string> => {
const res = await api.post('/api/label-print-agent/preview', { templateId, fieldValues }, { responseType: 'blob' });
return URL.createObjectURL(res.data as Blob);
},
};
+56 -4
View File
@@ -8,7 +8,7 @@ import {
UserOutlined, FileTextOutlined, ThunderboltOutlined,
PlusOutlined, DeleteOutlined, EditOutlined, CloudUploadOutlined,
HistoryOutlined, MinusCircleOutlined, CopyOutlined, KeyOutlined,
QrcodeOutlined, UnorderedListOutlined,
QrcodeOutlined, UnorderedListOutlined, PrinterOutlined,
} from '@ant-design/icons';
import type { ColumnsType } from 'antd/es/table';
import {
@@ -26,6 +26,7 @@ import {
type BarcodeTemplate,
type LabelInputField,
} from '../api/barcode-templates';
import { labelPrintAgentApi } from '../api/labelPrintAgent';
import {
paperlessApi, type PaperlessTag, type PaperlessDocType,
type PaperlessCustomField, type PaperlessCorrespondent,
@@ -1845,6 +1846,8 @@ function BarcodeTemplatesTab() {
const [editing, setEditing] = useState<BarcodeTemplate | null>(null);
const [isNew, setIsNew] = useState(false);
const [testValue, setTestValue] = useState('');
const [testPrinting, setTestPrinting] = useState(false);
const [previewUrl, setPreviewUrl] = useState<string | null>(null);
const [form] = Form.useForm();
const load = useCallback(async () => {
@@ -1915,6 +1918,31 @@ function BarcodeTemplatesTab() {
}
};
const handleTestLabel = async () => {
if (!editing) return;
setTestPrinting(true);
try {
const values = await form.validateFields();
await barcodeTemplatesApi.update(editing.Id, values);
const inputFields: LabelInputField[] = values.LabelInputFields ?? [];
const testFieldValues: Record<string, string> = {};
const today = new Date().toISOString().slice(0, 10);
for (const f of inputFields) {
if (f.type === 'date') testFieldValues[f.name] = today;
else if (f.type === 'number') testFieldValues[f.name] = '1';
else testFieldValues[f.name] = 'Test';
}
const url = await labelPrintAgentApi.previewLabel(editing.Id, testFieldValues);
if (previewUrl) URL.revokeObjectURL(previewUrl);
setPreviewUrl(url);
load();
} catch (err: any) {
message.error(err?.response?.data?.message ?? 'Vorschau fehlgeschlagen');
} finally {
setTestPrinting(false);
}
};
const handleDelete = async (id: number) => {
await barcodeTemplatesApi.remove(id);
message.success('Vorlage gelöscht');
@@ -1981,11 +2009,17 @@ function BarcodeTemplatesTab() {
<Modal
title={editing ? 'Eingangsdokumentart bearbeiten' : 'Neue Eingangsdokumentart'}
open={modalOpen}
onOk={handleSave}
onCancel={() => { setModalOpen(false); setEditing(null); }}
okText="Speichern"
cancelText="Abbrechen"
width={720}
footer={[
...(editing && !isNew ? [
<Button key="test" icon={<PrinterOutlined />} loading={testPrinting} onClick={handleTestLabel}>
Testetikett erstellen
</Button>,
] : []),
<Button key="cancel" onClick={() => { setModalOpen(false); setEditing(null); }}>Abbrechen</Button>,
<Button key="save" type="primary" onClick={handleSave}>Speichern</Button>,
]}
>
<Form form={form} layout="vertical">
<Form.Item name="Name" label="Name" rules={[{ required: true, message: 'Name ist erforderlich' }]}>
@@ -2164,6 +2198,24 @@ function BarcodeTemplatesTab() {
</>
)}
</Modal>
<Modal
title="Etikett-Vorschau"
open={!!previewUrl}
onCancel={() => { URL.revokeObjectURL(previewUrl!); setPreviewUrl(null); }}
footer={<Button onClick={() => { URL.revokeObjectURL(previewUrl!); setPreviewUrl(null); }}>Schließen</Button>}
width={520}
>
{previewUrl && (
<div style={{ background: '#e0e0e0', padding: 24, display: 'flex', justifyContent: 'center', borderRadius: 4 }}>
<img
src={previewUrl}
alt="Etikett-Vorschau"
style={{ maxWidth: '100%', boxShadow: '0 2px 8px rgba(0,0,0,0.3)', display: 'block' }}
/>
</div>
)}
</Modal>
</>
);
}