Quellen-Seite: PDF-Thumbnails der ersten Seite + Thumbnail-API-Endpoint
This commit is contained in:
parent
11e4da0bf3
commit
ee08cb0c29
31
app/main.py
31
app/main.py
@ -875,6 +875,37 @@ neu analysiert, um verifizierte Zitate zu erzeugen.</p>
|
||||
)
|
||||
|
||||
|
||||
@app.get("/api/programme/thumbnail/{programm_id}")
|
||||
async def programme_thumbnail(programm_id: str):
|
||||
"""Thumbnail der ersten Seite eines Wahlprogramm-PDFs (PNG, 200px breit).
|
||||
|
||||
Wird auf der Quellen-Seite als Vorschau angezeigt. Cached 24h.
|
||||
"""
|
||||
import fitz
|
||||
if programm_id not in PROGRAMME:
|
||||
raise HTTPException(status_code=404)
|
||||
info = PROGRAMME[programm_id]
|
||||
pdf_path = static_dir / "referenzen" / info["pdf"]
|
||||
if not pdf_path.exists():
|
||||
raise HTTPException(status_code=404)
|
||||
try:
|
||||
doc = fitz.open(str(pdf_path))
|
||||
page = doc[0]
|
||||
# 200px Breite, proportional skaliert
|
||||
zoom = 200 / page.rect.width
|
||||
mat = fitz.Matrix(zoom, zoom)
|
||||
pix = page.get_pixmap(matrix=mat)
|
||||
png_bytes = pix.tobytes("png")
|
||||
doc.close()
|
||||
return Response(
|
||||
content=png_bytes,
|
||||
media_type="image/png",
|
||||
headers={"Cache-Control": "public, max-age=86400"},
|
||||
)
|
||||
except Exception:
|
||||
raise HTTPException(status_code=500)
|
||||
|
||||
|
||||
@app.get("/api/programme")
|
||||
async def list_programme():
|
||||
"""List all available programmes."""
|
||||
|
||||
@ -221,7 +221,13 @@
|
||||
<h2>Wahlprogramme NRW 2022</h2>
|
||||
<div class="programme-grid">
|
||||
{% for prog in programmes if prog.typ == 'wahlprogramm' %}
|
||||
<div class="programme-card">
|
||||
<div class="programme-card" style="display: flex; gap: 1rem;">
|
||||
<a href="{{ prog.pdf_url }}" target="_blank" style="flex-shrink: 0;">
|
||||
<img src="/api/programme/thumbnail/{{ prog.id }}" alt="{{ prog.name }}"
|
||||
style="width: 80px; border: 1px solid #ddd; border-radius: 4px;"
|
||||
loading="lazy" onerror="this.style.display='none'">
|
||||
</a>
|
||||
<div>
|
||||
<h3>
|
||||
<span class="programme-badge badge-{{ prog.partei|lower }}">{{ prog.partei }}</span>
|
||||
{{ prog.name }}
|
||||
@ -230,7 +236,7 @@
|
||||
<span class="programme-badge badge-wahlprogramm">Wahlprogramm</span>
|
||||
{% if prog.bundesland %}{{ prog.bundesland }}{% endif %}
|
||||
</div>
|
||||
<div style="margin-top: 1rem;">
|
||||
<div style="margin-top: 0.5rem;">
|
||||
<a href="{{ prog.pdf_url }}" target="_blank" class="btn btn-primary">
|
||||
📄 PDF herunterladen
|
||||
</a>
|
||||
@ -240,14 +246,21 @@
|
||||
</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
|
||||
<h2>Grundsatzprogramme</h2>
|
||||
<div class="programme-grid">
|
||||
{% for prog in programmes if prog.typ == 'parteiprogramm' %}
|
||||
<div class="programme-card">
|
||||
<div class="programme-card" style="display: flex; gap: 1rem;">
|
||||
<a href="{{ prog.pdf_url }}" target="_blank" style="flex-shrink: 0;">
|
||||
<img src="/api/programme/thumbnail/{{ prog.id }}" alt="{{ prog.name }}"
|
||||
style="width: 80px; border: 1px solid #ddd; border-radius: 4px;"
|
||||
loading="lazy" onerror="this.style.display='none'">
|
||||
</a>
|
||||
<div>
|
||||
<h3>
|
||||
<span class="programme-badge badge-{{ prog.partei|lower }}">{{ prog.partei }}</span>
|
||||
{{ prog.name }}
|
||||
@ -255,7 +268,7 @@
|
||||
<div class="programme-meta">
|
||||
<span class="programme-badge badge-parteiprogramm">Grundsatzprogramm</span>
|
||||
</div>
|
||||
<div style="margin-top: 1rem;">
|
||||
<div style="margin-top: 0.5rem;">
|
||||
<a href="{{ prog.pdf_url }}" target="_blank" class="btn btn-primary">
|
||||
📄 PDF herunterladen
|
||||
</a>
|
||||
@ -265,6 +278,7 @@
|
||||
</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user