From 55b354e86513f5113029061a10a7422721d7b225 Mon Sep 17 00:00:00 2001
From: rene
Date: Thu, 4 Jun 2026 12:27:01 +0200
Subject: [PATCH 01/78] =?UTF-8?q?Freunde:=20Annehmen/Ablehnen-Buttons=20mi?=
=?UTF-8?q?t=20Text-Label=20(Icon-only=20war=20f=C3=BCr=20Nutzer=20nicht?=
=?UTF-8?q?=20erkennbar)=20+=20Fix=20/apifriends/same-breed=20Slash-Bug,?=
=?UTF-8?q?=20SW=20v1162?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
VERSION | 2 +-
backend/static/index.html | 24 ++++++++++++------------
backend/static/js/app.js | 2 +-
backend/static/js/pages/dog-profile.js | 2 +-
backend/static/js/pages/friends.js | 2 ++
backend/static/landing.html | 2 +-
backend/static/sw.js | 2 +-
7 files changed, 19 insertions(+), 17 deletions(-)
diff --git a/VERSION b/VERSION
index 8535dde..d5e7c40 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1161
\ No newline at end of file
+1162
\ No newline at end of file
diff --git a/backend/static/index.html b/backend/static/index.html
index 950d38a..85c40c8 100644
--- a/backend/static/index.html
+++ b/backend/static/index.html
@@ -86,14 +86,14 @@
Ban Yaro
-
+
-
-
-
-
-
+
+
+
+
+
@@ -617,11 +617,11 @@
-
-
-
-
-
+
+
+
+
+
@@ -631,7 +631,7 @@
-
+
diff --git a/backend/static/js/app.js b/backend/static/js/app.js
index 23c0284..af14237 100644
--- a/backend/static/js/app.js
+++ b/backend/static/js/app.js
@@ -3,7 +3,7 @@
Router, State-Management, Navigation, Initialisierung.
============================================================ */
-const APP_VER = '1161'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
+const APP_VER = '1162'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
const APP_VERSION = '1.6.0'; // ← semantische Version, wird bei make release gesetzt
window.APP_VER = APP_VER; // global verfügbar für andere Module (z.B. offline-indicator)
window.APP_VERSION = APP_VERSION;
diff --git a/backend/static/js/pages/dog-profile.js b/backend/static/js/pages/dog-profile.js
index f942b02..c5498d8 100644
--- a/backend/static/js/pages/dog-profile.js
+++ b/backend/static/js/pages/dog-profile.js
@@ -2452,7 +2452,7 @@ window.Page_dog_profile = (() => {
const el = document.getElementById('dp-same-breed-chip');
if (!el) return;
try {
- const data = await API.get('friends/same-breed');
+ const data = await API.get('/friends/same-breed');
if (!data || data.count === 0) return;
const hauptRasse = data.rassen[0]?.rasse || '';
const label = data.count === 1
diff --git a/backend/static/js/pages/friends.js b/backend/static/js/pages/friends.js
index ea4405c..87a177a 100644
--- a/backend/static/js/pages/friends.js
+++ b/backend/static/js/pages/friends.js
@@ -361,10 +361,12 @@ window.Page_friends = (() => {
+ Annehmen
+ Ablehnen
diff --git a/backend/static/landing.html b/backend/static/landing.html
index cc2d2b7..bd85f7f 100644
--- a/backend/static/landing.html
+++ b/backend/static/landing.html
@@ -4,7 +4,7 @@
-
+
Ban Yaro — Die Hunde-App für Deutschland, Österreich & Schweiz
diff --git a/backend/static/sw.js b/backend/static/sw.js
index 4d7fd1d..dab5f8d 100644
--- a/backend/static/sw.js
+++ b/backend/static/sw.js
@@ -4,7 +4,7 @@
============================================================ */
// ← EINZIGE Stelle für die Version — STATIC_ASSETS und CACHE_VERSION leiten sich ab
-const VER = '1161';
+const VER = '1162';
const CACHE_VERSION = `by-v${VER}`;
const CACHE_STATIC = `${CACHE_VERSION}-static`;
const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten
From 152fde716cc328b57cca928897253a9149677e0a Mon Sep 17 00:00:00 2001
From: rene
Date: Thu, 4 Jun 2026 13:35:53 +0200
Subject: [PATCH 02/78] =?UTF-8?q?Fix:=20Freunde=20Annehmen/Ablehnen/Chat?=
=?UTF-8?q?=20per=20Event-Delegation=20statt=20Inline-onclick=20(von=20CSP?=
=?UTF-8?q?-H=C3=A4rtung=2065cfa25=20blockiert),=20SW=20v1163?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
VERSION | 2 +-
backend/static/index.html | 24 ++++++++++++------------
backend/static/js/app.js | 2 +-
backend/static/js/pages/friends.js | 23 +++++++++++++++++++----
backend/static/landing.html | 2 +-
backend/static/sw.js | 2 +-
6 files changed, 35 insertions(+), 20 deletions(-)
diff --git a/VERSION b/VERSION
index d5e7c40..c659825 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1162
\ No newline at end of file
+1163
\ No newline at end of file
diff --git a/backend/static/index.html b/backend/static/index.html
index 85c40c8..487ccb1 100644
--- a/backend/static/index.html
+++ b/backend/static/index.html
@@ -86,14 +86,14 @@
Ban Yaro
-
+
-
-
-
-
-
+
+
+
+
+
@@ -617,11 +617,11 @@
-
-
-
-
-
+
+
+
+
+
@@ -631,7 +631,7 @@
-
+
diff --git a/backend/static/js/app.js b/backend/static/js/app.js
index af14237..ca5ddd8 100644
--- a/backend/static/js/app.js
+++ b/backend/static/js/app.js
@@ -3,7 +3,7 @@
Router, State-Management, Navigation, Initialisierung.
============================================================ */
-const APP_VER = '1162'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
+const APP_VER = '1163'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
const APP_VERSION = '1.6.0'; // ← semantische Version, wird bei make release gesetzt
window.APP_VER = APP_VER; // global verfügbar für andere Module (z.B. offline-indicator)
window.APP_VERSION = APP_VERSION;
diff --git a/backend/static/js/pages/friends.js b/backend/static/js/pages/friends.js
index 87a177a..dffce5d 100644
--- a/backend/static/js/pages/friends.js
+++ b/backend/static/js/pages/friends.js
@@ -148,6 +148,21 @@ window.Page_friends = (() => {
_searchTimer = setTimeout(() => _doSearch(q), 380);
});
+ // Delegierter Click-Handler — robust auch unter strikter CSP / für
+ // dynamisch nachgerenderte Buttons (Anfragen, Freundesliste).
+ // Ersetzt Inline-onclick, das auf manchen iOS-PWA-Sessions nicht feuerte.
+ _container.addEventListener('click', e => {
+ const btn = e.target.closest('[data-fr-action]');
+ if (!btn) return;
+ const id = parseInt(btn.dataset.frId, 10);
+ switch (btn.dataset.frAction) {
+ case 'accept': _accept(id); break;
+ case 'decline': _decline(id); break;
+ case 'cancel': _cancel(id); break;
+ case 'chat': _openChat(id); break;
+ }
+ });
+
// Prefill aus URL-Parameter → sofort suchen
if (prefill && prefill.length >= 2) {
_doSearch(prefill);
@@ -359,12 +374,12 @@ window.Page_friends = (() => {
+ data-fr-action="accept" data-fr-id="${r.id}" title="Annehmen">
Annehmen
+ data-fr-action="decline" data-fr-id="${r.id}" title="Ablehnen">
Ablehnen
@@ -402,7 +417,7 @@ window.Page_friends = (() => {
Anfrage ausstehend
+ data-fr-action="cancel" data-fr-id="${r.id}" title="Zurückziehen">
@@ -514,7 +529,7 @@ window.Page_friends = (() => {
diff --git a/backend/static/landing.html b/backend/static/landing.html
index bd85f7f..8584afd 100644
--- a/backend/static/landing.html
+++ b/backend/static/landing.html
@@ -4,7 +4,7 @@
-
+
Ban Yaro — Die Hunde-App für Deutschland, Österreich & Schweiz
diff --git a/backend/static/sw.js b/backend/static/sw.js
index dab5f8d..ed96e6e 100644
--- a/backend/static/sw.js
+++ b/backend/static/sw.js
@@ -4,7 +4,7 @@
============================================================ */
// ← EINZIGE Stelle für die Version — STATIC_ASSETS und CACHE_VERSION leiten sich ab
-const VER = '1162';
+const VER = '1163';
const CACHE_VERSION = `by-v${VER}`;
const CACHE_STATIC = `${CACHE_VERSION}-static`;
const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten
From 2ddd8ac350e80f1ab8786d04c69599b380eaf083 Mon Sep 17 00:00:00 2001
From: rene
Date: Thu, 4 Jun 2026 13:59:27 +0200
Subject: [PATCH 03/78] =?UTF-8?q?Fix:=20alle=20funktionalen=20Inline-Event?=
=?UTF-8?q?-Handler=20=E2=86=92=20addEventListener/Delegation=20(von=20CSP?=
=?UTF-8?q?-H=C3=A4rtung=2065cfa25=20app-weit=20blockiert)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Chat (senden/öffnen/löschen/Foto), Tagebuch-Buch, KI-Berichte, Wiki-Moderation,
Events-Detail, Walks-Lightbox, Routen-Foto, Navigations-CTAs (data-page),
Presse-Copy + Züchter-Landing (externes JS). 35x UI.modal.close → data-modal-close,
28x totes event.stopPropagation entfernt. Verbleibend: kosmetische onerror/Hover. SW v1164
---
VERSION | 2 +-
backend/static/index.html | 24 ++++----
backend/static/js/app.js | 18 +++++-
backend/static/js/pages/admin.js | 6 +-
backend/static/js/pages/adoption.js | 4 +-
backend/static/js/pages/chat.js | 38 ++++++++----
backend/static/js/pages/diary.js | 5 +-
backend/static/js/pages/dog-profile.js | 64 +++++++++++---------
backend/static/js/pages/ernaehrung.js | 6 +-
backend/static/js/pages/events.js | 18 ++++--
backend/static/js/pages/expenses.js | 6 +-
backend/static/js/pages/forum.js | 8 +--
backend/static/js/pages/friends.js | 5 +-
backend/static/js/pages/health.js | 78 ++++++++++---------------
backend/static/js/pages/laeufi.js | 8 +--
backend/static/js/pages/litters.js | 2 +-
backend/static/js/pages/lost.js | 3 +-
backend/static/js/pages/personality.js | 2 +-
backend/static/js/pages/playdate.js | 2 +-
backend/static/js/pages/poison.js | 2 +-
backend/static/js/pages/routes.js | 6 +-
backend/static/js/pages/settings.js | 4 +-
backend/static/js/pages/sitting.js | 7 +--
backend/static/js/pages/walks.js | 13 ++---
backend/static/js/pages/widget.js | 2 +-
backend/static/js/pages/wiki.js | 19 +++++-
backend/static/js/pages/zucht-profil.js | 3 +-
backend/static/js/presse.js | 11 ++++
backend/static/js/worlds.js | 3 +-
backend/static/js/zuechter.js | 6 ++
backend/static/landing.html | 2 +-
backend/static/presse.html | 13 +----
backend/static/sw.js | 2 +-
backend/static/zuechter.html | 9 +--
34 files changed, 228 insertions(+), 173 deletions(-)
create mode 100644 backend/static/js/presse.js
create mode 100644 backend/static/js/zuechter.js
diff --git a/VERSION b/VERSION
index c659825..b90f375 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1163
\ No newline at end of file
+1164
\ No newline at end of file
diff --git a/backend/static/index.html b/backend/static/index.html
index 487ccb1..b3a37b7 100644
--- a/backend/static/index.html
+++ b/backend/static/index.html
@@ -86,14 +86,14 @@
Ban Yaro
-
+
-
-
-
-
-
+
+
+
+
+
@@ -617,11 +617,11 @@
-
-
-
-
-
+
+
+
+
+
@@ -631,7 +631,7 @@
-
+
diff --git a/backend/static/js/app.js b/backend/static/js/app.js
index ca5ddd8..cfa9be2 100644
--- a/backend/static/js/app.js
+++ b/backend/static/js/app.js
@@ -3,7 +3,7 @@
Router, State-Management, Navigation, Initialisierung.
============================================================ */
-const APP_VER = '1163'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
+const APP_VER = '1164'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
const APP_VERSION = '1.6.0'; // ← semantische Version, wird bei make release gesetzt
window.APP_VER = APP_VER; // global verfügbar für andere Module (z.B. offline-indicator)
window.APP_VERSION = APP_VERSION;
@@ -443,6 +443,20 @@ const App = (() => {
return;
}
+ // Foto-Lightbox (Inline-onclick ist CSP-blockiert)
+ const lb = e.target.closest('[data-lightbox-url]');
+ if (lb) {
+ window.UI?.lightbox?.show?.([{ url: lb.dataset.lightboxUrl }], 0);
+ return;
+ }
+
+ // Externer Link in neuem Tab
+ const ol = e.target.closest('[data-open-url]');
+ if (ol) {
+ window.open(ol.dataset.openUrl, '_blank');
+ return;
+ }
+
// Header-User-Button → Settings
if (e.target.closest('#header-user-btn')) {
navigate('settings');
@@ -1164,7 +1178,7 @@ const App = (() => {
icon: UI.icon(icon),
title: 'Anmelden erforderlich',
text,
- action: `Anmelden `,
+ action: `Anmelden `,
});
}
diff --git a/backend/static/js/pages/admin.js b/backend/static/js/pages/admin.js
index 5002350..8c0a077 100644
--- a/backend/static/js/pages/admin.js
+++ b/backend/static/js/pages/admin.js
@@ -2661,7 +2661,7 @@ window.Page_admin = (() => {
background:var(--c-surface-2);border-radius:var(--radius-md);
padding:var(--space-3);max-height:60vh;overflow-y:auto;
color:var(--c-text)">${UI.escape(l.body || '(kein Text gespeichert)')}`,
- footer: `Schließen `,
+ footer: `Schließen `,
});
});
});
@@ -2760,7 +2760,7 @@ window.Page_admin = (() => {
`,
footer: `
- Abbrechen
+ Abbrechen
Speichern `,
});
@@ -2993,7 +2993,7 @@ window.Page_admin = (() => {
`,
footer: `
- Schließen
+ Schließen
Notiz speichern `,
});
document.getElementById('adm-bew-save-note')?.addEventListener('click', async () => {
diff --git a/backend/static/js/pages/adoption.js b/backend/static/js/pages/adoption.js
index b2c6410..38803ff 100644
--- a/backend/static/js/pages/adoption.js
+++ b/backend/static/js/pages/adoption.js
@@ -780,7 +780,7 @@ window.Page_adoption = (() => {
${UI.icon('heart')} Interesse bekunden
- Abbrechen
+ Abbrechen
`;
@@ -879,7 +879,7 @@ window.Page_adoption = (() => {
${UI.icon('plus')} Inserat erstellen
- Abbrechen
+ Abbrechen
`;
diff --git a/backend/static/js/pages/chat.js b/backend/static/js/pages/chat.js
index 3d7d877..10b64f5 100644
--- a/backend/static/js/pages/chat.js
+++ b/backend/static/js/pages/chat.js
@@ -18,6 +18,23 @@ window.Page_chat = (() => {
_container = container;
_myId = appState?.user?.id || null;
+ // Delegierter Click-Handler — Inline-onclick wird von der CSP blockiert.
+ if (!_container._chatClickBound) {
+ _container.addEventListener('click', e => {
+ const t = e.target.closest('[data-chat-action]');
+ if (!t) return;
+ switch (t.dataset.chatAction) {
+ case 'open': _openThread(parseInt(t.dataset.chatId, 10)); break;
+ case 'list': _showList(); break;
+ case 'photo': document.getElementById('chat-photo-input')?.click(); break;
+ case 'send': _send(); break;
+ case 'delete': _deleteMsg(parseInt(t.dataset.chatId, 10)); break;
+ case 'img': window.open(t.dataset.chatUrl, '_blank'); break;
+ }
+ });
+ _container._chatClickBound = true;
+ }
+
// Heartbeat: alle 30s online-Status senden
API.chat.heartbeat().catch(() => {});
_heartbeatTimer = setInterval(() => {
@@ -132,7 +149,7 @@ window.Page_chat = (() => {
? ` `
: '';
return `
-
+
${initials}
${onlineDot ? `
` : ''}
@@ -166,14 +183,14 @@ window.Page_chat = (() => {
// Aktive Markierung in der Liste
document.querySelectorAll('.chat-conv-item').forEach(el =>
- el.classList.toggle('active', el.getAttribute('onclick')?.includes(String(convId)))
+ el.classList.toggle('active', el.dataset.chatId === String(convId))
);
const threadHTML = `
-
-
+
+
-
+
@@ -219,9 +235,11 @@ window.Page_chat = (() => {
input.addEventListener('keydown', e => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
- Page_chat._send();
+ _send();
}
});
+ document.getElementById('chat-photo-input')
+ ?.addEventListener('change', e => _onPhotoSelected(e.target));
await _loadMessages(true);
await API.chat.markRead(_convId).catch(() => {});
@@ -313,7 +331,7 @@ window.Page_chat = (() => {
const timeStr = _fmtTime(m.created_at);
const deleteBtn = isMine && !m.is_deleted
? `
+ data-chat-action="delete" data-chat-id="${m.id}" title="Löschen">
`
: '';
@@ -328,7 +346,7 @@ window.Page_chat = (() => {
// Medieninhalt
let bubbleContent = '';
if (m.media_url) {
- bubbleContent += `
`;
+ bubbleContent += `
`;
}
if (m.text) {
bubbleContent += (m.media_url ? `
` : '') +
diff --git a/backend/static/js/pages/diary.js b/backend/static/js/pages/diary.js
index 686007c..2d496f6 100644
--- a/backend/static/js/pages/diary.js
+++ b/backend/static/js/pages/diary.js
@@ -1113,8 +1113,7 @@ window.Page_diary = (() => {
${datumLang}
${!_appState?.activeDog?.is_guest
- ? `
+ ? `
@@ -1722,7 +1721,7 @@ window.Page_diary = (() => {
`,
footer: `
- Schließen
+ Schließen
Importieren `,
});
diff --git a/backend/static/js/pages/dog-profile.js b/backend/static/js/pages/dog-profile.js
index c5498d8..61d23a7 100644
--- a/backend/static/js/pages/dog-profile.js
+++ b/backend/static/js/pages/dog-profile.js
@@ -616,7 +616,7 @@ window.Page_dog_profile = (() => {
footer: `
Speichern
- Abbrechen
+ Abbrechen
`,
});
document.getElementById('chip-edit-save-btn').addEventListener('click', async () => {
@@ -675,7 +675,7 @@ window.Page_dog_profile = (() => {
${hasPhoto ? `Speichern ` : ''}
${hasPhoto ? `${UI.icon('trash')} Löschen ` : ''}
- Abbrechen
+ Abbrechen
`;
@@ -957,7 +957,7 @@ window.Page_dog_profile = (() => {
`,
footer: `
-
Schließen
+
Schließen
Link erstellen `,
});
@@ -1489,7 +1489,7 @@ window.Page_dog_profile = (() => {
${data.hinweis ? `
${UI.escape(data.hinweis)}
` : ''}
`,
- footer: `
Schließen `,
+ footer: `
Schließen `,
});
return;
}
@@ -1608,7 +1608,7 @@ window.Page_dog_profile = (() => {
`,
footer: `
`,
footer: `
- Abbrechen
+ Abbrechen
Speichern
`,
});
@@ -1896,7 +1896,7 @@ window.Page_dog_profile = (() => {
`,
footer: `
- Abbrechen
+ Abbrechen
Speichern
`,
});
@@ -1960,7 +1960,7 @@ window.Page_dog_profile = (() => {
`,
footer: `
- Abbrechen
+ Abbrechen
Speichern
`,
});
@@ -2017,7 +2017,7 @@ window.Page_dog_profile = (() => {
UI.modal.open({
title: 'Hundepass-Link teilen',
body: shareWrap.innerHTML,
- footer: `Schließen `,
+ footer: `Schließen `,
});
document.getElementById('pp-sharelink-copy')?.addEventListener('click', async () => {
await navigator.clipboard.writeText(url).catch(() => {});
@@ -2209,7 +2209,7 @@ window.Page_dog_profile = (() => {
? 'background:#7a4f1a;color:#f5e4c0;border-color:#7a4f1a;'
: 'background:#f5f0e8;color:#444;border-color:#e0d4b8;';
const label = y === 'alle' ? 'Alle' : y;
- return `
- ${nurFotos ? '✓' : ''}
Nur Einträge mit Fotos
- ${nurMeilensteine ? '✓' : ''}
@@ -2255,11 +2255,11 @@ window.Page_dog_profile = (() => {
- 📖 Buch öffnen
- ✕
@@ -2268,18 +2268,14 @@ window.Page_dog_profile = (() => {
`;
};
- window._buchSetJahr = (y) => { selectedJahr = y; renderModal(); };
- window._buchToggleFotos = () => { nurFotos = !nurFotos; renderModal(); };
- window._buchToggleMeilensteine = () => { nurMeilensteine = !nurMeilensteine; renderModal(); };
- window._buchClose = () => {
+ const setJahr = (y) => { selectedJahr = y; renderModal(); };
+ const toggleFotos = () => { nurFotos = !nurFotos; renderModal(); };
+ const toggleMeilen = () => { nurMeilensteine = !nurMeilensteine; renderModal(); };
+ const closeModal = () => {
modalEl.remove();
- delete window._buchSetJahr;
- delete window._buchToggleFotos;
- delete window._buchToggleMeilensteine;
- delete window._buchOpen;
- delete window._buchClose;
+ document.removeEventListener('keydown', onKey);
};
- window._buchOpen = () => {
+ const openBuch = () => {
const params = new URLSearchParams();
if (selectedJahr !== 'alle') params.set('jahr', selectedJahr);
if (nurFotos) params.set('nur_fotos', 'true');
@@ -2290,10 +2286,24 @@ window.Page_dog_profile = (() => {
renderModal();
document.body.appendChild(modalEl);
- modalEl.addEventListener('click', e => { if (e.target === modalEl) window._buchClose(); });
+
+ // Delegierter Click-Handler (Inline-onclick wird von der CSP blockiert);
+ // überlebt das Re-Rendern via renderModal().
+ modalEl.addEventListener('click', e => {
+ if (e.target === modalEl) { closeModal(); return; }
+ const btn = e.target.closest('[data-buch-action]');
+ if (!btn) return;
+ switch (btn.dataset.buchAction) {
+ case 'year': setJahr(btn.dataset.buchYear); break;
+ case 'fotos': toggleFotos(); break;
+ case 'meilen': toggleMeilen(); break;
+ case 'open': openBuch(); break;
+ case 'close': closeModal(); break;
+ }
+ });
const onKey = e => {
- if (e.key === 'Escape') { window._buchClose(); document.removeEventListener('keydown', onKey); }
+ if (e.key === 'Escape') { closeModal(); }
};
document.addEventListener('keydown', onKey);
}
@@ -2310,7 +2320,7 @@ window.Page_dog_profile = (() => {
`,
- footer: `Schließen `,
+ footer: `Schließen `,
size: 'large',
});
diff --git a/backend/static/js/pages/ernaehrung.js b/backend/static/js/pages/ernaehrung.js
index bc7c46d..6fd04a7 100644
--- a/backend/static/js/pages/ernaehrung.js
+++ b/backend/static/js/pages/ernaehrung.js
@@ -53,7 +53,7 @@ window.Page_ernaehrung = (() => {
icon: ' ',
title: 'Noch kein Hund angelegt',
text: 'Erstelle zuerst ein Hundeprofil.',
- action: `Profil erstellen `,
+ action: `Profil erstellen `,
});
return;
}
@@ -728,7 +728,7 @@ window.Page_ernaehrung = (() => {
`;
const footer = `
- Abbrechen
+ Abbrechen
Speichern
`;
UI.modal.open({ title: 'Futter erfassen', body, footer });
@@ -840,7 +840,7 @@ window.Page_ernaehrung = (() => {
`;
const footer = `
- Abbrechen
+ Abbrechen
Speichern
`;
UI.modal.open({ title: 'Reaktion erfassen', body, footer });
diff --git a/backend/static/js/pages/events.js b/backend/static/js/pages/events.js
index 62c2d23..1aaa1a2 100644
--- a/backend/static/js/pages/events.js
+++ b/backend/static/js/pages/events.js
@@ -221,17 +221,17 @@ window.Page_events = (() => {
${ev.rsvp_count ? `${_icon('users')} ${ev.rsvp_count} nehmen teil ` : ''}
${ev.link ? `` : ''}
- ${isOwn ? `${_icon('pencil-simple')} ` : ''}
+ ${isOwn ? `${_icon('pencil-simple')} ` : ''}
${_state.user ? `
+ title="Notiz" class="text-muted">
${_icon('note-pencil')} ` : ''}
@@ -276,7 +276,7 @@ window.Page_events = (() => {
${datum}
${ev.ort_name ? `📍 ${UI.escape(ev.ort_name)} ` : ''}
${ev.beschreibung ? `${UI.escape(ev.beschreibung.slice(0, 80))}${ev.beschreibung.length > 80 ? '…' : ''} ` : ''}
- Details
`;
@@ -512,7 +512,7 @@ window.Page_events = (() => {
${isEdit ? `Löschen ` : ''}
- Abbrechen
+ Abbrechen
`;
@@ -570,6 +570,14 @@ window.Page_events = (() => {
// Click-Handler
// ----------------------------------------------------------
function _onClick(e) {
+ // Detail-Link (Karten-Popup) — Inline-onclick ist CSP-blockiert
+ const detailLink = e.target.closest('[data-ev-detail]');
+ if (detailLink) {
+ e.preventDefault();
+ _showDetail(parseInt(detailLink.dataset.evDetail, 10));
+ return;
+ }
+
// Quelle-Filter
const sourceBtn = e.target.closest('[data-ev-quelle]');
if (sourceBtn) {
diff --git a/backend/static/js/pages/expenses.js b/backend/static/js/pages/expenses.js
index 0a69315..57036ee 100644
--- a/backend/static/js/pages/expenses.js
+++ b/backend/static/js/pages/expenses.js
@@ -485,7 +485,7 @@ window.Page_expenses = (() => {
`;
const footer = `
- Abbrechen
+ Abbrechen
Speichern `;
UI.modal.open({ title: r ? 'Dauerauftrag bearbeiten' : 'Neuer Dauerauftrag', body, footer });
@@ -755,10 +755,10 @@ window.Page_expenses = (() => {
style="color:var(--c-danger);margin-right:auto">
${UI.icon('trash')}
- Abbrechen
+ Abbrechen
Speichern
` : `
- Abbrechen
+ Abbrechen
Speichern
`;
diff --git a/backend/static/js/pages/forum.js b/backend/static/js/pages/forum.js
index 512ed6d..7bbaa3f 100644
--- a/backend/static/js/pages/forum.js
+++ b/backend/static/js/pages/forum.js
@@ -295,7 +295,7 @@ function _fmtDate(iso) {
`;
UI.modal.open({ title: '🏆 Hund des Monats', body,
- footer: `Schließen ` });
+ footer: `Schließen ` });
document.getElementById('hdm-login-link')?.addEventListener('click', e => {
e.preventDefault(); UI.modal.close(); App.navigate('settings');
@@ -1022,7 +1022,7 @@ function _fmtDate(iso) {
`,
- footer: `Verstanden `,
+ footer: `Verstanden `,
});
}
@@ -1376,7 +1376,7 @@ function _fmtDate(iso) {
`,
footer: `
- Abbrechen
+ Abbrechen
${UI.icon('floppy-disk')} Speichern `,
});
document.getElementById(id)?.addEventListener('submit', async e => {
@@ -1423,7 +1423,7 @@ function _fmtDate(iso) {
`,
footer: `
- Abbrechen
+ Abbrechen
${UI.icon('floppy-disk')} Speichern `,
});
diff --git a/backend/static/js/pages/friends.js b/backend/static/js/pages/friends.js
index dffce5d..0ee68d9 100644
--- a/backend/static/js/pages/friends.js
+++ b/backend/static/js/pages/friends.js
@@ -27,7 +27,7 @@ window.Page_friends = (() => {
icon: UI.icon('users'),
title: 'Anmelden erforderlich',
text: 'Melde dich an, um Freunde zu finden und Anfragen zu verwalten.',
- action: `Anmelden `,
+ action: `Anmelden `,
});
return;
}
@@ -524,8 +524,7 @@ window.Page_friends = (() => {
+ title="Notiz">
{
icon: ' ',
title: 'Noch kein Hund angelegt',
text: 'Erstelle zuerst ein Hundeprofil.',
- action: `Profil erstellen `,
+ action: `Profil erstellen `,
});
return;
}
@@ -403,8 +403,7 @@ window.Page_health = (() => {
${e.notiz ? `${UI.escape(e.notiz)}
` : ''}
Notiz
+ data-label="${UI.escape(e.bezeichnung)}"> Notiz
`;
@@ -511,8 +510,7 @@ window.Page_health = (() => {
${e.notiz ? `${UI.escape(e.notiz)}
` : ''}
Notiz
+ data-label="${UI.escape(e.bezeichnung)}"> Notiz
`;
@@ -563,8 +561,7 @@ window.Page_health = (() => {
${e.notiz ? `${UI.escape(e.notiz)}
` : ''}
Notiz
+ data-label="Gewicht ${UI.escape(e.datum)}"> Notiz
`).join('');
@@ -801,8 +798,7 @@ window.Page_health = (() => {
${e.notiz ? `${UI.escape(e.notiz)}
` : ''}
Notiz
+ data-label="Läufigkeit ${UI.escape(e.datum)}"> Notiz
`;
}).join('');
@@ -839,8 +835,7 @@ window.Page_health = (() => {
${e.notiz ? `${UI.escape(e.notiz)}
` : ''}
Notiz
+ data-label="${UI.escape(e.bezeichnung)}"> Notiz
`).join('')}
@@ -880,8 +875,7 @@ window.Page_health = (() => {
${e.notiz ? `${UI.escape(e.notiz)}
` : ''}
Notiz
+ data-label="${UI.escape(e.bezeichnung)}"> Notiz
`).join('');
@@ -923,19 +917,16 @@ window.Page_health = (() => {
${e.notiz ? `${UI.escape(e.notiz)}
` : ''}
Notiz
+ data-label="${UI.escape(e.bezeichnung)}"> Notiz
${count
? ``,
- footer: `Schließen
+ footer: `Schließen
Jetzt bewerten
@@ -1998,7 +1984,7 @@ window.Page_health = (() => {
title: `${UI.escape(praxis.name)} bewerten`,
body,
footer: `
- Abbrechen
+ Abbrechen
${existing ? 'Bewertung aktualisieren' : 'Bewertung abgeben'}
@@ -2373,7 +2359,7 @@ window.Page_health = (() => {
value="${UI.escape(currentNr)}" placeholder="z.B. 276009200123456" maxlength="20">
`,
footer: `
- Abbrechen
+ Abbrechen
Speichern `,
});
document.getElementById('transponder-save-btn').addEventListener('click', async () => {
@@ -2441,11 +2427,11 @@ window.Page_health = (() => {
const b = berichte[idx];
const nav = berichte.length > 1 ? `
- ‹ Älter
${idx+1} / ${berichte.length}
- Neuer ›
` : '';
@@ -2455,10 +2441,13 @@ window.Page_health = (() => {
${fmtDate(b)}
${UI.escape(b.bericht)}
`,
});
+ // Inline-onclick wird von der CSP blockiert → per addEventListener verdrahten.
+ document.querySelector('[data-ki-nav="prev"]')
+ ?.addEventListener('click', () => { if (idx < berichte.length - 1) { idx++; showBericht(); } });
+ document.querySelector('[data-ki-nav="next"]')
+ ?.addEventListener('click', () => { if (idx > 0) { idx--; showBericht(); } });
}
- window._kiPrev = () => { if (idx < berichte.length - 1) { idx++; showBericht(); } };
- window._kiNext = () => { if (idx > 0) { idx--; showBericht(); } };
showBericht();
});
} catch (_) {
@@ -2620,15 +2609,13 @@ window.Page_health = (() => {
${adresse ? `${UI.escape(adresse)}
` : ''}
${vet.telefon ? `
` : ''}
${vet.notfall_telefon ? `
` : ''}
@@ -2718,14 +2705,13 @@ window.Page_health = (() => {
${doc.beschreibung ? `${UI.escape(doc.beschreibung)}
` : ''}
@@ -3007,7 +2993,7 @@ function _showPoiKorrekturModal(osmId, poiName, currentOh) {
Bei ernsthaften oder sich verschlechternden Symptomen sofort zum Tierarzt.
`,
footer: `
- Schließen
+ Schließen
Frage stellen `,
});
@@ -3233,7 +3219,7 @@ function _showPoiKorrekturModal(osmId, poiName, currentOh) {
`;
const footer = `
- Abbrechen
+ Abbrechen
Speichern `;
UI.modal.open({ title: existing ? 'Versicherung bearbeiten' : 'Versicherung eintragen', body, footer });
setTimeout(() => {
@@ -3385,7 +3371,7 @@ function _showPoiKorrekturModal(osmId, poiName, currentOh) {
`;
const footer = `
- Abbrechen
+ Abbrechen
Speichern `;
UI.modal.open({ title: 'Verhalten erfassen', body, footer });
setTimeout(() => {
diff --git a/backend/static/js/pages/laeufi.js b/backend/static/js/pages/laeufi.js
index 0147376..fccd8de 100644
--- a/backend/static/js/pages/laeufi.js
+++ b/backend/static/js/pages/laeufi.js
@@ -394,7 +394,7 @@ window.Page_laeufi = (() => {
`,
footer: `
- Abbrechen
+ Abbrechen
${isEdit ? 'Speichern' : 'Eintragen'} `,
});
document.getElementById('laeufi-form').addEventListener('submit', async e => {
@@ -472,7 +472,7 @@ window.Page_laeufi = (() => {
`,
footer: `
- Abbrechen
+ Abbrechen
${isEdit ? 'Speichern' : 'Eintragen'} `,
});
document.getElementById('deck-form').addEventListener('submit', async e => {
@@ -505,7 +505,7 @@ window.Page_laeufi = (() => {
title: `Progesterontests — ${_fmtDate(laeufi.beginn)}`,
body: ``,
footer: `
- Schließen
+ Schließen
${UI.icon('plus')} Test eintragen `,
});
await _loadProgContent(laeufi.id);
@@ -602,7 +602,7 @@ window.Page_laeufi = (() => {
`,
footer: `
- Abbrechen
+ Abbrechen
Eintragen `,
});
document.getElementById('prog-form').addEventListener('submit', async e => {
diff --git a/backend/static/js/pages/litters.js b/backend/static/js/pages/litters.js
index 6ef1748..4baf680 100644
--- a/backend/static/js/pages/litters.js
+++ b/backend/static/js/pages/litters.js
@@ -867,7 +867,7 @@ window.Page_litters = (() => {
`,
footer: `
- Abbrechen
+ Abbrechen
${isEdit ? 'Speichern' : 'Eintragen'} `,
});
diff --git a/backend/static/js/pages/lost.js b/backend/static/js/pages/lost.js
index 50c0a98..cdacd39 100644
--- a/backend/static/js/pages/lost.js
+++ b/backend/static/js/pages/lost.js
@@ -410,7 +410,6 @@ window.Page_lost = (() => {
⏳ Sync ausstehend
🗑 Verwerfen
@@ -419,7 +418,7 @@ window.Page_lost = (() => {
+ title="Notiz">
Notiz
` : '')}
diff --git a/backend/static/js/pages/personality.js b/backend/static/js/pages/personality.js
index 6a3bbbc..9cd4733 100644
--- a/backend/static/js/pages/personality.js
+++ b/backend/static/js/pages/personality.js
@@ -392,7 +392,7 @@ window.Page_personality = (() => {
${typ.aktivitaeten.map(a => `
${a.label} → `).join('')}
+ data-page="${a.page}">${a.label} →`).join('')}
diff --git a/backend/static/js/pages/playdate.js b/backend/static/js/pages/playdate.js
index 618a9fb..c0d04be 100644
--- a/backend/static/js/pages/playdate.js
+++ b/backend/static/js/pages/playdate.js
@@ -333,7 +333,7 @@ function _fmtDate(iso) {
icon: UI.icon('paw-print'),
title: 'Noch kein Hund',
text: 'Lege zuerst einen Hund in deinem Profil an.',
- action: `Hund anlegen `,
+ action: `Hund anlegen `,
});
return;
}
diff --git a/backend/static/js/pages/poison.js b/backend/static/js/pages/poison.js
index 71fafec..acc7e7d 100644
--- a/backend/static/js/pages/poison.js
+++ b/backend/static/js/pages/poison.js
@@ -302,7 +302,7 @@ window.Page_poison = (() => {
${_appState.user ? `
+ title="Notiz">
Notiz
` : ''}
diff --git a/backend/static/js/pages/routes.js b/backend/static/js/pages/routes.js
index 357a1e5..2ca9849 100644
--- a/backend/static/js/pages/routes.js
+++ b/backend/static/js/pages/routes.js
@@ -1946,7 +1946,7 @@ window.Page_routes = (() => {
`;
const footer = `
- Abbrechen
+ Abbrechen
${UI.icon('paper-plane-tilt')} Senden `;
UI.modal.open({ title: `${UI.icon('chat-circle-dots')} Feedback senden`, body, footer });
document.getElementById('rk-nav-fb-send')?.addEventListener('click', async () => {
@@ -1987,7 +1987,7 @@ window.Page_routes = (() => {
target="_blank" style="flex-shrink:0;margin-left:8px;color:var(--c-primary);font-size:12px">Navi
`).join('')}
`).join('');
- UI.modal.open({ title: `${UI.icon('map-pin')} POIs entlang der Route`, body, footer: `Schließen ` });
+ UI.modal.open({ title: `${UI.icon('map-pin')} POIs entlang der Route`, body, footer: `Schließen ` });
});
}
@@ -2299,7 +2299,7 @@ window.Page_routes = (() => {
const photoGallery = photos.length ? `
- ${photos.map(u => `
`).join('')}
+ ${photos.map(u => `
`).join('')}
${isOwn ? `
+
diff --git a/backend/static/js/pages/settings.js b/backend/static/js/pages/settings.js
index b55f1fb..e959070 100644
--- a/backend/static/js/pages/settings.js
+++ b/backend/static/js/pages/settings.js
@@ -321,7 +321,7 @@ window.Page_settings = (() => {
style="margin-top:2px;flex-shrink:0;accent-color:${color}">
Ich habe die AGB gelesen und stimme ihnen zu.
+ data-page="agb">AGB gelesen und stimme ihnen zu.
@@ -2396,7 +2396,7 @@ window.Page_settings = (() => {
`,
footer: `
- Abbrechen
+ Abbrechen
Link senden `,
});
document.getElementById(id)?.addEventListener('submit', async e => {
diff --git a/backend/static/js/pages/sitting.js b/backend/static/js/pages/sitting.js
index 095a8f8..647cb3c 100644
--- a/backend/static/js/pages/sitting.js
+++ b/backend/static/js/pages/sitting.js
@@ -139,8 +139,7 @@ window.Page_sitting = (() => {
${_state.user ? `
+ title="Notiz" style="color:var(--c-text-muted);margin-top:var(--space-1)">
${UI.icon('note-pencil')} ` : ''}
@@ -324,7 +323,7 @@ window.Page_sitting = (() => {
`;
const footer = `
- Abbrechen
+ Abbrechen
${UI.icon('paper-plane-tilt')} Anfrage senden
`;
UI.modal.open({ title: 'Anfrage senden', body, footer });
@@ -410,7 +409,7 @@ window.Page_sitting = (() => {
${s ? `${UI.icon('floppy-disk')} Speichern` : `${UI.icon('plus')} Profil erstellen`}
- Abbrechen
+ Abbrechen
`;
UI.modal.open({ title: s ? 'Sitter-Profil bearbeiten' : 'Sitter-Profil erstellen', body, footer });
diff --git a/backend/static/js/pages/walks.js b/backend/static/js/pages/walks.js
index dfa11ee..9633a14 100644
--- a/backend/static/js/pages/walks.js
+++ b/backend/static/js/pages/walks.js
@@ -351,8 +351,7 @@ window.Page_walks = (() => {
data-wk-note-id="${w.id}"
data-wk-note-label="${UI.escape(w.titel + ' ' + w.datum)}"
data-wk-note-ort="${UI.escape(w.ort_name || '')}"
- title="Notiz" style="color:var(--c-text-muted);font-size:var(--text-xs)"
- onclick="event.stopPropagation()">
+ title="Notiz" style="color:var(--c-text-muted);font-size:var(--text-xs)">
${UI.icon('note-pencil')} ` : ''}
`;
@@ -554,7 +553,7 @@ window.Page_walks = (() => {
: (walk.photos || []).map(p => `
+ data-lightbox-url="${UI.escape(p.url)}">
${p.user_id === _appState.user?.id || isOwn ? `
✕
@@ -637,7 +636,7 @@ window.Page_walks = (() => {
div.style.cssText = 'position:relative;aspect-ratio:1';
div.innerHTML = `
+ data-lightbox-url="${UI.escape(photo.url)}">
✕ `;
grid.appendChild(div);
@@ -1108,7 +1107,7 @@ window.Page_walks = (() => {
+ data-lightbox-url="${UI.escape(s.foto_url)}">
${UI.icon('user')} ${UI.escape(s.user_name || 'Anonym')}
${s.dog_name ? ` · 🐕 ${UI.escape(s.dog_name)}` : ''}
@@ -1169,7 +1168,7 @@ window.Page_walks = (() => {
`,
footer: `
-
Abbrechen
+
Abbrechen
Einreichen
`,
});
@@ -1366,7 +1365,7 @@ window.Page_walks = (() => {
`,
footer: `
-
Abbrechen
+
Abbrechen
Speichern
`,
});
diff --git a/backend/static/js/pages/widget.js b/backend/static/js/pages/widget.js
index 51a5579..0f15caa 100644
--- a/backend/static/js/pages/widget.js
+++ b/backend/static/js/pages/widget.js
@@ -30,7 +30,7 @@ window.Page_widget = (() => {
icon: UI.icon('dog'),
title: 'Kein Hund angelegt',
text: 'Erstelle zuerst ein Hundeprofil.',
- action: `
Profil erstellen `,
+ action: `
Profil erstellen `,
});
return;
}
diff --git a/backend/static/js/pages/wiki.js b/backend/static/js/pages/wiki.js
index b38e5cb..715ae68 100644
--- a/backend/static/js/pages/wiki.js
+++ b/backend/static/js/pages/wiki.js
@@ -80,6 +80,19 @@ window.Page_wiki = (() => {
async function init(container, appState) {
_container = container;
_appState = appState;
+
+ // Delegierter Click-Handler — Inline-onclick wird von der CSP blockiert.
+ if (!_container._wikiClickBound) {
+ _container.addEventListener('click', e => {
+ const btn = e.target.closest('[data-wiki-action]');
+ if (!btn) return;
+ const id = parseInt(btn.dataset.wikiId, 10);
+ if (btn.dataset.wikiAction === 'approve') _approveSubmission(id);
+ else if (btn.dataset.wikiAction === 'reject') _rejectSubmission(id);
+ });
+ _container._wikiClickBound = true;
+ }
+
await _render();
}
@@ -180,11 +193,11 @@ window.Page_wiki = (() => {
+ data-wiki-action="approve" data-wiki-id="${s.id}">
${UI.icon('check')} Freischalten
+ data-wiki-action="reject" data-wiki-id="${s.id}">
${UI.icon('x')} Ablehnen
@@ -1400,7 +1413,7 @@ window.Page_wiki = (() => {
${data.hinweis ? `
${UI.escape(data.hinweis)}
` : ''}
`,
- footer: `
Schließen `,
+ footer: `
Schließen `,
});
return;
}
diff --git a/backend/static/js/pages/zucht-profil.js b/backend/static/js/pages/zucht-profil.js
index b46e1a2..b92f305 100644
--- a/backend/static/js/pages/zucht-profil.js
+++ b/backend/static/js/pages/zucht-profil.js
@@ -118,8 +118,9 @@ window.Page_zucht_profil = (() => {
${UI.icon('warning')}
${UI.escape(err.message || 'Fehler beim Laden.')}
-
Zurück
+
Zurück
`;
+ _container.querySelector('#zp-back-btn')?.addEventListener('click', () => history.back());
}
}
diff --git a/backend/static/js/presse.js b/backend/static/js/presse.js
new file mode 100644
index 0000000..26a7768
--- /dev/null
+++ b/backend/static/js/presse.js
@@ -0,0 +1,11 @@
+// Presse-Seite — ausgelagert, da Inline-Script/onclick von der CSP blockiert wird.
+document.addEventListener('DOMContentLoaded', () => {
+ const btn = document.querySelector('.copy-btn');
+ btn?.addEventListener('click', () => {
+ const text = document.getElementById('boilerplate-text').innerText.replace('Kopieren', '').trim();
+ navigator.clipboard.writeText(text).then(() => {
+ btn.textContent = 'Kopiert ✓';
+ setTimeout(() => btn.textContent = 'Kopieren', 2000);
+ });
+ });
+});
diff --git a/backend/static/js/worlds.js b/backend/static/js/worlds.js
index 52f3baa..be0e629 100644
--- a/backend/static/js/worlds.js
+++ b/backend/static/js/worlds.js
@@ -1399,8 +1399,9 @@ window.Worlds = (() => {
🐾
Dein Hund wartet
Melde dich an um loszulegen
-
Anmelden
+
Anmelden
`;
+ el.querySelector('#world-login-btn')?.addEventListener('click', () => navigateTo('settings'));
return;
}
diff --git a/backend/static/js/zuechter.js b/backend/static/js/zuechter.js
new file mode 100644
index 0000000..da18f38
--- /dev/null
+++ b/backend/static/js/zuechter.js
@@ -0,0 +1,6 @@
+// Züchter-Landingpage — ausgelagert, da Inline-onclick von der CSP blockiert wird.
+// Verhindert Redirect-Loop beim Öffnen der App aus der Landingpage.
+document.addEventListener('DOMContentLoaded', () => {
+ document.querySelectorAll('[data-stay-in-app]').forEach(el =>
+ el.addEventListener('click', () => sessionStorage.setItem('by_stay_in_app', '1')));
+});
diff --git a/backend/static/landing.html b/backend/static/landing.html
index 8584afd..b243361 100644
--- a/backend/static/landing.html
+++ b/backend/static/landing.html
@@ -4,7 +4,7 @@
-
+
Ban Yaro — Die Hunde-App für Deutschland, Österreich & Schweiz
diff --git a/backend/static/presse.html b/backend/static/presse.html
index 85ee38d..8bbc68e 100644
--- a/backend/static/presse.html
+++ b/backend/static/presse.html
@@ -221,7 +221,7 @@
Über Ban Yaro — Kurztext für Redaktionen
-
Kopieren
+
Kopieren
Ban Yaro ist eine kostenlose Hunde-App für den deutschsprachigen Raum. Die App läuft als Progressive Web App direkt im Smartphone-Browser — ohne Installation über den App Store. Funktionen: Hunde-Tagebuch mit Fotos und Wetter, digitale Gesundheitsakte, interaktive Karte mit Hundewiesen und Giftköder-Alarm, Community-Forum und Trainingspläne. Gegründet 2024 von René Degelmann, Ebersberg bei München. Erreichbar unter banyaro.app.
@@ -386,16 +386,7 @@
-
+