diff --git a/backend/app/admin_ui.py b/backend/app/admin_ui.py
index 8d8e879..fba1b91 100644
--- a/backend/app/admin_ui.py
+++ b/backend/app/admin_ui.py
@@ -156,6 +156,19 @@ def _build_image_entries(article: dict, extraction: dict, meta: dict) -> list[di
return entries
+def _publish_readiness(article: dict, meta: dict) -> tuple[bool, list[str]]:
+ reasons: list[str] = []
+ if article.get("status") not in {"approved", "published"}:
+ reasons.append("Status ist nicht 'approved'")
+ if int(article.get("legal_checked", 0)) != 1:
+ reasons.append("Rechtsfreigabe fehlt")
+ image_review = meta.get("image_review") if isinstance(meta.get("image_review"), dict) else {}
+ selected_image = image_review.get("selected_url") if isinstance(image_review.get("selected_url"), str) else None
+ if not selected_image:
+ reasons.append("Hauptbild nicht ausgewählt")
+ return len(reasons) == 0, reasons
+
+
def _legal_checklist(article: dict, feed: dict | None) -> list[dict[str, str]]:
meta = article.get("meta", {})
extraction = meta.get("extraction") if isinstance(meta.get("extraction"), dict) else {}
@@ -287,6 +300,9 @@ def admin_dashboard(request: Request):
extraction = meta.get("extraction") if isinstance(meta.get("extraction"), dict) else {}
images = _read_article_images(article, extraction)
article["meta"] = meta
+ ready, reasons = _publish_readiness(article, meta)
+ article["publish_ready"] = ready
+ article["publish_blockers"] = reasons
article["extracted_images"] = images
article["image_entries"] = _build_image_entries(article, extraction, meta)
image_review = meta.get("image_review") if isinstance(meta.get("image_review"), dict) else {}
@@ -339,6 +355,9 @@ def admin_article_detail(request: Request, article_id: int):
if not article.get("press_contact") and isinstance(extraction.get("press_contact"), str):
article["press_contact"] = extraction.get("press_contact")
article["extraction"] = extraction
+ publish_ready, publish_blockers = _publish_readiness(article, meta)
+ article["publish_ready"] = publish_ready
+ article["publish_blockers"] = publish_blockers
article["image_selection"] = extraction.get("image_selection") if isinstance(extraction.get("image_selection"), dict) else {}
article["image_entries"] = _build_image_entries(article, extraction, meta)
image_review = meta.get("image_review") if isinstance(meta.get("image_review"), dict) else {}
diff --git a/backend/app/config.py b/backend/app/config.py
index e194bcc..fc52ec3 100644
--- a/backend/app/config.py
+++ b/backend/app/config.py
@@ -2,6 +2,7 @@ from functools import lru_cache
from pathlib import Path
from dotenv import load_dotenv
+from pydantic import AliasChoices, Field
from pydantic_settings import BaseSettings, SettingsConfigDict
@@ -25,9 +26,9 @@ class Settings(BaseSettings):
app_db_path: str = "backend/data/rss_news.db"
- wordpress_base_url: str | None = None
- wordpress_username: str | None = None
- wordpress_app_password: str | None = None
+ wordpress_base_url: str | None = Field(default=None, validation_alias=AliasChoices("WORDPRESS_BASE_URL", "WP_BASE_URL"))
+ wordpress_username: str | None = Field(default=None, validation_alias=AliasChoices("WORDPRESS_USERNAME", "WP_USERNAME"))
+ wordpress_app_password: str | None = Field(default=None, validation_alias=AliasChoices("WORDPRESS_APP_PASSWORD", "WP_PASSWORD"))
wordpress_default_status: str = "draft"
diff --git a/backend/templates/admin_article_detail.html b/backend/templates/admin_article_detail.html
index a5943ef..6f06d36 100644
--- a/backend/templates/admin_article_detail.html
+++ b/backend/templates/admin_article_detail.html
@@ -203,10 +203,21 @@
Voraussetzungen: Status `approved`, Rechtsfreigabe aktiv, Hauptbild gesetzt. Publish bereit Publish blockiertWordPress Publish Queue
-
+ {% for reason in article.publish_blockers %}
+
+ {% endif %}
+ {% endif %}