Historique des versions : snapshots horodatés, différences, restauration
- Avant d'écraser un schéma, le contenu précédent est copié dans DATA_DIR/.history/<chemin>/<date>.excalidraw, au plus une version par HISTORY_INTERVAL (10 min) ; rétention HISTORY_KEEP (50) et HISTORY_MAX_AGE. Pas de git : l'image reste distroless. - API : GET /api/history, GET /api/history/version, POST /api/history/snapshot, POST /api/history/restore (le contenu remplacé devient une version). - L'historique suit renommages et déplacements, part à la corbeille avec le schéma supprimé. - Dialogue Historique (barre du haut, menu de l'explorateur) : aperçu, différences colorées avec l'état actuel, restaurer, restaurer en copie, créer une version. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H6J7vKwXx7uopxKhWfFJpm
This commit is contained in:
1 parent
88f7750577
commit
9f9ec3b3a4
14 files changed
+1005
-7
No files matched your search
@@ -1,6 +1,6 @@
|
||||
# excalidraw-go
|
||||
|
||||
Excalidraw auto-hébergé avec un **gestionnaire de fichiers intégré** : arborescence de dossiers, **vignettes des schémas**, création, renommage, **sélection et déplacement multiples** (glisser-déposer ou dialogue « Déplacer vers… »), duplication, suppression (corbeille), recherche, import/export de fichiers `.excalidraw`, sauvegarde automatique côté serveur. Interface web unique, responsive (l'explorateur devient un tiroir sur mobile).
|
||||
Excalidraw auto-hébergé avec un **gestionnaire de fichiers intégré** : arborescence de dossiers, **vignettes des schémas**, création, renommage, **sélection et déplacement multiples** (glisser-déposer ou dialogue « Déplacer vers… »), duplication, suppression (corbeille), recherche, import/export de fichiers `.excalidraw`, sauvegarde automatique côté serveur, **historique des versions** avec comparaison visuelle et restauration. Interface web unique, responsive (l'explorateur devient un tiroir sur mobile).
|
||||
|
||||
- **Backend** : Go 1.24, bibliothèque standard uniquement (aucune dépendance externe), API REST/JSON, stockage en fichiers `.excalidraw` sur un volume.
|
||||
- **Frontend** : React 19 + composant officiel [`@excalidraw/excalidraw`](https://www.npmjs.com/package/@excalidraw/excalidraw) 0.18.1 (licence MIT), build Vite **embarqué dans le binaire Go** (`embed`).
|
||||
@@ -20,6 +20,7 @@ Navigateur ──HTTP──▶ conteneur excalidraw-go (:8080, uid 65532, rootfs
|
||||
├─ .library.excalidrawlib ← bibliothèque partagée
|
||||
├─ .settings.json, .logo.png ← titre et logo de la barre
|
||||
├─ .thumbs/projets/réseau/sdn.excalidraw.png ← miniatures (régénérables)
|
||||
├─ .history/projets/réseau/sdn.excalidraw/<date>.excalidraw ← versions
|
||||
└─ .trash/<horodatage>/... ← éléments supprimés
|
||||
```
|
||||
|
||||
@@ -42,6 +43,9 @@ docker compose up -d --build
|
||||
| `UPDATE_CHECK` | `true` | Interroge `registry.npmjs.org` pour signaler une nouvelle version d'Excalidraw (`false` : désactivé) |
|
||||
| `UPDATE_CHECK_INTERVAL` | `12h` | Intervalle entre deux vérifications (durée Go, minimum `1m`) |
|
||||
| `NPM_REGISTRY` | `https://registry.npmjs.org` | Registre interrogé (miroir interne possible) |
|
||||
| `HISTORY_KEEP` | `50` | Versions conservées par schéma (`0` : historique désactivé) |
|
||||
| `HISTORY_INTERVAL` | `10m` | Écart minimal entre deux versions automatiques (`0` : une version à chaque enregistrement) |
|
||||
| `HISTORY_MAX_AGE` | `0` | Âge au-delà duquel une version est purgée (ex. `2160h` = 90 jours ; `0` : jamais) |
|
||||
| `EXCALIDRAW_VERSION` (build) | vide | Version d'Excalidraw imposée à la construction de l'image ; vide = celle de `package-lock.json` |
|
||||
|
||||
Bind mount au lieu du volume nommé : `- ./data:/data` puis `chown -R 65532:65532 ./data`.
|
||||
@@ -89,6 +93,20 @@ Rendues par le navigateur avec `exportToBlob` d'Excalidraw (PNG 320 px), puis st
|
||||
|
||||
Une miniature plus ancienne que son schéma est ignorée (`404`) puis régénérée. Elles suivent les renommages, déplacements, copies et suppressions ; `.thumbs/` peut être supprimé sans risque. En thème sombre, elles sont inversées en CSS comme le canevas Excalidraw.
|
||||
|
||||
### Historique des versions
|
||||
|
||||
Avant qu'un schéma soit écrasé, son contenu précédent est copié dans `DATA_DIR/.history/<chemin du schéma>/<date>.excalidraw` (fichier Excalidraw complet, ouvrable tel quel). L'enregistrement automatique écrit toutes les 1,5 s pendant l'édition : une version n'est donc conservée que si la précédente date d'au moins `HISTORY_INTERVAL` (10 min par défaut), ce qui donne une version par séance de travail ou par tranche de 10 minutes. Les `HISTORY_KEEP` plus récentes sont gardées, et `HISTORY_MAX_AGE` purge les plus anciennes.
|
||||
|
||||
Le dialogue *Historique* (icône horloge de la barre du haut, ou menu « … » d'un schéma dans l'explorateur) :
|
||||
|
||||
- liste les versions et affiche un aperçu de chacune ;
|
||||
- **Différences** : l'état actuel superposé à la version choisie, éléments ajoutés depuis en vert, supprimés depuis en rouge pointillé, modifiés en orange, le reste estompé (comparaison par identifiant d'élément Excalidraw) ;
|
||||
- **Restaurer** remplace le schéma par la version ; l'état remplacé devient lui-même une version, la restauration s'annule donc ;
|
||||
- **Restaurer en copie** crée un nouveau schéma « nom (version du …) » à côté de l'original ;
|
||||
- **Créer une version** fixe immédiatement l'état actuel (jalon avant une modification importante).
|
||||
|
||||
L'historique suit les renommages et déplacements ; à la suppression d'un schéma, il part avec lui dans la corbeille (`.trash/<horodatage>/.history/`). Pas de binaire `git` requis : l'image reste distroless.
|
||||
|
||||
### Concurrence
|
||||
|
||||
Chaque lecture renvoie un `ETag` (SHA-256 tronqué du contenu) ; chaque sauvegarde l'envoie en `If-Match`. Si le fichier a été modifié ailleurs (autre onglet, autre poste), le serveur répond `412` et l'interface propose d'écraser ou de recharger. Il n'y a pas d'édition collaborative temps réel (voir *Évolutions*).
|
||||
@@ -110,6 +128,10 @@ Tous les chemins sont relatifs à `DATA_DIR`, en notation `/`. Les composants co
|
||||
| PUT | `/api/thumb?path=x.excalidraw` | PNG (1 Mo max) | `204` |
|
||||
| POST | `/api/copy` | `{"from":"…","to":"…"}` | `Entry` |
|
||||
| DELETE | `/api/entry?path=x[&recursive=true]` | | `204` (déplacé dans `.trash/`) |
|
||||
| GET | `/api/history?path=x.excalidraw` | | `[{"id","time","size"}]`, la plus récente en premier |
|
||||
| GET | `/api/history/version?path=x.excalidraw&id=<id>` | | JSON de la version |
|
||||
| POST | `/api/history/snapshot` | `{"path":"x.excalidraw"}` | `{"id","time","size"}` (version du contenu courant) |
|
||||
| POST | `/api/history/restore` | `{"path":"x.excalidraw","id":"<id>"}` | `Entry` + `ETag` |
|
||||
| GET/PUT | `/api/library` | bibliothèque `excalidrawlib` | |
|
||||
| GET | `/api/settings` | | `{"title":"...","logo":"<version>","channel":"latest"}` (`logo` vide sans logo) |
|
||||
| PUT | `/api/settings` | `{"title":"..."}` (80 caractères max, vide = titre par défaut) et/ou `{"channel":"latest"\|"next"}` | réglages |
|
||||
@@ -145,7 +167,7 @@ Arborescence :
|
||||
|
||||
```
|
||||
cmd/server/main.go serveur HTTP, SPA embarquée, auth Basic, healthcheck
|
||||
internal/storage/ accès disque : sécurité des chemins, écriture atomique, ETag, corbeille
|
||||
internal/storage/ accès disque : sécurité des chemins, écriture atomique, ETag, corbeille, historique
|
||||
internal/api/ routes REST
|
||||
web/embed.go embarque web/dist (produit par le build Vite)
|
||||
frontend/src/App.tsx éditeur Excalidraw, sauvegarde auto, conflits, bibliothèque
|
||||
@@ -153,6 +175,7 @@ frontend/src/Explorer.tsx gestionnaire de fichiers (vignettes/liste, sélectio
|
||||
frontend/src/MoveDialog.tsx sélecteur de dossier « Déplacer vers… »
|
||||
frontend/src/Thumb.tsx vignette chargée à l'affichage, générée si absente
|
||||
frontend/src/thumbs.ts rendu PNG des miniatures et file de génération
|
||||
frontend/src/HistoryDialog.tsx historique : aperçu, différences, restauration
|
||||
```
|
||||
|
||||
## Sécurité
|
||||
@@ -165,6 +188,5 @@ frontend/src/thumbs.ts rendu PNG des miniatures et file de génération
|
||||
## Limites et évolutions possibles
|
||||
|
||||
- **Collaboration temps réel** : nécessiterait le serveur [excalidraw-room](https://github.com/excalidraw/excalidraw-room) (WebSocket) et la logique de réconciliation (`reconcileElements`) côté client.
|
||||
- **Historique de versions** : commit git automatique dans `DATA_DIR` à chaque sauvegarde, ou snapshots du volume (ZFS/Btrfs).
|
||||
- **Multi-utilisateurs avec espaces privés** : identité transmise par le reverse proxy (`X-Forwarded-User`) et racine par utilisateur.
|
||||
- Les schémas avec beaucoup d'images embarquées sont volumineux (base64 dans le JSON) ; ajuster `MAX_BODY_MB`.
|
||||
Reference in new issue
Block a user