User Panel: Phase-8-Abschluss, Titelbild/Lizenzen/Zeitzonen und KI-Pruef-Pipeline

Phase 8 (Rest) + Umbauten vom 10./11.06.:
- Ein Titelbild pro PM (Cover 1280x580), SVG-Platzhalter-Set + Picker,
  PressReleaseCoverImage-Resolver
- Lizenz-/Rechteformular nach "Lizenztyp Bildupload" (7 Lizenztypen,
  Personen-/Sachrechte-Status, bedingte Pflichtfelder, Risikohinweise)
- Veroeffentlichungs-Box vereinfacht (Embargo aus der Form-UI entfernt),
  geplante Termine in Europe/Berlin (Speicherung UTC, DISPLAY_TIMEZONE)
- Quota-Stub (users.press_release_quota) + monatlicher Reset-Command
- Einreichungs-Modal einheitlich in Show/Create/Edit; Ghost-Buttons auf
  filled; PM-Editor-Layout responsive entkoppelt (.pr-editor-layout)

KI-Pruef-Pipeline (Phasen 1-5 des Entwicklungsplans):
- API-Haertung: status nicht mehr per API setzbar, eigene Submit-Route
  durch denselben Funnel (Blacklist, Quota, Status-Log)
- Klassifikation Rot/Gelb/Gruen asynchron (Queue classification,
  OpenAI-Treiber + deterministischer Fallback), ki_audits-Audit-Log
- Routing: Rot -> rejected + Mail, Gelb -> Review-Queue, Gruen ->
  Auto-Publish; Scheduler publiziert nur gruene faellige PMs
- Content-Score 0-100 -> Stufe (Standard/Geprueft/Hochwertig) inkl.
  Editor-Panel und Badges; Re-Klassifikation/-Score bei Aenderung
- Admin: KI-Badge + Filter, On-Demand-Pruefung mit Anbieter-Override

Suite: 442 passed, 4 skipped.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-06-12 08:30:13 +00:00
parent 0efabaf446
commit a000238ca8
141 changed files with 5922 additions and 1001 deletions

View file

@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="900" viewBox="0 0 1600 900" role="img" aria-label="Platzhalter">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#1a2540"/>
<stop offset="1" stop-color="#2e3d66"/>
</linearGradient>
<pattern id="grid" width="64" height="64" patternUnits="userSpaceOnUse">
<path d="M64 0H0V64" fill="none" stroke="#ffffff" stroke-opacity="0.08" stroke-width="1"/>
</pattern>
</defs>
<rect width="1600" height="900" fill="url(#bg)"/>
<rect width="1600" height="900" fill="url(#grid)"/>
<circle cx="1240" cy="300" r="240" fill="#ffffff" fill-opacity="0.05"/>
<circle cx="320" cy="700" r="160" fill="#ffffff" fill-opacity="0.06"/>
</svg>

After

Width:  |  Height:  |  Size: 765 B

View file

@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="900" viewBox="0 0 1600 900" role="img" aria-label="Platzhalter">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#1f2e22"/>
<stop offset="1" stop-color="#3a5a3a"/>
</linearGradient>
<pattern id="grid" width="64" height="64" patternUnits="userSpaceOnUse">
<path d="M64 0H0V64" fill="none" stroke="#ffffff" stroke-opacity="0.08" stroke-width="1"/>
</pattern>
</defs>
<rect width="1600" height="900" fill="url(#bg)"/>
<rect width="1600" height="900" fill="url(#grid)"/>
<circle cx="1240" cy="300" r="240" fill="#ffffff" fill-opacity="0.05"/>
<circle cx="320" cy="700" r="160" fill="#ffffff" fill-opacity="0.06"/>
</svg>

After

Width:  |  Height:  |  Size: 765 B

View file

@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="900" viewBox="0 0 1600 900" role="img" aria-label="Platzhalter">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#2e2117"/>
<stop offset="1" stop-color="#8a5e27"/>
</linearGradient>
<pattern id="grid" width="64" height="64" patternUnits="userSpaceOnUse">
<path d="M64 0H0V64" fill="none" stroke="#ffffff" stroke-opacity="0.08" stroke-width="1"/>
</pattern>
</defs>
<rect width="1600" height="900" fill="url(#bg)"/>
<rect width="1600" height="900" fill="url(#grid)"/>
<circle cx="1240" cy="300" r="240" fill="#ffffff" fill-opacity="0.05"/>
<circle cx="320" cy="700" r="160" fill="#ffffff" fill-opacity="0.06"/>
</svg>

After

Width:  |  Height:  |  Size: 765 B

View file

