diff --git a/src/components/article/tabs/ArticleLabelTab.jsx b/src/components/article/tabs/ArticleLabelTab.jsx index 976e29d..f9ec2e4 100644 --- a/src/components/article/tabs/ArticleLabelTab.jsx +++ b/src/components/article/tabs/ArticleLabelTab.jsx @@ -12,20 +12,15 @@ import CheckCircleIcon from '@mui/icons-material/CheckCircle'; import CancelScheduleSendOutlinedIcon from '@mui/icons-material/CancelScheduleSendOutlined'; import { enqueueSnackbar } from 'notistack'; -import { labeltemplate, printer, article } from '../../../api'; +import { labeltemplate, article } from '../../../api'; import { companyAutomat } from '../../../automats'; import { notifyError } from '../../../utils/notify'; import BackendError from '../../BackendError'; -function filterZplPrinters(agentprinters, fallbackPrinters = []) { - const filteredAgent = (Array.isArray(agentprinters) ? agentprinters : []).filter( +function filterZplPrinters(agentprinters) { + return (Array.isArray(agentprinters) ? agentprinters : []).filter( (p) => p.enabled !== false && (!p.type || p.type.toLowerCase() === 'zpl'), ); - if (filteredAgent.length > 0) return filteredAgent; - - return (Array.isArray(fallbackPrinters) ? fallbackPrinters : []).filter( - (p) => !p.type || p.type.toLowerCase() === 'zpl', - ); } function getPrinterLabel(p) { @@ -52,6 +47,20 @@ function getPrinterLabel(p) { return label; } +function getPrinterLabelLength(printer, livePrinters = []) { + if (!printer) return null; + const live = (livePrinters || []).find( + (lp) => + (lp.agentprinterId && lp.agentprinterId === printer.id) || + (lp.id && lp.id === printer.id) || + (printer.serial && lp.serial && String(printer.serial).toLowerCase() === String(lp.serial).toLowerCase()), + ); + const raw = printer.labelLength ?? live?.labelLength; + if (raw == null) return null; + const num = Number(raw); + return Number.isFinite(num) && num > 0 ? num : null; +} + export default class ArticleLabelTab extends PureComponent { constructor(props) { super(props); @@ -59,20 +68,23 @@ export default class ArticleLabelTab extends PureComponent { this.state = { templates: null, printers: initialPrinters, + livePrinters: Array.isArray(companyAutomat.state.livePrinters) + ? companyAutomat.state.livePrinters + : [], selectedTemplateId: '', selectedPrinterId: initialPrinters.length > 0 ? initialPrinters[0].id : '', quantity: 1, loading: true, error: null, }; - this.legacyPrinters = []; } componentDidMount() { this.unsub = companyAutomat.subscribe(this, (state) => { - const zplPrinters = filterZplPrinters(state.agentprinters, this.legacyPrinters); + const zplPrinters = filterZplPrinters(state.agentprinters); this.setState((prev) => ({ printers: zplPrinters, + livePrinters: Array.isArray(state.livePrinters) ? state.livePrinters : [], selectedPrinterId: prev.selectedPrinterId && zplPrinters.some((p) => p.id === prev.selectedPrinterId) ? prev.selectedPrinterId @@ -101,27 +113,16 @@ export default class ArticleLabelTab extends PureComponent { this.setState({ loading: true, error: null }); const sku = this.props.article?.sku; try { - const [resTemplates] = await Promise.all([ - labeltemplate.list(sku ? { sku } : undefined), - companyAutomat.actions.loadAgentPrinters().catch(() => companyAutomat.state.agentprinters), - ]); - + const resTemplates = await labeltemplate.list(sku ? { sku } : undefined); const templates = resTemplates.labeltemplates || []; - let zplPrinters = filterZplPrinters(companyAutomat.state.agentprinters); - - if (zplPrinters.length === 0) { - try { - const resPrinters = await printer.list(); - this.legacyPrinters = (resPrinters.printers || []).filter((p) => p.type === 'zpl'); - zplPrinters = filterZplPrinters(companyAutomat.state.agentprinters, this.legacyPrinters); - } catch { - // ignore legacy fallback error - } - } + const zplPrinters = filterZplPrinters(companyAutomat.state.agentprinters); this.setState((prev) => ({ templates, printers: zplPrinters, + livePrinters: Array.isArray(companyAutomat.state.livePrinters) + ? companyAutomat.state.livePrinters + : prev.livePrinters, selectedTemplateId: templates.length > 0 ? prev.selectedTemplateId && templates.some((t) => t.id === prev.selectedTemplateId) @@ -152,7 +153,6 @@ export default class ArticleLabelTab extends PureComponent { await article.printLabel(articleData.sku, { templateId: selectedTemplateId, agentprinterId: selectedPrinterId, - printerId: selectedPrinterId, quantity, }); enqueueSnackbar('Druckauftrag erfolgreich gesendet', { variant: 'success' }); @@ -178,6 +178,7 @@ export default class ArticleLabelTab extends PureComponent { const { templates, printers, + livePrinters, selectedTemplateId, selectedPrinterId, quantity, @@ -185,6 +186,9 @@ export default class ArticleLabelTab extends PureComponent { error, } = this.state; + const currentPrinter = (printers || []).find((p) => p.id === selectedPrinterId); + const printerLabelLength = getPrinterLabelLength(currentPrinter, livePrinters); + if (loading) { return ( @@ -227,6 +231,16 @@ export default class ArticleLabelTab extends PureComponent { {templates.map((t) => { const isSelected = t.id === selectedTemplateId; + const dpi = t.dpi === 300 ? 300 : 203; + const tmplHeight = t.height || 200; + const tmplWidth = t.width || 448; + const hasPrinterLength = printerLabelLength != null && printerLabelLength > 0; + const totalHeight = hasPrinterLength ? Math.max(tmplHeight, printerLabelLength) : tmplHeight; + const isCutoff = hasPrinterLength && printerLabelLength < tmplHeight; + const outlineColor = isCutoff ? '#d32f2f' : '#1976d2'; + const tmplHeightPercent = (tmplHeight / totalHeight) * 100; + const printerHeightPercent = hasPrinterLength ? (printerLabelLength / totalHeight) * 100 : 100; + return ( {t.thumb ? ( - {t.name} + > + {/* Template preview image */} + + {t.name} + {/* If template exceeds printer label length, shade the cutoff overflow */} + {isCutoff && ( + + )} + + + {/* Dotted outline for printer label length */} + {hasPrinterLength && ( + + )} + ) : ( Keine Vorschau @@ -295,7 +372,7 @@ export default class ArticleLabelTab extends PureComponent { {t.name} - {t.width}x{t.height} ({t.dpi} dpi) + {t.width}x{t.height} ({dpi} dpi) @@ -314,11 +391,14 @@ export default class ArticleLabelTab extends PureComponent { onChange={(e) => this.setState({ selectedPrinterId: e.target.value })} sx={{ minWidth: 200 }} > - {printers.map((p) => ( - - {getPrinterLabel(p)} - - ))} + {printers.map((p) => { + const len = getPrinterLabelLength(p, livePrinters); + return ( + + {getPrinterLabel(p)}{len != null ? ` (${len} px)` : ''} + + ); + })} p.enabled !== false && (!p.type || p.type.toLowerCase() === 'zpl'), ); - if (filteredAgent.length > 0) return filteredAgent; - - return (Array.isArray(fallbackPrinters) ? fallbackPrinters : []).filter( - (p) => !p.type || p.type.toLowerCase() === 'zpl', - ); } function getPrinterLabel(p) { @@ -134,7 +129,6 @@ class ArtikelVorlagenPage extends PureComponent { }; this._cancelled = false; this._currentEditId = null; - this._legacyPrinters = []; this.handleRetry = this.handleRetry.bind(this); this.handleOpenNew = this.handleOpenNew.bind(this); this.handleOpenEdit = this.handleOpenEdit.bind(this); @@ -154,10 +148,8 @@ class ArtikelVorlagenPage extends PureComponent { this._cancelled = false; void this.loadTemplates(); this.unsubPrinters = companyAutomat.subscribe(this, (state) => ({ - printers: filterZplPrinters(state.agentprinters, this._legacyPrinters), + printers: filterZplPrinters(state.agentprinters), })); - void companyAutomat.actions.loadAgentPrinters().catch(() => {}); - void this.loadFallbackPrinters(); } componentWillUnmount() { @@ -165,21 +157,6 @@ class ArtikelVorlagenPage extends PureComponent { this.unsubPrinters?.(); } - async loadFallbackPrinters() { - try { - const resPrinters = await printer.list(); - this._legacyPrinters = (resPrinters.printers || []).filter( - (p) => !p.type || p.type.toLowerCase() === 'zpl', - ); - if (this._cancelled) return; - this.setState({ - printers: filterZplPrinters(companyAutomat.state.agentprinters, this._legacyPrinters), - }); - } catch { - // ignore - } - } - async loadTemplates() { this.setState({ status: 'loading', error: null }); try { @@ -358,8 +335,7 @@ class ArtikelVorlagenPage extends PureComponent { this.setState({ printing: true }); try { const payload = { - printerId: targetPrinter.id, - agentprinterId: targetPrinter.printeragentId || targetPrinter.id, + agentprinterId: targetPrinter.id, templateId: editorTemplate?.id, name: editorName, width: editorWidth,