217 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			217 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
# Fix de la Sauvegarde Excalidraw - Diagnostic et Solution
 | 
						|
 | 
						|
## Problème Initial
 | 
						|
 | 
						|
1. **Bouton Sauvegarde ne déclenchait aucune requête réseau**
 | 
						|
2. **Boutons Export PNG/SVG désactivés en permanence**
 | 
						|
 | 
						|
## Cause Racine
 | 
						|
 | 
						|
Le problème était dans la **séquence de binding des listeners** :
 | 
						|
 | 
						|
### Séquence défaillante :
 | 
						|
1. `ngAfterViewInit()` s'exécute
 | 
						|
2. Tente de binder les listeners sur `<excalidraw-editor>`
 | 
						|
3. **Mais l'élément n'existe pas encore** car il est derrière `*ngIf="!isLoading()"`
 | 
						|
4. Les listeners ne sont jamais attachés
 | 
						|
5. L'événement `scene-change` n'est jamais capturé
 | 
						|
6. `excalidrawReady` reste `false`
 | 
						|
7. Les exports restent désactivés
 | 
						|
 | 
						|
## Solution Implémentée
 | 
						|
 | 
						|
### 1. Binding au bon moment
 | 
						|
 | 
						|
**Avant** :
 | 
						|
```typescript
 | 
						|
ngAfterViewInit(): void {
 | 
						|
  this.bindEditorHostListeners(); // ❌ Trop tôt
 | 
						|
  setTimeout(() => this.bindEditorHostListeners(), 0);
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
**Après** :
 | 
						|
```typescript
 | 
						|
onExcalidrawReady() {
 | 
						|
  this.excalidrawReady = true;
 | 
						|
  this.bindEditorHostListeners(); // ✅ Après le (ready) event
 | 
						|
}
 | 
						|
 | 
						|