@ -0,0 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="900" viewBox="0 0 1600 900" role="img" aria-label="Platzhalter">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#1a2540"/>
<stop offset="1" stop-color="#2e3d66"/>
</linearGradient>
<pattern id="lines" width="48" height="48" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
<line x1="0" y1="0" x2="0" y2="48" stroke="#ffffff" stroke-opacity="0.09" stroke-width="2"/>
</pattern>
</defs>
<rect width="1600" height="900" fill="url(#bg)"/>
<rect width="1600" height="900" fill="url(#lines)"/>
<circle cx="1300" cy="640" r="220" fill="#ffffff" fill-opacity="0.05"/>
</svg>

After

Width:  |  Height:  |  Size: 726 B

View file

@ -0,0 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="900" viewBox="0 0 1600 900" role="img" aria-label="Platzhalter">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#1f2e22"/>
<stop offset="1" stop-color="#3a5a3a"/>
</linearGradient>
<pattern id="lines" width="48" height="48" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
<line x1="0" y1="0" x2="0" y2="48" stroke="#ffffff" stroke-opacity="0.09" stroke-width="2"/>
</pattern>
</defs>
<rect width="1600" height="900" fill="url(#bg)"/>
<rect width="1600" height="900" fill="url(#lines)"/>
<circle cx="1300" cy="640" r="220" fill="#ffffff" fill-opacity="0.05"/>
</svg>

After

Width:  |  Height:  |  Size: 726 B

View file

@ -0,0 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="900" viewBox="0 0 1600 900" role="img" aria-label="Platzhalter">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#2e2117"/>
<stop offset="1" stop-color="#8a5e27"/>
</linearGradient>
<pattern id="lines" width="48" height="48" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
<line x1="0" y1="0" x2="0" y2="48" stroke="#ffffff" stroke-opacity="0.09" stroke-width="2"/>
</pattern>
</defs>
<rect width="1600" height="900" fill="url(#bg)"/>
<rect width="1600" height="900" fill="url(#lines)"/>
<circle cx="1300" cy="640" r="220" fill="#ffffff" fill-opacity="0.05"/>
</svg>

After

Width:  |  Height:  |  Size: 726 B

View file

@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="900" viewBox="0 0 1600 900" role="img" aria-label="Platzhalter">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#1a2540"/>
<stop offset="1" stop-color="#2e3d66"/>
</linearGradient>
<pattern id="dots" width="44" height="44" patternUnits="userSpaceOnUse">
<circle cx="22" cy="22" r="2.4" fill="#ffffff" fill-opacity="0.12"/>
</pattern>
</defs>
<rect width="1600" height="900" fill="url(#bg)"/>
<rect width="1600" height="900" fill="url(#dots)"/>
<circle cx="380" cy="280" r="200" fill="#ffffff" fill-opacity="0.05"/>
<circle cx="1280" cy="680" r="150" fill="#ffffff" fill-opacity="0.06"/>
</svg>

After

Width:  |  Height:  |  Size: 743 B

View file

@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="900" viewBox="0 0 1600 900" role="img" aria-label="Platzhalter">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#1f2e22"/>
<stop offset="1" stop-color="#3a5a3a"/>
</linearGradient>
<pattern id="dots" width="44" height="44" patternUnits="userSpaceOnUse">
<circle cx="22" cy="22" r="2.4" fill="#ffffff" fill-opacity="0.12"/>
</pattern>
</defs>
<rect width="1600" height="900" fill="url(#bg)"/>
<rect width="1600" height="900" fill="url(#dots)"/>
<circle cx="380" cy="280" r="200" fill="#ffffff" fill-opacity="0.05"/>
<circle cx="1280" cy="680" r="150" fill="#ffffff" fill-opacity="0.06"/>
</svg>

After

Width:  |  Height:  |  Size: 743 B

View file

@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="900" viewBox="0 0 1600 900" role="img" aria-label="Platzhalter">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#2e2117"/>
<stop offset="1" stop-color="#8a5e27"/>
</linearGradient>
<pattern id="dots" width="44" height="44" patternUnits="userSpaceOnUse">
<circle cx="22" cy="22" r="2.4" fill="#ffffff" fill-opacity="0.12"/>
</pattern>
</defs>
<rect width="1600" height="900" fill="url(#bg)"/>
<rect width="1600" height="900" fill="url(#dots)"/>
<circle cx="380" cy="280" r="200" fill="#ffffff" fill-opacity="0.05"/>
<circle cx="1280" cy="680" r="150" fill="#ffffff" fill-opacity="0.06"/>
</svg>

After

Width:  |  Height:  |  Size: 743 B

View file

