diff --git a/src/view.lisp b/src/view.lisp index 6061f53..1b91d5d 100644 --- a/src/view.lisp +++ b/src/view.lisp @@ -46,6 +46,26 @@ :developmentp :productionp) (:import-from :caveman2 - :url-for)) + :url-for) + (:export #:title!) ; Added in Chapter 3 (Mockup section). + ) +;; in-package and let code added in Chapter 3, also. This is +;; preperation for Switching Layout Templates section. +(in-package + :rails-to-caveman.djula) ; Make sure this states your app name. +(let(title) + (defun title! (&optional sub) + (if sub + (format nil "~@[~A - ~]~:(~A~)" + (setf title sub) + ;; Make sure find-system states your app name. + #.(asdf:coerce-name(asdf:find-system :rails-to-caveman))) + title))) ; End of Chapter 3 additional code. (setf djula:*djula-execute-package* (find-package :rails-to-caveman.djula)) + +;;; This is a custom filter which is was added in Chapter 3 +;;; (Routing). Apparently, this is a filter which is part of the djula +;;; project's TODOs. This filter is used in 'step13.html' (in +;;; /templates directory). +(djula::def-filter :break(it) (cl-ppcre:regex-replace-all #\newline it "
")) diff --git a/src/web.lisp b/src/web.lisp index 306457b..30e2de7 100644 --- a/src/web.lisp +++ b/src/web.lisp @@ -1,11 +1,11 @@ (in-package :cl-user) (defpackage rails-to-caveman.web (:use :cl - :caveman2 + :caveman2 :rails-to-caveman.config - :rails-to-caveman.view + :rails-to-caveman.view :rails-to-caveman.db - :datafly + :datafly :sxql) (:export :*web*)) (in-package :rails-to-caveman.web) @@ -24,13 +24,22 @@ ;; Routing rules (defroute "/" () - (render #P"index.html")) + (render #P"index.html" + ;; Use to pass message to view -- it is expecting a + ;; `MESSAGE' item. You do not need to add it, though. Or, + ;; you can pass it an empty value/string if you do not want + ;; to leave the code commented out. + + ;; '(:message "This is not a message") ; Added Chapter 3. + '(:numbers (1 2 3 4 5)) + )) (defroute "/about" () + ;; about.html should be in the /templates directory. (render #P"about.html" '(:page-title "About"))) (defroute "/hello/:name" (&key name) - ;; Substitutes `:name' with `name'. + ;; Substitutes ':name' with `NAME'. (format nil "Hello, ~A" name)) (defroute "/say/*/to/*" (&key splat) @@ -42,7 +51,7 @@ (defroute ("/hello/([\\w]+)" :regexp t) (&key captures) ;; Parse the second part of the URL via a regular expression ;; (regexp). The result of the parsed regexp text is stored in - ;; `captures', hence the use of 'first' in the format string. + ;; `CAPTURES', hence the use of 'first' in the format string. (format nil "Hello, ~A!" (first captures))) (defroute "/hello/?:name?" (&key name) @@ -51,7 +60,7 @@ ;; 1. /hello/earth ;; 2. /hello?NAME=earth - ;; The query string must be in UPPERCASE. Otherwise, the `name' will + ;; The query string must be in UPPERCASE. Otherwise, the `NAME' will ;; be bound to `nil'. (format nil "Hello, ~A" name)) @@ -59,7 +68,7 @@ ;; If you want the query string in lowercase, enclose `name' (in ;; this case) with vertical bars '|'. This will force you to have ;; only one route (unlike the route above). `NAME' will now bind to - ;; `nil'. + ;; `NIL'. ;; 1. /hello?name=earth ;; 2. /hello?NAME=earth <--- no longer works ('earth' binds to nil). @@ -75,7 +84,7 @@ (defroute "/lesson/step*" (&key splat (|name| "Anonymous")) ;; 'Anonymous' is the default value for `|name|'. ;; Query style: Working with Parameters. - ;; Example URL: lesson/step1?name=Sato + ;; Example URL: /lesson/step1?name=Sato (case (parse-integer (car splat) :junk-allowed t) (1 (format nil "Hello, ~A" |name|)))) @@ -83,16 +92,91 @@ ;; If /lesson/step1 is used, it will be redirected to /lesson/step2, ;; then /lesson/step3 and finally /lesson/step4. No matter where you ;; start (along as it is below 4), the redirects will always take - ;; you wot /lesson/step4. + ;; you to /lesson/step4. - ;; The example includes `name' but it is never used. I am keeping it + ;; The example includes `NAME' BUT it is never used. I am keeping it ;; here for consistency between the reference material and this code ;; base. (case (parse-integer (car splat) :junk-allowed t) (1 '(302 (:location "/lesson/step2"))) (2 '(302 (:location "/lesson/step3"))) (3 '(302 (:location "/lesson/step4"))) - (4 "Moved to step4"))) + (4 "Moved to step4") + + ;; To be honest, I do not know what this is actually doing. It is + ;; mentioned in 'STEP5 Flash' in Chapter 3 (I.E. Tutorial 3: + ;; Routing). This applies to case's 5 and 6. + (5 (setf (gethash :notice *session*) "Move to step6") + `(302 (:location "/lesson/step6"))) + (6 (let((notice (gethash :notice *session*))) + (remhash :notice *session*) notice)) + + ;; This is part of an example about using djula (which is a + ;; template engine used by Caveman2. djula is a port of Python's + ;; Django template engine. + ;; step7.html should be in the /templates directory. + (7 (render "step7.html" + `(:price ,(floor(* 2000 1.08))))) + (8 (render "step7.html" '(:price 1000))) + (9 (render "step9.html" + '(:comment "Hello"))) + ;; If you dare to embed HTML, add safe after the variable + ;; reference on the View side (step10.html). + (10 (render "step10.html" + '(:comment "safe html"))) + (11 `(200 (:content-type "text/html; charset=utf-8") + (, (let ((population 704414) (surface 141.31)) + (render "step11.html" + `(:contents + ,(format nil + ;; ~D = Decimal + + ;; ~,,2F = Fixed-Format + ;; Floating-Point + + ;; ~,,2F = Print exactly two + ;; digits after the decimal + ;; point and many as necessary + ;; before the decimal point. + "Population: ~D Floor Surface: ~D Population/Surface: ~,,2F" + population + (floor surface) + (/ population surface)))))))) + (12 (render "step11.html" + `(:contents ,(local-time:format-timestring + nil + (local-time:now) + :format '((:year 4)"/"(:month 2)"/"(:day 2)"(" :short-weekday ") " + (:hour 2)":"(:min 2)":"(:sec 2)))))) + (13 `(200 (:content-type "text/html; charset=utf-8") + ;; This view uses 'format' in step13.html (view in + ;; /templates directory). + (,(render "step13.html" '(:population 127767944))))) + (14 (render "step14.html" + ;; The view uses a custom filter which was added to + ;; view.lisp. + `(:contents ,(format nil "foo~%bar~%bazz")))) + ;; The view demonstrates how to form links. + (15 (render "step15.html")) + ;; The view demonstrates how to display images. + ;; Images are stored in the /static/images directory. + (16 (render "step16.html")) + ;; Provides control branches which you can navigate via djula in + ;; step17.html (/templates directory). + (17 `(200 (:content-type "text/html; charset=utf-8") + ;; Adjust `STOCK' to adjust what is viewed in step17.html. + (,(let((stock 10)) + (render "step17.html" + `(:stock-zerop ,(< 0 stock) :stock ,stock)))))) + ;; This creates a list (cons list) which is then cycled through in + ;; /templates/step18.html using the djula template engine.. + (18 (render "step18.html" + '(:items + ((:pan . 2680) + (:glass . 2550) + (:pepper-mill . 4515) + (:peeler . 945))))) + )) ;; ;; Error pages diff --git a/static/css/main.css b/static/css/main.css index 2e05864..a0d04e0 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -1,21 +1,45 @@ -@charset "UTF-8"; - +/* whole pages */ body { - font-family: 'Myriad Pro', Calibri, Helvetica, Arial, sans-serif; + background-color: white; + color: black; + margin: 0; padding: 0; + font-family: Meiryo, sans-serif; } -a:link { - color: #005585; - text-decoration: none; -} -a:visited { - color: #485270; +/* link */ +a:link { color: #00c; } +a:visited { color: #00c; } +a:hover { color: #f00; } +a img { border: none; } + +/* whole border */ +div#container { + margin: 0 auto; + padding-top: 5px; + width: 780px; } -a:hover { - color: #b83800; - text-decoration: underline; + +/* left pane */ +main { + float: left; + width: 530px; + padding: 10px, 10px, 10px, 0; } -#main { - text-align: center; +/* right pane */ +aside#sidebar { + float: left; + width: 230px; + background-color: #e8ffff; + padding: 5px; + font-size: 86%; } + +/* link of menubar */ +nav.menubar a { text-decoration: none; } + +/* link of menubar (not visited) */ +nav.menubar a:link { color: #ccc; } + +/* link of menubar (visited) */ +nav.menubar a:visited { color: #ccc; } diff --git a/static/images/lisplogo.svg b/static/images/lisplogo.svg new file mode 100644 index 0000000..75c4f9b --- /dev/null +++ b/static/images/lisplogo.svg @@ -0,0 +1,406 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + Made with secret + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + alien technology + + CAUTION: + + diff --git a/templates/index.html b/templates/index.html index 6a3c687..3fa348d 100644 --- a/templates/index.html +++ b/templates/index.html @@ -1,7 +1,24 @@ -{% extends "layouts/default.html" %} -{% block title %}Welcome to Caveman2{% endblock %} +{% extends "layouts/app.html" %} + +{% comment "Set title using title function." %} + +{%block title %}{% lisp (title! "Bitchin!") %}{% endblock %} +{% endcomment %} + + +{% block title %}Rails to Caveman2 Demo.{% endblock %} + {% block content %} -
- Welcome to Caveman2! -
+ +

{{ message }}

+

Here we go!

{% endblock %} diff --git a/templates/layouts/app.html b/templates/layouts/app.html new file mode 100644 index 0000000..5bf206b --- /dev/null +++ b/templates/layouts/app.html @@ -0,0 +1,25 @@ + + + + + {% block title %}{% endblock %} + + + +
+
+ {% include "shared/header.html" %} +
+
+ {% block content %}{% endblock %} +
+ + + + diff --git a/templates/layouts/demo.html b/templates/layouts/demo.html new file mode 100644 index 0000000..679ff01 --- /dev/null +++ b/templates/layouts/demo.html @@ -0,0 +1,13 @@ + + + + + + + {% block title %}Your app{% endblock %} + + + + {% block content %}{% endblock %} + + diff --git a/templates/shared/footer.html b/templates/shared/footer.html new file mode 100644 index 0000000..6fb4cda --- /dev/null +++ b/templates/shared/footer.html @@ -0,0 +1 @@ +About this website| Copyright(C) 2021 craigoates.net diff --git a/templates/shared/header.html b/templates/shared/header.html new file mode 100644 index 0000000..7b58218 --- /dev/null +++ b/templates/shared/header.html @@ -0,0 +1,11 @@ +Your app + + diff --git a/templates/shared/login_form.html b/templates/shared/login_form.html new file mode 100644 index 0000000..48eb279 --- /dev/null +++ b/templates/shared/login_form.html @@ -0,0 +1,14 @@ +

Login

+
+
+ + +
+
+ + +
+
+ +
+
diff --git a/templates/shared/sidebar.html b/templates/shared/sidebar.html new file mode 100644 index 0000000..f47da9f --- /dev/null +++ b/templates/shared/sidebar.html @@ -0,0 +1,14 @@ +{% include "shared/login_form.html" %} +

Latest News

+ + +

Member Blog

+ diff --git a/templates/step10.html b/templates/step10.html new file mode 100644 index 0000000..1e989d1 --- /dev/null +++ b/templates/step10.html @@ -0,0 +1,3 @@ + +

{{comment | safe}}

diff --git a/templates/step11.html b/templates/step11.html new file mode 100644 index 0000000..d74c626 --- /dev/null +++ b/templates/step11.html @@ -0,0 +1 @@ +

{{contents}}

diff --git a/templates/step13.html b/templates/step13.html new file mode 100644 index 0000000..a2f34a6 --- /dev/null +++ b/templates/step13.html @@ -0,0 +1,7 @@ + +

Step 13 | Population: {{population | format: "~D"}}

diff --git a/templates/step14.html b/templates/step14.html new file mode 100644 index 0000000..50ff8d3 --- /dev/null +++ b/templates/step14.html @@ -0,0 +1,3 @@ + +

{{contents|break|safe}}

diff --git a/templates/step15.html b/templates/step15.html new file mode 100644 index 0000000..19750a7 --- /dev/null +++ b/templates/step15.html @@ -0,0 +1,2 @@ + +Home diff --git a/templates/step16.html b/templates/step16.html new file mode 100644 index 0000000..3efcbf8 --- /dev/null +++ b/templates/step16.html @@ -0,0 +1,8 @@ +

Powered by + + lisplogo +

diff --git a/templates/step17.html b/templates/step17.html new file mode 100644 index 0000000..61bcc3f --- /dev/null +++ b/templates/step17.html @@ -0,0 +1,14 @@ + + +{% if stock-zerop %} +Stock: {{stock}} +{% else %} +This is no stock. +{% endif %} diff --git a/templates/step18.html b/templates/step18.html new file mode 100644 index 0000000..ab4b1b3 --- /dev/null +++ b/templates/step18.html @@ -0,0 +1,30 @@ + + +

+ + {% for (key . val) in items %} + + + + + {% endfor %} +
{{ key }}{{ val | format: ~:D }} Currency Points
+

+ diff --git a/templates/step7.html b/templates/step7.html new file mode 100644 index 0000000..0816bdd --- /dev/null +++ b/templates/step7.html @@ -0,0 +1 @@ +

{{price}}

diff --git a/templates/step9.html b/templates/step9.html new file mode 100644 index 0000000..52ad2e2 --- /dev/null +++ b/templates/step9.html @@ -0,0 +1 @@ +

{{comment}}