ngAfterViewInit(): void {
 | 
						|
  // L'élément sera bindé via (ready)="onExcalidrawReady()"
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
Le template a déjà `(ready)="onExcalidrawReady()"` qui se déclenche quand l'API Excalidraw est disponible.
 | 
						|
 | 
						|
### 2. Indicateur Visuel de Sauvegarde
 | 
						|
 | 
						|
Remplacement du bouton texte par un **indicateur visuel avec icône de disquette** :
 | 
						|
 | 
						|
#### États :
 | 
						|
- 🔴 **Rouge** + "Non sauvegardé" : modifications non enregistrées
 | 
						|
- ⚫ **Gris** + "Sauvegardé" : tout est sauvegardé
 | 
						|
- 🟡 **Jaune** + "Sauvegarde..." + animation pulse : sauvegarde en cours
 | 
						|
 | 
						|
#### Comportement :
 | 
						|
- **Cliquable** : force une sauvegarde immédiate
 | 
						|
- **Tooltip** : indique l'état et suggère Ctrl+S
 | 
						|
- **Toast** : notification "Sauvegarde réussie" ou "Erreur de sauvegarde"
 | 
						|
 | 
						|
### 3. Sauvegarde Automatique
 | 
						|
 | 
						|
**Pipeline RxJS** :
 | 
						|
```typescript
 | 
						|
fromEvent<CustomEvent>(host, 'scene-change')
 | 
						|
  .pipe(
 | 
						|
    debounceTime(2000),           // Attend 2s après le dernier changement
 | 
						|
    distinctUntilChanged(),       // Ignore si identique au dernier hash
 | 
						|
    switchMap(() => save()),      // Sauvegarde
 | 
						|
  )
 | 
						|
```
 | 
						|
 | 
						|
### 4. Logs de Diagnostic
 | 
						|
 | 
						|
Ajout de logs console pour tracer le flux :
 | 
						|
- `🎨 Excalidraw Ready - Binding listeners`
 | 
						|
- `🔗 Binding Excalidraw host listeners`
 | 
						|
- `📝 Scene changed`
 | 
						|
- `💾 Autosaving...`
 | 
						|
- `✅ Autosave successful`
 | 
						|
- `💾 Manual save triggered`
 | 
						|
- `📤 Sending save request...`
 | 
						|
- `✅ Manual save successful`
 | 
						|
 | 
						|
## Fichiers Modifiés
 | 
						|
 | 
						|
### `src/app/features/drawings/drawings-editor.component.ts`
 | 
						|
- Déplacement du binding dans `onExcalidrawReady()`
 | 
						|
- Ajout de logs pour diagnostic
 | 
						|
- Toast sur sauvegarde manuelle
 | 
						|
- Debounce augmenté à 2s pour l'autosave
 | 
						|
 | 
						|
### `src/app/features/drawings/drawings-editor.component.html`
 | 
						|
- Remplacement du bouton "💾 Sauvegarder" par indicateur visuel
 | 
						|
- Icône SVG de disquette avec états de couleur
 | 
						|
- Suppression des indicateurs redondants ("Modifications non enregistrées")
 | 
						|
- Conservation uniquement des erreurs et conflits
 | 
						|
 | 
						|
## Comment Tester
 | 
						|
 | 
						|
### 1. Ouvrir un fichier
 | 
						|
```
 | 
						|
1. Ouvrir tests.excalidraw.md
 | 
						|
2. Vérifier dans la console : "🎨 Excalidraw Ready"
 | 
						|
3. Vérifier : "🔗 Binding Excalidraw host listeners"
 | 
						|
```
 | 
						|
 | 
						|
### 2. Test Sauvegarde Automatique
 | 
						|
```
 | 
						|
1. Ajouter un élément au dessin
 | 
						|
2. Vérifier console : "📝 Scene changed"
 | 
						|
3. Attendre 2 secondes
 | 
						|
4. Vérifier console : "💾 Autosaving..."
 | 
						|
5. Vérifier console : "✅ Autosave successful"
 | 
						|
6. Vérifier requête réseau : PUT /api/files?path=...
 | 
						|
7. Vérifier indicateur : 🔴 Rouge → ⚫ Gris
 | 
						|
```
 | 
						|
 | 
						|
### 3. Test Sauvegarde Manuelle
 | 
						|
```
 | 
						|
1. Ajouter un élément au dessin
 | 
						|
2. Cliquer sur l'indicateur (disquette rouge)
 | 
						|
3. Vérifier console : "💾 Manual save triggered"
 | 
						|
4. Vérifier console : "📤 Sending save request..."
 | 
						|
5. Vérifier console : "✅ Manual save successful"
 | 
						|
6. Vérifier toast : "Sauvegarde réussie"
 | 
						|
7. Vérifier requête réseau : PUT /api/files?path=...
 | 
						|
8. Vérifier indicateur : 🔴 → ⚫
 | 
						|
```
 | 
						|
 | 
						|
### 4. Test Export PNG/SVG
 | 
						|
```
 | 
						|
1. S'assurer que le fichier est chargé
 | 
						|
2. Vérifier que les boutons Export sont activés
 | 
						|
3. Cliquer "🖼️ Export PNG"
 | 
						|
4. Vérifier requête réseau : PUT /api/files/blob?path=...png
 | 
						|
5. Vérifier toast si erreur
 | 
						|
```
 | 
						|
 | 
						|
### 5. Test Ctrl+S
 | 
						|
```
 | 
						|
1. Modifier le dessin
 | 
						|
2. Appuyer Ctrl+S (ou Cmd+S sur Mac)
 | 
						|
3. Vérifier console : "💾 Manual save triggered"
 | 
						|
4. Vérifier toast : "Sauvegarde réussie"
 | 
						|
```
 | 
						|
 | 
						|
## Comportement Attendu
 | 
						|
 | 
						|
### Au Chargement
 | 
						|
1. Spinner de chargement
 | 
						|
2. GET `/api/files?path=tests.excalidraw.md`
 | 
						|
3. `🎨 Excalidraw Ready - Binding listeners`
 | 
						|
4. `🔗 Binding Excalidraw host listeners`
 | 
						|
5. Indicateur : ⚫ Gris "Sauvegardé"
 | 
						|
6. Exports : activés
 | 
						|
 | 
						|
### Pendant l'Édition
 | 
						|
1. Ajout d'un élément
 | 
						|
2. `📝 Scene changed`
 | 
						|
3. Indicateur : 🔴 Rouge "Non sauvegardé"
 | 
						|
4. Attente de 2 secondes
 | 
						|
5. `💾 Autosaving...`
 | 
						|
6. PUT `/api/files?path=...`
 | 
						|
7. `✅ Autosave successful`
 | 
						|
8. Indicateur : ⚫ Gris "Sauvegardé"
 | 
						|
 | 
						|
### Après Clic Sauvegarde
 | 
						|
1. `💾 Manual save triggered`
 | 
						|
2. `📤 Sending save request...`
 | 
						|
3. PUT `/api/files?path=...`
 | 
						|
4. `✅ Manual save successful`
 | 
						|
5. Toast : "Sauvegarde réussie"
 | 
						|
6. Indicateur : ⚫ Gris "Sauvegardé"
 | 
						|
 | 
						|
## Troubleshooting
 | 
						|
 | 
						|
### Pas de logs dans la console
 | 
						|
→ Le composant ne charge pas, vérifier `ngOnInit()`
 | 
						|
 | 
						|
### "⚠️ Cannot bind listeners - host element not found"
 | 
						|
→ L'élément web component n'est pas créé, vérifier le template `*ngIf`
 | 
						|
 | 
						|
### "❌ No host element" lors du clic Sauvegarde
 | 
						|
→ `@ViewChild` ne trouve pas l'élément, vérifier `#editorEl`
 | 
						|
 | 
						|
### "❌ No scene data"
 | 
						|
→ `getScene()` retourne null, vérifier que l'API Excalidraw est initialisée
 | 
						|
 | 
						|
### Pas de requête réseau
 | 
						|
→ Vérifier dans la console les logs "💾" et "📤"
 | 
						|
→ Si absents, le binding n'a pas eu lieu
 | 
						|
 | 
						|
### Export désactivés
 | 
						|
→ Vérifier `excalidrawReady` dans le composant
 | 
						|
→ Doit être `true` après `onExcalidrawReady()`
 | 
						|
 | 
						|
## Prochaines Étapes
 | 
						|
 | 
						|
Une fois le problème résolu (les logs apparaissent et les requêtes passent) :
 | 
						|
 | 
						|
1. **Retirer les logs de debug** dans `drawings-editor.component.ts`
 | 
						|
2. **Tester la sauvegarde intensive** (ajouter/supprimer rapidement des éléments)
 | 
						|
3. **Tester les conflits** (modifier le fichier externellement)
 | 
						|
4. **Vérifier la performance** (fichiers avec 100+ éléments)
 | 
						|
5. **Tester sur mobile** (responsive + touch)
 | 
						|
 | 
						|
## Résumé
 | 
						|
 | 
						|
✅ Binding des listeners au bon moment (après `ready`)  
 | 
						|
✅ Indicateur visuel clair (disquette colorée)  
 | 
						|
✅ Sauvegarde automatique (2s debounce)  
 | 
						|
✅ Sauvegarde manuelle (clic ou Ctrl+S)  
 | 
						|
✅ Toast notifications  
 | 
						|
✅ Logs de diagnostic  
 | 
						|
✅ Export PNG/SVG fonctionnels  
 |