fixes to the physical scanner functionality
Release Inventarsystem / release-docker (push) Successful in 3m15s
Release Inventarsystem / release-docker (push) Successful in 3m15s
This commit is contained in:
@@ -637,7 +637,7 @@
|
|||||||
<span class="close" id="closePhysicalScannerBtn" role="button" tabindex="0" aria-label="Physischen Scanner schließen">×</span>
|
<span class="close" id="closePhysicalScannerBtn" role="button" tabindex="0" aria-label="Physischen Scanner schließen">×</span>
|
||||||
<h2 id="physicalScannerTitle">Physischer Scanner</h2>
|
<h2 id="physicalScannerTitle">Physischer Scanner</h2>
|
||||||
<p id="physicalScannerInstruction">Scanner ist bereit. Bitte den angezeigten Code scannen.</p>
|
<p id="physicalScannerInstruction">Scanner ist bereit. Bitte den angezeigten Code scannen.</p>
|
||||||
<div id="physicalScannerCode" class="physical-scanner-code" aria-live="polite"></div>
|
<div id="physicalScannerCode" class="physical-scanner-code" tabindex="0" aria-label="Eingehender Scan" aria-live="polite"></div>
|
||||||
<p id="physicalScannerStatus" class="library-scan-status" aria-live="polite">Warte auf Scan...</p>
|
<p id="physicalScannerStatus" class="library-scan-status" aria-live="polite">Warte auf Scan...</p>
|
||||||
<button id="stopPhysicalScannerBtn" class="button" type="button">Scanner schließen</button>
|
<button id="stopPhysicalScannerBtn" class="button" type="button">Scanner schließen</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -873,7 +873,7 @@
|
|||||||
let keyboardScanBuffer = '';
|
let keyboardScanBuffer = '';
|
||||||
let keyboardLastKeyAt = 0;
|
let keyboardLastKeyAt = 0;
|
||||||
let physicalScannerModalOpen = false;
|
let physicalScannerModalOpen = false;
|
||||||
const KEYBOARD_SCAN_INTERCHAR_MS = 100; // max time between keystrokes to consider them one scan
|
const KEYBOARD_SCAN_INTERCHAR_MS = 500; // max time between slower scanner keystrokes
|
||||||
const physicalScanQueue = [];
|
const physicalScanQueue = [];
|
||||||
let keyboardScanProcessing = false;
|
let keyboardScanProcessing = false;
|
||||||
let editLibraryState = {
|
let editLibraryState = {
|
||||||
@@ -1249,7 +1249,7 @@
|
|||||||
modal.style.display = 'flex';
|
modal.style.display = 'flex';
|
||||||
updatePhysicalScannerModal('Warte auf Scan...', 'warn');
|
updatePhysicalScannerModal('Warte auf Scan...', 'warn');
|
||||||
document.addEventListener('keydown', keyboardScanKeydownHandler);
|
document.addEventListener('keydown', keyboardScanKeydownHandler);
|
||||||
document.getElementById('closePhysicalScannerBtn')?.focus();
|
document.getElementById('physicalScannerCode')?.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
function closePhysicalScannerModal() {
|
function closePhysicalScannerModal() {
|
||||||
@@ -1287,13 +1287,13 @@
|
|||||||
// Scanner keystrokes must not be submitted into the focused form field.
|
// Scanner keystrokes must not be submitted into the focused form field.
|
||||||
const displayCode = document.getElementById('physicalScannerCode');
|
const displayCode = document.getElementById('physicalScannerCode');
|
||||||
if (displayCode) displayCode.textContent = code;
|
if (displayCode) displayCode.textContent = code;
|
||||||
updatePhysicalScannerModal('Code empfangen. Verarbeitung läuft...', 'warn');
|
updatePhysicalScannerModal('Enter erkannt. Code wird verarbeitet...', 'warn');
|
||||||
processPhysicalScan(code);
|
processPhysicalScan(code);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Physical scanners in this workflow emit numeric codes only.
|
// Accept all printable scanner characters, including letters and punctuation.
|
||||||
if (e.key.length === 1 && /\d/.test(e.key)) {
|
if (e.key.length === 1) {
|
||||||
// If time gap too big, start new buffer
|
// If time gap too big, start new buffer
|
||||||
if (keyboardLastKeyAt && (now - keyboardLastKeyAt) > KEYBOARD_SCAN_INTERCHAR_MS) {
|
if (keyboardLastKeyAt && (now - keyboardLastKeyAt) > KEYBOARD_SCAN_INTERCHAR_MS) {
|
||||||
keyboardScanBuffer = '';
|
keyboardScanBuffer = '';
|
||||||
@@ -1316,7 +1316,8 @@
|
|||||||
while (physicalScanQueue.length > 0) {
|
while (physicalScanQueue.length > 0) {
|
||||||
await handleScanSuccess(physicalScanQueue.shift());
|
await handleScanSuccess(physicalScanQueue.shift());
|
||||||
if (physicalScannerModalOpen) {
|
if (physicalScannerModalOpen) {
|
||||||
updatePhysicalScannerModal('Aktion abgeschlossen. Bereit für den nächsten Scan.', 'ok');
|
const displayCode = document.getElementById('physicalScannerCode');
|
||||||
|
if (displayCode) displayCode.textContent = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@@ -1349,6 +1350,7 @@
|
|||||||
setActiveStudentCard(scannedCode);
|
setActiveStudentCard(scannedCode);
|
||||||
setScanStatus(`Ausweis gesetzt: ${activeStudentCardId}. Bitte den nächsten Ausweis scannen.`, 'ok');
|
setScanStatus(`Ausweis gesetzt: ${activeStudentCardId}. Bitte den nächsten Ausweis scannen.`, 'ok');
|
||||||
showSmallConfirm(`Ausweis erkannt: ${activeStudentCardId}. Sie können den nächsten scannen.`, 'ok');
|
showSmallConfirm(`Ausweis erkannt: ${activeStudentCardId}. Sie können den nächsten scannen.`, 'ok');
|
||||||
|
updatePhysicalScannerModal(`Ausweis erkannt. Bereit für den nächsten Scan.`, 'ok');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1374,6 +1376,7 @@
|
|||||||
setActiveStudentCard(scannedCode);
|
setActiveStudentCard(scannedCode);
|
||||||
setScanStatus(`Neuer Ausweis gesetzt: ${activeStudentCardId}. Bitte Medien scannen.`, 'ok');
|
setScanStatus(`Neuer Ausweis gesetzt: ${activeStudentCardId}. Bitte Medien scannen.`, 'ok');
|
||||||
showSmallConfirm(`Benutzer gewechselt zu: ${activeStudentCardId}`, 'ok');
|
showSmallConfirm(`Benutzer gewechselt zu: ${activeStudentCardId}`, 'ok');
|
||||||
|
updatePhysicalScannerModal('Ausweis erkannt. Jetzt Mediencodes scannen.', 'ok');
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (document.getElementById('scanModeSelect').value === 'continuous') {
|
if (document.getElementById('scanModeSelect').value === 'continuous') {
|
||||||
@@ -1386,6 +1389,7 @@
|
|||||||
if (!activeStudentCardId) {
|
if (!activeStudentCardId) {
|
||||||
setScanStatus('Kein Ausweis aktiv! Bitte zuerst einen Schülerausweis scannen.', 'error');
|
setScanStatus('Kein Ausweis aktiv! Bitte zuerst einen Schülerausweis scannen.', 'error');
|
||||||
showSmallConfirm('Bitte zuerst Ausweis scannen', 'error');
|
showSmallConfirm('Bitte zuerst Ausweis scannen', 'error');
|
||||||
|
updatePhysicalScannerModal('Kein Ausweis aktiv. Bitte zuerst den Ausweis scannen.', 'error');
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (document.getElementById('scanModeSelect').value === 'continuous') {
|
if (document.getElementById('scanModeSelect').value === 'continuous') {
|
||||||
@@ -1414,15 +1418,19 @@
|
|||||||
if (!response.ok || !result.ok) {
|
if (!response.ok || !result.ok) {
|
||||||
setScanStatus(result.message || 'Scan-Aktion fehlgeschlagen.', 'error');
|
setScanStatus(result.message || 'Scan-Aktion fehlgeschlagen.', 'error');
|
||||||
showSmallConfirm(result.message || 'Aktion fehlgeschlagen.', 'error');
|
showSmallConfirm(result.message || 'Aktion fehlgeschlagen.', 'error');
|
||||||
|
updatePhysicalScannerModal(result.message || 'Scan-Aktion fehlgeschlagen.', 'error');
|
||||||
} else if (result.action === 'borrowed') {
|
} else if (result.action === 'borrowed') {
|
||||||
setScanStatus(`Ausgeliehen: ${result.item_name}`, 'ok');
|
setScanStatus(`Ausgeliehen: ${result.item_name}`, 'ok');
|
||||||
showSmallConfirm(`Ausgeliehen: ${result.item_name}`, 'ok');
|
showSmallConfirm(`Ausgeliehen: ${result.item_name}`, 'ok');
|
||||||
|
updatePhysicalScannerModal('Ausleihe erfolgreich. Bereit für den nächsten Mediencode.', 'ok');
|
||||||
} else if (result.action === 'returned') {
|
} else if (result.action === 'returned') {
|
||||||
setScanStatus(`Zurückgegeben: ${result.item_name}`, 'ok');
|
setScanStatus(`Zurückgegeben: ${result.item_name}`, 'ok');
|
||||||
showSmallConfirm(`Zurückgegeben: ${result.item_name}`, 'ok');
|
showSmallConfirm(`Zurückgegeben: ${result.item_name}`, 'ok');
|
||||||
|
updatePhysicalScannerModal('Rückgabe erfolgreich. Bereit für den nächsten Mediencode.', 'ok');
|
||||||
} else {
|
} else {
|
||||||
setScanStatus(result.message || 'Aktion durchgeführt.', 'ok');
|
setScanStatus(result.message || 'Aktion durchgeführt.', 'ok');
|
||||||
showSmallConfirm(result.message || 'Erfolgreich', 'ok');
|
showSmallConfirm(result.message || 'Erfolgreich', 'ok');
|
||||||
|
updatePhysicalScannerModal('Aktion erfolgreich. Bereit für den nächsten Mediencode.', 'ok');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tabellen-Ansicht aktualisieren
|
// Tabellen-Ansicht aktualisieren
|
||||||
@@ -1433,6 +1441,7 @@
|
|||||||
console.error('Continuous scan action failed:', err);
|
console.error('Continuous scan action failed:', err);
|
||||||
setScanStatus('Fehler beim Verarbeiten des Scans.', 'error');
|
setScanStatus('Fehler beim Verarbeiten des Scans.', 'error');
|
||||||
showSmallConfirm('Fehler im Netzwerk/System', 'error');
|
showSmallConfirm('Fehler im Netzwerk/System', 'error');
|
||||||
|
updatePhysicalScannerModal('Fehler beim Verarbeiten. Bitte erneut scannen.', 'error');
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -1449,6 +1458,7 @@
|
|||||||
setActiveStudentCard(scannedCode);
|
setActiveStudentCard(scannedCode);
|
||||||
setScanStatus(`Ausweis gesetzt: ${activeStudentCardId}. Bitte den nächsten Mediencode scannen.`, 'ok');
|
setScanStatus(`Ausweis gesetzt: ${activeStudentCardId}. Bitte den nächsten Mediencode scannen.`, 'ok');
|
||||||
showSmallConfirm(`Ausweis erkannt: ${activeStudentCardId}. Bitte jetzt den nächsten Mediencode scannen.`, 'ok');
|
showSmallConfirm(`Ausweis erkannt: ${activeStudentCardId}. Bitte jetzt den nächsten Mediencode scannen.`, 'ok');
|
||||||
|
updatePhysicalScannerModal('Ausweis erkannt. Jetzt den Mediencode scannen.', 'ok');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1457,7 +1467,11 @@
|
|||||||
setScanStatus('Verarbeite Mediencode...', 'warn');
|
setScanStatus('Verarbeite Mediencode...', 'warn');
|
||||||
const response = await fetch('/api/library_scan_action', {
|
const response = await fetch('/api/library_scan_action', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {'Content-Type': 'application/json'},
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-CSRFToken': '{{ csrf_token }}',
|
||||||
|
'X-CSRF-Token': '{{ csrf_token }}'
|
||||||
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
student_card_id: activeStudentCardId,
|
student_card_id: activeStudentCardId,
|
||||||
item_code: scannedCode
|
item_code: scannedCode
|
||||||
@@ -1467,24 +1481,29 @@
|
|||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
if (!response.ok || !result.ok) {
|
if (!response.ok || !result.ok) {
|
||||||
setScanStatus(result.message || 'Scan-Aktion fehlgeschlagen.', 'error');
|
setScanStatus(result.message || 'Scan-Aktion fehlgeschlagen.', 'error');
|
||||||
|
updatePhysicalScannerModal(result.message || 'Scan-Aktion fehlgeschlagen.', 'error');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.action === 'borrowed') {
|
if (result.action === 'borrowed') {
|
||||||
setScanStatus(`Ausgeliehen: ${result.item_name}`, 'ok');
|
setScanStatus(`Ausgeliehen: ${result.item_name}`, 'ok');
|
||||||
showSmallConfirm(`Ausgeliehen: ${result.item_name}`, 'ok');
|
showSmallConfirm(`Ausgeliehen: ${result.item_name}`, 'ok');
|
||||||
|
updatePhysicalScannerModal('Ausleihe erfolgreich. Bereit für den nächsten Mediencode.', 'ok');
|
||||||
} else if (result.action === 'returned') {
|
} else if (result.action === 'returned') {
|
||||||
setScanStatus(`Zurückgegeben: ${result.item_name}`, 'ok');
|
setScanStatus(`Zurückgegeben: ${result.item_name}`, 'ok');
|
||||||
showSmallConfirm(`Zurückgegeben: ${result.item_name}`, 'ok');
|
showSmallConfirm(`Zurückgegeben: ${result.item_name}`, 'ok');
|
||||||
|
updatePhysicalScannerModal('Rückgabe erfolgreich. Bereit für den nächsten Mediencode.', 'ok');
|
||||||
} else {
|
} else {
|
||||||
setScanStatus(result.message || 'Aktion durchgeführt.', 'ok');
|
setScanStatus(result.message || 'Aktion durchgeführt.', 'ok');
|
||||||
showSmallConfirm(result.message || 'Aktion durchgeführt.', 'ok');
|
showSmallConfirm(result.message || 'Aktion durchgeführt.', 'ok');
|
||||||
|
updatePhysicalScannerModal('Aktion erfolgreich. Bereit für den nächsten Mediencode.', 'ok');
|
||||||
}
|
}
|
||||||
|
|
||||||
await loadLibraryItems();
|
await loadLibraryItems();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Quick scan action failed:', err);
|
console.error('Quick scan action failed:', err);
|
||||||
setScanStatus('Fehler beim Verarbeiten des Scans.', 'error');
|
setScanStatus('Fehler beim Verarbeiten des Scans.', 'error');
|
||||||
|
updatePhysicalScannerModal('Fehler beim Verarbeiten. Bitte erneut scannen.', 'error');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1501,16 +1520,19 @@
|
|||||||
if (!resp.ok || !result.ok) {
|
if (!resp.ok || !result.ok) {
|
||||||
setScanStatus(result.message || 'Rückgabe fehlgeschlagen.', 'error');
|
setScanStatus(result.message || 'Rückgabe fehlgeschlagen.', 'error');
|
||||||
showSmallConfirm(result.message || 'Rückgabe fehlgeschlagen.', 'error');
|
showSmallConfirm(result.message || 'Rückgabe fehlgeschlagen.', 'error');
|
||||||
|
updatePhysicalScannerModal(result.message || 'Rückgabe fehlgeschlagen.', 'error');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
setScanStatus(result.message || `Zurückgegeben: ${result.item_name || ''}`, 'ok');
|
setScanStatus(result.message || `Zurückgegeben: ${result.item_name || ''}`, 'ok');
|
||||||
showSmallConfirm(result.message || `Zurückgegeben: ${result.item_name || ''}`, 'ok');
|
showSmallConfirm(result.message || `Zurückgegeben: ${result.item_name || ''}`, 'ok');
|
||||||
|
updatePhysicalScannerModal('Rückgabe erfolgreich. Bereit für den nächsten Mediencode.', 'ok');
|
||||||
await loadLibraryItems();
|
await loadLibraryItems();
|
||||||
return true;
|
return true;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Return by code failed:', err);
|
console.error('Return by code failed:', err);
|
||||||
setScanStatus('Fehler bei Rückgabe.', 'error');
|
setScanStatus('Fehler bei Rückgabe.', 'error');
|
||||||
showSmallConfirm('Fehler bei Rückgabe.', 'error');
|
showSmallConfirm('Fehler bei Rückgabe.', 'error');
|
||||||
|
updatePhysicalScannerModal('Fehler bei Rückgabe. Bitte erneut scannen.', 'error');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user