Add comprehensive documentation and analysis files
Add extensive project documentation including analysis review, image rendering changelog and guide, contributing guidelines, hidden files configuration guide, PWA documentation suite, roadmap, and dashboard specification.
This commit is contained in:
parent
456b308af6
commit
5280dc7a50
384
docs/ANALYSE_REVIEW.md
Normal file
384
docs/ANALYSE_REVIEW.md
Normal file
@ -0,0 +1,384 @@
|
|||||||
|
# ObsiGate — Analyse complète & Recommandations V1.1
|
||||||
|
|
||||||
|
> **Date :** 2026-05-25 | **Analyste :** Hermes-Claw + Audit Code Source | **Version testée :** 1.4.0 (backend) / 1.5.0 (frontend) — http://openclaw1.dev.home:2020
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 Table des matières
|
||||||
|
|
||||||
|
1. [Résumé exécutif](#1-résumé-exécutif)
|
||||||
|
2. [Fonctionnalités actuelles](#2-fonctionnalités-actuelles)
|
||||||
|
3. [Forces](#3-forces)
|
||||||
|
4. [Points d'amélioration](#4-points-damélioration)
|
||||||
|
5. [Roadmap suggérée](#5-roadmap-suggérée)
|
||||||
|
6. [Checklist de professionnalisation](#6-checklist-de-professionnalisation)
|
||||||
|
7. [Notes de révision V1.1](#7-notes-de-révision-v11)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Résumé exécutif
|
||||||
|
|
||||||
|
**ObsiGate** est un gestionnaire web de vaults Obsidian Markdown auto-hébergé.
|
||||||
|
La version actuelle (1.4.0/1.5.0) est un produit **riche et mature**, bien au-delà d'une simple V1.
|
||||||
|
Il dispose d'un moteur de recherche TF-IDF avancé, un éditeur CodeMirror 6 intégré, une vue graphique,
|
||||||
|
un support PWA complet, des opérations CRUD sur fichiers/dossiers, et une synchronisation temps réel via SSE + watchdog.
|
||||||
|
|
||||||
|
**Note globale : 8.5/10** — Produit fonctionnel, performant et professionnel.
|
||||||
|
Les améliorations restantes sont principalement d'ordre sécuritaire
|
||||||
|
(masquage des secrets, rate limiting) et de polish (documentation API, backlinks, tests automatisés).
|
||||||
|
|
||||||
|
**Recommandation prioritaire :** Traiter les 2 points de sécurité
|
||||||
|
(masquage secrets + rate limiting), puis les enrichissements UX
|
||||||
|
(backlinks, conflits Syncthing).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Fonctionnalités actuelles
|
||||||
|
|
||||||
|
| # | Fonctionnalité | Statut | Détail |
|
||||||
|
|---|---------------|:------:|--------|
|
||||||
|
| 1 | Authentification | ✅ | JWT HS256 + Argon2id, sessions persistantes, "Se souvenir de moi", contrôle d'accès par vault |
|
||||||
|
| 2 | Multi-vaults | ✅ | Configurables via env vars ou API dynamique, support VAULT et DIR |
|
||||||
|
| 3 | Arborescence de fichiers | ✅ | Navigation hiérarchique avec lazy-loading, compteur d'éléments par dossier, icônes par type |
|
||||||
|
| 4 | Rendu Markdown | ✅ | Conversion HTML via mistune, tables, task lists, footnotes, strikethrough |
|
||||||
|
| 5 | Extraction YAML frontmatter | ✅ | Tous les champs parsés, carte frontmatter pliable avec badges, dates formatées, tags |
|
||||||
|
| 6 | Vue Source (raw) | ✅ | Toggle markdown brut + frontmatter |
|
||||||
|
| 7 | Bouton Copier | ✅ | Copie du contenu source |
|
||||||
|
| 8 | Bouton Télécharger | ✅ | Téléchargement du fichier |
|
||||||
|
| 9 | Onglet RÉCENT | ✅ | Onglet sidebar dédié + dashboard avec timestamps relatifs, previews, tags, bookmarks |
|
||||||
|
| 10 | Onglet TAGS | ✅ | Nuage de tags cliquable, compteurs, filtrage des tags template configurables |
|
||||||
|
| 11 | Recherche avancée | ✅ | Moteur TF-IDF, opérateurs (`tag:`, `vault:`, `title:`, `path:`, `ext:`), snippets `<mark>`, facettes, pagination, tri |
|
||||||
|
| 12 | Autocomplétion de recherche | ✅ | Dropdown avec historique (localStorage), suggestions fichiers + tags, navigation clavier |
|
||||||
|
| 13 | Filtre fichiers sidebar | ✅ | Filtre par nom, option case-sensitive, recherche sur l'index des chemins |
|
||||||
|
| 14 | Thème Sombre | ✅ | Toggle clair/sombre, persisté localStorage, highlight.js adaptatif |
|
||||||
|
| 15 | Administration utilisateurs | ✅ | Interface CRUD complète (admin uniquement) |
|
||||||
|
| 16 | Configurations | ✅ | Paramètres recherche, backend, watcher, tags, fichiers cachés, diagnostics, à propos |
|
||||||
|
| 17 | Table des matières | ✅ | Panneau droit avec scroll-spy, IntersectionObserver, barre de progression de lecture |
|
||||||
|
| 18 | Bookmarks | ✅ | Dashboard avec favoris, toggle depuis les cartes de fichiers |
|
||||||
|
| 19 | Historique d'ouverture | ✅ | Fichiers récemment ouverts par utilisateur, persisté sur disque |
|
||||||
|
| 20 | Éditeur CodeMirror 6 | ✅ | Coloration syntaxique multi-langages, autocomplétion, Ctrl+F, Ctrl+S |
|
||||||
|
| 21 | Création fichiers/dossiers | ✅ | Via menu contextuel (clic droit) et modals dédiées |
|
||||||
|
| 22 | Renommage fichiers/dossiers | ✅ | Renommage inline via menu contextuel |
|
||||||
|
| 23 | Suppression fichiers/dossiers | ✅ | Avec confirmation, suppression récursive pour les dossiers |
|
||||||
|
| 24 | Menu contextuel | ✅ | Clic droit : copier chemin, vue graphique, créer, renommer, supprimer |
|
||||||
|
| 25 | Wikilinks cliquables | ✅ | `[[lien]]` et `[[lien|alias]]` convertis en liens navigables, liens brisés en rouge |
|
||||||
|
| 26 | Images Obsidian | ✅ | Résolution intelligente (7 stratégies), support `![[image]]`, ``, `<img>` dans liens |
|
||||||
|
| 27 | Vue Graphique | ✅ | Canvas force-directed, nœuds fichiers/dossiers, arêtes parent + wikilinks, zoom/pan |
|
||||||
|
| 28 | Onglets de contenu | ✅ | Barre d'onglets multi-fichiers |
|
||||||
|
| 29 | Fenêtres popout | ✅ | Vue standalone avec éditeur, TOC, thème sombre, login intégré |
|
||||||
|
| 30 | Find in Page | ✅ | Barre Ctrl+F avec case-sensitive, mot entier, regex |
|
||||||
|
| 31 | PWA | ✅ | Service worker, manifest.json, icônes, notification de mise à jour |
|
||||||
|
| 32 | SSE — Synchronisation temps réel | ✅ | Reconnexion automatique, panneau d'état, événements index/vault |
|
||||||
|
| 33 | Watchdog — Surveillance fichiers | ✅ | inotify natif + fallback polling, debounce configurable, mise à jour incrémentale |
|
||||||
|
| 34 | Filtrage dossiers/fichiers cachés | ✅ | Par vault (`hideHiddenFiles`), paramétrable dans Configurations |
|
||||||
|
| 35 | Gestion dynamique des vaults | ✅ | Ajout/suppression via API sans redémarrage |
|
||||||
|
| 36 | API REST | ✅ | 20+ endpoints (CRUD fichiers, recherche, tags, graph, bookmarks, config, diagnostics...) |
|
||||||
|
| 37 | Sécurité | ✅ | Headers CSP/X-Frame/XSS, protection path traversal, non-root, permissions vault |
|
||||||
|
| 38 | Toast notifications | ✅ | Feedback utilisateur (succès, erreur) |
|
||||||
|
| 39 | Barre de progression d'indexation | ✅ | Affichée dans le header pendant l'indexation initiale |
|
||||||
|
| 40 | Breadcrumb navigable | ✅ | Cliquable, repositionne automatiquement la sidebar |
|
||||||
|
| 41 | Redimensionnement sidebar | ✅ | Drag handle, persisté localStorage, limites min/max |
|
||||||
|
| 42 | Docker multi-plateforme | ✅ | linux/amd64, arm64, arm/v7, i386 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Forces
|
||||||
|
|
||||||
|
### 🎨 Design & UX
|
||||||
|
- **Interface épurée** — layout 3 colonnes (sidebar | contenu | TOC) avec onglets sidebar
|
||||||
|
- **Français natif** — rare et appréciable pour un outil de cette catégorie
|
||||||
|
- **Responsive** — s'adapte aux différentes tailles d'écran, menu hamburger mobile
|
||||||
|
- **Feedback visuel** — timestamps relatifs ("il y a 5 min", "il y a 3 h"), toasts, barres de progression
|
||||||
|
- **PWA** — installation sur l'écran d'accueil, service worker, notifications de mise à jour
|
||||||
|
|
||||||
|
### 🧠 Métadonnées
|
||||||
|
- **Extraction YAML complète** — tous les champs du frontmatter parsés et affichés dans une carte pliable stylisée
|
||||||
|
- **Tags cliquables** — dans la vue fichier, l'onglet RÉCENT, et le nuage de tags
|
||||||
|
- **Résolution wikilinks** — O(1) via table de lookup, support multi-vaults
|
||||||
|
- **Images** — résolution multi-stratégies (7 stratégies) des syntaxes Obsidian
|
||||||
|
|
||||||
|
### 🏗️ Architecture
|
||||||
|
- **Multi-vaults** — supporte plusieurs vaults simultanément avec contrôle d'accès par utilisateur
|
||||||
|
- **Auto-détection** — découverte automatique des vaults via variables d'environnement
|
||||||
|
- **API dynamique** — ajout/suppression de vaults sans redémarrage
|
||||||
|
- **Performance** — TF-IDF avec ThreadPoolExecutor, index mémoire, lookup O(1), SSE temps réel
|
||||||
|
- **Stack moderne** — FastAPI + mistune + watchdog (backend), Vanilla JS SPA + CodeMirror 6 + highlight.js (frontend)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Points d'amélioration
|
||||||
|
|
||||||
|
### 4.1 🔴 Critique — Sécurité
|
||||||
|
|
||||||
|
#### 4.1.1 Masquage automatique des secrets
|
||||||
|
|
||||||
|
**Problème :** Les clés API, tokens et secrets sont visibles en clair dans les aperçus de contenu et la vue RÉCENT.
|
||||||
|
|
||||||
|
**Exemple concret observé :** Fichier "AI API" → preview contient des clés OpenAI en clair.
|
||||||
|
|
||||||
|
**Solution :** Implémenter un `SecretRedactor` (backend) qui scanne le contenu avant affichage :
|
||||||
|
- Patterns : OpenAI/Claude keys, JWT tokens, GitHub tokens, clés hex/base64 > 40 chars
|
||||||
|
- Preview RÉCENT/Dashboard : Masquer toutes les clés
|
||||||
|
- Vue Source : Warning "Ce fichier contient N secrets potentiels. [Afficher]"
|
||||||
|
- Vue Rendu : Masquer avec placeholder visuel
|
||||||
|
- Export/Téléchargement : Conserver le contenu original
|
||||||
|
|
||||||
|
**Priorité :** 🔴 P0 — Corriger avant toute exposition publique
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 4.1.2 Rate limiting & protection brute-force
|
||||||
|
|
||||||
|
**Problème :** Absence de rate limiting sur le login.
|
||||||
|
|
||||||
|
**Solution :** Middleware rate-limit — 5 tentatives max par IP sur 15 minutes, blocage après 10 échecs.
|
||||||
|
|
||||||
|
**Priorité :** 🔴 P0
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 4.1.3 Filtrage des dossiers sensibles — Amélioration
|
||||||
|
|
||||||
|
**État actuel :** VaultWatcher ignore déjà `.obsidian`, `.trash`, `.git`, `__pycache__`, `node_modules`.
|
||||||
|
Le paramètre `hideHiddenFiles` par vault masque les fichiers/dossiers commençant par `.`.
|
||||||
|
|
||||||
|
**Amélioration :** Rendre la liste `IGNORED_DIRS` configurable.
|
||||||
|
|
||||||
|
**Priorité :** 🟡 P2 — Déjà partiellement résolu
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4.2 🟠 Important — Performance & Robustesse
|
||||||
|
|
||||||
|
#### 4.2.1 Log d'audit
|
||||||
|
|
||||||
|
Pas de traçabilité des actions critiques (écritures, suppressions, changements de config).
|
||||||
|
Logger les actions avec utilisateur, timestamp, vault, chemin dans `data/audit.log`.
|
||||||
|
|
||||||
|
**Priorité :** 🟠 P1
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 4.2.2 Backup automatique avant écriture
|
||||||
|
|
||||||
|
Pas de filet de sécurité avant modification/suppression.
|
||||||
|
Sauvegarder le contenu original dans `.obsigate-backup/` horodaté.
|
||||||
|
|
||||||
|
**Priorité :** 🟠 P1
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 4.2.3 Timeout de session configurable
|
||||||
|
|
||||||
|
TTL JWT codé en dur. Rendre configurable.
|
||||||
|
|
||||||
|
**Priorité :** 🟡 P2
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4.3 🟡 UX & Navigation
|
||||||
|
|
||||||
|
#### 4.3.1 Backlinks panel
|
||||||
|
|
||||||
|
Afficher les fichiers contenant des wikilinks pointant vers le fichier courant.
|
||||||
|
Construire un index inversé des wikilinks au scan initial.
|
||||||
|
|
||||||
|
**Priorité :** 🟡 P2
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 4.3.2 Correction TOC — scroll avec caractères accentués
|
||||||
|
|
||||||
|
Le clic sur un titre dans la TOC ne fonctionne pas pour certains titres accentués.
|
||||||
|
Les fonctions slugify backend/frontend utilisent des normalisations Unicode qui divergent.
|
||||||
|
|
||||||
|
**Solution :** Unifier l'algorithme + fallback `scrollIntoView`.
|
||||||
|
|
||||||
|
**Priorité :** 🟡 P2
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 4.3.3 Gestion fichiers non-supportés
|
||||||
|
|
||||||
|
Les fichiers binaires non supportés déclenchent une erreur 500.
|
||||||
|
Ajouter un message explicite avec bouton de téléchargement.
|
||||||
|
|
||||||
|
**Priorité :** 🟢 P3
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4.4 🟢 Fonctionnel — Feature Gaps
|
||||||
|
|
||||||
|
#### 4.4.1 Gestion des conflits Syncthing
|
||||||
|
|
||||||
|
Les fichiers `.sync-conflict-*` sont indexables mais pas d'outil de résolution.
|
||||||
|
Ajouter section « Conflits » avec diff et choix (garder local/conflit).
|
||||||
|
|
||||||
|
**Priorité :** 🟢 P3
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 4.4.2 Dashboard statistiques
|
||||||
|
|
||||||
|
Dashboard avec métriques par vault : fichiers totaux, taille, top tags, orphelins.
|
||||||
|
|
||||||
|
**Priorité :** 🟢 P4
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4.5 🔵 Architecture & Code
|
||||||
|
|
||||||
|
#### 4.5.1 Documentation OpenAPI/Swagger enrichie
|
||||||
|
|
||||||
|
L'API REST (20+ endpoints) est documentée via docstrings Python.
|
||||||
|
FastAPI génère automatiquement /docs et /redoc. Enrichir les modèles Pydantic.
|
||||||
|
|
||||||
|
**Priorité :** 🟡 P2
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 4.5.2 Webhook / Event system
|
||||||
|
|
||||||
|
Notifier des systèmes externes lors de changements (création, modification, suppression).
|
||||||
|
|
||||||
|
**Priorité :** 🟢 P3
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 4.5.3 Authentification multi-facteurs
|
||||||
|
|
||||||
|
TOTP ou WebAuthn pour l'accès admin.
|
||||||
|
|
||||||
|
**Priorité :** 🔵 P5
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Roadmap suggérée
|
||||||
|
|
||||||
|
### Phase 1 — Correctifs urgents (1-2 semaines)
|
||||||
|
|
||||||
|
| # | Tâche | Effort |
|
||||||
|
|---|-------|:------:|
|
||||||
|
| 1 | Redacteur de secrets dans les aperçus | 2h |
|
||||||
|
| 2 | Rate limiting sur le login | 2h |
|
||||||
|
| 3 | Log d'audit (écritures, suppressions) | 3h |
|
||||||
|
| 4 | Backup automatique avant écriture | 3h |
|
||||||
|
|
||||||
|
### Phase 2 — UX (2-4 semaines)
|
||||||
|
|
||||||
|
| # | Tâche | Effort |
|
||||||
|
|---|-------|:------:|
|
||||||
|
| 5 | Backlinks panel | 6h |
|
||||||
|
| 6 | Correction TOC scroll avec accents | 3h |
|
||||||
|
| 7 | Gestion des conflits Syncthing (diff + résolution) | 8h |
|
||||||
|
| 8 | Liste IGNORED_DIRS configurable | 2h |
|
||||||
|
| 9 | Gestion élégante des fichiers non supportés | 2h |
|
||||||
|
|
||||||
|
### Phase 3 — Avancé (4-8 semaines)
|
||||||
|
|
||||||
|
| # | Tâche | Effort |
|
||||||
|
|---|-------|:------:|
|
||||||
|
| 10 | Dashboard statistiques | 6h |
|
||||||
|
| 11 | Webhooks | 5h |
|
||||||
|
| 12 | Enrichissement doc OpenAPI/Swagger | 3h |
|
||||||
|
| 13 | Timeout de session configurable | 2h |
|
||||||
|
|
||||||
|
### Phase 4 — Polish (continu)
|
||||||
|
|
||||||
|
| # | Tâche | Effort |
|
||||||
|
|---|-------|:------:|
|
||||||
|
| 14 | Tests automatisés (pytest + Playwright) | 16h |
|
||||||
|
| 15 | CI/CD pipeline | 4h |
|
||||||
|
| 16 | Docker image officielle (registry) | 3h |
|
||||||
|
| 17 | i18n (anglais + français) | 8h |
|
||||||
|
| 18 | Documentation utilisateur enrichie | 8h |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Checklist de professionnalisation
|
||||||
|
|
||||||
|
### 🔒 Sécurité
|
||||||
|
- [ ] Redacteur de secrets (API keys, tokens, passwords)
|
||||||
|
- [x] Exclusion dossiers .obsidian/, .trash/, .git/ (watcher + hideHiddenFiles)
|
||||||
|
- [ ] Rate limiting sur le login
|
||||||
|
- [x] CSP headers (Content-Security-Policy)
|
||||||
|
- [ ] HTTPS obligatoire en production (reverse proxy recommandé)
|
||||||
|
- [ ] Session timeout configurable
|
||||||
|
- [ ] Log d'audit (qui a fait quoi quand)
|
||||||
|
- [ ] Backup automatique avant écriture
|
||||||
|
|
||||||
|
### 🚀 Performance
|
||||||
|
- [x] Moteur TF-IDF avec normalisation d'accents
|
||||||
|
- [x] Lazy-loading de l'arborescence
|
||||||
|
- [x] Pagination des résultats de recherche
|
||||||
|
- [x] Table de lookup O(1) pour wikilinks
|
||||||
|
|
||||||
|
### 🎨 UX
|
||||||
|
- [x] Wikilinks cliquables
|
||||||
|
- [x] Tags cliquables
|
||||||
|
- [x] Breadcrumb navigable
|
||||||
|
- [x] Mode sombre persistant (localStorage)
|
||||||
|
- [x] Raccourcis clavier (Ctrl+K, Ctrl+T)
|
||||||
|
- [ ] Drag & drop pour upload d'images
|
||||||
|
- [x] Notifications toast
|
||||||
|
- [ ] Page 404 personnalisée
|
||||||
|
- [x] États vides stylisés
|
||||||
|
|
||||||
|
### 🛠️ Fonctionnel
|
||||||
|
- [x] Éditeur CodeMirror 6
|
||||||
|
- [x] Création fichiers/dossiers (menu contextuel)
|
||||||
|
- [x] Renommage fichiers/dossiers (menu contextuel)
|
||||||
|
- [x] Suppression fichiers/dossiers (menu contextuel)
|
||||||
|
- [x] API REST complète (20+ endpoints)
|
||||||
|
- [ ] Documentation OpenAPI enrichie
|
||||||
|
- [ ] CLI companion (obsigate-cli)
|
||||||
|
- [ ] Gestion conflits Syncthing (diff + résolution)
|
||||||
|
- [ ] Export multi-formats (PDF, HTML standalone)
|
||||||
|
|
||||||
|
### 🧪 Qualité
|
||||||
|
- [ ] Tests unitaires (pytest)
|
||||||
|
- [ ] Tests E2E (Playwright)
|
||||||
|
- [ ] CI/CD (GitHub Actions)
|
||||||
|
- [x] Image Docker (Dockerfile)
|
||||||
|
- [ ] Documentation utilisateur
|
||||||
|
- [ ] CHANGELOG.md
|
||||||
|
- [ ] Semantic versioning
|
||||||
|
|
||||||
|
### 🌍 Communauté
|
||||||
|
- [x] Page Git avec README
|
||||||
|
- [ ] Capture d'écran animée (GIF/WebM)
|
||||||
|
- [x] Badges (version, license)
|
||||||
|
- [x] Guide de contribution (CONTRIBUTING.md)
|
||||||
|
- [ ] Template d'issue (bug / feature request)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Notes de révision V1.1
|
||||||
|
|
||||||
|
**Corrections majeures par rapport à l'analyse V1 (qui sous-estimait largement le projet) :**
|
||||||
|
|
||||||
|
| Analyse V1 | Réalité V1.1 |
|
||||||
|
|---|---|
|
||||||
|
| "Feature Gap — Éditeur Markdown (CodeMirror) Phase 3" | ✅ Déjà implémenté avec 15+ langages, autocomplétion, Ctrl+F, Ctrl+S |
|
||||||
|
| "Feature Gap — Création fichiers/dossiers Phase 3" | ✅ Déjà fonctionnel via menu contextuel + modals |
|
||||||
|
| "Feature Gap — Wikilinks cliquables Phase 2" | ✅ Déjà fonctionnels avec résolution multi-vaults et liens brisés |
|
||||||
|
| "Feature Gap — Tags cliquables Phase 3" | ✅ Déjà fonctionnels |
|
||||||
|
| "Feature Gap — Breadcrumb navigable Phase 2" | ✅ Déjà implémenté |
|
||||||
|
| Recherche notée "performances à améliorer" | ✅ Moteur TF-IDF complet avec opérateurs avancés, facettes, autocomplétion |
|
||||||
|
| "Filtrage dossiers sensibles non implémenté" | ✅ Déjà présent (watcher + hideHiddenFiles par vault) |
|
||||||
|
| Non mentionné : PWA | ✅ Service worker, manifest, icônes, notif de mise à jour |
|
||||||
|
| Non mentionné : Vue Graphique | ✅ Canvas force-directed avec wikilinks |
|
||||||
|
| Non mentionné : Find in Page | ✅ Ctrl+F avec case-sensitive, mot entier, regex |
|
||||||
|
| Non mentionné : Onglets de contenu | ✅ Barre d'onglets multi-fichiers |
|
||||||
|
| Non mentionné : Fenêtres Popout | ✅ Standalone avec éditeur, TOC, login |
|
||||||
|
| Non mentionné : Menu contextuel | ✅ Clic droit avec CRUD complet |
|
||||||
|
| Non mentionné : Bookmarks | ✅ Toggle + dashboard |
|
||||||
|
| Non mentionné : Toast notifications | ✅ Feedback succès/erreur |
|
||||||
|
| Non mentionné : Résolution images | ✅ 7 stratégies pour syntaxes Obsidian |
|
||||||
|
|
||||||
|
**Note globale révisée :** 7/10 → **8.5/10**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Analyse réalisée le 2026-05-25 — Révisée V1.1 après audit complet du code source*
|
||||||
|
*Document : ANALYSE_REVIEW.md*
|
||||||
197
docs/CHANGELOG_IMAGE_RENDERING.md
Normal file
197
docs/CHANGELOG_IMAGE_RENDERING.md
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
# Changelog - Obsidian Image Rendering Feature
|
||||||
|
|
||||||
|
## Version 1.2.0 - Image Rendering Support
|
||||||
|
|
||||||
|
### 🖼️ New Features
|
||||||
|
|
||||||
|
#### Comprehensive Image Syntax Support
|
||||||
|
- **Standard Markdown with HTML attributes**: `[<img width="180" height="60" src="path"/>](url)`
|
||||||
|
- **Obsidian wiki-link embeds (full path)**: `![[folder/subfolder/image.svg]]`
|
||||||
|
- **Obsidian wiki-link embeds (filename only)**: `![[image.png]]`
|
||||||
|
- **Standard Markdown images**: ``
|
||||||
|
|
||||||
|
#### Intelligent Multi-Strategy Path Resolution
|
||||||
|
Implements 7-tier resolution system with priority order:
|
||||||
|
1. Absolute path detection
|
||||||
|
2. Configured attachments folder lookup
|
||||||
|
3. Startup index unique match
|
||||||
|
4. Same directory as markdown file
|
||||||
|
5. Vault root relative resolution
|
||||||
|
6. Startup index closest path match
|
||||||
|
7. Styled placeholder fallback
|
||||||
|
|
||||||
|
#### Attachment Indexing System
|
||||||
|
- Asynchronous vault scanning at startup
|
||||||
|
- Supports: `.png`, `.jpg`, `.jpeg`, `.gif`, `.svg`, `.webp`, `.bmp`, `.ico`
|
||||||
|
- Per-vault index with filename → absolute path mapping
|
||||||
|
- Resolution cache for performance optimization
|
||||||
|
- Detailed logging of indexed attachments
|
||||||
|
|
||||||
|
#### Vault Configuration Extensions
|
||||||
|
New optional environment variables:
|
||||||
|
- `VAULT_N_ATTACHMENTS_PATH`: Relative path to primary attachments folder
|
||||||
|
- `VAULT_N_SCAN_ATTACHMENTS`: Enable/disable attachment scanning (default: true)
|
||||||
|
|
||||||
|
#### API Endpoints
|
||||||
|
- `GET /api/image/{vault}?path=...`: Serve images with proper MIME types
|
||||||
|
- `POST /api/attachments/rescan/{vault}`: Manual vault attachment rescan
|
||||||
|
- `GET /api/attachments/stats?vault=...`: Attachment statistics per vault
|
||||||
|
|
||||||
|
#### Frontend Enhancements
|
||||||
|
- Responsive image rendering with max-width constraints
|
||||||
|
- Styled placeholders for missing images with tooltips
|
||||||
|
- Hover effects on linked images
|
||||||
|
- Rounded corners and subtle shadows
|
||||||
|
|
||||||
|
### 📁 New Files
|
||||||
|
|
||||||
|
- `backend/attachment_indexer.py`: Image scanning, indexing, and resolution
|
||||||
|
- `backend/image_processor.py`: Markdown preprocessing for all image syntaxes
|
||||||
|
- `IMAGE_RENDERING_GUIDE.md`: Comprehensive implementation and testing guide
|
||||||
|
- `CHANGELOG_IMAGE_RENDERING.md`: This file
|
||||||
|
|
||||||
|
### 🔧 Modified Files
|
||||||
|
|
||||||
|
#### Backend
|
||||||
|
- `backend/indexer.py`:
|
||||||
|
- Updated vault config to support attachments configuration
|
||||||
|
- Integrated attachment index building at startup
|
||||||
|
- Added config storage in vault data structure
|
||||||
|
|
||||||
|
- `backend/main.py`:
|
||||||
|
- Added image preprocessing to markdown rendering pipeline
|
||||||
|
- Implemented `/api/image/{vault}` endpoint with MIME type detection
|
||||||
|
- Added `/api/attachments/rescan/{vault}` endpoint
|
||||||
|
- Added `/api/attachments/stats` endpoint
|
||||||
|
- Updated `_render_markdown()` to accept current file path
|
||||||
|
- Imported `mimetypes` module for content-type detection
|
||||||
|
|
||||||
|
#### Frontend
|
||||||
|
- `frontend/style.css`:
|
||||||
|
- Added `.image-not-found` placeholder styling
|
||||||
|
- Added responsive image rendering styles
|
||||||
|
- Added hover effects for linked images
|
||||||
|
|
||||||
|
#### Documentation
|
||||||
|
- `README.md`:
|
||||||
|
- Added image rendering feature to features list
|
||||||
|
- Added new environment variables documentation
|
||||||
|
- Added new API endpoints to API section
|
||||||
|
- Added comprehensive "Rendu d'images Obsidian" section
|
||||||
|
- Updated usage instructions
|
||||||
|
|
||||||
|
### 🎯 Implementation Details
|
||||||
|
|
||||||
|
#### Resolution Algorithm
|
||||||
|
```python
|
||||||
|
def resolve_image_path(image_src, vault_name, vault_root, current_file_path, attachments_path):
|
||||||
|
# 1. Check cache
|
||||||
|
# 2. Try absolute path
|
||||||
|
# 3. Try config attachments folder
|
||||||
|
# 4. Try startup index (unique match)
|
||||||
|
# 5. Try same directory as markdown file
|
||||||
|
# 6. Try vault root relative
|
||||||
|
# 7. Try startup index (closest match)
|
||||||
|
# 8. Return None (fallback to placeholder)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Image Preprocessing Pipeline
|
||||||
|
```python
|
||||||
|
def preprocess_images(content, vault_name, vault_root, current_file_path, attachments_path):
|
||||||
|
# 1. Process HTML img in markdown links
|
||||||
|
# 2. Process wiki-link embeds
|
||||||
|
# 3. Process standard markdown images
|
||||||
|
# All paths resolved and transformed to /api/image endpoint
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Attachment Index Structure
|
||||||
|
```python
|
||||||
|
attachment_index = {
|
||||||
|
"VaultName": {
|
||||||
|
"image.png": [Path("/absolute/path/to/image.png")],
|
||||||
|
"logo.svg": [Path("/path/1/logo.svg"), Path("/path/2/logo.svg")]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 🔒 Security
|
||||||
|
|
||||||
|
- Path traversal protection maintained for image serving
|
||||||
|
- All image paths validated through `_resolve_safe_path()`
|
||||||
|
- MIME type detection prevents serving arbitrary files
|
||||||
|
- Read-only vault mounts recommended in docker-compose
|
||||||
|
|
||||||
|
### ⚡ Performance
|
||||||
|
|
||||||
|
- **Startup**: O(n) scan where n = number of files in vault
|
||||||
|
- **Resolution (cached)**: O(1) hash table lookup
|
||||||
|
- **Resolution (uncached)**: O(k) where k ≤ 7 strategies
|
||||||
|
- **Memory**: ~100 bytes per indexed image
|
||||||
|
- **Cache invalidation**: On manual rescan only
|
||||||
|
|
||||||
|
### 📊 Logging
|
||||||
|
|
||||||
|
New log messages:
|
||||||
|
- `Vault '{name}': indexed {count} attachments` (INFO)
|
||||||
|
- `Vault '{name}': attachment scanning disabled` (INFO)
|
||||||
|
- `Image resolved via strategy N (description)` (DEBUG)
|
||||||
|
- `Image not resolved (fallback)` (DEBUG)
|
||||||
|
- `Rescanned attachments for vault '{name}': {count} attachments` (INFO)
|
||||||
|
|
||||||
|
### 🧪 Testing
|
||||||
|
|
||||||
|
All acceptance criteria met:
|
||||||
|
- ✅ All 4 image syntaxes render correctly
|
||||||
|
- ✅ Startup scan is asynchronous and non-blocking
|
||||||
|
- ✅ Filename-only wiki-links resolve via index
|
||||||
|
- ✅ Config attachmentsPath used as priority
|
||||||
|
- ✅ Unresolved images show styled placeholder
|
||||||
|
- ✅ No regression on standard markdown syntax
|
||||||
|
- ✅ Rescan command works without restart
|
||||||
|
|
||||||
|
### 🐛 Known Limitations
|
||||||
|
|
||||||
|
1. **No automatic file watching**: Changes to image files require manual rescan
|
||||||
|
2. **No thumbnail generation**: Large images served at full resolution
|
||||||
|
3. **No image optimization**: Images served as-is from filesystem
|
||||||
|
4. **Case sensitivity**: Filename matching is case-insensitive, but path matching respects OS
|
||||||
|
|
||||||
|
### 🔄 Migration Guide
|
||||||
|
|
||||||
|
#### For Existing Installations
|
||||||
|
|
||||||
|
1. **No breaking changes**: Feature is fully backward compatible
|
||||||
|
2. **Optional configuration**: Works without any new environment variables
|
||||||
|
3. **Automatic indexing**: Enabled by default for all vaults
|
||||||
|
|
||||||
|
#### To Enable Optimized Resolution
|
||||||
|
|
||||||
|
Add to your `docker-compose.yml`:
|
||||||
|
```yaml
|
||||||
|
environment:
|
||||||
|
- VAULT_1_ATTACHMENTS_PATH=Assets/Images # Your attachments folder
|
||||||
|
```
|
||||||
|
|
||||||
|
#### To Disable Scanning (for vaults without images)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
environment:
|
||||||
|
- VAULT_N_SCAN_ATTACHMENTS=false
|
||||||
|
```
|
||||||
|
|
||||||
|
### 📝 Documentation
|
||||||
|
|
||||||
|
- **README.md**: Updated with feature overview and configuration
|
||||||
|
- **IMAGE_RENDERING_GUIDE.md**: Comprehensive implementation guide
|
||||||
|
- **CHANGELOG_IMAGE_RENDERING.md**: This detailed changelog
|
||||||
|
|
||||||
|
### 🙏 Acknowledgments
|
||||||
|
|
||||||
|
Implementation based on Obsidian's image handling specifications and community feedback regarding vault attachment organization patterns.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Release Date**: 2025
|
||||||
|
**Compatibility**: ObsiGate 1.1.0+
|
||||||
|
**Python Version**: 3.11+
|
||||||
|
**Dependencies**: No new dependencies required
|
||||||
169
docs/CONTRIBUTING.md
Normal file
169
docs/CONTRIBUTING.md
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
# Contribuer à ObsiGate
|
||||||
|
|
||||||
|
Merci de votre intérêt pour ObsiGate ! Ce guide décrit les standards de code et le workflow de développement.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prérequis
|
||||||
|
|
||||||
|
- **Python** 3.11+
|
||||||
|
- **Docker** >= 20.10 (pour les tests conteneurisés)
|
||||||
|
- **Git**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Lancer en mode développement
|
||||||
|
|
||||||
|
### 1. Cloner et installer les dépendances
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://git.dracodev.net/Projets/ObsiGate.git
|
||||||
|
cd ObsiGate
|
||||||
|
|
||||||
|
# Créer un environnement virtuel
|
||||||
|
python -m venv .venv
|
||||||
|
source .venv/bin/activate # Linux/macOS
|
||||||
|
# .venv\Scripts\activate # Windows
|
||||||
|
|
||||||
|
pip install -r backend/requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Configurer les vaults de test
|
||||||
|
|
||||||
|
Créez un dossier `test_vault/` (ignoré par `.gitignore`) avec quelques fichiers `.md` :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p test_vault
|
||||||
|
echo -e "---\ntags: [test, demo]\ntitle: Note de test\n---\n# Hello\nCeci est une note de test." > test_vault/test.md
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Lancer le serveur de développement
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Définir les variables de vault
|
||||||
|
export VAULT_1_NAME=Test
|
||||||
|
export VAULT_1_PATH=$(pwd)/test_vault
|
||||||
|
|
||||||
|
# Lancer avec rechargement automatique
|
||||||
|
uvicorn backend.main:app --host 0.0.0.0 --port 8080 --reload
|
||||||
|
```
|
||||||
|
|
||||||
|
L'interface est accessible sur `http://localhost:8080`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Standards de code
|
||||||
|
|
||||||
|
### Python (backend/)
|
||||||
|
|
||||||
|
- **Docstrings** : chaque fonction publique doit avoir une docstring complète (style Google/Sphinx).
|
||||||
|
- **Types** : utiliser les annotations de type sur tous les paramètres et retours.
|
||||||
|
- **Modèles** : chaque endpoint FastAPI doit avoir un `response_model` Pydantic.
|
||||||
|
- **Imports** : groupés par standard lib, third-party, local — séparés par une ligne vide.
|
||||||
|
- **Logging** : utiliser le logger du module (`logger = logging.getLogger("obsigate.xxx")`).
|
||||||
|
- **Sécurité** : tout chemin fichier fourni par l'utilisateur doit passer par `_resolve_safe_path()`.
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Exemple de fonction conforme
|
||||||
|
def ma_fonction(param: str, count: int = 10) -> List[str]:
|
||||||
|
"""Description courte de la fonction.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
param: Description du paramètre.
|
||||||
|
count: Nombre maximum de résultats.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Liste de chaînes correspondantes.
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
### JavaScript (frontend/)
|
||||||
|
|
||||||
|
- **Vanilla JS uniquement** — zéro framework, zéro dépendance npm.
|
||||||
|
- **Fonctions nommées** : pas de logique inline dans les event listeners.
|
||||||
|
- **`"use strict"`** : le code est wrappé dans une IIFE stricte.
|
||||||
|
- **Commentaires** : documenter toute logique non-triviale avec des commentaires en ligne.
|
||||||
|
- **Gestion d'erreurs** : toujours `try/catch` les appels `api()`, afficher un toast en cas d'erreur.
|
||||||
|
- **Performance** : utiliser `safeCreateIcons()` (debounced) plutôt que `lucide.createIcons()` directement.
|
||||||
|
|
||||||
|
### CSS (frontend/)
|
||||||
|
|
||||||
|
- **CSS variables** : toutes les couleurs et valeurs de spacing doivent utiliser des variables CSS définies dans `:root`.
|
||||||
|
- **Pas de valeurs hardcodées** : utiliser `var(--danger)` au lieu de `#ff7b72`, etc.
|
||||||
|
- **Thèmes** : toute nouvelle couleur doit être déclarée dans les deux blocs de thème (`dark` et `light`).
|
||||||
|
- **Mobile-first** : vérifier le rendu mobile pour tout changement de layout.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tester les changements
|
||||||
|
|
||||||
|
### Test local rapide
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Lancer le serveur
|
||||||
|
export VAULT_1_NAME=Test && export VAULT_1_PATH=$(pwd)/test_vault
|
||||||
|
uvicorn backend.main:app --port 8080 --reload
|
||||||
|
|
||||||
|
# Vérifier le health check
|
||||||
|
curl http://localhost:8080/api/health
|
||||||
|
|
||||||
|
# Vérifier l'indexation
|
||||||
|
curl http://localhost:8080/api/vaults
|
||||||
|
|
||||||
|
# Tester la recherche
|
||||||
|
curl "http://localhost:8080/api/search?q=test"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test Docker
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build local
|
||||||
|
docker build -t obsigate:test .
|
||||||
|
|
||||||
|
# Lancer avec une vault de test
|
||||||
|
docker run --rm -p 8080:8080 \
|
||||||
|
-v $(pwd)/test_vault:/vaults/Test:ro \
|
||||||
|
-e VAULT_1_NAME=Test \
|
||||||
|
-e VAULT_1_PATH=/vaults/Test \
|
||||||
|
obsigate:test
|
||||||
|
|
||||||
|
# Vérifier le healthcheck
|
||||||
|
curl http://localhost:8080/api/health
|
||||||
|
```
|
||||||
|
|
||||||
|
### Vérifications avant commit
|
||||||
|
|
||||||
|
1. **API** : tous les endpoints retournent les bons codes HTTP.
|
||||||
|
2. **Frontend** : tester en thème clair ET sombre.
|
||||||
|
3. **Mobile** : tester à 375px de largeur (DevTools).
|
||||||
|
4. **Erreurs** : vérifier que les toasts s'affichent correctement sur erreur réseau.
|
||||||
|
5. **Performance** : pas de régression visible sur le temps de chargement.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Workflow Git
|
||||||
|
|
||||||
|
1. **Fork** le projet
|
||||||
|
2. Créer une branche depuis `main` : `git checkout -b feature/ma-feature`
|
||||||
|
3. Commiter avec des messages clairs en français ou anglais
|
||||||
|
4. Pousser et créer une **Pull Request**
|
||||||
|
5. Attendre la review avant de merger
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Structure des commits
|
||||||
|
|
||||||
|
```
|
||||||
|
type: description courte
|
||||||
|
|
||||||
|
Corps optionnel avec plus de détails.
|
||||||
|
```
|
||||||
|
|
||||||
|
Types : `feat`, `fix`, `perf`, `refactor`, `docs`, `style`, `chore`, `test`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Questions ?
|
||||||
|
|
||||||
|
Ouvrez une issue sur [git.dracodev.net/Projets/ObsiGate/issues](https://git.dracodev.net/Projets/ObsiGate/issues).
|
||||||
154
docs/HIDDEN_FILES_GUIDE.md
Normal file
154
docs/HIDDEN_FILES_GUIDE.md
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
# Guide de configuration des fichiers et dossiers cachés
|
||||||
|
|
||||||
|
## Vue d'ensemble
|
||||||
|
|
||||||
|
ObsiGate prend désormais en charge les fichiers et dossiers cachés (ceux qui commencent par un point, comme `.obsidian`, `.git`, etc.) avec une configuration flexible par vault.
|
||||||
|
|
||||||
|
## Fonctionnalités
|
||||||
|
|
||||||
|
### 1. **Activation globale par vault**
|
||||||
|
Vous pouvez activer l'indexation de TOUS les fichiers cachés pour un vault spécifique.
|
||||||
|
|
||||||
|
### 2. **Liste blanche flexible**
|
||||||
|
Ajoutez des dossiers cachés individuels à une liste blanche, même si l'activation globale est désactivée.
|
||||||
|
|
||||||
|
### 3. **Configuration persistante**
|
||||||
|
Les paramètres sont sauvegardés et persistent entre les redémarrages.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Via variables d'environnement
|
||||||
|
|
||||||
|
Ajoutez ces variables à votre configuration Docker ou `.env` :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Pour activer tous les fichiers cachés dans un vault
|
||||||
|
VAULT_1_INCLUDE_HIDDEN=true
|
||||||
|
|
||||||
|
# Pour ajouter des dossiers spécifiques à la liste blanche
|
||||||
|
VAULT_1_HIDDEN_WHITELIST=.obsidian,.github,.vscode
|
||||||
|
|
||||||
|
# Exemple pour un deuxième vault
|
||||||
|
VAULT_2_INCLUDE_HIDDEN=false
|
||||||
|
VAULT_2_HIDDEN_WHITELIST=.obsidian
|
||||||
|
```
|
||||||
|
|
||||||
|
### Via l'interface web
|
||||||
|
|
||||||
|
1. Ouvrez le menu **Options** (icône d'engrenage)
|
||||||
|
2. Cliquez sur **Configurations**
|
||||||
|
3. Faites défiler jusqu'à la section **📁 Fichiers et dossiers cachés**
|
||||||
|
4. Pour chaque vault, vous pouvez :
|
||||||
|
- **Activer/désactiver** l'inclusion de tous les fichiers cachés
|
||||||
|
- **Ajouter des dossiers** à la liste blanche individuellement
|
||||||
|
- **Supprimer des dossiers** de la liste blanche
|
||||||
|
|
||||||
|
5. Cliquez sur **Sauvegarder les paramètres**
|
||||||
|
6. Cliquez sur **Réindexer avec nouveaux paramètres** pour appliquer les changements
|
||||||
|
|
||||||
|
## Exemples d'utilisation
|
||||||
|
|
||||||
|
### Cas 1 : Indexer uniquement le dossier .obsidian
|
||||||
|
|
||||||
|
```bash
|
||||||
|
VAULT_1_INCLUDE_HIDDEN=false
|
||||||
|
VAULT_1_HIDDEN_WHITELIST=.obsidian
|
||||||
|
```
|
||||||
|
|
||||||
|
Ou via l'interface :
|
||||||
|
- Désactiver "Inclure tous les fichiers cachés"
|
||||||
|
- Ajouter `.obsidian` à la liste blanche
|
||||||
|
|
||||||
|
### Cas 2 : Indexer tous les fichiers cachés
|
||||||
|
|
||||||
|
```bash
|
||||||
|
VAULT_1_INCLUDE_HIDDEN=true
|
||||||
|
```
|
||||||
|
|
||||||
|
Ou via l'interface :
|
||||||
|
- Activer "Inclure tous les fichiers cachés"
|
||||||
|
|
||||||
|
### Cas 3 : Indexer plusieurs dossiers cachés spécifiques
|
||||||
|
|
||||||
|
```bash
|
||||||
|
VAULT_1_INCLUDE_HIDDEN=false
|
||||||
|
VAULT_1_HIDDEN_WHITELIST=.obsidian,.github,.vscode
|
||||||
|
```
|
||||||
|
|
||||||
|
Ou via l'interface :
|
||||||
|
- Désactiver "Inclure tous les fichiers cachés"
|
||||||
|
- Ajouter `.obsidian`, `.github`, `.vscode` à la liste blanche
|
||||||
|
|
||||||
|
## API Endpoints
|
||||||
|
|
||||||
|
### Obtenir les paramètres d'un vault
|
||||||
|
|
||||||
|
```http
|
||||||
|
GET /api/vaults/{vault_name}/settings
|
||||||
|
```
|
||||||
|
|
||||||
|
Réponse :
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"includeHidden": false,
|
||||||
|
"hiddenWhitelist": [".obsidian", ".github"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Mettre à jour les paramètres d'un vault
|
||||||
|
|
||||||
|
```http
|
||||||
|
POST /api/vaults/{vault_name}/settings
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"includeHidden": true,
|
||||||
|
"hiddenWhitelist": [".obsidian"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Obtenir les paramètres de tous les vaults
|
||||||
|
|
||||||
|
```http
|
||||||
|
GET /api/vaults/settings/all
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture technique
|
||||||
|
|
||||||
|
### Backend
|
||||||
|
|
||||||
|
- **`backend/indexer.py`** : Fonction `_should_include_path()` qui vérifie si un chemin doit être inclus
|
||||||
|
- **`backend/vault_settings.py`** : Gestion de la persistance des paramètres
|
||||||
|
- **`backend/main.py`** : Endpoints API pour gérer les paramètres
|
||||||
|
- **`backend/attachment_indexer.py`** : Respect des paramètres pour les pièces jointes
|
||||||
|
|
||||||
|
### Frontend
|
||||||
|
|
||||||
|
- **`frontend/index.html`** : Section de configuration dans le modal
|
||||||
|
- **`frontend/app.js`** : Fonctions `loadHiddenFilesSettings()`, `saveHiddenFilesSettings()`, etc.
|
||||||
|
- **`frontend/style.css`** : Styles pour l'interface de configuration
|
||||||
|
|
||||||
|
## Notes importantes
|
||||||
|
|
||||||
|
1. **Réindexation requise** : Après modification des paramètres, une réindexation est nécessaire pour appliquer les changements
|
||||||
|
2. **Persistance** : Les paramètres sont sauvegardés dans `/app/data/vault_settings.json`
|
||||||
|
3. **Priorité** : Les variables d'environnement sont chargées au démarrage, mais peuvent être écrasées via l'interface web
|
||||||
|
4. **Performance** : L'activation de tous les fichiers cachés peut augmenter le temps d'indexation selon le nombre de fichiers
|
||||||
|
|
||||||
|
## Dépannage
|
||||||
|
|
||||||
|
### Les fichiers cachés n'apparaissent pas après activation
|
||||||
|
|
||||||
|
1. Vérifiez que les paramètres sont bien sauvegardés
|
||||||
|
2. Déclenchez une réindexation manuelle
|
||||||
|
3. Vérifiez les logs du serveur pour d'éventuelles erreurs
|
||||||
|
|
||||||
|
### Les paramètres ne persistent pas
|
||||||
|
|
||||||
|
1. Vérifiez que le dossier `/app/data/` est accessible en écriture
|
||||||
|
2. Vérifiez les permissions du fichier `vault_settings.json`
|
||||||
|
3. Consultez les logs pour les erreurs de sauvegarde
|
||||||
|
|
||||||
|
### Conflit entre variables d'environnement et interface web
|
||||||
|
|
||||||
|
Les paramètres de l'interface web écrasent les variables d'environnement. Pour revenir aux variables d'environnement, supprimez le fichier `vault_settings.json` et redémarrez.
|
||||||
380
docs/IMAGE_RENDERING_GUIDE.md
Normal file
380
docs/IMAGE_RENDERING_GUIDE.md
Normal file
@ -0,0 +1,380 @@
|
|||||||
|
# Obsidian Image Rendering - Implementation Guide
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
ObsiGate now supports comprehensive Obsidian-compatible image rendering with intelligent multi-strategy path resolution. This document provides implementation details, testing guidance, and troubleshooting tips.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Features Implemented
|
||||||
|
|
||||||
|
### ✅ Supported Image Syntaxes
|
||||||
|
|
||||||
|
1. **Standard Markdown with HTML attributes** (Obsidian-compatible)
|
||||||
|
```markdown
|
||||||
|
[<img width="180" height="60" src="path/to/image.svg"/>](https://example.com)
|
||||||
|
```
|
||||||
|
- Preserves `width` and `height` attributes
|
||||||
|
- Maintains clickable link wrapper
|
||||||
|
- Resolves `src` through the resolution pipeline
|
||||||
|
|
||||||
|
2. **Obsidian wiki-link embed with full path**
|
||||||
|
```markdown
|
||||||
|
![[06_Boite_a_Outils/6.2_Attachments/image.svg]]
|
||||||
|
```
|
||||||
|
- Full vault-relative path
|
||||||
|
- Resolves relative to vault root
|
||||||
|
|
||||||
|
3. **Obsidian wiki-link embed with filename only**
|
||||||
|
```markdown
|
||||||
|
![[image.svg]]
|
||||||
|
```
|
||||||
|
- Filename only, no path
|
||||||
|
- Resolved using attachment index built at startup
|
||||||
|
|
||||||
|
4. **Standard Markdown image**
|
||||||
|
```markdown
|
||||||
|

|
||||||
|
```
|
||||||
|
- Goes through multi-strategy resolution pipeline
|
||||||
|
- External URLs (http://, https://) are preserved unchanged
|
||||||
|
|
||||||
|
### ✅ Attachment Index
|
||||||
|
|
||||||
|
- **Startup scan**: Asynchronous scan of all vaults for image files
|
||||||
|
- **Supported formats**: `.png`, `.jpg`, `.jpeg`, `.gif`, `.svg`, `.webp`, `.bmp`, `.ico`
|
||||||
|
- **Index structure**: `{vault_name: {filename_lower: [absolute_path, ...]}}`
|
||||||
|
- **Resolution cache**: Results cached per vault + filename for performance
|
||||||
|
- **Logging**: Number of attachments indexed per vault logged at startup
|
||||||
|
|
||||||
|
### ✅ Multi-Strategy Path Resolution
|
||||||
|
|
||||||
|
Priority order (stops at first successful resolution):
|
||||||
|
|
||||||
|
| Priority | Strategy | Description |
|
||||||
|
|----------|----------|-------------|
|
||||||
|
| 1 | Absolute path | If path is absolute and file exists |
|
||||||
|
| 2 | Config attachments folder | Resolve relative to `VAULT_N_ATTACHMENTS_PATH` |
|
||||||
|
| 3 | Startup index (unique match) | Lookup filename in index; use if only one match |
|
||||||
|
| 4 | Same directory | Resolve relative to current markdown file's directory |
|
||||||
|
| 5 | Vault root relative | Resolve relative to vault root |
|
||||||
|
| 6 | Startup index (closest match) | If multiple matches, pick best path match |
|
||||||
|
| 7 | Fallback | Display styled placeholder with tooltip |
|
||||||
|
|
||||||
|
### ✅ Configuration Schema
|
||||||
|
|
||||||
|
New environment variables per vault:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Required
|
||||||
|
VAULT_1_NAME=MyVault
|
||||||
|
VAULT_1_PATH=/vaults/MyVault
|
||||||
|
|
||||||
|
# Optional - Image configuration
|
||||||
|
VAULT_1_ATTACHMENTS_PATH=06_Boite_a_Outils/6.2_Attachments # Relative path
|
||||||
|
VAULT_1_SCAN_ATTACHMENTS=true # Default: true
|
||||||
|
```
|
||||||
|
|
||||||
|
### ✅ API Endpoints
|
||||||
|
|
||||||
|
**Serve Image**
|
||||||
|
```
|
||||||
|
GET /api/image/{vault_name}?path=relative/path/to/image.png
|
||||||
|
```
|
||||||
|
- Returns image with proper MIME type
|
||||||
|
- Supports all common image formats
|
||||||
|
- Path traversal protection
|
||||||
|
|
||||||
|
**Rescan Vault Attachments**
|
||||||
|
```
|
||||||
|
POST /api/attachments/rescan/{vault_name}
|
||||||
|
```
|
||||||
|
- Clears cache for the vault
|
||||||
|
- Re-scans vault directory for images
|
||||||
|
- Returns attachment count
|
||||||
|
|
||||||
|
**Attachment Statistics**
|
||||||
|
```
|
||||||
|
GET /api/attachments/stats?vault={vault_name}
|
||||||
|
```
|
||||||
|
- Returns attachment counts per vault
|
||||||
|
- Optional vault filter
|
||||||
|
|
||||||
|
### ✅ Frontend Styling
|
||||||
|
|
||||||
|
**Image Rendering**
|
||||||
|
- Images displayed with `max-width: 100%` for responsiveness
|
||||||
|
- Rounded corners and subtle shadow
|
||||||
|
- Hover effect on linked images
|
||||||
|
|
||||||
|
**Placeholder for Missing Images**
|
||||||
|
- Styled error box with dashed border
|
||||||
|
- Shows filename in monospace font
|
||||||
|
- Tooltip displays full path
|
||||||
|
- Red color scheme for visibility
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Testing Guide
|
||||||
|
|
||||||
|
### Test Case 1: Standard Markdown Image
|
||||||
|
|
||||||
|
**Markdown:**
|
||||||
|
```markdown
|
||||||
|

|
||||||
|
```
|
||||||
|
|
||||||
|
**Expected:**
|
||||||
|
- Image resolves via multi-strategy resolution
|
||||||
|
- Displays with proper styling
|
||||||
|
- Shows placeholder if not found
|
||||||
|
|
||||||
|
### Test Case 2: Wiki-link with Full Path
|
||||||
|
|
||||||
|
**Markdown:**
|
||||||
|
```markdown
|
||||||
|
![[Assets/Images/diagram.svg]]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Expected:**
|
||||||
|
- Resolves relative to vault root
|
||||||
|
- SVG renders inline
|
||||||
|
- Maintains aspect ratio
|
||||||
|
|
||||||
|
### Test Case 3: Wiki-link with Filename Only
|
||||||
|
|
||||||
|
**Markdown:**
|
||||||
|
```markdown
|
||||||
|
![[logo.png]]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Expected:**
|
||||||
|
- Searches attachment index
|
||||||
|
- Resolves to unique match if only one exists
|
||||||
|
- Shows placeholder if not found or ambiguous
|
||||||
|
|
||||||
|
### Test Case 4: HTML Image in Link
|
||||||
|
|
||||||
|
**Markdown:**
|
||||||
|
```markdown
|
||||||
|
[<img width="200" height="100" src="banner.jpg"/>](https://example.com)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Expected:**
|
||||||
|
- Preserves width and height attributes
|
||||||
|
- Image is clickable and links to URL
|
||||||
|
- Resolves banner.jpg through resolution pipeline
|
||||||
|
|
||||||
|
### Test Case 5: External Image URL
|
||||||
|
|
||||||
|
**Markdown:**
|
||||||
|
```markdown
|
||||||
|

|
||||||
|
```
|
||||||
|
|
||||||
|
**Expected:**
|
||||||
|
- URL preserved unchanged
|
||||||
|
- Image loaded from external source
|
||||||
|
- No resolution attempted
|
||||||
|
|
||||||
|
### Test Case 6: Missing Image
|
||||||
|
|
||||||
|
**Markdown:**
|
||||||
|
```markdown
|
||||||
|
![[nonexistent.png]]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Expected:**
|
||||||
|
- Displays: `[image not found: nonexistent.png]`
|
||||||
|
- Styled with red dashed border
|
||||||
|
- Tooltip shows full attempted path
|
||||||
|
|
||||||
|
### Test Case 7: Attachments Path Priority
|
||||||
|
|
||||||
|
**Setup:**
|
||||||
|
```bash
|
||||||
|
VAULT_1_ATTACHMENTS_PATH=Attachments
|
||||||
|
```
|
||||||
|
|
||||||
|
**Markdown:**
|
||||||
|
```markdown
|
||||||
|
![[photo.jpg]]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Expected:**
|
||||||
|
- Checks `Attachments/photo.jpg` first (strategy 2)
|
||||||
|
- Falls back to index search if not found
|
||||||
|
- Logs resolution strategy used
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Images Not Displaying
|
||||||
|
|
||||||
|
**Symptom:** Images show as placeholders even though files exist
|
||||||
|
|
||||||
|
**Checks:**
|
||||||
|
1. Verify attachment index was built at startup:
|
||||||
|
```bash
|
||||||
|
docker logs obsigate | grep "indexed.*attachments"
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Check attachment stats:
|
||||||
|
```bash
|
||||||
|
curl http://localhost:2020/api/attachments/stats
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Verify file permissions (Docker must be able to read images)
|
||||||
|
|
||||||
|
4. Check if image extension is supported (see `IMAGE_EXTENSIONS` in `attachment_indexer.py`)
|
||||||
|
|
||||||
|
**Solution:**
|
||||||
|
- Rescan attachments: `curl -X POST http://localhost:2020/api/attachments/rescan/VaultName`
|
||||||
|
- Check Docker volume mounts in `docker-compose.yml`
|
||||||
|
- Verify `VAULT_N_SCAN_ATTACHMENTS` is not set to `false`
|
||||||
|
|
||||||
|
### Attachment Scan Disabled
|
||||||
|
|
||||||
|
**Symptom:** Log shows "attachment scanning disabled"
|
||||||
|
|
||||||
|
**Cause:** `VAULT_N_SCAN_ATTACHMENTS=false` in environment
|
||||||
|
|
||||||
|
**Solution:**
|
||||||
|
- Remove the variable or set to `true`
|
||||||
|
- Restart container: `docker-compose restart obsigate`
|
||||||
|
|
||||||
|
### Wrong Image Resolved (Multiple Matches)
|
||||||
|
|
||||||
|
**Symptom:** Image with common filename resolves to wrong file
|
||||||
|
|
||||||
|
**Cause:** Multiple files with same name in different directories
|
||||||
|
|
||||||
|
**Solution:**
|
||||||
|
1. Use full path syntax: `![[folder/subfolder/image.png]]`
|
||||||
|
2. Configure `VAULT_N_ATTACHMENTS_PATH` to prioritize specific folder
|
||||||
|
3. Rename files to be unique
|
||||||
|
|
||||||
|
### Performance Issues with Large Vaults
|
||||||
|
|
||||||
|
**Symptom:** Slow startup or high memory usage
|
||||||
|
|
||||||
|
**Cause:** Large number of images being indexed
|
||||||
|
|
||||||
|
**Optimization:**
|
||||||
|
1. Disable scanning for vaults without images:
|
||||||
|
```bash
|
||||||
|
VAULT_N_SCAN_ATTACHMENTS=false
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Use specific attachments folder to reduce scan scope:
|
||||||
|
```bash
|
||||||
|
VAULT_N_ATTACHMENTS_PATH=Images
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Monitor memory usage:
|
||||||
|
```bash
|
||||||
|
docker stats obsigate
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Module Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
backend/
|
||||||
|
├── attachment_indexer.py # Image scanning and indexing
|
||||||
|
├── image_processor.py # Markdown preprocessing
|
||||||
|
├── indexer.py # Vault indexing (updated)
|
||||||
|
└── main.py # API endpoints (updated)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Data Flow
|
||||||
|
|
||||||
|
```
|
||||||
|
Startup:
|
||||||
|
├─ indexer.build_index()
|
||||||
|
│ ├─ Scans markdown files
|
||||||
|
│ └─ Calls attachment_indexer.build_attachment_index()
|
||||||
|
└─ attachment_indexer builds image index per vault
|
||||||
|
|
||||||
|
Rendering:
|
||||||
|
├─ User requests markdown file
|
||||||
|
├─ main._render_markdown() called
|
||||||
|
│ ├─ image_processor.preprocess_images()
|
||||||
|
│ │ ├─ Detects all 4 image syntaxes
|
||||||
|
│ │ ├─ Calls resolve_image_path() for each
|
||||||
|
│ │ └─ Transforms to /api/image/{vault}?path=...
|
||||||
|
│ └─ mistune renders to HTML
|
||||||
|
└─ Frontend displays with styled images
|
||||||
|
|
||||||
|
Image Serving:
|
||||||
|
├─ Browser requests /api/image/{vault}?path=...
|
||||||
|
├─ main.api_image() validates and resolves path
|
||||||
|
├─ Determines MIME type
|
||||||
|
└─ Returns image bytes with proper content-type
|
||||||
|
```
|
||||||
|
|
||||||
|
### Resolution Cache
|
||||||
|
|
||||||
|
- **Key:** `(vault_name, image_src)`
|
||||||
|
- **Value:** `Optional[Path]` (resolved absolute path or None)
|
||||||
|
- **Invalidation:** On vault rescan
|
||||||
|
- **Thread-safe:** Protected by `_attachment_lock`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Performance Characteristics
|
||||||
|
|
||||||
|
| Operation | Complexity | Notes |
|
||||||
|
|-----------|-----------|-------|
|
||||||
|
| Attachment scan | O(n) | n = number of files in vault |
|
||||||
|
| Image resolution (cached) | O(1) | Hash table lookup |
|
||||||
|
| Image resolution (uncached) | O(k) | k = number of strategies (max 7) |
|
||||||
|
| Rescan vault | O(n) | Rebuilds index for one vault |
|
||||||
|
|
||||||
|
**Memory Usage:**
|
||||||
|
- ~100 bytes per indexed image (filename + path)
|
||||||
|
- Resolution cache grows with unique image references
|
||||||
|
- Cache cleared on rescan
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Future Enhancements
|
||||||
|
|
||||||
|
Potential improvements for future versions:
|
||||||
|
|
||||||
|
1. **Lazy loading**: Only index images when first accessed
|
||||||
|
2. **Image thumbnails**: Generate and cache thumbnails for large images
|
||||||
|
3. **Image metadata**: Extract and display EXIF data
|
||||||
|
4. **Batch rescan**: Rescan all vaults with one command
|
||||||
|
5. **File watcher**: Auto-rescan on filesystem changes
|
||||||
|
6. **Image optimization**: Compress images on-the-fly
|
||||||
|
7. **CDN support**: Serve images from external CDN
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Acceptance Criteria Status
|
||||||
|
|
||||||
|
- [x] All 4 image syntaxes render correctly in markdown preview
|
||||||
|
- [x] Startup scan completes without blocking UI (async/background)
|
||||||
|
- [x] Images with filename-only wiki-links resolve via index
|
||||||
|
- [x] Config `attachmentsPath` used as priority lookup
|
||||||
|
- [x] Unresolved images show visible placeholder, not broken icon
|
||||||
|
- [x] No regression on standard markdown image syntax `![]()`
|
||||||
|
- [x] Rescan command works and updates display without restart
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Version Information
|
||||||
|
|
||||||
|
**Implementation Date:** 2025
|
||||||
|
**ObsiGate Version:** 1.2.0 (pending)
|
||||||
|
**Python Version:** 3.11+
|
||||||
|
**Dependencies:** No new dependencies required
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*For questions or issues, refer to the main README.md or open an issue on the project repository.*
|
||||||
182
docs/INSTALLATION_PWA.md
Normal file
182
docs/INSTALLATION_PWA.md
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
# Installation PWA - Guide Rapide
|
||||||
|
|
||||||
|
## 🚀 Démarrage Rapide
|
||||||
|
|
||||||
|
ObsiGate est maintenant une Progressive Web App ! Voici comment l'installer et l'utiliser.
|
||||||
|
|
||||||
|
## 📋 Prérequis
|
||||||
|
|
||||||
|
- Docker et docker-compose installés
|
||||||
|
- Navigateur moderne (Chrome, Edge, Safari, Firefox)
|
||||||
|
- HTTPS en production (ou localhost pour le développement)
|
||||||
|
|
||||||
|
## 🔧 Installation
|
||||||
|
|
||||||
|
### 1. Démarrer ObsiGate
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ObsiGate
|
||||||
|
docker-compose up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Générer les Icônes (Optionnel)
|
||||||
|
|
||||||
|
Les icônes SVG sont déjà générées. Pour les convertir en PNG :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Installer ImageMagick ou Inkscape
|
||||||
|
# Puis exécuter dans frontend/icons/
|
||||||
|
for file in *.svg; do
|
||||||
|
size=$(echo $file | grep -oP '\d+x\d+' | head -1 | cut -d'x' -f1)
|
||||||
|
convert -background none -resize ${size}x${size} "$file" "${file%.svg}.png"
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note** : Les navigateurs modernes supportent les SVG, cette étape est optionnelle.
|
||||||
|
|
||||||
|
### 3. Accéder à l'Application
|
||||||
|
|
||||||
|
Ouvrez votre navigateur sur : **http://localhost:2020**
|
||||||
|
|
||||||
|
## 📱 Installer l'Application
|
||||||
|
|
||||||
|
### Sur Desktop (Chrome, Edge, Brave)
|
||||||
|
|
||||||
|
1. Cliquez sur l'icône **➕** ou **⬇️** dans la barre d'adresse
|
||||||
|
2. Cliquez sur **"Installer ObsiGate"**
|
||||||
|
3. L'application s'ouvre dans une fenêtre dédiée
|
||||||
|
|
||||||
|
### Sur Android
|
||||||
|
|
||||||
|
1. Ouvrez le menu **⋮** (trois points)
|
||||||
|
2. Sélectionnez **"Ajouter à l'écran d'accueil"**
|
||||||
|
3. Confirmez l'installation
|
||||||
|
4. L'icône ObsiGate apparaît sur votre écran d'accueil
|
||||||
|
|
||||||
|
### Sur iOS/iPadOS
|
||||||
|
|
||||||
|
1. Appuyez sur le bouton **Partager** 📤
|
||||||
|
2. Faites défiler et sélectionnez **"Sur l'écran d'accueil"**
|
||||||
|
3. Nommez l'application et appuyez sur **"Ajouter"**
|
||||||
|
4. L'icône ObsiGate apparaît sur votre écran d'accueil
|
||||||
|
|
||||||
|
## ✨ Fonctionnalités PWA
|
||||||
|
|
||||||
|
### Mode Hors Ligne
|
||||||
|
- Interface utilisateur accessible sans connexion
|
||||||
|
- Dernières données consultées disponibles en cache
|
||||||
|
- Synchronisation automatique au retour en ligne
|
||||||
|
|
||||||
|
### Mises à Jour Automatiques
|
||||||
|
- Vérification toutes les minutes
|
||||||
|
- Notification élégante quand une nouvelle version est disponible
|
||||||
|
- Mise à jour en un clic
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
- Chargement instantané grâce au cache
|
||||||
|
- Réduction de la consommation de données
|
||||||
|
- Expérience fluide et réactive
|
||||||
|
|
||||||
|
## 🔍 Vérification
|
||||||
|
|
||||||
|
### Vérifier que le PWA fonctionne
|
||||||
|
|
||||||
|
1. Ouvrez **DevTools** (F12)
|
||||||
|
2. Allez dans l'onglet **"Application"**
|
||||||
|
3. Vérifiez :
|
||||||
|
- **Manifest** : Doit afficher les métadonnées ObsiGate
|
||||||
|
- **Service Workers** : Doit montrer un SW actif
|
||||||
|
- **Cache Storage** : Doit contenir `obsigate-v1.4.0-static` et `dynamic`
|
||||||
|
|
||||||
|
### Tester le Mode Hors Ligne
|
||||||
|
|
||||||
|
1. DevTools → Onglet **"Network"**
|
||||||
|
2. Cochez **"Offline"**
|
||||||
|
3. Rechargez la page
|
||||||
|
4. L'application doit fonctionner avec les données en cache
|
||||||
|
|
||||||
|
## 🎨 Personnalisation
|
||||||
|
|
||||||
|
### Modifier les Couleurs du Thème
|
||||||
|
|
||||||
|
Éditez `frontend/manifest.json` :
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"theme_color": "#2563eb", // Couleur de la barre d'état
|
||||||
|
"background_color": "#1a1a1a" // Couleur de fond au lancement
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Régénérer les Icônes
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python generate_pwa_icons.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Puis personnalisez le script pour vos propres designs.
|
||||||
|
|
||||||
|
## 🐛 Dépannage
|
||||||
|
|
||||||
|
### L'icône d'installation n'apparaît pas
|
||||||
|
|
||||||
|
**Causes possibles** :
|
||||||
|
- Pas de HTTPS (sauf localhost)
|
||||||
|
- Manifeste invalide
|
||||||
|
- Service Worker non enregistré
|
||||||
|
|
||||||
|
**Solution** :
|
||||||
|
```bash
|
||||||
|
# Vérifier les logs du navigateur
|
||||||
|
# Console → Rechercher "PWA" ou "Service Worker"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Le mode hors ligne ne fonctionne pas
|
||||||
|
|
||||||
|
**Vérification** :
|
||||||
|
1. DevTools → Application → Service Workers
|
||||||
|
2. Vérifier que le SW est "activated and running"
|
||||||
|
3. Vérifier le Cache Storage
|
||||||
|
|
||||||
|
**Solution** :
|
||||||
|
```javascript
|
||||||
|
// Forcer la mise à jour du SW
|
||||||
|
navigator.serviceWorker.getRegistration().then(reg => reg.update());
|
||||||
|
```
|
||||||
|
|
||||||
|
### Désinstaller l'Application
|
||||||
|
|
||||||
|
**Desktop** :
|
||||||
|
- Clic droit sur l'icône → "Désinstaller"
|
||||||
|
- Ou : Menu app → "Désinstaller ObsiGate"
|
||||||
|
|
||||||
|
**Mobile** :
|
||||||
|
- Maintenez l'icône → "Supprimer"
|
||||||
|
- Ou : Paramètres → Applications → ObsiGate → Désinstaller
|
||||||
|
|
||||||
|
## 📚 Documentation Complète
|
||||||
|
|
||||||
|
- **`PWA_GUIDE.md`** - Guide complet avec toutes les fonctionnalités
|
||||||
|
- **`PWA_CHANGELOG.md`** - Liste détaillée des modifications
|
||||||
|
- **`PWA_SUMMARY.md`** - Résumé technique des implémentations
|
||||||
|
|
||||||
|
## ✅ Checklist de Déploiement
|
||||||
|
|
||||||
|
- [ ] ObsiGate démarré avec Docker
|
||||||
|
- [ ] Accessible sur localhost:2020
|
||||||
|
- [ ] Manifeste visible dans DevTools
|
||||||
|
- [ ] Service Worker enregistré
|
||||||
|
- [ ] Cache fonctionnel
|
||||||
|
- [ ] Mode hors ligne testé
|
||||||
|
- [ ] Installation testée sur au moins un appareil
|
||||||
|
- [ ] Audit Lighthouse PWA > 90/100
|
||||||
|
|
||||||
|
## 🎉 Félicitations !
|
||||||
|
|
||||||
|
Vous avez maintenant ObsiGate en tant que Progressive Web App !
|
||||||
|
|
||||||
|
Profitez de vos notes Obsidian partout, même hors ligne. 📖✨
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Besoin d'aide ?** Consultez `PWA_GUIDE.md` pour plus de détails.
|
||||||
312
docs/MODIFICATIONS_PWA.txt
Normal file
312
docs/MODIFICATIONS_PWA.txt
Normal file
@ -0,0 +1,312 @@
|
|||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
OBSIGATE - TRANSFORMATION EN PROGRESSIVE WEB APP (PWA)
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
✅ STATUT : TRANSFORMATION COMPLÈTE ET FONCTIONNELLE
|
||||||
|
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
📦 FICHIERS CRÉÉS
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
FRONTEND
|
||||||
|
--------
|
||||||
|
✅ frontend/manifest.json - Manifeste PWA complet
|
||||||
|
✅ frontend/sw.js - Service Worker avec cache intelligent
|
||||||
|
✅ frontend/icons/icon-72x72.svg - Icône 72x72
|
||||||
|
✅ frontend/icons/icon-96x96.svg - Icône 96x96
|
||||||
|
✅ frontend/icons/icon-128x128.svg - Icône 128x128
|
||||||
|
✅ frontend/icons/icon-144x144.svg - Icône 144x144
|
||||||
|
✅ frontend/icons/icon-152x152.svg - Icône 152x152
|
||||||
|
✅ frontend/icons/icon-192x192.svg - Icône 192x192 (Android standard)
|
||||||
|
✅ frontend/icons/icon-384x384.svg - Icône 384x384
|
||||||
|
✅ frontend/icons/icon-512x512.svg - Icône 512x512 (splash screen)
|
||||||
|
✅ frontend/icons/icon-192x192-maskable.svg - Icône maskable 192x192
|
||||||
|
✅ frontend/icons/icon-512x512-maskable.svg - Icône maskable 512x512
|
||||||
|
✅ frontend/icons/search-96x96.svg - Icône raccourci recherche
|
||||||
|
✅ frontend/icons/README.md - Guide conversion SVG→PNG
|
||||||
|
|
||||||
|
SCRIPTS
|
||||||
|
-------
|
||||||
|
✅ generate_pwa_icons.py - Générateur automatique d'icônes
|
||||||
|
|
||||||
|
DOCUMENTATION
|
||||||
|
-------------
|
||||||
|
✅ PWA_GUIDE.md - Guide complet PWA (utilisation, config)
|
||||||
|
✅ PWA_CHANGELOG.md - Changelog détaillé des modifications
|
||||||
|
✅ PWA_SUMMARY.md - Résumé technique
|
||||||
|
✅ INSTALLATION_PWA.md - Guide d'installation rapide
|
||||||
|
✅ MODIFICATIONS_PWA.txt - Ce fichier
|
||||||
|
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
🔧 FICHIERS MODIFIÉS
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
FRONTEND
|
||||||
|
--------
|
||||||
|
✅ frontend/index.html
|
||||||
|
- Ajout meta tags PWA (description, theme-color, mobile-web-app-capable)
|
||||||
|
- Ajout lien vers manifest.json
|
||||||
|
- Ajout icônes Apple Touch
|
||||||
|
- Ajout favicon SVG
|
||||||
|
|
||||||
|
✅ frontend/app.js
|
||||||
|
- Fonction registerServiceWorker() pour enregistrer le SW
|
||||||
|
- Fonction showUpdateNotification() pour les mises à jour
|
||||||
|
- Gestion événement beforeinstallprompt (installation)
|
||||||
|
- Gestion événement appinstalled (confirmation)
|
||||||
|
- Appel registerServiceWorker() au DOMContentLoaded
|
||||||
|
|
||||||
|
✅ frontend/style.css
|
||||||
|
- Styles .pwa-update-notification
|
||||||
|
- Styles .pwa-update-content
|
||||||
|
- Styles .pwa-update-btn et .pwa-update-dismiss
|
||||||
|
- Styles #pwa-install-btn (optionnel)
|
||||||
|
- Animation @keyframes slideInUp
|
||||||
|
- Responsive mobile pour notifications PWA
|
||||||
|
|
||||||
|
BACKEND
|
||||||
|
-------
|
||||||
|
✅ backend/main.py
|
||||||
|
- Route GET /sw.js pour servir le service worker
|
||||||
|
Headers: Cache-Control: no-cache, Service-Worker-Allowed: /
|
||||||
|
- Route GET /manifest.json pour servir le manifeste
|
||||||
|
Headers: Cache-Control: public, max-age=3600
|
||||||
|
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
🎯 FONCTIONNALITÉS IMPLÉMENTÉES
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
MANIFESTE PWA (manifest.json)
|
||||||
|
------------------------------
|
||||||
|
✅ Métadonnées complètes (nom, description, icônes)
|
||||||
|
✅ Configuration affichage standalone (mode app)
|
||||||
|
✅ Couleurs thème (#2563eb bleu, #1a1a1a sombre)
|
||||||
|
✅ Icônes multiples tailles (72px à 512px)
|
||||||
|
✅ Icônes maskables pour Android adaptatif
|
||||||
|
✅ Raccourcis d'application (recherche)
|
||||||
|
✅ Screenshots (placeholders)
|
||||||
|
✅ Catégories (productivity, utilities)
|
||||||
|
|
||||||
|
SERVICE WORKER (sw.js)
|
||||||
|
----------------------
|
||||||
|
✅ Cache statique (interface: HTML, CSS, JS, icônes)
|
||||||
|
✅ Cache dynamique (API, max 50 entrées avec rotation)
|
||||||
|
✅ Stratégie Cache-First pour assets statiques
|
||||||
|
✅ Stratégie Network-First pour API
|
||||||
|
✅ Gestion mises à jour automatiques
|
||||||
|
✅ Nettoyage automatique anciens caches
|
||||||
|
✅ Exclusion endpoints SSE (/api/events)
|
||||||
|
✅ Exclusion endpoints auth (/api/auth/*)
|
||||||
|
✅ Fallback gracieux hors ligne
|
||||||
|
✅ Support notifications push (préparé)
|
||||||
|
✅ Support background sync (préparé)
|
||||||
|
|
||||||
|
INTERFACE UTILISATEUR
|
||||||
|
---------------------
|
||||||
|
✅ Enregistrement automatique service worker
|
||||||
|
✅ Notification élégante mises à jour
|
||||||
|
✅ Toast confirmation installation
|
||||||
|
✅ Bouton installation optionnel (beforeinstallprompt)
|
||||||
|
✅ Styles responsive notifications
|
||||||
|
✅ Animation slide-in pour notifications
|
||||||
|
|
||||||
|
BACKEND
|
||||||
|
-------
|
||||||
|
✅ Endpoint /sw.js avec headers appropriés
|
||||||
|
✅ Endpoint /manifest.json avec cache
|
||||||
|
✅ Service icônes via /static/icons/
|
||||||
|
|
||||||
|
GÉNÉRATION ICÔNES
|
||||||
|
-----------------
|
||||||
|
✅ Script Python automatisé
|
||||||
|
✅ 8 tailles régulières (72, 96, 128, 144, 152, 192, 384, 512)
|
||||||
|
✅ 2 icônes maskables (192, 512)
|
||||||
|
✅ Icône recherche pour raccourcis (96)
|
||||||
|
✅ Design cohérent (livre bleu gradient)
|
||||||
|
✅ Documentation conversion SVG→PNG
|
||||||
|
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
📱 COMPATIBILITÉ
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
NAVIGATEURS DESKTOP
|
||||||
|
-------------------
|
||||||
|
Chrome : ✅ Installation native + SW + Cache + Notifications
|
||||||
|
Edge : ✅ Installation native + SW + Cache + Notifications
|
||||||
|
Firefox : ⚠️ SW + Cache (pas d'installation native)
|
||||||
|
Safari : ⚠️ SW + Cache (support PWA limité)
|
||||||
|
|
||||||
|
NAVIGATEURS MOBILE
|
||||||
|
------------------
|
||||||
|
Chrome Android : ✅ Installation + SW + Cache + Notifications + Raccourcis
|
||||||
|
Safari iOS : ✅ Add to Home Screen + SW + Cache
|
||||||
|
Samsung Internet: ✅ Installation native + SW + Cache
|
||||||
|
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
🚀 UTILISATION
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
INSTALLATION DESKTOP (Chrome/Edge)
|
||||||
|
----------------------------------
|
||||||
|
1. Ouvrir ObsiGate dans le navigateur
|
||||||
|
2. Cliquer sur l'icône d'installation (barre d'adresse)
|
||||||
|
3. Confirmer l'installation
|
||||||
|
4. L'app s'ouvre dans une fenêtre dédiée
|
||||||
|
|
||||||
|
INSTALLATION ANDROID
|
||||||
|
--------------------
|
||||||
|
1. Ouvrir ObsiGate dans Chrome
|
||||||
|
2. Menu ⋮ → "Ajouter à l'écran d'accueil"
|
||||||
|
3. Confirmer
|
||||||
|
4. Icône ObsiGate sur l'écran d'accueil
|
||||||
|
|
||||||
|
INSTALLATION iOS
|
||||||
|
----------------
|
||||||
|
1. Ouvrir ObsiGate dans Safari
|
||||||
|
2. Bouton Partager 📤
|
||||||
|
3. "Sur l'écran d'accueil"
|
||||||
|
4. Confirmer
|
||||||
|
5. Icône ObsiGate sur l'écran d'accueil
|
||||||
|
|
||||||
|
GÉNÉRATION ICÔNES
|
||||||
|
-----------------
|
||||||
|
python generate_pwa_icons.py
|
||||||
|
|
||||||
|
# Optionnel : Conversion SVG→PNG
|
||||||
|
cd frontend/icons
|
||||||
|
for file in *.svg; do
|
||||||
|
size=$(echo $file | grep -oP '\d+x\d+' | head -1 | cut -d'x' -f1)
|
||||||
|
convert -background none -resize ${size}x${size} "$file" "${file%.svg}.png"
|
||||||
|
done
|
||||||
|
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
🔍 VÉRIFICATION
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
DEVTOOLS - ONGLET APPLICATION
|
||||||
|
------------------------------
|
||||||
|
✅ Manifest : Doit afficher métadonnées ObsiGate
|
||||||
|
✅ Service Workers : Doit montrer SW actif
|
||||||
|
✅ Cache Storage : obsigate-v1.4.0-static et dynamic
|
||||||
|
|
||||||
|
TEST MODE HORS LIGNE
|
||||||
|
---------------------
|
||||||
|
1. DevTools → Network → Cocher "Offline"
|
||||||
|
2. Recharger la page
|
||||||
|
3. L'app doit fonctionner avec cache
|
||||||
|
|
||||||
|
LIGHTHOUSE AUDIT
|
||||||
|
----------------
|
||||||
|
Score PWA attendu : 90-100/100
|
||||||
|
|
||||||
|
CONSOLE NAVIGATEUR
|
||||||
|
------------------
|
||||||
|
# Vérifier enregistrement SW
|
||||||
|
navigator.serviceWorker.getRegistration()
|
||||||
|
.then(reg => console.log('SW:', reg));
|
||||||
|
|
||||||
|
# Forcer mise à jour
|
||||||
|
navigator.serviceWorker.getRegistration()
|
||||||
|
.then(reg => reg.update());
|
||||||
|
|
||||||
|
# Vider cache
|
||||||
|
caches.keys().then(keys =>
|
||||||
|
Promise.all(keys.map(key => caches.delete(key)))
|
||||||
|
);
|
||||||
|
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
🎨 PERSONNALISATION
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
MODIFIER COULEURS
|
||||||
|
-----------------
|
||||||
|
Fichier: frontend/manifest.json
|
||||||
|
{
|
||||||
|
"theme_color": "#2563eb", // Barre d'état
|
||||||
|
"background_color": "#1a1a1a" // Fond lancement
|
||||||
|
}
|
||||||
|
|
||||||
|
MODIFIER ICÔNES
|
||||||
|
---------------
|
||||||
|
1. Éditer generate_pwa_icons.py
|
||||||
|
2. Modifier create_svg_icon() et create_maskable_svg_icon()
|
||||||
|
3. Régénérer: python generate_pwa_icons.py
|
||||||
|
|
||||||
|
AJOUTER RACCOURCIS
|
||||||
|
------------------
|
||||||
|
Fichier: frontend/manifest.json
|
||||||
|
{
|
||||||
|
"shortcuts": [
|
||||||
|
{
|
||||||
|
"name": "Nouvelle Note",
|
||||||
|
"url": "/?action=new",
|
||||||
|
"icons": [{"src": "/static/icons/new-96x96.svg", "sizes": "96x96"}]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
📚 DOCUMENTATION
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
PWA_GUIDE.md : Guide complet (installation, config, débogage)
|
||||||
|
PWA_CHANGELOG.md : Changelog détaillé des modifications
|
||||||
|
PWA_SUMMARY.md : Résumé technique des implémentations
|
||||||
|
INSTALLATION_PWA.md : Guide d'installation rapide
|
||||||
|
frontend/icons/README.md : Instructions conversion icônes
|
||||||
|
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
✅ CHECKLIST FINALE
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
FICHIERS
|
||||||
|
--------
|
||||||
|
✅ manifest.json créé et valide
|
||||||
|
✅ sw.js créé et fonctionnel
|
||||||
|
✅ 11 icônes SVG générées
|
||||||
|
✅ Meta tags PWA ajoutés à index.html
|
||||||
|
✅ Service worker enregistré dans app.js
|
||||||
|
✅ Styles notifications ajoutés à style.css
|
||||||
|
✅ Routes backend ajoutées à main.py
|
||||||
|
✅ Documentation complète créée
|
||||||
|
|
||||||
|
FONCTIONNALITÉS
|
||||||
|
---------------
|
||||||
|
✅ Installation native (desktop/mobile)
|
||||||
|
✅ Mode hors ligne opérationnel
|
||||||
|
✅ Cache intelligent (statique + dynamique)
|
||||||
|
✅ Notifications de mise à jour
|
||||||
|
✅ Raccourcis d'application
|
||||||
|
✅ Icônes adaptatives (maskable)
|
||||||
|
✅ Thème cohérent
|
||||||
|
✅ Responsive design maintenu
|
||||||
|
|
||||||
|
TESTS
|
||||||
|
-----
|
||||||
|
✅ Manifeste valide (DevTools)
|
||||||
|
✅ Service Worker enregistré
|
||||||
|
✅ Cache fonctionnel
|
||||||
|
✅ Mode hors ligne testé
|
||||||
|
✅ Compatible Chrome/Edge/Safari/Firefox
|
||||||
|
✅ Compatible Android/iOS
|
||||||
|
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
🎉 RÉSULTAT
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
ObsiGate est maintenant une PROGRESSIVE WEB APP COMPLÈTE offrant :
|
||||||
|
|
||||||
|
📱 Installation native sur tous les appareils
|
||||||
|
🔌 Mode hors ligne fonctionnel
|
||||||
|
⚡ Performance optimisée avec cache intelligent
|
||||||
|
🔄 Mises à jour automatiques avec notifications
|
||||||
|
🎨 Expérience utilisateur native
|
||||||
|
🌍 Compatible multi-plateforme
|
||||||
|
📦 Taille optimisée (icônes SVG)
|
||||||
|
🔒 Sécurisé (HTTPS requis en production)
|
||||||
|
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
ObsiGate v1.5.0 PWA - Vos notes Obsidian, partout, tout le temps ! 📖✨
|
||||||
|
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
187
docs/PWA_CHANGELOG.md
Normal file
187
docs/PWA_CHANGELOG.md
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
# Changelog PWA - ObsiGate
|
||||||
|
|
||||||
|
## Version 1.5.0 - Support PWA Complet
|
||||||
|
|
||||||
|
### 🎉 Nouvelles Fonctionnalités
|
||||||
|
|
||||||
|
#### Progressive Web App (PWA)
|
||||||
|
- ✅ **Manifeste Web** (`manifest.json`) avec métadonnées complètes
|
||||||
|
- ✅ **Service Worker** (`sw.js`) pour le mode hors ligne et le cache
|
||||||
|
- ✅ **Icônes PWA** en multiples tailles (72px à 512px)
|
||||||
|
- ✅ **Installation native** sur desktop et mobile
|
||||||
|
- ✅ **Mode hors ligne** avec stratégies de cache intelligentes
|
||||||
|
- ✅ **Notifications de mise à jour** avec interface élégante
|
||||||
|
- ✅ **Raccourcis d'application** (recherche rapide)
|
||||||
|
|
||||||
|
#### Fichiers Ajoutés
|
||||||
|
|
||||||
|
**Frontend**
|
||||||
|
- `frontend/manifest.json` - Manifeste PWA
|
||||||
|
- `frontend/sw.js` - Service Worker
|
||||||
|
- `frontend/icons/` - Répertoire des icônes PWA (SVG)
|
||||||
|
- `icon-72x72.svg` à `icon-512x512.svg`
|
||||||
|
- `icon-192x192-maskable.svg`, `icon-512x512-maskable.svg`
|
||||||
|
- `search-96x96.svg`
|
||||||
|
- `README.md` - Guide de conversion des icônes
|
||||||
|
|
||||||
|
**Scripts**
|
||||||
|
- `generate_pwa_icons.py` - Générateur d'icônes PWA automatique
|
||||||
|
|
||||||
|
**Documentation**
|
||||||
|
- `PWA_GUIDE.md` - Guide complet d'utilisation PWA
|
||||||
|
- `PWA_CHANGELOG.md` - Ce fichier
|
||||||
|
|
||||||
|
#### Modifications Frontend
|
||||||
|
|
||||||
|
**index.html**
|
||||||
|
- Ajout des meta tags PWA (description, theme-color, mobile-web-app-capable)
|
||||||
|
- Ajout du lien vers le manifeste
|
||||||
|
- Ajout des icônes Apple Touch
|
||||||
|
- Ajout du favicon SVG
|
||||||
|
|
||||||
|
**app.js**
|
||||||
|
- Fonction `registerServiceWorker()` pour enregistrer le SW
|
||||||
|
- Fonction `showUpdateNotification()` pour les mises à jour
|
||||||
|
- Gestion de l'événement `beforeinstallprompt` pour l'installation
|
||||||
|
- Gestion de l'événement `appinstalled` avec notification toast
|
||||||
|
|
||||||
|
**style.css**
|
||||||
|
- Styles pour `.pwa-update-notification`
|
||||||
|
- Styles pour `.pwa-update-content`
|
||||||
|
- Styles pour les boutons de mise à jour
|
||||||
|
- Animation `slideInUp` pour les notifications
|
||||||
|
- Responsive mobile pour les notifications PWA
|
||||||
|
|
||||||
|
#### Modifications Backend
|
||||||
|
|
||||||
|
**main.py**
|
||||||
|
- Route `GET /sw.js` pour servir le service worker
|
||||||
|
- Headers: `Cache-Control: no-cache`, `Service-Worker-Allowed: /`
|
||||||
|
- Route `GET /manifest.json` pour servir le manifeste
|
||||||
|
- Headers: `Cache-Control: public, max-age=3600`
|
||||||
|
|
||||||
|
### 🔧 Configuration
|
||||||
|
|
||||||
|
#### Service Worker
|
||||||
|
|
||||||
|
**Stratégies de Cache**
|
||||||
|
- **Cache First** : Assets statiques (HTML, CSS, JS, icônes)
|
||||||
|
- **Network First** : API et données dynamiques
|
||||||
|
- **Fallback gracieux** : Affichage hors ligne élégant
|
||||||
|
|
||||||
|
**Gestion du Cache**
|
||||||
|
- Cache statique : `obsigate-v1.4.0-static`
|
||||||
|
- Cache dynamique : `obsigate-v1.4.0-dynamic` (max 50 entrées)
|
||||||
|
- Nettoyage automatique des anciens caches
|
||||||
|
- Vérification des mises à jour toutes les 60 secondes
|
||||||
|
|
||||||
|
**Exclusions**
|
||||||
|
- Endpoints SSE (`/api/events`)
|
||||||
|
- Endpoints d'authentification (`/api/auth/*`)
|
||||||
|
- Requêtes non-GET
|
||||||
|
|
||||||
|
#### Manifeste PWA
|
||||||
|
|
||||||
|
**Métadonnées**
|
||||||
|
- Nom : "ObsiGate"
|
||||||
|
- Description complète en français
|
||||||
|
- Thème : `#2563eb` (bleu)
|
||||||
|
- Background : `#1a1a1a` (sombre)
|
||||||
|
- Display : `standalone` (mode app)
|
||||||
|
- Orientation : `any`
|
||||||
|
|
||||||
|
**Icônes**
|
||||||
|
- 8 tailles régulières (72px à 512px)
|
||||||
|
- 2 icônes maskables (192px, 512px)
|
||||||
|
- Format : SVG (convertible en PNG)
|
||||||
|
|
||||||
|
**Raccourcis**
|
||||||
|
- Recherche : `/?action=search`
|
||||||
|
|
||||||
|
### 📱 Compatibilité
|
||||||
|
|
||||||
|
| Fonctionnalité | Chrome | Edge | Firefox | Safari | iOS Safari | Android |
|
||||||
|
|----------------|--------|------|---------|--------|------------|---------|
|
||||||
|
| Installation | ✅ | ✅ | ❌ | ⚠️ | ✅ | ✅ |
|
||||||
|
| Service Worker | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||||
|
| Mode Hors Ligne| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||||
|
| Notifications | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ |
|
||||||
|
| Raccourcis | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ |
|
||||||
|
|
||||||
|
### 🚀 Utilisation
|
||||||
|
|
||||||
|
#### Installation Desktop
|
||||||
|
1. Ouvrir ObsiGate dans Chrome/Edge
|
||||||
|
2. Cliquer sur l'icône d'installation dans la barre d'adresse
|
||||||
|
3. Confirmer l'installation
|
||||||
|
|
||||||
|
#### Installation Mobile (Android)
|
||||||
|
1. Ouvrir ObsiGate dans Chrome
|
||||||
|
2. Menu ⋮ → "Ajouter à l'écran d'accueil"
|
||||||
|
3. Confirmer
|
||||||
|
|
||||||
|
#### Installation iOS
|
||||||
|
1. Ouvrir ObsiGate dans Safari
|
||||||
|
2. Bouton Partager 📤
|
||||||
|
3. "Sur l'écran d'accueil"
|
||||||
|
4. Confirmer
|
||||||
|
|
||||||
|
### 🔍 Tests
|
||||||
|
|
||||||
|
#### Vérifications Effectuées
|
||||||
|
- ✅ Manifeste valide (DevTools → Application → Manifest)
|
||||||
|
- ✅ Service Worker enregistré (DevTools → Application → Service Workers)
|
||||||
|
- ✅ Cache fonctionnel (DevTools → Application → Cache Storage)
|
||||||
|
- ✅ Mode hors ligne opérationnel (DevTools → Network → Offline)
|
||||||
|
- ✅ Notifications de mise à jour
|
||||||
|
- ✅ Installation sur desktop (Chrome, Edge)
|
||||||
|
- ✅ Responsive design maintenu
|
||||||
|
|
||||||
|
#### Lighthouse Score
|
||||||
|
- PWA : 90-100/100 (attendu)
|
||||||
|
- Performance : Maintenu
|
||||||
|
- Accessibilité : Maintenu
|
||||||
|
- Best Practices : Maintenu
|
||||||
|
- SEO : Maintenu
|
||||||
|
|
||||||
|
### 📝 Notes de Migration
|
||||||
|
|
||||||
|
#### Pour les Utilisateurs Existants
|
||||||
|
- Aucune action requise
|
||||||
|
- Le PWA est optionnel
|
||||||
|
- L'application web fonctionne normalement sans installation
|
||||||
|
- Le service worker s'enregistre automatiquement
|
||||||
|
|
||||||
|
#### Pour les Développeurs
|
||||||
|
- Les icônes SVG peuvent être converties en PNG si nécessaire
|
||||||
|
- Le script `generate_pwa_icons.py` peut être personnalisé
|
||||||
|
- Le service worker peut être désactivé en commentant `registerServiceWorker()`
|
||||||
|
|
||||||
|
### 🐛 Problèmes Connus
|
||||||
|
|
||||||
|
- **Firefox Desktop** : Pas d'installation native (limitation du navigateur)
|
||||||
|
- **Safari Desktop** : Support PWA limité (limitation du navigateur)
|
||||||
|
- **iOS** : Pas de notifications push (limitation iOS)
|
||||||
|
|
||||||
|
### 🔜 Améliorations Futures
|
||||||
|
|
||||||
|
- [ ] Background Sync pour les modifications hors ligne
|
||||||
|
- [ ] Notifications push pour les mises à jour de vaults
|
||||||
|
- [ ] Cache prédictif basé sur l'historique
|
||||||
|
- [ ] Stratégies de cache configurables
|
||||||
|
- [ ] Support des screenshots dans le manifeste
|
||||||
|
- [ ] Conversion automatique SVG → PNG au build
|
||||||
|
|
||||||
|
### 📚 Documentation
|
||||||
|
|
||||||
|
- `PWA_GUIDE.md` - Guide complet d'utilisation et de configuration
|
||||||
|
- `frontend/icons/README.md` - Instructions de conversion des icônes
|
||||||
|
- Commentaires inline dans `sw.js` et `app.js`
|
||||||
|
|
||||||
|
### 🙏 Remerciements
|
||||||
|
|
||||||
|
Merci à la communauté PWA pour les standards et bonnes pratiques.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**ObsiGate v1.5.0** - Maintenant disponible en Progressive Web App ! 🎉
|
||||||
343
docs/PWA_GUIDE.md
Normal file
343
docs/PWA_GUIDE.md
Normal file
@ -0,0 +1,343 @@
|
|||||||
|
# Guide PWA - ObsiGate
|
||||||
|
|
||||||
|
ObsiGate est maintenant une **Progressive Web App (PWA)** complète, offrant une expérience d'application native sur tous les appareils.
|
||||||
|
|
||||||
|
## 🎯 Qu'est-ce qu'une PWA ?
|
||||||
|
|
||||||
|
Une Progressive Web App combine le meilleur du web et des applications natives :
|
||||||
|
- **Installation** : Installez ObsiGate sur votre appareil comme une application native
|
||||||
|
- **Mode hors ligne** : Accédez à vos notes même sans connexion internet
|
||||||
|
- **Notifications** : Recevez des alertes de mise à jour
|
||||||
|
- **Performance** : Chargement rapide grâce au cache intelligent
|
||||||
|
- **Multi-plateforme** : Fonctionne sur desktop, mobile et tablette
|
||||||
|
|
||||||
|
## 📱 Installation
|
||||||
|
|
||||||
|
### Sur Desktop (Chrome, Edge, Brave)
|
||||||
|
|
||||||
|
1. Ouvrez ObsiGate dans votre navigateur
|
||||||
|
2. Cliquez sur l'icône d'installation dans la barre d'adresse (➕ ou ⬇️)
|
||||||
|
3. Cliquez sur "Installer" dans la popup
|
||||||
|
4. ObsiGate apparaît maintenant dans vos applications
|
||||||
|
|
||||||
|
**Alternative** : Menu ⋮ → "Installer ObsiGate..."
|
||||||
|
|
||||||
|
### Sur Android
|
||||||
|
|
||||||
|
1. Ouvrez ObsiGate dans Chrome
|
||||||
|
2. Appuyez sur le menu ⋮ (trois points)
|
||||||
|
3. Sélectionnez "Ajouter à l'écran d'accueil"
|
||||||
|
4. Confirmez l'installation
|
||||||
|
5. L'icône ObsiGate apparaît sur votre écran d'accueil
|
||||||
|
|
||||||
|
### Sur iOS/iPadOS (Safari)
|
||||||
|
|
||||||
|
1. Ouvrez ObsiGate dans Safari
|
||||||
|
2. Appuyez sur le bouton Partager 📤
|
||||||
|
3. Faites défiler et sélectionnez "Sur l'écran d'accueil"
|
||||||
|
4. Nommez l'application et appuyez sur "Ajouter"
|
||||||
|
5. ObsiGate apparaît sur votre écran d'accueil
|
||||||
|
|
||||||
|
## ⚡ Fonctionnalités PWA
|
||||||
|
|
||||||
|
### Mode Hors Ligne
|
||||||
|
|
||||||
|
Le service worker met en cache :
|
||||||
|
- **Interface utilisateur** : HTML, CSS, JavaScript
|
||||||
|
- **Ressources statiques** : Icônes, polices
|
||||||
|
- **Contenu API** : Dernières données consultées
|
||||||
|
|
||||||
|
**Stratégies de cache** :
|
||||||
|
- **Cache First** : Assets statiques (interface)
|
||||||
|
- **Network First** : API et données dynamiques
|
||||||
|
- **Fallback** : Affichage gracieux en cas d'erreur
|
||||||
|
|
||||||
|
### Mises à Jour Automatiques
|
||||||
|
|
||||||
|
- Vérification des mises à jour toutes les minutes
|
||||||
|
- Notification élégante quand une nouvelle version est disponible
|
||||||
|
- Mise à jour en un clic sans perte de données
|
||||||
|
|
||||||
|
### Raccourcis d'Application
|
||||||
|
|
||||||
|
Accès rapide aux fonctionnalités depuis l'icône :
|
||||||
|
- **Recherche** : Ouvre directement la recherche
|
||||||
|
|
||||||
|
## 🛠️ Configuration Technique
|
||||||
|
|
||||||
|
### Fichiers PWA
|
||||||
|
|
||||||
|
```
|
||||||
|
ObsiGate/
|
||||||
|
├── frontend/
|
||||||
|
│ ├── manifest.json # Manifeste PWA
|
||||||
|
│ ├── sw.js # Service Worker
|
||||||
|
│ ├── icons/ # Icônes PWA
|
||||||
|
│ │ ├── icon-72x72.svg
|
||||||
|
│ │ ├── icon-192x192.svg
|
||||||
|
│ │ ├── icon-512x512.svg
|
||||||
|
│ │ └── ...
|
||||||
|
│ ├── index.html # Meta tags PWA
|
||||||
|
│ ├── app.js # Enregistrement SW
|
||||||
|
│ └── style.css # Styles PWA
|
||||||
|
└── generate_pwa_icons.py # Générateur d'icônes
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manifeste (manifest.json)
|
||||||
|
|
||||||
|
Définit les métadonnées de l'application :
|
||||||
|
- Nom et description
|
||||||
|
- Icônes (multiples tailles)
|
||||||
|
- Couleurs de thème
|
||||||
|
- Mode d'affichage (standalone)
|
||||||
|
- Raccourcis d'application
|
||||||
|
|
||||||
|
### Service Worker (sw.js)
|
||||||
|
|
||||||
|
Gère le cache et le mode hors ligne :
|
||||||
|
- **Cache statique** : Interface et assets
|
||||||
|
- **Cache dynamique** : Données API (max 50 entrées)
|
||||||
|
- **Stratégies** : Cache-first et Network-first
|
||||||
|
- **Nettoyage** : Suppression automatique des anciens caches
|
||||||
|
|
||||||
|
### Icônes PWA
|
||||||
|
|
||||||
|
Tailles supportées :
|
||||||
|
- **72x72** : Favicon, petites icônes
|
||||||
|
- **96x96** : Raccourcis
|
||||||
|
- **128x128, 144x144, 152x152** : Appareils mobiles
|
||||||
|
- **192x192** : Android home screen (standard)
|
||||||
|
- **384x384** : Haute résolution
|
||||||
|
- **512x512** : Splash screens, maskable icons
|
||||||
|
|
||||||
|
**Maskable icons** : Icônes adaptatives avec safe zone pour Android
|
||||||
|
|
||||||
|
## 🔧 Génération des Icônes
|
||||||
|
|
||||||
|
### Utilisation du Script
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Générer les icônes SVG
|
||||||
|
python generate_pwa_icons.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Le script crée :
|
||||||
|
- Icônes régulières (toutes tailles)
|
||||||
|
- Icônes maskables (192x192, 512x512)
|
||||||
|
- Icône de recherche (96x96)
|
||||||
|
- README avec instructions de conversion
|
||||||
|
|
||||||
|
### Conversion SVG → PNG (Production)
|
||||||
|
|
||||||
|
**Option 1 : ImageMagick**
|
||||||
|
```bash
|
||||||
|
cd frontend/icons
|
||||||
|
for file in *.svg; do
|
||||||
|
size=$(echo $file | grep -oP '\d+x\d+' | head -1 | cut -d'x' -f1)
|
||||||
|
convert -background none -resize ${size}x${size} "$file" "${file%.svg}.png"
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
**Option 2 : Inkscape**
|
||||||
|
```bash
|
||||||
|
cd frontend/icons
|
||||||
|
for file in *.svg; do
|
||||||
|
size=$(echo $file | grep -oP '\d+x\d+' | head -1 | cut -d'x' -f1)
|
||||||
|
inkscape "$file" --export-filename="${file%.svg}.png" --export-width=$size
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
**Option 3 : Outils en ligne**
|
||||||
|
- https://cloudconvert.com/svg-to-png
|
||||||
|
- https://convertio.co/svg-png/
|
||||||
|
|
||||||
|
**Note** : Les navigateurs modernes supportent les SVG directement, la conversion PNG est optionnelle.
|
||||||
|
|
||||||
|
## 🎨 Personnalisation
|
||||||
|
|
||||||
|
### Modifier les Couleurs
|
||||||
|
|
||||||
|
Éditez `frontend/manifest.json` :
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"theme_color": "#2563eb", // Couleur de la barre d'état
|
||||||
|
"background_color": "#1a1a1a" // Couleur de fond au lancement
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Modifier les Icônes
|
||||||
|
|
||||||
|
1. Éditez `generate_pwa_icons.py`
|
||||||
|
2. Modifiez les fonctions `create_svg_icon()` et `create_maskable_svg_icon()`
|
||||||
|
3. Régénérez : `python generate_pwa_icons.py`
|
||||||
|
|
||||||
|
### Ajouter des Raccourcis
|
||||||
|
|
||||||
|
Éditez `frontend/manifest.json` :
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"shortcuts": [
|
||||||
|
{
|
||||||
|
"name": "Nouvelle Note",
|
||||||
|
"url": "/?action=new",
|
||||||
|
"icons": [{"src": "/static/icons/new-96x96.png", "sizes": "96x96"}]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔍 Débogage
|
||||||
|
|
||||||
|
### Vérifier l'Installation PWA
|
||||||
|
|
||||||
|
**Chrome DevTools** :
|
||||||
|
1. Ouvrez DevTools (F12)
|
||||||
|
2. Onglet "Application"
|
||||||
|
3. Section "Manifest" : Vérifiez les métadonnées
|
||||||
|
4. Section "Service Workers" : Vérifiez l'enregistrement
|
||||||
|
5. Section "Cache Storage" : Inspectez le cache
|
||||||
|
|
||||||
|
### Tester le Mode Hors Ligne
|
||||||
|
|
||||||
|
1. DevTools → Onglet "Network"
|
||||||
|
2. Cochez "Offline"
|
||||||
|
3. Rechargez la page
|
||||||
|
4. L'application doit fonctionner avec les données en cache
|
||||||
|
|
||||||
|
### Logs du Service Worker
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Dans la console du navigateur
|
||||||
|
navigator.serviceWorker.getRegistration().then(reg => {
|
||||||
|
console.log('Service Worker:', reg);
|
||||||
|
console.log('Active:', reg.active);
|
||||||
|
console.log('Waiting:', reg.waiting);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Forcer la Mise à Jour
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Dans la console
|
||||||
|
navigator.serviceWorker.getRegistration().then(reg => {
|
||||||
|
reg.update();
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Désinstaller le Service Worker
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Dans la console
|
||||||
|
navigator.serviceWorker.getRegistrations().then(registrations => {
|
||||||
|
registrations.forEach(reg => reg.unregister());
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📊 Métriques PWA
|
||||||
|
|
||||||
|
### Lighthouse Audit
|
||||||
|
|
||||||
|
1. Chrome DevTools → Onglet "Lighthouse"
|
||||||
|
2. Sélectionnez "Progressive Web App"
|
||||||
|
3. Cliquez sur "Generate report"
|
||||||
|
|
||||||
|
**Critères évalués** :
|
||||||
|
- ✅ Manifeste valide
|
||||||
|
- ✅ Service Worker enregistré
|
||||||
|
- ✅ HTTPS (ou localhost)
|
||||||
|
- ✅ Icônes appropriées
|
||||||
|
- ✅ Responsive design
|
||||||
|
- ✅ Mode hors ligne
|
||||||
|
|
||||||
|
### Score Attendu
|
||||||
|
|
||||||
|
ObsiGate devrait obtenir **90-100/100** sur l'audit PWA.
|
||||||
|
|
||||||
|
## 🚀 Déploiement
|
||||||
|
|
||||||
|
### Prérequis
|
||||||
|
|
||||||
|
- **HTTPS obligatoire** en production (sauf localhost)
|
||||||
|
- Service Worker nécessite une connexion sécurisée
|
||||||
|
|
||||||
|
### Configuration Reverse Proxy
|
||||||
|
|
||||||
|
**Nginx** :
|
||||||
|
```nginx
|
||||||
|
location /sw.js {
|
||||||
|
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
||||||
|
add_header Service-Worker-Allowed "/";
|
||||||
|
proxy_pass http://obsigate:8080;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /manifest.json {
|
||||||
|
add_header Cache-Control "public, max-age=3600";
|
||||||
|
proxy_pass http://obsigate:8080;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Traefik** :
|
||||||
|
```yaml
|
||||||
|
http:
|
||||||
|
middlewares:
|
||||||
|
sw-headers:
|
||||||
|
headers:
|
||||||
|
customResponseHeaders:
|
||||||
|
Cache-Control: "no-cache, no-store, must-revalidate"
|
||||||
|
Service-Worker-Allowed: "/"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔒 Sécurité
|
||||||
|
|
||||||
|
### Content Security Policy
|
||||||
|
|
||||||
|
Le service worker respecte la CSP définie dans le backend :
|
||||||
|
- Scripts : `'self'` + CDN autorisés
|
||||||
|
- Styles : `'self'` + CDN autorisés
|
||||||
|
- Images : `'self'` + data URIs
|
||||||
|
|
||||||
|
### Permissions
|
||||||
|
|
||||||
|
PWA installée demande les mêmes permissions que le site web :
|
||||||
|
- Aucune permission supplémentaire requise
|
||||||
|
- Notifications : optionnelles (désactivées par défaut)
|
||||||
|
|
||||||
|
## 📱 Compatibilité
|
||||||
|
|
||||||
|
| Plateforme | Support | Notes |
|
||||||
|
|------------|---------|-------|
|
||||||
|
| Chrome Desktop | ✅ Complet | Installation native |
|
||||||
|
| Edge Desktop | ✅ Complet | Installation native |
|
||||||
|
| Firefox Desktop | ⚠️ Partiel | Pas d'installation, SW fonctionne |
|
||||||
|
| Safari Desktop | ⚠️ Partiel | Support limité |
|
||||||
|
| Chrome Android | ✅ Complet | Installation + notifications |
|
||||||
|
| Safari iOS | ✅ Complet | "Add to Home Screen" |
|
||||||
|
| Samsung Internet | ✅ Complet | Installation native |
|
||||||
|
|
||||||
|
## 🎓 Ressources
|
||||||
|
|
||||||
|
- [MDN - Progressive Web Apps](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps)
|
||||||
|
- [web.dev - PWA](https://web.dev/progressive-web-apps/)
|
||||||
|
- [PWA Builder](https://www.pwabuilder.com/)
|
||||||
|
- [Workbox (Google)](https://developers.google.com/web/tools/workbox)
|
||||||
|
|
||||||
|
## ❓ FAQ
|
||||||
|
|
||||||
|
**Q : Puis-je utiliser ObsiGate sans l'installer ?**
|
||||||
|
R : Oui, l'installation est optionnelle. Le site web fonctionne normalement.
|
||||||
|
|
||||||
|
**Q : Les données sont-elles synchronisées hors ligne ?**
|
||||||
|
R : Non, le mode hors ligne utilise le cache local. Les modifications nécessitent une connexion.
|
||||||
|
|
||||||
|
**Q : Comment désinstaller l'application ?**
|
||||||
|
R : Desktop : Clic droit sur l'icône → "Désinstaller". Mobile : Maintenez l'icône → "Supprimer".
|
||||||
|
|
||||||
|
**Q : Le cache prend-il beaucoup d'espace ?**
|
||||||
|
R : Non, le cache est limité à ~50 entrées dynamiques + assets statiques (~5-10 MB).
|
||||||
|
|
||||||
|
**Q : Puis-je désactiver le service worker ?**
|
||||||
|
R : Oui, supprimez l'enregistrement dans DevTools ou commentez `registerServiceWorker()` dans `app.js`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**ObsiGate PWA** - Vos notes Obsidian, partout, tout le temps. 📖✨
|
||||||
255
docs/PWA_SUMMARY.md
Normal file
255
docs/PWA_SUMMARY.md
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
# Résumé - ObsiGate PWA
|
||||||
|
|
||||||
|
## ✅ Transformation Réussie en Progressive Web App
|
||||||
|
|
||||||
|
ObsiGate est maintenant une **Progressive Web App (PWA)** complète et fonctionnelle.
|
||||||
|
|
||||||
|
### 📦 Fichiers Créés
|
||||||
|
|
||||||
|
```
|
||||||
|
ObsiGate/
|
||||||
|
├── frontend/
|
||||||
|
│ ├── manifest.json ✅ Manifeste PWA
|
||||||
|
│ ├── sw.js ✅ Service Worker
|
||||||
|
│ ├── icons/ ✅ Icônes PWA (11 fichiers SVG)
|
||||||
|
│ │ ├── icon-72x72.svg
|
||||||
|
│ │ ├── icon-96x96.svg
|
||||||
|
│ │ ├── icon-128x128.svg
|
||||||
|
│ │ ├── icon-144x144.svg
|
||||||
|
│ │ ├── icon-152x152.svg
|
||||||
|
│ │ ├── icon-192x192.svg
|
||||||
|
│ │ ├── icon-384x384.svg
|
||||||
|
│ │ ├── icon-512x512.svg
|
||||||
|
│ │ ├── icon-192x192-maskable.svg
|
||||||
|
│ │ ├── icon-512x512-maskable.svg
|
||||||
|
│ │ ├── search-96x96.svg
|
||||||
|
│ │ └── README.md
|
||||||
|
│ ├── index.html ✅ Modifié (meta tags PWA)
|
||||||
|
│ ├── app.js ✅ Modifié (enregistrement SW)
|
||||||
|
│ └── style.css ✅ Modifié (styles notifications)
|
||||||
|
├── backend/
|
||||||
|
│ └── main.py ✅ Modifié (routes SW et manifeste)
|
||||||
|
├── generate_pwa_icons.py ✅ Script de génération d'icônes
|
||||||
|
├── PWA_GUIDE.md ✅ Guide complet PWA
|
||||||
|
├── PWA_CHANGELOG.md ✅ Changelog détaillé
|
||||||
|
└── PWA_SUMMARY.md ✅ Ce fichier
|
||||||
|
```
|
||||||
|
|
||||||
|
### 🎯 Fonctionnalités Implémentées
|
||||||
|
|
||||||
|
#### 1. Manifeste Web (`manifest.json`)
|
||||||
|
- ✅ Métadonnées complètes (nom, description, icônes)
|
||||||
|
- ✅ Configuration d'affichage (standalone)
|
||||||
|
- ✅ Couleurs de thème (#2563eb)
|
||||||
|
- ✅ Raccourcis d'application (recherche)
|
||||||
|
- ✅ Icônes adaptatives (maskable)
|
||||||
|
|
||||||
|
#### 2. Service Worker (`sw.js`)
|
||||||
|
- ✅ Cache statique (interface utilisateur)
|
||||||
|
- ✅ Cache dynamique (données API, max 50 entrées)
|
||||||
|
- ✅ Stratégie Cache-First pour assets statiques
|
||||||
|
- ✅ Stratégie Network-First pour API
|
||||||
|
- ✅ Gestion des mises à jour automatiques
|
||||||
|
- ✅ Nettoyage automatique des anciens caches
|
||||||
|
- ✅ Support des notifications push (préparé)
|
||||||
|
- ✅ Background sync (préparé)
|
||||||
|
|
||||||
|
#### 3. Interface Utilisateur
|
||||||
|
- ✅ Meta tags PWA dans `<head>`
|
||||||
|
- ✅ Enregistrement automatique du service worker
|
||||||
|
- ✅ Notification élégante des mises à jour
|
||||||
|
- ✅ Gestion de l'événement d'installation
|
||||||
|
- ✅ Toast de confirmation d'installation
|
||||||
|
- ✅ Styles responsive pour notifications
|
||||||
|
|
||||||
|
#### 4. Backend
|
||||||
|
- ✅ Route `/sw.js` avec headers appropriés
|
||||||
|
- ✅ Route `/manifest.json` avec cache
|
||||||
|
- ✅ Service des icônes via `/static/icons/`
|
||||||
|
|
||||||
|
#### 5. Génération d'Icônes
|
||||||
|
- ✅ Script Python automatisé
|
||||||
|
- ✅ Création de 8 tailles régulières
|
||||||
|
- ✅ Création de 2 icônes maskables
|
||||||
|
- ✅ Icône de recherche pour raccourcis
|
||||||
|
- ✅ Documentation de conversion SVG→PNG
|
||||||
|
|
||||||
|
### 🚀 Utilisation
|
||||||
|
|
||||||
|
#### Installation Rapide
|
||||||
|
|
||||||
|
**Desktop (Chrome/Edge)**
|
||||||
|
```
|
||||||
|
1. Ouvrir ObsiGate
|
||||||
|
2. Cliquer sur l'icône d'installation (barre d'adresse)
|
||||||
|
3. Confirmer
|
||||||
|
```
|
||||||
|
|
||||||
|
**Android**
|
||||||
|
```
|
||||||
|
1. Ouvrir ObsiGate dans Chrome
|
||||||
|
2. Menu ⋮ → "Ajouter à l'écran d'accueil"
|
||||||
|
3. Confirmer
|
||||||
|
```
|
||||||
|
|
||||||
|
**iOS**
|
||||||
|
```
|
||||||
|
1. Ouvrir ObsiGate dans Safari
|
||||||
|
2. Bouton Partager 📤
|
||||||
|
3. "Sur l'écran d'accueil"
|
||||||
|
4. Confirmer
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Génération des Icônes
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Générer les icônes SVG
|
||||||
|
python generate_pwa_icons.py
|
||||||
|
|
||||||
|
# Optionnel : Convertir en PNG (production)
|
||||||
|
cd frontend/icons
|
||||||
|
# Voir frontend/icons/README.md pour les commandes
|
||||||
|
```
|
||||||
|
|
||||||
|
### 🔍 Vérification
|
||||||
|
|
||||||
|
#### Checklist PWA
|
||||||
|
|
||||||
|
- ✅ Manifeste valide et accessible
|
||||||
|
- ✅ Service Worker enregistré
|
||||||
|
- ✅ Icônes multiples tailles (72px à 512px)
|
||||||
|
- ✅ HTTPS ou localhost
|
||||||
|
- ✅ Mode hors ligne fonctionnel
|
||||||
|
- ✅ Responsive design
|
||||||
|
- ✅ Meta tags appropriés
|
||||||
|
- ✅ Thème cohérent
|
||||||
|
|
||||||
|
#### Tests à Effectuer
|
||||||
|
|
||||||
|
1. **Manifeste** : DevTools → Application → Manifest
|
||||||
|
2. **Service Worker** : DevTools → Application → Service Workers
|
||||||
|
3. **Cache** : DevTools → Application → Cache Storage
|
||||||
|
4. **Hors Ligne** : DevTools → Network → Offline
|
||||||
|
5. **Installation** : Icône dans la barre d'adresse
|
||||||
|
6. **Lighthouse** : Audit PWA (score attendu : 90-100)
|
||||||
|
|
||||||
|
### 📊 Compatibilité
|
||||||
|
|
||||||
|
| Plateforme | Installation | Mode Hors Ligne | Notifications |
|
||||||
|
|------------|--------------|-----------------|---------------|
|
||||||
|
| Chrome Desktop | ✅ | ✅ | ✅ |
|
||||||
|
| Edge Desktop | ✅ | ✅ | ✅ |
|
||||||
|
| Firefox Desktop | ❌ | ✅ | ✅ |
|
||||||
|
| Safari Desktop | ⚠️ | ✅ | ❌ |
|
||||||
|
| Chrome Android | ✅ | ✅ | ✅ |
|
||||||
|
| Safari iOS | ✅ | ✅ | ❌ |
|
||||||
|
|
||||||
|
### 🎨 Personnalisation
|
||||||
|
|
||||||
|
#### Modifier les Couleurs
|
||||||
|
|
||||||
|
**Fichier** : `frontend/manifest.json`
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"theme_color": "#2563eb", // Barre d'état
|
||||||
|
"background_color": "#1a1a1a" // Fond au lancement
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Modifier les Icônes
|
||||||
|
|
||||||
|
**Fichier** : `generate_pwa_icons.py`
|
||||||
|
```python
|
||||||
|
# Éditer les fonctions :
|
||||||
|
# - create_svg_icon()
|
||||||
|
# - create_maskable_svg_icon()
|
||||||
|
# Puis régénérer : python generate_pwa_icons.py
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Ajouter des Raccourcis
|
||||||
|
|
||||||
|
**Fichier** : `frontend/manifest.json`
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"shortcuts": [
|
||||||
|
{
|
||||||
|
"name": "Recherche",
|
||||||
|
"url": "/?action=search",
|
||||||
|
"icons": [{"src": "/static/icons/search-96x96.svg", "sizes": "96x96"}]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 🔧 Configuration Avancée
|
||||||
|
|
||||||
|
#### Stratégies de Cache
|
||||||
|
|
||||||
|
**Cache First** (assets statiques)
|
||||||
|
- Interface : HTML, CSS, JS
|
||||||
|
- Icônes et polices
|
||||||
|
- Fallback rapide
|
||||||
|
|
||||||
|
**Network First** (données dynamiques)
|
||||||
|
- API endpoints
|
||||||
|
- Contenu des vaults
|
||||||
|
- Fallback sur cache si hors ligne
|
||||||
|
|
||||||
|
#### Exclusions du Cache
|
||||||
|
|
||||||
|
- Endpoints SSE (`/api/events`)
|
||||||
|
- Endpoints d'authentification (`/api/auth/*`)
|
||||||
|
- Requêtes non-GET
|
||||||
|
|
||||||
|
### 📚 Documentation
|
||||||
|
|
||||||
|
- **`PWA_GUIDE.md`** : Guide complet d'utilisation et configuration
|
||||||
|
- **`PWA_CHANGELOG.md`** : Changelog détaillé des modifications
|
||||||
|
- **`frontend/icons/README.md`** : Instructions de conversion des icônes
|
||||||
|
- **Commentaires inline** : Dans `sw.js` et `app.js`
|
||||||
|
|
||||||
|
### 🐛 Dépannage
|
||||||
|
|
||||||
|
#### Le Service Worker ne s'enregistre pas
|
||||||
|
```javascript
|
||||||
|
// Console navigateur
|
||||||
|
navigator.serviceWorker.getRegistration()
|
||||||
|
.then(reg => console.log('SW:', reg))
|
||||||
|
.catch(err => console.error('Erreur:', err));
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Forcer la Mise à Jour
|
||||||
|
```javascript
|
||||||
|
// Console navigateur
|
||||||
|
navigator.serviceWorker.getRegistration()
|
||||||
|
.then(reg => reg.update());
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Vider le Cache
|
||||||
|
```javascript
|
||||||
|
// Console navigateur
|
||||||
|
caches.keys().then(keys =>
|
||||||
|
Promise.all(keys.map(key => caches.delete(key)))
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### ✨ Prochaines Étapes
|
||||||
|
|
||||||
|
1. **Tester l'installation** sur différents appareils
|
||||||
|
2. **Vérifier le mode hors ligne** avec DevTools
|
||||||
|
3. **Lancer un audit Lighthouse** pour valider le score PWA
|
||||||
|
4. **Optionnel** : Convertir les icônes SVG en PNG pour une meilleure compatibilité
|
||||||
|
5. **Déployer** avec HTTPS pour activer toutes les fonctionnalités PWA
|
||||||
|
|
||||||
|
### 🎉 Résultat
|
||||||
|
|
||||||
|
ObsiGate est maintenant une **Progressive Web App complète** offrant :
|
||||||
|
- 📱 Installation native sur tous les appareils
|
||||||
|
- 🔌 Mode hors ligne fonctionnel
|
||||||
|
- ⚡ Performance optimisée avec cache intelligent
|
||||||
|
- 🔄 Mises à jour automatiques avec notifications
|
||||||
|
- 🎨 Expérience utilisateur native
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**ObsiGate v1.5.0 PWA** - Vos notes Obsidian, partout, tout le temps ! 📖✨
|
||||||
133
docs/README_PWA.md
Normal file
133
docs/README_PWA.md
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
# 📱 ObsiGate PWA - Progressive Web App
|
||||||
|
|
||||||
|
> **ObsiGate est maintenant une Progressive Web App complète !**
|
||||||
|
|
||||||
|
## 🎯 Qu'est-ce qui a changé ?
|
||||||
|
|
||||||
|
ObsiGate peut maintenant être **installé comme une application native** sur votre ordinateur, smartphone ou tablette, et fonctionne **même hors ligne**.
|
||||||
|
|
||||||
|
## ✨ Nouvelles Fonctionnalités
|
||||||
|
|
||||||
|
### 📲 Installation Native
|
||||||
|
- **Desktop** : Installez ObsiGate comme une application Windows/Mac/Linux
|
||||||
|
- **Mobile** : Ajoutez ObsiGate à votre écran d'accueil Android/iOS
|
||||||
|
- **Tablette** : Expérience optimisée sur iPad et tablettes Android
|
||||||
|
|
||||||
|
### 🔌 Mode Hors Ligne
|
||||||
|
- Accédez à vos notes même sans connexion internet
|
||||||
|
- Cache intelligent des dernières données consultées
|
||||||
|
- Synchronisation automatique au retour en ligne
|
||||||
|
|
||||||
|
### ⚡ Performance Améliorée
|
||||||
|
- Chargement instantané grâce au cache
|
||||||
|
- Réduction de la consommation de données
|
||||||
|
- Interface ultra-réactive
|
||||||
|
|
||||||
|
### 🔔 Mises à Jour Automatiques
|
||||||
|
- Vérification automatique des nouvelles versions
|
||||||
|
- Notification élégante quand une mise à jour est disponible
|
||||||
|
- Installation en un clic sans perte de données
|
||||||
|
|
||||||
|
## 🚀 Installation Rapide
|
||||||
|
|
||||||
|
### Sur Desktop (Chrome, Edge, Brave)
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Ouvrez ObsiGate dans votre navigateur
|
||||||
|
2. Cliquez sur l'icône ➕ dans la barre d'adresse
|
||||||
|
3. Cliquez sur "Installer"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Sur Android
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Ouvrez ObsiGate dans Chrome
|
||||||
|
2. Menu ⋮ → "Ajouter à l'écran d'accueil"
|
||||||
|
3. Confirmez l'installation
|
||||||
|
```
|
||||||
|
|
||||||
|
### Sur iOS/iPadOS
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Ouvrez ObsiGate dans Safari
|
||||||
|
2. Bouton Partager 📤
|
||||||
|
3. "Sur l'écran d'accueil"
|
||||||
|
4. Confirmez
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📦 Fichiers PWA Ajoutés
|
||||||
|
|
||||||
|
```
|
||||||
|
ObsiGate/
|
||||||
|
├── frontend/
|
||||||
|
│ ├── manifest.json # Manifeste PWA
|
||||||
|
│ ├── sw.js # Service Worker
|
||||||
|
│ └── icons/ # Icônes (11 fichiers)
|
||||||
|
├── generate_pwa_icons.py # Générateur d'icônes
|
||||||
|
├── PWA_GUIDE.md # Guide complet
|
||||||
|
├── PWA_CHANGELOG.md # Changelog détaillé
|
||||||
|
├── PWA_SUMMARY.md # Résumé technique
|
||||||
|
├── INSTALLATION_PWA.md # Guide installation
|
||||||
|
└── MODIFICATIONS_PWA.txt # Liste des modifications
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔍 Vérification
|
||||||
|
|
||||||
|
Pour vérifier que le PWA fonctionne :
|
||||||
|
|
||||||
|
1. Ouvrez **DevTools** (F12)
|
||||||
|
2. Onglet **"Application"**
|
||||||
|
3. Vérifiez :
|
||||||
|
- ✅ **Manifest** : Métadonnées ObsiGate
|
||||||
|
- ✅ **Service Workers** : SW actif
|
||||||
|
- ✅ **Cache Storage** : Caches présents
|
||||||
|
|
||||||
|
## 📚 Documentation
|
||||||
|
|
||||||
|
- **[PWA_GUIDE.md](PWA_GUIDE.md)** - Guide complet d'utilisation
|
||||||
|
- **[INSTALLATION_PWA.md](INSTALLATION_PWA.md)** - Installation rapide
|
||||||
|
- **[PWA_CHANGELOG.md](PWA_CHANGELOG.md)** - Changelog détaillé
|
||||||
|
- **[PWA_SUMMARY.md](PWA_SUMMARY.md)** - Résumé technique
|
||||||
|
|
||||||
|
## 🎨 Personnalisation
|
||||||
|
|
||||||
|
### Modifier les couleurs
|
||||||
|
|
||||||
|
Éditez `frontend/manifest.json` :
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"theme_color": "#2563eb",
|
||||||
|
"background_color": "#1a1a1a"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Régénérer les icônes
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python generate_pwa_icons.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🌐 Compatibilité
|
||||||
|
|
||||||
|
| Plateforme | Installation | Hors Ligne |
|
||||||
|
|------------|--------------|------------|
|
||||||
|
| Chrome Desktop | ✅ | ✅ |
|
||||||
|
| Edge Desktop | ✅ | ✅ |
|
||||||
|
| Firefox Desktop | ⚠️ | ✅ |
|
||||||
|
| Safari Desktop | ⚠️ | ✅ |
|
||||||
|
| Chrome Android | ✅ | ✅ |
|
||||||
|
| Safari iOS | ✅ | ✅ |
|
||||||
|
|
||||||
|
## 🎉 Résultat
|
||||||
|
|
||||||
|
ObsiGate offre maintenant :
|
||||||
|
- 📱 Expérience d'application native
|
||||||
|
- 🔌 Fonctionnement hors ligne
|
||||||
|
- ⚡ Performance optimale
|
||||||
|
- 🔄 Mises à jour automatiques
|
||||||
|
- 🌍 Multi-plateforme
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**ObsiGate v1.5.0 PWA** - Vos notes Obsidian, partout, tout le temps ! 📖✨
|
||||||
72
docs/ROADMAP.md
Normal file
72
docs/ROADMAP.md
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
# ObsiGate — Roadmap
|
||||||
|
|
||||||
|
> **Date :** 2026-05-25 | **Version :** 1.4.0 / 1.5.0
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Légende
|
||||||
|
|
||||||
|
- ✅ Complété
|
||||||
|
- 🟡 En cours / Partiel / À investiguer
|
||||||
|
- ⬜ À faire
|
||||||
|
- 🔴 Critique
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Nouvelles fonctionnalités (historique TODO.md)
|
||||||
|
|
||||||
|
- ✅ **Indexation incrémentale automatique** — Le watcher détecte les nouveaux fichiers et met à jour l'index sans réindexation complète. Utilise `_on_vault_change` → `update_single_file` / `remove_single_file` / `handle_file_move`.
|
||||||
|
- ✅ **Copier le chemin** — Option "Copier le chemin" dans le menu contextuel (clic droit) de l'arborescence pour tout élément (vault, dossier, fichier).
|
||||||
|
- ✅ **Panneau À propos** — Section "À propos" dans le modal Configurations affichant la version, la version API, les stats de santé.
|
||||||
|
- ✅ **Vue Graphique** — Canvas force-directed accessible via menu contextuel sur les vaults et dossiers. Affiche nœuds (fichiers/dossiers) et arêtes (parent + wikilinks). Zoom/pan interactif.
|
||||||
|
- ✅ **Mode onglets (Tabs)** — Barre d'onglets multi-fichiers permettant de visualiser plusieurs fichiers simultanément, avec fermeture et navigation.
|
||||||
|
- ✅ **Login Popout** — La fenêtre popout affiche un formulaire de connexion quand l'authentification est requise, puis recharge la page après login.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Corrections (historique TODO.md)
|
||||||
|
|
||||||
|
- ✅ **Login popout avec redirection** — Quand un fichier est ouvert via l'URL popout et que l'authentification est requise, un formulaire de login est proposé. Après connexion réussie, la page recharge automatiquement.
|
||||||
|
- 🟡 **Correction TOC — scroll avec caractères accentués** — Le clic sur un titre dans la table des matières ne fonctionne pas toujours pour les titres contenant des lettres accentuées. Les fonctions slugify (frontend) et _heading_slugify (backend) utilisent des normalisations Unicode qui peuvent diverger pour certains caractères (ex: œ, æ). **À corriger :** unifier l'algorithme + ajouter un fallback `scrollIntoView`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Améliorations prioritaires (voir ANALYSE_REVIEW.md §4)
|
||||||
|
|
||||||
|
### 🔴 Sécurité — P0
|
||||||
|
|
||||||
|
- 🔴 **Masquage automatique des secrets** — Implémenter un `SecretRedactor` pour masquer les clés API, tokens, et mots de passe dans les aperçus de contenu (preview RÉCENT, dashboard, vue rendu).
|
||||||
|
- 🔴 **Rate limiting sur le login** — 5 tentatives max par IP sur 15 minutes, blocage après 10 échecs.
|
||||||
|
|
||||||
|
### 🟠 Robustesse — P1
|
||||||
|
|
||||||
|
- 🟠 **Log d'audit** — Tracer les écritures, suppressions, et changements de config dans `data/audit.log`.
|
||||||
|
- 🟠 **Backup automatique avant écriture** — Sauvegarder le contenu original dans `.obsigate-backup/` avant chaque PUT ou DELETE.
|
||||||
|
|
||||||
|
### 🟡 UX — P2
|
||||||
|
|
||||||
|
- 🟡 **Backlinks panel** — Afficher les fichiers contenant des wikilinks pointant vers le fichier courant. Index inversé des wikilinks.
|
||||||
|
- 🟡 **Gestion des conflits Syncthing** — Dashboard « Conflits » avec diff et résolution (garder local, garder conflit).
|
||||||
|
- 🟡 **Liste IGNORED_DIRS configurable** — Rendre la liste des dossiers ignorés par le watcher configurable (env var ou Configurations).
|
||||||
|
- 🟡 **Timeout de session configurable** — Exposer le TTL JWT dans les Configurations.
|
||||||
|
|
||||||
|
### 🟢 Fonctionnel — P3/P4
|
||||||
|
|
||||||
|
- 🟢 **Dashboard statistiques** — Métriques par vault : fichiers totaux, taille, top tags, orphelins.
|
||||||
|
- 🟢 **Webhooks** — Notifier des systèmes externes lors de changements (création, modif, suppression).
|
||||||
|
- 🟢 **Documentation OpenAPI enrichie** — Enrichir les modèles Pydantic pour la doc auto-générée /docs et /redoc.
|
||||||
|
- 🟢 **Gestion fichiers non-supportés** — Message explicite + bouton download pour les fichiers binaires non gérés.
|
||||||
|
|
||||||
|
### ⬜ Qualité & Polish — P5+
|
||||||
|
|
||||||
|
- ⬜ **Tests unitaires** (pytest)
|
||||||
|
- ⬜ **Tests E2E** (Playwright)
|
||||||
|
- ⬜ **CI/CD pipeline** (GitHub Actions)
|
||||||
|
- ⬜ **i18n** (support anglais + français)
|
||||||
|
- ⬜ **CHANGELOG.md**
|
||||||
|
- ⬜ **Documentation utilisateur enrichie**
|
||||||
|
- ⬜ **Authentification multi-facteurs** (TOTP/WebAuthn)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Document généré le 2026-05-25 — Remplace l'ancien TODO.md*
|
||||||
161
docs/SPEC_Dashboard_RecentFiles.md
Normal file
161
docs/SPEC_Dashboard_RecentFiles.md
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
# SPEC: Widget "Derniers fichiers ouverts" sur la page principale
|
||||||
|
|
||||||
|
## 1. Objectif
|
||||||
|
|
||||||
|
Remplacer le message d'accueil actuel (`#welcome`) par un widget dashboard professionnel affichant les **XX derniers fichiers ouverts**. Le nombre de fichiers affichés sera configurable via les paramètres existants (`cfg-recent-limit`).
|
||||||
|
|
||||||
|
## 2. Architecture du composant
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
graph TD
|
||||||
|
A["#content-area"] --> B["#dashboard-home"]
|
||||||
|
B --> C["En-tête: Logo + Titre"]
|
||||||
|
B --> D["Sélecteur vault filter"]
|
||||||
|
B --> E["#dashboard-recent-grid"]
|
||||||
|
B --> F["#dashboard-recent-empty"]
|
||||||
|
|
||||||
|
E --> G["Carte 1: fichier récent"]
|
||||||
|
E --> H["Carte 2: fichier récent"]
|
||||||
|
E --> I["..."]
|
||||||
|
|
||||||
|
G --> G1["Icône fichier"]
|
||||||
|
G --> G2["Titre"]
|
||||||
|
G --> G3["Chemin breadcrumb"]
|
||||||
|
G --> G4["Tags"]
|
||||||
|
G --> G5["Horodatage"]
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. Design UI/UX
|
||||||
|
|
||||||
|
### 3.1 Structure HTML (dans `#content-area`)
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div id="dashboard-home" class="dashboard-home">
|
||||||
|
<div class="dashboard-header">
|
||||||
|
<div class="dashboard-title-row">
|
||||||
|
<i data-lucide="clock" class="dashboard-icon"></i>
|
||||||
|
<h2>Derniers fichiers ouverts</h2>
|
||||||
|
</div>
|
||||||
|
<div class="dashboard-filter-row">
|
||||||
|
<select id="dashboard-vault-filter">
|
||||||
|
<option value="">Tous les vaults</option>
|
||||||
|
</select>
|
||||||
|
<span class="dashboard-count" id="dashboard-count"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="dashboard-recent-grid" class="dashboard-recent-grid"></div>
|
||||||
|
<div id="dashboard-recent-empty" class="dashboard-recent-empty hidden">
|
||||||
|
<i data-lucide="inbox"></i>
|
||||||
|
<span>Aucun fichier récent</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 Layout Grid
|
||||||
|
|
||||||
|
- **Desktop (>1024px)**: Grid 3 colonnes
|
||||||
|
- **Tablet (768-1024px)**: Grid 2 colonnes
|
||||||
|
- **Mobile (<768px)**: Grid 1 colonne
|
||||||
|
|
||||||
|
### 3.3 Style des cartes (`.dashboard-card`)
|
||||||
|
|
||||||
|
| Élément | Style |
|
||||||
|
|---------|-------|
|
||||||
|
| Container | `border-radius: 12px`, `padding: 16px`, fond `var(--bg-secondary)` |
|
||||||
|
| Hover | Légère élévation avec `box-shadow`, bordure accent |
|
||||||
|
| Icône | 32x32px, couleur accent |
|
||||||
|
| Titre | `font-weight: 600`, `font-size: 14px`, truncation avec ellipsis |
|
||||||
|
| Chemin | `font-size: 11px`, `color: var(--text-muted)` |
|
||||||
|
| Tags | Pills compacts, même style que sidebar |
|
||||||
|
| Horodatage | Badge discret avec icône clock |
|
||||||
|
| Badge vault | Position absolute en haut-droit |
|
||||||
|
|
||||||
|
### 3.4 États
|
||||||
|
|
||||||
|
| État | Description |
|
||||||
|
|------|-------------|
|
||||||
|
| **Chargement** | Skeleton cards animées (pulse) |
|
||||||
|
| **Données** | Grid de cartes |
|
||||||
|
| **Vide** | Icône + message centré |
|
||||||
|
| **Erreur** | Toast notification |
|
||||||
|
|
||||||
|
## 4. Interactions
|
||||||
|
|
||||||
|
| Action | Comportement |
|
||||||
|
|--------|--------------|
|
||||||
|
| **Clic sur carte** | Ouvre le fichier (`openFile(vault, path)`) |
|
||||||
|
| **Changement filter vault** | Recharge les données avec filtre |
|
||||||
|
| **Hover carte** | Élévation visuelle, curseur pointer |
|
||||||
|
| **Fermeture fichier** | Affiche le dashboard (si plus de fichier ouvert) |
|
||||||
|
|
||||||
|
## 5. Intégration JavaScript
|
||||||
|
|
||||||
|
### 5.1 Nouveau module `DashboardRecentWidget`
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const DashboardRecentWidget = {
|
||||||
|
async load(vaultFilter) { /* Charge via /api/recent */ },
|
||||||
|
render(files) { /* Génère le HTML des cartes */ },
|
||||||
|
showEmpty() { /* Affiche état vide */ },
|
||||||
|
showLoading() { /* Affiche skeletons */ },
|
||||||
|
init() { /* Bind events, charge initial */ }
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.2 Points d'intégration
|
||||||
|
|
||||||
|
- **Au démarrage**: `DashboardRecentWidget.init()` dans `DOMContentLoaded`
|
||||||
|
- **Ouverture fichier**: Dashboard masqué automatiquement
|
||||||
|
- **Fermeture fichier**: Dashboard affiché si `activeEditor === null`
|
||||||
|
- **Filtre vault**: Recharge via `loadRecentFiles` de la sidebar (partage du cache)
|
||||||
|
|
||||||
|
### 5.3 Partage avec sidebar "Recent"
|
||||||
|
|
||||||
|
Le widget réutilisera `_recentFilesCache` et `renderRecentList` mais avec un **template de carte différent** pour le dashboard.
|
||||||
|
|
||||||
|
## 6. Fichiers à modifier
|
||||||
|
|
||||||
|
| Fichier | Modification |
|
||||||
|
|---------|--------------|
|
||||||
|
| `frontend/index.html` | Remplacer `#welcome` par `#dashboard-home` |
|
||||||
|
| `frontend/style.css` | Ajouter `.dashboard-home`, `.dashboard-card`, skeleton, animations |
|
||||||
|
| `frontend/app.js` | Ajouter `DashboardRecentWidget`, modifier `showWelcome()`, intégration hooks |
|
||||||
|
|
||||||
|
## 7. Paramètres configurables
|
||||||
|
|
||||||
|
| Paramètre | Source | Description |
|
||||||
|
|-----------|--------|-------------|
|
||||||
|
| `recent_files_limit` | Backend config | Nombre max de fichiers (5-100, défaut: 20) |
|
||||||
|
|
||||||
|
## 8. Accessibilité
|
||||||
|
|
||||||
|
- Rôles ARIA appropriés (`role="region"`, `aria-label`)
|
||||||
|
- Navigation clavier fonctionnelle
|
||||||
|
- Contraste des couleurs conforme WCAG 2.1 AA
|
||||||
|
- Support screen reader pour les états vides/chargement
|
||||||
|
|
||||||
|
## 9. Responsive breakpoints
|
||||||
|
|
||||||
|
```css
|
||||||
|
.dashboard-recent-grid {
|
||||||
|
display: grid;
|
||||||
|
gap: 16px;
|
||||||
|
/* Mobile first */
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 10. Animations
|
||||||
|
|
||||||
|
| Événement | Animation |
|
||||||
|
|-----------|-----------|
|
||||||
|
| Entrée cartes | Fade-in + slide-up staggeré (50ms entre cartes) |
|
||||||
|
| Hover carte | Scale 1.02 + shadow |
|
||||||
|
| Skeleton loading | Pulse animation |
|
||||||
|
| Transition vault filter | Fade out/in des cartes |
|
||||||
Loading…
x
Reference in New Issue
Block a user