From a59c670e438df59ae71c5a5869439bdd2681e961 Mon Sep 17 00:00:00 2001 From: Deeman Date: Tue, 24 Feb 2026 01:20:02 +0100 Subject: [PATCH] feat: HTMX-ify article publish/delete actions for inline updates - Publish/Unpublish returns updated partial via HTMX - Delete returns empty string to remove row without page reload - Extract article_row.html partial (used by both results table and individual HTMX responses) - article_results.html now includes article_row.html via loop Subtask 7 of CMS admin improvement. Co-Authored-By: Claude Opus 4.6 --- web/src/padelnomics/admin/routes.py | 15 +++++++++ .../admin/partials/article_results.html | 33 +------------------ .../templates/admin/partials/article_row.html | 33 +++++++++++++++++++ 3 files changed, 49 insertions(+), 32 deletions(-) create mode 100644 web/src/padelnomics/admin/templates/admin/partials/article_row.html diff --git a/web/src/padelnomics/admin/routes.py b/web/src/padelnomics/admin/routes.py index 0fc4097..89336cc 100644 --- a/web/src/padelnomics/admin/routes.py +++ b/web/src/padelnomics/admin/routes.py @@ -1849,6 +1849,9 @@ async def article_delete(article_id: int): from ..sitemap import invalidate_sitemap_cache invalidate_sitemap_cache() + if request.headers.get("HX-Request"): + return "" # row removed via hx-swap="outerHTML" + await flash("Article deleted.", "success") return redirect(url_for("admin.articles")) @@ -1873,6 +1876,18 @@ async def article_publish(article_id: int): from ..sitemap import invalidate_sitemap_cache invalidate_sitemap_cache() + if request.headers.get("HX-Request"): + updated = await fetch_one( + """SELECT *, + CASE WHEN status = 'published' AND published_at > datetime('now') + THEN 'scheduled' + WHEN status = 'published' THEN 'live' + ELSE status END AS display_status + FROM articles WHERE id = ?""", + (article_id,), + ) + return await render_template("admin/partials/article_row.html", a=updated) + await flash(f"Article status changed to {new_status}.", "success") return redirect(url_for("admin.articles")) diff --git a/web/src/padelnomics/admin/templates/admin/partials/article_results.html b/web/src/padelnomics/admin/templates/admin/partials/article_results.html index 5756cb1..2d95b07 100644 --- a/web/src/padelnomics/admin/templates/admin/partials/article_results.html +++ b/web/src/padelnomics/admin/templates/admin/partials/article_results.html @@ -13,38 +13,7 @@ {% for a in articles %} - - {{ a.title }} - - {% if a.display_status == 'live' %} - Live - {% elif a.display_status == 'scheduled' %} - Scheduled - {% else %} - Draft - {% endif %} - - {{ a.published_at[:10] if a.published_at else '-' }} - {{ a.language | upper if a.language else '-' }} - {{ a.template_slug or 'Manual' }} - - {% if a.display_status == 'live' %} - View - {% endif %} - Edit -
- - -
-
- - -
- - + {% include "admin/partials/article_row.html" %} {% endfor %} diff --git a/web/src/padelnomics/admin/templates/admin/partials/article_row.html b/web/src/padelnomics/admin/templates/admin/partials/article_row.html new file mode 100644 index 0000000..1e3b227 --- /dev/null +++ b/web/src/padelnomics/admin/templates/admin/partials/article_row.html @@ -0,0 +1,33 @@ + + {{ a.title }} + + {% if a.display_status == 'live' %} + Live + {% elif a.display_status == 'scheduled' %} + Scheduled + {% else %} + Draft + {% endif %} + + {{ a.published_at[:10] if a.published_at else '-' }} + {{ a.language | upper if a.language else '-' }} + {{ a.template_slug or 'Manual' }} + + {% if a.display_status == 'live' %} + View + {% endif %} + Edit + + + +