@ -0,0 +1,16 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="900" viewBox="0 0 1600 900" role="img" aria-label="Platzhalter">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#1a2540"/>
<stop offset="1" stop-color="#2e3d66"/>
</linearGradient>
<pattern id="waves" width="260" height="120" patternUnits="userSpaceOnUse">
<path d="M-20 70C30 30 80 30 130 70S230 110 280 70" fill="none" stroke="#ffffff" stroke-opacity="0.10" stroke-width="4"/>
<path d="M-20 110C30 70 80 70 130 110S230 150 280 110" fill="none" stroke="#ffffff" stroke-opacity="0.06" stroke-width="3"/>
</pattern>
</defs>
<rect width="1600" height="900" fill="url(#bg)"/>
<rect width="1600" height="900" fill="url(#waves)"/>
<circle cx="1270" cy="260" r="220" fill="#ffffff" fill-opacity="0.05"/>
<circle cx="360" cy="690" r="180" fill="#ffffff" fill-opacity="0.055"/>
</svg>

After

Width:  |  Height:  |  Size: 932 B

View file

@ -0,0 +1,16 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="900" viewBox="0 0 1600 900" role="img" aria-label="Platzhalter">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#1f2e22"/>
<stop offset="1" stop-color="#3a5a3a"/>
</linearGradient>
<pattern id="waves" width="260" height="120" patternUnits="userSpaceOnUse">
<path d="M-20 70C30 30 80 30 130 70S230 110 280 70" fill="none" stroke="#ffffff" stroke-opacity="0.10" stroke-width="4"/>
<path d="M-20 110C30 70 80 70 130 110S230 150 280 110" fill="none" stroke="#ffffff" stroke-opacity="0.06" stroke-width="3"/>
</pattern>
</defs>
<rect width="1600" height="900" fill="url(#bg)"/>
<rect width="1600" height="900" fill="url(#waves)"/>
<circle cx="1270" cy="260" r="220" fill="#ffffff" fill-opacity="0.05"/>
<circle cx="360" cy="690" r="180" fill="#ffffff" fill-opacity="0.055"/>
</svg>

After

Width:  |  Height:  |  Size: 932 B

View file

@ -0,0 +1,16 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="900" viewBox="0 0 1600 900" role="img" aria-label="Platzhalter">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#2e2117"/>
<stop offset="1" stop-color="#8a5e27"/>
</linearGradient>
<pattern id="waves" width="260" height="120" patternUnits="userSpaceOnUse">
<path d="M-20 70C30 30 80 30 130 70S230 110 280 70" fill="none" stroke="#ffffff" stroke-opacity="0.10" stroke-width="4"/>
<path d="M-20 110C30 70 80 70 130 110S230 150 280 110" fill="none" stroke="#ffffff" stroke-opacity="0.06" stroke-width="3"/>
</pattern>
</defs>
<rect width="1600" height="900" fill="url(#bg)"/>
<rect width="1600" height="900" fill="url(#waves)"/>
<circle cx="1270" cy="260" r="220" fill="#ffffff" fill-opacity="0.05"/>
<circle cx="360" cy="690" r="180" fill="#ffffff" fill-opacity="0.055"/>
</svg>

After

Width:  |  Height:  |  Size: 932 B

View file

