Component names now reflect filesystem location using / as path separator and : as namespace separator for shared components: ~sx-header → ~layouts/header ~layout-app-body → ~shared:layout/app-body ~blog-admin-dashboard → ~admin/dashboard 209 files, 4,941 replacements across all services. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
83 lines
3.6 KiB
Plaintext
83 lines
3.6 KiB
Plaintext
;; Events container-nav fragment handler
|
||
;; returns: sx
|
||
;;
|
||
;; Renders calendar entry nav items + calendar link nav items
|
||
;; for the scrollable navigation panel on blog post pages.
|
||
;;
|
||
;; Params (from request.args):
|
||
;; container_type — "page" (default)
|
||
;; container_id — int
|
||
;; post_slug — string
|
||
;; paginate_url — base URL for infinite scroll
|
||
;; page — current page (default 1)
|
||
;; exclude — comma-separated exclusion prefixes
|
||
;; current_calendar — currently selected calendar slug
|
||
|
||
(defhandler container-nav
|
||
(&key container_type container_id post_slug paginate_url page exclude current_calendar)
|
||
|
||
(let ((ct (or container_type "page"))
|
||
(cid (parse-int (or container_id "0")))
|
||
(slug (or post_slug ""))
|
||
(purl (or paginate_url ""))
|
||
(pg (parse-int (or page "1")))
|
||
(excl-raw (or exclude ""))
|
||
(cur-cal (or current_calendar ""))
|
||
(excludes (filter (fn (e) (not (empty? e)))
|
||
(map trim (split excl-raw ","))))
|
||
(has-cal-excl (not (empty? (filter (fn (e) (starts-with? e "calendar"))
|
||
excludes))))
|
||
(styles (or (jinja-global "styles") (dict)))
|
||
(nav-class (or (get styles "nav_button") ""))
|
||
(sel-colours (or (jinja-global "select_colours") "")))
|
||
|
||
;; Only render if no calendar-* exclusion
|
||
(when (not has-cal-excl)
|
||
(let ((result (service "calendar" "associated-entries"
|
||
:content-type ct :content-id cid :page pg))
|
||
(entries (first result))
|
||
(has-more (nth result 1))
|
||
(calendars (service "calendar" "calendars-for-container"
|
||
:container-type ct :container-id cid)))
|
||
|
||
(<>
|
||
;; Calendar entry nav items
|
||
(map (fn (entry)
|
||
(let ((entry-path (str "/" slug "/"
|
||
(get entry "calendar_slug") "/"
|
||
(get entry "start_at_year") "/"
|
||
(get entry "start_at_month") "/"
|
||
(get entry "start_at_day")
|
||
"/entries/" (get entry "id") "/"))
|
||
(date-str (str (format-date (get entry "start_at") "%b %d, %Y at %H:%M")
|
||
(if (get entry "end_at")
|
||
(str " – " (format-date (get entry "end_at") "%H:%M"))
|
||
""))))
|
||
(~shared:navigation/calendar-entry-nav
|
||
:href (app-url "events" entry-path)
|
||
:name (get entry "name")
|
||
:date-str date-str
|
||
:nav-class nav-class))) entries)
|
||
|
||
;; Infinite scroll sentinel
|
||
(when (and has-more (not (empty? purl)))
|
||
(~shared:misc/htmx-sentinel
|
||
:id (str "entries-load-sentinel-" pg)
|
||
:hx-get (str purl "?page=" (+ pg 1))
|
||
:hx-trigger "intersect once"
|
||
:hx-swap "beforebegin"
|
||
:class "flex-shrink-0 w-1"))
|
||
|
||
;; Calendar link nav items
|
||
(map (fn (cal)
|
||
(let ((href (app-url "events" (str "/" slug "/" (get cal "slug") "/")))
|
||
(is-selected (if (not (empty? cur-cal))
|
||
(= (get cal "slug") cur-cal)
|
||
false)))
|
||
(~shared:navigation/calendar-link-nav
|
||
:href href
|
||
:name (get cal "name")
|
||
:nav-class nav-class
|
||
:is-selected is-selected
|
||
:select-colours sel-colours))) calendars))))))
|