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")
|
@app.get("/api/programme")
|
||||||
async def list_programme():
|
async def list_programme():
|
||||||
"""List all available programmes."""
|
"""List all available programmes."""
|
||||||
|
|||||||
@ -221,7 +221,13 @@
|
|||||||
<h2>Wahlprogramme NRW 2022</h2>
|
<h2>Wahlprogramme NRW 2022</h2>
|
||||||
<div class="programme-grid">
|
<div class="programme-grid">
|
||||||
{% for prog in programmes if prog.typ == 'wahlprogramm' %}
|
{% 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>
|
<h3>
|
||||||
<span class="programme-badge badge-{{ prog.partei|lower }}">{{ prog.partei }}</span>
|
<span class="programme-badge badge-{{ prog.partei|lower }}">{{ prog.partei }}</span>
|
||||||
{{ prog.name }}
|
{{ prog.name }}
|
||||||
@ -230,7 +236,7 @@
|
|||||||
<span class="programme-badge badge-wahlprogramm">Wahlprogramm</span>
|
<span class="programme-badge badge-wahlprogramm">Wahlprogramm</span>
|
||||||
{% if prog.bundesland %}{{ prog.bundesland }}{% endif %}
|
{% if prog.bundesland %}{{ prog.bundesland }}{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div style="margin-top: 1rem;">
|
<div style="margin-top: 0.5rem;">
|
||||||
<a href="{{ prog.pdf_url }}" target="_blank" class="btn btn-primary">
|
<a href="{{ prog.pdf_url }}" target="_blank" class="btn btn-primary">
|
||||||
📄 PDF herunterladen
|
📄 PDF herunterladen
|
||||||
</a>
|
</a>
|
||||||
@ -241,13 +247,20 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2>Grundsatzprogramme</h2>
|
<h2>Grundsatzprogramme</h2>
|
||||||
<div class="programme-grid">
|
<div class="programme-grid">
|
||||||
{% for prog in programmes if prog.typ == 'parteiprogramm' %}
|
{% 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>
|
<h3>
|
||||||
<span class="programme-badge badge-{{ prog.partei|lower }}">{{ prog.partei }}</span>
|
<span class="programme-badge badge-{{ prog.partei|lower }}">{{ prog.partei }}</span>
|
||||||
{{ prog.name }}
|
{{ prog.name }}
|
||||||
@ -255,7 +268,7 @@
|
|||||||
<div class="programme-meta">
|
<div class="programme-meta">
|
||||||
<span class="programme-badge badge-parteiprogramm">Grundsatzprogramm</span>
|
<span class="programme-badge badge-parteiprogramm">Grundsatzprogramm</span>
|
||||||
</div>
|
</div>
|
||||||
<div style="margin-top: 1rem;">
|
<div style="margin-top: 0.5rem;">
|
||||||
<a href="{{ prog.pdf_url }}" target="_blank" class="btn btn-primary">
|
<a href="{{ prog.pdf_url }}" target="_blank" class="btn btn-primary">
|
||||||
📄 PDF herunterladen
|
📄 PDF herunterladen
|
||||||
</a>
|
</a>
|
||||||
@ -266,6 +279,7 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user