diff of 2359b53912b3eb167072e1f83da49c0869d32515
2359b53912b3eb167072e1f83da49c0869d32515
diff --git a/aggressive-murja.asd b/aggressive-murja.asd
index e8245db..58bc4f5 100644
--- a/aggressive-murja.asd
+++ b/aggressive-murja.asd
@@ -41,7 +41,8 @@
(:file "migrations")
(:file "json")))
(:module "murja-newui"
- :components ((:file "newui")))
+ :components ((:file "newui")
+ (:file "simpledate")))
(:file "migration-list")
(:file "settings")
@@ -76,11 +77,18 @@
(:file "user-editor")
(:file "root-routes")))
+ (:module "models"
+ :components
+ ((:file "user")
+ (:file "post")))
+
(:module "views"
:components
((:module "components"
:components ((:file "tab")
- (:file "root")))
+ (:file "root")
+ (:file "post")
+ (:file "page")))
(:file "blog-main")))
(:file "main"))))
diff --git a/src/models/post.lisp b/src/models/post.lisp
new file mode 100644
index 0000000..c83a7b6
--- /dev/null
+++ b/src/models/post.lisp
@@ -0,0 +1,77 @@
+(defpackage murja.models.post
+ (:use :cl)
+ (:export :get-page :get-post :post-id :post-title :article :creator :tags :created-at :post-hidden? :post-unlisted?)
+ (:import-from :com.inuoe.jzon :parse))
+
+(in-package :murja.models.post)
+
+;; fuck it we're moving from hashmaps to clos now
+(defclass Post ()
+ ;; slots are copied from the table blog.Post, accessors are what I might call these were I designing the db nowadays
+ ((id :initarg :id :accessor post-id :col-type integer)
+ (title :initarg :title :accessor post-title :col-type string)
+ (content :initarg :content :accessor article :col-type string)
+ (creator :initarg :creator :initform nil :accessor creator)
+ (creator-id :col-type string :reader creator-id)
+ (tags :initarg :tags :accessor tags :col-type string)
+ (created-at :initarg :created-at :accessor created-at :col-type simple-date:timestamp)
+ (hidden :initarg :hidden? :accessor post-hidden? :col-type boolean)
+ (unlisted :initarg :unlisted? :accessor post-unlisted? :col-type boolean))
+ (:metaclass postmodern:dao-class)
+ (:keys id)
+ (:table-name "blog.Post"))
+
+(defmethod print-object ((p Post) output)
+ (with-slots (creator id title content creator-id tags created-at hidden unlisted) p
+
+ (format output "#<POST: ~{~{~a: ~s~}~^,~%~t ~}>" (list
+ (list :id id)
+ (list :title title)
+ (list :content
+ (if (> (length content) 50)
+ (format nil "~a..."
+ (str:substring 0 50 content))
+ content))
+ (list :creator-id creator-id)
+ (list :creator creator)
+ (list :tags tags)
+ (list :created-at created-at)
+ (list :hidden hidden)
+ (list :unlisted unlisted)))))
+
+;; (postmodern:query "SELECT * FROM blog.Post limit 1" (:dao post :single))
+;; (postmodern:get-dao 'Post 349)
+;; #<POST: ID: 349, TITLE: "Lisp webapps ", CONTENT: "<p>So, after <a href=\"https://feuerx.net/blog/post...", CREATOR-ID: 1, TAGS: "[\"postgresql\", \"hunchentoot\", \"lisp\", \"programming\"]", CREATED-AT: #<SIMPLE-DATE:TIMESTAMP 22-02-2025T09:31:40,016>, HIDDEN: NIL, UNLISTED: NIL>
+
+(defun fix-post (p)
+ (setf (tags p) (parse (tags p)))
+ (setf (creator p) (postmodern:get-dao 'murja.models.user:user (creator-id p)))
+ p)
+
+(defun get-post (id)
+ (let ((p (postmodern:get-dao 'Post id)))
+ (fix-post p)
+ p))
+
+(defun get-page (page page-size &key allow-hidden? modified-since)
+ (let* ((page (if (< page 1)
+ 1
+ page)))
+ (map 'list
+ #'fix-post
+ (postmodern:query
+ "SELECT p.*
+FROM blog.Post p
+WHERE ((NOT p.unlisted) OR $3)
+ AND ((NOT p.hidden) OR $3)
+ AND (($4::timestamp IS NULL) OR p.created_at > $4::timestamp)
+ORDER BY p.created_at DESC
+LIMIT $2
+OFFSET $1"
+ (* (1- page) page-size)
+ page-size
+ allow-hidden?
+ (if modified-since
+ modified-since
+ :null)
+ (:dao Post)))))
diff --git a/src/models/user.lisp b/src/models/user.lisp
new file mode 100644
index 0000000..3158fec
--- /dev/null
+++ b/src/models/user.lisp
@@ -0,0 +1,28 @@
+(defpackage murja.models.user
+ (:use :cl)
+ (:export :User :user-id :user-username :user-password :user-nickname :user-img-location))
+
+(in-package :murja.models.user)
+
+(defclass User ()
+ ((id :initarg :id :accessor user-id :col-type integer)
+ (username :initarg :username :accessor user-username :col-type string)
+ (password :initarg :password :accessor user-password :col-type string)
+ (nickname :initarg :nickname :accessor user-nickname :col-type string)
+ (img-location :initarg :img-location :accessor user-img-location :col-type string))
+
+ (:metaclass postmodern:dao-class)
+ (:keys id)
+ (:table-name "blog.Users"))
+
+(defmethod print-object ((usr User) output)
+ (with-slots (id username nickname img-location) usr
+
+ (format output "#<USER: ~{~{~a: ~s~}~^,~%~t ~}>" (list
+ (list :id id)
+ (list :username username)
+ (list :nickname nickname)
+ (list :password "******")
+ (list :img-location img-location)))))
+
+;; (postmodern:get-dao 'User 1)
diff --git a/src/murja-newui/newui.lisp b/src/murja-newui/newui.lisp
index 187fe51..9280cb7 100644
--- a/src/murja-newui/newui.lisp
+++ b/src/murja-newui/newui.lisp
@@ -103,7 +103,7 @@
(defmethod render ((s t))
(prin1-to-string s))
-(defparameter *single-element-tags* (list :link :meta :input)
+(defparameter *single-element-tags* (list :link :meta :input :img)
"Contains tags that don't expand to <:tag attrs>children</:tag> but instead into <:tag attrs />")
(defmethod render ((c component))
diff --git a/src/murja-newui/simpledate.lisp b/src/murja-newui/simpledate.lisp
new file mode 100644
index 0000000..3a3a8e2
--- /dev/null
+++ b/src/murja-newui/simpledate.lisp
@@ -0,0 +1,11 @@
+(defpackage murja.newui.simpledate
+ (:documentation "Provides render method for postmodern's simpledate classes. Do not load if you do not use :D")
+ (:use :cl)
+ (:import-from :murja.newui :render))
+
+(in-package :murja.newui.simpledate)
+
+(defmethod render ((ts simple-date:timestamp))
+ (multiple-value-bind (year month day hour minute second millisec)
+ (simple-date:decode-timestamp ts)
+ (format nil "~2,'0d.~2,'0d.~d ~2,'0d:~2,'0d" day month year hour minute)))
diff --git a/src/views/blog-main.lisp b/src/views/blog-main.lisp
index cb8cd57..a15a0e6 100644
--- a/src/views/blog-main.lisp
+++ b/src/views/blog-main.lisp
@@ -4,7 +4,6 @@
(:import-from :murja.routes.root-routes :@check-if-initial)
(:import-from :murja.routes.settings-routes :get-settings)
(:import-from :murja.middleware.db :@transaction)
- (:import-from :murja.posts.post-db :get-titles-by-year :get-page )
(:import-from :murja.newui :@newui :c :with-state)
(:import-from :easy-routes :defroute))
@@ -16,9 +15,8 @@
(let* ((settings (get-settings))
(page-size (gethash "recent-post-count" settings))
(page 1)
- (page-posts (get-page page page-size)))
+ (page-posts (murja.models.post:get-page page page-size)))
(root-component
(tabs "Home"
(hash
- ("Home" (c :p () "lol")))))))
-
+ ("Home" (murja.views.components.page:page page-posts)))))))
diff --git a/src/views/components/page.lisp b/src/views/components/page.lisp
new file mode 100644
index 0000000..7b87de5
--- /dev/null
+++ b/src/views/components/page.lisp
@@ -0,0 +1,11 @@
+(defpackage murja.views.components.page
+ (:use :cl :murja.newui :cl-hash-util :binding-arrows )
+ (:export :page))
+
+(in-package :murja.views.components.page)
+
+(defun page (list-of-posts)
+ (component :div (:class "page")
+ (map 'list (lambda (post)
+ (murja.views.components.post:post post))
+ list-of-posts)))
diff --git a/src/views/components/post.lisp b/src/views/components/post.lisp
new file mode 100644
index 0000000..4f8d274
--- /dev/null
+++ b/src/views/components/post.lisp
@@ -0,0 +1,21 @@
+(defpackage murja.views.components.post
+ (:use :cl :murja.newui :cl-hash-util :binding-arrows :murja.models.user :murja.models.post)
+ (:export :post))
+
+(in-package :murja.views.components.post)
+
+(defun post (post)
+ (let ((creator (creator post)))
+ (c :article (:class "post")
+ (c :h2 ()
+ (c :a (:href (format nil "/blog/post/~d" (post-id post)))
+ (post-title post)))
+ (c :section (:class "meta")
+ (c :img (:class "user_avatar" :src (user-img-location creator)))
+ (c :p () (format nil "By ~a" (user-nickname creator)))
+ (c :p () "Written at"
+ (c :time (:datetime (created-at post))
+ (created-at post))))
+
+ (c :section (:class "content") (article post)))))
+