Release v1.1.4
This commit is contained in:
commit
89c75bed81
5 changed files with 128 additions and 9 deletions
|
|
@ -3,8 +3,8 @@
|
|||
Router, State-Management, Navigation, Initialisierung.
|
||||
============================================================ */
|
||||
|
||||
const APP_VER = '536'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
|
||||
const APP_VERSION = '1.1.3'; // ← semantische Version, wird bei make release gesetzt
|
||||
const APP_VER = '539'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
|
||||
const APP_VERSION = '1.1.4'; // ← semantische Version, wird bei make release gesetzt
|
||||
const IS_STAGING = location.hostname === 'staging.banyaro.app';
|
||||
|
||||
const App = (() => {
|
||||
|
|
|
|||
|
|
@ -136,7 +136,13 @@ window.Page_notes = (() => {
|
|||
<!-- Header -->
|
||||
<div class="notes-header">
|
||||
<h2 class="notes-title">Notizblock</h2>
|
||||
<span class="notes-count">${_notes.length} Notiz${_notes.length !== 1 ? 'en' : ''}</span>
|
||||
<div style="display:flex;align-items:center;gap:var(--space-2)">
|
||||
<span class="notes-count">${_notes.length} Notiz${_notes.length !== 1 ? 'en' : ''}</span>
|
||||
<button id="notes-new-btn" class="btn btn-primary btn-sm" style="gap:4px">
|
||||
<svg class="ph-icon" aria-hidden="true" style="width:15px;height:15px"><use href="/icons/phosphor.svg#plus"></use></svg>
|
||||
${_filterType && _filterType !== '' ? _rubrik(_filterType).label : 'Neue Notiz'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Datenschutz-Hinweis (einmalig, wegklickbar) -->
|
||||
|
|
@ -361,6 +367,11 @@ window.Page_notes = (() => {
|
|||
_container.querySelector('#notes-privacy-notice')?.remove();
|
||||
});
|
||||
|
||||
// Neue Notiz
|
||||
_container.querySelector('#notes-new-btn')?.addEventListener('click', () => {
|
||||
_openCreateModal(_filterType || '');
|
||||
});
|
||||
|
||||
// Filter-Chips
|
||||
_container.querySelectorAll('.notes-chip').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
|
|
@ -464,6 +475,101 @@ window.Page_notes = (() => {
|
|||
_render();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// Create-Modal — neue Notiz mit vorausgewählter Kategorie
|
||||
// ----------------------------------------------------------
|
||||
function _openCreateModal(preselectedType = '') {
|
||||
const ERSTELL_RUBRIKEN = RUBRIKEN.filter(r => r.type !== ''); // ohne "Alle"
|
||||
let _selType = preselectedType || ERSTELL_RUBRIKEN[0].type;
|
||||
|
||||
const modalId = 'notes-create-modal';
|
||||
document.getElementById(modalId)?.remove();
|
||||
|
||||
const overlay = document.createElement('div');
|
||||
overlay.id = modalId;
|
||||
overlay.style.cssText = `position:fixed;inset:0;z-index:9999;display:flex;align-items:flex-end;justify-content:center;background:rgba(0,0,0,0.45)`;
|
||||
|
||||
const _buildContent = () => {
|
||||
const rb = _rubrik(_selType);
|
||||
return `
|
||||
<div style="background:var(--c-surface);border-radius:var(--radius-lg) var(--radius-lg) 0 0;
|
||||
width:100%;max-width:480px;max-height:90vh;overflow-y:auto;
|
||||
padding:var(--space-5) var(--space-4) var(--space-6);box-shadow:0 -4px 24px rgba(0,0,0,0.15)">
|
||||
<div style="width:40px;height:4px;background:var(--c-border);border-radius:2px;margin:0 auto var(--space-4)"></div>
|
||||
<h3 style="font-size:var(--text-base);font-weight:700;margin:0 0 var(--space-4)">Neue Notiz</h3>
|
||||
|
||||
<!-- Kategorie-Auswahl -->
|
||||
<div style="margin-bottom:var(--space-4)">
|
||||
<label style="display:block;font-size:var(--text-sm);font-weight:600;color:var(--c-text);margin-bottom:var(--space-2)">Kategorie</label>
|
||||
<div style="display:flex;flex-wrap:wrap;gap:var(--space-2)">
|
||||
${ERSTELL_RUBRIKEN.map(r => `
|
||||
<button class="nc-cat" data-type="${r.type}"
|
||||
style="font-size:var(--text-xs);font-weight:600;padding:4px var(--space-3);
|
||||
border-radius:999px;border:1.5px solid ${_selType===r.type ? r.color : 'var(--c-border)'};
|
||||
background:${_selType===r.type ? r.color+'22' : 'var(--c-surface-2)'};
|
||||
color:${_selType===r.type ? r.color : 'var(--c-text-secondary)'};cursor:pointer">
|
||||
${_esc(r.label)}
|
||||
</button>`).join('')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Text -->
|
||||
<div style="margin-bottom:var(--space-4)">
|
||||
<label style="display:block;font-size:var(--text-sm);font-weight:600;color:var(--c-text);margin-bottom:var(--space-2)">Notiz</label>
|
||||
<textarea id="nc-text" rows="5" placeholder="Was möchtest du festhalten…"
|
||||
style="width:100%;padding:var(--space-3);border:1.5px solid var(--c-border);
|
||||
border-radius:var(--radius-md);font-size:var(--text-sm);
|
||||
font-family:var(--font-sans);background:var(--c-surface);
|
||||
color:var(--c-text);resize:vertical;outline:none;line-height:1.5;
|
||||
box-sizing:border-box"></textarea>
|
||||
</div>
|
||||
|
||||
<div style="display:flex;gap:var(--space-3)">
|
||||
<button id="nc-cancel" class="btn btn-ghost" style="flex:1">Abbrechen</button>
|
||||
<button id="nc-save" class="btn btn-primary" style="flex:1">Speichern</button>
|
||||
</div>
|
||||
</div>`;
|
||||
};
|
||||
|
||||
overlay.innerHTML = _buildContent();
|
||||
document.body.appendChild(overlay);
|
||||
|
||||
const _rebind = () => {
|
||||
overlay.querySelectorAll('.nc-cat').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
_selType = btn.dataset.type;
|
||||
overlay.innerHTML = _buildContent();
|
||||
_rebind();
|
||||
overlay.querySelector('#nc-text')?.focus();
|
||||
});
|
||||
});
|
||||
|
||||
overlay.querySelector('#nc-cancel')?.addEventListener('click', () => overlay.remove());
|
||||
overlay.addEventListener('click', e => { if (e.target === overlay) overlay.remove(); });
|
||||
|
||||
overlay.querySelector('#nc-save')?.addEventListener('click', async () => {
|
||||
const text = overlay.querySelector('#nc-text')?.value?.trim();
|
||||
if (!text) { UI.toast.warning('Bitte einen Text eingeben.'); return; }
|
||||
const btn = overlay.querySelector('#nc-save');
|
||||
await UI.asyncButton(btn, async () => {
|
||||
const rb = _rubrik(_selType);
|
||||
await API.notes.create(_selType, 'standalone', {
|
||||
text,
|
||||
parent_label: rb.label,
|
||||
});
|
||||
overlay.remove();
|
||||
_filterType = _selType;
|
||||
await _reload();
|
||||
UI.toast.success('Notiz gespeichert.');
|
||||
});
|
||||
});
|
||||
|
||||
setTimeout(() => overlay.querySelector('#nc-text')?.focus(), 100);
|
||||
};
|
||||
|
||||
_rebind();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// Edit-Modal (Bottom-Sheet Stil)
|
||||
// ----------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -604,14 +604,27 @@ window.Page_settings = (() => {
|
|||
}
|
||||
if (btn) btn.textContent = 'Prüfe…';
|
||||
try {
|
||||
// Aktuelle Version vom Server holen (no-cache)
|
||||
const serverResp = await fetch('/js/app.js', { cache: 'no-store' });
|
||||
const serverText = await serverResp.text();
|
||||
const match = serverText.match(/APP_VERSION\s*=\s*'([^']+)'/);
|
||||
const serverVersion = match?.[1] || null;
|
||||
const localVersion = typeof APP_VERSION !== 'undefined' ? APP_VERSION : '0';
|
||||
|
||||
// SW update anstoßen
|
||||
const reg = await navigator.serviceWorker.getRegistration();
|
||||
await reg?.update();
|
||||
if (reg?.waiting) {
|
||||
// Neuer SW wartet — sofort aktivieren
|
||||
|
||||
if (serverVersion && serverVersion !== localVersion) {
|
||||
// Neuere Version verfügbar — Seite neu laden
|
||||
if (reg?.waiting) reg.waiting.postMessage({ type: 'SKIP_WAITING' });
|
||||
UI.toast.info(`Update auf v${serverVersion} verfügbar — Seite wird neu geladen…`);
|
||||
setTimeout(() => location.reload(), 1500);
|
||||
} else if (reg?.waiting) {
|
||||
reg.waiting.postMessage({ type: 'SKIP_WAITING' });
|
||||
UI.toast.success('Update wird installiert…');
|
||||
} else {
|
||||
UI.toast.success('Ban Yaro ist aktuell — v' + (typeof APP_VERSION !== 'undefined' ? APP_VERSION : '1.0.0') + '.');
|
||||
UI.toast.success(`Ban Yaro ist aktuell — v${localVersion}`);
|
||||
}
|
||||
} catch {
|
||||
UI.toast.error('Update-Prüfung fehlgeschlagen.');
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"id": "/",
|
||||
"version": "1.1.3",
|
||||
"version": "1.1.4",
|
||||
"name": "Ban Yaro — Die Hunde-Plattform",
|
||||
"short_name": "Ban Yaro",
|
||||
"description": "Alles rund um deinen Hund. Von Welpe bis Opa.",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Offline-Cache + Push Notifications + Tile-Cache
|
||||
============================================================ */
|
||||
|
||||
const CACHE_VERSION = 'by-v559';
|
||||
const CACHE_VERSION = 'by-v562';
|
||||
const CACHE_STATIC = `${CACHE_VERSION}-static`;
|
||||
const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten
|
||||
const CACHE_API = 'ban-yaro-api-v1'; // API-Response-Cache
|
||||
|
|
@ -134,13 +134,13 @@ function _isCacheableGet(pathname) {
|
|||
// INSTALL — App Shell cachen
|
||||
// ----------------------------------------------------------
|
||||
self.addEventListener('install', event => {
|
||||
self.skipWaiting(); // Sofort übernehmen — kein Warten auf Cache-Aufbau
|
||||
event.waitUntil(
|
||||
caches.open(CACHE_STATIC)
|
||||
.then(cache => cache.addAll(STATIC_ASSETS))
|
||||
.then(() => caches.open(CACHE_API).then(c =>
|
||||
fetch('/api/training/exercises').then(r => { if (r.ok) c.put('/api/training/exercises', r); }).catch(() => {})
|
||||
))
|
||||
.then(() => self.skipWaiting())
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue