ppt-tool/backend/api/v1/ppt/endpoints/export.py
Vadym Samoilenko c97841f6d1 Phase 6: Export & Polish — brand export, client dashboard, retention, analytics
- Brand-enforced export pipeline (PPTX/PDF with auto brand fonts/colors/logo)
- Client library dashboard with two-level navigation (client grid → detail tabs)
- Data retention service with ARQ cron jobs (daily cleanup + weekly purge)
- Brand-adaptive UI theme via CSS custom properties (dynamic per client)
- Analytics dashboard with overview, usage, quality, and performance metrics

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 16:41:58 +00:00

58 lines
1.8 KiB
Python

"""Presentation export endpoints with brand enforcement."""
import uuid
from typing import Literal, Optional
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel
from sqlalchemy.ext.asyncio import AsyncSession
from models.sql.presentation import PresentationModel
from models.sql.user import UserModel
from services import audit_service
from services.database import get_async_session
from utils.auth_dependencies import get_current_user
from utils.export_utils import export_presentation
EXPORT_ROUTER = APIRouter(prefix="/api/v1/ppt", tags=["Export"])
class ExportRequest(BaseModel):
format: Literal["pptx", "pdf"] = "pptx"
@EXPORT_ROUTER.post("/presentation/{presentation_id}/export")
async def export_with_brand(
presentation_id: uuid.UUID,
body: ExportRequest,
current_user: UserModel = Depends(get_current_user),
session: AsyncSession = Depends(get_async_session),
):
"""Export presentation with automatic brand enforcement.
- Loads brand config from the presentation's client
- Applies brand fonts, colors, logo, and contrast fixes
- Returns file path for download
"""
presentation = await session.get(PresentationModel, presentation_id)
if not presentation:
raise HTTPException(status_code=404, detail="Presentation not found")
result = await export_presentation(
presentation_id=presentation.id,
title=presentation.title or str(presentation.id),
export_as=body.format,
client_id=presentation.client_id,
session=session,
)
# Audit log
audit_service.log(
user_id=current_user.id,
action="export",
resource_type="presentation",
resource_id=presentation.id,
client_id=presentation.client_id,
details={"format": body.format},
)
return {"path": result.path}