@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="900" viewBox="0 0 1600 900" role="img" aria-label="Platzhalter">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#1a2540"/>
<stop offset="1" stop-color="#2e3d66"/>
</linearGradient>
</defs>
<rect width="1600" height="900" fill="url(#bg)"/>
<rect x="170" y="190" width="520" height="42" rx="10" fill="#ffffff" fill-opacity="0.12"/>
<rect x="170" y="282" width="820" height="22" rx="8" fill="#ffffff" fill-opacity="0.08"/>
<rect x="170" y="334" width="690" height="22" rx="8" fill="#ffffff" fill-opacity="0.07"/>
<rect x="170" y="386" width="760" height="22" rx="8" fill="#ffffff" fill-opacity="0.06"/>
<rect x="1030" y="250" width="330" height="240" rx="20" fill="#ffffff" fill-opacity="0.055"/>
<path d="M1100 430L1190 340L1260 400L1305 355L1360 430H1100Z" fill="#ffffff" fill-opacity="0.10"/>
<circle cx="1290" cy="315" r="28" fill="#ffffff" fill-opacity="0.11"/>
<circle cx="1280" cy="700" r="180" fill="#ffffff" fill-opacity="0.04"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="900" viewBox="0 0 1600 900" role="img" aria-label="Platzhalter">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#1f2e22"/>
<stop offset="1" stop-color="#3a5a3a"/>
</linearGradient>
</defs>
<rect width="1600" height="900" fill="url(#bg)"/>
<rect x="170" y="190" width="520" height="42" rx="10" fill="#ffffff" fill-opacity="0.12"/>
<rect x="170" y="282" width="820" height="22" rx="8" fill="#ffffff" fill-opacity="0.08"/>
<rect x="170" y="334" width="690" height="22" rx="8" fill="#ffffff" fill-opacity="0.07"/>
<rect x="170" y="386" width="760" height="22" rx="8" fill="#ffffff" fill-opacity="0.06"/>
<rect x="1030" y="250" width="330" height="240" rx="20" fill="#ffffff" fill-opacity="0.055"/>
<path d="M1100 430L1190 340L1260 400L1305 355L1360 430H1100Z" fill="#ffffff" fill-opacity="0.10"/>
<circle cx="1290" cy="315" r="28" fill="#ffffff" fill-opacity="0.11"/>
<circle cx="1280" cy="700" r="180" fill="#ffffff" fill-opacity="0.04"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="900" viewBox="0 0 1600 900" role="img" aria-label="Platzhalter">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#2e2117"/>
<stop offset="1" stop-color="#8a5e27"/>
</linearGradient>
</defs>
<rect width="1600" height="900" fill="url(#bg)"/>
<rect x="170" y="190" width="520" height="42" rx="10" fill="#ffffff" fill-opacity="0.12"/>
<rect x="170" y="282" width="820" height="22" rx="8" fill="#ffffff" fill-opacity="0.08"/>
<rect x="170" y="334" width="690" height="22" rx="8" fill="#ffffff" fill-opacity="0.07"/>
<rect x="170" y="386" width="760" height="22" rx="8" fill="#ffffff" fill-opacity="0.06"/>
<rect x="1030" y="250" width="330" height="240" rx="20" fill="#ffffff" fill-opacity="0.055"/>
<path d="M1100 430L1190 340L1260 400L1305 355L1360 430H1100Z" fill="#ffffff" fill-opacity="0.10"/>
<circle cx="1290" cy="315" r="28" fill="#ffffff" fill-opacity="0.11"/>
<circle cx="1280" cy="700" r="180" fill="#ffffff" fill-opacity="0.04"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,16 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="900" viewBox="0 0 1600 900" role="img" aria-label="Platzhalter">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#1a2540"/>
<stop offset="1" stop-color="#2e3d66"/>
</linearGradient>
<pattern id="rings" width="180" height="180" patternUnits="userSpaceOnUse">
<circle cx="90" cy="90" r="38" fill="none" stroke="#ffffff" stroke-opacity="0.09" stroke-width="3"/>
<circle cx="90" cy="90" r="4" fill="#ffffff" fill-opacity="0.13"/>
</pattern>
</defs>
<rect width="1600" height="900" fill="url(#bg)"/>
<rect width="1600" height="900" fill="url(#rings)"/>
<path d="M260 680C510 540 710 560 960 410C1140 302 1260 260 1410 288" fill="none" stroke="#ffffff" stroke-opacity="0.12" stroke-width="8" stroke-linecap="round"/>
<circle cx="960" cy="410" r="100" fill="#ffffff" fill-opacity="0.045"/>
</svg>

After

Width:  |  Height:  |  Size: 944 B

View file

@ -0,0 +1,16 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="900" viewBox="0 0 1600 900" role="img" aria-label="Platzhalter">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#1f2e22"/>
<stop offset="1" stop-color="#3a5a3a"/>
</linearGradient>
<pattern id="rings" width="180" height="180" patternUnits="userSpaceOnUse">
<circle cx="90" cy="90" r="38" fill="none" stroke="#ffffff" stroke-opacity="0.09" stroke-width="3"/>
<circle cx="90" cy="90" r="4" fill="#ffffff" fill-opacity="0.13"/>
</pattern>
</defs>
<rect width="1600" height="900" fill="url(#bg)"/>
<rect width="1600" height="900" fill="url(#rings)"/>
<path d="M260 680C510 540 710 560 960 410C1140 302 1260 260 1410 288" fill="none" stroke="#ffffff" stroke-opacity="0.12" stroke-width="8" stroke-linecap="round"/>
<circle cx="960" cy="410" r="100" fill="#ffffff" fill-opacity="0.045"/>
</svg>

After

Width:  |  Height:  |  Size: 944 B

View file

@ -0,0 +1,16 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1600" height="900" viewBox="0 0 1600 900" role="img" aria-label="Platzhalter">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#2e2117"/>
<stop offset="1" stop-color="#8a5e27"/>
</linearGradient>
<pattern id="rings" width="180" height="180" patternUnits="userSpaceOnUse">
<circle cx="90" cy="90" r="38" fill="none" stroke="#ffffff" stroke-opacity="0.09" stroke-width="3"/>
<circle cx="90" cy="90" r="4" fill="#ffffff" fill-opacity="0.13"/>
</pattern>
</defs>
<rect width="1600" height="900" fill="url(#bg)"/>
<rect width="1600" height="900" fill="url(#rings)"/>
<path d="M260 680C510 540 710 560 960 410C1140 302 1260 260 1410 288" fill="none" stroke="#ffffff" stroke-opacity="0.12" stroke-width="8" stroke-linecap="round"/>
<circle cx="960" cy="410" r="100" fill="#ffffff" fill-opacity="0.045"/>
</svg>

After

Width:  |  Height:  |  Size: 944 B