Commit graph

85 commits

Author SHA1 Message Date
shubham.goyal@brandtech.plus
d5bb04a837 fix download path 2026-05-17 20:35:21 +05:30
shubham.goyal@brandtech.plus
36ae0438a1 Merge branch 'main' of https://bitbucket.org/zlalani/ppt-tool 2026-05-17 20:08:17 +05:30
shubham.goyal@brandtech.plus
e054916f44 fix ppt download issue 2026-05-17 20:07:56 +05:30
Shubham Goyal
9917015456 Merged in fix/login-issue (pull request #1)
fix login issue and ppt outlines
2026-05-12 13:38:14 +00:00
shubham.goyal@brandtech.plus
7296c5b600 fix login issue and ppt outlines 2026-04-28 22:23:55 +05:30
Vadym Samoilenko
e63f790cd8 Fix MSAL config: hardcode IDs + pass as Docker build args
NEXT_PUBLIC_* vars are baked at Next.js build time but were not
available during Docker build (web service had no env_file/build args).
Hardcode IDs as fallback in msalConfig.ts, also wire AZURE_AD_*
through Dockerfile ARGs and docker-compose build args.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 12:49:46 +00:00
Vadym Samoilenko
f2f729a50b Switch Azure AD auth to MSAL SPA (browser-side token exchange)
- Replace server-side ConfidentialClientApplication + OAuth callback
  with MSAL browser popup flow (PKCE, no client_secret required)
- Backend: add POST /sso-token endpoint that validates Azure AD ID token
  via Microsoft JWKS, issues session cookie; remove /login + /callback
- Frontend: install @azure/msal-browser + @azure/msal-react, wrap app
  with MsalProvider, login page uses loginPopup() → sends id_token to backend
- Pass NEXT_PUBLIC_AZURE_* env vars through next.config.mjs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 12:34:52 +00:00
Vadym Samoilenko
864278a0fa Comprehensive audit: fix auth, basePath, security, and UI bugs
Backend security (P0):
- Add get_current_user auth to all files endpoints (upload, decompose, url, update)
- Add get_current_user auth to all images endpoints (generate, upload, uploaded, generated, delete)
- Add get_current_user auth to slide edit and edit-html endpoints
- Add get_current_user auth to outlines SSE stream endpoint (was fully unauthenticated)

Frontend API fixes:
- adminSlice fetchTeams: bare fetch() → apiFetch() (was missing basePath prefix)
- dashboard getPresentation: add missing getHeader() auth headers
- images getUploadedImages/deleteImage: add missing getHeader() auth headers
- templates/[id] toggle layout: bare fetch() → apiFetch() (404 in production)
- header.ts: remove incorrect client-side CORS headers (Access-Control-Allow-*)

UI fixes:
- admin/users: add fetchUsers() refetch after deactivate (table wasn't updating)
- presentationGeneration.ts: fix corrupt comment with embedded import statement

Security:
- has-required-key/route.ts: remove console.log() leaking OPENAI_API_KEY to logs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 18:46:45 +00:00
Vadym Samoilenko
25b70af9fb Fix 422 errors: clientSlice bare fetch, prepare schemaJSON null, update SlideModel validation
- clientSlice: fetchMasterDecks + fetchClientPresentations use apiFetch (adds /ppt-tool basePath)
- useCustomTemplates: parsedLayoutToCompiled generates schemaJSON from elements instead of null
  (null schemaJSON caused 422 on /prepare because backend SlideLayoutModel.json_schema: dict is required)
- presentation.py: update_presentation uses SlideInput (plain Pydantic model with extra='ignore')
  instead of SlideModel (table=True SQLModel) to avoid strict validation causing 422 on /update

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 18:26:54 +00:00
Vadym Samoilenko
17d1a0573c Fix screenshot img src URLs missing /ppt-tool basePath
master-decks page: deck thumbnail + layout screenshot
templates/[id] page: layout thumbnail

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 18:12:39 +00:00
Vadym Samoilenko
910f58369c Fix EventSource URLs missing /ppt-tool basePath
Add apiUrl() helper to apiFetch.ts for non-fetch URL construction.
Fixed 3 SSE streams: outlines, presentation, job progress.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 18:02:07 +00:00
Vadym Samoilenko
6157fcbc4e Fix PyMuPDF: replace get_text("markdown") with get_text("text")
"markdown" format requires PyMuPDF >= 1.24.0, not available on server.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 17:59:22 +00:00
Vadym Samoilenko
8670822a59 Fix bare fetch() calls missing /ppt-tool basePath prefix
ConfigurationInitializer: /api/can-change-keys and /api/user-config
providerUtils: /api/v1/ppt/ollama/models/available

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 17:52:47 +00:00
Vadym Samoilenko
ae511f1086 Speed up updates: hot-copy backend code, suppress GPU warnings
- update.sh: docker cp backend into running container + restart (no rebuild)
  Backend updates now take ~5s instead of 2min
- backend/Dockerfile: ORT_DISABLE_GPU=1 suppresses ONNX GPU discovery errors
  on CPU-only servers

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 17:49:48 +00:00
Vadym Samoilenko
598f7343c3 Add update.sh: fast code-only deploy (skips full rebuild)
Detects changed files since last pull, rebuilds only affected services.
Use ./update.sh for code changes, ./deploy.sh for dep/Dockerfile changes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 17:45:37 +00:00
Vadym Samoilenko
bbaef76fa7 Fix Google image generation: model, response modality, data extraction
- NanoBanana Pro: gemini-2.0-flash-exp-image → gemini-3.1-flash-image-preview
- Add response_modalities=["IMAGE","TEXT"] so Gemini returns image data
- Replace part.as_image() with base64.b64decode(part.inline_data.data)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 17:42:01 +00:00
Vadym Samoilenko
19222ab36d Fix auth for optical-dev.oliver.solutions/ppt-tool/ deployment
- AZURE_AD_REDIRECT_URI set to https://optical-dev.oliver.solutions/ppt-tool/
- Root page intercepts ?code= from Azure AD and forwards to backend callback
- Post-OAuth redirect uses NEXT_PUBLIC_BASE_PATH env var (/ppt-tool/dashboard)
- Cookie secure flag driven by COOKIE_SECURE env var (true in prod)
- Dev login now works alongside Azure AD when DEV_AUTH_PASSWORD is set
- Login page shows both Microsoft SSO and dev form when both modes enabled
- docker-compose.prod.yml: add COOKIE_SECURE=true and NEXT_PUBLIC_BASE_PATH

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 17:38:42 +00:00
Vadym Samoilenko
1e28574512 Fix login redirect: use router.push('/dashboard') instead of window.location.href
window.location.href bypasses Next.js basePath, sending to /dashboard instead of /ppt-tool/dashboard.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 22:45:42 +00:00
Vadym Samoilenko
1e00d480e2 Fix apiFetch: hardcode /ppt-tool basePath (publicRuntimeConfig broken in App Router)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 22:38:59 +00:00
Vadym Samoilenko
a99e18c744 Fix apiFetch basePath: use publicRuntimeConfig instead of NEXT_PUBLIC_ env var
NEXT_PUBLIC_* vars are inlined at build time — not available in Docker build context.
publicRuntimeConfig is resolved at runtime from next.config.mjs, which works correctly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 22:32:49 +00:00
Vadym Samoilenko
4e9ce79a3c Fix broken import in dashboard.ts
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 22:26:09 +00:00
Vadym Samoilenko
62ea9011a0 Fix apiFetch: update remaining files + add .next-build to .gitignore
authSlice, clientSlice, custom-template hooks, dashboard/presentation-generation
services and CustomConfig — all /api/v1/ calls now route through apiFetch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 22:24:42 +00:00
Vadym Samoilenko
bebe2ac390 Fix API routing: apiFetch helper prefixes basePath for all /api/v1/ calls
Without this, fetch('/api/v1/...') from the browser hits Apache root,
which routes /api/ to OliVAS (port 8000) instead of DeckForge (port 8001).
apiFetch prepends NEXT_PUBLIC_BASE_PATH so requests go through Next.js
rewrites to the correct backend.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 22:12:25 +00:00
Vadym Samoilenko
3077159da3 Fix redirect loop and login redirect for /ppt-tool deployment
- Add basePath/assetPrefix to next.config.mjs (was only patched on server)
- Fix AuthGuard to use router.push('/login') instead of window.location.href
  (window.location ignores Next.js basePath, sent users to /login not /ppt-tool/login)
- Remove deploy.sh Step 10 deckforge.conf creation — DeckForge rules are now
  merged into optical-dev.oliver.solutions.conf alongside OliVAS config

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 21:57:45 +00:00
Vadym Samoilenko
8960267c3c Fix 404: redirect /ppt-tool (no slash) to /ppt-tool/ in Apache
Next.js basePath redirects /ppt-tool/ → /ppt-tool (308), then Apache
had no rule for the slash-less path. Added RedirectMatch to complete
the loop back to /ppt-tool/.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 21:33:04 +00:00
Vadym Samoilenko
f2b65df132 Pre-build ChromaDB icons index in Docker image
Avoids 3-10 min CPU-heavy index rebuild on every container start.
ONNX model + icons index baked into image at build time.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 21:31:14 +00:00
Vadym Samoilenko
40c22e8d47 Fix: add retry loop for API health check (same as frontend)
API takes time to initialize — immediate curl always fails.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 21:27:41 +00:00
Vadym Samoilenko
5c052e718d Fix deploy port conflict: auto-detect free port + persist to .env
- Read API/WEB/PG/REDIS ports from .env on startup (Docker Compose
  loads .env directly, shell exports are ignored by it)
- check_port: auto-find next free port instead of interactive prompt
- set_env_port: write chosen port back to .env so it persists across runs
- port_taken_by_other: use 'ss | grep' instead of ss sport filter (more reliable)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 21:25:16 +00:00
Vadym Samoilenko
2b31281be5 Fix Google LB health check: serve 200 on GET / instead of 302
Google Cloud LB marks backend unhealthy when GET / returns 302.
Serve /var/www/html/index.html (meta-redirect to /ppt-tool/) for root
so health check gets 200 OK and traffic flows through.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 21:22:31 +00:00
Vadym Samoilenko
9afda2069e Fix port binding: replace !reset with !override in prod compose overlay
In Compose v5, !reset resets a key to its default (empty) and ignores
the provided values. !override replaces the existing list entirely,
which is the correct behaviour for restricting ports to 127.0.0.1.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 21:12:15 +00:00
Vadym Samoilenko
be052db7af Fix domain typo: oliver.solution → oliver.solutions everywhere
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 21:06:09 +00:00
Vadym Samoilenko
32aea6e1a6 Fix deploy: wait up to 2min for Next.js frontend to start before health check
Next.js SSR takes 30-60s to compile on first boot — immediate curl check
always fails. Now retries every 5s for up to 24 attempts (2 minutes).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 21:02:40 +00:00
Vadym Samoilenko
f02b8a0b30 Fix Apache config: remove ProxyTimeout from Location block (not allowed there)
timeout=1800 already set on ProxyPass directive directly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 21:00:33 +00:00
Vadym Samoilenko
455e6e0c00 Redesign outline editor: two-column split layout + premium card UX
- OutlinePage: two-column split (slides left 60%, template right 40%),
  sticky header with slide count badge + Add Slide button, #F8F7FF bg
- WizardOutlinePage: outline left, tabbed Brief|Template right panel,
  file-to-slide linking preserved in Brief tab
- OutlineItem: title+bullets preview with click-to-edit, hover-reveal
  drag handle (GripVertical) + AI Rewrite (inline prompt) + Delete,
  streaming states: pulsing left border + bouncing dots for active card

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 20:48:32 +00:00
Vadym Samoilenko
d10759b4de Fix port conflict: use !reset tag to replace base ports, not append
Docker Compose merges port lists from multiple -f files by concatenation.
Without !reset, both 0.0.0.0:8000:8000 (base) and 127.0.0.1:8000:8000
(prod override) are applied simultaneously, causing "port already allocated".
!reset clears the list before applying prod-specific bindings (requires
Docker Compose v2.24+, available in current docker-compose-plugin via apt).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 20:33:37 +00:00
Vadym Samoilenko
f73291285d Improve presentation pipeline: brief summarization + section attribution + narrative continuity
Based on PPTAgent (EMNLP 2025) and DocPres research findings:

1. Brief summarization (summarize_brief.py)
   - For content >800 chars: single LLM call extracts {overview, sections[{title,
     key_points, data_points}]} before outline generation
   - Prevents "lost middle" context loss in long documents
   - BriefStructure.to_outline_context() formats sections for outline prompt
   - BriefStructure.get_section_text(idx) returns targeted excerpt per slide

2. Section attribution in SlideOutlineModel
   - Added source_section_idx: Optional[int] field
   - LLM sets this during outline generation to map each slide → brief section
   - Used to pass targeted section text to per-slide content generation
     instead of full brief (reduces hallucination, improves accuracy)

3. Narrative continuity in slide content generation
   - prev_slide_title passed to each content generation call
   - Injected in user prompt: "ensure this slide continues naturally from..."
   - Batch-safe: titles collected from completed batch before next starts

4. Source section text in content generation
   - source_section_text parameter added to get_slide_content_from_type_and_outline
   - Injected as "Source Material for This Slide" in user prompt
   - Only data points present in the excerpt should be used

5. Richer layout catalog
   - PresentationLayoutModel.to_catalog_string() added
   - Includes field names + maxLength constraints alongside layout descriptions
   - Helps LLM make informed layout choices based on content type

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 20:22:22 +00:00
Vadym Samoilenko
8715fa8bd2 Replace docling+layoutparser+torch with PyMuPDF (~3.5GB → ~80MB)
- docling removed: PDF now parsed by PyMuPDF (fitz), PPTX by python-pptx
- layoutparser removed: already optional with graceful fallback (returns [])
- torch/pytorch index removed: no longer needed by any dependency
- pymupdf added: ~20MB wheel, no ML deps, faster than docling for text extraction
- All existing DOCX parsing kept (python-docx, already working)
- extract_text_from_image_via_vision() unchanged (Gemini API)

Result: api/worker Docker image ~3-4GB lighter, no NVIDIA libs on CPU server

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 20:06:46 +00:00
Vadym Samoilenko
f9ae1c9b3a Fix: force torch CPU-only build to avoid 5-8GB NVIDIA CUDA packages
Without [tool.uv.sources] binding torch to the pytorch-cpu index,
docling/layoutparser pull the full CUDA torch from PyPI, which includes
nvidia-nccl, nvidia-cusparselt, nvidia-cudnn etc (~5-8GB of GPU libs
useless on CPU-only servers). This caused "no space left on device"
during Docker layer extraction on the production server.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:57:08 +00:00
Vadym Samoilenko
1fe15a1cec Fix port check: only allow our own compose containers, not any Docker
Previously any Docker process on the port was treated as safe.
Now uses docker inspect on our project's containers specifically,
so ports used by other apps on the server trigger the conflict prompt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:25:48 +00:00
Vadym Samoilenko
e33fec5353 Fix deploy.sh: run as normal user, sudo only for privileged ops
Removes root check; uses sudo internally for apt/apache/ufw commands
so git pull and docker commands run as the invoking user (with correct
SSH keys and docker group membership).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:17:09 +00:00
Vadym Samoilenko
7c8b8cd369 Add production deploy script and Apache/Docker config
- deploy.sh: idempotent 12-step deploy for Ubuntu (prereqs, port
  conflict check, basePath patch, build, migrate, Apache + UFW setup)
- docker-compose.prod.yml: prod overrides (127.0.0.1 bindings, no nginx)
- apache/deckforge.conf: reverse proxy template with SSE support

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 19:15:19 +00:00
Vadym Samoilenko
587f5ef6e1 Add 3 sandbox features: diagrams, mermaid, and template code-gen
Feature 1 — PPTX from Template (Code-Gen):
- backend/services/template_codegen_service.py: analyze PPTX, strip slides,
  Gemini code-gen + subprocess exec (60s timeout, auto-retry on error)
- backend/api/v1/ppt/endpoints/template_codegen.py: POST /template-codegen/generate
  (multipart: presentation_id + template_file + custom_prompt, rate-limited 3/min)
- frontend/components/TemplateCodegenExport.tsx: drag-drop modal
- Header.tsx: "Export from Template" option in export dropdown

Feature 2 — Diagrams in Slides:
- backend/models/diagram_data.py: DiagramData / FlowStep / BarChartItem models
- generate_slide_content.py: optional __diagram__ + __mermaid__ fields in LLM schema
- DiagramRenderer.tsx: pure React flowchart / bar chart / pie chart (no deps)
- SlideRenderer.tsx: chart elements render DiagramRenderer/MermaidRenderer;
  floating overlay fallback when no chart element exists in JSON layout
- V1ContentRender.tsx: diagram/mermaid overlay on built-in template slides
- generate-pptx/route.ts: addDiagramToSlide() — bar/pie via pptxgenjs addChart(),
  flowchart via addShape()+addText(), mermaid via /api/mermaid-to-image

Feature 3 — Mermaid Diagrams:
- MermaidRenderer.tsx: dynamic import mermaid@11, useEffect render, error fallback
- frontend/app/api/mermaid-to-image/route.ts: Puppeteer renders Mermaid to PNG → base64

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 18:47:31 +00:00
Vadym Samoilenko
6ea431bc75 Fix SSE routing: exclude text/event-stream requests from API rewrite
afterFiles ordering was insufficient in Next.js 14 — the catch-all
/api/v1/* rewrite still intercepted SSE requests before route handlers.

Fix: add a `missing` condition on `Accept: text/event-stream` to the
rewrite rule. EventSource always sends this header, so SSE requests now
skip the rewrite entirely and are handled by the existing route handlers
(app/api/v1/ppt/outlines/stream, presentation/stream, jobs/stream).
Normal JSON API requests are unaffected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 21:27:38 +00:00
Vadym Samoilenko
65da74ab13 Fix SSE 500: move API rewrites to afterFiles so route handlers take priority
The flat-array form of rewrites() runs as beforeFiles, intercepting /api/v1/*
requests before Next.js can match route handlers. This caused the SSE stream
endpoints (outlines/stream, presentation/stream, jobs/stream) to be handled
by the buffering HTTP proxy instead of the custom streaming route handlers,
resulting in ECONNRESET → 500 on the browser.

afterFiles rewrites only apply when no matching app/api/ file exists, so
route handlers now win over the backend proxy for all /api/v1/* paths that
have explicit handlers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 21:14:44 +00:00
Vadym Samoilenko
58e738e79b Replace PPTX export pipeline: Puppeteer/python-pptx → PptxGenJS
- New POST /api/generate-pptx route (Next.js) uses PptxGenJS to build
  PPTX directly from the Phase 8 JSON element model — no headless Chrome
- export_utils.py queries DB for slides + layout codes, POSTs payload to
  Next.js, saves binary response to disk (removes python-pptx/Puppeteer)
- Coordinate conversion: px / 96 → inches (1280×720 = 13.333×7.5 in)
- CSS color/font-size parsing (hex, rgb/rgba, px→pt at 0.75pt/px)
- Fallback renderer for slides without a JSON layout schema
- PDF export (Puppeteer) unchanged

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 21:04:31 +00:00
Vadym Samoilenko
1f5a0c27da Fix SSE proxy: create Next.js route handlers for all streaming endpoints
Next.js rewrites() buffer HTTP responses and drop long-lived connections,
making SSE (text/event-stream) impossible. The backend never even received
the request (no log entry in API, ECONNRESET in web proxy logs).

Create dedicated route.ts files for all 3 SSE endpoints:
- /api/v1/ppt/outlines/stream/[id]
- /api/v1/ppt/presentation/stream/[id]
- /api/v1/ppt/jobs/[job_id]/stream

Each route forwards cookies for auth and returns backend's ReadableStream
directly as a Response, preventing any buffering. Sets X-Accel-Buffering: no
to also disable nginx buffering.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 20:43:58 +00:00
Vadym Samoilenko
e360983249 Fix 5 post-Phase8 bugs: SSE crash, custom templates, ordering, persistence, JSON display
- outlines.py: Fix ECONNRESET/socket-hang-up — Depends session closes before
  StreamingResponse generator runs; capture presentation data upfront, use
  async_session_maker() inside inner() for the final DB commit (same pattern as Phase 4)
- useCustomTemplates.ts: Filter null-template items in summary map (crashed on
  presentations without a TemplateModel); use item.layout_count instead of hardcoded 0
- TemplateSelection.tsx: Move custom AI templates section above built-in templates
- presentationGeneration.ts + OutlinePage.tsx: Add selectedTemplateId to Redux so
  template selection persists when navigating away and back to /outline; clearOutlines
  also resets selectedTemplateId for new presentation flows
- DocumentPreviewPage.tsx: Detect JSON file content (table decomposition output) and
  convert to markdown table or pretty-printed code block before passing to MarkdownRenderer

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 20:25:28 +00:00
Vadym Samoilenko
df99af91ac Fix migration: move to correct path, update down_revision to c7a3f8e21d4b
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 20:10:36 +00:00
Vadym Samoilenko
ae41562103 Phase 8: Data-driven slide architecture + template management overhaul
Replaces TSX/Babel compilation pipeline with a JSON element model:
- New _do_parse_v2(): 1 LLM call/layout (vs 2) classifies OXML geometry
  elements into placeholder types → JSON stored in layout_code
- SlideRenderer.tsx: renders JSON element model as %-positioned divs,
  no Babel compilation or runtime errors
- parseLayoutSchema.ts: isJsonLayoutCode() / parseLayoutSchema() /
  mergeElementsWithContent() — full JSON schema parsing layer
- useCustomTemplates.ts: transparent dual-format support (JSON + TSX)
  via parsedLayoutToCompiled() adapter

Template management improvements:
- PresentationLayoutCodeModel: +is_enabled (bool) +thumbnail_path (str)
- Migration 005: adds both columns to presentation_layout_codes
- DELETE /master-decks/{id}: hard delete (files + TemplateModel +
  PresentationLayoutCodeModel rows + MasterDeckModel)
- PATCH /template-management/layouts/{db_id}/toggle-enabled: new endpoint
- LayoutData response: +db_id, +is_enabled, +thumbnail_path
- _register_as_template(): stores thumbnail_path + is_enabled per layout

Admin UI:
- /admin/templates/ — list all custom templates with delete
- /admin/templates/[id]/ — layout grid with screenshots + enable/disable
- AdminSidebar: Templates nav item

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 20:05:25 +00:00
Vadym Samoilenko
af95e73806 Fix SSE crash + React layout error boundaries
- documents_loader: skip missing files (print warning + continue) instead
  of raising HTTPException inside SSE generator — prevents "response
  already started" runtime error when temp files are wiped on restart
- V1ContentRender: wrap non-edit mode render in SlideErrorBoundary so
  broken custom layout components show a red placeholder instead of
  crashing the page (React error #62)
- CustomTemplateCard: wrap LayoutPreview in SlideErrorBoundary for the
  same reason — bad compiled TSX from master deck parsing no longer
  crashes the outline template picker

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