feat(N): workflow pipeline, 3D viewer, worker management, QC tests
- workflow_builder.py: fix broken stubs, add render_order_line_still_task
(resolves step_path from DB instead of passing order_line_id as step_path)
- domains/rendering/tasks.py: add render_order_line_still_task,
export_gltf_for_order_line_task, export_blend_for_order_line_task,
generate_gltf_geometry_task (trimesh STL→GLB, no Blender needed)
- tasks/step_tasks.py: add generate_gltf_geometry_task for CadFile GLB export
- cad router: POST /{id}/generate-gltf-geometry endpoint (admin/PM)
- worker router: GET /celery-workers + POST /scale (docker compose subprocess)
- Dockerfile: pip install -e "[dev]" to enable pytest
- docker-compose.yml: docker socket + compose file mount on backend
- ThreeDViewer.tsx: mode toggle (geometry/production), wireframe, env presets,
download buttons (GLB + .blend)
- CadPreview.tsx: load gltf_geometry/gltf_production/blend_production assets
from MediaAsset table and pass URLs to ThreeDViewer
- ProductDetail.tsx: "View 3D" button → /cad/:id, "Generate GLB" button
- media router/service: cad_file_id filter on GET /api/media
- WorkerManagement.tsx: new page with worker status, queue depth, scale controls
- App.tsx + Layout.tsx: /workers route + sidebar link (admin/PM)
- tests: test_rendering_service.py, test_orders_service.py (backend)
- tests: WorkerActivity.test.tsx, WorkerManagement.test.tsx (frontend)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,36 +1,64 @@
|
||||
import { useParams, useNavigate } from 'react-router-dom'
|
||||
import { ArrowLeft } from 'lucide-react'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import ThreeDViewer from '../components/cad/ThreeDViewer'
|
||||
import { getMediaAssets } from '../api/media'
|
||||
|
||||
/**
|
||||
* Route: /cad/:id
|
||||
*
|
||||
* Renders the full-screen 3D viewer for a specific CAD file.
|
||||
* When the viewer is closed the user is navigated back.
|
||||
* Full-screen 3D viewer for a CAD file.
|
||||
* Passes production GLB URL if a gltf_geometry MediaAsset exists for this CAD file.
|
||||
*/
|
||||
export default function CadPreviewPage() {
|
||||
const { id } = useParams<{ id: string }>()
|
||||
const navigate = useNavigate()
|
||||
|
||||
// Load any geometry GLB that was generated for this CAD file
|
||||
const { data: gltfAssets } = useQuery({
|
||||
queryKey: ['media-assets', id, 'gltf_geometry'],
|
||||
queryFn: () => getMediaAssets({ cad_file_id: id!, asset_type: 'gltf_geometry' }),
|
||||
enabled: !!id,
|
||||
staleTime: 30_000,
|
||||
})
|
||||
|
||||
// Load production GLB if available
|
||||
const { data: productionAssets } = useQuery({
|
||||
queryKey: ['media-assets', id, 'gltf_production'],
|
||||
queryFn: () => getMediaAssets({ cad_file_id: id!, asset_type: 'gltf_production' }),
|
||||
enabled: !!id,
|
||||
staleTime: 30_000,
|
||||
})
|
||||
|
||||
// Load blend assets for download
|
||||
const { data: blendAssets } = useQuery({
|
||||
queryKey: ['media-assets', id, 'blend_production'],
|
||||
queryFn: () => getMediaAssets({ cad_file_id: id!, asset_type: 'blend_production' }),
|
||||
enabled: !!id,
|
||||
staleTime: 30_000,
|
||||
})
|
||||
|
||||
if (!id) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center h-full text-content-muted gap-4 p-8">
|
||||
<p className="text-lg">No CAD file ID provided.</p>
|
||||
<button
|
||||
onClick={() => navigate(-1)}
|
||||
className="flex items-center gap-2 text-sm text-accent hover:underline"
|
||||
>
|
||||
<ArrowLeft size={16} />
|
||||
Go back
|
||||
</button>
|
||||
<div className="flex items-center justify-center h-full text-content-muted p-8">
|
||||
<p>No CAD file ID provided.</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const latestGltf = gltfAssets?.[0]
|
||||
const latestProduction = productionAssets?.[0]
|
||||
const latestBlend = blendAssets?.[0]
|
||||
|
||||
return (
|
||||
<ThreeDViewer
|
||||
cadFileId={id}
|
||||
onClose={() => navigate(-1)}
|
||||
geometryGltfUrl={latestGltf?.download_url ?? undefined}
|
||||
productionGltfUrl={latestProduction?.download_url ?? undefined}
|
||||
downloadUrls={{
|
||||
glb: latestGltf?.download_url ?? undefined,
|
||||
blend: latestBlend?.download_url ?? undefined,
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user