Some checks failed
Deploy to Production / Build and Deploy (push) Failing after 3s
Slide generator (generate_pptx): - Pivot vers génération PowerPoint natif (pptxgenjs) au lieu de Reveal.js HTML - 4 nouveaux layouts diagramme : timeline, process, comparison, metrics - 2 nouveaux layouts image : image-content (texte + image), image-full (plein cadre) - Redesign visuel de tous les layouts (cover split, section full-bleed, header band) - Palettes corrigées : bg blanc sur toutes les palettes, contrastes réels - fit:shrink systématique sur tous les textes pour éviter les débordements - Extraction automatique des images des notes (Markdown/HTML) et injection dans le prompt IA - Prompt IA renforcé : impose "style" et "theme" explicitement dans le JSON, impose ≥2 layouts diagramme - Fix overlap timeline : zones de texte calculées sans collision avec les cercles - Notification agent mise à jour : bouton download .pptx au lieu d'ouvrir HTML Excalidraw generator: - Layout Dagre/ELK pour graphes auto-positionnés - Styles visuels : coloré, austère, sketch-plus (Virgil font) - Zones/containers pour architecture-cloud - Sanitisation du graphe et métriques de qualité de layout Co-authored-by: Cursor <cursoragent@cursor.com>
48 lines
1.7 KiB
TypeScript
48 lines
1.7 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server'
|
|
import { prisma } from '@/lib/prisma'
|
|
import { auth } from '@/auth'
|
|
|
|
export async function GET(req: NextRequest) {
|
|
try {
|
|
const session = await auth()
|
|
if (!session?.user?.id) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
|
|
|
const canvasId = req.nextUrl.searchParams.get('id')
|
|
if (!canvasId) return NextResponse.json({ error: 'Missing id' }, { status: 400 })
|
|
|
|
const canvas = await prisma.canvas.findUnique({
|
|
where: { id: canvasId, userId: session.user.id },
|
|
})
|
|
if (!canvas) return NextResponse.json({ error: 'Not found' }, { status: 404 })
|
|
|
|
let parsed: any
|
|
try { parsed = JSON.parse(canvas.data) } catch {
|
|
return NextResponse.json({ error: 'Invalid data' }, { status: 500 })
|
|
}
|
|
|
|
if (parsed.type !== 'pptx' || !parsed.base64) {
|
|
return NextResponse.json({ error: 'Not a PPTX canvas' }, { status: 400 })
|
|
}
|
|
|
|
const byteChars = atob(parsed.base64)
|
|
const bytes = new Uint8Array(byteChars.length)
|
|
for (let i = 0; i < byteChars.length; i++) bytes[i] = byteChars.charCodeAt(i)
|
|
|
|
const filename = parsed.filename || `${canvas.name.replace(/[^a-zA-Z0-9]/g, '_')}.pptx`
|
|
|
|
// Auto-delete after serving
|
|
await prisma.canvas.delete({ where: { id: canvasId } })
|
|
|
|
return new NextResponse(bytes, {
|
|
headers: {
|
|
'Content-Type': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
|
'Content-Disposition': `attachment; filename="${filename}"`,
|
|
'Content-Length': String(bytes.length),
|
|
},
|
|
})
|
|
} catch (error) {
|
|
console.error('[Canvas Download]', error)
|
|
return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 })
|
|
}
|
|
}
|