Skip to content

Commit da9d483

Browse files
author
Project Team
committed
Restore image display on results page; show image on error page
- ui_routes.py ui_verify_result: encode the saved image from disk as a base64 data URL and pass it to results.html (was hardcoded None since the async queue was introduced) - ui_routes.py: add GET /ui/verify/image/{job_id} endpoint that serves the raw image bytes directly from the shared volume - verify_pending.html: add an <img> element pointing at the new image endpoint, revealed in onFailed() so the user can see which label failed alongside the error detail and Retry button
1 parent 8be70a4 commit da9d483

File tree

2 files changed

+50
-2
lines changed

2 files changed

+50
-2
lines changed

app/templates/verify_pending.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,15 @@
5151
<i id="resultIcon" class="bi" style="font-size:4rem;"></i>
5252
</div>
5353

54+
<!-- Uploaded image (shown on failure so the user knows which image failed) -->
55+
<div id="imageArea" style="display:none;" class="my-3">
56+
<img id="labelImage"
57+
src="/ui/verify/image/{{ job_id }}"
58+
alt="Uploaded label"
59+
class="img-fluid rounded"
60+
style="max-height:220px; max-width:100%;">
61+
</div>
62+
5463
<h4 class="mb-2" id="statusHeading">Verifying Label</h4>
5564
<p class="text-muted mb-1" id="statusMessage">Your label is queued for verification.</p>
5665
<p class="small text-muted" id="queueInfo"></p>
@@ -95,6 +104,7 @@ <h4 class="mb-2" id="statusHeading">Verifying Label</h4>
95104
const elQueue = document.getElementById('queueInfo');
96105
const elSpinner = document.getElementById('spinnerArea');
97106
const elIcon = document.getElementById('iconArea');
107+
const elImageArea = document.getElementById('imageArea');
98108
const elResultIcon = document.getElementById('resultIcon');
99109
const elDots = [document.getElementById('dot1'),
100110
document.getElementById('dot2'),
@@ -171,6 +181,7 @@ <h4 class="mb-2" id="statusHeading">Verifying Label</h4>
171181
stopPolling();
172182
elSpinner.style.display = 'none';
173183
elIcon.style.display = 'block';
184+
elImageArea.style.display = 'block';
174185
elResultIcon.className = 'bi bi-exclamation-octagon-fill text-danger';
175186
elHeading.textContent = 'Verification Failed';
176187
elMessage.textContent = `All ${data.max_attempts} attempt(s) exhausted.`;

app/ui_routes.py

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,18 @@ async def ui_verify_result(
488488
)
489489

490490
result = job["result"]
491-
filename = Path(job["image_path"]).name
491+
image_path = Path(job["image_path"])
492+
filename = image_path.name
493+
494+
# Re-encode the saved image as a base64 data URL for display in the template
495+
image_data = None
496+
try:
497+
raw = image_path.read_bytes()
498+
suffix = image_path.suffix.lower()
499+
mime = "image/png" if suffix == ".png" else "image/jpeg"
500+
image_data = f"data:{mime};base64,{base64.b64encode(raw).decode()}"
501+
except Exception as e:
502+
logger.warning(f"Could not encode image for results page: {e}")
492503

493504
return templates.TemplateResponse(
494505
"results.html",
@@ -497,7 +508,7 @@ async def ui_verify_result(
497508
"username": username,
498509
"result": result,
499510
"filename": filename,
500-
"image_data": None, # Image file is on disk; we don't re-encode it here
511+
"image_data": image_data,
501512
}
502513
)
503514

@@ -552,6 +563,32 @@ async def ui_verify_retry(
552563
)
553564

554565

566+
@router.get("/ui/verify/image/{job_id}")
567+
async def ui_verify_image(
568+
request: Request,
569+
job_id: str,
570+
username: str = Depends(get_current_user_ui)
571+
):
572+
"""
573+
Serve the uploaded image for a verify job directly from the shared volume.
574+
Used by both the pending/error page and the results page.
575+
"""
576+
from api import verify_queue
577+
from fastapi.responses import Response
578+
579+
job = verify_queue.get(job_id)
580+
if job is None:
581+
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Job not found")
582+
583+
image_path = Path(job["image_path"])
584+
if not image_path.exists():
585+
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Image not found")
586+
587+
suffix = image_path.suffix.lower()
588+
media_type = "image/png" if suffix == ".png" else "image/jpeg"
589+
return Response(content=image_path.read_bytes(), media_type=media_type)
590+
591+
555592
@router.get("/ui/health", response_class=HTMLResponse)
556593
async def ui_health(request: Request):
557594
"""

0 commit comments

Comments
 (0)