feat: layout hamburger, media browser filters+previews, billing fixes
- Layout: mobile hamburger menu + overlay backdrop + close button; content area always full-width - Media browser: filter chips (default still+turntable); advanced toggle for GLB/STL; thumbnail_url previews for non-image types; video hover-play for turntable - Backend: asset_types multi-filter, thumbnail_url in MediaAssetOut, download proxy endpoint for MinIO/local files - Admin: "Import Existing Media" button → POST /api/admin/import-media-assets - Billing: fix invoice create 500 (MissingGreenlet — use selectinload after commit); PDF download uses axios blob instead of bare <a href> (auth header missing); fix storage.upload() accepting str|Path - SSE task logs: task_logs.py core + router, LiveRenderLog component - CadPreview: fix infinite loop when no gltf_geometry assets; loading screen before ThreeDViewer render - render-worker: add trimesh layer to Dockerfile Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -141,6 +141,14 @@ export default function AdminPage() {
|
||||
onError: (e: any) => toast.error(e.response?.data?.detail || 'Failed'),
|
||||
})
|
||||
|
||||
const importMediaAssetsMut = useMutation({
|
||||
mutationFn: () => api.post('/admin/import-media-assets'),
|
||||
onSuccess: (res) => {
|
||||
toast.success(`Imported: ${res.data.created} created, ${res.data.skipped} skipped`)
|
||||
},
|
||||
onError: (e: any) => toast.error(e.response?.data?.detail || 'Import failed'),
|
||||
})
|
||||
|
||||
const generateMissingStlsMut = useMutation({
|
||||
mutationFn: () => api.post('/admin/settings/generate-missing-stls'),
|
||||
onSuccess: (res) => {
|
||||
@@ -666,6 +674,18 @@ export default function AdminPage() {
|
||||
</button>
|
||||
<p className="text-xs text-content-muted">Re-renders thumbnails for all completed CAD files.</p>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<button
|
||||
onClick={() => importMediaAssetsMut.mutate()}
|
||||
disabled={importMediaAssetsMut.isPending}
|
||||
className="btn-secondary text-sm w-full justify-start"
|
||||
title="Create MediaAsset records for all existing CAD thumbnails and order line renders"
|
||||
>
|
||||
<RefreshCw size={14} className={importMediaAssetsMut.isPending ? 'animate-spin' : ''} />
|
||||
{importMediaAssetsMut.isPending ? 'Importing…' : 'Import Existing Media'}
|
||||
</button>
|
||||
<p className="text-xs text-content-muted">Registers existing renders & CAD thumbnails in the Media Browser.</p>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<button
|
||||
onClick={() => generateMissingStlsMut.mutate()}
|
||||
|
||||
Reference in New Issue
Block a user