diff --git a/src/components/article.lisp b/src/components/article.lisp index e008cb1..d7ec861 100644 --- a/src/components/article.lisp +++ b/src/components/article.lisp @@ -7,7 +7,11 @@ (:export #:~article)) (in-package #:website/components/article) -(defcomp ~article (&key title content revised-at draft-p) +(defcomp ~article (&key title + content + published-at + revised-at + draft-p) (hsx (<> (and draft-p (hsx (p :class "text-lg text-pink-500" "Draft Mode"))) @@ -15,7 +19,19 @@ (h1 title) (raw! content) (p :class "text-right" - "(Last updated: " - (|time| :datetime (datetime revised-at) - (asctime revised-at)) - ")"))))) + (and published-at + (hsx + (span + "(Published: " + (|time| :datetime (datetime published-at) + (asctime published-at)) + ")"))) + (and revised-at + (hsx + (<> + (br) + (span + "(Last updated: " + (|time| :datetime (datetime revised-at) + (asctime revised-at)) + ")"))))))))) diff --git a/src/lib/cache.lisp b/src/lib/cache.lisp index 6e8393e..31e840f 100644 --- a/src/lib/cache.lisp +++ b/src/lib/cache.lisp @@ -2,9 +2,11 @@ (:use #:cl) (:import-from #:function-cache #:defcached - #:clear-cache) + #:clear-cache + #:clear-cache-partial-arguments) (:export #:memorize - #:clear-cache)) + #:clear-cache + #:clear-cache-partial-artuments)) (in-package #:website/lib/cache) (defmacro memorize (name) diff --git a/src/lib/cms.lisp b/src/lib/cms.lisp index 317a095..567394e 100644 --- a/src/lib/cms.lisp +++ b/src/lib/cms.lisp @@ -9,9 +9,13 @@ (:import-from #:website/lib/cache #:memorize) (:export #:get-about + #:*get-about-cache* #:get-works + #:*get-works-cache* #:get-blog-list - #:get-blog-detail)) + #:*get-blog-list-cache* + #:get-blog-detail + #:*get-blog-detail-cache*)) (in-package #:website/lib/cms) (setf microcms:*service-domain* (microcms-service-domain)) diff --git a/src/routes/api/revalidate.lisp b/src/routes/api/revalidate.lisp index d0d1491..687838a 100644 --- a/src/routes/api/revalidate.lisp +++ b/src/routes/api/revalidate.lisp @@ -1,15 +1,19 @@ (defpackage #:website/routes/api/revalidate (:use #:cl - #:jingle) + #:jingle + #:access) (:import-from #:website/lib/env #:microcms-webhook-key) (:import-from #:website/helper #:get-request-body-plist) (:import-from #:website/lib/cms - #:get-about - #:get-works) + #:*get-about-cache* + #:*get-works-cache* + #:*get-blog-list-cache* + #:*get-blog-detail-cache*) (:import-from #:website/lib/cache - #:clear-cache) + #:clear-cache + #:clear-cache-partial-arguments) (:export #:handle-post)) (in-package #:website/routes/api/revalidate) @@ -20,7 +24,29 @@ (set-response-status :unauthorized) (return-from handle-post '(:|message| "Invalid token"))) (let* ((body (get-request-body-plist)) - (api (getf body :|api|))) - (cond ((string= api "about") (clear-cache 'get-about)) - ((string= api "works") (clear-cache 'get-works))) - '(:|message| "ok"))) + (api (getf body :|api|)) + (id (getf body :|id|)) + (old-draft-key (accesses body :|contents| :|old| :|draftKey|)) + (new-draft-key (accesses body :|contents| :|new| :|draftKey|))) + (cond ((string= api "about") + (if new-draft-key + (clear-cache-partial-arguments *get-about-cache* + (list :query (list :draft-key new-draft-key))) + (clear-cache *get-about-cache*))) + ((string= api "works") + (if new-draft-key + (clear-cache-partial-arguments *get-works-cache* + (list :query (list :draft-key new-draft-key))) + (clear-cache *get-works-cache*))) + ((string= api "blog") + (unless new-draft-key + (clear-cache *get-blog-list-cache*) + (clear-cache-partial-arguments *get-blog-detail-cache* + (list id :query (list :draft-key old-draft-key)))) + (clear-cache-partial-arguments *get-blog-detail-cache* + (list id :query (list :draft-key new-draft-key))))) + (list :|api| api + :|id| id + :|old-draft-key| old-draft-key + :|new-draft-key| new-draft-key + :|message| "ok"))) diff --git a/src/routes/blog.lisp b/src/routes/blog.lisp deleted file mode 100644 index 820b359..0000000 --- a/src/routes/blog.lisp +++ /dev/null @@ -1,14 +0,0 @@ -(defpackage #:website/routes/blog - (:use #:cl - #:hsx - #:jingle) - (:export #:handle-get)) -(in-package #:website/routes/blog) - -(defparameter *metadata* - (list :title "blog")) - -(defun handle-get (params) - (declare (ignore params)) - (setf (context :metadata) *metadata*) - (hsx (p "coming soon"))) diff --git a/src/routes/blog/<id>.lisp b/src/routes/blog/<id>.lisp new file mode 100644 index 0000000..e567b6e --- /dev/null +++ b/src/routes/blog/<id>.lisp @@ -0,0 +1,30 @@ +(defpackage #:website/routes/blog/<id> + (:use #:cl + #:hsx + #:jingle) + (:import-from #:website/lib/cms + #:get-blog-detail) + (:import-from #:website/routes/not-found + #:handle-not-found) + (:import-from #:website/components/article + #:~article) + (:export #:handle-get)) +(in-package #:website/routes/blog/<id>) + +(defun handle-get (params) + (with-request-params ((id :id nil) + (draft-key "draft-key" nil)) params + (setf (context :no-cache) draft-key) + (let ((blog (get-blog-detail id :query (list :draft-key draft-key)))) + (unless blog + (return-from handle-get (handle-not-found))) + (setf (context :metadata) (list :title (getf blog :title) + :description (getf blog :description) + :type "article")) + (hsx + (~article + :title (getf blog :title) + :content (getf blog :content) + :published-at (getf blog :published-at) + :revised-at (getf blog :revised-at) + :draft-p draft-key))))) diff --git a/src/routes/blog/index.lisp b/src/routes/blog/index.lisp new file mode 100644 index 0000000..81dca37 --- /dev/null +++ b/src/routes/blog/index.lisp @@ -0,0 +1,38 @@ +(defpackage #:website/routes/blog/index + (:use #:cl + #:hsx + #:jingle) + (:import-from #:website/lib/cms + #:get-blog-list) + (:import-from #:website/lib/time + #:asctime) + (:export #:handle-get)) +(in-package #:website/routes/blog/index) + +(defparameter *metadata* + (list :title "blog")) + +(defun handle-get (params) + (declare (ignore params)) + (setf (context :metadata) *metadata*) + (let ((blogs (getf (get-blog-list :query '(:fields "id,title,publishedAt" + :limit 100)) + :contents))) + (hsx + (section + (h1 :class "font-bold text-4xl mb-8" + "Blog") + (ul :preload "mouseover" :class "flex flex-col gap-y-2" + (loop + :for item :in blogs :collect + (hsx + (li + (a + :class "hover:text-pink-500" + :href (format nil "/blog/~a" (getf item :id)) + (span :class "font-bold" + "・ " (getf item :title)) + (span :class "text-sm text-gray-400 ml-2" + "(" (asctime (getf item :published-at)) ")")))))) + ;TODO: pagenation + )))) diff --git a/src/routes/not-found.lisp b/src/routes/not-found.lisp index 163ff70..ef23176 100644 --- a/src/routes/not-found.lisp +++ b/src/routes/not-found.lisp @@ -13,6 +13,7 @@ :error t)) (defun handle-not-found () + (set-response-status :not-found) (setf (context :metadata) *metadata*) (if (api-request-p) '(:|message| "404 Not Found")