Hartmut
ced64055f2
refactor(admin): remove Pillow as selectable renderer, restructure admin page
...
- Backend: VALID_RENDERERS = {"blender"} only; remove pillow from renderer-status response
- Frontend: remove renderer picker (pillow/blender buttons) — Blender is the only renderer
- Blender options always visible, grouped into Render Quality / Performance / Output sections
- Maintenance buttons in 2-column grid with descriptions
- Page reorder: Pricing Summary → Users → Blender Settings → Render Templates →
Asset Libraries → Output Types → Pricing Tiers → SMTP → Templates
- Pillow code kept internally as fallback (not exposed in UI)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-06 21:20:28 +01:00
Hartmut
a18d4c23ec
feat(K): Blender Asset Library + production exports (GLB + .blend)
...
- feat(migration): 045_asset_libraries — new asset_libraries table (blend_file_path, catalog JSONB)
- feat(model): AssetLibrary SQLAlchemy model in domains/materials/models.py
- feat(api): POST/GET/PATCH/DELETE /api/asset-libraries + /upload-blend + /refresh-catalog endpoints
- feat(celery): refresh_asset_library_catalog task on thumbnail_rendering queue — runs Blender headless
- feat(blender): catalog_assets.py — extracts asset-marked materials + node_groups from .blend
- feat(blender): asset_library.py — apply_asset_library_materials + apply_asset_library_node_groups helpers
- feat(blender): export_gltf.py — STEP→STL→GLB production export with optional asset library
- feat(blender): export_blend.py — STEP→STL→.blend production export with pack_all()
- feat(frontend): api/assetLibraries.ts — full CRUD API client
- feat(frontend): AssetLibraryPanel in Admin.tsx — upload, refresh, expand catalog view
- docs: Blender asset_data marking requirement learning in LEARNINGS.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-06 20:56:26 +01:00
Hartmut
7a1329958d
feat(J): WebSocket live-events + replace polling + fix ffmpeg turntable timeout
...
- fix(render): ffmpeg overlay=0:0 -> overlay=0:0:shortest=1 to prevent hang on finite PNG sequences
- feat(ws): add core/websocket.py ConnectionManager + Redis Pub/Sub subscriber loop
- feat(ws): add /api/ws WebSocket endpoint with JWT query-param auth in main.py
- feat(ws): emit render_complete/failed + cad_processing_complete events from step_tasks.py
- feat(ws): emit order_status_change events from orders router
- feat(ws): add beat_tasks.py broadcast_queue_status task (every 10s via Redis __broadcast__)
- feat(frontend): add useWebSocket hook with auto-reconnect (exponential backoff, 25s ping)
- feat(frontend): add WebSocketContext + WebSocketProvider wrapping App
- refactor(frontend): remove polling from WorkerActivity (was 5s/3s) + OrderDetail (was 5s)
- refactor(frontend): reduce polling in Layout (8s->60s) + NotificationCenter (15s->60s)
- docs: add ffmpeg shortest=1 + WebSocket JWT auth learnings to LEARNINGS.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-06 20:49:34 +01:00
Hartmut
d138bc4bc4
feat(activity): merge CAD + render jobs into unified timeline
...
- Single chronological list sorted by updated_at (newest first)
- Type badges distinguish CAD processing (FileCode2) from Render jobs (Image)
- Render job rows now link directly to the order (/orders/:id)
- Remove separate "Render Jobs" and "CAD File Processing" sections
- Stat cards simplified to 4: CAD active/failed + Render active/failed
- Backend: add order_id to RenderJobEntry response
- Frontend: add order_id to RenderJobEntry interface, remove flamenco_job_id
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-06 20:01:03 +01:00
Hartmut
ab3f9c734a
fix: render pipeline + multi-tenancy bugs (B-Fix-1 through B-Fix-9)
...
- Remove worker-thumbnail (no Blender, was competing on thumbnail_rendering)
- Move render_order_line_task to thumbnail_rendering queue (render-worker)
- Restore template_service.py real implementation (fix circular import shim)
- Thread tenant_id through STEP upload, Excel import, product create
- Make system tables (output_types, materials, etc.) tenant_id nullable
- Fix tenants frontend 307-redirect: use trailing slash /tenants/
- Remove Flamenco + Three.js from Admin UI (unsupported)
- Set all output_types render_backend to celery (was flamenco)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-06 19:34:20 +01:00
Hartmut
df02067687
fix(ui): theme WorkflowEditor for dark mode
...
Replace all hardcoded gray-*/white Tailwind classes with semantic CSS
variable tokens (bg-surface, text-content, border-border-default, etc.)
so the page respects dark/light mode correctly.
- Sidebar, header bar, toolbar: bg-surface + border-border-default
- Node cards: bg-surface + border-accent (selected) / border-border-default
- ConfigSidepanel: bg-surface, text-content-secondary labels
- NewWorkflowModal: bg-surface, border-border-default inputs, accent buttons
- Workflow list items: bg-accent-light highlight for selected, hover:bg-surface-hover
- Empty state icon: text-content-muted
- ReactFlow: colorMode prop tied to useThemeStore (dark/light)
- Background: removed hardcoded #e5e7eb dot color (uses ReactFlow colorMode)
- All blue-600 buttons → bg-accent / hover:bg-accent-hover
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-06 18:21:35 +01:00
Hartmut
c0ea60d984
fix: resolve open risks — invoice race condition, SMTP config, workflow seeds
...
- billing/service.py: pg_advisory_xact_lock on invoice_number_seq per year
→ prevents duplicate INV-YYYY-NNNN under concurrent requests
- admin.py: SMTP settings in system_settings (smtp_host/port/user/password/
from_address/enabled) with GET+PUT support; seed-workflows endpoint creates
4 standard workflow definitions (still-cycles, still-eevee, turntable,
multi-angle) idempotently
- notifications/service.py: send_email_notification_stub now sends real
SMTP email via smtplib when smtp_enabled=true in system_settings
- Admin.tsx: SMTP settings panel (host/port/user/password/from + enable
toggle, save button); Seed Standard Workflows maintenance button
- Upload.tsx: fix TS error — title→aria-label on Lucide icons
- Admin.tsx Settings type: add render_backend/flamenco_* fields (TS fix)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-06 18:15:45 +01:00
Hartmut
f19a6ccde8
feat(F-G-H-I): STL cache, invoices, import validation, notification settings
...
Phase F — STL Hash Cache:
- Migration 041: step_file_hash column on cad_files
- cache_service.py: SHA256 hash + MinIO-backed STL cache (check/store)
- render_step_thumbnail: compute+persist hash before render
- generate_stl_cache: check MinIO cache before cadquery conversion, store after
Phase G — Invoices:
- Migration 042: invoices + invoice_lines tables with RLS
- Invoice/InvoiceLine models + schemas
- billing service: generate_invoice_number (INV-YYYY-NNNN), create/list/get/delete/PDF
- WeasyPrint PDF generation; backend Dockerfile + pyproject.toml deps
- invoice_router with 6 endpoints; registered in main.py
- frontend: Billing.tsx page + api/billing.ts; route + nav link
Phase H — Import Sanity Check:
- Migration 043: import_validations table
- ImportValidation model + schemas
- run_sanity_check: material fuzzy-match (cutoff=0.8), STEP availability, duplicate detection
- validate_excel_import Celery task (queue: step_processing)
- uploads.py: create ImportValidation on /excel, fire task, expose GET /validations/{id}
- frontend: Upload.tsx polling ValidationDialog with Ampel status indicators
Phase I — Notification Settings:
- Migration 044: notification_configs table (user×event×channel toggles)
- NotificationConfig model + seeds (in_app=true, email=false)
- get/upsert/reset config endpoints on /notifications/config
- frontend: NotificationSettings.tsx page + api/notifications.ts extensions
Infrastructure:
- docker-compose.yml: add worker-thumbnail service (concurrency=1, Q=thumbnail_rendering)
- Fix Dockerfile: libgdk-pixbuf-2.0-0 (correct Debian bookworm package name)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-06 18:05:01 +01:00
Hartmut
c74e118b98
feat(E): add MediaAsset catalog — model, CRUD API, MediaBrowser UI
...
Migration 040: media_assets table with RLS (tenant_isolation + admin_bypass).
domains/media/: MediaAsset model, schemas, service, router with ZIP-download.
publish_asset Celery task in rendering/tasks.py.
core/storage.py: download_bytes() method for MinIO + LocalStorage.
frontend: MediaBrowser.tsx (grid/list, multi-select, zip-download, pagination) + api/media.ts.
Route /media (AdminRoute) + sidebar link with Image icon for admin+pm.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-06 17:11:17 +01:00
Hartmut
217555025f
feat(C3): add React Flow workflow editor
...
frontend/src/pages/WorkflowEditor.tsx: full React Flow editor with
custom nodes (Input/Convert/Render/FFmpeg/Output), config sidepanel,
node palette with drag-drop, new workflow dialog.
frontend/src/api/workflows.ts: workflow CRUD API client.
@xyflow/react added to package.json dependencies.
Route /workflows + sidebar link for admin+pm.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-06 17:06:10 +01:00
Hartmut
5da90b5434
feat(B3): wire X-Tenant-ID header interceptor in axios client
...
Reads schaeffler_tenant_id from localStorage and injects it as
X-Tenant-ID header for all API requests (admin cross-tenant view).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-06 16:31:04 +01:00
Hartmut
82bf46725b
feat(B3): add tenant management UI (CRUD + tenant selector)
...
- frontend/src/api/tenants.ts: Tenant CRUD API client (getTenants, getTenant, createTenant, updateTenant, deleteTenant)
- frontend/src/pages/Tenants.tsx: Admin page with table, create/edit modals, delete confirm, and cross-tenant selector persisted in localStorage
- App.tsx: /tenants route (AdminRoute-guarded)
- Layout.tsx: Tenants sidebar link (admin-only, Building2 icon)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-06 16:13:26 +01:00
Hartmut
bce762a783
feat: initial commit
2026-03-05 22:12:38 +01:00