feat: v6.0.0 PWA offline support
- manifest + icones, service worker (precache, network-first, Background Sync)
- module client FlowOffline (IndexedDB, queue, delta, flush) + hook editeur
- endpoints /api/v2/sync/{delta,batch,status} + moteur de sync (conflits LWW/orpheline/copie offline)
- migrations offline_sync_queue + sync_version (triggers)
- UI offline (banner, badge sync, toasts, icone dirty) + doc /help
- tests pytest (sync, migrations, SW, offline) + E2E Playwright; bump 6.0.0
This commit is contained in:
@@ -5,6 +5,11 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>FlowDeck — {% block title_prefix %}Home{% endblock %}</title>
|
||||
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg">
|
||||
<link rel="manifest" href="/static/manifest.json">
|
||||
<meta name="theme-color" content="#191919">
|
||||
<link rel="apple-touch-icon" href="/static/icons/apple-touch-icon.png">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
<link rel="stylesheet" href="/static/css/app.css?v=5.1.1">
|
||||
<link rel="stylesheet" href="/static/css/design-tokens.css?v=5.2.0">
|
||||
<link rel="stylesheet" href="/static/css/components.css?v=5.2.0">
|
||||
@@ -750,6 +755,11 @@
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<!-- ============ PWA SYNC BADGE (v6.0.0) ============ -->
|
||||
<div id="fd-sync-badge" class="fd-sync-badge" style="display:none" role="status" aria-live="polite">
|
||||
<span class="fd-sync-spinner"></span><span>Synchronisation…</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script data-cfasync="false">
|
||||
@@ -2271,5 +2281,55 @@
|
||||
})();
|
||||
</script>
|
||||
|
||||
{# ─── PWA: sync indicators (v6.0.0) ─── #}
|
||||
<style>
|
||||
.fd-sync-badge{position:fixed;top:10px;right:14px;z-index:600;display:flex;align-items:center;gap:8px;
|
||||
background:var(--bg-secondary,#262626);border:1px solid var(--border,rgba(255,255,255,.1));
|
||||
color:var(--text-secondary,#b8b8b8);border-radius:20px;padding:5px 12px;font-size:12px;
|
||||
box-shadow:0 4px 16px rgba(0,0,0,.35);}
|
||||
.fd-sync-spinner{width:12px;height:12px;border:2px solid rgba(255,255,255,.25);
|
||||
border-top-color:var(--accent,#2383E2);border-radius:50%;display:inline-block;
|
||||
animation:fd-spin .8s linear infinite;}
|
||||
@keyframes fd-spin{to{transform:rotate(360deg)}}
|
||||
.sidebar-item.fd-dirty .page-name::after{content:'⟳';margin-left:6px;font-size:11px;
|
||||
color:var(--accent,#2383E2);opacity:.85;}
|
||||
</style>
|
||||
|
||||
{# ─── PWA: offline client module + service worker registration (v6.0.0) ─── #}
|
||||
<script src="/static/js/offline.js?v=6.0.0" defer data-cfasync="false"></script>
|
||||
<script data-cfasync="false">
|
||||
(function() {
|
||||
if (!('serviceWorker' in navigator)) return;
|
||||
window.addEventListener('load', function() {
|
||||
navigator.serviceWorker.register('/sw.js').then(function(reg) {
|
||||
if ('sync' in reg && reg.sync) {
|
||||
reg.sync.register('sync-flowdeck').catch(function() {});
|
||||
}
|
||||
}).catch(function() {});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
{# ─── PWA: sync badge + toasts wiring (v6.0.0) ─── #}
|
||||
<script data-cfasync="false">
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
if (!window.FlowOffline) return;
|
||||
window.FlowOffline.onChange(function(s) {
|
||||
var badge = document.getElementById('fd-sync-badge');
|
||||
if (badge) badge.style.display = s.isSyncing ? 'flex' : 'none';
|
||||
});
|
||||
window.addEventListener('flowdeck:sync-done', function(ev) {
|
||||
var d = ev.detail || {};
|
||||
if (d.failed) {
|
||||
if (window.showToast) window.showToast(d.failed + ' modification(s) non synchronisée(s)', 'error');
|
||||
} else if (d.conflicts) {
|
||||
if (window.showToast) window.showToast('Synchronisé — ' + d.conflicts + ' conflit(s) résolu(s)', 'info');
|
||||
} else if (d.synced) {
|
||||
if (window.showToast) window.showToast('Modifications synchronisées', 'success');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user