src/view/components/root.lisp
(defpackage murja.view.components.root
(:use :cl :spinneret :binding-arrows
:murja.settings
:murja.middleware.auth
:murja.model.user)
(:export :*inject-to-head* :*inject-to-sidebar* :root-component)
(:import-from :murja.posts.post-db :get-titles-by-year))
(in-package :murja.view.components.root)
(defun sidebar-tree ()
(let* ((sidebar-titles (->>
(get-titles-by-year)
(lisp-fixup:group-by "Year"))))
(with-html
(:ul :id "grouper"
(loop for year being the hash-keys of sidebar-titles
collecting (:li
(:details
(:summary (format nil "~a (~d)" year (length (gethash year sidebar-titles))))
(:ul
(let ((by-month (lisp-fixup:group-by "Month" (gethash year sidebar-titles))))
(loop for month being the hash-keys of by-month
collecting (:li
(:details
(:summary (format nil "~a (~d)" month (length (gethash month by-month))))
(:ul
(map 'list
(lambda (title)
(cl-hash-util:with-keys ("Id" "Title") title
(:li (:a :href (format nil "/blog/post/~d" Id)
Title))))
(gethash month by-month)))))))))))))))
(defun sidebar/new-post ()
(let ((disabled-routes (list "/blog/new-post"
"/blog/post/editor")))
(with-html
(if (and *user*
(not (member (cl-ppcre:regex-replace "/\\d+$" (hunchentoot:request-uri*) "")
disabled-routes
:test 'equal)))
(:form :action "/blog/new-post" :method "post"
(:input :type :submit :value "NEW POST"))))))
(defun loginform/user-widget ()
(with-html
(if *user*
(:p :data-testid "welcome-user-label"
"Welcome, " (:a :href "/blog/usersettings" (user-nickname *user*)))
(:form :method "post" :action "/api/login"
(:label "Username "
(:input :id "username" :name "username" :data-testid "username-input-field"))
(:label "Password "
(:input :id "password" :name "password" :type "password" :data-testid "password-input-field"))
(:input :type :submit :value "Log in")))))
(defvar *inject-to-head* nil)
(defvar *inject-to-sidebar* nil)
(defmacro root-component (inner-component)
(assert inner-component)
"Returns the root html element of murja with `inner-component` embedded inside it"
`(format nil "<!DOCTYPE html>~%~a"
;; let's make *inject-to-sidebar* request-scoped
(let ((*inject-to-sidebar* nil))
(with-html-string
(:html
(:head
(:link :href "/resources/murja.css" :rel "stylesheet" :type "text/css")
(:meta :charset "UTF-8")
(dolist (head-element *inject-to-head*)
(funcall head-element)))
(:body
(:header
(:a :href "/" (gethash "blog-title" *settings* )))
(:div :class "sidebar-flex"
,inner-component
(:div :id "sidebar"
(sidebar/new-post)
(loginform/user-widget)
(sidebar-tree)
(if *inject-to-sidebar*
(progn (format t "*inject-to-sidebar* is something~%")
(funcall *inject-to-sidebar*))
(format t "*inject-to-sidebar* is nothing~%"))))))))))