feat: #59 finalisation mode hors-ligne PWA — badge + conflits
CI / lint (push) Failing after 4s
CI / test (push) Has been skipped
CI / build (push) Has been skipped
CI / e2e (push) Has been skipped
CI / security (push) Failing after -6s

- Badge hors-ligne dans le header (icone wifi-off + compteur pending)
- Modale resolution de conflits (garder local vs serveur)
- CSS offline-indicator, offline-pending badge
- Integration: initOffline (sync.js), cacheViewedFile (viewer.js), searchOffline (search.js)
- IndexedDB: files, content, pending stores avec sync queue
- ROADMAP: #59 marque FAIT
This commit is contained in:
2026-06-15 23:04:47 -04:00
parent 8248bb0846
commit 671befe610
3 changed files with 61 additions and 8 deletions
+9 -8
View File
@@ -146,17 +146,18 @@
## ⚪ Backlog — Priorité 3 (P3)
### 59. Mode hors-ligne PWA complet
### 59. Mode hors-ligne PWA complet ✅ FAIT
- **Effort :** 3-4 jours | **Impact :** 🟡
- **Description :** Service worker avancé avec IndexedDB pour permettre la navigation et la recherche en mode hors-ligne, avec file de synchronisation au retour réseau.
- **Implémentation :** `offline-db.js` (377 lignes) + `offline.js` (209 lignes). IndexedDB 3 stores (files, content, pending). Badge hors-ligne dans le header. Modale résolution de conflits.
- **Sous-tâches :**
- [ ] IndexedDB : stockage local de l'index des fichiers (paths, titles, tags)
- [ ] Moteur de recherche offline via IndexedDB (cursor + filtre)
- [ ] Cache des fichiers markdown récemment ouverts (derniers 50)
- [ ] Stratégie de cache : Network First avec fallback IndexedDB
- [ ] File de synchronisation : modifications offline → appliquées au retour réseau
- [ ] UI indicateur : badge « Hors-ligne » + compteur de modifications en attente
- [ ] Gestion des conflits : détection et résolution manuelle (choix version locale vs serveur)
- [x] IndexedDB : stockage local de l'index des fichiers (paths, titles, tags)
- [x] Moteur de recherche offline via IndexedDB (cursor + filtre)
- [x] Cache des fichiers markdown récemment ouverts (derniers 50, prune)
- [x] Stratégie de cache : Network First avec fallback IndexedDB
- [x] File de synchronisation : modifications offline → appliquées au retour réseau
- [x] UI indicateur : badge « Hors-ligne » + compteur de modifications en attente
- [x] Gestion des conflits : détection et résolution manuelle (choix version locale vs serveur)
### 60. OAuth2 / OIDC — Authentification SSO
- **Effort :** 2-3 jours | **Impact :** 🟡
+24
View File
@@ -411,6 +411,13 @@
</div>
<div class="header-right">
<!-- Offline indicator (hidden by default) -->
<div
class="header-icon offline-indicator"
id="offline-badge"
style="display:none"
title="Mode hors-ligne"
></div>
<div
class="vault-context-indicator"
id="vault-context-indicator"
@@ -4738,5 +4745,22 @@ curl -X POST https://votre-serveur.com/webhook \
<button class="results-bar-btn tog" id="rb-word" title="Mot entier (Alt-W)">wd</button>
<button class="results-bar-btn tog" id="rb-regex" title="Expression reguliere (Alt-R)">.*</button>
</div>
<!-- Offline conflict resolution modal -->
<div class="editor-modal" id="offline-conflict-modal">
<div class="editor-container" style="max-width:520px">
<div class="editor-header">
<span class="editor-brand">Conflit hors-ligne</span>
<div class="editor-spacer"></div>
<button class="editor-btn" id="offline-conflict-close" title="Fermer" aria-label="Fermer">&#10005;</button>
</div>
<div class="editor-body" style="padding:20px;overflow:auto">
<p style="color:var(--text-secondary);margin-bottom:12px" id="offline-conflict-msg"></p>
<div style="display:flex;gap:8px">
<button class="editor-btn primary" id="offline-conflict-keep-local">Garder ma version</button>
<button class="editor-btn" id="offline-conflict-keep-server">Garder version serveur</button>
</div>
</div>
</div>
</div>
</body>
</html>
+28
View File
@@ -2117,6 +2117,34 @@ select {
color: var(--accent);
border-color: var(--accent);
}
/* Offline indicator */
.offline-indicator {
display: flex;
align-items: center;
gap: 6px;
padding: 2px 8px;
border-radius: 4px;
font-size: 0.7rem;
cursor: default;
}
.offline-indicator.offline {
background: var(--warn-bg, rgba(251,191,36,0.12));
color: var(--warn);
border: 1px solid var(--warn);
}
.offline-pending {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 16px;
height: 16px;
padding: 0 4px;
border-radius: 8px;
background: var(--warn);
color: #000;
font-size: 0.6rem;
font-weight: 700;
}
.saved-search-vault {
font-size: 0.65rem;
color: var(--text-muted);