From e2cd32a5505be77e82ed636c72843e5fe6c6d01a Mon Sep 17 00:00:00 2001 From: rene Date: Fri, 1 May 2026 19:37:46 +0200 Subject: [PATCH] =?UTF-8?q?Feature:=20Moderation=20=E2=80=94=20Forum-Meldu?= =?UTF-8?q?ngen=20+=20POI-Korrekturen,=20SW=20by-v589?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/static/js/app.js | 2 +- backend/static/js/pages/admin.js | 128 ++++++++++++++++++++++++++++++- backend/static/sw.js | 2 +- 3 files changed, 127 insertions(+), 5 deletions(-) diff --git a/backend/static/js/app.js b/backend/static/js/app.js index 1db5ad9..bdb4e29 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 = '588'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen +const APP_VER = '589'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen const APP_VERSION = '1.2.1'; // ← semantische Version, wird bei make release gesetzt const IS_STAGING = location.hostname === 'staging.banyaro.app'; diff --git a/backend/static/js/pages/admin.js b/backend/static/js/pages/admin.js index fa8df59..6809ee0 100644 --- a/backend/static/js/pages/admin.js +++ b/backend/static/js/pages/admin.js @@ -1474,14 +1474,19 @@ window.Page_admin = (() => { async function _loadModeration(el) { el.innerHTML = `
Lade…
`; - const [zuchter, fotos] = await Promise.all([ + const [zuchter, fotos, reports, poiEdits] = await Promise.all([ API.get('/wiki/zuchter/pending').catch(() => []), API.get('/wiki/foto-submissions').catch(() => []), + API.get('/moderation/reports').catch(() => []), + API.get('/moderation/poi-edits').catch(() => []), ]); + const poiPending = poiEdits.filter(e => e.status === 'pending'); const modItems = [ - { label: 'Züchter-Einreichungen', count: zuchter.length, icon: 'certificate' }, - { label: 'Foto-Einreichungen', count: fotos.length, icon: 'image' }, + { label: 'Züchter-Einreichungen', count: zuchter.length, icon: 'certificate' }, + { label: 'Foto-Einreichungen', count: fotos.length, icon: 'image' }, + { label: 'Forum-Meldungen', count: reports.length, icon: 'warning' }, + { label: 'POI-Korrekturen', count: poiPending.length, icon: 'map-pin' }, ].filter(i => i.count > 0); let html = ` @@ -1572,6 +1577,88 @@ window.Page_admin = (() => { `; } + // --- Forum-Meldungen --- + html += `

+ Forum-Meldungen + + ${reports.length} + +

`; + if (!reports.length) { + html += `

Keine offenen Meldungen.

`; + } else { + html += `
+ ${reports.map(r => ` +
+
+
+
+ ${_esc(r.target_type)} #${r.target_id} · Gemeldet von ${_esc(r.melder_name || '?')} +
+
+ Grund: ${_esc(r.grund)} +
+ ${r.content_preview ? ` +
${_esc(r.content_preview)}
` : ''} +
+ +
+
`).join('')} +
`; + } + + // --- POI-Korrekturen --- + html += `

+ POI-Korrekturen + + ${poiPending.length} + +

`; + if (!poiPending.length) { + html += `

Keine ausstehenden POI-Korrekturen.

`; + } else { + html += `
+ + + + + + + + + + + ${poiPending.map((e, i) => ` + + + + + + + + `).join('')} + +
OrtFeldAltNeuVon
${_esc(e.poi_name || `OSM #${e.osm_id}`)}${_esc(e.field)}${_esc(e.old_value || '—')}${_esc(e.new_value || '—')}${_esc(e.einreicher_name || '?')} + + +
+
`; + } + el.innerHTML = html; // Züchter freigeben @@ -1610,6 +1697,41 @@ window.Page_admin = (() => { await _loadModeration(el); }); }); + + // Forum-Meldung erledigen + el.querySelectorAll('.adm-mod-resolve').forEach(btn => { + btn.addEventListener('click', async () => { + btn.disabled = true; + try { + await API.patch(`/moderation/reports/${btn.dataset.rid}`, {}); + await _loadModeration(el); + } catch (e) { UI.toast.error(e.message); btn.disabled = false; } + }); + }); + + // POI-Korrektur freigeben + el.querySelectorAll('.adm-poi-approve').forEach(btn => { + btn.addEventListener('click', async () => { + btn.disabled = true; + try { + await API.patch(`/moderation/poi-edits/${btn.dataset.id}`, { action: 'approve' }); + UI.toast.success('Korrektur übernommen.'); + await _loadModeration(el); + } catch (e) { UI.toast.error(e.message); btn.disabled = false; } + }); + }); + + // POI-Korrektur ablehnen + el.querySelectorAll('.adm-poi-reject').forEach(btn => { + btn.addEventListener('click', async () => { + btn.disabled = true; + try { + await API.patch(`/moderation/poi-edits/${btn.dataset.id}`, { action: 'reject' }); + UI.toast.success('Korrektur abgelehnt.'); + await _loadModeration(el); + } catch (e) { UI.toast.error(e.message); btn.disabled = false; } + }); + }); } // ------------------------------------------------------------------ diff --git a/backend/static/sw.js b/backend/static/sw.js index 57beb81..48d8c56 100644 --- a/backend/static/sw.js +++ b/backend/static/sw.js @@ -3,7 +3,7 @@ Offline-Cache + Push Notifications + Tile-Cache ============================================================ */ -const CACHE_VERSION = 'by-v588'; +const CACHE_VERSION = 'by-v589'; 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