Refactor SX templates: shared components, Python migration, cleanup
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 6m0s
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 6m0s
- Extract shared components (empty-state, delete-btn, sentinel, crud-*, view-toggle, img-or-placeholder, avatar, sumup-settings-form, auth forms, order tables/detail/checkout) - Migrate all Python sx_call() callers to use shared components directly - Remove 55+ thin wrapper defcomps from domain .sx files - Remove trivial passthrough wrappers (blog-header-label, market-card-text, etc) - Unify duplicate auth flows (account + federation) into shared/sx/templates/auth.sx - Unify duplicate order views (cart + orders) into shared/sx/templates/orders.sx - Disable static file caching in dev (SEND_FILE_MAX_AGE_DEFAULT=0) - Add SX response validation and debug headers Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -51,10 +51,9 @@ _oob_header_sx = oob_header_sx
|
||||
|
||||
def _blog_header_sx(ctx: dict, *, oob: bool = False) -> str:
|
||||
"""Blog header row — empty child of root."""
|
||||
label_sx = sx_call("blog-header-label")
|
||||
return sx_call("menu-row-sx",
|
||||
id="blog-row", level=1,
|
||||
link_label_content=SxExpr(label_sx),
|
||||
link_label_content=SxExpr("(div)"),
|
||||
child_id="blog-header-child", oob=oob,
|
||||
)
|
||||
|
||||
@@ -160,7 +159,7 @@ def _blog_sentinel_sx(ctx: dict) -> str:
|
||||
total_pages = int(total_pages)
|
||||
|
||||
if page >= total_pages:
|
||||
return sx_call("blog-end-of-results")
|
||||
return sx_call("end-of-results")
|
||||
|
||||
current_local_href = ctx.get("current_local_href", "/index")
|
||||
next_url = f"{current_local_href}?page={page + 1}"
|
||||
@@ -190,9 +189,9 @@ def _blog_sentinel_sx(ctx: dict) -> str:
|
||||
)
|
||||
|
||||
return (
|
||||
sx_call("blog-sentinel-mobile", id=f"sentinel-{page}-m", next_url=next_url, hyperscript=mobile_hs)
|
||||
sx_call("sentinel-mobile", id=f"sentinel-{page}-m", next_url=next_url, hyperscript=mobile_hs)
|
||||
+ " "
|
||||
+ sx_call("blog-sentinel-desktop", id=f"sentinel-{page}-d", next_url=next_url, hyperscript=desktop_hs)
|
||||
+ sx_call("sentinel-desktop", id=f"sentinel-{page}-d", next_url=next_url, hyperscript=desktop_hs)
|
||||
)
|
||||
|
||||
|
||||
@@ -363,11 +362,11 @@ def _page_cards_sx(ctx: dict) -> str:
|
||||
if page_num < total_pages:
|
||||
current_local_href = ctx.get("current_local_href", "/index?type=pages")
|
||||
next_url = f"{current_local_href}&page={page_num + 1}" if "?" in current_local_href else f"{current_local_href}?page={page_num + 1}"
|
||||
parts.append(sx_call("blog-page-sentinel",
|
||||
parts.append(sx_call("sentinel-simple",
|
||||
id=f"sentinel-{page_num}-d", next_url=next_url,
|
||||
))
|
||||
elif pages:
|
||||
parts.append(sx_call("blog-end-of-results"))
|
||||
parts.append(sx_call("end-of-results"))
|
||||
else:
|
||||
parts.append(sx_call("blog-no-pages"))
|
||||
|
||||
@@ -407,12 +406,12 @@ def _view_toggle_sx(ctx: dict) -> str:
|
||||
list_href = f"{current_local_href}"
|
||||
tile_href = f"{current_local_href}{'&' if '?' in current_local_href else '?'}view=tile"
|
||||
|
||||
list_svg_sx = sx_call("blog-list-svg")
|
||||
tile_svg_sx = sx_call("blog-tile-svg")
|
||||
list_svg_sx = sx_call("list-svg")
|
||||
tile_svg_sx = sx_call("tile-svg")
|
||||
|
||||
return sx_call("blog-view-toggle",
|
||||
return sx_call("view-toggle",
|
||||
list_href=list_href, tile_href=tile_href, hx_select=hx_select,
|
||||
list_cls=list_cls, tile_cls=tile_cls,
|
||||
list_cls=list_cls, tile_cls=tile_cls, storage_key="blog_view",
|
||||
list_svg=SxExpr(list_svg_sx), tile_svg=SxExpr(tile_svg_sx),
|
||||
)
|
||||
|
||||
@@ -782,7 +781,7 @@ def _home_main_panel_sx(ctx: dict) -> str:
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def _post_admin_main_panel_sx(ctx: dict) -> str:
|
||||
return sx_call("blog-admin-empty")
|
||||
return '(div :class "pb-8")'
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -790,7 +789,7 @@ def _post_admin_main_panel_sx(ctx: dict) -> str:
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def _settings_main_panel_sx(ctx: dict) -> str:
|
||||
return sx_call("blog-settings-empty")
|
||||
return '(div :class "max-w-2xl mx-auto px-4 py-6")'
|
||||
|
||||
|
||||
def _cache_main_panel_sx(ctx: dict) -> str:
|
||||
@@ -821,7 +820,7 @@ def _snippets_list_sx(ctx: dict) -> str:
|
||||
user_id = getattr(user, "id", None)
|
||||
|
||||
if not snippets:
|
||||
return sx_call("blog-snippets-empty")
|
||||
return sx_call("empty-state", icon="fa fa-puzzle-piece", message="No snippets yet. Create one from the blog editor.")
|
||||
|
||||
badge_colours = {
|
||||
"private": "bg-stone-200 text-stone-700",
|
||||
@@ -856,10 +855,12 @@ def _snippets_list_sx(ctx: dict) -> str:
|
||||
|
||||
if s_uid == user_id or is_admin:
|
||||
del_url = qurl("snippets.delete_snippet", snippet_id=s_id)
|
||||
extra += sx_call("blog-snippet-delete-button",
|
||||
confirm_text=f'Delete \u201c{s_name}\u201d?',
|
||||
delete_url=del_url,
|
||||
hx_headers=f'{{"X-CSRFToken": "{csrf}"}}',
|
||||
extra += sx_call("delete-btn",
|
||||
url=del_url, trigger_target="#snippets-list",
|
||||
title="Delete snippet?",
|
||||
text=f'Delete \u201c{s_name}\u201d?',
|
||||
sx_headers=f'{{"X-CSRFToken": "{csrf}"}}',
|
||||
cls="px-3 py-1 text-sm bg-red-200 hover:bg-red-300 rounded text-red-800 flex-shrink-0",
|
||||
)
|
||||
|
||||
row_parts.append(sx_call("blog-snippet-row",
|
||||
@@ -890,7 +891,7 @@ def _menu_items_list_sx(ctx: dict) -> str:
|
||||
csrf = _ctx_csrf(ctx)
|
||||
|
||||
if not menu_items:
|
||||
return sx_call("blog-menu-items-empty")
|
||||
return sx_call("empty-state", icon="fa fa-inbox", message="No menu items yet. Add one to get started!")
|
||||
|
||||
row_parts = []
|
||||
for item in menu_items:
|
||||
@@ -903,7 +904,8 @@ def _menu_items_list_sx(ctx: dict) -> str:
|
||||
edit_url = qurl("menu_items.edit_menu_item", item_id=i_id)
|
||||
del_url = qurl("menu_items.delete_menu_item_route", item_id=i_id)
|
||||
|
||||
img_sx = sx_call("blog-menu-item-image", src=fi, label=label)
|
||||
img_sx = sx_call("img-or-placeholder", src=fi, alt=label,
|
||||
size_cls="w-12 h-12 rounded-full object-cover flex-shrink-0")
|
||||
|
||||
row_parts.append(sx_call("blog-menu-item-row",
|
||||
img=SxExpr(img_sx), label=label, slug=slug,
|
||||
@@ -958,7 +960,7 @@ def _tag_groups_main_panel_sx(ctx: dict) -> str:
|
||||
))
|
||||
groups_sx = sx_call("blog-tag-groups-list", items=SxExpr("(<> " + " ".join(li_parts) + ")"))
|
||||
else:
|
||||
groups_sx = sx_call("blog-tag-groups-empty")
|
||||
groups_sx = sx_call("empty-state", message="No tag groups yet.", cls="text-stone-500 text-sm")
|
||||
|
||||
# Unassigned tags
|
||||
unassigned_sx = ""
|
||||
@@ -1687,7 +1689,8 @@ def render_menu_items_nav_oob(menu_items, ctx: dict | None = None) -> str:
|
||||
|
||||
selected = "true" if (item_slug == first_seg or item_slug == app_name) else "false"
|
||||
|
||||
img_sx = sx_call("blog-nav-item-image", src=fi, label=label)
|
||||
img_sx = sx_call("img-or-placeholder", src=fi, alt=label,
|
||||
size_cls="w-8 h-8 rounded-full object-cover flex-shrink-0")
|
||||
|
||||
if item_slug != "cart":
|
||||
item_parts.append(sx_call("blog-nav-item-link",
|
||||
@@ -1702,12 +1705,13 @@ def render_menu_items_nav_oob(menu_items, ctx: dict | None = None) -> str:
|
||||
|
||||
items_sx = "(<> " + " ".join(item_parts) + ")" if item_parts else ""
|
||||
|
||||
return sx_call("blog-nav-wrapper",
|
||||
arrow_cls=arrow_cls, container_id=container_id,
|
||||
return sx_call("scroll-nav-wrapper",
|
||||
wrapper_id="menu-items-nav-wrapper", container_id=container_id,
|
||||
arrow_cls=arrow_cls,
|
||||
left_hs=f"on click set #{container_id}.scrollLeft to #{container_id}.scrollLeft - 200",
|
||||
scroll_hs=scroll_hs,
|
||||
right_hs=f"on click set #{container_id}.scrollLeft to #{container_id}.scrollLeft + 200",
|
||||
items=SxExpr(items_sx) if items_sx else None,
|
||||
items=SxExpr(items_sx) if items_sx else None, oob=True,
|
||||
)
|
||||
|
||||
|
||||
@@ -1737,15 +1741,12 @@ def render_features_panel(features: dict, post: dict,
|
||||
sumup_sx = ""
|
||||
if features.get("calendar") or features.get("market"):
|
||||
placeholder = "\u2022" * 8 if sumup_configured else "sup_sk_..."
|
||||
connected = sx_call("blog-sumup-connected") if sumup_configured else ""
|
||||
key_hint = sx_call("blog-sumup-key-hint") if sumup_configured else ""
|
||||
|
||||
sumup_sx = sx_call("blog-sumup-form",
|
||||
sumup_url=sumup_url, merchant_code=sumup_merchant_code,
|
||||
placeholder=placeholder,
|
||||
key_hint=SxExpr(key_hint) if key_hint else None,
|
||||
sumup_configured=sumup_configured,
|
||||
checkout_prefix=sumup_checkout_prefix,
|
||||
connected=SxExpr(connected) if connected else None,
|
||||
)
|
||||
|
||||
return sx_call("blog-features-panel",
|
||||
@@ -1906,8 +1907,8 @@ def render_nav_entries_oob(associated_entries, calendars, post: dict, ctx: dict
|
||||
|
||||
href = events_url_fn(entry_path) if events_url_fn else entry_path
|
||||
|
||||
item_parts.append(sx_call("blog-nav-entry-item",
|
||||
href=href, nav_cls=nav_cls, name=e_name, date_str=date_str,
|
||||
item_parts.append(sx_call("calendar-entry-nav",
|
||||
href=href, nav_class=nav_cls, name=e_name, date_str=date_str,
|
||||
))
|
||||
|
||||
# Calendar links
|
||||
@@ -1923,6 +1924,11 @@ def render_nav_entries_oob(associated_entries, calendars, post: dict, ctx: dict
|
||||
|
||||
items_sx = "(<> " + " ".join(item_parts) + ")" if item_parts else ""
|
||||
|
||||
return sx_call("blog-nav-entries-wrapper",
|
||||
scroll_hs=scroll_hs, items=SxExpr(items_sx) if items_sx else None,
|
||||
return sx_call("scroll-nav-wrapper",
|
||||
wrapper_id="entries-calendars-nav-wrapper", container_id="associated-items-container",
|
||||
arrow_cls="entries-nav-arrow",
|
||||
left_hs="on click set #associated-items-container.scrollLeft to #associated-items-container.scrollLeft - 200",
|
||||
scroll_hs=scroll_hs,
|
||||
right_hs="on click set #associated-items-container.scrollLeft to #associated-items-container.scrollLeft + 200",
|
||||
items=SxExpr(items_sx) if items_sx else None, oob=True,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user