feat(grfn/bbbg): Display flash messages

Get flash working via a functioning cookie-store session middleware, and
display flash messages if present at the top of every page.

Change-Id: If5f267dee3f41ef7954ea82667822c596e1b0474
This commit is contained in:
Griffin Smith 2021-12-13 22:43:05 -05:00
parent e7899e6c0b
commit 0286d63df7
5 changed files with 98 additions and 18 deletions

View file

@ -8,7 +8,8 @@
[cheshire.core :as json]
[compojure.core :refer [GET POST routes]]
[honeysql.helpers :refer [merge-where]]
[ring.util.response :refer [content-type redirect response]]))
[ring.util.response :refer [content-type redirect response]]
[bbbg.views.flash :as flash]))
(defn attendees-routes [{:keys [db]}]
(routes
@ -38,5 +39,20 @@
(db.event/attended! db {::event/id event_id
::attendee/id attendee_id})
(-> (redirect (str "/signup-forms/" event_id))
(assoc :flash "Thank you for signing in! Enjoy the event.")))
(assoc-in [:session :test] 1)
(flash/add-flash
#:flash{:type :success
:message "Thank you for signing in! Enjoy the event."})))
(response "Something went wrong")))))
(comment
(def db (:db bbbg.core/system))
(db/list db
(->
(db.attendee/search "gr")
(db.attendee/for-event #uuid "9f4f3eae-3317-41a7-843c-81bcae52aebf")))
(honeysql.format/format
(->
(db.attendee/search "gr")
(db.attendee/for-event #uuid "9f4f3eae-3317-41a7-843c-81bcae52aebf")))
)

View file

@ -1,5 +1,6 @@
(ns bbbg.handlers.core
(:require
[bbbg.views.flash :as flash]
[hiccup.core :refer [html]]
[ring.util.response :refer [content-type response]]))
@ -7,7 +8,7 @@
(let [[{:keys [title]} body]
(if (map? opts)
[opts body]
[{} (into [opts] body)])]
[{} (concat [opts] body)])]
(html
[:html {:lang "en"}
[:head
@ -19,7 +20,9 @@
:type "text/css"
:href "/main.css"}]]
[:body
(into [:div.content] body)
[:div.content
(flash/render-flash)
body]
[:script {:src "https://cdnjs.cloudflare.com/ajax/libs/tarekraafat-autocomplete.js/10.2.6/autoComplete.js"}]
[:script {:src "/main.js"}]]])))

View file

@ -5,7 +5,8 @@
[bbbg.event :as event]
[bbbg.handlers.core :refer [page-response]]
[compojure.core :refer [context GET POST]]
[ring.util.response :refer [redirect]]))
[ring.util.response :refer [redirect]]
[bbbg.views.flash :as flash]))
(defn events-index [events]
[:ul.events-list
@ -41,4 +42,5 @@
(let [event (db.event/create! db {::event/date date})]
(-> (str "/signup-forms/" (::event/id event))
redirect
(assoc-in [:flash :message] "Event Created"))))))
(flash/add-flash {:flash/type :success
:flash/message "Event Created"}))))))

View file

@ -0,0 +1,33 @@
(ns bbbg.views.flash
(:require [clojure.spec.alpha :as s]))
(s/def :flash/type #{:success :error :warning})
(s/def :flash/message string?)
(s/def ::flash (s/keys :req [:flash/type :flash/message]))
(s/fdef add-flash :args (s/cat :resp map? :flash ::flash) :ret map?)
;;;
(def ^:dynamic *flash* nil)
(defn wrap-page-flash [handler]
(fn
([request]
(binding [*flash* (:flash request)]
(handler request)))
([request respond raise]
(binding [*flash* (:flash request)]
(handler request respond raise)))))
(defn add-flash [resp flash]
(update-in resp [:flash :flash/messages] conj flash))
(defn render-flash
([] (render-flash *flash*))
([flash]
(when-some [messages (not-empty (:flash/messages flash))]
[:ul.flash-messages
(for [message messages]
[:li.flash-message
{:class (str "flash-" (-> message :flash/type name))}
(:flash/message message)])])))

View file

@ -5,6 +5,8 @@
[bbbg.handlers.home :as home]
[bbbg.handlers.signup-form :as signup-form]
[bbbg.styles :refer [stylesheet]]
[bbbg.util.core :as u]
[bbbg.views.flash :refer [wrap-page-flash]]
[clojure.spec.alpha :as s]
[com.stuartsierra.component :as component]
[compojure.core :refer [GET routes]]
@ -13,23 +15,44 @@
[ring.middleware.flash :refer [wrap-flash]]
[ring.middleware.keyword-params :refer [wrap-keyword-params]]
[ring.middleware.params :refer [wrap-params]]
[ring.util.response :refer [content-type response resource-response]]))
[ring.middleware.session :refer [wrap-session]]
[ring.middleware.session.cookie :refer [cookie-store]]
[ring.util.response :refer [content-type resource-response response]])
(:import
java.util.Base64))
(s/def ::port pos-int?)
(s/def ::cookie-secret
(s/and bytes? #(= 16 (count %))))
(s/def ::config
(s/keys :req [::port]))
(s/keys :req [::port]
:opt [::cookie-secret]))
(s/fdef make-server
:args (s/cat :config ::config))
(defn- string->cookie-secret [raw]
(s/assert
::cookie-secret
(when raw
(.decode (Base64/getDecoder)
(.getBytes raw "UTF-8")))))
(defn env->config []
(s/assert
::config
{::port (:port env 8888)}))
(u/remove-nils
{::port (:port env 8888)
::cookie-secret (some-> env :cookie-secret string->cookie-secret)})))
(defn dev-config []
(s/assert ::config {::port 8888}))
(s/assert
::config
{::port 8888
::cookie-secret (into-array Byte/TYPE (repeat 16 0))}))
;;;
@ -47,17 +70,19 @@
(events/events-routes env)
(home/home-routes env)))
(defn middleware [app]
(defn middleware [app env]
(-> app
wrap-keyword-params
wrap-params
wrap-flash))
wrap-page-flash
wrap-flash
(wrap-session {:store (cookie-store {:key (:cookie-secret env)})})))
(defn handler [this]
(middleware
(app-routes this)))
(defn handler [env]
(-> (app-routes env)
(middleware env)))
(defrecord WebServer [port db]
(defrecord WebServer [port cookie-secret db]
component/Lifecycle
(start [this]
(assoc this
@ -71,7 +96,8 @@
(dissoc this ::shutdown-fn))
this)))
(defn make-server [{::keys [port]}]
(defn make-server [{::keys [port cookie-secret]}]
(component/using
(map->WebServer {:port port})
(map->WebServer {:port port
:cookie-secret cookie-secret})
[:db]))