161 lines
4.6 KiB
Clojure
161 lines
4.6 KiB
Clojure
(ns auto-ap.effects
|
|
(:require-macros [cljs.core.async.macros :refer [go]])
|
|
(:require [re-frame.core :as re-frame]
|
|
[cljs-http.client :as http]
|
|
[cljs-time.coerce :as c]
|
|
[cljs-time.core :as time]
|
|
[cljs-time.format :as format]
|
|
[cljs.core.async :refer [<! ] :as async]
|
|
[clojure.string :as str]
|
|
[clojure.walk :as walk]
|
|
[venia.core :as v]
|
|
[auto-ap.history :as p]
|
|
[pushy.core :as pushy]))
|
|
|
|
(re-frame/reg-fx
|
|
:redirect
|
|
(fn [uri]
|
|
(pushy/set-token! p/history uri)))
|
|
|
|
(re-frame/reg-fx
|
|
:new-window
|
|
(fn [url]
|
|
(.open js/window url)))
|
|
|
|
(re-frame/reg-fx
|
|
:set-local-storage
|
|
(fn [[name value]]
|
|
(if value
|
|
(.setItem js/localStorage name value)
|
|
(.removeItem js/localStorage name ))))
|
|
|
|
;; 2017-09-19T07:00:00.000Z
|
|
(def is-8601 #"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$")
|
|
|
|
|
|
(defn dates->date-times [x]
|
|
(walk/postwalk
|
|
(fn [node]
|
|
(cond
|
|
|
|
(and (string? node)
|
|
(re-matches is-8601 node))
|
|
(format/parse (format/formatters :date-time) node)
|
|
|
|
(instance? js/Date node)
|
|
(time/to-default-time-zone (c/from-date node))
|
|
|
|
:else
|
|
node))
|
|
x))
|
|
|
|
(re-frame/reg-fx
|
|
:http
|
|
(fn [{:keys [method uri on-success on-error body headers token]}]
|
|
(go
|
|
(let [headers (if token
|
|
(assoc headers "Authorization" (str "Token " token))
|
|
headers)
|
|
response (<! (http/request {:method method
|
|
:body body
|
|
:headers headers
|
|
:url uri}))]
|
|
(if (>= (:status response) 400)
|
|
(when on-error
|
|
(->> response
|
|
:body
|
|
(dates->date-times)
|
|
(conj on-error)
|
|
(re-frame/dispatch)))
|
|
(->> response
|
|
:body
|
|
(dates->date-times)
|
|
(conj on-success)
|
|
(re-frame/dispatch)))))))
|
|
|
|
(re-frame/reg-fx
|
|
:https
|
|
(fn [{:keys [requests on-success on-failure]}]
|
|
(go
|
|
|
|
(let [results (->>
|
|
(for [{:keys [method body headers uri token]} requests]
|
|
(go
|
|
(let [headers (if token
|
|
(assoc headers "Authorization" (str "Token " token))
|
|
headers)
|
|
response (<! (http/request {:method method
|
|
:body body
|
|
:headers headers
|
|
:url uri}))]
|
|
(if (>= (:status response) 400)
|
|
:error
|
|
:success))))
|
|
(async/merge)
|
|
(async/reduce conj [])
|
|
(async/<!))]
|
|
(if (some #{:error} results)
|
|
(re-frame/dispatch on-failure)
|
|
(re-frame/dispatch on-success))))))
|
|
|
|
(defn kebab->snake [s]
|
|
(str/replace s #"-" "_"))
|
|
|
|
(defn snake [x]
|
|
(if (namespace x)
|
|
(keyword (namespace x) (kebab->snake (name x)))
|
|
(keyword (kebab->snake (name x)))))
|
|
|
|
(defn ->graphql [m]
|
|
(walk/postwalk
|
|
(fn [node]
|
|
(cond
|
|
|
|
(keyword? node)
|
|
(snake node)
|
|
|
|
|
|
:else
|
|
node))
|
|
m))
|
|
|
|
(defonce timeouts
|
|
(atom {}))
|
|
|
|
(re-frame/reg-fx
|
|
:dispatch-debounce
|
|
(fn [{:keys [event time key]}]
|
|
(js/clearTimeout (@timeouts key))
|
|
(swap! timeouts assoc key
|
|
(js/setTimeout (fn []
|
|
(re-frame/dispatch event)
|
|
(swap! timeouts dissoc key))
|
|
time))))
|
|
|
|
(re-frame/reg-fx
|
|
:graphql
|
|
(fn [{:keys [query on-success on-error token variables query-obj]}]
|
|
(go
|
|
(let [headers (if token
|
|
{"Authorization" (str "Token " token)}
|
|
{})
|
|
query (or query (v/graphql-query (->graphql query-obj)))
|
|
response (<! (http/request {:method :get
|
|
:headers headers
|
|
:url (str "/api/graphql?query=" (js/encodeURIComponent query)
|
|
"&variables=" (pr-str (or variables {})))}))]
|
|
(if (>= (:status response) 400)
|
|
(when on-error
|
|
(->> response
|
|
:body
|
|
:errors
|
|
(dates->date-times)
|
|
(conj on-error)
|
|
(re-frame/dispatch)))
|
|
(->> response
|
|
:body
|
|
:data
|
|
(dates->date-times)
|
|
(conj on-success)
|
|
(re-frame/dispatch)))))))
|