Move SX construction from Python to .sx defcomps (phases 0-4)

Eliminate Python s-expression string building across account, orders,
federation, and cart services. Visual rendering logic now lives entirely
in .sx defcomp components; Python files contain only data serialization,
header/layout wiring, and thin wrappers that call defcomps.

Phase 0: Shared DRY extraction — auth/orders header defcomps, format-decimal/
pluralize/escape/route-prefix primitives.
Phase 1: Account — dashboard, newsletters, login/device/check-email content.
Phase 2: Orders — order list, detail, filter, checkout return assembled defcomps.
Phase 3: Federation — social nav, post cards, timeline, search, actors,
notifications, compose, profile assembled defcomps.
Phase 4: Cart — overview, page cart items/calendar/tickets/summary, admin,
payments assembled defcomps; orders rendering reuses Phase 2 shared defcomps.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-03 22:36:34 +00:00
parent 03f0929fdf
commit 193578ef88
23 changed files with 1824 additions and 1795 deletions

View File

@@ -73,11 +73,41 @@ def register(url_prefix: str) -> Blueprint:
result = await g.s.execute(stmt)
orders = result.scalars().all()
from sx.sx_components import _orders_rows_sx
from shared.sx.helpers import sx_response
from shared.sx.helpers import sx_response, sx_call, SxExpr
from shared.sx.parser import serialize
from shared.utils import route_prefix
pfx = route_prefix()
order_dicts = []
for o in orders:
order_dicts.append({
"id": o.id,
"status": o.status or "pending",
"created_at_formatted": o.created_at.strftime("%-d %b %Y, %H:%M") if o.created_at else "\u2014",
"description": o.description or "",
"currency": o.currency or "GBP",
"total_formatted": f"{o.total_amount or 0:.2f}",
})
detail_prefix = pfx + url_for("orders.defpage_order_detail", order_id=0).rsplit("0/", 1)[0]
qs_fn = makeqs_factory()
sx_src = _orders_rows_sx(orders, page, total_pages, url_for, qs_fn)
rows_url = pfx + url_for("orders.orders_rows")
# Build just the rows fragment (not full table) for infinite scroll
parts = []
for od in order_dicts:
parts.append(sx_call("order-row-pair",
order=SxExpr(serialize(od)),
detail_url_prefix=detail_prefix))
if page < total_pages:
parts.append(sx_call("infinite-scroll",
url=rows_url + qs_fn(page=page + 1),
page=page, total_pages=total_pages,
id_prefix="orders", colspan=5))
else:
parts.append(sx_call("order-end-row"))
sx_src = "(<> " + " ".join(parts) + ")"
resp = sx_response(sx_src)
resp.headers["Hx-Push-Url"] = _current_url_without_page()
return _vary(resp)