u
This commit is contained in:
@@ -17,6 +17,7 @@ export { posterminal } from './posterminal.js';
|
|||||||
export { printer } from './printer.js';
|
export { printer } from './printer.js';
|
||||||
export { printeragent } from './printeragent.js';
|
export { printeragent } from './printeragent.js';
|
||||||
export { agentprinter } from './agentprinter.js';
|
export { agentprinter } from './agentprinter.js';
|
||||||
|
export { printerjob } from './printerjob.js';
|
||||||
export { propertyname } from './propertyname.js';
|
export { propertyname } from './propertyname.js';
|
||||||
export { quote } from './quote.js';
|
export { quote } from './quote.js';
|
||||||
export { retoure } from './retoure.js';
|
export { retoure } from './retoure.js';
|
||||||
|
|||||||
100
src/api/printerjob.js
Normal file
100
src/api/printerjob.js
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
import { http } from './http.js';
|
||||||
|
|
||||||
|
export const printerjob = {
|
||||||
|
/**
|
||||||
|
* POST /api/zpljob
|
||||||
|
* @param {{ agentprinterId: number, data: string, copiescount?: number }} payload
|
||||||
|
* → { printerjob: PrinterJob }
|
||||||
|
*/
|
||||||
|
createZplJob({ agentprinterId, data, copiescount = 1 }) {
|
||||||
|
return http('/api/zpljob', {
|
||||||
|
method: 'POST',
|
||||||
|
body: {
|
||||||
|
agentprinterId: Number(agentprinterId),
|
||||||
|
data: String(data),
|
||||||
|
copiescount: Number(copiescount) || 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a minimal ZPL test label to a specific agent printer.
|
||||||
|
* @param {number} agentprinterId
|
||||||
|
* @param {{ model?: string }} [options]
|
||||||
|
* → { printerjob: PrinterJob }
|
||||||
|
*/
|
||||||
|
sendTestZpl(agentprinterId, { model = 'Zebra' } = {}) {
|
||||||
|
const timeStr = new Date().toLocaleTimeString('de-DE');
|
||||||
|
const safeModel = String(model || 'Drucker').replace(/[\^~]/g, '');
|
||||||
|
const zpl = [
|
||||||
|
'^XA',
|
||||||
|
'^FO40,40^ADN,36,20^FDTestdruck OK^FS',
|
||||||
|
`^FO40,85^ADN,18,10^FD${safeModel}^FS`,
|
||||||
|
`^FO40,115^ADN,18,10^FDID: ${agentprinterId} - ${timeStr}^FS`,
|
||||||
|
'^XZ',
|
||||||
|
].join('\n');
|
||||||
|
return this.createZplJob({
|
||||||
|
agentprinterId,
|
||||||
|
data: zpl,
|
||||||
|
copiescount: 1,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET /api/printerjob
|
||||||
|
* @param {{ agentprinterId?: number, state?: string }} [query]
|
||||||
|
* → { printerjobs: PrinterJob[] }
|
||||||
|
*/
|
||||||
|
list(query = {}) {
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
if (query.agentprinterId != null) params.set('agentprinterId', String(query.agentprinterId));
|
||||||
|
if (query.state != null) params.set('state', String(query.state));
|
||||||
|
const qs = params.toString();
|
||||||
|
return http(qs ? `/api/printerjob?${qs}` : '/api/printerjob');
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET /api/printerjob/:id
|
||||||
|
* → { printerjob: PrinterJob }
|
||||||
|
*/
|
||||||
|
get(id) {
|
||||||
|
return http(`/api/printerjob/${id}`);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST /api/printerjob
|
||||||
|
* @param {{ agentprinterId: number, type?: 'zpl'|'pdf'|'epos', data: string }} payload
|
||||||
|
* → { printerjob: PrinterJob }
|
||||||
|
*/
|
||||||
|
create({ agentprinterId, type = 'zpl', data }) {
|
||||||
|
return http('/api/printerjob', {
|
||||||
|
method: 'POST',
|
||||||
|
body: {
|
||||||
|
agentprinterId: Number(agentprinterId),
|
||||||
|
type,
|
||||||
|
data,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST /api/printerjob/:id/cancel
|
||||||
|
* → { success: true, printerjob: PrinterJob }
|
||||||
|
*/
|
||||||
|
cancel(id) {
|
||||||
|
return http(`/api/printerjob/${id}/cancel`, {
|
||||||
|
method: 'POST',
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DELETE /api/printerjob/:id
|
||||||
|
* → { success: true, deletedJob: PrinterJob }
|
||||||
|
*/
|
||||||
|
delete(id) {
|
||||||
|
return http(`/api/printerjob/${id}`, {
|
||||||
|
method: 'DELETE',
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
@@ -28,6 +28,7 @@ import {
|
|||||||
printer as printerApi,
|
printer as printerApi,
|
||||||
printeragent as printeragentApi,
|
printeragent as printeragentApi,
|
||||||
agentprinter as agentprinterApi,
|
agentprinter as agentprinterApi,
|
||||||
|
printerjob as printerjobApi,
|
||||||
supplier as supplierApi,
|
supplier as supplierApi,
|
||||||
unit as unitApi,
|
unit as unitApi,
|
||||||
warehouse as warehouseApi,
|
warehouse as warehouseApi,
|
||||||
@@ -876,6 +877,14 @@ const actions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async sendTestPrint(agentprinterId, options = {}) {
|
||||||
|
return printerjobApi.sendTestZpl(agentprinterId, options);
|
||||||
|
},
|
||||||
|
|
||||||
|
async createZplJob(payload) {
|
||||||
|
return printerjobApi.createZplJob(payload);
|
||||||
|
},
|
||||||
|
|
||||||
async loadLivePrinters() {
|
async loadLivePrinters() {
|
||||||
const companyId =
|
const companyId =
|
||||||
authAutomat.state.user?.selectedCompanyId ?? companyAutomat.state.current?.id;
|
authAutomat.state.user?.selectedCompanyId ?? companyAutomat.state.current?.id;
|
||||||
|
|||||||
@@ -120,7 +120,14 @@ class AgentQrCode extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderPrinterDiagnostics(printer, live) {
|
function renderPrinterDiagnostics(printer, live) {
|
||||||
if (!live) {
|
const isOnline = printer?.online ?? (live ? !live.unreachable && live.status !== 'offline' : false);
|
||||||
|
const isOpen = printer?.open ?? (live?.errors?.headOpen || live?.headOpen || false);
|
||||||
|
const isPaused = printer?.pause ?? (live?.errors?.pause || live?.pause || false);
|
||||||
|
const isError = printer?.error ?? (live?.errors?.other || live?.error || false);
|
||||||
|
const isUnreachable = !isOnline || (live?.errors?.unreachable || false);
|
||||||
|
const labelLength = printer?.labelLength ?? live?.labelLength;
|
||||||
|
|
||||||
|
if (!isOnline) {
|
||||||
return (
|
return (
|
||||||
<Chip
|
<Chip
|
||||||
label="Offline"
|
label="Offline"
|
||||||
@@ -132,9 +139,8 @@ function renderPrinterDiagnostics(printer, live) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const errors = live.errors || {};
|
|
||||||
const errorChips = [];
|
const errorChips = [];
|
||||||
if (errors.headOpen) {
|
if (isOpen) {
|
||||||
errorChips.push(
|
errorChips.push(
|
||||||
<Chip
|
<Chip
|
||||||
key="headOpen"
|
key="headOpen"
|
||||||
@@ -145,7 +151,7 @@ function renderPrinterDiagnostics(printer, live) {
|
|||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (errors.pause) {
|
if (isPaused) {
|
||||||
errorChips.push(
|
errorChips.push(
|
||||||
<Chip
|
<Chip
|
||||||
key="pause"
|
key="pause"
|
||||||
@@ -156,7 +162,7 @@ function renderPrinterDiagnostics(printer, live) {
|
|||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (errors.unreachable) {
|
if (isUnreachable) {
|
||||||
errorChips.push(
|
errorChips.push(
|
||||||
<Chip
|
<Chip
|
||||||
key="unreachable"
|
key="unreachable"
|
||||||
@@ -167,7 +173,7 @@ function renderPrinterDiagnostics(printer, live) {
|
|||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (errors.other) {
|
if (isError) {
|
||||||
errorChips.push(
|
errorChips.push(
|
||||||
<Chip
|
<Chip
|
||||||
key="other"
|
key="other"
|
||||||
@@ -192,9 +198,9 @@ function renderPrinterDiagnostics(printer, live) {
|
|||||||
variant="outlined"
|
variant="outlined"
|
||||||
sx={{ fontSize: '0.7rem', height: 20, fontWeight: 600 }}
|
sx={{ fontSize: '0.7rem', height: 20, fontWeight: 600 }}
|
||||||
/>
|
/>
|
||||||
{live.labelLength != null ? (
|
{labelLength != null ? (
|
||||||
<Chip
|
<Chip
|
||||||
label={`Etikett: ${live.labelLength} px`}
|
label={`Etikett: ${labelLength} px`}
|
||||||
size="small"
|
size="small"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
sx={{ fontSize: '0.7rem', height: 20 }}
|
sx={{ fontSize: '0.7rem', height: 20 }}
|
||||||
@@ -227,6 +233,7 @@ export default class PrinterAgentSettingsPanel extends PureComponent {
|
|||||||
editingId: null,
|
editingId: null,
|
||||||
editNameDraft: '',
|
editNameDraft: '',
|
||||||
sortDrafts: {},
|
sortDrafts: {},
|
||||||
|
testingPrinterId: null,
|
||||||
};
|
};
|
||||||
this.handleRetry = this.handleRetry.bind(this);
|
this.handleRetry = this.handleRetry.bind(this);
|
||||||
this.handleCreateAgent = this.handleCreateAgent.bind(this);
|
this.handleCreateAgent = this.handleCreateAgent.bind(this);
|
||||||
@@ -241,6 +248,7 @@ export default class PrinterAgentSettingsPanel extends PureComponent {
|
|||||||
this.handleTogglePrinterEnabled = this.handleTogglePrinterEnabled.bind(this);
|
this.handleTogglePrinterEnabled = this.handleTogglePrinterEnabled.bind(this);
|
||||||
this.handleMovePrinter = this.handleMovePrinter.bind(this);
|
this.handleMovePrinter = this.handleMovePrinter.bind(this);
|
||||||
this.handleDeletePrinter = this.handleDeletePrinter.bind(this);
|
this.handleDeletePrinter = this.handleDeletePrinter.bind(this);
|
||||||
|
this.handleTestPrint = this.handleTestPrint.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@@ -467,6 +475,24 @@ export default class PrinterAgentSettingsPanel extends PureComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async handleTestPrint(printer) {
|
||||||
|
if (!printer?.id) return;
|
||||||
|
this.setState({ testingPrinterId: printer.id });
|
||||||
|
try {
|
||||||
|
await companyAutomat.actions.sendTestPrint(printer.id, {
|
||||||
|
model: printer.model || printer.type || 'Zebra',
|
||||||
|
});
|
||||||
|
enqueueSnackbar(
|
||||||
|
`Testdruck für ${printer.model || 'Drucker'} (#${printer.id}) an Drucker-Warteschlange gesendet.`,
|
||||||
|
{ variant: 'success' },
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
notifyError(err);
|
||||||
|
} finally {
|
||||||
|
this.setState({ testingPrinterId: null });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
error,
|
error,
|
||||||
@@ -479,6 +505,7 @@ export default class PrinterAgentSettingsPanel extends PureComponent {
|
|||||||
patchingAgentId,
|
patchingAgentId,
|
||||||
editingId,
|
editingId,
|
||||||
editNameDraft,
|
editNameDraft,
|
||||||
|
testingPrinterId,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
if (error && printeragents.length === 0) {
|
if (error && printeragents.length === 0) {
|
||||||
@@ -564,8 +591,6 @@ export default class PrinterAgentSettingsPanel extends PureComponent {
|
|||||||
const isEditing = editingId === agent.id;
|
const isEditing = editingId === agent.id;
|
||||||
const isPaired = agent.pairedAt != null;
|
const isPaired = agent.pairedAt != null;
|
||||||
const isEnabled = agent.enabled !== false;
|
const isEnabled = agent.enabled !== false;
|
||||||
const clientState = agent.clientstate;
|
|
||||||
const isOnline = clientState === 'online';
|
|
||||||
const pairedDateText = formatDateTime(agent.pairedAt);
|
const pairedDateText = formatDateTime(agent.pairedAt);
|
||||||
const lastseenText = formatDateTime(agent.lastseenAt) ?? 'Nie';
|
const lastseenText = formatDateTime(agent.lastseenAt) ?? 'Nie';
|
||||||
const updatedText = formatDateTime(agent.updatedAt) ?? '—';
|
const updatedText = formatDateTime(agent.updatedAt) ?? '—';
|
||||||
@@ -700,17 +725,6 @@ export default class PrinterAgentSettingsPanel extends PureComponent {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Live connection state */}
|
|
||||||
{clientState ? (
|
|
||||||
<Chip
|
|
||||||
label={isOnline ? 'Online' : 'Offline'}
|
|
||||||
size="small"
|
|
||||||
variant="outlined"
|
|
||||||
color={isOnline ? 'success' : 'default'}
|
|
||||||
sx={{ fontSize: '0.75rem', fontWeight: 600 }}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
{/* Agent version */}
|
{/* Agent version */}
|
||||||
{agent.agentversion ? (
|
{agent.agentversion ? (
|
||||||
<Tooltip title="Agent Software-Version">
|
<Tooltip title="Agent Software-Version">
|
||||||
@@ -931,6 +945,30 @@ export default class PrinterAgentSettingsPanel extends PureComponent {
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||||
|
{/* Test print button */}
|
||||||
|
<Tooltip title="Test-Etikett an Drucker senden (ZPL)">
|
||||||
|
<span>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
variant="outlined"
|
||||||
|
color="primary"
|
||||||
|
startIcon={<PrintOutlinedIcon sx={{ fontSize: 15 }} />}
|
||||||
|
disabled={testingPrinterId === p.id}
|
||||||
|
onClick={() => void this.handleTestPrint(p)}
|
||||||
|
sx={{
|
||||||
|
textTransform: 'none',
|
||||||
|
fontSize: '0.75rem',
|
||||||
|
py: 0.25,
|
||||||
|
px: 1,
|
||||||
|
minHeight: 26,
|
||||||
|
fontWeight: 600,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{testingPrinterId === p.id ? 'Druckt…' : 'Testdruck'}
|
||||||
|
</Button>
|
||||||
|
</span>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
{/* Enabled toggle switch */}
|
{/* Enabled toggle switch */}
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
control={
|
control={
|
||||||
|
|||||||
Reference in New Issue
Block a user