src/view/admin/components/previouslies-script.lisp
(defpackage murja.view.admin.components.previouslies-script
(:use :cl :binding-arrows :parenscript :paren-async)
(:export :previouslies-component-frontend)
(:documentation "All the parenscript logic hidden from making murja.view.admin.components.editor an eyesore"))
(in-package :murja.view.admin.components.previouslies-script)
(eval-when (:compile-toplevel :load-toplevel :execute)
(named-readtables:in-readtable :murja.ps))
(defun previouslies-component-frontend ()
(ps
(defun remove-previously (id)
(lambda (e)
(chain e (prevent-default))
(let* ((previouslies-input (chain document
(query-selector "#previouslies")))
(previouslies (chain JSON (parse (@ previouslies-input value)))))
(setf (@ previouslies-input value)
(chain JSON
(stringify
(chain previouslies
(filter
(lambda (el)
(not (= (@ el id) id))))))))
(regenerate-previously-component nil))))
(defun regenerate-previously-component (e)
(let* ((previouslies-container (chain document
(query-selector "#previouslies-container")))
(previouslies-input (chain document
(query-selector "#previouslies")))
(previouslies (chain JSON (parse (@ previouslies-input value))))
(ul-root (chain document
(create-element "ul"))))
;; drop the old previously DOM completely, holding on to the state-holding <input type="hidden"/>
(setf (@ previouslies-container innerHTML) "")
;; generate list of links ->posts and buttons to remove them
(dolist (el previouslies)
(let ((li (chain document (create-element "li")))
(a (chain document (create-element "a")))
(remove-btn (chain document (create-element "button"))))
(setf (@ remove-btn inner-text) "X")
(setf (@ a href) (+ "/blog/post/" (@ el id)))
(setf (@ a inner-text) (@ el title))
(chain remove-btn
(add-event-listener "click" (remove-previously (@ el id))))
(chain li
(append-child a))
(chain li
(append-child remove-btn))
(setf (@ li class-name) "editor-previously-li")
(chain ul-root
(append-child li))))
;; add the state-holding <input type="hidden" /> back to DOM
(chain previouslies-container
(append-child previouslies-input))
;; add the previously generated <ul> tree into DOM
(chain previouslies-container
(append-child ul-root))
nil))
(defun-async previously-searched (e)
(let ((result (await (fetch "/api/posts/search-previously"
(create
method "POST"
body (@ e target value)
headers (create
"Content-Type" "application/json"))))))
(when (equal 200 (@ result status))
(let* ((previouslies-input (chain document
(query-selector "#previouslies")))
(current-previouslies (chain JSON (parse (@ previouslies-input value))))
(root-select (chain document
(query-selector "#previouslyPostResult")))
(result (await (chain result (json))))
(result-data (chain result
(filter (lambda (el)
(not (chain current-previouslies
(includes el))))))))
(setf (@ root-select innerHTML) "")
(dolist (result result-data)
(let ((option (chain document
(create-element "option"))))
(setf (@ option innerText) (@ result title))
(setf (@ option value) (@ result id))
(chain option
(add-event-listener "click" (lambda (e)
(chain e (prevent-default))
(let* ((id (@ e target value))
(title (@ e target innerText))
(previouslies-input (chain document
(query-selector "#previouslies")))
(current-previouslies (chain JSON (parse (@ previouslies-input value)))))
(chain current-previouslies
(push (create id id
title title)))
(setf (@ previouslies-input value) (chain JSON (stringify current-previouslies)))
(setf (@ root-select innerHTML) "")
(setf (@ (chain document
(query-selector "#previouslySearcher"))
innerHTML) "")
(regenerate-previously-component)))))
(chain root-select (append-child option))))))))
(defun link-add-previously-button (e)
(chain document
(query-selector "#add-previously")
(add-event-listener "click"
(lambda (ee)
(chain ee (prevent-default))
(chain document
(query-selector "#previouslyModal")
(show-modal)))))
(chain document
(query-selector "#closeModal")
(add-event-listener "click"
(lambda (ee)
(chain ee (prevent-default))
(chain document
(query-selector "#previouslyModal")
(close)))))
(chain document
(query-selector "#previouslySearcher")
(add-event-listener "input" #'previously-searched)))
(chain document
(add-event-listener "DOMContentLoaded"
#'regenerate-previously-component))
(chain document
(add-event-listener "DOMContentLoaded"
#'link-add-previously-button))))