Make post header row generic: admin cog + container_nav in shared helper
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m31s

Move admin cog generation and container_nav border wrapping from
blog-specific wrapper into shared post_header_html so all services
render identical post header rows. Blog, events, cart all delegate
to the shared helper now. Cart admin pages fetch container_nav_html
via fragments. Village Hall always links to blog.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-28 22:37:24 +00:00
parent 2e4fbd5777
commit f628b35fc3
4 changed files with 53 additions and 38 deletions

View File

@@ -51,36 +51,8 @@ def _blog_header_html(ctx: dict, *, oob: bool = False) -> str:
# ---------------------------------------------------------------------------
def _post_header_html(ctx: dict, *, oob: bool = False) -> str:
"""Build the post-level header row (blog-specific: container-nav wrapping + admin cog)."""
overrides: dict = {}
# Blog wraps container_nav_html in border styling
container_nav = ctx.get("container_nav_html", "")
if container_nav:
overrides["container_nav_html"] = render("blog-container-nav",
container_nav_html=container_nav,
)
# Admin cog link
from quart import url_for as qurl, request
post = ctx.get("post") or {}
slug = post.get("slug", "")
rights = ctx.get("rights") or {}
has_admin = rights.get("admin") if isinstance(rights, dict) else getattr(rights, "admin", False)
if has_admin and slug:
select_colours = ctx.get("select_colours", "")
styles = ctx.get("styles") or {}
nav_btn = styles.get("nav_button", "") if isinstance(styles, dict) else getattr(styles, "nav_button", "")
admin_href = qurl("blog.post.admin.admin", slug=slug)
is_admin_page = "/admin" in request.path
overrides["post_admin_nav_html"] = render("nav-link",
href=admin_href, hx_select="#main-panel", icon="fa fa-cog",
aclass=f"{nav_btn} {select_colours}",
select_colours=select_colours, is_selected=is_admin_page,
)
effective_ctx = {**ctx, **overrides} if overrides else ctx
return _shared_post_header_html(effective_ctx, oob=oob)
"""Build the post-level header row — delegates to shared helper."""
return _shared_post_header_html(ctx, oob=oob)
# ---------------------------------------------------------------------------

View File

@@ -39,9 +39,32 @@ def _ensure_post_ctx(ctx: dict, page_post: Any) -> dict:
return ctx
def _post_header_html(ctx: dict, page_post: Any, *, oob: bool = False) -> str:
async def _ensure_container_nav(ctx: dict) -> dict:
"""Fetch container_nav_html if not already present (for post header row)."""
if ctx.get("container_nav_html"):
return ctx
post = ctx.get("post") or {}
post_id = post.get("id")
slug = post.get("slug", "")
if not post_id:
return ctx
from shared.infrastructure.fragments import fetch_fragments
nav_params = {
"container_type": "page",
"container_id": str(post_id),
"post_slug": slug,
}
events_nav, market_nav = await fetch_fragments([
("events", "container-nav", nav_params),
("market", "container-nav", nav_params),
], required=False)
return {**ctx, "container_nav_html": events_nav + market_nav}
async def _post_header_html(ctx: dict, page_post: Any, *, oob: bool = False) -> str:
"""Build post-level header row from page_post DTO, using shared helper."""
ctx = _ensure_post_ctx(ctx, page_post)
ctx = await _ensure_container_nav(ctx)
return _shared_post_header_html(ctx, oob=oob)
@@ -794,7 +817,7 @@ async def render_cart_admin_page(ctx: dict, page_post: Any) -> str:
"""Full page: cart page admin overview."""
content = _cart_admin_main_panel_html(ctx)
root_hdr = root_header_html(ctx)
post_hdr = _post_header_html(ctx, page_post)
post_hdr = await _post_header_html(ctx, page_post)
admin_hdr = _cart_page_admin_header_html(ctx, page_post)
return full_page(ctx, header_rows_html=root_hdr + post_hdr + admin_hdr, content_html=content)
@@ -814,7 +837,7 @@ async def render_cart_payments_page(ctx: dict, page_post: Any) -> str:
"""Full page: payments config."""
content = _cart_payments_main_panel_html(ctx)
root_hdr = root_header_html(ctx)
post_hdr = _post_header_html(ctx, page_post)
post_hdr = await _post_header_html(ctx, page_post)
admin_hdr = _cart_page_admin_header_html(ctx, page_post, selected="payments")
return full_page(ctx, header_rows_html=root_hdr + post_hdr + admin_hdr, content_html=content)

View File

@@ -37,10 +37,8 @@ _oob_header_html = oob_header_html
# ---------------------------------------------------------------------------
def _post_header_html(ctx: dict, *, oob: bool = False) -> str:
"""Build the post-level header row (events-specific: calendar links + admin cog)."""
admin_nav = _post_nav_html(ctx)
effective_ctx = {**ctx, "post_admin_nav_html": admin_nav} if admin_nav else ctx
return _shared_post_header_html(effective_ctx, oob=oob)
"""Build the post-level header row — delegates to shared helper."""
return _shared_post_header_html(ctx, oob=oob)
def _post_nav_html(ctx: dict) -> str:

View File

@@ -89,9 +89,31 @@ def post_header_html(ctx: dict, *, oob: bool = False) -> str:
container_nav = ctx.get("container_nav_html", "")
if container_nav:
nav_parts.append(container_nav)
nav_parts.append(
'<div class="flex flex-col sm:flex-row sm:items-center gap-2'
' border-r border-stone-200 mr-2 sm:max-w-2xl"'
' id="entries-calendars-nav-wrapper">'
f'{container_nav}</div>'
)
# Admin cog — external link to blog admin (generic across all services)
admin_nav = ctx.get("post_admin_nav_html", "")
if not admin_nav:
rights = ctx.get("rights") or {}
has_admin = rights.get("admin") if isinstance(rights, dict) else getattr(rights, "admin", False)
if has_admin and slug:
from quart import request
admin_href = call_url(ctx, "blog_url", f"/{slug}/admin/")
is_admin_page = "/admin" in request.path
sel_cls = "!bg-stone-500 !text-white" if is_admin_page else ""
base_cls = ("justify-center cursor-pointer flex flex-row"
" items-center gap-2 rounded bg-stone-200 text-black p-3")
admin_nav = (
f'<div class="relative nav-group">'
f'<a href="{escape(admin_href)}"'
f' class="{base_cls} {sel_cls}">'
f'<i class="fa fa-cog" aria-hidden="true"></i></a></div>'
)
if admin_nav:
nav_parts.append(admin_nav)