feat(grfn/bbbg): Style event list
Change-Id: I917e11e453126246c4110a6e42452dda4713b441 Reviewed-on: https://cl.tvl.fyi/c/depot/+/4667 Reviewed-by: grfn <grfn@gws.fyi> Autosubmit: grfn <grfn@gws.fyi> Tested-by: BuildkiteCI
This commit is contained in:
parent
a68fe5b636
commit
b175121101
5 changed files with 124 additions and 44 deletions
|
@ -1,6 +1,6 @@
|
|||
(ns bbbg.db
|
||||
(:gen-class)
|
||||
(:refer-clojure :exclude [get list])
|
||||
(:refer-clojure :exclude [get list count])
|
||||
(:require [camel-snake-kebab.core :as csk :refer [->kebab-case ->snake_case]]
|
||||
[bbbg.util.core :as u]
|
||||
[clojure.set :as set]
|
||||
|
@ -293,13 +293,18 @@
|
|||
sql-map-or-table)
|
||||
(merge jdbc-opts opts)))))
|
||||
|
||||
(defn count
|
||||
[db sql-map]
|
||||
(binding [*meta-db* db]
|
||||
(:count
|
||||
(fetch db {:select [[:%count.* :count]], :from [[sql-map :sq]]}))))
|
||||
|
||||
(defn exists?
|
||||
"Returns true if the given sql query-map would return any results"
|
||||
[db sql-map]
|
||||
(binding [*meta-db* db]
|
||||
(pos?
|
||||
(:count
|
||||
(fetch db {:select [[:%count.* :count]], :from [[sql-map :sq]]})))))
|
||||
(count db sql-map))))
|
||||
|
||||
(defn execute!
|
||||
"Given a database and a honeysql query map, perform an operation on the
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
[bbbg.db :as db]
|
||||
[bbbg.event :as event]
|
||||
[bbbg.util.sql :refer [count-where]]
|
||||
[honeysql.helpers :refer [merge-group-by merge-left-join merge-select]]
|
||||
[honeysql.helpers
|
||||
:refer [merge-group-by merge-left-join merge-select merge-where]]
|
||||
[java-time :refer [local-date]]))
|
||||
|
||||
(defn create! [db event]
|
||||
|
@ -32,6 +33,16 @@
|
|||
([] (on-day (local-date)))
|
||||
([db] (db/list db (today))))
|
||||
|
||||
(defn upcoming
|
||||
([] (upcoming {:select [:event.*] :from [:event]}))
|
||||
([query]
|
||||
(merge-where query [:>= :date (local-date)])))
|
||||
|
||||
(defn past
|
||||
([] (past {:select [:event.*] :from [:event]}))
|
||||
([query]
|
||||
(merge-where query [:< :date (local-date)])))
|
||||
|
||||
(defn with-attendee-counts
|
||||
[query]
|
||||
(-> query
|
||||
|
|
|
@ -3,26 +3,64 @@
|
|||
[bbbg.db :as db]
|
||||
[bbbg.db.event :as db.event]
|
||||
[bbbg.event :as event]
|
||||
[bbbg.handlers.core :refer [authenticated? page-response]]
|
||||
[bbbg.handlers.core :refer [*authenticated?* page-response]]
|
||||
[bbbg.meetup.import :refer [import-attendees!]]
|
||||
[bbbg.util.display :refer [format-date]]
|
||||
[bbbg.util.display :refer [format-date pluralize]]
|
||||
[bbbg.util.time :as t]
|
||||
[bbbg.views.flash :as flash]
|
||||
[compojure.coercions :refer [as-uuid]]
|
||||
[compojure.core :refer [context GET POST]]
|
||||
[java-time :refer [local-date]]
|
||||
[ring.util.response :refer [not-found redirect]]))
|
||||
[ring.util.response :refer [not-found redirect]])
|
||||
(:import
|
||||
java.time.format.FormatStyle))
|
||||
|
||||
(defn events-index [{:keys [events authenticated?]}]
|
||||
[:div
|
||||
(when authenticated?
|
||||
[:a {:href "/events/new"}
|
||||
(defn- num-attendees [event]
|
||||
(str
|
||||
(:num-attendees event)
|
||||
(if (= (t/->LocalDate (::event/date event))
|
||||
(local-date))
|
||||
" Signed In"
|
||||
(str " Attendee" (when-not (= 1 (:num-attendees event)) "s")))))
|
||||
|
||||
(def index-type->label
|
||||
{:upcoming "Upcoming"
|
||||
:past "Past"})
|
||||
(def other-index-type
|
||||
{:upcoming :past
|
||||
:past :upcoming})
|
||||
|
||||
(defn events-index
|
||||
[{:keys [events num-events type]}]
|
||||
[:div.page
|
||||
[:div.page-header
|
||||
[:h1
|
||||
(pluralize
|
||||
num-events
|
||||
(str (index-type->label type) " Event"))]
|
||||
[:a {:href (str "/events"
|
||||
(when (= :upcoming type)
|
||||
"/past"))}
|
||||
"View "
|
||||
(index-type->label (other-index-type type))
|
||||
" Events"]]
|
||||
(when *authenticated?*
|
||||
[:a.button {:href "/events/new"}
|
||||
"Create New Event"])
|
||||
[:ul.events-list
|
||||
(for [event events]
|
||||
(for [event (sort-by
|
||||
::event/date
|
||||
(comp - compare)
|
||||
events)]
|
||||
[:li
|
||||
[:p
|
||||
[:a {:href (str "/events/" (::event/id event))}
|
||||
(format-date (::event/date event))]])]])
|
||||
(format-date (::event/date event)
|
||||
FormatStyle/FULL)]]
|
||||
[:p
|
||||
(pluralize (:num-rsvps event) "RSVP")
|
||||
", "
|
||||
(num-attendees event)]])]])
|
||||
|
||||
(defn- import-attendee-list-form-group []
|
||||
[:div.form-group
|
||||
|
@ -41,19 +79,15 @@
|
|||
:value "Import"}]]])
|
||||
|
||||
(defn event-page [{:keys [event]}]
|
||||
[:div.event-page
|
||||
[:h1 (format-date (::event/date event))]
|
||||
[:div.stats
|
||||
[:p (:num-rsvps event) " RSVP"
|
||||
(when-not (= 1 (:num-rsvps event)) "s")]
|
||||
[:p (:num-attendees event)
|
||||
(if (= (t/->LocalDate (::event/date event))
|
||||
(local-date))
|
||||
" Signed In"
|
||||
(str " Attendee" (when-not (= 1 (:num-attendees event)) "s")))]]
|
||||
[:div
|
||||
[:div.page
|
||||
[:div.page-header
|
||||
[:h1 (format-date (::event/date event)
|
||||
FormatStyle/FULL)]
|
||||
[:a {:href (str "/signup-forms/" (::event/id event) )}
|
||||
"Go to Signup Form"]]
|
||||
[:div.stats
|
||||
[:p (pluralize (:num-rsvps event) "RSVP")]
|
||||
[:p (num-attendees event)]]
|
||||
[:div
|
||||
(import-attendees-form event)]])
|
||||
|
||||
|
@ -65,6 +99,7 @@
|
|||
(defn event-form
|
||||
([] (event-form {}))
|
||||
([event]
|
||||
[:div.page
|
||||
[:form {:method "POST"
|
||||
:action "/events"
|
||||
:enctype "multipart/form-data"}
|
||||
|
@ -77,15 +112,23 @@
|
|||
(import-attendee-list-form-group)
|
||||
[:div.form-group
|
||||
[:input {:type "submit"
|
||||
:value "Create Event"}]]]))
|
||||
:value "Create Event"}]]]]))
|
||||
|
||||
(defn- events-list-handler [db query type]
|
||||
(let [events (db/list db (db.event/with-stats query))
|
||||
num-events (db/count db query)]
|
||||
(page-response
|
||||
(events-index {:events events
|
||||
:num-events num-events
|
||||
:type type}))))
|
||||
|
||||
(defn events-routes [{:keys [db]}]
|
||||
(context "/events" []
|
||||
(GET "/" request
|
||||
(let [events (db/list db :event)]
|
||||
(page-response
|
||||
(events-index {:events events
|
||||
:authenticated? (authenticated? request)}))))
|
||||
(GET "/" []
|
||||
(events-list-handler db (db.event/upcoming) :upcoming))
|
||||
|
||||
(GET "/past" []
|
||||
(events-list-handler db (db.event/past) :past))
|
||||
|
||||
(GET "/new" [date]
|
||||
(page-response
|
||||
|
|
|
@ -310,6 +310,13 @@
|
|||
{:font-weight "bold"
|
||||
:margin-bottom "0.9rem"}])])
|
||||
|
||||
(defstyles events
|
||||
[:.events-list
|
||||
{:margin-top "1rem"}
|
||||
|
||||
[:li
|
||||
{:margin-bottom "1rem"}]])
|
||||
|
||||
(defstyles styles
|
||||
forms
|
||||
tables
|
||||
|
@ -320,6 +327,7 @@
|
|||
home-page
|
||||
signup-page
|
||||
attendees
|
||||
events
|
||||
|
||||
[:body
|
||||
{:color black}]
|
||||
|
@ -340,6 +348,13 @@
|
|||
:margin-left "auto"
|
||||
:margin-right "auto"})]
|
||||
|
||||
[:.page-header
|
||||
{:display :flex
|
||||
:flex-wrap :wrap
|
||||
:padding-bottom "0.7rem"
|
||||
:margin-bottom "1rem"
|
||||
:border-bottom [["1px" "solid" silver]]}]
|
||||
|
||||
[(attr= "role" "button")
|
||||
{:cursor :pointer}]
|
||||
|
||||
|
|
|
@ -10,8 +10,14 @@
|
|||
(let [formatter (DateTimeFormatter/ofLocalizedDate format-style)]
|
||||
(.format (t/->LocalDate d) formatter))))
|
||||
|
||||
(defn pluralize
|
||||
([n sing plur]
|
||||
(str (or n 0) " " (if (= 1 n) sing plur)))
|
||||
([n sing]
|
||||
(pluralize n sing (str sing "s"))))
|
||||
|
||||
(comment
|
||||
(format-date #inst "2021-12-19T05:00:00.000-00:00")
|
||||
(format-date #inst "2021-12-19T05:00:00.000-00:00"
|
||||
FormatStyle/SHORT)
|
||||
FormatStyle/FULL)
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue