diff options
author | Griffin Smith <grfn@gws.fyi> | 2020-07-22T22·16-0400 |
---|---|---|
committer | glittershark <grfn@gws.fyi> | 2020-07-23T22·20+0000 |
commit | d445136140cbd89599940c489efecefa544d1bd6 (patch) | |
tree | 89c7e4c062173857f3a7d2bb9c915f8f6c66fb87 /web/panettone/src/panettone.lisp | |
parent | d3b7de0783230b78edd44010e144f47e0ee4bea5 (diff) |
feat(web/panettone): Add initial styles r/1442
Take an initial crack at styling most of the Panettone application, taking inspiration from the styles from todo.tvl.fyi and tvl.fyi itself. This uses the LASS CSS library, after a brief attempt at using css-lite which I ended up not going with because I don't like the library's design very much, and also it's not compatible with sbcl's (safety 3) (some macroexpansions SETQ undeclared variables). Change-Id: I054402e4c68ae1e99884d5164e6e2fc39d2779ff Reviewed-on: https://cl.tvl.fyi/c/depot/+/1350 Tested-by: BuildkiteCI Reviewed-by: eta <eta@theta.eu.org>
Diffstat (limited to 'web/panettone/src/panettone.lisp')
-rw-r--r-- | web/panettone/src/panettone.lisp | 158 |
1 files changed, 96 insertions, 62 deletions
diff --git a/web/panettone/src/panettone.lisp b/web/panettone/src/panettone.lisp index b8199034e14b..288f278f12da 100644 --- a/web/panettone/src/panettone.lisp +++ b/web/panettone/src/panettone.lisp @@ -1,11 +1,4 @@ -(defpackage panettone - (:use :cl :klatre :easy-routes) - (:import-from :defclass-std :defclass/std) - (:import-from :alexandria :if-let) - (:shadowing-import-from :alexandria :when-let) - (:export :start-panettone :main)) (in-package :panettone) - (declaim (optimize (safety 3))) ;;; @@ -170,67 +163,100 @@ updated issue" (defmacro render (&body body) `(who:with-html-output-to-string (*standard-output* nil :prologue t) (:head - (:title (who:esc *title*))) - (:body ,@body))) + (:title (who:esc *title*)) + (:link :rel "stylesheet" :type "text/css" :href "/main.css")) + (:body + (:div :class "content" + ,@body)))) (defun render/login (&optional message) (render - (:h1 "Login") - (when message - (who:htm (:div.alert (who:esc message)))) - (:form - :method :post :action "/login" - (:div - (:label :for "username" - "Username") - (:input :type "text" - :name "username" - :id "username" - :placeholder "username")) - (:div - (:label :for "password" - "Password") - (:input :type "password" - :name "password" - :id "password" - :placeholder "password")) - (:input :type "submit" - :value "Submit")))) + (:div + :class "login-form" + (:header + (:h1 "Login")) + (:main + :class "login-form" + (when message + (who:htm (:div :class "alert" (who:esc message)))) + (:form + :method :post :action "/login" + (:div + (:label :for "username" + "Username") + (:input :type "text" + :name "username" + :id "username" + :placeholder "username")) + (:div + (:label :for "password" + "Password") + (:input :type "password" + :name "password" + :id "password" + :placeholder "password")) + (:input :type "submit" + :value "Submit")))))) + +(defun created-by-at (issue) + (who:with-html-output (*standard-output*) + (:span :class "created-by-at" + "Opened by " + (:span :class "username" + (who:esc + (or + (when-let ((author (author issue))) + (displayname author)) + "someone"))) + " at " + (:span :class "timestamp" + (who:esc + (format-dottime (created-at issue))))))) (defun render/index (&key issues) (render - (:h1 "Issues") - (:a :href "/issues/new" "New Issue") - (:ul - (loop for issue in issues - do (who:htm - (:li - (:a :href (format nil "/issues/~A" (cl-prevalence:get-id issue)) - (who:esc (subject issue))))))))) + (:header + (:h1 "Issues") + (:a + :class "new-issue" + :href "/issues/new" "New Issue")) + (:main + (:ol + :class "issue-list" + (dolist (issue issues) + (let ((issue-id (get-id issue))) + (who:htm + (:li + (:a :href (format nil "/issues/~A" issue-id) + (:p + (:span :class "issue-subject" + (who:esc (subject issue)))) + (:span :class "issue-number" + (who:esc (format nil "#~A" issue-id))) + " - " + (created-by-at issue)))))))))) (defun render/new-issue () (render - (:h1 "New Issue") - (:form - :method :post :action "/issues" - (:div - (:label :for "subject" "Subject") - (:input :type :text - :id "subject" - :name "subject" - :placeholder "Subject")) - - (:div - (:textarea :name "body")) - - (:input :type :submit - :value "Create Issue")))) - -(defun created-by-at (issue) - (format nil "Opened by ~A at ~A" - (when-let ((author (author issue))) - (displayname author)) - (format-dottime (created-at issue)))) + (:header + (:h1 "New Issue")) + (:main + (:form :method "post" + :action "/issues" + :class "issue-form" + (:div + (:input :type "text" + :id "subject" + :name "subject" + :placeholder "Subject")) + + (:div + (:textarea :name "body" + :placeholder "Description" + :rows 10)) + + (:input :type "submit" + :value "Create Issue"))))) (comment (format nil "foo: ~A" "foo") @@ -239,9 +265,13 @@ updated issue" (defun render/issue (issue) (check-type issue issue) (render - (:h1 (who:esc (subject issue))) - (:p (who:esc (created-by-at issue))) - (:p (who:esc (body issue))))) + (:header + (:h1 (who:esc (subject issue))) + (:div :class "issue-number" + (who:esc (format nil "#~A" (get-id issue))))) + (:main + (:p (created-by-at issue)) + (:p (who:esc (body issue)))))) (defun render/not-found (entity-type) (render @@ -296,6 +326,10 @@ updated issue" (issue-not-found (_) (render/not-found "Issue")))) +(defroute styles ("/main.css") () + (setf (hunchentoot:content-type*) "text/css") + (apply #'lass:compile-and-write panettone.css:styles)) + (defvar *acceptor* nil "Hunchentoot acceptor for Panettone's web server.") |