From a01da17221eac9b43d207b3e49e1b1613087cfb6 Mon Sep 17 00:00:00 2001 From: s4luorth Date: Thu, 1 Oct 2026 10:36:12 +0200 Subject: [PATCH] Auftragsname (Zusatz) + Signatur-Abstand-Feld im Neuauftrag - orders.order_name (optionaler Auftragsname); im Neuauftrag setzbar, auf der Board-Karte als Eyebrow ueber dem Namen angezeigt; in manual-order gespeichert. - Neuauftrag: Signatur-Feld "Abstand (mm)" (leer = Standard halber Zeilenabstand), via signature_offsets.spacing durchgereicht. Co-Authored-By: Claude Opus 4.8 --- bootstrap/bootstrap.mjs | 1 + .../dist/index.js | 31 +++++++++++++------ .../dist/index.js | 1 + .../dist/index.js | 3 +- 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/bootstrap/bootstrap.mjs b/bootstrap/bootstrap.mjs index a05c519..7b9a3c6 100644 --- a/bootstrap/bootstrap.mjs +++ b/bootstrap/bootstrap.mjs @@ -252,6 +252,7 @@ const collections = [ { collection: 'orders', meta: { icon: 'receipt_long', note: 'Auftrag.' }, fields: [ f('order_number', 'string', { interface: 'input', unique: true, required: true }), + f('order_name', 'string', { interface: 'input', note: 'Optionaler Auftragsname (z. B. „EinDollarBrille Dankeskarten"). Wird zusätzlich zur Nummer angezeigt.' }), m2o('customer', 'directus_users', { note: 'Kunde = Login-Konto (Zuordnung per E-Mail).' }), f('customer_email', 'string', { interface: 'input', required: true, note: 'Zuordnungsschlüssel.' }), m2o('product', 'products'), diff --git a/extensions/directus-extension-skrift-neuauftrag/dist/index.js b/extensions/directus-extension-skrift-neuauftrag/dist/index.js index 712ab8e..860c3d8 100644 --- a/extensions/directus-extension-skrift-neuauftrag/dist/index.js +++ b/extensions/directus-extension-skrift-neuauftrag/dist/index.js @@ -72,11 +72,11 @@ const NeuAuftrag = defineComponent({ const leereZeile = () => ({ free_text: '', placeholders: {} }); const neu = reactive({ - product: '', format: '', font: 'tilda', + product: '', format: '', font: 'tilda', orderName: '', // Relative Schriftgröße in % (getrennt Brief/Kuvert); 100 = Standard. fontSizeLetter: 100, fontSizeEnvelope: 100, // Unterschrift auf dem Brief ([[signatur1]]): SVG-Inhalt + Feinjustierung. - sigSvg: '', sigLabel: '', sigX: 0, sigY: 0, sigScale: 100, + sigSvg: '', sigLabel: '', sigX: 0, sigY: 0, sigScale: 100, sigSpacing: '', // Mehrseitiges Schriftstück (Auto-Fluss über mehrere A4-Seiten). mehrseitig: false, seitenInfo: '', // Kuvert-Adresse je Empfänger: '5zeilen' (5 Zeilen) oder 'individuell' (einzeilig). @@ -311,7 +311,11 @@ const NeuAuftrag = defineComponent({ // bereits ein sigPayload() für den Unterschriften-Service (PDF) gibt. const briefSigPayload = () => (neu.sigSvg ? { signatures: { signatur1: neu.sigSvg }, - signature_offsets: { signatur1: { x: Number(neu.sigX) || 0, y: Number(neu.sigY) || 0, scale: (Number(neu.sigScale) || 100) / 100 } } } + signature_offsets: { signatur1: { + x: Number(neu.sigX) || 0, y: Number(neu.sigY) || 0, scale: (Number(neu.sigScale) || 100) / 100, + // Abstand in mm (leer = Backend-Default = halber Zeilenabstand). + ...(String(neu.sigSpacing).trim() !== '' ? { spacing: Number(neu.sigSpacing) || 0 } : {}), + } } } : {}); async function preview() { @@ -407,7 +411,7 @@ const NeuAuftrag = defineComponent({ try { const kv = kuvertPayload(); const res = await api.post('/skrift-orders/manual-order', { - product: neu.product, format: neu.format, font: neu.font, + product: neu.product, format: neu.format, font: neu.font, order_name: neu.orderName.trim() || undefined, realistic: neu.realistic, font_scale_letter: neu.fontSizeLetter / 100, font_scale_envelope: neu.fontSizeEnvelope / 100, multi_page: neu.mehrseitig, @@ -430,9 +434,9 @@ const NeuAuftrag = defineComponent({ } function zuruecksetzen() { Object.assign(neu, { - product: produkte.value[0]?.key || 'briefe', format: neuFormate()[0]?.key || '', font: 'tilda', + product: produkte.value[0]?.key || 'briefe', format: neuFormate()[0]?.key || '', font: 'tilda', orderName: '', fontSizeLetter: 100, fontSizeEnvelope: 100, - sigSvg: '', sigLabel: '', sigX: 0, sigY: 0, sigScale: 100, mehrseitig: false, seitenInfo: '', + sigSvg: '', sigLabel: '', sigX: 0, sigY: 0, sigScale: 100, sigSpacing: '', mehrseitig: false, seitenInfo: '', adressModus: '5zeilen', kuverts: true, absenderAufKuvert: false, envelopeSender: '', envelopeSenderScale: 100, envFormat: '', realistic: true, customer_email: '', text: '', rows: [leereZeile()], anzahl: 1, importOpen: false, importText: '', @@ -672,10 +676,11 @@ const NeuAuftrag = defineComponent({ h('span', { style: `color:${ACCENT};font-size:13px;font-weight:600;` }, `✓ ${neu.sigLabel} – als [[signatur1]] im Text`), btn('Entfernen', sigEntfernen), ]), - h('div', { style: 'display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px;' }, [ + h('div', { style: 'display:grid;grid-template-columns:1fr 1fr 1fr 1fr;gap:12px;' }, [ h('div', {}, [label('Versatz X (mm)'), h('input', { type: 'number', step: 1, value: neu.sigX, style: WFELD + 'width:100%;', onInput: (e) => { neu.sigX = e.target.value; neu.previewSession = null; } })]), h('div', {}, [label('Versatz Y (mm)'), h('input', { type: 'number', step: 1, value: neu.sigY, style: WFELD + 'width:100%;', onInput: (e) => { neu.sigY = e.target.value; neu.previewSession = null; } })]), h('div', {}, [label('Größe (%)'), h('input', { type: 'number', step: 5, value: neu.sigScale, style: WFELD + 'width:100%;', onInput: (e) => { neu.sigScale = e.target.value; neu.previewSession = null; } })]), + h('div', {}, [label('Abstand (mm)'), h('input', { type: 'number', step: 1, min: 0, placeholder: 'Standard', value: neu.sigSpacing, style: WFELD + 'width:100%;', onInput: (e) => { neu.sigSpacing = e.target.value; neu.previewSession = null; } })]), ]), subdued('Positiv X = nach rechts, positiv Y = nach unten. Nach dem Anpassen „Aktualisieren" in der Vorschau klicken.', 'margin-top:8px;'), ]) : null, @@ -685,9 +690,15 @@ const NeuAuftrag = defineComponent({ // Bereich 4 – Kunde const b4 = h('div', { style: BEREICH }, [ bereichKopf('👤 Kunde'), - h('div', { style: 'max-width:420px;' }, [ - label('Kunde verknüpfen (E-Mail, optional)'), - h('input', { type: 'email', value: neu.customer_email, placeholder: 'kunde@example.de', style: WFELD + 'width:100%;', onInput: (e) => { neu.customer_email = e.target.value; } }), + h('div', { style: 'display:flex;gap:16px;flex-wrap:wrap;' }, [ + h('div', { style: 'flex:1 1 280px;max-width:420px;' }, [ + label('Auftragsname (optional)'), + h('input', { type: 'text', value: neu.orderName, placeholder: 'z. B. EinDollarBrille Dankeskarten', style: WFELD + 'width:100%;', onInput: (e) => { neu.orderName = e.target.value; } }), + ]), + h('div', { style: 'flex:1 1 280px;max-width:420px;' }, [ + label('Kunde verknüpfen (E-Mail, optional)'), + h('input', { type: 'email', value: neu.customer_email, placeholder: 'kunde@example.de', style: WFELD + 'width:100%;', onInput: (e) => { neu.customer_email = e.target.value; } }), + ]), ]), ]); diff --git a/extensions/directus-extension-skrift-orders/dist/index.js b/extensions/directus-extension-skrift-orders/dist/index.js index 3c18cf7..a91dbbd 100644 --- a/extensions/directus-extension-skrift-orders/dist/index.js +++ b/extensions/directus-extension-skrift-orders/dist/index.js @@ -2083,6 +2083,7 @@ const handler = (router, { services, getSchema, logger }) => { const orderData = { customer: customerId, customer_email: customerEmail, + order_name: clean(body.order_name) || null, product: product.id, format: formatId, person_type: body.person_type === 'unternehmen' ? 'unternehmen' : 'privat', font: ['tilda', 'alva', 'ellie'].includes(body.font) ? body.font : 'tilda', diff --git a/extensions/directus-extension-skrift-produktion/dist/index.js b/extensions/directus-extension-skrift-produktion/dist/index.js index 80634e6..0357a29 100644 --- a/extensions/directus-extension-skrift-produktion/dist/index.js +++ b/extensions/directus-extension-skrift-produktion/dist/index.js @@ -252,7 +252,7 @@ const Board = defineComponent({ // ── Laden ── // Basis-Felder ohne die evtl. noch nicht gebootstrapten Felder – diese // werden separat versucht, damit ein fehlendes Feld nicht das ganze Board sperrt. - const ORDER_FELDER = 'id,order_number,status,payment_status,production_status,needs_envelope,envelope_format,' + const ORDER_FELDER = 'id,order_number,order_name,status,payment_status,production_status,needs_envelope,envelope_format,' + 'envelope_labeling,shipping_type,shipping_day,keep_contacts,entries_count,count_inland,count_ausland,brief_gedruckt,kuvert_gedruckt,' + 'date_updated,date_created,format.key,format.name,product.name,product.type,product.input_mode,' + 'source,api_client.id,api_client.name,motif_mode,motif.name,shipping_address,' @@ -1430,6 +1430,7 @@ const Board = defineComponent({ : h('input', { type: 'checkbox', checked: istGewaehlt(o.id), onClick: (e) => toggleAuswahl(o.id, e), title: 'Für Sammel-Druck auswählen', style: 'width:18px;height:18px;margin-top:5px;cursor:pointer;flex-shrink:0;' }), h('div', { style: 'min-width:0;' }, [ + o.order_name ? h('div', { style: 'font-size:12px;font-weight:500;color:var(--primary,#1e50a5);text-transform:uppercase;letter-spacing:.03em;margin-bottom:1px;' }, o.order_name) : null, h('div', { style: 'font-size:19px;font-weight:500;letter-spacing:-.01em;line-height:1.25;' }, kundeName(o) || `#${o.order_number}`), h('div', { style: 'display:flex;align-items:baseline;gap:8px;margin-top:4px;flex-wrap:wrap;' }, [ h('span', { style: `font-size:22px;font-weight:500;color:${ACCENT};line-height:1;` }, String(o.entries_count || 0)),