Files
HartOMat/plan.md
T
Hartmut bfd58e3419 fix: media thumbnails, product dimensions, inline 3D viewer, GLB export
Bug A: Media Library thumbnails were gray because <img src> cannot send
JWT auth headers. Added useAuthBlob() hook (fetch + createObjectURL) in
MediaBrowser.tsx. Also fixed publish_asset Celery task to populate
product_id + cad_file_id on MediaAsset for thumbnail fallback resolution.

Bug B: Product dimensions now shown in Product Details card with Ruler
icon and "from CAD" label when cad_mesh_attributes.dimensions_mm exists.

Bug C: Replaced 128×128 CAD thumbnail with InlineCadViewer component.
Queries gltf_geometry MediaAssets, fetches GLB via auth fetch → blob URL
→ Three.js Canvas with OrbitControls. Falls back to thumbnail + "Load 3D
Model" button. Polling when GLB generation is in progress.

Bug D: trimesh was in [cad] optional extra but Dockerfile only installed
[dev]. Changed to pip install -e ".[dev,cad]" — trimesh now available in
backend container, GLB + Colors export works.

Also added bbox extraction (STL-first numpy parsing) in render_step_thumbnail
and admin "Re-extract CAD Metadata" bulk endpoint.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 13:27:46 +01:00

4.8 KiB
Raw Blame History

Plan: 4 Bug Fixes — Media Thumbnails, Product Dimensions, Inline 3D Viewer, GLB Export

Root Cause Analysis

Bug A — Missing Thumbnails in Media Library

<img src="/api/media/{id}/download"> fails silently: the download endpoint requires JWT auth, but <img> tags don't send auth headers → 401 → imgError=true → gray icon. For thumbnail type assets: fallback works via get_thumbnail_url()/api/cad/{cad_file_id}/thumbnail (no-auth endpoint). For still type: no cad_file_id/product_id → no fallback → gray icon shown.

Bug B — No Dimensions in "Product Details" Card

The cad_mesh_attributes.dimensions_mm block exists in the CAD File section (right sidebar), NOT in the "Product Details" card. User wants it in Product Details.

Bug C — No Embedded 3D Viewer

"View 3D" navigates to /cad/:id (full page). User wants an inline viewer in the product page CAD card that auto-loads when a gltf_geometry asset exists.

Bug D — GLB + Colors Error

trimesh is in pyproject.toml but the backend container was not rebuilt → ModuleNotFoundError: No module named 'trimesh'. Needs rebuild.


Betroffene Dateien

File Change Bug
frontend/src/pages/MediaBrowser.tsx useAuthBlob hook + use in AssetCard A
backend/app/domains/rendering/tasks.py publish_asset populates product_id + cad_file_id A
frontend/src/pages/ProductDetail.tsx Add dimensions to Product Details card + inline viewer B, C
frontend/src/components/cad/InlineCadViewer.tsx New compact 3D viewer component C
backend/ (docker rebuild) Rebuild to install trimesh D

Tasks (in Reihenfolge)

Task A1: Backend — publish_asset populates product_id + cad_file_id

  • Datei: backend/app/domains/rendering/tasks.py
  • Was: In publish_asset, after loading the OrderLine, also load line.product_id and the product's cad_file_id. Set these on the new MediaAsset. This enables the _resolve_thumbnails_bulk fallback and get_thumbnail_url() for still assets.
  • Akzeptanzkriterium: New still assets have product_id and cad_file_id set in DB.

Task A2: Frontend — useAuthBlob hook in MediaBrowser

  • Datei: frontend/src/pages/MediaBrowser.tsx
  • Was: Add useAuthBlob(url) hook that fetches the URL with Authorization header and returns a blob URL. Use it in AssetCard instead of asset.download_url for image rendering. Revoke blob URL on unmount.
  • Akzeptanzkriterium: Still images visible in media library grid.

Task B: Frontend — Dimensions in Product Details card

  • Datei: frontend/src/pages/ProductDetail.tsx
  • Was: In the "Product Details" card (around line 409-433), after the Notes field, add a read-only "Dimensions" row if product.cad_mesh_attributes?.dimensions_mm exists. Format: "X × Y × Z mm" with a Ruler icon and small "from CAD" label.
  • Akzeptanzkriterium: Dimensions visible in Product Details card when mesh_attributes populated.

Task C: Frontend — Inline 3D Viewer in CAD card

  • Datei: frontend/src/components/cad/InlineCadViewer.tsx (new), frontend/src/pages/ProductDetail.tsx
  • Was:
    1. Create InlineCadViewer component that:
      • Accepts cadFileId: string
      • Queries getMediaAssets({ cad_file_id, asset_types: ['gltf_geometry'] })
      • If asset found: fetches GLB with auth (axios → arraybuffer → blob URL) → renders Three.js canvas (OrbitControls, auto-fit camera)
      • While loading: shows spinner
      • If no asset: shows "Generate GLB" button + thumbnail fallback
    2. In ProductDetail: replace the 128×128 thumbnail box with InlineCadViewer (make it ~300px tall)
      • Move thumbnail fallback inside InlineCadViewer
      • Keep "View 3D" as "View Full Screen" link below viewer
      • Remove standalone "View 3D" button (or keep as secondary link)
  • Akzeptanzkriterium: Inline 3D model visible in product page without clicking "View 3D".

Task D: Backend rebuild — install trimesh

  • Was: Run docker compose up -d --build backend to install trimesh from pyproject.toml
  • Akzeptanzkriterium: docker compose exec backend python3 -c "import trimesh; print('ok')" succeeds. GLB + Colors download works.

Migrations-Check

Keine DB-Migrationen nötig. product_id und cad_file_id sind bereits Spalten in media_assets.

Reihenfolge-Empfehlung

A1 + A2 + B + C parallel (alle unabhängig). D parallel (nur Docker rebuild, kein Code).

Risiken / Offene Fragen

  • useAuthBlob creates blob URLs per asset — 50+ assets in grid could trigger many fetches. Add limit or lazy load (only fetch when card is visible).
  • InlineCadViewer: GLB fetch for large files may take 5-30s. Show skeleton/spinner.
  • useGLTF from drei expects a URL string. Blob URLs work fine.
  • ThreeDViewer has onClose required prop — InlineCadViewer should be a new simpler component.