diff --git a/src/clojsa/handler.clj b/src/clojsa/handler.clj index 660ec7f..a105b8a 100644 --- a/src/clojsa/handler.clj +++ b/src/clojsa/handler.clj @@ -25,18 +25,25 @@ (defroutes app-routes (GET "/" request (views/index-page request)) - (GET "/login" [] (views/login-page)) + (GET "/login" [] + (views/main-template + {:title "Login"} + (-> (views/login-form ["/bookmarks"] false) + (views/login-page)))) (POST "/login" [username password next :as {session :session}] (let [resp-cookies (client/login-response username password session)] {:status 302 :headers {"Location" next} - :session (assoc session :cookies resp-cookies)})) + :session (assoc session :cookies resp-cookies :loggedin true)})) (GET "/bookmarks" [page :<< as-int :as {session :session}] - (let [beems (get-bookmarks session page)] - (views/bookmarks-page beems))) + (if (get session :loggedin) + (let [beems (get-bookmarks session page)] + (views/bookmarks-page beems)) + {:status 302 + :headers {"Location" "/login"}})) (GET "/bookmarks" [] {:status 302 :headers {"Location" "/bookmarks?page=1"}}) @@ -44,8 +51,17 @@ (GET "/thread/:id" [id :<< as-int page :<< as-int :as {session :session}] - (let [thread (get-thread session id page)] - (views/thread-page thread))) + (let [thread (get-thread session id page) + {:keys [id page page-count title]} thread + login-part (views/login-form + ["/thread/%d?page=%d" id page] + (get session :loggedin false)) + header-part (views/header-fragment login-part) + thread-part (views/thread-page thread) + paginate-part (views/paginate + (str "/thread/" id) page page-count)] + (views/main-template {:title title} + header-part thread-part paginate-part))) (GET "/thread/:id" [id] {:status 302 :headers {"Location" (str "/thread/" id "?page=1")}}) diff --git a/src/clojsa/views.clj b/src/clojsa/views.clj index d379ef0..06d8f8a 100644 --- a/src/clojsa/views.clj +++ b/src/clojsa/views.clj @@ -5,44 +5,43 @@ [ring.util.anti-forgery :refer [anti-forgery-field]])) -(def ^:dynamic *thread* {}) +(defn login-form [next loggedin] + (if loggedin + [:a.navbar-item "Logout"] + [:div.navbar-item.has-dropdown.is-hoverable + [:a.navbar-link "Login"] + [:div.navbar-dropdown.is-right + [:div.navbar-item + [:form#login-form {:action "/login" :method "post"} + (anti-forgery-field) + [:input {:type "hidden" :name "next" + :value (apply format next)}] + [:div.field + [:label.label {:for "username"} "username"] + [:div.control + [:input#username.input {:name "username" :type "text" + :placeholder "enter your username"}]]] + [:div.field + [:label.label {:for "password"} "password"] + [:div.control + [:input#password.input {:name "password" :type "password" + :placeholder "enter your password"}]]] + [:div.field + [:div.control + [:button.button.is-primary "Submit"]]]]]]])) -(defn login-form [] - [:form#login-form {:action "/login" :method "post"} - (anti-forgery-field) - [:input {:type "hidden" :name "next" - :value (format "/thread/%d?page=%d" (:id *thread*) (:page *thread*))}] - [:div.field - [:label.label {:for "username"} "username"] - [:div.control - [:input#username.input {:name "username" :type "text" - :placeholder "enter your username"}]]] - [:div.field - [:label.label {:for "password"} "password"] - [:div.control - [:input#password.input {:name "password" :type "password" - :placeholder "enter your password"}]]] - [:div.field - [:div.control - [:button.button.is-primary "Submit"]]]]) +(defn header-fragment [login] + [:nav.navbar.is-transparent + [:div.navbar-brand + [:a.burger.navbar-burger {:role "button" :data-target "mainNav"} + (repeat 3 [:span {:aria-hidden "true"}])]] + [:div#mainNav.navbar-menu + [:div.navbar-start + [:a.navbar-item {:href "/bookmarks"} "Bookmarks"]] + [:div.navbar-end + login]]]) -(defn header-fragment [] - (html - [:nav.navbar - [:div.navbar-brand - [:a.burger.navbar-burger {:role "button" :data-target "mainNav"} - (repeat 3 [:span {:aria-hidden "true"}])]] - [:div#mainNav.navbar-menu - [:div.navbar-start - [:a.navbar-item {:href "/bookmarks"} "Bookmarks"]] - [:div.navbar-end - [:div.navbar-item.has-dropdown.is-hoverable - [:a.navbar-link "Login"] - [:div.navbar-dropdown.is-right - [:div.navbar-item - (login-form)]]]]]])) - -(defn main-template [opts & insert-body-here] +(defn main-template [opts header & insert-body-here] (html5 {:lang "de"} [:head @@ -56,7 +55,7 @@ [:body {:hx-boost "false"} [:header - (header-fragment)] + header] [:main insert-body-here] (include-js "/js/main.js")])) @@ -68,59 +67,53 @@ [:pre.output [:code (with-out-str (clojure.pprint/pprint req))]]])) -(defn login-page [] - (main-template - {:title "login"} - [:div.container.box - (login-form "")])) +(defn login-page [login] + [:div.container.box + login]) (defn paginate [base cur last] (let [page-fstring "%s?page=%d" href (partial format page-fstring base)] - [:nav.container.box.pagination {:hx-boot "false"} - [:a.pagination-previous - {:href (href (dec cur))} "<"] - [:a.pagination-next - {:href (href (inc cur))} ">"] - [:ul.pagination-list - [:li - [:a.pagination-link - {:href (href 1)} (str 1)]] - [:li - [:span.pagination-ellipsis "…"]] - (for [i (range (- cur 2) (+ cur 3))] - [:li - [:a.pagination-link - {:href (href i) - :class (when (= i cur) "is-current")} (str i)]]) - [:li - [:span.pagination-ellipsis "…"]] - [:li - [:a.pagination-link - {:href (href last)} (str last)]]]])) + [:section + [:nav.container.box.pagination {:hx-boot "false"} + [:a.pagination-previous + {:href (href (dec cur))} "<"] + [:a.pagination-next + {:href (href (inc cur))} ">"] + [:ul.pagination-list + [:li + [:a.pagination-link + {:href (href 1)} (str 1)]] + [:li + [:span.pagination-ellipsis "…"]] + (for [i (range (- cur 2) (+ cur 3))] + [:li + [:a.pagination-link + {:href (href i) + :class (when (= i cur) "is-current")} (str i)]]) + [:li + [:span.pagination-ellipsis "…"]] + [:li + [:a.pagination-link + {:href (href last)} (str last)]]]]])) -(defn thread-page [thread] - (binding [*thread* thread] - (let [{:keys [id title page page-count content]} thread] - (main-template - {:title title} - [:div.container - [:h1.is-size-3.mb-4 title]] - [:section.thread - (for [post content] - [:article.container.box - [:div.tile.is-ancestor - [:aside.userinfo.tile.is-3.is-parent - (:ui post)] - [:main.postbody.content.tile.is-9.is-parent.is-vertical - [:div.tile.is-child - (:pb post)] - [:div.level.tile.is-child.is-12 - [:div.level-right - [:span.postdate.level-item - (:pd post)]]]]]])] - [:section - (paginate (str "/thread/" id) page page-count)])))) +(defn thread-page [{:keys [title content]}] + (list + [:section.title [:div.container + [:h1.is-size-3.mb-4 title]]] + [:section.thread + (for [post content] + [:article.container.box + [:div.tile.is-ancestor + [:aside.userinfo.tile.is-3.is-parent + (:ui post)] + [:main.postbody.content.tile.is-9.is-parent.is-vertical + [:div.tile.is-child + (:pb post)] + [:div.level.tile.is-child.is-12 + [:div.level-right + [:span.postdate.level-item + (:pd post)]]]]]])])) (defn bookmarks-page [beems] (let [{:keys [title page page-count content]} beems]