From eb59e97e963a110f154b6e827481734a99372d8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arne=20Schl=C3=BCter?= Date: Fri, 20 Apr 2018 14:56:50 +0200 Subject: [PATCH] Sketch out method to associate routes with api data --- src/airsonic_ui/events.cljs | 55 +++++++++++-------------------------- src/airsonic_ui/routes.cljs | 24 ++++++++++++++-- 2 files changed, 38 insertions(+), 41 deletions(-) diff --git a/src/airsonic_ui/events.cljs b/src/airsonic_ui/events.cljs index 1e4cc00..ec2a421 100644 --- a/src/airsonic_ui/events.cljs +++ b/src/airsonic_ui/events.cljs @@ -2,44 +2,18 @@ (:require [re-frame.core :as re-frame] [ajax.core :as ajax] [airsonic-ui.routes :as routes] - [airsonic-ui.config :as config] [airsonic-ui.db :as db] - [clojure.string :as string])) + [airsonic-ui.api :as api])) -;; TODO: - -;; api related functions - -(defn ^:private uri-escape [s] - (js/encodeURIComponent s)) - -(defn ^:private api-url [endpoint params] - (let [query (->> (assoc params - :f "json" - :c "airsonic-ui-cljs" - :v "1.15.0") - (map (fn [[k v]] - (str (uri-escape (name k)) "=" (uri-escape v)))) - (string/join "&"))] - (str config/server "/rest/" endpoint "?" query))) - -(defn ^:private api-error? - "We need to look at the message body because the subsonic api always responds - with status 200" - [response] - (= "failed" (-> response :subsonic-response :status))) - -(defn ^:private error-message - [response] - (let [{:keys [code message]} (-> response :subsonic-response :error)] - (str "Code " code ": " message))) +;; this is called with user and password to try and see if the credentials are +;; correct; if yes, ::auth-success will be fired (re-frame/reg-event-fx ::authenticate (fn [{:keys [db]} [_ user pass]] {:db (update db :active-requests inc) :http-xhrio {:method :get - :uri (api-url "ping" {:u user :p pass}) + :uri (api/url "ping" {:u user :p pass}) :response-format (ajax/json-response-format {:keywords? true}) :on-success [::auth-success user pass] :on-failure [::api-failure]}})) @@ -54,22 +28,23 @@ {::routes/set-credentials login :db (-> (update db :active-requests #(max (dec %) 0)) (assoc :login login)) - :dispatch-n (list [::start-page] - [::api-request "getAlbumList2" :albumList2 {:type "recent"}])}))) + :dispatch [::logged-in]}))) ;; we do this in two steps to make sure the credentials are set once we navigate (re-frame/reg-event-fx - ::start-page + ::logged-in (fn [_ _] {::routes/navigate [::routes/main]})) ;; TODO: Test that credentials are actually taken +;; TODO: Move these in the future? events.cljs should just do wiring. We could +;; implement api.cljs as a completely independent module. (re-frame/reg-event-fx - ::api-request + :api-request (fn [{:keys [db]} [_ endpoint k params]] {:http-xhrio {:method :get - :uri (api-url endpoint (merge params (:login db))) + :uri (api/url endpoint (merge params (:login db))) :response-format (ajax/json-response-format {:keywords? true}) :on-success [::api-success k] :on-failure [::api-failure]}})) @@ -89,18 +64,20 @@ ;; routing -(re-frame/reg-event-db +(re-frame/reg-event-fx ::routes/navigation - (fn [db [_ route params query]] + (fn [{:keys [db]} [_ route params query]] ;; all the naviagation logic is in routes.cljs; all we need to do here ;; is say what actually happens once we've navigated succesfully - (assoc db :current-route [route params query]))) + (println "routes/route-data" (routes/data-for route params query)) + {:db (assoc db :current-route [route params query]) + :dispatch (routes/data-for route params query)})) (re-frame/reg-event-fx ::routes/unauthorized (fn [fx _] ;; log out on 403 - {:navigate [routes/default-route] + {::routes/navigate [routes/default-route] ::routes/unset-credentials nil :db db/default-db})) diff --git a/src/airsonic_ui/routes.cljs b/src/airsonic_ui/routes.cljs index af0173e..4eac91d 100644 --- a/src/airsonic_ui/routes.cljs +++ b/src/airsonic_ui/routes.cljs @@ -10,11 +10,30 @@ ["/album/:id" ::album-view] ["/artist/:id" ::artist-view]])) -(def protected-routes #{::main ::album-view}) - +; use this in views to construct a url (defn url-for [k params] (str "#" (r/resolve router k params))) +; which routes need valid login credentials? +(def protected-routes #{::main ::album-view}) + +; which data should be requested for which route? can either be a vector or a function returning a vector +(def route-data + {::main [:api-request "getAlbumList2" :albumList2 {:type "recent"}] + ::album-view (fn [route-id params _] + [:api-request "getAlbum" :album {:id (:id params)}])}) + + +(defn data-for + "Wrapper around route-data so we can call it like a function no matter whether + the value associated with the route key is a function or not." + [route params query] + (if-let [route-data' (route-data route)] + (if (vector? route-data') + route-data' + (route-data' route params query)) + [])) + ;; shouldn't need to change anything below ;; these are helper effects we can use to navigate; the first two manage an atom @@ -36,6 +55,7 @@ (re-frame/reg-fx ::navigate (fn [[route-id params query]] + (println "calling ::navigate with" route-id params query) (r/navigate! router route-id params query))) (defn can-access? [route]