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:
@@ -90,6 +90,65 @@
|
||||
compose)
|
||||
(div :id "timeline" timeline))
|
||||
|
||||
;; --- Data-driven post card (replaces Python _post_card_sx loop) ---
|
||||
|
||||
(defcomp ~federation-post-card-from-data (&key d has-actor csrf
|
||||
like-url unlike-url
|
||||
boost-url unboost-url)
|
||||
(let* ((boosted-by (get d "boosted_by"))
|
||||
(actor-icon (get d "actor_icon"))
|
||||
(actor-name (get d "actor_name"))
|
||||
(initial (or (get d "initial") "?"))
|
||||
(avatar (~avatar
|
||||
:src actor-icon
|
||||
:cls (if actor-icon "w-10 h-10 rounded-full"
|
||||
"w-10 h-10 rounded-full bg-stone-300 flex items-center justify-center text-stone-600 font-bold text-sm")
|
||||
:initial (when (not actor-icon) initial)))
|
||||
(boost (when boosted-by (~federation-boost-label :name boosted-by)))
|
||||
(content-sx (if (get d "summary")
|
||||
(~federation-content :content (get d "content") :summary (get d "summary"))
|
||||
(~federation-content :content (get d "content"))))
|
||||
(original (when (get d "original_url")
|
||||
(~federation-original-link :url (get d "original_url"))))
|
||||
(safe-id (get d "safe_id"))
|
||||
(interactions (when has-actor
|
||||
(let* ((oid (get d "object_id"))
|
||||
(ainbox (get d "author_inbox"))
|
||||
(target (str "#interactions-" safe-id))
|
||||
(liked (get d "liked_by_me"))
|
||||
(boosted-me (get d "boosted_by_me"))
|
||||
(l-action (if liked unlike-url like-url))
|
||||
(l-cls (str "flex items-center gap-1 " (if liked "text-red-500 hover:text-red-600" "hover:text-red-500")))
|
||||
(l-icon (if liked "\u2665" "\u2661"))
|
||||
(b-action (if boosted-me unboost-url boost-url))
|
||||
(b-cls (str "flex items-center gap-1 " (if boosted-me "text-green-600 hover:text-green-700" "hover:text-green-600")))
|
||||
(reply-url (get d "reply_url"))
|
||||
(reply (when reply-url (~federation-reply-link :url reply-url)))
|
||||
(like-form (~federation-like-form
|
||||
:action l-action :target target :oid oid :ainbox ainbox
|
||||
:csrf csrf :cls l-cls :icon l-icon :count (get d "like_count")))
|
||||
(boost-form (~federation-boost-form
|
||||
:action b-action :target target :oid oid :ainbox ainbox
|
||||
:csrf csrf :cls b-cls :count (get d "boost_count"))))
|
||||
(div :id (str "interactions-" safe-id)
|
||||
(~federation-interaction-buttons :like like-form :boost boost-form :reply reply))))))
|
||||
(~federation-post-card
|
||||
:boost boost :avatar avatar
|
||||
:actor-name actor-name :actor-username (get d "actor_username")
|
||||
:domain (get d "domain") :time (get d "time")
|
||||
:content content-sx :original original
|
||||
:interactions interactions)))
|
||||
|
||||
;; Data-driven timeline items (replaces Python _timeline_items_sx loop)
|
||||
(defcomp ~federation-timeline-items-from-data (&key items next-url has-actor csrf
|
||||
like-url unlike-url boost-url unboost-url)
|
||||
(<>
|
||||
(map (lambda (d)
|
||||
(~federation-post-card-from-data :d d :has-actor has-actor :csrf csrf
|
||||
:like-url like-url :unlike-url unlike-url :boost-url boost-url :unboost-url unboost-url))
|
||||
(or items (list)))
|
||||
(when next-url (~federation-scroll-sentinel :url next-url))))
|
||||
|
||||
;; --- Compose ---
|
||||
|
||||
(defcomp ~federation-compose-reply (&key reply-to)
|
||||
|
||||
Reference in New Issue
Block a user