feat: add root-level minibuffer actions and update template

This commit is contained in:
2026-06-21 11:56:05 -04:00
parent 6e821de7b1
commit c505a3c239
3 changed files with 68 additions and 53 deletions
+39 -33
View File
@@ -174,38 +174,6 @@ SELECTED-ID expands the matching book's detail section."
collect (ht collect (ht
("date" (format "[%s]" date)) ("date" (format "[%s]" date))
("text" text)))))))) ("text" text))))))))
("minibuffer"
(when selected
(let ((status (plist-get book :status)))
(ht ("actions"
(append
(cond
((equal status "WANT")
(list
(ht ("command" "status") ("label" "Mark reading")
("href" (format "/edit?id=%s&action=status&value=READING" id)))
(ht ("command" "note") ("label" "Add note")
("href" (format "/edit?id=%s&action=note" id)))))
((equal status "READING")
(list
(ht ("command" "status") ("label" "Mark read")
("href" (format "/edit?id=%s&action=status&value=READ" id)))
(ht ("command" "status") ("label" "Abandon")
("href" (format "/edit?id=%s&action=status&value=ABANDONED" id)))
(ht ("command" "note") ("label" "Add note")
("href" (format "/edit?id=%s&action=note" id)))))
((equal status "READ")
(list
(ht ("command" "status") ("label" "Read again")
("href" (format "/edit?id=%s&action=status&value=READING" id)))
(ht ("command" "note") ("label" "Add note")
("href" (format "/edit?id=%s&action=note" id)))))
((equal status "ABANDONED")
(list
(ht ("command" "status") ("label" "Try again")
("href" (format "/edit?id=%s&action=status&value=READING" id)))))
(t nil))
nil))))))
))) )))
(push model book-models))) (push model book-models)))
(push (ht ("label" (cdr (assoc status status-labels))) (push (ht ("label" (cdr (assoc status status-labels)))
@@ -217,7 +185,45 @@ SELECTED-ID expands the matching book's detail section."
("reading_count" reading-count) ("reading_count" reading-count)
("current_filter" effective-filter) ("current_filter" effective-filter)
("summary_groups" (nreverse summary-groups)) ("summary_groups" (nreverse summary-groups))
("groups" (nreverse groups)))))) ("groups" (nreverse groups))
("minibuffer"
(when selected-id
(let* ((books-by-id (make-hash-table :test 'equal)))
(dolist (b books)
(puthash (plist-get b :id) b books-by-id))
(let ((book (gethash selected-id books-by-id)))
(when book
(let ((status (or (plist-get book :status) "WANT")))
(ht ("actions"
(append
(cond
((equal status "WANT")
(list
(ht ("command" "status") ("label" "Mark reading")
("href" (format "/edit?id=%s&action=status&value=READING" selected-id)))
(ht ("command" "note") ("label" "Add note")
("href" (format "/edit?id=%s&action=note" selected-id)))))
((equal status "READING")
(list
(ht ("command" "status") ("label" "Mark read")
("href" (format "/edit?id=%s&action=status&value=READ" selected-id)))
(ht ("command" "status") ("label" "Abandon")
("href" (format "/edit?id=%s&action=status&value=ABANDONED" selected-id)))
(ht ("command" "note") ("label" "Add note")
("href" (format "/edit?id=%s&action=note" selected-id)))))
((equal status "READ")
(list
(ht ("command" "status") ("label" "Read again")
("href" (format "/edit?id=%s&action=status&value=READING" selected-id)))
(ht ("command" "note") ("label" "Add note")
("href" (format "/edit?id=%s&action=note" selected-id)))))
((equal status "ABANDONED")
(list
(ht ("command" "status") ("label" "Try again")
("href" (format "/edit?id=%s&action=status&value=READING" selected-id)))))
(t nil))
nil))))))))
)))))
(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
+5 -2
View File
@@ -132,8 +132,11 @@
{{#minibuffer}} {{#minibuffer}}
<footer class="minibuffer"> <footer class="minibuffer">
<span class="muted">M-x</span> <span class="muted">M-x</span>
<span>{{command}}</span> <span style="display:flex;gap:.5rem;flex-wrap:wrap">
<span class="text">{{text}}<span class="caret">▏</span></span> {{#actions}}
<a href="{{href}}" class="pill" style="text-decoration:none">{{label}}</a>
{{/actions}}
</span>
</footer> </footer>
{{/minibuffer}} {{/minibuffer}}
</article> </article>
+24 -18
View File
@@ -106,29 +106,35 @@
"spine-set-status signals error for unknown ID." "spine-set-status signals error for unknown ID."
(should-error (spine-set-status "nonexistent-id" "READING"))) (should-error (spine-set-status "nonexistent-id" "READING")))
(ert-deftest spine-edit-model-minibuffer-want ()
"Selected WANT book has Mark reading and Add note actions." "Selected WANT book has Mark reading and Add note actions."
(spine-edit-test--cleanup) (spine-edit-test--cleanup)
(ert-deftest spine-edit-model-minibuffer-reading ()
"Selected READING book has Mark read, Abandon, Add note actions."
(spine-edit-test--cleanup)
(unwind-protect (unwind-protect
(progn (progn
(spine-edit-test--setup) (spine-edit-test--setup)
(let* ((books (spine-books)) (let* ((books (spine-books))
(book (car books)) (book (car books))
(id (plist-get book :id)) (id (plist-get book :id)))
(model (spine-index-model books nil id)) (spine-set-status id "READING")
(groups (ht-get model "groups"))) (let ((model (spine-index-model (spine-books) nil id)))
(cl-labels ((find-book-model (groups id) (let ((mb (ht-get model "minibuffer")))
(cl-block nil (should mb)
(dolist (g groups) (let ((actions (ht-get mb "actions")))
(dolist (b (ht-get g "books")) (should (= (length actions) 3))
(when (string= (ht-get b "title") "Edit Test Book") (should (string= (ht-get (nth 0 actions) "label") "Mark read"))
(cl-return b))))))) (should (string= (ht-get (nth 1 actions) "label") "Abandon"))
(let ((bm (find-book-model groups id))) (should (string= (ht-get (nth 2 actions) "label") "Add note")))))))
(should bm) (spine-edit-test--cleanup)))
(let ((mb (ht-get bm "minibuffer")))
(should mb) (ert-deftest spine-edit-model-minibuffer-nil-when-no-selection ()
(let ((actions (ht-get mb "actions"))) "No minibuffer when no book is selected."
(should (= (length actions) 2)) (spine-edit-test--cleanup)
(should (string= (ht-get (nth 0 actions) "label") "Mark reading")) (unwind-protect
(should (string= (ht-get (nth 1 actions) "label") "Add note")))))))) (progn
(spine-edit-test--setup)
(let ((model (spine-index-model (spine-books))))
(should-not (ht-get model "minibuffer"))))
(spine-edit-test--cleanup))) (spine-edit-test--cleanup)))