Remove render_to_sx from public API: enforce sx_call for all service code
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m44s
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m44s
Replace ~250 render_to_sx calls across all services with sync sx_call, converting many async functions to sync where no other awaits remained. Make render_to_sx/render_to_sx_with_env private (_render_to_sx). Add (post-header-ctx) IO primitive and shared post/post-admin defmacros. Convert built-in post/post-admin layouts from Python to register_sx_layout with .sx defcomps. Remove dead post_admin_mobile_nav_sx. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,7 @@ from typing import Any
|
||||
|
||||
from shared.sx.parser import SxExpr
|
||||
from shared.sx.helpers import (
|
||||
render_to_sx,
|
||||
sx_call,
|
||||
post_header_sx as _post_header_sx,
|
||||
oob_header_sx as _oob_header_sx,
|
||||
full_page_sx, oob_page_sx,
|
||||
@@ -25,21 +25,21 @@ from .helpers import _markets_admin_panel_sx
|
||||
# Browse page
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
async def _product_grid(cards_sx: str) -> str:
|
||||
def _product_grid(cards_sx: str) -> str:
|
||||
"""Wrap product cards in a grid as sx."""
|
||||
return await render_to_sx("market-product-grid", cards=SxExpr(cards_sx))
|
||||
return sx_call("market-product-grid", cards=SxExpr(cards_sx))
|
||||
|
||||
|
||||
async def render_browse_page(ctx: dict) -> str:
|
||||
"""Full page: product browse with filters."""
|
||||
cards = await _product_cards_sx(ctx)
|
||||
content = await _product_grid(cards)
|
||||
cards = _product_cards_sx(ctx)
|
||||
content = _product_grid(cards)
|
||||
|
||||
from shared.sx.helpers import render_to_sx_with_env
|
||||
hdr = await render_to_sx_with_env("market-browse-layout-full", {},
|
||||
post_header=SxExpr(await _post_header_sx(ctx)),
|
||||
market_header=SxExpr(await _market_header_sx(ctx)))
|
||||
menu = await _mobile_nav_panel_sx(ctx)
|
||||
market_header=SxExpr(_market_header_sx(ctx)))
|
||||
menu = _mobile_nav_panel_sx(ctx)
|
||||
filter_sx = await _mobile_filter_summary_sx(ctx)
|
||||
aside_sx = await _desktop_filter_sx(ctx)
|
||||
|
||||
@@ -49,17 +49,17 @@ async def render_browse_page(ctx: dict) -> str:
|
||||
|
||||
async def render_browse_oob(ctx: dict) -> str:
|
||||
"""OOB response: product browse."""
|
||||
cards = await _product_cards_sx(ctx)
|
||||
content = await _product_grid(cards)
|
||||
cards = _product_cards_sx(ctx)
|
||||
content = _product_grid(cards)
|
||||
|
||||
oob_hdr = await _oob_header_sx("post-header-child", "market-header-child",
|
||||
await _market_header_sx(ctx))
|
||||
oobs = await render_to_sx("market-browse-layout-oob",
|
||||
_market_header_sx(ctx))
|
||||
oobs = sx_call("market-browse-layout-oob",
|
||||
oob_header=SxExpr(oob_hdr),
|
||||
post_header_oob=SxExpr(await _post_header_sx(ctx, oob=True)),
|
||||
clear_oob=SxExpr(_clear_deeper_oob("post-row", "post-header-child",
|
||||
"market-row", "market-header-child")))
|
||||
menu = await _mobile_nav_panel_sx(ctx)
|
||||
menu = _mobile_nav_panel_sx(ctx)
|
||||
filter_sx = await _mobile_filter_summary_sx(ctx)
|
||||
aside_sx = await _desktop_filter_sx(ctx)
|
||||
|
||||
@@ -67,9 +67,9 @@ async def render_browse_oob(ctx: dict) -> str:
|
||||
menu=menu, filter=filter_sx, aside=aside_sx)
|
||||
|
||||
|
||||
async def render_browse_cards(ctx: dict) -> str:
|
||||
def render_browse_cards(ctx: dict) -> str:
|
||||
"""Pagination fragment: product cards -- sx wire format."""
|
||||
return await _product_cards_sx(ctx)
|
||||
return _product_cards_sx(ctx)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -78,29 +78,29 @@ async def render_browse_cards(ctx: dict) -> str:
|
||||
|
||||
async def render_product_page(ctx: dict, d: dict) -> str:
|
||||
"""Full page: product detail."""
|
||||
content = await _product_detail_sx(d, ctx)
|
||||
meta = await _product_meta_sx(d, ctx)
|
||||
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("market-product-layout-full", {},
|
||||
post_header=SxExpr(await _post_header_sx(ctx)),
|
||||
market_header=SxExpr(await _market_header_sx(ctx)),
|
||||
product_header=SxExpr(await _product_header_sx(ctx, d)))
|
||||
market_header=SxExpr(_market_header_sx(ctx)),
|
||||
product_header=SxExpr(_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 = await _product_detail_sx(d, ctx)
|
||||
content = _product_detail_sx(d, ctx)
|
||||
|
||||
oobs = await render_to_sx("market-oob-wrap",
|
||||
parts=SxExpr("(<> " + await _market_header_sx(ctx, oob=True) + " "
|
||||
oobs = sx_call("market-oob-wrap",
|
||||
parts=SxExpr("(<> " + _market_header_sx(ctx, oob=True) + " "
|
||||
+ await _oob_header_sx("market-header-child", "product-header-child",
|
||||
await _product_header_sx(ctx, d)) + " "
|
||||
_product_header_sx(ctx, d)) + " "
|
||||
+ _clear_deeper_oob("post-row", "post-header-child",
|
||||
"market-row", "market-header-child",
|
||||
"product-row", "product-header-child") + ")"))
|
||||
menu = await _mobile_nav_panel_sx(ctx)
|
||||
menu = _mobile_nav_panel_sx(ctx)
|
||||
return await oob_page_sx(oobs=oobs, content=content, menu=menu)
|
||||
|
||||
|
||||
@@ -110,25 +110,25 @@ async def render_product_oob(ctx: dict, d: dict) -> str:
|
||||
|
||||
async def render_product_admin_page(ctx: dict, d: dict) -> str:
|
||||
"""Full page: product admin."""
|
||||
content = await _product_detail_sx(d, ctx)
|
||||
content = _product_detail_sx(d, ctx)
|
||||
|
||||
from shared.sx.helpers import render_to_sx_with_env
|
||||
hdr = await render_to_sx_with_env("market-product-admin-layout-full", {},
|
||||
post_header=SxExpr(await _post_header_sx(ctx)),
|
||||
market_header=SxExpr(await _market_header_sx(ctx)),
|
||||
product_header=SxExpr(await _product_header_sx(ctx, d)),
|
||||
admin_header=SxExpr(await _product_admin_header_sx(ctx, d)))
|
||||
market_header=SxExpr(_market_header_sx(ctx)),
|
||||
product_header=SxExpr(_product_header_sx(ctx, d)),
|
||||
admin_header=SxExpr(_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 = await _product_detail_sx(d, ctx)
|
||||
content = _product_detail_sx(d, ctx)
|
||||
|
||||
oobs = await render_to_sx("market-oob-wrap",
|
||||
parts=SxExpr("(<> " + await _product_header_sx(ctx, d, oob=True) + " "
|
||||
oobs = sx_call("market-oob-wrap",
|
||||
parts=SxExpr("(<> " + _product_header_sx(ctx, d, oob=True) + " "
|
||||
+ await _oob_header_sx("product-header-child", "product-admin-header-child",
|
||||
await _product_admin_header_sx(ctx, d)) + " "
|
||||
_product_admin_header_sx(ctx, d)) + " "
|
||||
+ _clear_deeper_oob("post-row", "post-header-child",
|
||||
"market-row", "market-header-child",
|
||||
"product-row", "product-header-child",
|
||||
@@ -149,7 +149,7 @@ async def render_markets_admin_list_panel(ctx: dict) -> str:
|
||||
# Public API: POST handler fragment renderers
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
async def render_all_markets_cards(markets: list, has_more: bool,
|
||||
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
|
||||
@@ -157,10 +157,10 @@ async def render_all_markets_cards(markets: list, has_more: bool,
|
||||
|
||||
prefix = route_prefix()
|
||||
next_url = prefix + url_for("all_markets.markets_fragment", page=page + 1)
|
||||
return await _market_cards_sx(markets, page_info, page, has_more, next_url)
|
||||
return _market_cards_sx(markets, page_info, page, has_more, next_url)
|
||||
|
||||
|
||||
async def render_page_markets_cards(markets: list, has_more: bool,
|
||||
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
|
||||
@@ -168,11 +168,11 @@ async def render_page_markets_cards(markets: list, has_more: bool,
|
||||
|
||||
prefix = route_prefix()
|
||||
next_url = prefix + url_for("page_markets.markets_fragment", page=page + 1)
|
||||
return await _market_cards_sx(markets, {}, page, has_more, next_url,
|
||||
return _market_cards_sx(markets, {}, page, has_more, next_url,
|
||||
show_page_badge=False, post_slug=post_slug)
|
||||
|
||||
|
||||
async def render_like_toggle_button(slug: str, liked: bool, *,
|
||||
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."""
|
||||
@@ -193,7 +193,7 @@ async def render_like_toggle_button(slug: str, liked: bool, *,
|
||||
icon = "fa-regular fa-heart"
|
||||
label = f"Like this {item_type}"
|
||||
|
||||
return await render_to_sx(
|
||||
return sx_call(
|
||||
"market-like-toggle-button",
|
||||
colour=colour, action=like_url,
|
||||
hx_headers=f'{{"X-CSRFToken": "{csrf}"}}',
|
||||
@@ -201,7 +201,7 @@ async def render_like_toggle_button(slug: str, liked: bool, *,
|
||||
)
|
||||
|
||||
|
||||
async def render_cart_added_response(cart: list, item: Any, d: dict) -> str:
|
||||
def render_cart_added_response(cart: list, item: Any, d: dict) -> str:
|
||||
"""Render the HTMX response after add-to-cart.
|
||||
|
||||
Returns OOB fragments: cart-mini icon + product add/remove buttons + cart item row.
|
||||
@@ -217,30 +217,30 @@ async def render_cart_added_response(cart: list, item: Any, d: dict) -> str:
|
||||
# 1. Cart mini icon OOB
|
||||
if count > 0:
|
||||
cart_href = _cart_url("/")
|
||||
cart_mini = await render_to_sx("market-cart-mini-count", href=cart_href, count=str(count))
|
||||
cart_mini = sx_call("market-cart-mini-count", href=cart_href, count=str(count))
|
||||
else:
|
||||
from shared.config import config
|
||||
blog_href = config().get("blog_url", "/")
|
||||
logo = config().get("logo", "")
|
||||
cart_mini = await render_to_sx("market-cart-mini-empty", href=blog_href, logo=logo)
|
||||
cart_mini = sx_call("market-cart-mini-empty", href=blog_href, logo=logo)
|
||||
|
||||
# 2. Add/remove buttons OOB
|
||||
action = url_for("market.browse.product.cart", product_slug=slug)
|
||||
quantity = getattr(item, "quantity", 0) if item else 0
|
||||
if not quantity:
|
||||
cart_add = await render_to_sx(
|
||||
cart_add = sx_call(
|
||||
"market-cart-add-empty",
|
||||
cart_id=f"cart-{slug}", action=action, csrf=csrf,
|
||||
)
|
||||
else:
|
||||
cart_href = _cart_url("/") if callable(_cart_url) else "/"
|
||||
cart_add = await render_to_sx(
|
||||
cart_add = sx_call(
|
||||
"market-cart-add-quantity",
|
||||
cart_id=f"cart-{slug}", action=action, csrf=csrf,
|
||||
minus_val=str(quantity - 1), plus_val=str(quantity + 1),
|
||||
quantity=str(quantity), cart_href=cart_href,
|
||||
)
|
||||
add_sx = await render_to_sx(
|
||||
add_sx = sx_call(
|
||||
"market-cart-add-oob",
|
||||
id=f"cart-add-{slug}",
|
||||
inner=SxExpr(cart_add),
|
||||
|
||||
Reference in New Issue
Block a user