feat: Default to OCR scanner, auto-start camera, hide viewport after capture
- Default add-asset mode changed from barcode to OCR - Auto-start OCR camera when switching to OCR mode or Add Asset tab - Camera viewport hidden entirely after photo capture (no placeholder showing) - Retake button added to all OCR result states (found, not-found, error) - 'Retake' resets UI and re-starts camera for a new photo
This commit is contained in:
Binary file not shown.
Binary file not shown.
+7
-13
@@ -1,16 +1,10 @@
|
||||
#!/bin/bash
|
||||
# Restart canteen-asset-tracker server
|
||||
cd /home/oplabs/projects/canteen-asset-tracker
|
||||
|
||||
# Kill existing server
|
||||
pkill -f "python.*server.py" 2>/dev/null || true
|
||||
pkill -f "uvicorn.*server:app.*8901" 2>/dev/null || true
|
||||
sleep 1
|
||||
|
||||
# Activate venv and start
|
||||
source .venv/bin/activate
|
||||
nohup python server.py > /tmp/canteen-server.log 2>&1 &
|
||||
echo "Server PID: $!"
|
||||
sleep 3
|
||||
|
||||
# Check health
|
||||
curl -s http://localhost:8901/health 2>/dev/null || curl -s http://localhost:8900/health 2>/dev/null || echo "Health check failed"
|
||||
python -m uvicorn server:app --host 0.0.0.0 --port 8901 \
|
||||
--ssl-keyfile key.pem --ssl-certfile cert.pem --log-level info \
|
||||
> /tmp/canteen-server.log 2>&1 &
|
||||
echo "PID=$!"
|
||||
sleep 2
|
||||
curl -sk https://localhost:8901/health 2>/dev/null
|
||||
|
||||
+35
-9
@@ -2438,9 +2438,13 @@
|
||||
el.classList.toggle('active', el.dataset.tab === tabId);
|
||||
});
|
||||
|
||||
// Tab lifecycle hooks
|
||||
if (tabId === 'tabAddAsset') startScanning();
|
||||
else stopScanning();
|
||||
// Tab lifecycle hooks — start the appropriate scanner
|
||||
if (tabId === 'tabAddAsset') {
|
||||
if (addAssetMode === 'ocr') startOcrCamera();
|
||||
else startScanning();
|
||||
} else {
|
||||
stopScanning();
|
||||
}
|
||||
|
||||
if (tabId === 'tabAssets') { loadAssets(); }
|
||||
|
||||
@@ -2553,7 +2557,7 @@
|
||||
// ═══════════════════════════════════════════════════════════════════════
|
||||
// ADD ASSET TAB — 3 Modes: Barcode, OCR, Manual
|
||||
// ═══════════════════════════════════════════════════════════════════════
|
||||
let addAssetMode = 'barcode';
|
||||
let addAssetMode = 'ocr';
|
||||
let stream = null;
|
||||
let ocrStream = null;
|
||||
let codeReader = null;
|
||||
@@ -2582,6 +2586,8 @@
|
||||
|
||||
if (mode === 'barcode') {
|
||||
startScanning();
|
||||
} else if (mode === 'ocr') {
|
||||
startOcrCamera();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3133,7 +3139,8 @@
|
||||
<div class="or-id">${esc(data.machine_id)}${methodBadge}</div>
|
||||
<div class="or-meta">${confLabel}</div>
|
||||
${data.raw_text ? `<div class="or-raw">OCR text: ${esc(data.raw_text)}</div>` : ''}
|
||||
<div class="or-searching" style="margin-top:8px;font-size:13px;color:var(--text2);">🔍 Searching for asset...</div>`;
|
||||
<div class="or-searching" style="margin-top:8px;font-size:13px;color:var(--text2);">🔍 Searching for asset...</div>
|
||||
<div style="margin-top:8px;"><button class="btn btn-outline btn-sm" onclick="retakeOcr()" style="width:100%;">🔄 Retake</button></div>`;
|
||||
setOcrStatus('Machine ID found! Searching...', 'working');
|
||||
|
||||
// Auto-search the asset
|
||||
@@ -3142,7 +3149,8 @@
|
||||
el.innerHTML = `
|
||||
<div style="font-size:16px;font-weight:600;color:var(--red);">No machine ID detected</div>
|
||||
<div class="or-meta">Try again with better lighting and focus on the sticker.</div>
|
||||
${data.raw_text ? `<div class="or-raw">OCR text: ${esc(data.raw_text)}</div>` : ''}`;
|
||||
${data.raw_text ? `<div class="or-raw">OCR text: ${esc(data.raw_text)}</div>` : ''}
|
||||
<div style="margin-top:8px;"><button class="btn btn-outline btn-sm" onclick="retakeOcr()" style="width:100%;">🔄 Try Again</button></div>`;
|
||||
setOcrStatus('No machine ID found — try again', 'error');
|
||||
}
|
||||
|
||||
@@ -3215,15 +3223,17 @@
|
||||
el.innerHTML += `<div style="margin-top:8px;font-size:12px;color:var(--green);">${gi("📍")} GPS saved to asset</div>`;
|
||||
AppState.ocrGpsSaved = false;
|
||||
}
|
||||
el.innerHTML += `<div style="margin-top:8px;">
|
||||
<button class="btn btn-outline btn-sm" onclick="switchTab('tabAssets');viewAsset(${asset.id});" style="width:100%;">View Details</button>
|
||||
el.innerHTML += `<div style="margin-top:8px;display:flex;gap:6px;">
|
||||
<button class="btn btn-outline btn-sm" onclick="switchTab('tabAssets');viewAsset(${asset.id});" style="flex:1;">View Details</button>
|
||||
<button class="btn btn-outline btn-sm" onclick="retakeOcr()" style="flex:1;">🔄 Retake</button>
|
||||
</div>`;
|
||||
} catch (e) {
|
||||
if (e.message === 'Asset not found' || e.message.includes('404')) {
|
||||
const el = document.getElementById('ocrResult');
|
||||
el.innerHTML = `
|
||||
<div class="or-id">${esc(machineId)} ❌</div>
|
||||
<div class="or-meta" style="color:var(--amber);">Machine ID not found in database</div>`;
|
||||
<div class="or-meta" style="color:var(--amber);">Machine ID not found in database</div>
|
||||
<div style="margin-top:8px;"><button class="btn btn-outline btn-sm" onclick="retakeOcr()" style="width:100%;">🔄 Retake</button></div>`;
|
||||
setOcrStatus('Asset not found — try scanning the barcode instead', 'error');
|
||||
} else {
|
||||
setOcrStatus('Lookup error: ' + e.message, 'error');
|
||||
@@ -3262,6 +3272,18 @@
|
||||
};
|
||||
}
|
||||
|
||||
// ── Retake OCR photo after capture ──────────────────────────────────
|
||||
function retakeOcr() {
|
||||
// Reset the OCR UI for a new capture
|
||||
document.getElementById('ocrResult').style.display = 'none';
|
||||
document.getElementById('ocrResult').innerHTML = '';
|
||||
document.getElementById('ocrGpsBadge').style.display = 'none';
|
||||
setOcrStatus('', '');
|
||||
const camArea = document.getElementById('ocrCameraArea');
|
||||
if (camArea) camArea.style.display = '';
|
||||
startOcrCamera();
|
||||
}
|
||||
|
||||
async function captureOcr() {
|
||||
const video = document.getElementById('ocrVideo');
|
||||
if (!video || !ocrStream) return;
|
||||
@@ -3275,6 +3297,10 @@
|
||||
// Stop camera after capturing photo
|
||||
stopOcrCamera();
|
||||
|
||||
// Hide the camera viewport entirely — don't show placeholder after capture
|
||||
const camArea = document.getElementById('ocrCameraArea');
|
||||
if (camArea) camArea.style.display = 'none';
|
||||
|
||||
setOcrStatus('Processing OCR...', 'working');
|
||||
document.getElementById('ocrResult').style.display = 'none';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user