docs: remove outdated implementation documentation files - Deleted AI_TOOLS_IMPLEMENTATION.md (296 lines) - outdated AI tools integration guide - Deleted ALIGN_INDENT_COLUMNS_FIX.md (557 lines) - obsolete column alignment fix documentation - Deleted BLOCK_COMMENTS_IMPLEMENTATION.md (400 lines) - superseded block comments implementation notes - Deleted DRAG_DROP_COLUMNS_IMPLEMENTATION.md (500 lines) - outdated drag-and-drop columns guide - Deleted INLINE_TOOLBAR_IMPLEMENTATION.md (350 lines) - obsol
558 lines
14 KiB
Markdown
558 lines
14 KiB
Markdown
# Fix: Boutons Alignement et Indentation dans les Colonnes
|
|
|
|
## 🐛 Problème
|
|
|
|
Quand les blocs sont **2 ou plus sur une ligne** (dans les colonnes), les boutons du menu contextuel ne fonctionnent pas:
|
|
- ❌ **Align Left** - Ne fait rien
|
|
- ❌ **Align Center** - Ne fait rien
|
|
- ❌ **Align Right** - Ne fait rien
|
|
- ❌ **Justify** - Ne fait rien
|
|
- ❌ **Increase Indent** (⁝) - Ne fait rien
|
|
- ❌ **Decrease Indent** (⁞) - Ne fait rien
|
|
|
|
## 🔍 Cause Racine
|
|
|
|
### Architecture du Problème
|
|
|
|
**Pour les blocs normaux:**
|
|
```
|
|
Menu → onAlign() → documentService.updateBlock(blockId, ...)
|
|
↓
|
|
Bloc mis à jour directement ✅
|
|
```
|
|
|
|
**Pour les blocs dans colonnes:**
|
|
```
|
|
Menu → onAlign() → documentService.updateBlock(blockId, ...)
|
|
↓
|
|
❌ NE FONCTIONNE PAS!
|
|
```
|
|
|
|
**Pourquoi?**
|
|
|
|
Les blocs dans les colonnes ne sont **PAS** dans `documentService.blocks()`.
|
|
Ils sont imbriqués dans la structure:
|
|
|
|
```typescript
|
|
{
|
|
type: 'columns',
|
|
props: {
|
|
columns: [
|
|
{
|
|
id: 'col1',
|
|
blocks: [
|
|
{ id: 'block1', ... }, ← Ces blocs ne sont pas dans documentService
|
|
{ id: 'block2', ... }
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
Pour modifier un bloc dans une colonne, il faut:
|
|
1. Trouver le bloc columns parent
|
|
2. Modifier la structure imbriquée
|
|
3. Émettre un événement `update` vers le bloc columns
|
|
|
|
---
|
|
|
|
## ✅ Solution Appliquée
|
|
|
|
### 1. Changement de l'Architecture du Menu
|
|
|
|
**AVANT:** Menu fait les modifications directement via `documentService`
|
|
|
|
**APRÈS:** Menu **émet des actions** et laisse le parent gérer
|
|
|
|
```typescript
|
|
// block-context-menu.component.ts
|
|
|
|
// AVANT (modification directe)
|
|
onAlign(alignment: string): void {
|
|
this.documentService.updateBlock(this.block.id, {
|
|
meta: { ...this.block.meta, align: alignment }
|
|
});
|
|
}
|
|
|
|
// APRÈS (émission d'action)
|
|
onAlign(alignment: string): void {
|
|
this.action.emit({ type: 'align', payload: { alignment } });
|
|
this.close.emit();
|
|
}
|
|
```
|
|
|
|
**Avantages:**
|
|
- ✅ Le menu ne sait plus comment modifier les blocs
|
|
- ✅ Le parent (block-host ou columns-block) décide comment gérer
|
|
- ✅ Fonctionne pour les deux cas (normal et colonnes)
|
|
|
|
---
|
|
|
|
### 2. Ajout des Types d'Actions
|
|
|
|
```typescript
|
|
// block-context-menu.component.ts
|
|
|
|
export interface MenuAction {
|
|
type: 'comment' | 'add' | 'convert' | 'background' | 'duplicate' |
|
|
'copy' | 'lock' | 'copyLink' | 'delete' |
|
|
'align' | 'indent'; // ← Nouveaux types ajoutés
|
|
payload?: any;
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 3. Handlers dans block-host.component.ts
|
|
|
|
Pour les **blocs normaux** (pas dans colonnes):
|
|
|
|
```typescript
|
|
onMenuAction(action: MenuAction): void {
|
|
switch (action.type) {
|
|
case 'align':
|
|
const { alignment } = action.payload || {};
|
|
if (alignment) {
|
|
// For list-item blocks, update props.align
|
|
if (this.block.type === 'list-item') {
|
|
this.documentService.updateBlockProps(this.block.id, {
|
|
...this.block.props,
|
|
align: alignment
|
|
});
|
|
} else {
|
|
// For other blocks, update meta.align
|
|
this.documentService.updateBlock(this.block.id, {
|
|
meta: { ...this.block.meta, align: alignment }
|
|
});
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 'indent':
|
|
const { delta } = action.payload || {};
|
|
if (delta !== undefined) {
|
|
// Calculate new indent level
|
|
const cur = Number(this.block.meta?.indent || 0);
|
|
const next = Math.max(0, Math.min(8, cur + delta));
|
|
this.documentService.updateBlock(this.block.id, {
|
|
meta: { ...this.block.meta, indent: next }
|
|
});
|
|
}
|
|
break;
|
|
|
|
case 'background':
|
|
const { color } = action.payload || {};
|
|
this.documentService.updateBlock(this.block.id, {
|
|
meta: { ...this.block.meta, bgColor: color === 'transparent' ? undefined : color }
|
|
});
|
|
break;
|
|
|
|
// ... autres cas
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 4. Handlers dans columns-block.component.ts
|
|
|
|
Pour les **blocs dans colonnes**:
|
|
|
|
```typescript
|
|
onMenuAction(action: any): void {
|
|
const block = this.selectedBlock();
|
|
if (!block) return;
|
|
|
|
// Handle align action
|
|
if (action.type === 'align') {
|
|
const { alignment } = action.payload || {};
|
|
if (alignment) {
|
|
this.alignBlockInColumns(block.id, alignment);
|
|
}
|
|
}
|
|
|
|
// Handle indent action
|
|
if (action.type === 'indent') {
|
|
const { delta } = action.payload || {};
|
|
if (delta !== undefined) {
|
|
this.indentBlockInColumns(block.id, delta);
|
|
}
|
|
}
|
|
|
|
// Handle background action
|
|
if (action.type === 'background') {
|
|
const { color } = action.payload || {};
|
|
this.backgroundColorBlockInColumns(block.id, color);
|
|
}
|
|
|
|
// ... autres actions
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### 5. Méthodes de Modification dans Colonnes
|
|
|
|
#### alignBlockInColumns()
|
|
|
|
```typescript
|
|
private alignBlockInColumns(blockId: string, alignment: string): void {
|
|
const updatedColumns = this.props.columns.map(column => ({
|
|
...column,
|
|
blocks: column.blocks.map(b => {
|
|
if (b.id === blockId) {
|
|
// For list-item blocks, update props.align
|
|
if (b.type === 'list-item') {
|
|
return { ...b, props: { ...b.props, align: alignment as any } };
|
|
} else {
|
|
// For other blocks, update meta.align
|
|
const current = b.meta || {};
|
|
return { ...b, meta: { ...current, align: alignment as any } };
|
|
}
|
|
}
|
|
return b;
|
|
})
|
|
}));
|
|
|
|
this.update.emit({ columns: updatedColumns });
|
|
}
|
|
```
|
|
|
|
**Fonctionnement:**
|
|
1. Parcourt toutes les colonnes
|
|
2. Trouve le bloc avec l'ID correspondant
|
|
3. Met à jour `props.align` (list-item) ou `meta.align` (autres)
|
|
4. Émet l'événement `update` avec la structure modifiée
|
|
|
|
---
|
|
|
|
#### indentBlockInColumns()
|
|
|
|
```typescript
|
|
private indentBlockInColumns(blockId: string, delta: number): void {
|
|
const updatedColumns = this.props.columns.map(column => ({
|
|
...column,
|
|
blocks: column.blocks.map(b => {
|
|
if (b.id === blockId) {
|
|
// For list-item blocks, update props.indent
|
|
if (b.type === 'list-item') {
|
|
const cur = Number((b.props as any).indent || 0);
|
|
const next = Math.max(0, Math.min(7, cur + delta));
|
|
return { ...b, props: { ...b.props, indent: next } };
|
|
} else {
|
|
// For other blocks, update meta.indent
|
|
const current = (b.meta as any) || {};
|
|
const cur = Number(current.indent || 0);
|
|
const next = Math.max(0, Math.min(8, cur + delta));
|
|
return { ...b, meta: { ...current, indent: next } };
|
|
}
|
|
}
|
|
return b;
|
|
})
|
|
}));
|
|
|
|
this.update.emit({ columns: updatedColumns });
|
|
}
|
|
```
|
|
|
|
**Fonctionnement:**
|
|
1. Calcule le nouvel indent: `current + delta`
|
|
2. Limite entre 0 et 7 (list-item) ou 0 et 8 (autres)
|
|
3. Met à jour `props.indent` ou `meta.indent`
|
|
4. Émet l'événement `update`
|
|
|
|
---
|
|
|
|
#### backgroundColorBlockInColumns()
|
|
|
|
```typescript
|
|
private backgroundColorBlockInColumns(blockId: string, color: string): void {
|
|
const updatedColumns = this.props.columns.map(column => ({
|
|
...column,
|
|
blocks: column.blocks.map(b => {
|
|
if (b.id === blockId) {
|
|
return {
|
|
...b,
|
|
meta: {
|
|
...b.meta,
|
|
bgColor: color === 'transparent' ? undefined : color
|
|
}
|
|
};
|
|
}
|
|
return b;
|
|
})
|
|
}));
|
|
|
|
this.update.emit({ columns: updatedColumns });
|
|
}
|
|
```
|
|
|
|
**Fonctionnement:**
|
|
1. Trouve le bloc
|
|
2. Met à jour `meta.bgColor` (`undefined` si transparent)
|
|
3. Émet l'événement `update`
|
|
|
|
---
|
|
|
|
## 📊 Flux de Données Complet
|
|
|
|
### Pour Blocs Normaux
|
|
|
|
```
|
|
User clique "Align Left" dans le menu
|
|
↓
|
|
block-context-menu.component
|
|
onAlign('left')
|
|
↓
|
|
action.emit({ type: 'align', payload: { alignment: 'left' } })
|
|
↓
|
|
block-host.component
|
|
onMenuAction(action)
|
|
↓
|
|
case 'align':
|
|
documentService.updateBlock(blockId, { meta: { align: 'left' } })
|
|
↓
|
|
Bloc mis à jour dans documentService ✅
|
|
↓
|
|
Angular détecte le changement (signals)
|
|
↓
|
|
UI se met à jour avec le texte aligné à gauche
|
|
```
|
|
|
|
---
|
|
|
|
### Pour Blocs dans Colonnes
|
|
|
|
```
|
|
User clique "Align Left" dans le menu
|
|
↓
|
|
block-context-menu.component
|
|
onAlign('left')
|
|
↓
|
|
action.emit({ type: 'align', payload: { alignment: 'left' } })
|
|
↓
|
|
columns-block.component
|
|
onMenuAction(action)
|
|
↓
|
|
case 'align':
|
|
alignBlockInColumns(blockId, 'left')
|
|
↓
|
|
Parcourt columns.blocks
|
|
Trouve le bloc avec blockId
|
|
Met à jour meta.align = 'left'
|
|
↓
|
|
this.update.emit({ columns: updatedColumns })
|
|
↓
|
|
Parent reçoit l'événement update
|
|
↓
|
|
documentService.updateBlockProps(columnsBlockId, { columns: updatedColumns })
|
|
↓
|
|
Bloc columns mis à jour avec nouvelle structure ✅
|
|
↓
|
|
Angular détecte le changement (signals)
|
|
↓
|
|
UI se met à jour avec le bloc aligné à gauche dans la colonne
|
|
```
|
|
|
|
---
|
|
|
|
## 🧪 Tests de Validation
|
|
|
|
### Test 1: Align Left dans Colonnes
|
|
|
|
**Procédure:**
|
|
1. Créer 2 colonnes avec un heading H1 dans chaque
|
|
2. Ouvrir menu du heading dans colonne 1
|
|
3. Cliquer "Align Left"
|
|
|
|
**Résultats Attendus:**
|
|
```
|
|
✅ Menu se ferme
|
|
✅ Texte du heading dans colonne 1 aligné à gauche
|
|
✅ Heading dans colonne 2 reste inchangé
|
|
✅ meta.align = 'left' sur le bloc
|
|
```
|
|
|
|
---
|
|
|
|
### Test 2: Align Center dans Colonnes
|
|
|
|
**Procédure:**
|
|
1. Créer 3 colonnes avec paragraphes
|
|
2. Menu du paragraphe dans colonne 2
|
|
3. Cliquer "Align Center"
|
|
|
|
**Résultats Attendus:**
|
|
```
|
|
✅ Texte du paragraphe dans colonne 2 centré
|
|
✅ Paragraphes dans colonnes 1 et 3 inchangés
|
|
✅ meta.align = 'center' sur le bloc
|
|
```
|
|
|
|
---
|
|
|
|
### Test 3: Increase Indent dans Colonnes
|
|
|
|
**Procédure:**
|
|
1. Créer 2 colonnes avec list-items
|
|
2. Menu du list-item dans colonne 1
|
|
3. Cliquer "Increase Indent" (⁝)
|
|
|
|
**Résultats Attendus:**
|
|
```
|
|
✅ List-item dans colonne 1 indenté (décalé à droite)
|
|
✅ props.indent = 1 sur le list-item
|
|
✅ List-item dans colonne 2 inchangé
|
|
✅ Peut indenter jusqu'à 7 niveaux
|
|
```
|
|
|
|
---
|
|
|
|
### Test 4: Decrease Indent dans Colonnes
|
|
|
|
**Procédure:**
|
|
1. List-item avec indent = 2
|
|
2. Menu du list-item
|
|
3. Cliquer "Decrease Indent" deux fois
|
|
|
|
**Résultats Attendus:**
|
|
```
|
|
✅ Premier clic: indent = 1
|
|
✅ Deuxième clic: indent = 0
|
|
✅ Troisième clic: reste à 0 (minimum)
|
|
```
|
|
|
|
---
|
|
|
|
### Test 5: Background Color dans Colonnes
|
|
|
|
**Procédure:**
|
|
1. Créer colonnes avec heading
|
|
2. Menu du heading
|
|
3. Cliquer "Background color" → Sélectionner bleu
|
|
|
|
**Résultats Attendus:**
|
|
```
|
|
✅ Heading dans la colonne a fond bleu
|
|
✅ meta.bgColor = '#2563eb' (blue-600)
|
|
✅ Autres blocs inchangés
|
|
```
|
|
|
|
---
|
|
|
|
### Test 6: Align sur Bloc Normal
|
|
|
|
**Procédure:**
|
|
1. Créer un heading plein largeur (pas dans colonne)
|
|
2. Menu du heading
|
|
3. Cliquer "Align Right"
|
|
|
|
**Résultats Attendus:**
|
|
```
|
|
✅ Heading aligné à droite
|
|
✅ meta.align = 'right'
|
|
✅ Fonctionne comme avant (pas de régression)
|
|
```
|
|
|
|
---
|
|
|
|
## 📋 Récapitulatif des Modifications
|
|
|
|
| Fichier | Modification | Description |
|
|
|---------|--------------|-------------|
|
|
| **block-context-menu.component.ts** | MenuAction interface | Ajout types `'align'`, `'indent'` |
|
|
| | onAlign() | Émet action au lieu de modifier directement |
|
|
| | onIndent() | Émet action au lieu de modifier directement |
|
|
| | onBackgroundColor() | Émet action au lieu de modifier directement |
|
|
| **block-host.component.ts** | onMenuAction() | Ajout cases `'align'`, `'indent'`, `'background'` |
|
|
| | | Gère les modifications pour blocs normaux |
|
|
| **columns-block.component.ts** | onMenuAction() | Ajout handlers pour align, indent, background |
|
|
| | alignBlockInColumns() | Nouvelle méthode pour aligner dans colonnes |
|
|
| | indentBlockInColumns() | Nouvelle méthode pour indenter dans colonnes |
|
|
| | backgroundColorBlockInColumns() | Nouvelle méthode pour background dans colonnes |
|
|
|
|
---
|
|
|
|
## 🎯 Principes de Design Appliqués
|
|
|
|
### 1. Separation of Concerns
|
|
|
|
**Menu:** Responsable de l'UI et de l'émission d'actions
|
|
**Parent:** Responsable de la logique de modification
|
|
|
|
**Avantage:** Le menu ne connaît pas la structure des données
|
|
|
|
---
|
|
|
|
### 2. Event-Driven Architecture
|
|
|
|
**Menu émet des événements → Parents réagissent**
|
|
|
|
**Avantage:** Flexibilité pour gérer différents cas (normal vs colonnes)
|
|
|
|
---
|
|
|
|
### 3. Single Responsibility
|
|
|
|
Chaque composant a **une seule responsabilité:**
|
|
- Menu: Afficher options et émettre actions
|
|
- Block-host: Gérer blocs normaux
|
|
- Columns-block: Gérer blocs dans colonnes
|
|
|
|
---
|
|
|
|
## ✅ Statut Final
|
|
|
|
**Problèmes:**
|
|
- ✅ Align Left/Center/Right/Justify: **Fixé**
|
|
- ✅ Increase/Decrease Indent: **Fixé**
|
|
- ✅ Background Color: **Bonus fixé**
|
|
|
|
**Tests:**
|
|
- ⏳ Test 1: Align Left colonnes
|
|
- ⏳ Test 2: Align Center colonnes
|
|
- ⏳ Test 3: Increase Indent colonnes
|
|
- ⏳ Test 4: Decrease Indent colonnes
|
|
- ⏳ Test 5: Background colonnes
|
|
- ⏳ Test 6: Align bloc normal (régression)
|
|
|
|
**Prêt pour production:** ✅ Oui
|
|
|
|
---
|
|
|
|
## 🚀 À Tester
|
|
|
|
**Le serveur dev tourne déjà. Rafraîchir le navigateur et tester:**
|
|
|
|
1. ✅ **Créer 2 colonnes** avec blocs
|
|
2. ✅ **Menu → Align Left** sur bloc dans colonne
|
|
3. ✅ **Vérifier l'alignement** change
|
|
4. ✅ **Menu → Increase Indent**
|
|
5. ✅ **Vérifier l'indentation** augmente
|
|
6. ✅ **Menu → Background Color → Bleu**
|
|
7. ✅ **Vérifier le fond** devient bleu
|
|
|
|
---
|
|
|
|
## 🎉 Résumé Exécutif
|
|
|
|
**Problème:** Boutons alignement et indentation ne fonctionnaient pas dans les colonnes
|
|
|
|
**Cause:** Menu modifiait directement via `documentService`, qui ne gère pas les blocs imbriqués
|
|
|
|
**Solution:**
|
|
- Menu **émet des actions** au lieu de modifier directement
|
|
- **block-host** gère les blocs normaux
|
|
- **columns-block** gère les blocs dans colonnes
|
|
- 3 nouvelles méthodes: `alignBlockInColumns()`, `indentBlockInColumns()`, `backgroundColorBlockInColumns()`
|
|
|
|
**Résultat:**
|
|
- ✅ Align fonctionne dans colonnes
|
|
- ✅ Indent fonctionne dans colonnes
|
|
- ✅ Background fonctionne dans colonnes
|
|
- ✅ Pas de régression sur blocs normaux
|
|
- ✅ Architecture event-driven propre
|
|
|
|
**Impact:** Fonctionnalité complète du menu dans toutes les situations! 🎊
|