|
@@ -0,0 +1,111 @@
|
|
|
|
|
+(in-package :cl-user)
|
|
|
|
|
+
|
|
|
|
|
+(restas:define-module #:assboard.web
|
|
|
|
|
+ (:use :cl :hunchentoot :assboard.utils))
|
|
|
|
|
+
|
|
|
|
|
+(in-package #:assboard.web)
|
|
|
|
|
+
|
|
|
|
|
+;; Parameters
|
|
|
|
|
+(setf (who:html-mode) :html5)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+(defclass renderer () ())
|
|
|
|
|
+(restas::register-pkgmodule-traits
|
|
|
|
|
+ 'assboard.web
|
|
|
|
|
+ :render-method (lambda () (make-instance 'assboard.web::renderer)))
|
|
|
|
|
+
|
|
|
|
|
+;; Rendering
|
|
|
|
|
+(defgeneric finalize-page (data)
|
|
|
|
|
+ (:documentation "Final rendering step"))
|
|
|
|
|
+(defgeneric render-route-data (route data)
|
|
|
|
|
+ (:documentation "Process route-specific data"))
|
|
|
|
|
+
|
|
|
|
|
+(defmethod finalize-page ((data list))
|
|
|
|
|
+ (who:with-html-output-to-string (out nil :prologue t)
|
|
|
|
|
+ (:html
|
|
|
|
|
+ (:head
|
|
|
|
|
+ (:meta :charset "utf-8")
|
|
|
|
|
+ (:meta :http-equiv "X-UA-Compatible" :content "IE=edge")
|
|
|
|
|
+ (:meta :name "viewport" :content "width=device-width, initial-scale=1")
|
|
|
|
|
+ (:title (who:str (getf data :title)))
|
|
|
|
|
+ (:link :rel "stylesheet" :href (restas:genurl 'static/css :file "styles.css")))
|
|
|
|
|
+ (:body
|
|
|
|
|
+ (who:str (getf data :menu))
|
|
|
|
|
+ (who:str (getf data :content))))))
|
|
|
|
|
+
|
|
|
|
|
+(defmethod render-route-data (route data)
|
|
|
|
|
+ (list*
|
|
|
|
|
+ :title (getf data :title "AssBoard")
|
|
|
|
|
+ data))
|
|
|
|
|
+
|
|
|
|
|
+(defmethod restas:render-object ((designer renderer) (object list))
|
|
|
|
|
+ (let ((full-data (render-route-data (restas:route-symbol restas:*route*)
|
|
|
|
|
+ object)))
|
|
|
|
|
+ (finalize-page full-data)))
|
|
|
|
|
+
|
|
|
|
|
+(defun posts-list (posts)
|
|
|
|
|
+ (who:with-html-output-to-string (out)
|
|
|
|
|
+ (:ul
|
|
|
|
|
+ (loop for post in posts
|
|
|
|
|
+ :do (who:htm
|
|
|
|
|
+ (:li
|
|
|
|
|
+ (:a :href (restas:genurl 'posting :id (data::posting-id post))
|
|
|
|
|
+ (who:str (data::posting-title post)))
|
|
|
|
|
+ " by "
|
|
|
|
|
+ (:a :href (restas:genurl 'author
|
|
|
|
|
+ :author (data::posting-author post))
|
|
|
|
|
+ (who:str (data::posting-author post)))))))))
|
|
|
|
|
+
|
|
|
|
|
+(defmethod render-route-data ((route (eql 'index)) (posts list))
|
|
|
|
|
+ (list
|
|
|
|
|
+ :title "AssBoard"
|
|
|
|
|
+ :content
|
|
|
|
|
+ (who:with-html-output-to-string (out)
|
|
|
|
|
+ (:h1 "AssBoard open postings")
|
|
|
|
|
+ (who:str (posts-list posts)))))
|
|
|
|
|
+
|
|
|
|
|
+(restas:define-route index ("")
|
|
|
|
|
+ (pomo:query-dao
|
|
|
|
|
+ 'data::posting
|
|
|
|
|
+ (:select 'id 'author 'status 'title 'maintainer 'created-on
|
|
|
|
|
+ :from 'posting)))
|
|
|
|
|
+
|
|
|
|
|
+(defmethod restas:render-object ((designer renderer) (object data::posting))
|
|
|
|
|
+ (finalize-page
|
|
|
|
|
+ (list
|
|
|
|
|
+ :title (format nil "~A by ~A @ AssBoard"
|
|
|
|
|
+ (data::posting-title object)
|
|
|
|
|
+ (data::posting-author object))
|
|
|
|
|
+ :content
|
|
|
|
|
+ (who:with-html-output-to-string (out)
|
|
|
|
|
+ (:h1 (who:str (data::posting-title object)))
|
|
|
|
|
+ (:p (who:str (data::posting-body object)))))))
|
|
|
|
|
+
|
|
|
|
|
+(restas:define-route posting ("posting/:id/")
|
|
|
|
|
+ (let ((post (pomo:get-dao 'data::posting id)))
|
|
|
|
|
+ (if post post
|
|
|
|
|
+ hunchentoot:+HTTP-NOT-FOUND+)))
|
|
|
|
|
+
|
|
|
|
|
+(defmethod render-route-data ((route (eql 'author)) (data list))
|
|
|
|
|
+ (list
|
|
|
|
|
+ :title (format nil "~A's postings @ AssBoard" (getf data :author))
|
|
|
|
|
+ :content
|
|
|
|
|
+ (who:with-html-output-to-string (out)
|
|
|
|
|
+ (:h1 (who:str (getf data :author)) "'s postings")
|
|
|
|
|
+ (who:str (posts-list (getf data :posts))))))
|
|
|
|
|
+
|
|
|
|
|
+(restas:define-route author ("author/:author/")
|
|
|
|
|
+ (let ((posts (pomo:query-dao
|
|
|
|
|
+ 'data::posting
|
|
|
|
|
+ (:select 'id 'author 'status 'title 'maintainer 'created-on
|
|
|
|
|
+ :from 'posting
|
|
|
|
|
+ :where (:= 'author author)))))
|
|
|
|
|
+ (if posts
|
|
|
|
|
+ (list :author author :posts posts)
|
|
|
|
|
+ hunchentoot:+HTTP-NOT-FOUND+)))
|
|
|
|
|
+
|
|
|
|
|
+(restas:define-route static/css ("css/:file" :content-type "text/css")
|
|
|
|
|
+ (let ((css-path (merge-pathnames "css/" +project-path+)))
|
|
|
|
|
+ (merge-pathnames file css-path)))
|
|
|
|
|
+
|
|
|
|
|
+
|