Frontend routing implementation

This commit is contained in:
Juho Teperi 2018-01-12 11:04:44 +02:00
parent 4f78f56464
commit 468a0947d2
6 changed files with 107 additions and 4 deletions

2
.gitignore vendored
View file

@ -1,4 +1,4 @@
/target
target/
/classes
/checkouts
pom.xml

View file

@ -0,0 +1,9 @@
(defproject metosin/reitit-frontend "0.1.3"
:description "Reitit: Clojurescript frontend routing core"
:url "https://github.com/metosin/reitit"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:plugins [[lein-parent "0.3.2"]]
:parent-project {:path "../../project.clj"
:inherit [:deploy-repositories :managed-dependencies]}
:dependencies [[metosin/reitit-core]])

View file

@ -0,0 +1,90 @@
(ns reitit.frontend
"Utilities to implement frontend routing using Reitit.
Controller is way to declare as data the side-effects and optionally
other data related to the route."
(:require [reitit.core :as reitit]
[clojure.string :as str]
goog.Uri
[reitit.coercion :as coercion]))
;;
;; Utilities
;;
(defn query-params
"Parse query-params from URL into a map."
[^goog.Uri uri]
(let [q (.getQueryData uri)]
(->> q
(.getKeys)
(map (juxt keyword #(.get q %)))
(into {}))))
(defn get-hash
"Given browser hash starting with #, remove the # and
end slashes."
[]
(-> js/location.hash
(subs 1)
(str/replace #"/$" "")))
;;
;; Controller implementation
;;
(defn get-params
"Get controller parameters given match. If controller provides :params
function that will be called with the match. Default is nil."
[controller match]
(if-let [f (:params controller)]
(f match)))
(defn apply-controller
"Run side-effects (:start or :stop) for controller.
The side-effect function is called with controller params."
[controller method]
(when-let [f (get controller method)]
(f (::params controller))))
(defn- pad-same-length [a b]
(concat a (take (- (count b) (count a)) (repeat nil))))
(defn apply-controllers
"Applies changes between current controllers and
those previously enabled. Resets controllers whose
parameters have changed."
[old-controllers new-match]
(let [new-controllers (map (fn [controller]
(assoc controller ::params (get-params controller new-match)))
(:controllers (:data new-match)))
changed-controllers (->> (map (fn [old new]
;; different controllers, or params changed
(if (not= old new)
{:old old, :new new}))
(pad-same-length old-controllers new-controllers)
(pad-same-length new-controllers old-controllers))
(keep identity)
vec)]
(doseq [controller (map :old changed-controllers)]
(apply-controller controller :stop))
(doseq [controller (map :new changed-controllers)]
(apply-controller controller :start))
new-controllers))
(defn hash-change [router hash]
(let [uri (goog.Uri/parse hash)
match (or (reitit/match-by-path router (.getPath uri))
{:data {:name :not-found}})
q (query-params uri)
;; Coerce if coercion enabled
c (if (:result match)
(coercion/coerce-request (:result match) {:query-params q
:path-params (:params match)})
{:query q
:path (:param match)})
;; Replace original params with coerced params
match (-> match
(assoc :query (:query c))
(assoc :params (:path c)))]
match))

View file

@ -11,4 +11,6 @@
[metosin/reitit-spec]
[metosin/reitit-schema]
[metosin/reitit-swagger]
[metosin/reitit-swagger-ui]])
[metosin/reitit-swagger-ui]
[metosin/reitit-frontend]
[metosin/reitit-re-frame]])

View file

@ -16,6 +16,7 @@
[metosin/reitit-schema "0.1.3"]
[metosin/reitit-swagger "0.1.3"]
[metosin/reitit-swagger-ui "0.1.3"]
[metosin/reitit-frontend "0.1.3"]
[meta-merge "1.0.0"]
[ring/ring-core "1.6.3"]
@ -40,7 +41,8 @@
"modules/reitit-spec/src"
"modules/reitit-schema/src"
"modules/reitit-swagger/src"
"modules/reitit-swagger-ui/src"]
"modules/reitit-swagger-ui/src"
"modules/reitit-frontend/src"]
:dependencies [[org.clojure/clojure "1.9.0"]
[org.clojure/clojurescript "1.10.238"]

View file

@ -3,6 +3,6 @@
set -e
# Modules
for ext in reitit-core reitit-ring reitit-spec reitit-schema reitit-swagger reitit-swagger-ui reitit; do
for ext in reitit-core reitit-ring reitit-spec reitit-schema reitit-swagger reitit-swagger-ui reitit-frontend reitit; do
cd modules/$ext; lein "$@"; cd ../..;
done