224 lines
10 KiB
HTML
224 lines
10 KiB
HTML
<!doctype html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
<title>{{ title }}</title>
|
|
<link rel="stylesheet" href="/admin/static/admin.css" />
|
|
</head>
|
|
<body>
|
|
<header class="topbar">
|
|
<div>
|
|
<h1>Artikel-Detail #{{ article.id }}</h1>
|
|
<p>Angemeldet als <strong>{{ user }}</strong></p>
|
|
</div>
|
|
<div class="row">
|
|
<a class="linkbtn" href="/admin/dashboard">Zurück</a>
|
|
<form method="post" action="/admin/logout">
|
|
<button type="submit" class="secondary">Logout</button>
|
|
</form>
|
|
</div>
|
|
</header>
|
|
|
|
<main class="container">
|
|
{% if flash_msg %}
|
|
<section class="card flash {{ 'flash-error' if flash_type == 'error' else 'flash-success' }}">
|
|
{{ flash_msg }}
|
|
</section>
|
|
{% endif %}
|
|
|
|
<section class="card">
|
|
<h2>{{ article.title }}</h2>
|
|
<div class="detail-grid">
|
|
<div class="detail-item"><span class="k">Status</span><span><span class="badge">{{ article.status_ui }}</span></span></div>
|
|
<div class="detail-item"><span class="k">Artikel-Datum</span><span>{{ article.published_at or "-" }}</span></div>
|
|
<div class="detail-item"><span class="k">Alter</span><span>{{ article.days_old if article.days_old is not none else "-" }} Tage</span></div>
|
|
<div class="detail-item"><span class="k">Relevanz</span><span>{{ article.relevance }}</span></div>
|
|
<div class="detail-item"><span class="k">Autor</span><span>{{ article.author or "-" }}</span></div>
|
|
<div class="detail-item"><span class="k">Feed</span><span>{{ feed.name if feed else "-" }}</span></div>
|
|
<div class="detail-item"><span class="k">Quelle Snapshot</span><span>{{ article.source_name_snapshot or "-" }}</span></div>
|
|
<div class="detail-item"><span class="k">Lizenz Snapshot</span><span>{{ article.source_license_name_snapshot or "-" }}</span></div>
|
|
<div class="detail-item"><span class="k">Terms Snapshot</span><span>{{ article.source_terms_url_snapshot or "-" }}</span></div>
|
|
</div>
|
|
<p><strong>Quelle:</strong> <a href="{{ article.source_url }}" target="_blank" rel="noopener">{{ article.source_url }}</a></p>
|
|
{% if article.canonical_url %}<p><strong>Canonical:</strong> <a href="{{ article.canonical_url }}" target="_blank" rel="noopener">{{ article.canonical_url }}</a></p>{% endif %}
|
|
{% if article.summary %}
|
|
<p><strong>Summary:</strong> {{ article.summary }}</p>
|
|
{% endif %}
|
|
<p><strong>WordPress Post:</strong>
|
|
{% if article.wp_post_url %}
|
|
<a href="{{ article.wp_post_url }}" target="_blank" rel="noopener">#{{ article.wp_post_id }}</a>
|
|
{% elif article.wp_post_id %}
|
|
#{{ article.wp_post_id }}
|
|
{% else %}
|
|
-
|
|
{% endif %}
|
|
</p>
|
|
<p><strong>Publish Attempts:</strong> {{ article.publish_attempts or 0 }} | <strong>Letzter Fehler:</strong> {{ article.publish_last_error or "-" }}</p>
|
|
</section>
|
|
|
|
<section class="card">
|
|
<h2>Checkliste</h2>
|
|
<table>
|
|
<thead>
|
|
<tr><th>Kriterium</th><th>Status</th><th>Wert</th></tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for c in checklist %}
|
|
<tr>
|
|
<td>{{ c.label }}</td>
|
|
<td>
|
|
{% if c.status == "ok" %}
|
|
<span class="badge ok">OK</span>
|
|
{% else %}
|
|
<span class="badge bad">Fehlt</span>
|
|
{% endif %}
|
|
</td>
|
|
<td>{{ c.value }}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</section>
|
|
|
|
<section class="card">
|
|
<h2>Extrahierte Daten</h2>
|
|
<p><strong>Bilder:</strong> {{ article.image_entries|length if article.image_entries else 0 }}</p>
|
|
{% if article.selected_image_url %}
|
|
<p><strong>Ausgewähltes Hauptbild:</strong> <a href="{{ article.selected_image_url }}" target="_blank" rel="noopener">{{ article.selected_image_url }}</a></p>
|
|
{% if article.selected_image_proxy_url %}
|
|
<img src="{{ article.selected_image_proxy_url }}" alt="Ausgewähltes Hauptbild" class="thumb" loading="lazy" />
|
|
{% endif %}
|
|
{% endif %}
|
|
{% if article.image_entries %}
|
|
{% if article.image_selection %}
|
|
<details>
|
|
<summary>Automatische Bildauswahl (Score + Gründe)</summary>
|
|
<div class="subtle">Primärbild (Auto): {{ article.image_selection.primary or "-" }}</div>
|
|
<div class="subtle">Ausgewählt: {{ article.image_selection.selected_count or 0 }} / Kandidaten: {{ article.image_selection.total_candidates or 0 }}</div>
|
|
{% if article.image_selection.ranked %}
|
|
<table>
|
|
<thead>
|
|
<tr><th>Bild</th><th>Score</th><th>Gründe</th></tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for r in article.image_selection.ranked %}
|
|
<tr>
|
|
<td><a href="{{ r.url }}" target="_blank" rel="noopener">{{ r.url }}</a></td>
|
|
<td>{{ r.score }}</td>
|
|
<td>{{ r.reasons|join(", ") if r.reasons else "-" }}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% endif %}
|
|
</details>
|
|
{% endif %}
|
|
<div class="image-grid">
|
|
{% for image in article.image_entries %}
|
|
<article class="image-card {{ 'image-selected' if image.is_selected else '' }} {{ 'image-excluded' if image.is_excluded else '' }}">
|
|
<a href="{{ image.url }}" target="_blank" rel="noopener">
|
|
<img src="{{ image.proxy_url }}" data-fallback-src="{{ image.url }}" alt="Artikelbild" loading="lazy" onerror="if(!this.dataset.fallbackUsed){this.dataset.fallbackUsed='1';this.src=this.dataset.fallbackSrc;}else{this.classList.add('img-failed');}" />
|
|
</a>
|
|
<div class="image-meta">
|
|
{% if image.is_selected %}<span class="badge ok">Ausgewählt</span>{% endif %}
|
|
{% if image.is_excluded %}<span class="badge bad">Ausgeblendet</span>{% endif %}
|
|
{% if image.is_irrelevant_hint %}<span class="badge">evtl. irrelevant</span>{% endif %}
|
|
</div>
|
|
<div class="image-actions">
|
|
<form method="post" action="/admin/articles/{{ article.id }}/images/decision">
|
|
<input type="hidden" name="image_url" value="{{ image.url }}" />
|
|
<input type="hidden" name="action" value="select" />
|
|
<button type="submit">Als Hauptbild</button>
|
|
</form>
|
|
{% if not image.is_excluded %}
|
|
<form method="post" action="/admin/articles/{{ article.id }}/images/decision">
|
|
<input type="hidden" name="image_url" value="{{ image.url }}" />
|
|
<input type="hidden" name="action" value="exclude" />
|
|
<button type="submit" class="secondary">Ausblenden</button>
|
|
</form>
|
|
{% else %}
|
|
<form method="post" action="/admin/articles/{{ article.id }}/images/decision">
|
|
<input type="hidden" name="image_url" value="{{ image.url }}" />
|
|
<input type="hidden" name="action" value="restore" />
|
|
<button type="submit" class="secondary">Einblenden</button>
|
|
</form>
|
|
{% endif %}
|
|
</div>
|
|
<div class="subtle"><a href="{{ image.url }}" target="_blank" rel="noopener">{{ image.url }}</a></div>
|
|
</article>
|
|
{% endfor %}
|
|
</div>
|
|
{% endif %}
|
|
{% if article.press_contact or article.extraction.press_contact %}
|
|
<p><strong>Pressekontakt</strong></p>
|
|
<div class="pre">{{ article.press_contact or article.extraction.press_contact }}</div>
|
|
{% endif %}
|
|
{% if article.extraction.extraction_error %}
|
|
<p class="subtle">Extraktionsfehler: {{ article.extraction.extraction_error }}</p>
|
|
{% endif %}
|
|
</section>
|
|
|
|
<section class="card">
|
|
<h2>Volltext</h2>
|
|
<div class="pre">{{ article.content_raw or "-" }}</div>
|
|
</section>
|
|
|
|
<section class="card">
|
|
<h2>Rewrite-Text (editierbar)</h2>
|
|
<form method="post" action="/admin/articles/{{ article.id }}/rewrite-save" class="stack">
|
|
<textarea name="content_rewritten" rows="14" style="width:100%;">{{ article.content_rewritten or "" }}</textarea>
|
|
<button type="submit">Rewrite-Text speichern</button>
|
|
</form>
|
|
{% if article.meta.generated_tags %}
|
|
<p><strong>Generierte Tags:</strong> {{ article.meta.generated_tags|join("; ") }}</p>
|
|
{% endif %}
|
|
<p class="subtle">Dieser Text wird für den WordPress-Entwurf verwendet, falls vorhanden.</p>
|
|
</section>
|
|
|
|
<section class="card">
|
|
<h2>Status ändern</h2>
|
|
{% if article.status_ui in ["new", "rewrite"] %}
|
|
<form method="post" action="/admin/articles/{{ article.id }}/rewrite-run" class="row" style="margin-bottom:8px;">
|
|
<button type="submit">Rewrite ausführen (OpenAI)</button>
|
|
</form>
|
|
{% endif %}
|
|
{% if article.status_ui == "published" %}
|
|
<form method="post" action="/admin/articles/{{ article.id }}/reopen" class="row" style="margin-bottom:8px;">
|
|
<button type="submit">Zurück in Rewrite-Workflow</button>
|
|
</form>
|
|
{% endif %}
|
|
<form method="post" action="/admin/articles/{{ article.id }}/transition" class="row">
|
|
<select name="target_status">
|
|
{% for s in allowed_transitions %}
|
|
<option value="{{ s }}">{{ s }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
<input name="note" placeholder="Notiz" />
|
|
<button type="submit" class="secondary">Setzen</button>
|
|
</form>
|
|
</section>
|
|
|
|
<section class="card">
|
|
<h2>WordPress Publish Queue</h2>
|
|
{% if article.publish_ready %}
|
|
<p><span class="badge ok">Publish bereit</span></p>
|
|
{% else %}
|
|
<p><span class="badge bad">Publish blockiert</span></p>
|
|
{% if article.publish_blockers %}
|
|
<ul>
|
|
{% for reason in article.publish_blockers %}
|
|
<li class="subtle">{{ reason }}</li>
|
|
{% endfor %}
|
|
</ul>
|
|
{% endif %}
|
|
{% endif %}
|
|
<p class="subtle">Voraussetzungen: Status `publish` und Hauptbild gesetzt.</p>
|
|
<form method="post" action="/admin/articles/{{ article.id }}/publish-enqueue" class="row">
|
|
<input name="max_attempts" value="3" />
|
|
<button type="submit" {% if not article.publish_ready %}disabled{% endif %}>In Queue einreihen</button>
|
|
</form>
|
|
</section>
|
|
</main>
|
|
</body>
|
|
</html>
|