Compare commits
3 Commits
726a4d3c02
...
fc13d905db
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fc13d905db | ||
|
|
ab52721c7f | ||
|
|
1e74b3a149 |
@@ -265,13 +265,25 @@ def job_detail(job_id: int, request: Request, db: Session = Depends(get_db)):
|
|||||||
job = db.query(PrintJob).filter(PrintJob.id == job_id).first()
|
job = db.query(PrintJob).filter(PrintJob.id == job_id).first()
|
||||||
if not job:
|
if not job:
|
||||||
raise HTTPException(status_code=404, detail="Job not found")
|
raise HTTPException(status_code=404, detail="Job not found")
|
||||||
stl = db.query(StlCache).filter_by(filename=job.file_name).first() if job.file_name else None
|
|
||||||
|
file_missing = False
|
||||||
|
stl = None
|
||||||
|
if job.file_name:
|
||||||
|
file_path = get_stl_dir() / job.file_name
|
||||||
|
if not file_path.exists():
|
||||||
|
file_missing = True
|
||||||
|
else:
|
||||||
|
stl = db.query(StlCache).filter_by(filename=job.file_name).first()
|
||||||
|
if stl is None and not job.file_name.endswith(".gcode"):
|
||||||
|
stl = analyse(job.file_name, db)
|
||||||
|
|
||||||
estimation = estimate(stl.volume_ccm, job.job_material) if stl and stl.volume_ccm else None
|
estimation = estimate(stl.volume_ccm, job.job_material) if stl and stl.volume_ccm else None
|
||||||
return templates.TemplateResponse("job_detail.html", {
|
return templates.TemplateResponse("job_detail.html", {
|
||||||
"request": request,
|
"request": request,
|
||||||
"active": "jobs",
|
"active": "jobs",
|
||||||
"job": job,
|
"job": job,
|
||||||
"stl": stl,
|
"stl": stl,
|
||||||
|
"file_missing": file_missing,
|
||||||
"estimation": estimation,
|
"estimation": estimation,
|
||||||
"printers": db.query(Printer).order_by(Printer.name).all(),
|
"printers": db.query(Printer).order_by(Printer.name).all(),
|
||||||
"brackets": db.query(JobBracket).order_by(JobBracket.name).all(),
|
"brackets": db.query(JobBracket).order_by(JobBracket.name).all(),
|
||||||
|
|||||||
@@ -23,7 +23,11 @@ def analyse(filename: str, db: Session) -> StlCache | None:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
import trimesh
|
import trimesh
|
||||||
mesh = trimesh.load(str(filepath), force="mesh")
|
loaded = trimesh.load(str(filepath))
|
||||||
|
if isinstance(loaded, trimesh.Scene):
|
||||||
|
mesh = trimesh.util.concatenate(list(loaded.geometry.values()))
|
||||||
|
else:
|
||||||
|
mesh = loaded
|
||||||
extents = mesh.extents # [size_x, size_y, size_z] in mm
|
extents = mesh.extents # [size_x, size_y, size_z] in mm
|
||||||
volume_mm3 = abs(mesh.volume) # mm³ (negative for inverted normals)
|
volume_mm3 = abs(mesh.volume) # mm³ (negative for inverted normals)
|
||||||
entry = StlCache(
|
entry = StlCache(
|
||||||
|
|||||||
@@ -103,7 +103,7 @@
|
|||||||
<div class="card h-100">
|
<div class="card h-100">
|
||||||
<div class="card-header border-secondary d-flex align-items-center justify-content-between" style="border-color:#21262d">
|
<div class="card-header border-secondary d-flex align-items-center justify-content-between" style="border-color:#21262d">
|
||||||
<span class="text-secondary small text-uppercase fw-normal">File & Geometry</span>
|
<span class="text-secondary small text-uppercase fw-normal">File & Geometry</span>
|
||||||
{% if job.file_name %}
|
{% if job.file_name and not file_missing %}
|
||||||
<div class="d-flex gap-2">
|
<div class="d-flex gap-2">
|
||||||
<a href="/files/{{ job.file_name }}" class="btn btn-outline-primary btn-sm py-0 px-2" style="font-size:.75rem" download>
|
<a href="/files/{{ job.file_name }}" class="btn btn-outline-primary btn-sm py-0 px-2" style="font-size:.75rem" download>
|
||||||
<i class="bi bi-download me-1"></i>Download
|
<i class="bi bi-download me-1"></i>Download
|
||||||
@@ -122,7 +122,12 @@
|
|||||||
{% if job.file_name %}
|
{% if job.file_name %}
|
||||||
<div class="text-white mb-3 font-monospace" style="font-size:.85rem">{{ job.file_name }}</div>
|
<div class="text-white mb-3 font-monospace" style="font-size:.85rem">{{ job.file_name }}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if stl %}
|
{% if file_missing %}
|
||||||
|
<div class="alert alert-danger py-2 px-3 mb-0" style="font-size:.875rem">
|
||||||
|
<i class="bi bi-exclamation-triangle-fill me-2"></i>
|
||||||
|
File <code>{{ job.file_name }}</code> not found on disk.
|
||||||
|
</div>
|
||||||
|
{% elif stl %}
|
||||||
<table class="table table-dark table-sm mb-0" style="font-size:.875rem">
|
<table class="table table-dark table-sm mb-0" style="font-size:.875rem">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr><td class="text-secondary border-0">Bounding box</td>
|
<tr><td class="text-secondary border-0">Bounding box</td>
|
||||||
@@ -136,7 +141,7 @@
|
|||||||
{% elif job.file_name and job.file_name.endswith('.gcode') %}
|
{% elif job.file_name and job.file_name.endswith('.gcode') %}
|
||||||
<p class="text-secondary small mb-0">Geometry not available for gcode files.</p>
|
<p class="text-secondary small mb-0">Geometry not available for gcode files.</p>
|
||||||
{% elif job.file_name %}
|
{% elif job.file_name %}
|
||||||
<p class="text-secondary small mb-0">Not yet analysed.</p>
|
<p class="text-secondary small mb-0">Analysis failed — check file format.</p>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p class="text-secondary small mb-0">No file attached.</p>
|
<p class="text-secondary small mb-0">No file attached.</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -7,4 +7,6 @@ cryptography==44.0.3
|
|||||||
jinja2==3.1.4
|
jinja2==3.1.4
|
||||||
python-multipart==0.0.20
|
python-multipart==0.0.20
|
||||||
trimesh==4.5.3
|
trimesh==4.5.3
|
||||||
|
networkx
|
||||||
|
lxml
|
||||||
httpx==0.28.1
|
httpx==0.28.1
|
||||||
|
|||||||
Reference in New Issue
Block a user