Replace Python sx_call loops with data-driven SX defcomps using map
Move rendering logic from Python for-loops building sx_call strings into SX defcomp components that use map/lambda over data dicts. Python now serializes display data into plain dicts and passes them via a single sx_call; the SX layer handles iteration and conditional rendering. Covers orders (rows, items, calendar, tickets), federation (timeline, search, actors, profile activities), and blog (cards, pages, filters, snippets, menu items, tag groups, page search, nav OOB). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -47,6 +47,17 @@
|
||||
(h2 :class "text-base sm:text-lg font-semibold" "Event tickets in this order")
|
||||
(ul :class "divide-y divide-stone-200 rounded-2xl border border-stone-200 bg-white/80" items)))
|
||||
|
||||
;; Data-driven ticket items (replaces Python loop)
|
||||
(defcomp ~checkout-return-tickets-from-data (&key tickets)
|
||||
(~checkout-return-tickets
|
||||
:items (<> (map (lambda (tk)
|
||||
(~checkout-return-ticket
|
||||
:name (get tk "name") :pill (get tk "pill")
|
||||
:state (get tk "state") :type-name (get tk "type_name")
|
||||
:date-str (get tk "date_str") :code (get tk "code")
|
||||
:price (get tk "price")))
|
||||
(or tickets (list))))))
|
||||
|
||||
(defcomp ~checkout-return-content (&key summary items calendar tickets status-message)
|
||||
(div :class "max-w-full px-1 py-1"
|
||||
(when summary
|
||||
|
||||
@@ -99,29 +99,14 @@ def _orders_rows_sx(orders: list, page: int, total_pages: int,
|
||||
from shared.utils import route_prefix
|
||||
pfx = route_prefix()
|
||||
|
||||
parts = []
|
||||
for o in orders:
|
||||
d = _order_row_data(o, pfx + url_for_fn("orders.defpage_order_detail", order_id=o.id))
|
||||
parts.append(sx_call("order-row-desktop",
|
||||
oid=d["oid"], created=d["created"],
|
||||
desc=d["desc"], total=d["total"],
|
||||
pill=d["pill_desktop"], status=d["status"],
|
||||
url=d["url"]))
|
||||
parts.append(sx_call("order-row-mobile",
|
||||
oid=d["oid"], created=d["created"],
|
||||
total=d["total"], pill=d["pill_mobile"],
|
||||
status=d["status"], url=d["url"]))
|
||||
|
||||
if page < total_pages:
|
||||
next_url = pfx + url_for_fn("orders.orders_rows") + qs_fn(page=page + 1)
|
||||
parts.append(sx_call("infinite-scroll",
|
||||
url=next_url, page=page,
|
||||
total_pages=total_pages,
|
||||
id_prefix="orders", colspan=5))
|
||||
else:
|
||||
parts.append(sx_call("order-end-row"))
|
||||
|
||||
return "(<> " + " ".join(parts) + ")"
|
||||
order_dicts = [
|
||||
_order_row_data(o, pfx + url_for_fn("orders.defpage_order_detail", order_id=o.id))
|
||||
for o in orders
|
||||
]
|
||||
next_url = (pfx + url_for_fn("orders.orders_rows") + qs_fn(page=page + 1)) if page < total_pages else None
|
||||
return sx_call("order-rows-from-data",
|
||||
orders=order_dicts, page=page, total_pages=total_pages,
|
||||
next_url=next_url)
|
||||
|
||||
|
||||
def _orders_main_panel_sx(orders: list, rows_sx: str) -> str:
|
||||
@@ -153,35 +138,25 @@ def _order_items_sx(order: Any) -> str:
|
||||
"""Render order items list as sx."""
|
||||
if not order or not order.items:
|
||||
return ""
|
||||
items = []
|
||||
for item in order.items:
|
||||
prod_url = market_product_url(item.product_slug)
|
||||
if item.product_image:
|
||||
img = sx_call(
|
||||
"order-item-image",
|
||||
src=item.product_image, alt=item.product_title or "Product image",
|
||||
)
|
||||
else:
|
||||
img = sx_call("order-item-no-image")
|
||||
|
||||
items.append(sx_call(
|
||||
"order-item-row",
|
||||
href=prod_url, img=SxExpr(img),
|
||||
title=item.product_title or "Unknown product",
|
||||
pid=f"Product ID: {item.product_id}",
|
||||
qty=f"Qty: {item.quantity}",
|
||||
item_dicts = [
|
||||
dict(
|
||||
href=market_product_url(item.product_slug),
|
||||
product_image=item.product_image,
|
||||
product_title=item.product_title or "Unknown product",
|
||||
product_id=str(item.product_id),
|
||||
quantity=str(item.quantity),
|
||||
price=f"{item.currency or order.currency or 'GBP'} {item.unit_price or 0:.2f}",
|
||||
))
|
||||
|
||||
items_sx = "(<> " + " ".join(items) + ")"
|
||||
return sx_call("order-items-panel", items=SxExpr(items_sx))
|
||||
)
|
||||
for item in order.items
|
||||
]
|
||||
return sx_call("order-items-from-data", items=item_dicts)
|
||||
|
||||
|
||||
def _calendar_items_sx(calendar_entries: list | None) -> str:
|
||||
"""Render calendar bookings for an order as sx."""
|
||||
if not calendar_entries:
|
||||
return ""
|
||||
items = []
|
||||
entry_dicts = []
|
||||
for e in calendar_entries:
|
||||
st = e.state or ""
|
||||
pill = (
|
||||
@@ -193,16 +168,13 @@ def _calendar_items_sx(calendar_entries: list | None) -> str:
|
||||
ds = e.start_at.strftime("%-d %b %Y, %H:%M") if e.start_at else ""
|
||||
if e.end_at:
|
||||
ds += f" \u2013 {e.end_at.strftime('%-d %b %Y, %H:%M')}"
|
||||
items.append(sx_call(
|
||||
"order-calendar-entry",
|
||||
entry_dicts.append(dict(
|
||||
name=e.name,
|
||||
pill=f"inline-flex items-center rounded-full px-2 py-0.5 text-[11px] font-medium {pill}",
|
||||
status=st.capitalize(), date_str=ds,
|
||||
cost=f"\u00a3{e.cost or 0:.2f}",
|
||||
))
|
||||
|
||||
items_sx = "(<> " + " ".join(items) + ")"
|
||||
return sx_call("order-calendar-section", items=SxExpr(items_sx))
|
||||
return sx_call("order-calendar-from-data", entries=entry_dicts)
|
||||
|
||||
|
||||
def _order_main_sx(order: Any, calendar_entries: list | None) -> str:
|
||||
@@ -287,7 +259,7 @@ def _ticket_items_sx(order_tickets: list | None) -> str:
|
||||
"""Render ticket items for an order as sx."""
|
||||
if not order_tickets:
|
||||
return ""
|
||||
items = []
|
||||
ticket_dicts = []
|
||||
for tk in order_tickets:
|
||||
st = tk.state or ""
|
||||
pill = (
|
||||
@@ -296,22 +268,19 @@ def _ticket_items_sx(order_tickets: list | None) -> str:
|
||||
else "bg-blue-100 text-blue-800" if st == "checked_in"
|
||||
else "bg-stone-100 text-stone-700"
|
||||
)
|
||||
pill_cls = f"inline-flex items-center rounded-full px-2 py-0.5 text-[11px] font-medium {pill}"
|
||||
ds = tk.entry_start_at.strftime("%-d %b %Y, %H:%M") if tk.entry_start_at else ""
|
||||
if tk.entry_end_at:
|
||||
ds += f" – {tk.entry_end_at.strftime('%-d %b %Y, %H:%M')}"
|
||||
items.append(sx_call(
|
||||
"checkout-return-ticket",
|
||||
ticket_dicts.append(dict(
|
||||
name=tk.entry_name,
|
||||
pill=pill_cls,
|
||||
pill=f"inline-flex items-center rounded-full px-2 py-0.5 text-[11px] font-medium {pill}",
|
||||
state=st.replace("_", " ").capitalize(),
|
||||
type_name=tk.ticket_type_name or None,
|
||||
date_str=ds,
|
||||
code=tk.code,
|
||||
price=f"£{tk.price or 0:.2f}",
|
||||
))
|
||||
items_sx = "(<> " + " ".join(items) + ")"
|
||||
return sx_call("checkout-return-tickets", items=SxExpr(items_sx))
|
||||
return sx_call("checkout-return-tickets-from-data", tickets=ticket_dicts)
|
||||
|
||||
|
||||
async def render_checkout_return_page(ctx: dict, order: Any | None,
|
||||
|
||||
Reference in New Issue
Block a user