Epic 6: Stories 6-2 (Markdown roundtrip) + 6-3 (Brainstorm PPTX + Canvas)
Story 6-2 — Markdown roundtrip export/import: - lib/editor/markdown-export.ts: tiptapHTMLToMarkdown, markdownToHTML, looksLikeMarkdown - lib/editor/markdown-paste-extension.ts: TipTap extension paste Markdown → blocs - note-editor-toolbar.tsx: export .md + import .md (file picker) - rich-text-editor.tsx: intégration MarkdownPasteExtension - 40 tests unitaires markdown-export.test.ts Story 6-3 — Brainstorm PPTX + Canvas: - lib/brainstorm/export-pptx.ts: génération PPTX 5 slides (pptxgenjs) - app/api/brainstorm/[sessionId]/export-pptx/route.ts: route POST protégée - brainstorm-page.tsx: bouton PPTX, auto-select session, fix emoji, fix router.replace - wave-canvas.tsx: fitTrigger recentrage, légende bas-droite Onboarding activation wizard (Story 6-1): - components/onboarding/: wizard multi-étapes, hints éditeur - app/api/onboarding/: route PATCH onboarding - prisma/migrations: champs onboarding user Locales: 15 langues mises à jour (brainstorm, markdown, onboarding keys) Sprint: 6-1 done, 6-2 review, 6-3 review Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
182
docs/6-3-brainstorm-canvas-finalize.md
Normal file
182
docs/6-3-brainstorm-canvas-finalize.md
Normal file
@@ -0,0 +1,182 @@
|
||||
# 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 in `package.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 :
|
||||
|
||||
1. **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.
|
||||
2. **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 :
|
||||
- [x] **AC-1** : Un bouton "Télécharger en PPTX" est visible dans le modal "Résumé/Export" du brainstorm
|
||||
- [x] **AC-2** : Au clic, un fichier `brainstorm-{seedIdea-slug}.pptx` est téléchargé via le navigateur
|
||||
- [x] **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
|
||||
- [x] **AC-4** : Les idées dismissées ne sont pas incluses
|
||||
- [x] **AC-5** : Le thème utilise les couleurs de l'app (brand-accent `#A47148`, fond clair)
|
||||
- [x] **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 :
|
||||
- [x] **AC-7** : Une légende compacte est visible en bas-gauche du canvas (Wave 1 🟠, Wave 2 🔵, Wave 3 🟣, ✓ Converti, ✦ IA, initiale Humain)
|
||||
- [x] **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
|
||||
|
||||
- [x] 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 de `pptx.tool.ts`)
|
||||
- Retourner le buffer en `application/vnd.openxmlformats-officedocument.presentationml.presentation`
|
||||
- Headers: `Content-Disposition: attachment; filename="brainstorm-{slug}.pptx"`
|
||||
|
||||
### T2 — Lib helper `lib/brainstorm/export-pptx.ts`
|
||||
|
||||
- [x] T2.1 — Créer `lib/brainstorm/export-pptx.ts` avec `generateBrainstormPptx(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
|
||||
|
||||
### T3 — Bouton PPTX dans le modal export
|
||||
|
||||
- [x] 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`
|
||||
|
||||
### T4 — UX Canvas : légende + recentrer
|
||||
|
||||
- [x] 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
|
||||
- [x] T4.2 — Exposer une ref/méthode `fitToScreen()` ou callback `onFitToScreen` depuis `WaveCanvas`
|
||||
- Re-applique `zoom.transform` vers `d3.zoomIdentity.translate(centerX, centerY).scale(0.8)`
|
||||
- [x] T4.3 — Dans `brainstorm-page.tsx`, ajouter un bouton ⊙ "Recentrer" dans les contrôles canvas
|
||||
- Appelle `fitToScreen()`
|
||||
- i18n key `brainstorm.fitToScreen`
|
||||
|
||||
### T5 — i18n (15 locales)
|
||||
|
||||
- [x] T5.1 — Ajouter dans `locales/en.json` et `locales/fr.json` :
|
||||
- `brainstorm.downloadPptx`, `brainstorm.downloadPptxDesc`, `brainstorm.pptxSuccess`, `brainstorm.pptxError`, `brainstorm.fitToScreen`
|
||||
- [x] 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) :**
|
||||
```typescript
|
||||
// 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`) :**
|
||||
```typescript
|
||||
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 :**
|
||||
```typescript
|
||||
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` + `forwardRef` un objet `{ fitToScreen: () => void }`
|
||||
- Ou plus simple : passer une prop `fitTrigger: number` (increment → re-zoom)
|
||||
|
||||
### Thème PPTX
|
||||
|
||||
Cohérent avec l'identité visuelle Momento :
|
||||
- `bg: F2F0E9` — fond papier
|
||||
- `primary: 1C1C1C` — noir ardoise
|
||||
- `accent: A47148` — brand-accent Momento
|
||||
- `secondary: D4A373` — ocre clair
|
||||
|
||||
### Fichiers clés existants
|
||||
- `memento-note/lib/ai/tools/pptx.tool.ts` — référence pour patterns pptxgenjs
|
||||
- `memento-note/components/brainstorm/wave-canvas.tsx` — canvas D3
|
||||
- `memento-note/components/brainstorm/brainstorm-page.tsx` — page principale
|
||||
- `memento-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 |
|
||||
Reference in New Issue
Block a user