Die Freigabe ist jetzt der taegliche Arbeitsschritt und bekommt eine eigene Seite: /admin/freigabe listet alle wartenden Artikel mit Bild, Score, Tags und dem umgeschriebenen Text lesbar gerendert, dazu die drei Aktionen Freigeben, Neu schreiben, Verwerfen. Nach jeder Aktion geht es zurueck in die Liste, damit sich eine Warteschlange am Stueck abarbeiten laesst. Der Vorschautext ist Modell-Ausgabe ueber fremde Webseiten und laeuft deshalb durch einen Tag-Whitelist-Filter statt roh ins Template. Aufgeraeumt: - Artikelliste zeigte interne Kuerzel statt Klartext - Status `review` (Relevanz-Warnzone) wurde als "Rewrite" ausgegeben - `Rewrite -> Freigegeben` entfernt: zweiter Weg an der Freigabe vorbei - `Freigegeben -> Veroeffentlicht` entfernt: das macht der WP-Sync - API-Statusliste wird abgeleitet statt handgepflegt, sie kannte den neuen Status nicht und lehnte den Wechsel mit 422 ab Behoben: list_articles las content_rewritten nicht mit, die neue Seite haette nie einen Text angezeigt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
144 lines
5.5 KiB
HTML
144 lines
5.5 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" />
|
|
<style>
|
|
.schedule-table td, .schedule-table th { padding: 6px 10px; }
|
|
.slot-free { color: #aaa; font-style: italic; }
|
|
.slot-booked-db { color: #1a7a1a; font-weight: bold; }
|
|
.slot-booked-wp { color: #b35a00; font-weight: bold; }
|
|
.badge-db { background: #d4edda; color: #155724; padding: 2px 6px; border-radius: 4px; font-size: 0.75em; }
|
|
.badge-wp { background: #fff3cd; color: #856404; padding: 2px 6px; border-radius: 4px; font-size: 0.75em; }
|
|
.summary-bar { display: flex; gap: 1.5rem; margin-bottom: 1rem; font-size: 0.95em; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<header class="topbar">
|
|
<div>
|
|
<h1>rss-news Veröffentlichungsplan</h1>
|
|
<p>Angemeldet als <strong>{{ user }}</strong></p>
|
|
</div>
|
|
<div class="row">
|
|
<a class="linkbtn" href="/admin/dashboard">Dashboard</a>
|
|
<a class="linkbtn" href="/admin/freigabe">Freigabe</a>
|
|
<a class="linkbtn" href="/admin/connectivity">Connectivity</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" style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:1rem;">
|
|
<div>
|
|
<h2 style="margin:0;">WordPress → DB Synchronisieren</h2>
|
|
<p class="subtle" style="margin:4px 0 0;">Liest alle geplanten WP-Beiträge und aktualisiert die Slots in der lokalen DB.<br>Nutze dies nach manuellen Änderungen in WordPress.</p>
|
|
</div>
|
|
<form method="post" action="/admin/wp-sync">
|
|
<button type="submit">🔄 Jetzt synchronisieren</button>
|
|
</form>
|
|
</section>
|
|
|
|
<section class="card">
|
|
<h2>Slot-Übersicht (nächste 60 Tage)</h2>
|
|
<div class="summary-bar">
|
|
<span>📅 Belegte Slots gesamt: <strong>{{ slots|length }}</strong></span>
|
|
<span>🗄️ Aus Pipeline-DB: <strong>{{ slots|selectattr('source', 'eq', 'db')|list|length }}</strong></span>
|
|
<span>🌐 Nur in WordPress: <strong>{{ slots|selectattr('source', 'eq', 'wordpress')|list|length }}</strong></span>
|
|
</div>
|
|
<table class="schedule-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Tag</th>
|
|
{% for h in hours %}
|
|
<th>{{ "%02d:00 Uhr"|format(h) }}</th>
|
|
{% endfor %}
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for day in calendar_days %}
|
|
{% if day.any_booked %}
|
|
<tr>
|
|
<td><strong>{{ day.weekday }}</strong> {{ day.date_fmt }}</td>
|
|
{% for s in day.slots %}
|
|
<td>
|
|
{% if s.booked %}
|
|
{% set info = s.slot %}
|
|
{% if info.source == 'db' %}
|
|
<span class="slot-booked-db">✅</span>
|
|
<span class="badge-db">DB</span>
|
|
<div style="font-size:0.85em;">
|
|
{% if info.article_id %}
|
|
<a href="/admin/articles/{{ info.article_id }}">
|
|
{{ (info.article_title or "Artikel")[:50] }}{% if (info.article_title or "")|length > 50 %}…{% endif %}
|
|
</a>
|
|
{% endif %}
|
|
<br /><span class="subtle">Status: {{ info.article_status }}</span>
|
|
{% if info.wp_post_url %}
|
|
<br /><a href="{{ info.wp_post_url }}" target="_blank" rel="noopener">WP öffnen</a>
|
|
{% endif %}
|
|
</div>
|
|
{% else %}
|
|
<span class="slot-booked-wp">⚠️</span>
|
|
<span class="badge-wp">WP</span>
|
|
<div style="font-size:0.85em;">{{ info.article_title }}</div>
|
|
{% endif %}
|
|
{% else %}
|
|
<span class="slot-free">frei</span>
|
|
{% endif %}
|
|
</td>
|
|
{% endfor %}
|
|
</tr>
|
|
{% endif %}
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% if not slots %}
|
|
<p class="subtle">Keine geplanten Beiträge in den nächsten 60 Tagen.</p>
|
|
{% endif %}
|
|
</section>
|
|
|
|
<section class="card">
|
|
<h2>Alle belegten Slots (Liste)</h2>
|
|
<table>
|
|
<thead>
|
|
<tr><th>Datum/Zeit</th><th>Quelle</th><th>Artikel</th><th>Status</th><th>WordPress</th></tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for s in slots %}
|
|
<tr>
|
|
<td>{{ s.formatted }}</td>
|
|
<td>
|
|
{% if s.source == 'db' %}<span class="badge-db">Pipeline-DB</span>
|
|
{% else %}<span class="badge-wp">WordPress</span>{% endif %}
|
|
</td>
|
|
<td>
|
|
{% if s.article_id %}
|
|
<a href="/admin/articles/{{ s.article_id }}">{{ (s.article_title or "")[:60] }}</a>
|
|
{% else %}
|
|
{{ s.article_title or "-" }}
|
|
{% endif %}
|
|
</td>
|
|
<td>{{ s.article_status or "-" }}</td>
|
|
<td>
|
|
{% if s.wp_post_url %}
|
|
<a href="{{ s.wp_post_url }}" target="_blank" rel="noopener">Draft öffnen</a>
|
|
{% else %}-{% endif %}
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</section>
|
|
</main>
|
|
</body>
|
|
</html>
|