Wiki: Bildrechte-Bestätigung bei Foto-Einreichung (Checkbox + DB + Mod-Badge), SW by-v363
This commit is contained in:
parent
de73c7901e
commit
d603b7bae1
6 changed files with 42 additions and 7 deletions
|
|
@ -532,6 +532,8 @@ def _migrate(conn_factory):
|
|||
("dogs", "rasse_id", "INTEGER"),
|
||||
# Pflege: Schere vs. Trimmen unterscheiden
|
||||
("pflege_tipps", "fell_pflege_art", "TEXT"),
|
||||
# Wiki-Foto-Einreichungen: Bildrechte-Bestätigung
|
||||
("wiki_foto_submissions", "rights_confirmed", "INTEGER NOT NULL DEFAULT 0"),
|
||||
]
|
||||
with conn_factory() as conn:
|
||||
for table, column, col_type in migrations:
|
||||
|
|
|
|||
|
|
@ -173,6 +173,7 @@ async def mod_fotos(user=Depends(require_moderator)):
|
|||
try:
|
||||
rows = conn.execute("""
|
||||
SELECT s.id, s.rasse_slug, s.foto_url, s.created_at,
|
||||
COALESCE(s.rights_confirmed, 0) AS rights_confirmed,
|
||||
u.name AS user_name,
|
||||
r.name AS rasse_name, r.foto_url AS aktuell_foto
|
||||
FROM wiki_foto_submissions s
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import os
|
|||
import shutil
|
||||
import time
|
||||
import logging
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, Request, UploadFile, File
|
||||
from fastapi import APIRouter, Depends, Form, HTTPException, Query, Request, UploadFile, File
|
||||
from fastapi.responses import JSONResponse
|
||||
from pydantic import BaseModel
|
||||
from database import db
|
||||
|
|
@ -290,6 +290,7 @@ async def quiz_result(
|
|||
async def submit_foto(
|
||||
slug: str,
|
||||
file: UploadFile = File(...),
|
||||
rights_confirmed: int = Form(0),
|
||||
user = Depends(get_current_user),
|
||||
):
|
||||
with db() as conn:
|
||||
|
|
@ -299,6 +300,9 @@ async def submit_foto(
|
|||
if not rasse:
|
||||
raise HTTPException(404, "Rasse nicht gefunden.")
|
||||
|
||||
if not rights_confirmed:
|
||||
raise HTTPException(400, "Bildrechte-Bestätigung fehlt.")
|
||||
|
||||
# Dateiformat prüfen
|
||||
ct = file.content_type or ""
|
||||
if not ct.startswith("image/"):
|
||||
|
|
@ -336,9 +340,9 @@ async def submit_foto(
|
|||
)
|
||||
|
||||
conn.execute("""
|
||||
INSERT INTO wiki_foto_submissions (user_id, rasse_id, foto_url)
|
||||
VALUES (?,?,?)
|
||||
""", (user["id"], rasse["id"], local_url))
|
||||
INSERT INTO wiki_foto_submissions (user_id, rasse_id, foto_url, rights_confirmed)
|
||||
VALUES (?,?,?,?)
|
||||
""", (user["id"], rasse["id"], local_url, 1))
|
||||
|
||||
logger.info(f"Foto-Einreichung: {rasse['name']} von User {user['id']}")
|
||||
return {"ok": True, "foto_url": local_url}
|
||||
|
|
|
|||
|
|
@ -172,9 +172,16 @@ window.Page_moderation = (() => {
|
|||
${_esc(f.rasse_name || f.rasse_slug)}
|
||||
</div>
|
||||
<div style="font-size:var(--text-xs);color:var(--c-text-muted);
|
||||
margin-bottom:var(--space-3)">
|
||||
margin-bottom:var(--space-2)">
|
||||
von ${_esc(f.user_name)}
|
||||
</div>
|
||||
<div style="margin-bottom:var(--space-3)">
|
||||
${f.rights_confirmed
|
||||
? `<span style="font-size:10px;font-weight:700;padding:2px 8px;border-radius:20px;
|
||||
background:#dcfce7;color:#166534">✓ Bildrechte bestätigt</span>`
|
||||
: `<span style="font-size:10px;font-weight:700;padding:2px 8px;border-radius:20px;
|
||||
background:#fef9c3;color:#92400e">⚠ Keine Bestätigung</span>`}
|
||||
</div>
|
||||
${f.aktuell_foto ? `
|
||||
<img src="${_esc(f.aktuell_foto)}" alt="Aktuell"
|
||||
style="width:100%;height:80px;object-fit:cover;
|
||||
|
|
|
|||
|
|
@ -847,11 +847,23 @@ window.Page_wiki = (() => {
|
|||
<div id="wiki-foto-preview" style="margin-top:var(--space-3);display:none">
|
||||
<img id="wiki-foto-preview-img" style="max-width:100%;max-height:200px;border-radius:var(--radius-md);object-fit:contain">
|
||||
</div>
|
||||
<div style="margin-top:var(--space-4);padding:var(--space-3);
|
||||
background:var(--c-surface-2);border-radius:var(--radius-md);
|
||||
border-left:3px solid var(--c-warning)">
|
||||
<label style="display:flex;gap:var(--space-3);align-items:flex-start;cursor:pointer">
|
||||
<input type="checkbox" id="wiki-foto-rights" style="margin-top:3px;flex-shrink:0">
|
||||
<span style="font-size:var(--text-sm);line-height:1.5">
|
||||
Ich bestätige, dass ich die <strong>uneingeschränkten Bildrechte</strong> an diesem Foto besitze
|
||||
und banyaro.app das dauerhaft gültige, kostenlose Recht einräume, es zu veröffentlichen und zu
|
||||
verwenden. Fotos aus dem Internet oder von Dritten dürfen nicht eingereicht werden.
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
`;
|
||||
const footer = `
|
||||
<button type="button" class="btn btn-secondary flex-1" id="wiki-foto-cancel">Abbrechen</button>
|
||||
<button type="submit" form="wiki-foto-form" class="btn btn-primary flex-1" id="wiki-foto-submit">
|
||||
<button type="submit" form="wiki-foto-form" class="btn btn-primary flex-1" id="wiki-foto-submit" disabled>
|
||||
${UI.icon('paper-plane-tilt')} Einreichen
|
||||
</button>
|
||||
`;
|
||||
|
|
@ -859,6 +871,10 @@ window.Page_wiki = (() => {
|
|||
UI.modal.open({ title: 'Foto vorschlagen', body, footer });
|
||||
document.getElementById('wiki-foto-cancel')?.addEventListener('click', UI.modal.close);
|
||||
|
||||
document.getElementById('wiki-foto-rights')?.addEventListener('change', e => {
|
||||
document.getElementById('wiki-foto-submit').disabled = !e.target.checked;
|
||||
});
|
||||
|
||||
document.getElementById('wiki-foto-input')?.addEventListener('change', e => {
|
||||
const file = e.target.files?.[0];
|
||||
if (!file) return;
|
||||
|
|
@ -874,6 +890,10 @@ window.Page_wiki = (() => {
|
|||
const input = document.getElementById('wiki-foto-input');
|
||||
const file = input?.files?.[0];
|
||||
if (!file) return;
|
||||
if (!document.getElementById('wiki-foto-rights')?.checked) {
|
||||
UI.toast('Bitte Bildrechte bestätigen.', 'danger');
|
||||
return;
|
||||
}
|
||||
|
||||
const btn = document.getElementById('wiki-foto-submit');
|
||||
btn.disabled = true;
|
||||
|
|
@ -882,6 +902,7 @@ window.Page_wiki = (() => {
|
|||
try {
|
||||
const fd = new FormData();
|
||||
fd.append('file', file);
|
||||
fd.append('rights_confirmed', '1');
|
||||
const token = localStorage.getItem('by_token');
|
||||
const resp = await fetch(`/api/wiki/rassen/${encodeURIComponent(slug)}/foto`, {
|
||||
method: 'POST',
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Offline-Cache + Push Notifications + Tile-Cache
|
||||
============================================================ */
|
||||
|
||||
const CACHE_VERSION = 'by-v362';
|
||||
const CACHE_VERSION = 'by-v363';
|
||||
const CACHE_STATIC = `${CACHE_VERSION}-static`;
|
||||
const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue