The rename script only matched ~prefixed names in .sx files.
Python render calls use bare strings like render_to_html("name")
which also need updating: 37 replacements across 8 files.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
217 lines
8.0 KiB
Python
217 lines
8.0 KiB
Python
"""Public render functions called from bp routes."""
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from shared.sx.parser import SxExpr
|
|
from shared.sx.helpers import (
|
|
sx_call,
|
|
post_header_sx as _post_header_sx,
|
|
oob_header_sx as _oob_header_sx,
|
|
full_page_sx, oob_page_sx,
|
|
)
|
|
|
|
from .utils import _product_detail_sx, _product_meta_sx
|
|
from .cards import _product_cards_sx, _market_cards_sx
|
|
from .filters import _desktop_filter_sx, _mobile_filter_summary_sx
|
|
from .layouts import (
|
|
_market_header_sx, _product_header_sx, _product_admin_header_sx,
|
|
_mobile_nav_panel_sx,
|
|
)
|
|
from .helpers import _markets_admin_panel_sx
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Browse page
|
|
# ---------------------------------------------------------------------------
|
|
|
|
async def render_browse_page(ctx: dict) -> str:
|
|
"""Full page: product browse with filters."""
|
|
content = sx_call("market-product-grid", cards=SxExpr(_product_cards_sx(ctx)))
|
|
|
|
from shared.sx.helpers import render_to_sx_with_env
|
|
hdr = await render_to_sx_with_env("layouts/browse-layout-full", {})
|
|
menu = _mobile_nav_panel_sx(ctx)
|
|
filter_sx = await _mobile_filter_summary_sx(ctx)
|
|
aside_sx = await _desktop_filter_sx(ctx)
|
|
|
|
return await full_page_sx(ctx, header_rows=hdr, content=content,
|
|
menu=menu, filter=filter_sx, aside=aside_sx)
|
|
|
|
|
|
async def render_browse_oob(ctx: dict) -> str:
|
|
"""OOB response: product browse."""
|
|
content = sx_call("market-product-grid", cards=SxExpr(_product_cards_sx(ctx)))
|
|
|
|
# Layout handles all OOB headers via auto-fetch macros
|
|
oobs = sx_call("market-browse-layout-oob")
|
|
menu = _mobile_nav_panel_sx(ctx)
|
|
filter_sx = await _mobile_filter_summary_sx(ctx)
|
|
aside_sx = await _desktop_filter_sx(ctx)
|
|
|
|
return await oob_page_sx(oobs=oobs, content=content,
|
|
menu=menu, filter=filter_sx, aside=aside_sx)
|
|
|
|
|
|
def render_browse_cards(ctx: dict) -> str:
|
|
"""Pagination fragment: product cards -- sx wire format."""
|
|
return _product_cards_sx(ctx)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Product detail
|
|
# ---------------------------------------------------------------------------
|
|
|
|
async def render_product_page(ctx: dict, d: dict) -> str:
|
|
"""Full page: product detail."""
|
|
content = _product_detail_sx(d, ctx)
|
|
meta = _product_meta_sx(d, ctx)
|
|
|
|
from shared.sx.helpers import render_to_sx_with_env
|
|
hdr = await render_to_sx_with_env("layouts/product-layout-full", {},
|
|
post_header=await _post_header_sx(ctx),
|
|
market_header=_market_header_sx(ctx),
|
|
product_header=_product_header_sx(ctx, d))
|
|
return await full_page_sx(ctx, header_rows=hdr, content=content, meta=meta)
|
|
|
|
|
|
async def render_product_oob(ctx: dict, d: dict) -> str:
|
|
"""OOB response: product detail."""
|
|
content = _product_detail_sx(d, ctx)
|
|
|
|
oobs = sx_call("market-product-oob",
|
|
market_header=SxExpr(_market_header_sx(ctx, oob=True)),
|
|
oob_header=SxExpr(await _oob_header_sx("market-header-child", "product-header-child",
|
|
_product_header_sx(ctx, d))))
|
|
menu = _mobile_nav_panel_sx(ctx)
|
|
return await oob_page_sx(oobs=oobs, content=content, menu=menu)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Product admin
|
|
# ---------------------------------------------------------------------------
|
|
|
|
async def render_product_admin_page(ctx: dict, d: dict) -> str:
|
|
"""Full page: product admin."""
|
|
content = _product_detail_sx(d, ctx)
|
|
|
|
from shared.sx.helpers import render_to_sx_with_env
|
|
hdr = await render_to_sx_with_env("layouts/product-admin-layout-full", {},
|
|
post_header=await _post_header_sx(ctx),
|
|
market_header=_market_header_sx(ctx),
|
|
product_header=_product_header_sx(ctx, d),
|
|
admin_header=_product_admin_header_sx(ctx, d))
|
|
return await full_page_sx(ctx, header_rows=hdr, content=content)
|
|
|
|
|
|
async def render_product_admin_oob(ctx: dict, d: dict) -> str:
|
|
"""OOB response: product admin."""
|
|
content = _product_detail_sx(d, ctx)
|
|
|
|
oobs = sx_call("market-product-admin-oob",
|
|
product_header=SxExpr(_product_header_sx(ctx, d, oob=True)),
|
|
oob_header=SxExpr(await _oob_header_sx("product-header-child", "product-admin-header-child",
|
|
_product_admin_header_sx(ctx, d))))
|
|
return await oob_page_sx(oobs=oobs, content=content)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Market admin list panel
|
|
# ---------------------------------------------------------------------------
|
|
|
|
async def render_markets_admin_list_panel(ctx: dict) -> str:
|
|
"""Render the markets admin panel HTML for POST/DELETE response."""
|
|
return await _markets_admin_panel_sx(ctx)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Public API: POST handler fragment renderers
|
|
# ---------------------------------------------------------------------------
|
|
|
|
def render_all_markets_cards(markets: list, has_more: bool,
|
|
page_info: dict, page: int) -> str:
|
|
"""Pagination fragment: all markets cards."""
|
|
from quart import url_for
|
|
from shared.utils import route_prefix
|
|
|
|
prefix = route_prefix()
|
|
next_url = prefix + url_for("all_markets.markets_fragment", page=page + 1)
|
|
return _market_cards_sx(markets, page_info, page, has_more, next_url)
|
|
|
|
|
|
def render_page_markets_cards(markets: list, has_more: bool,
|
|
page: int, post_slug: str) -> str:
|
|
"""Pagination fragment: page-scoped markets cards."""
|
|
from quart import url_for
|
|
from shared.utils import route_prefix
|
|
|
|
prefix = route_prefix()
|
|
next_url = prefix + url_for("page_markets.markets_fragment", page=page + 1)
|
|
return _market_cards_sx(markets, {}, page, has_more, next_url,
|
|
show_page_badge=False, post_slug=post_slug)
|
|
|
|
|
|
def render_like_toggle_button(slug: str, liked: bool, *,
|
|
like_url: str | None = None,
|
|
item_type: str = "product") -> str:
|
|
"""Render a standalone like toggle button for HTMX POST response."""
|
|
from shared.browser.app.csrf import generate_csrf_token
|
|
from quart import url_for
|
|
from shared.utils import host_url
|
|
|
|
csrf = generate_csrf_token()
|
|
if not like_url:
|
|
like_url = host_url(url_for("market.browse.product.like_toggle", product_slug=slug))
|
|
|
|
if liked:
|
|
colour = "text-red-600"
|
|
icon = "fa-solid fa-heart"
|
|
label = f"Unlike this {item_type}"
|
|
else:
|
|
colour = "text-stone-300"
|
|
icon = "fa-regular fa-heart"
|
|
label = f"Like this {item_type}"
|
|
|
|
return sx_call(
|
|
"market-like-toggle-button",
|
|
colour=colour, action=like_url,
|
|
hx_headers={"X-CSRFToken": csrf},
|
|
label=label, icon_cls=icon,
|
|
)
|
|
|
|
|
|
def render_cart_added_response(cart: list, item: Any, d: dict) -> str:
|
|
"""Render the HTMX response after add-to-cart via ~market-cart-added-response."""
|
|
from shared.browser.app.csrf import generate_csrf_token
|
|
from quart import url_for
|
|
from shared.infrastructure.urls import cart_url as _cart_url
|
|
|
|
csrf = generate_csrf_token()
|
|
slug = d.get("slug", "")
|
|
count = sum(getattr(ci, "quantity", 0) for ci in cart)
|
|
quantity = getattr(item, "quantity", 0) if item else 0
|
|
action = url_for("market.browse.product.cart", product_slug=slug)
|
|
|
|
if count > 0:
|
|
cart_href = _cart_url("/")
|
|
blog_href = ""
|
|
logo = ""
|
|
else:
|
|
from shared.config import config
|
|
cart_href = ""
|
|
blog_href = config().get("blog_url", "/")
|
|
logo = config().get("logo", "")
|
|
|
|
return sx_call("market-cart-added-response",
|
|
has_count=str(count) if count > 0 else None,
|
|
cart_href=cart_href,
|
|
blog_href=blog_href,
|
|
logo=logo,
|
|
slug=slug,
|
|
action=action,
|
|
csrf=csrf,
|
|
quantity=str(quantity),
|
|
minus_val=str(quantity - 1) if quantity > 0 else "0",
|
|
plus_val=str(quantity + 1),
|
|
)
|