477 lines
23 KiB
Markdown
477 lines
23 KiB
Markdown
# US-4 Redesign — Vue Structurée Inline dans l'Éditeur
|
||
|
||
> **Status :** DRAFT — En attente de validation fondateur
|
||
> **Remplace :** US-4 « Bloc de Base de Données Relationnelle Inline » (DEPRECATED)
|
||
> **Epic :** US-NEXTGEN-EDITOR
|
||
> **Dépend de :** US-STRUCTURED-VIEWS ✅ (livré), US-LIVING-BLOCKS ✅ (livré)
|
||
|
||
---
|
||
|
||
## 1. Problem Statement — Pourquoi l'ancienne US-4 est morte
|
||
|
||
L'implémentation actuelle (fichiers `tiptap-database-block-extension.tsx`, `database-block-editor.tsx`, `database-block-types.ts`) a été rejetée pour les raisons suivantes :
|
||
|
||
### 1.1 Copie de démo marketing, pas une feature produit
|
||
|
||
Le code source dans `createDefaultDatabaseBlockData()` insère **Jules Verne** et **Liu Cixin** avec leurs œuvres en données pré-remplies. C'est une copie directe du prototype `architectural-grid1/ModernBlockNoteEditor.tsx` qui était conçu pour une landing page, pas pour un produit de prise de notes réel.
|
||
|
||
### 1.2 Modèle de données parallèle et isolé
|
||
|
||
L'implémentation stocke `dbAuthorsJson` et `dbBooksJson` comme attributs HTML dans le nœud TipTap :
|
||
|
||
```html
|
||
<div data-database-block="true" data-db-id="authors-works-abc123"
|
||
data-db-authors='[{"id":"a1","name":"Jules Verne"}]'
|
||
data-db-books='[{"id":"bk1","title":"Vingt Mille Lieues..."}]'>
|
||
```
|
||
|
||
Problèmes critiques :
|
||
- **Isolation totale** : ces données n'ont aucun lien avec le carnet, les notes, ni les propriétés Prisma.
|
||
- **Scalabilité zéro** : stocker des listes entières de rows dans les attributs d'un nœud TipTap = explostion de la taille du HTML à chaque sauvegarde.
|
||
- **Duplication du modèle** : `NotebookSchema` + `NotebookProperty` + `NoteProperty` existent déjà en BDD et fonctionnent.
|
||
|
||
### 1.3 Confusion utilisateur
|
||
|
||
Un utilisateur qui tape `/database` s'attend à voir ses propres données structurées — pas un jeu de rôle bibliothèque de SF. Cette confusion est documentée comme rejet non-négociable par le fondateur.
|
||
|
||
### 1.4 Audit du code à supprimer
|
||
|
||
| Fichier | Statut | Raison |
|
||
|---------|--------|--------|
|
||
| `memento-note/components/tiptap-database-block-extension.tsx` | **SUPPRIMER** | Extension TipTap avec modèle `dbAuthors`/`dbBooks` |
|
||
| `memento-note/components/database-block-editor.tsx` | **SUPPRIMER** | UI Auteurs & Œuvres, hardcodé |
|
||
| `memento-note/lib/editor/database-block-types.ts` | **SUPPRIMER** | Types + données Verne/Liu Cixin |
|
||
| `rich-text-editor.tsx` L28, L193-194, L395, L412-420, L1286, L1335-1338, L1397-1401 | **MODIFIER** | Retirer imports et références `/database` anciens |
|
||
| `block-action-menu.tsx` L15-17, L33, L39, L51, L134-135 | **MODIFIER** | Retirer option `database` du menu "Transformer en" |
|
||
| `locales/*.json` — clés `databaseBlock.*` | **SUPPRIMER** | ~15 clés obsolètes |
|
||
|
||
---
|
||
|
||
## 2. Personas & Jobs-to-be-Done
|
||
|
||
### Persona 1 — Chloé, chercheuse (carnet "Thèse Linguistique")
|
||
|
||
Chloé a configuré son carnet avec des propriétés : `Statut` (select), `Langue` (select), `Lu` (checkbox), `Source` (text). Elle a 47 notes dans ce carnet. Elle rédige un chapitre synthétique et veut **voir le tableau de ses sources directement sous son paragraphe d'introduction**, sans quitter l'éditeur.
|
||
|
||
**Job-to-be-done :** *"Quand je rédige, je veux voir le tableau de mes données structurées en contexte, sans naviguer vers le carnet."*
|
||
|
||
### Persona 2 — Mehdi, chef de projet (carnet "Sprint Q2 2026")
|
||
|
||
Carnet structuré avec propriétés `Statut` (Kanban), `Priorité`, `Assigné`. Il prend ses notes de réunion et veut **insérer une vue en lecture de son Kanban** pour partager l'état du sprint dans la note de compte-rendu.
|
||
|
||
**Job-to-be-done :** *"Dans ma note de réunion, je veux une vue rapide de l'état des tâches du sprint."*
|
||
|
||
### Persona 3 — Yasmin, étudiante (carnet "Lectures Persan")
|
||
|
||
Carnet avec propriétés `Lu` (checkbox), `Note` (number). Elle lit en persan (RTL). Elle veut **voir sa liste de lectures sous forme de tableau** inline dans ses notes de révision.
|
||
|
||
**Job-to-be-done :** *"Dans mes notes, je veux voir mon tableau de lectures avec les bonnes valeurs — en persan, dans le bon sens."*
|
||
|
||
---
|
||
|
||
## 3. Options Produit pour `/database` — Analyse & Recommandation
|
||
|
||
### Option A — Embed Structured View (Recommandée ✅)
|
||
|
||
**Description :** Le bloc inline affiche une vue filtrée (Table ou Galerie) du schéma du carnet courant. Données lues depuis l'API existante. Le bloc stocke seulement `notebookId`, `displayMode`, `filterJson` dans ses attributs TipTap.
|
||
|
||
**Avantages :**
|
||
- Réutilise `NotesStructuredTable` et `NotesGalleryView` existants (quasi plug-and-play).
|
||
- Données cohérentes avec `/home` (même source de vérité).
|
||
- Léger : 3 attributs string dans le nœud TipTap, pas de payload.
|
||
- Facile à migrer : si le schéma du carnet change, le bloc se met à jour automatiquement.
|
||
- Clair pour l'utilisateur : "c'est mon carnet, mes données."
|
||
|
||
**Risques :**
|
||
- Éditeur doit recevoir `notebookId` (actuellement absent — patch mineur dans `note-content-area.tsx`).
|
||
- Si le carnet n'a pas de schéma, le bloc doit le gérer gracieusement.
|
||
|
||
**Verdict :** Option principale retenue.
|
||
|
||
### Option B — Linked Database Block (style Notion)
|
||
|
||
**Description :** L'utilisateur choisit n'importe quel carnet structuré (pas forcément le carnet de la note courante), avec filtre et vue configurables dans le bloc.
|
||
|
||
**Avantages :** Plus puissant — permet de croiser des carnets.
|
||
|
||
**Risques :**
|
||
- UI de sélection de carnet complexe dans le NodeView.
|
||
- Scope plus large que ce que justifie une US-4 isolée.
|
||
- Cross-notebook = scope Living Blocks étendu → reporter à v2.
|
||
|
||
**Verdict :** Déféré à v2 après que l'Option A soit stabilisée.
|
||
|
||
### Option C — Mini-table locale (colonnes libres dans la note)
|
||
|
||
**Description :** Table simple dans la note, indépendante des carnets, avec colonnes définissables par l'utilisateur.
|
||
|
||
**Avantages :** Pas de dépendance à Structured Views.
|
||
|
||
**Risques :**
|
||
- Crée exactement le second système de données parallèle qu'on veut éviter.
|
||
- Ne répond pas aux personas (Chloé et Mehdi veulent leurs vraies données).
|
||
- Rejectée explicitement par le fondateur.
|
||
|
||
**Verdict :** Hors scope. Ne pas implémenter.
|
||
|
||
### Option D — Supprimer `/database`
|
||
|
||
**Description :** Retirer complètement la commande slash et l'option du menu.
|
||
|
||
**Avantages :** Simple, propre.
|
||
|
||
**Risques :**
|
||
- Perd une surface UX qui a du sens (une fois bien connectée).
|
||
- L'annonce "database inline" est une attente utilisateur légitime.
|
||
|
||
**Verdict :** Fallback si l'Option A prend trop de temps — mais l'Option A est faisable en taille M.
|
||
|
||
---
|
||
|
||
## 4. User Story & Critères d'Acceptation (Given/When/Then)
|
||
|
||
### US-4 (Nouvelle) : Vue Structurée de Carnet Inline dans l'Éditeur
|
||
|
||
**En tant que** rédacteur dans un carnet structuré,
|
||
**Je veux** insérer une vue en lecture de mon tableau de notes directement dans le corps de ma note,
|
||
**Afin de** voir mes données structurées en contexte, sans quitter l'éditeur ni naviguer vers le carnet.
|
||
|
||
---
|
||
|
||
#### Scénario 1 — Insertion dans un carnet structuré
|
||
|
||
**Given** que ma note est dans un carnet qui a un schéma (`NotebookSchema` défini)
|
||
**When** je tape `/database` dans l'éditeur
|
||
**Then** un bloc `structuredViewBlock` est inséré, affichant la vue Table du carnet (colonnes = propriétés du schéma, lignes = notes du carnet)
|
||
**And** aucune donnée de démo n'est insérée
|
||
**And** l'utilisateur peut modifier les valeurs simples directement dans le bloc (checkbox, select, texte) — les changements se sauvegardent via `PATCH /api/notes/:id/properties`
|
||
|
||
---
|
||
|
||
#### Scénario 2 — Carnet sans schéma
|
||
|
||
**Given** que ma note est dans un carnet sans `NotebookSchema`
|
||
**When** j'insère un bloc `/database`
|
||
**Then** le bloc affiche un message contextuel : *"Ce carnet n'a pas encore de vue structurée. Configurez-en une depuis l'en-tête du carnet."* avec un lien vers le wizard
|
||
**And** aucune donnée n'est chargée, aucun crash
|
||
|
||
---
|
||
|
||
#### Scénario 3 — Note sans carnet
|
||
|
||
**Given** que ma note n'appartient à aucun carnet (notebookId absent)
|
||
**When** j'insère un bloc `/database`
|
||
**Then** le bloc affiche : *"Ce bloc nécessite un carnet. Déplacez cette note dans un carnet pour l'utiliser."*
|
||
|
||
---
|
||
|
||
#### Scénario 4 — Migration des blocs legacy
|
||
|
||
**Given** qu'une note contient un ancien nœud `data-database-block="true"` (auteurs/œuvres)
|
||
**When** la note est ouverte
|
||
**Then** le bloc obsolète est silencieusement retiré (ou affiché comme placeholder "bloc obsolète")
|
||
**And** le reste du contenu de la note est intact
|
||
**And** aucun crash ne se produit
|
||
|
||
---
|
||
|
||
#### Scénario 5 — RTL / locale persane
|
||
|
||
**Given** que la langue de l'app est `fa` (persan, RTL)
|
||
**When** le bloc est affiché
|
||
**Then** le wrapper du bloc a `dir="auto"`, le tableau s'aligne correctement en RTL
|
||
**And** les libellés du bloc sont traduits en persan (via `useLanguage()`)
|
||
|
||
---
|
||
|
||
#### Scénario 6 — Bascule de vue (Table → Galerie)
|
||
|
||
**Given** que le bloc est inséré dans un carnet avec `illustrationSvg` ou couleur
|
||
**When** l'utilisateur clique sur le sélecteur de vue dans le bloc
|
||
**Then** il peut basculer entre `Table` et `Galerie`
|
||
**And** l'attribut `displayMode` du nœud TipTap est mis à jour
|
||
**And** la vue se met à jour sans re-insertion du bloc
|
||
|
||
---
|
||
|
||
## 5. Out of Scope Explicite
|
||
|
||
| Fonctionnalité | Raison |
|
||
|----------------|--------|
|
||
| Vue Kanban inline | Drag-and-drop dans un NodeView TipTap = mauvaise UX, reporté en v2 |
|
||
| Sélection d'un carnet différent de la note courante | Scope trop large → v2 |
|
||
| Formules / rollups calculés | Hors scope Structured Views v1 |
|
||
| Relations multi-carnets | Hors scope — nécessite migration Prisma dédiée |
|
||
| Filtre personnalisé via UI dans le bloc | v2 — le bloc affiche tout le carnet en v1 |
|
||
| Pagination dans le bloc | v2 si le carnet dépasse 50 notes |
|
||
| Export PDF/CSV depuis le bloc | Fonctionnalité séparée |
|
||
|
||
---
|
||
|
||
## 6. Composants Prototype à Référencer
|
||
|
||
| Composant prototype | Usage | Note |
|
||
|--------------------|-------|------|
|
||
| `architectural-grid/` — `NotesStructuredTable` pattern | Colonnes et cellules — **référence design** | Utiliser le composant prod `notes-structured-table.tsx` |
|
||
| `architectural-grid/` — `NotesGalleryView` pattern | Vue galerie — **référence design** | Utiliser le composant prod `notes-gallery-view.tsx` |
|
||
| `architectural-grid1/ModernBlockNoteEditor.tsx` L1704+ | **NE PAS COPIER** — démo marketing Verne/Liu Cixin | Audit uniquement |
|
||
|
||
> ⚠️ Le prototype `architectural-grid1` est la référence de ce qu'il **ne faut pas** shipper. Le prototype `architectural-grid` (sans `1`) est la référence de design courant.
|
||
|
||
---
|
||
|
||
## 7. Modèle de Données
|
||
|
||
### 7.1 Nœud TipTap — Attributs (référence légère uniquement)
|
||
|
||
```typescript
|
||
// Extension TipTap — tiptap-structured-view-block-extension.tsx
|
||
Node.create({
|
||
name: 'structuredViewBlock',
|
||
group: 'block',
|
||
atom: true,
|
||
draggable: true,
|
||
addAttributes() {
|
||
return {
|
||
notebookId: {
|
||
default: null,
|
||
parseHTML: (el) => el.getAttribute('data-sv-notebook-id'),
|
||
renderHTML: (attrs) => attrs.notebookId
|
||
? { 'data-sv-notebook-id': attrs.notebookId }
|
||
: {},
|
||
},
|
||
displayMode: {
|
||
default: 'table',
|
||
parseHTML: (el) => el.getAttribute('data-sv-mode') || 'table',
|
||
renderHTML: (attrs) => ({ 'data-sv-mode': attrs.displayMode }),
|
||
},
|
||
filterJson: {
|
||
default: '{}',
|
||
parseHTML: (el) => el.getAttribute('data-sv-filter') || '{}',
|
||
renderHTML: (attrs) => ({ 'data-sv-filter': attrs.filterJson }),
|
||
},
|
||
}
|
||
},
|
||
parseHTML: () => [{ tag: 'div[data-structured-view-block]' }],
|
||
renderHTML: ({ HTMLAttributes }) =>
|
||
['div', mergeAttributes(HTMLAttributes, { 'data-structured-view-block': 'true' })],
|
||
addNodeView: () => ReactNodeViewRenderer(StructuredViewBlockEmbed),
|
||
})
|
||
```
|
||
|
||
### 7.2 Aucune migration Prisma requise
|
||
|
||
Le bloc réutilise le schéma Prisma existant :
|
||
- `NotebookSchema` / `NotebookProperty` → définition des colonnes
|
||
- `NoteProperty` → valeurs par note
|
||
- `Note` → lignes du tableau
|
||
|
||
Aucune nouvelle table. Aucun risque BDD.
|
||
|
||
### 7.3 Diagramme de relations
|
||
|
||
```mermaid
|
||
graph TD
|
||
A["structuredViewBlock node<br/>(TipTap attrs)"] -->|"notebookId"| B["GET /api/notebooks/:id/schema"]
|
||
B --> C["NotebookSchema<br/>(Prisma)"]
|
||
C --> D["NotebookProperty[]<br/>(colonnes)"]
|
||
A -->|"notebookId"| E["GET /api/notebooks/:id/notes<br/>(avec properties)"]
|
||
E --> F["Note[]<br/>(lignes)"]
|
||
F --> G["NoteProperty[]<br/>(valeurs)"]
|
||
D & G --> H["NotesStructuredTable<br/>(composant prod réutilisé)"]
|
||
H --> I["Rendu inline dans l'éditeur"]
|
||
```
|
||
|
||
---
|
||
|
||
## 8. Plan de Migration & Rollback du Code Actuel
|
||
|
||
### 8.1 Ordre de suppression (pour éviter les imports cassés)
|
||
|
||
1. **Supprimer** `memento-note/lib/editor/database-block-types.ts`
|
||
2. **Supprimer** `memento-note/components/database-block-editor.tsx`
|
||
3. **Supprimer** `memento-note/components/tiptap-database-block-extension.tsx`
|
||
4. **Modifier** `block-action-menu.tsx` — retirer import + option `database`
|
||
5. **Modifier** `rich-text-editor.tsx` — retirer import + slash entry + extension registration
|
||
6. **Créer** `tiptap-structured-view-block-extension.tsx` + `structured-view-block-embed.tsx`
|
||
7. **Modifier** `note-content-area.tsx` — passer `notebookId`
|
||
8. **Modifier** `locales/en.json` + `fr.json` — swap clés i18n
|
||
|
||
### 8.2 Gestion des notes existantes avec l'ancien bloc
|
||
|
||
Le nœud `databaseBlock` sera inconnu de TipTap après suppression de l'extension. Par défaut ProseMirror le drop silencieusement. Options :
|
||
|
||
- **Option simple (v1) :** Laisser ProseMirror supprimer le nœud inconnu au premier rendu — aucune action développeur.
|
||
- **Option propre (recommandée) :** Ajouter dans la nouvelle extension une règle `parseHTML` qui matche `div[data-database-block]` et le convertit en paragraphe `⚠️ Bloc base de données obsolète — ce contenu a été retiré.`
|
||
|
||
### 8.3 Rollback possible
|
||
|
||
Si le fondateur rejette l'Option A après implémentation :
|
||
- Les 3 fichiers supprimés sont dans git history — `git checkout HEAD~1 -- <fichier>` les restaure.
|
||
- La suppression de l'extension de `rich-text-editor.tsx` est une ligne — réversible en 2 minutes.
|
||
|
||
---
|
||
|
||
## 9. Risques Performance & Mitigations
|
||
|
||
| Risque | Probabilité | Impact | Mitigation |
|
||
|--------|-------------|--------|-----------|
|
||
| NodeView React lourd — re-render à chaque transaction TipTap | Haute | Haute | `shouldRerenderOnTransaction: false` sur l'éditeur (US-EDITOR-PERF) + `React.memo` sur le bloc embed + `trackNodeViewPosition: false` |
|
||
| SWR fetch bloque le rendu initial de la note | Moyenne | Moyenne | Suspense avec skeleton loader ; ne pas bloquer le rendu éditeur ; lazy-mount après 500ms |
|
||
| Note dans carnet avec 200+ notes — tableau trop long | Basse | Moyenne | Afficher les 20 premières notes avec `"Voir toutes les N notes dans le carnet"` CTA |
|
||
| RTL — cellules du tableau cassées | Basse | Haute | `dir="auto"` sur le wrapper ; tester avec locale `fa` avant merge |
|
||
|
||
---
|
||
|
||
## 10. i18n — Clés à Ajouter / Supprimer
|
||
|
||
### 10.1 Clés à ajouter (EN/FR minimum)
|
||
|
||
| Clé | EN | FR |
|
||
|-----|----|----|
|
||
| `structuredViewBlock.insertLabel` | Structured View | Vue structurée du carnet |
|
||
| `structuredViewBlock.insertDesc` | Embed your notebook's structured data | Intégrez les données structurées de votre carnet |
|
||
| `structuredViewBlock.noSchema` | This notebook has no structured view yet. Set one up from the notebook header. | Ce carnet n'a pas encore de vue structurée. Configurez-en une depuis l'en-tête du carnet. |
|
||
| `structuredViewBlock.noNotebook` | This block requires a notebook. Move this note to a notebook first. | Ce bloc nécessite un carnet. Déplacez cette note dans un carnet pour l'utiliser. |
|
||
| `structuredViewBlock.openInNotebook` | Open in notebook | Ouvrir dans le carnet |
|
||
| `structuredViewBlock.displayModeTable` | Table | Tableau |
|
||
| `structuredViewBlock.displayModeGallery` | Gallery | Galerie |
|
||
| `structuredViewBlock.loadError` | Failed to load structured data. | Impossible de charger les données structurées. |
|
||
| `structuredViewBlock.retry` | Retry | Réessayer |
|
||
| `structuredViewBlock.deprecatedBlock` | Outdated block removed. | Bloc obsolète retiré. |
|
||
|
||
> **Note :** Si l'utilisateur demande à compléter les 15 locales, ne remplir que les clés — laisser la traduction des 13 autres locales à l'outil de traduction externe (règle AGENTS.md).
|
||
|
||
### 10.2 Clés à supprimer (après vérification pas d'autre consommateur)
|
||
|
||
`databaseBlock.title`, `databaseBlock.viewTable`, `databaseBlock.viewCards`, `databaseBlock.hint`, `databaseBlock.colAuthor`, `databaseBlock.colWorks`, `databaseBlock.colRollup`, `databaseBlock.noLinkedWorks`, `databaseBlock.deleteShort`, `databaseBlock.addAuthor`, `databaseBlock.authorPlaceholder`, `databaseBlock.createAuthor`, `databaseBlock.worksBase`, `databaseBlock.storedCount`, `databaseBlock.addWork`, `databaseBlock.bookTitlePlaceholder`, `databaseBlock.selectAuthor`, `databaseBlock.tagPlaceholder`, `databaseBlock.coverPlaceholder`, `databaseBlock.insertWork`, `databaseBlock.deleteCard`, `databaseBlock.insertFailed`, `databaseBlock.defaultTag`
|
||
|
||
---
|
||
|
||
## 11. Checklist QA Manuelle
|
||
|
||
### 11.1 Français (LTR)
|
||
|
||
- [ ] Taper `/database` dans une note d'un carnet structuré → bloc s'insère avec les données réelles
|
||
- [ ] Taper `/database` → même résultat (rétrocompatibilité keyword)
|
||
- [ ] Taper `/database` dans une note sans carnet → message "nécessite un carnet"
|
||
- [ ] Taper `/database` dans une note d'un carnet sans schéma → callout wizard avec lien
|
||
- [ ] Ouvrir une note avec un ancien bloc `databaseBlock` → note s'ouvre, bloc absent ou placeholder, pas de crash
|
||
- [ ] Menu "Transformer en" → option "Vue structurée" présente, option "Base de données" (ancienne) absente
|
||
- [ ] Bascule Table ↔ Galerie dans le bloc → vue change, pas de réinsertion du bloc
|
||
- [ ] `npm run build` → 0 erreur, aucun import vers fichiers supprimés
|
||
|
||
### 11.2 Persan / RTL (fa)
|
||
|
||
- [ ] Changer la langue en `fa` → libellés du bloc en persan
|
||
- [ ] Le bloc wrapper est `dir="auto"` → tableau aligné à droite
|
||
- [ ] Cellules du tableau RTL lisibles (pas de texte coupé)
|
||
- [ ] Callout "no schema" en persan → texte lisible RTL
|
||
|
||
---
|
||
|
||
## 12. Estimation Effort
|
||
|
||
| Tâche | Taille |
|
||
|-------|--------|
|
||
| Supprimer 3 fichiers legacy | XS |
|
||
| Patcher `rich-text-editor.tsx` + `block-action-menu.tsx` | S |
|
||
| Patcher `note-content-area.tsx` (`notebookId` prop) | XS |
|
||
| Créer `tiptap-structured-view-block-extension.tsx` | S |
|
||
| Créer `structured-view-block-embed.tsx` (SWR + états + RTL) | M |
|
||
| i18n EN + FR | XS |
|
||
| QA manuelle FR + fa | S |
|
||
| **Total estimé** | **M** (~1–2 jours dev) |
|
||
|
||
---
|
||
|
||
## 13. Décisions Produit Actées
|
||
|
||
### Édition inline — ACTIVÉE en v1
|
||
L'utilisateur peut modifier les valeurs simples directement dans le bloc (checkbox, select, texte court). Les changements se sauvegardent via `PATCH /api/notes/:id/properties` avec mise à jour optimiste. C'est la meilleure expérience utilisateur — un bloc en lecture seule n'aurait aucun intérêt.
|
||
|
||
### Kanban inline — REPORTÉ en v2
|
||
Table + Galerie uniquement en v1. Le drag-and-drop dans un NodeView TipTap crée de mauvaises interactions. Le Kanban s'utilisera depuis le carnet comme aujourd'hui.
|
||
|
||
---
|
||
|
||
## Annexe — Diff Proposé pour `docs/story-nextgen-editor.md`
|
||
|
||
Remplacer la section `### US-4: Bloc de Base de Données Relationnelle Inline` (lignes 71–85) par :
|
||
|
||
```markdown
|
||
### US-4: Vue Structurée de Carnet Inline *(Redesign — voir `docs/story-nextgen-editor-us4-redesign.md`)*
|
||
|
||
> ⚠️ **DEPRECATED** — La spécification précédente (bloc "Auteurs & Œuvres") est rejetée.
|
||
> Voir [`docs/story-nextgen-editor-us4-redesign.md`](./story-nextgen-editor-us4-redesign.md) pour la nouvelle spec.
|
||
|
||
**En tant que** rédacteur dans un carnet structuré,
|
||
**Je veux** insérer une vue en lecture de mon tableau de notes directement dans le corps de ma note,
|
||
**Afin de** voir mes données structurées en contexte, sans quitter l'éditeur.
|
||
|
||
*(Critères d'acceptation détaillés dans le fichier redesign ci-dessus.)*
|
||
```
|
||
|
||
Et remplacer la section `### 1. Structure du Nœud de Base de Données Tiptap` + `### 2.` + `### 3.` dans les Spécifications Techniques (lignes 90–109) par :
|
||
|
||
```markdown
|
||
### 1. Structure du Nœud `structuredViewBlock` (TipTap)
|
||
Extension TipTap `StructuredViewBlockExtension` dans `tiptap-structured-view-block-extension.tsx` :
|
||
- Attributs : `notebookId` (string), `displayMode` ('table'|'gallery'), `filterJson` (string JSON)
|
||
- ReactNodeViewRenderer → `structured-view-block-embed.tsx`
|
||
|
||
### 2. Suppression du code legacy
|
||
- Supprimer : `tiptap-database-block-extension.tsx`, `database-block-editor.tsx`, `lib/editor/database-block-types.ts`
|
||
- Modifier : `rich-text-editor.tsx`, `block-action-menu.tsx`, `locales/*.json`
|
||
- Voir plan complet dans `docs/story-nextgen-editor-us4-redesign.md` §8.
|
||
```
|
||
|
||
---
|
||
|
||
## Annexe — Diff Proposé pour `docs/user-stories.md`
|
||
|
||
### Dans le tableau de bord (ligne 23)
|
||
|
||
```diff
|
||
-| **US-NEXTGEN-EDITOR** | Éditeur Next-Gen : Drag Handle + Menu Bloc + DB Inline + Smart Paste | 🚧 **PLANIFIÉ** | Voir `docs/story-nextgen-editor.md` |
|
||
+| **US-NEXTGEN-EDITOR** | Éditeur Next-Gen : Drag Handle + Menu Bloc + Vue Structurée Inline + Smart Paste | 🚧 **PLANIFIÉ** | Voir `docs/story-nextgen-editor.md` + `docs/story-nextgen-editor-us4-redesign.md` |
|
||
```
|
||
|
||
### Dans la section US-NEXTGEN-EDITOR (US-4, ligne 622–626)
|
||
|
||
```diff
|
||
-### US-4 : Bloc de Base de Données Relationnelle Inline
|
||
-- Slash `/database` → insère un React NodeView
|
||
-- Vues Tableau / Fiches avec Rollup dynamique
|
||
-- Modèle relationnel local (auteurs/livres par défaut, ou lié au carnet)
|
||
+### US-4 : Vue Structurée de Carnet Inline *(Redesign)*
|
||
+> Spec complète : [`docs/story-nextgen-editor-us4-redesign.md`](./story-nextgen-editor-us4-redesign.md)
|
||
+- Slash `/database` (+ keywords `db`, `tableau`, `structured`) → insère un `structuredViewBlock`
|
||
+- Affiche Table ou Galerie du carnet courant via l'API Structured Views existante
|
||
+- Bloc stocke uniquement `notebookId` + `displayMode` (pas de données en attrs)
|
||
+- Graceful fallback si carnet sans schéma ou note sans carnet
|
||
+- Supprime le code legacy `tiptap-database-block-extension.tsx` (Verne/Liu Cixin)
|
||
+- **Dépend de :** US-STRUCTURED-VIEWS ✅ (livré)
|
||
```
|
||
|
||
### Dans la liste de fichiers (ligne 627–631)
|
||
|
||
```diff
|
||
-### Fichiers
|
||
-- `[NEW]` `tiptap-drag-handle-plugin.ts` — Plugin ProseMirror pur
|
||
-- `[NEW]` `tiptap-database-block-extension.tsx` — NodeView React
|
||
-- `[MODIFY]` `rich-text-editor.tsx` — Intégration drag handle + DB + paste intercept
|
||
-- `[MODIFY]` `globals.css` — Gutter, poignée, glassmorphic dropdowns
|
||
+### Fichiers
|
||
+- `[NEW]` `tiptap-drag-handle-plugin.ts` — Plugin ProseMirror pur (US-1, inchangé)
|
||
+- `[NEW]` `tiptap-structured-view-block-extension.tsx` — NodeView Vue Structurée (remplace DB)
|
||
+- `[NEW]` `structured-view-block-embed.tsx` — Composant embed avec SWR + states
|
||
+- `[DELETE]` `tiptap-database-block-extension.tsx` — Bloc legacy auteurs/œuvres rejeté
|
||
+- `[DELETE]` `database-block-editor.tsx` — UI legacy rejetée
|
||
+- `[DELETE]` `lib/editor/database-block-types.ts` — Types legacy rejetés
|
||
+- `[MODIFY]` `rich-text-editor.tsx` — Intégration drag handle + Vue Structurée + paste intercept
|
||
+- `[MODIFY]` `note-content-area.tsx` — Passer `notebookId` à l'éditeur
|
||
+- `[MODIFY]` `block-action-menu.tsx` — Remplacer option "Database" par "Vue structurée"
|
||
+- `[MODIFY]` `globals.css` — Gutter, poignée, glassmorphic dropdowns
|
||
```
|