Feature: Moderation — Forum-Meldungen + POI-Korrekturen, SW by-v589
This commit is contained in:
parent
020153484a
commit
e2cd32a550
3 changed files with 127 additions and 5 deletions
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -1474,14 +1474,19 @@ window.Page_admin = (() => {
|
|||
async function _loadModeration(el) {
|
||||
el.innerHTML = `<div style="padding:var(--space-4);text-align:center;color:var(--c-text-muted)">Lade…</div>`;
|
||||
|
||||
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 = (() => {
|
|||
</div>`;
|
||||
}
|
||||
|
||||
// --- Forum-Meldungen ---
|
||||
html += `<h3 style="font-size:var(--text-sm);font-weight:var(--weight-semibold);
|
||||
color:var(--c-text-muted);text-transform:uppercase;letter-spacing:.06em;
|
||||
margin:var(--space-6) 0 var(--space-3)">
|
||||
Forum-Meldungen
|
||||
<span style="background:${reports.length ? 'var(--c-danger)' : 'var(--c-primary)'};color:#fff;
|
||||
border-radius:999px;padding:1px 8px;font-size:var(--text-xs);margin-left:6px">
|
||||
${reports.length}
|
||||
</span>
|
||||
</h3>`;
|
||||
if (!reports.length) {
|
||||
html += `<p style="font-size:var(--text-sm);color:var(--c-text-muted);margin-bottom:var(--space-6)">Keine offenen Meldungen.</p>`;
|
||||
} else {
|
||||
html += `<div style="display:flex;flex-direction:column;gap:var(--space-3);margin-bottom:var(--space-6)">
|
||||
${reports.map(r => `
|
||||
<div class="card" style="padding:var(--space-4);border-left:3px solid var(--c-danger)">
|
||||
<div style="display:flex;align-items:flex-start;gap:var(--space-3)">
|
||||
<div style="flex:1;min-width:0">
|
||||
<div style="font-size:var(--text-xs);color:var(--c-text-muted);margin-bottom:var(--space-1)">
|
||||
${_esc(r.target_type)} #${r.target_id} · Gemeldet von <strong>${_esc(r.melder_name || '?')}</strong>
|
||||
</div>
|
||||
<div style="font-size:var(--text-sm);font-weight:var(--weight-semibold);margin-bottom:var(--space-1)">
|
||||
Grund: ${_esc(r.grund)}
|
||||
</div>
|
||||
${r.content_preview ? `
|
||||
<div style="font-size:var(--text-xs);color:var(--c-text-secondary);
|
||||
padding:var(--space-2) var(--space-3);background:var(--c-surface-2);
|
||||
border-radius:var(--radius-sm)">${_esc(r.content_preview)}</div>` : ''}
|
||||
</div>
|
||||
<button class="btn btn-sm btn-primary adm-mod-resolve" data-rid="${r.id}" title="Als erledigt markieren">
|
||||
${UI.icon('check')}
|
||||
</button>
|
||||
</div>
|
||||
</div>`).join('')}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
// --- POI-Korrekturen ---
|
||||
html += `<h3 style="font-size:var(--text-sm);font-weight:var(--weight-semibold);
|
||||
color:var(--c-text-muted);text-transform:uppercase;letter-spacing:.06em;
|
||||
margin:var(--space-2) 0 var(--space-3)">
|
||||
POI-Korrekturen
|
||||
<span style="background:${poiPending.length ? 'var(--c-warning,#e65100)' : 'var(--c-primary)'};color:#fff;
|
||||
border-radius:999px;padding:1px 8px;font-size:var(--text-xs);margin-left:6px">
|
||||
${poiPending.length}
|
||||
</span>
|
||||
</h3>`;
|
||||
if (!poiPending.length) {
|
||||
html += `<p style="font-size:var(--text-sm);color:var(--c-text-muted)">Keine ausstehenden POI-Korrekturen.</p>`;
|
||||
} else {
|
||||
html += `<div class="card adm-table-card"><div class="adm-table-scroll">
|
||||
<table class="adm-table">
|
||||
<thead><tr style="background:var(--c-surface-2);text-align:left">
|
||||
<th class="adm-th">Ort</th>
|
||||
<th class="adm-th">Feld</th>
|
||||
<th class="adm-th">Alt</th>
|
||||
<th class="adm-th">Neu</th>
|
||||
<th class="adm-th">Von</th>
|
||||
<th class="adm-th"></th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
${poiPending.map((e, i) => `
|
||||
<tr style="${i%2===1?'background:var(--c-surface-2)':''}">
|
||||
<td class="adm-td" style="font-weight:var(--weight-semibold)">${_esc(e.poi_name || `OSM #${e.osm_id}`)}</td>
|
||||
<td class="adm-td"><code style="font-size:var(--text-xs)">${_esc(e.field)}</code></td>
|
||||
<td class="adm-td" style="color:var(--c-text-muted);font-size:var(--text-xs)">${_esc(e.old_value || '—')}</td>
|
||||
<td class="adm-td" style="font-size:var(--text-xs)">${_esc(e.new_value || '—')}</td>
|
||||
<td class="adm-td" style="color:var(--c-text-muted)">${_esc(e.einreicher_name || '?')}</td>
|
||||
<td class="adm-td" style="text-align:right;white-space:nowrap">
|
||||
<button class="btn btn-sm btn-primary adm-poi-approve" data-id="${e.id}" style="margin-right:4px">
|
||||
${UI.icon('check')}
|
||||
</button>
|
||||
<button class="btn btn-sm btn-ghost adm-poi-reject" data-id="${e.id}" style="color:var(--c-danger)">
|
||||
${UI.icon('x')}
|
||||
</button>
|
||||
</td>
|
||||
</tr>`).join('')}
|
||||
</tbody>
|
||||
</table>
|
||||
</div></div>`;
|
||||
}
|
||||
|
||||
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; }
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue