Compare commits

...

2 Commits

Author SHA1 Message Date
Aiirondev_dev 0114fec928 changes to the physical scanner processing
Release Inventarsystem / release-docker (push) Successful in 12m48s
2026-09-08 18:19:40 +02:00
Aiirondev_dev b16ad56b98 New password option fo the tenant adding and heatlth check
Release Inventarsystem / release-docker (push) Successful in 3m16s
2026-08-27 11:31:07 +02:00
3 changed files with 53 additions and 23 deletions
+5 -2
View File
@@ -542,7 +542,8 @@ def _enforce_module_access():
msg = {
'library': "Bibliotheks-Modul ist deaktiviert.",
'inventory': "Inventar-Modul ist deaktiviert.",
'student_cards': "Schülerausweis-Modul ist deaktiviert."
'student_cards': "Schülerausweis-Modul ist deaktiviert.",
'terminplaner': "Termin-Modul ist deaktiviert."
}.get(name, f"{name.capitalize()}-Modul ist deaktiviert.")
if request.path.startswith('/api/') or request.is_json:
@@ -554,6 +555,8 @@ def _enforce_module_access():
return redirect(url_for('home_admin'))
elif name != 'library' and cfg.MODULES.is_enabled('library'):
return redirect('/library')
elif name != 'terminplaner' and cfg.MODULES.is_enabled('terminplaner'):
return redirect('/terminplaner')
return redirect(url_for('my_borrowed_items'))
@@ -706,7 +709,7 @@ def _action_access_allowed(permissions, action_key):
def _permission_denied_fallback_endpoint(permissions, current_endpoint=None):
username = session.get('username')
for candidate in ('home_admin', 'my_borrowed_items', 'tutorial_page', 'notifications_view', 'impressum'):
for candidate in ('home_admin', 'library_view', 'terminplaner', 'my_borrowed_items', 'tutorial_page', 'notifications_view', 'impressum'):
if current_endpoint and candidate == current_endpoint:
continue
if _page_access_allowed(permissions, candidate):
+30 -15
View File
@@ -843,6 +843,8 @@
let keyboardScanBuffer = '';
let keyboardLastKeyAt = 0;
const KEYBOARD_SCAN_INTERCHAR_MS = 100; // max time between keystrokes to consider them one scan
const physicalScanQueue = [];
let keyboardScanProcessing = false;
let editLibraryState = {
itemId: '',
seriesGroupId: '',
@@ -1188,38 +1190,49 @@
// Only active when explicitly enabled
if (!keyboardScannerEnabled) return;
// Ignore if focus is in an input/textarea/contenteditable to avoid interfering with typing
const active = document.activeElement;
if (active && (active.tagName === 'INPUT' || active.tagName === 'TEXTAREA' || active.isContentEditable)) return;
const now = Date.now();
// If Enter/Return pressed -> finalize buffer
if (e.key === 'Enter') {
e.preventDefault();
const code = keyboardScanBuffer.trim();
keyboardScanBuffer = '';
keyboardLastKeyAt = 0;
if (!code) return;
// Process exactly like a camera scan - centralized logic handles the rest!
handleScanSuccess(code);
// Scanner keystrokes must not be submitted into the focused form field.
processPhysicalScan(code);
return;
}
// Only accept common printable characters; ignore modifier keys
if (e.key.length === 1) {
// Physical scanners in this workflow emit numeric codes only.
if (e.key.length === 1 && /\d/.test(e.key)) {
// If time gap too big, start new buffer
if (keyboardLastKeyAt && (now - keyboardLastKeyAt) > KEYBOARD_SCAN_INTERCHAR_MS) {
keyboardScanBuffer = '';
}
keyboardScanBuffer += e.key;
keyboardLastKeyAt = now;
// Prevent default so scanner input doesn't accidentally move focus or trigger shortcuts
// Prevent default so scanner input is captured even while an input has focus.
e.preventDefault();
}
}
function handleScanSuccess(decodedText) {
async function processPhysicalScan(code) {
physicalScanQueue.push(code);
if (keyboardScanProcessing) return;
keyboardScanProcessing = true;
try {
while (physicalScanQueue.length > 0) {
await handleScanSuccess(physicalScanQueue.shift());
}
} finally {
keyboardScanProcessing = false;
}
}
async function handleScanSuccess(decodedText) {
const scannedCode = typeof normalizeScannedCode === "function" ? normalizeScannedCode(decodedText) : decodedText;
if (!scannedCode) return;
@@ -1235,26 +1248,27 @@
// 1. Modus: Nur Rückgabe
if (mode === 'return_only') {
returnByCode(scannedCode);
await returnByCode(scannedCode);
return;
}
// 2. Modus: Nur Ausweis
if (mode === 'card_only') {
setActiveStudentCard(scannedCode);
setScanStatus(`Ausweis gesetzt: ${activeStudentCardId}`, 'ok');
setScanStatus(`Ausweis gesetzt: ${activeStudentCardId}. Bitte den nächsten Ausweis scannen.`, 'ok');
showSmallConfirm(`Ausweis erkannt: ${activeStudentCardId}. Sie können den nächsten scannen.`, 'ok');
return;
}
// 3. Modus: Schnellmodus (1x Ausweis, 1x Buch)
if (mode === 'quick_toggle') {
processQuickToggleScan(scannedCode);
await processQuickToggleScan(scannedCode);
return;
}
// 4. Modus: Dauermodus (1x Ausweis, Nx Bücher)
if (mode === 'continuous') {
processContinuousScan(scannedCode);
await processContinuousScan(scannedCode);
return;
}
}
@@ -1341,7 +1355,8 @@
// 2. Wenn kein Ausweis gesetzt ist, wird der Code als Ausweis interpretiert
if (!activeStudentCardId) {
setActiveStudentCard(scannedCode);
setScanStatus(`Ausweis gesetzt: ${activeStudentCardId}`, 'ok');
setScanStatus(`Ausweis gesetzt: ${activeStudentCardId}. Bitte den nächsten Mediencode scannen.`, 'ok');
showSmallConfirm(`Ausweis erkannt: ${activeStudentCardId}. Bitte jetzt den nächsten Mediencode scannen.`, 'ok');
return;
}
+18 -6
View File
@@ -821,14 +821,26 @@ case "$COMMAND" in
exit 1
fi
PORT_ARG="${3:-}"
PASSWORD_ARG="${4:-admin123}" # Optional 4th parameter; defaults to 'admin123' if omitted
ARG3="${3:-}"
ARG4="${4:-}"
PORT_ARG=""
PASSWORD_ARG="admin123"
# Check if the 3rd argument is numeric (Port) or text (Password)
if [ -n "$ARG3" ]; then
if printf '%s\n' "$ARG3" | grep -qE '^[0-9]+$'; then
PORT_ARG="$ARG3"
if [ -n "$ARG4" ]; then
PASSWORD_ARG="$ARG4"
fi
else
# If ARG3 is not numeric, treat it as the password without setting a port
PASSWORD_ARG="$ARG3"
fi
fi
if [ -n "$PORT_ARG" ]; then
if ! printf '%s\n' "$PORT_ARG" | grep -qE '^[0-9]+$'; then
echo "Error: Port must be a numeric value."
exit 1
fi
register_tenant_port "$TENANT_ID" "$PORT_ARG"
update_runtime_ports "$PORT_ARG"
sync_tenant_port_map