feat: add filter parameter to spine-index-model for concise default view
This commit is contained in:
@@ -74,8 +74,13 @@ Returns the rendered string."
|
|||||||
("existing_authors" (sort authors #'string<))
|
("existing_authors" (sort authors #'string<))
|
||||||
("existing_categories" (sort categories #'string<)))))
|
("existing_categories" (sort categories #'string<)))))
|
||||||
|
|
||||||
(defun spine-index-model (books &optional selected-id)
|
(defun spine-index-model (books &optional filter selected-id)
|
||||||
"Build the view model ht for templates/index.mustache from BOOKS.
|
"Build the view model ht for templates/index.mustache from BOOKS.
|
||||||
|
FILTER controls which books are shown:
|
||||||
|
nil - concise: READING + 5 most recent WANT, others as summary links
|
||||||
|
all - full listing, no truncation
|
||||||
|
read - only READ books
|
||||||
|
want - only WANT books
|
||||||
SELECTED-ID expands the matching book's detail section."
|
SELECTED-ID expands the matching book's detail section."
|
||||||
(let* ((status-labels
|
(let* ((status-labels
|
||||||
'(("WANT" . "on deck")
|
'(("WANT" . "on deck")
|
||||||
@@ -87,6 +92,8 @@ SELECTED-ID expands the matching book's detail section."
|
|||||||
("ebook" . "ti-device-tablet")
|
("ebook" . "ti-device-tablet")
|
||||||
("audiobook" . "ti-headphones")))
|
("audiobook" . "ti-headphones")))
|
||||||
(order '("WANT" "READING" "READ" "ABANDONED"))
|
(order '("WANT" "READING" "READ" "ABANDONED"))
|
||||||
|
(valid-filters '("all" "read" "want"))
|
||||||
|
(effective-filter (if (member filter valid-filters) filter nil))
|
||||||
(grouped (make-hash-table :test 'equal))
|
(grouped (make-hash-table :test 'equal))
|
||||||
(total (length books))
|
(total (length books))
|
||||||
(reading-count 0))
|
(reading-count 0))
|
||||||
@@ -96,64 +103,88 @@ SELECTED-ID expands the matching book's detail section."
|
|||||||
(dolist (book books)
|
(dolist (book books)
|
||||||
(let ((status (or (plist-get book :status) "WANT")))
|
(let ((status (or (plist-get book :status) "WANT")))
|
||||||
(push book (gethash status grouped))))
|
(push book (gethash status grouped))))
|
||||||
(let ((groups nil))
|
(let ((groups nil)
|
||||||
|
(summary-groups nil))
|
||||||
(dolist (status order)
|
(dolist (status order)
|
||||||
(let ((group-books (nreverse (gethash status grouped))))
|
(let ((group-books (nreverse (gethash status grouped))))
|
||||||
(when group-books
|
(when group-books
|
||||||
(let ((book-models nil))
|
(if (and (null effective-filter)
|
||||||
(dolist (book group-books)
|
(member status '("READ" "ABANDONED")))
|
||||||
(let* ((id (plist-get book :id))
|
(push (ht ("label" (cdr (assoc status status-labels)))
|
||||||
(selected (equal id selected-id))
|
("count" (length group-books))
|
||||||
(fmt (plist-get book :format))
|
("href" (format "/index?filter=%s"
|
||||||
(rating (plist-get book :rating))
|
(downcase status))))
|
||||||
(notes (plist-get book :notes))
|
summary-groups)
|
||||||
(status (or (plist-get book :status) "WANT"))
|
(when (or (null effective-filter)
|
||||||
(model
|
(string= (downcase status) effective-filter)
|
||||||
(ht
|
(string= effective-filter "all"))
|
||||||
("format_icon"
|
(when (and (null effective-filter)
|
||||||
(or (cdr (assoc fmt format-icons)) ""))
|
(string= status "WANT"))
|
||||||
("status_class" (downcase status))
|
(setq group-books
|
||||||
("status_label" (downcase status))
|
(cl-subseq (sort group-books
|
||||||
("title" (plist-get book :title))
|
(lambda (a b)
|
||||||
("author" (or (plist-get book :author) ""))
|
(let ((a-date (plist-get a :added))
|
||||||
("tags_inline"
|
(b-date (plist-get b :added)))
|
||||||
(let ((tags (plist-get book :tags)))
|
(cond
|
||||||
(when tags
|
((null a-date) nil)
|
||||||
(mapconcat (lambda (tag) (concat ":" tag ":"))
|
((null b-date) t)
|
||||||
tags " "))))
|
(t (string> a-date b-date))))))
|
||||||
("rec_via" (plist-get book :rec_by))
|
0 (min (length group-books) 5))))
|
||||||
("rating_display"
|
(let ((book-models nil))
|
||||||
(when (and rating (> (length rating) 0))
|
(dolist (book group-books)
|
||||||
(make-string (string-to-number rating) ?\u2605)))
|
(let* ((id (plist-get book :id))
|
||||||
("selected" selected)
|
(selected (equal id selected-id))
|
||||||
("detail"
|
(fmt (plist-get book :format))
|
||||||
(when selected
|
(rating (plist-get book :rating))
|
||||||
|
(notes (plist-get book :notes))
|
||||||
|
(status (or (plist-get book :status) "WANT"))
|
||||||
|
(model
|
||||||
(ht
|
(ht
|
||||||
("meta"
|
("format_icon"
|
||||||
(let ((added (plist-get book :added))
|
(or (cdr (assoc fmt format-icons)) ""))
|
||||||
(fmt (plist-get book :format)))
|
("status_class" (downcase status))
|
||||||
(cond
|
("status_label" (downcase status))
|
||||||
((and added fmt)
|
("title" (plist-get book :title))
|
||||||
(format "started %s · %s" added fmt))
|
("author" (or (plist-get book :author) ""))
|
||||||
(added (format "started %s" added))
|
("tags_inline"
|
||||||
(fmt (format "format: %s" fmt))
|
(let ((tags (plist-get book :tags)))
|
||||||
(t ""))))
|
(when tags
|
||||||
("notes"
|
(mapconcat (lambda (tag) (concat ":" tag ":"))
|
||||||
(when notes
|
tags " "))))
|
||||||
(cl-loop for (date text) in notes
|
("rec_via" (plist-get book :rec_by))
|
||||||
collect (ht
|
("rating_display"
|
||||||
("date" (format "[%s]" date))
|
(when (and rating (> (length rating) 0))
|
||||||
("text" text)))))))))))
|
(make-string (string-to-number rating) ?\u2605)))
|
||||||
(push model book-models)))
|
("selected" selected)
|
||||||
(push (ht ("label" (cdr (assoc status status-labels)))
|
("detail"
|
||||||
("count" (length group-books))
|
(when selected
|
||||||
("books" (nreverse book-models)))
|
(ht
|
||||||
groups)))))
|
("meta"
|
||||||
|
(let ((added (plist-get book :added))
|
||||||
|
(fmt (plist-get book :format)))
|
||||||
|
(cond
|
||||||
|
((and added fmt)
|
||||||
|
(format "started %s \302\267 %s" added fmt))
|
||||||
|
(added (format "started %s" added))
|
||||||
|
(fmt (format "format: %s" fmt))
|
||||||
|
(t ""))))
|
||||||
|
("notes"
|
||||||
|
(when notes
|
||||||
|
(cl-loop for (date text) in notes
|
||||||
|
collect (ht
|
||||||
|
("date" (format "[%s]" date))
|
||||||
|
("text" text)))))))))))
|
||||||
|
(push model book-models)))
|
||||||
|
(push (ht ("label" (cdr (assoc status status-labels)))
|
||||||
|
("count" (length group-books))
|
||||||
|
("books" (nreverse book-models)))
|
||||||
|
groups)))))))
|
||||||
(ht ("app_title" "spine")
|
(ht ("app_title" "spine")
|
||||||
("total_books" total)
|
("total_books" total)
|
||||||
("reading_count" reading-count)
|
("reading_count" reading-count)
|
||||||
|
("current_filter" (or effective-filter ""))
|
||||||
|
("summary_groups" (nreverse summary-groups))
|
||||||
("groups" (nreverse groups))))))
|
("groups" (nreverse groups))))))
|
||||||
|
|
||||||
(defun spine-add-book (&rest args)
|
(defun spine-add-book (&rest args)
|
||||||
"Add a new WANT book to `spine-org-file'.
|
"Add a new WANT book to `spine-org-file'.
|
||||||
Keyword arguments: :title :author :category :format :isbn :cover
|
Keyword arguments: :title :author :category :format :isbn :cover
|
||||||
|
|||||||
Reference in New Issue
Block a user