src/view/admin/media-admin.lisp
(defpackage murja.view.admin.media-admin
(:use :cl :binding-arrows :spinneret :ps :paren-async)
(:import-from :murja.media.media-db :select-referencing-posts*)
(:import-from :murja.view.components.tabs :deftab))
(in-package :murja.view.admin.media-admin)
(eval-when (:compile-toplevel :load-toplevel :execute)
(named-readtables:in-readtable :murja.ps))
(defun media-admin-script ()
(ps
(defun-async delete-selected (e)
(let* ((selected-nodes (chain document
(query-selector-all ".marked-for-deletion:checked")))
(delete-payload (create ids
(chain Array
(from selected-nodes)
(map (lambda (node)
(@ node dataset picid))))))
(result (await
(fetch "/api/pictures"
(create
method "DELETE"
body (chain JSON (stringify delete-payload))
headers (create "Content-Type" "application/json"))))))
(if (= (@ result status) 204)
(chain location (reload))
(alert (+ "Error: " (@ result status) ": " (await (chain result (text))))))))
(chain document
(add-event-listener "DOMContentLoaded"
(lambda (e)
(let ((select-all-btn
(chain document
(query-selector "#select-all")))
(delete-selected-btn
(chain document
(query-selector "#delete-selected"))))
(chain delete-selected-btn
(add-event-listener "click"
#'delete-selected))
(chain select-all-btn
(add-event-listener "click"
(lambda (e)
(dolist (element (chain document
(query-selector-all "input[type=checkbox]")))
(setf (@ element checked) true)))))))))))
(deftab blog/media-admin (:url "/blog/media-admin"
:title "Manage media"
:require-login t
:needed-abilities ("create-post" "delete-post" "edit-post"))
(let ((all-pics (postmodern:query "SELECT id, name from blog.media")))
(:script (:raw (media-admin-script)))
(:div.mediamanager-header (:button :id "select-all" "Select all") (:button :id "delete-selected" "Delete selected images"))
(:ul.images
(dolist (pic all-pics)
(destructuring-bind (id name) pic
(let ((referencing-posts (postmodern:query "SELECT post_id, post_title FROM blog.media_post_pairing WHERE media_id = $1" id)))
(:li.image
(:div.image-header (:label "Mark for deletion" (:input.marked-for-deletion :type :checkbox :data-picId id)))
(:details (:summary name)
(:img :src (format nil "/api/pictures/~a" id)))
(:details (:summary ("Referencing posts (~d)" (length referencing-posts)))
(if referencing-posts
(:ul
(dolist (referencer referencing-posts)
(destructuring-bind (post-id post-title) referencer
(:li (:a :href (format nil "/blog/post/~a" post-id) post-title)))))
(:div "No referencing posts"))))))))))