u
This commit is contained in:
@@ -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 (
|
||||
<Box sx={{ p: 4, display: 'flex', justifyContent: 'center' }}>
|
||||
@@ -227,6 +231,16 @@ export default class ArticleLabelTab extends PureComponent {
|
||||
<Grid container spacing={2}>
|
||||
{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 (
|
||||
<Grid size={{ xs: 12, sm: 6, md: 4 }} key={t.id}>
|
||||
<Paper
|
||||
@@ -272,18 +286,81 @@ export default class ArticleLabelTab extends PureComponent {
|
||||
bgcolor: 'background.default',
|
||||
borderRadius: 1,
|
||||
overflow: 'hidden',
|
||||
position: 'relative',
|
||||
}}
|
||||
>
|
||||
{t.thumb ? (
|
||||
<img
|
||||
src={`data:image/png;base64,${t.thumb}`}
|
||||
alt={t.name}
|
||||
style={{
|
||||
<Box
|
||||
sx={{
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
maxWidth: '100%',
|
||||
maxHeight: '100%',
|
||||
objectFit: 'contain',
|
||||
aspectRatio: `${tmplWidth} / ${totalHeight}`,
|
||||
boxSizing: 'border-box',
|
||||
bgcolor: '#fff',
|
||||
borderRadius: 0.5,
|
||||
boxShadow: '0 1px 2px rgba(0,0,0,0.1)',
|
||||
}}
|
||||
/>
|
||||
>
|
||||
{/* Template preview image */}
|
||||
<Box
|
||||
sx={{
|
||||
width: '100%',
|
||||
height: `${tmplHeightPercent}%`,
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
overflow: 'hidden',
|
||||
borderRadius: 0.5,
|
||||
}}
|
||||
>
|
||||
<img
|
||||
src={`data:image/png;base64,${t.thumb}`}
|
||||
alt={t.name}
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
objectFit: 'contain',
|
||||
display: 'block',
|
||||
}}
|
||||
/>
|
||||
{/* If template exceeds printer label length, shade the cutoff overflow */}
|
||||
{isCutoff && (
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: `${(printerLabelLength / tmplHeight) * 100}%`,
|
||||
bottom: 0,
|
||||
bgcolor: 'rgba(211, 47, 47, 0.22)',
|
||||
zIndex: 1,
|
||||
pointerEvents: 'none',
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
{/* Dotted outline for printer label length */}
|
||||
{hasPrinterLength && (
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
height: `${printerHeightPercent}%`,
|
||||
border: `2px dotted ${outlineColor}`,
|
||||
borderRadius: 0.5,
|
||||
pointerEvents: 'none',
|
||||
boxSizing: 'border-box',
|
||||
zIndex: 2,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
) : (
|
||||
<Typography variant="caption" color="text.disabled">
|
||||
Keine Vorschau
|
||||
@@ -295,7 +372,7 @@ export default class ArticleLabelTab extends PureComponent {
|
||||
{t.name}
|
||||
</Typography>
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
{t.width}x{t.height} ({t.dpi} dpi)
|
||||
{t.width}x{t.height} ({dpi} dpi)
|
||||
</Typography>
|
||||
</Box>
|
||||
</Paper>
|
||||
@@ -314,11 +391,14 @@ export default class ArticleLabelTab extends PureComponent {
|
||||
onChange={(e) => this.setState({ selectedPrinterId: e.target.value })}
|
||||
sx={{ minWidth: 200 }}
|
||||
>
|
||||
{printers.map((p) => (
|
||||
<MenuItem key={p.id} value={p.id}>
|
||||
{getPrinterLabel(p)}
|
||||
</MenuItem>
|
||||
))}
|
||||
{printers.map((p) => {
|
||||
const len = getPrinterLabelLength(p, livePrinters);
|
||||
return (
|
||||
<MenuItem key={p.id} value={p.id}>
|
||||
{getPrinterLabel(p)}{len != null ? ` (${len} px)` : ''}
|
||||
</MenuItem>
|
||||
);
|
||||
})}
|
||||
</TextInput>
|
||||
|
||||
<TextInput
|
||||
|
||||
@@ -30,22 +30,17 @@ import { backendErrorFrom } from '../../utils/backendError';
|
||||
import { notifyError } from '../../utils/notify';
|
||||
import { setLastArticleSku } from '../../automats/navigationAutomat';
|
||||
import companyAutomat from '../../automats/companyAutomat';
|
||||
import { labeltemplate, printer } from '../../api';
|
||||
import { labeltemplate } from '../../api';
|
||||
import { enqueueSnackbar } from 'notistack';
|
||||
import {
|
||||
BLUE_BG,
|
||||
SURFACE_BASE,
|
||||
} from '../../colors';
|
||||
|
||||
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) {
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user