Publication IA: - 4 templates (magazine, brief, essay, simple) avec CSS riche - Rewrite IA (article/exercises/tutorial/reference/mixed) - Modération avec timeout 12s + fallback safe - Quotas publish_enhance par tier (basic=2, pro=15, business=100) - Détection contenu stale (hash) - Migration DB publishedContent/publishedTemplate/publishedSourceHash Fixes: - cheerio v1.2: Element -> AnyNode (domhandler), decodeEntities cast - _isShared ajouté au type Note (champ virtuel serveur) - callout colors PDF export: extraction fonction pure testable - admin/published: guard note.userId null - Cmd+S fonctionne en mode dialog (pas seulement fullPage) i18n: - 23 clés publish* traduites dans les 15 locales - Extension Web Clipper: 13 locales mise à jour Tests: - callout-colors.test.ts (6 tests) - note-visible-in-view.test.ts (5 tests) - entitlements.test.ts + byok-entitlements.test.ts: mock usageLog + unstubAllEnvs - 199/199 tests passent Tracker: user-stories.md sync avec sprint-status.yaml
6.9 KiB
Story: Brainstorm Canvas — Finalisation (PPTX export + UX Canvas)
Epic: Epic 6 — Croissance & Activation (PLG) ID: 6-3-brainstorm-canvas-finalize Priority: High Status: review Depends on:
pptxgenjs@^4.0.1(already inpackage.json✅),lib/ai/tools/pptx.tool.ts(patterns)
Contexte
Le brainstorm canvas est quasi-complet (WaveCanvas D3, collaboration temps réel, export en note Markdown, finalize session). Il manque deux choses pour un produit fini :
- Export PPTX (FR12) : génère une présentation branded depuis la session brainstorm — route API serveur
/api/brainstorm/[sessionId]/export-pptx+ bouton dans le modal "Export/Résumé" existant. - UX Canvas : légende des vagues (couleurs Wave 1/2/3) + bouton "Fit to screen" (re-center).
pptxgenjs@^4.0.1 est déjà installé. lib/ai/tools/pptx.tool.ts fournit les patterns d'utilisation (lazy import, helpers, thèmes).
User Stories
US-BRAINSTORM-PPTX : Export PPTX
En tant qu' utilisateur,
Je veux télécharger ma session brainstorm en fichier .pptx,
Afin de la présenter ou la partager en dehors de l'application.
Critères d'acceptation :
- AC-1 : Un bouton "Télécharger en PPTX" est visible dans le modal "Résumé/Export" du brainstorm
- AC-2 : Au clic, un fichier
brainstorm-{seedIdea-slug}.pptxest téléchargé via le navigateur - AC-3 : Le PPTX contient : slide couverture (titre, seedIdea, date, stats), une slide par vague active (Wave 1/2/3 avec idées), slide "Top idées" (starred + converted), slide bilan
- AC-4 : Les idées dismissées ne sont pas incluses
- AC-5 : Le thème utilise les couleurs de l'app (brand-accent
#A47148, fond clair) - AC-6 : La route est protégée (auth + participant check)
US-BRAINSTORM-CANVAS-UX : UX Canvas
En tant qu' utilisateur, Je veux comprendre les codes couleurs du canvas et recentrer la vue, Afin de naviguer efficacement dans la session.
Critères d'acceptation :
- AC-7 : Une légende compacte est visible en bas-gauche du canvas (Wave 1 🟠, Wave 2 🔵, Wave 3 🟣, ✓ Converti, ✦ IA, initiale Humain)
- AC-8 : Un bouton "Recentrer" (⊙) est visible sur le canvas et recentre la vue sur le nœud racine
Tasks / Subtasks
T1 — Route API export PPTX
- T1.1 — Créer
app/api/brainstorm/[sessionId]/export-pptx/route.ts- Auth + participant check (réutiliser
verifyParticipant) - Charger la session avec les idées (non-dismissed)
- Générer le PPTX via
pptxgenjs(lazy import pattern depptx.tool.ts) - Retourner le buffer en
application/vnd.openxmlformats-officedocument.presentationml.presentation - Headers:
Content-Disposition: attachment; filename="brainstorm-{slug}.pptx"
- Auth + participant check (réutiliser
T2 — Lib helper lib/brainstorm/export-pptx.ts
- T2.1 — Créer
lib/brainstorm/export-pptx.tsavecgenerateBrainstormPptx(session): Promise<Buffer>- Thème "architectural_mono" (
bg: F2F0E9, primary: 1C1C1C, accent: A47148) — cohérent avec l'app - Slide 0 : Cover — titre "Brainstorm", seedIdea en sous-titre, date, stats (N idées, M converties)
- Slide 1-3 : Une slide par vague active — titre "Wave N — {label}", liste des idées (titre + description courte)
- Slide finale : "Top idées" — starred ⭐ et converties ✓ — max 6 items
- Idées dismissed : exclues
- Thème "architectural_mono" (
T3 — Bouton PPTX dans le modal export
- T3.1 — Dans
brainstorm-page.tsx, ajouter un bouton "Télécharger PPTX" dans le modal de résumé (summaryOpen)- Fetch
POST /api/brainstorm/{sessionId}/export-pptx→ blob download - Loading state + toast succès/erreur
- i18n key
brainstorm.downloadPptx
- Fetch
T4 — UX Canvas : légende + recentrer
- T4.1 — Dans
wave-canvas.tsx, ajouter une légende compacte (overlay bas-droit, au-dessus du hint double-click)- 4 entrées : Wave 1 🟠, Wave 2 🔵, Wave 3 🟣 + ✓ Converti
- Style minimaliste, fond semi-transparent
- T4.2 — Exposer une ref/méthode
fitToScreen()ou callbackonFitToScreendepuisWaveCanvas- Re-applique
zoom.transformversd3.zoomIdentity.translate(centerX, centerY).scale(0.8)
- Re-applique
- T4.3 — Dans
brainstorm-page.tsx, ajouter un bouton ⊙ "Recentrer" dans les contrôles canvas- Appelle
fitToScreen() - i18n key
brainstorm.fitToScreen
- Appelle
T5 — i18n (15 locales)
- T5.1 — Ajouter dans
locales/en.jsonetlocales/fr.json:brainstorm.downloadPptx,brainstorm.downloadPptxDesc,brainstorm.pptxSuccess,brainstorm.pptxError,brainstorm.fitToScreen
- T5.2 — Propager dans les 13 autres locales (valeur EN par défaut)
Dev Notes
Architecture
Route API ('use server' implicite via Next.js route handler) :
// app/api/brainstorm/[sessionId]/export-pptx/route.ts
export async function POST(req, { params }) {
// auth + verifyParticipant
// load session + ideas (status !== 'dismissed')
// generateBrainstormPptx(session) → Buffer
// return new Response(buffer, { headers: { 'Content-Type': 'application/vnd.openxmlformats...', 'Content-Disposition': 'attachment; filename=...' } })
}
Lazy import pptxgenjs (pattern depuis pptx.tool.ts) :
let _PptxGenJS: (new () => PptxGenJSModule) | null = null
async function getPptxGenClass() {
if (!_PptxGenJS) {
const mod = await import('pptxgenjs')
_PptxGenJS = (mod.default ?? mod) as unknown as new () => PptxGenJSModule
}
return _PptxGenJS
}
Client download depuis brainstorm-page.tsx :
const res = await fetch(`/api/brainstorm/${sessionId}/export-pptx`, { method: 'POST' })
const blob = await res.blob()
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = `brainstorm-${slug}.pptx`
a.click()
URL.revokeObjectURL(url)
WaveCanvas fit-to-screen :
- Exposer via
useImperativeHandle+forwardRefun objet{ fitToScreen: () => void } - Ou plus simple : passer une prop
fitTrigger: number(increment → re-zoom)
Thème PPTX
Cohérent avec l'identité visuelle Memento :
bg: F2F0E9— fond papierprimary: 1C1C1C— noir ardoiseaccent: A47148— brand-accent Mementosecondary: D4A373— ocre clair
Fichiers clés existants
memento-note/lib/ai/tools/pptx.tool.ts— référence pour patterns pptxgenjsmemento-note/components/brainstorm/wave-canvas.tsx— canvas D3memento-note/components/brainstorm/brainstorm-page.tsx— page principalememento-note/app/api/brainstorm/[sessionId]/export/route.ts— export Markdown (référence)memento-note/lib/brainstorm-collab.ts—verifyParticipant
Dev Agent Record
Implementation Plan
À compléter par l'agent dev
Debug Log
À compléter
Completion Notes
À compléter
File List
À compléter
Change Log
| Date | Description |
|---|---|
| 2026-05-29 | Story créée — 6-3 brainstorm canvas finalize |