mirror of
https://github.com/penpot/penpot.git
synced 2025-05-31 11:56:12 +02:00
Simplify error handling on events that communicate with backend.
This commit is contained in:
parent
47a70ad5c9
commit
6d2cd7da59
9 changed files with 63 additions and 121 deletions
|
@ -51,14 +51,15 @@
|
|||
|
||||
rs/WatchEvent
|
||||
(-apply-watch [this state s]
|
||||
(letfn [(on-error [err]
|
||||
(uum/error (tr "errors.auth"))
|
||||
(letfn [(on-error [{:keys [status payload]}]
|
||||
(println status payload)
|
||||
(uum/error (tr "errors.auth.unauthorized"))
|
||||
(rx/empty))]
|
||||
(let [params {:username username
|
||||
:password password
|
||||
:scope "webapp"}]
|
||||
(->> (rp/req :fetch/token params)
|
||||
(rx/catch on-error)
|
||||
(rx/catch rp/client-error? on-error)
|
||||
(rx/map :payload)
|
||||
(rx/mapcat #(rx/of (logged-in %)
|
||||
(dp/fetch-projects)
|
||||
|
|
|
@ -40,14 +40,10 @@
|
|||
rs/WatchEvent
|
||||
(-apply-watch [_ state s]
|
||||
(letfn [(on-success [{history :payload}]
|
||||
(->PinnedPageHistoryFetched (into [] history)))
|
||||
(on-failure [e]
|
||||
(uum/error (tr "errors.fetch-page-history"))
|
||||
(rx/empty))]
|
||||
(->PinnedPageHistoryFetched (into [] history)))]
|
||||
(let [params {:page id :pinned true}]
|
||||
(->> (rp/req :fetch/page-history params)
|
||||
(rx/map on-success)
|
||||
(rx/catch on-failure))))))
|
||||
(rx/map on-success))))))
|
||||
|
||||
(defn fetch-pinned-page-history
|
||||
[id]
|
||||
|
@ -82,16 +78,12 @@
|
|||
(-apply-watch [this state s]
|
||||
(letfn [(on-success [{history :payload}]
|
||||
(let [history (into [] history)]
|
||||
(->PageHistoryFetched history (not (nil? since)))))
|
||||
(on-failure [e]
|
||||
(uum/error (tr "errors.fetch-page-history"))
|
||||
(rx/empty))]
|
||||
(->PageHistoryFetched history (not (nil? since)))))]
|
||||
(let [params (merge
|
||||
{:page id :max (or max 15)}
|
||||
(when since {:since since}))]
|
||||
(->> (rp/req :fetch/page-history params)
|
||||
(rx/map on-success)
|
||||
(rx/catch on-failure))))))
|
||||
(rx/map on-success))))))
|
||||
|
||||
(defn fetch-page-history
|
||||
([id]
|
||||
|
@ -219,14 +211,10 @@
|
|||
rs/WatchEvent
|
||||
(-apply-watch [_ state s]
|
||||
(letfn [(on-success [{item :payload}]
|
||||
(->HistoryItemUpdated item))
|
||||
(on-failure [e]
|
||||
(uum/error (tr "errors.page-history-update"))
|
||||
(rx/empty))]
|
||||
(->HistoryItemUpdated item))]
|
||||
(rx/merge
|
||||
(->> (rp/req :update/page-history item)
|
||||
(rx/map on-success)
|
||||
(rx/catch on-failure))
|
||||
(rx/map on-success))
|
||||
(->> (rx/filter history-updated? s)
|
||||
(rx/take 1)
|
||||
(rx/map #(refres-page-history (:page item))))))))
|
||||
|
|
|
@ -43,14 +43,8 @@
|
|||
(defrecord FetchPages [projectid]
|
||||
rs/WatchEvent
|
||||
(-apply-watch [_ state s]
|
||||
(letfn [(on-loaded [{pages :payload}]
|
||||
(->PagesFetched pages))
|
||||
(on-error [err]
|
||||
(js/console.error err)
|
||||
(rx/empty))]
|
||||
(->> (rp/req :fetch/pages-by-project {:project projectid})
|
||||
(rx/map on-loaded)
|
||||
(rx/catch on-error)))))
|
||||
(->> (rp/req :fetch/pages-by-project {:project projectid})
|
||||
(rx/map (comp ->PagesFetched :payload)))))
|
||||
|
||||
(defn fetch-pages
|
||||
[projectid]
|
||||
|
@ -64,15 +58,11 @@
|
|||
(letfn [(on-created [{page :payload}]
|
||||
(rx/of
|
||||
#(stpr/unpack-page % page)
|
||||
#(stpr/assoc-page % page)))
|
||||
(on-failed [page]
|
||||
(uum/error (tr "errors.auth"))
|
||||
(rx/empty))]
|
||||
#(stpr/assoc-page % page)))]
|
||||
(let [params (-> (into {} this)
|
||||
(assoc :data {}))]
|
||||
(->> (rp/req :create/page params)
|
||||
(rx/mapcat on-created)
|
||||
(rx/catch on-failed))))))
|
||||
(rx/mapcat on-created))))))
|
||||
|
||||
(def ^:private create-page-schema
|
||||
{:name [sc/required sc/string]
|
||||
|
@ -102,15 +92,9 @@
|
|||
(defrecord SyncPage [id]
|
||||
rs/WatchEvent
|
||||
(-apply-watch [this state s]
|
||||
(letfn [(on-success [{page :payload}]
|
||||
(->PageSynced page))
|
||||
(on-failure [e]
|
||||
(uum/error (tr "errors.page-update"))
|
||||
(rx/empty))]
|
||||
(let [page (stpr/pack-page state id)]
|
||||
(->> (rp/req :update/page page)
|
||||
(rx/map on-success)
|
||||
(rx/catch on-failure))))))
|
||||
(let [page (stpr/pack-page state id)]
|
||||
(->> (rp/req :update/page page)
|
||||
(rx/map (comp ->PageSynced :payload))))))
|
||||
|
||||
(defn sync-page
|
||||
[id]
|
||||
|
@ -163,13 +147,9 @@
|
|||
rs/WatchEvent
|
||||
(-apply-watch [this state s]
|
||||
(letfn [(on-success [{page :payload}]
|
||||
#(assoc-in % [:pages-by-id id :version] (:version page)))
|
||||
(on-failure [e]
|
||||
(uum/error (tr "errors.page-update"))
|
||||
(rx/empty))]
|
||||
#(assoc-in % [:pages-by-id id :version] (:version page)))]
|
||||
(->> (rp/req :update/page-metadata (into {} this))
|
||||
(rx/map on-success)
|
||||
(rx/catch on-failure)))))
|
||||
(rx/map on-success)))))
|
||||
|
||||
(def ^:private update-page-schema
|
||||
{:id [sc/required]
|
||||
|
@ -192,15 +172,11 @@
|
|||
rs/WatchEvent
|
||||
(-apply-watch [_ state s]
|
||||
(letfn [(on-success [_]
|
||||
(rs/swap #(stpr/purge-page % id)))
|
||||
(on-failure [e]
|
||||
(uum/error (tr "errors.delete-page"))
|
||||
(rx/empty))]
|
||||
(rs/swap #(stpr/purge-page % id)))]
|
||||
(->> (rp/req :delete/page id)
|
||||
(rx/map on-success)
|
||||
(rx/tap callback)
|
||||
(rx/filter identity)
|
||||
(rx/catch on-failure)))))
|
||||
(rx/filter identity)))))
|
||||
|
||||
(defn delete-page
|
||||
([id] (DeletePage. id (constantly nil)))
|
||||
|
|
|
@ -17,31 +17,6 @@
|
|||
[uxbox.data.pages :as udp]
|
||||
[uxbox.ui.messages :as uum]))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Helpers
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn sort-projects-by
|
||||
[ordering projs]
|
||||
(case ordering
|
||||
:name (sort-by :name projs)
|
||||
:created (reverse (sort-by :created-at projs))
|
||||
projs))
|
||||
|
||||
(defn contains-term?
|
||||
[phrase term]
|
||||
(str/contains? (str/lower phrase) (str/trim (str/lower term))))
|
||||
|
||||
(defn filter-projects-by
|
||||
[term projs]
|
||||
(if (str/blank? term)
|
||||
projs
|
||||
(filter #(contains-term? (:name %) term) projs)))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Events
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; --- Projects Fetched
|
||||
|
||||
(defrecord ProjectsFetched [projects]
|
||||
|
@ -59,12 +34,9 @@
|
|||
rs/WatchEvent
|
||||
(-apply-watch [_ state s]
|
||||
(letfn [(on-loaded [{projects :payload}]
|
||||
#(reduce stpr/assoc-project % projects))
|
||||
(on-error [err]
|
||||
(rx/empty))]
|
||||
#(reduce stpr/assoc-project % projects))]
|
||||
(->> (rp/req :fetch/projects)
|
||||
(rx/map on-loaded)
|
||||
(rx/catch on-error)))))
|
||||
(rx/map on-loaded)))))
|
||||
|
||||
(defn fetch-projects
|
||||
[]
|
||||
|
@ -94,12 +66,8 @@
|
|||
:layout layout
|
||||
:project (:id project)
|
||||
:name "Page 1"
|
||||
:data nil})))
|
||||
(on-failure [err]
|
||||
(uum/error (tr "errors.create-project"))
|
||||
(rx/empty))]
|
||||
:data nil})))]
|
||||
(->> (rp/req :create/project {:name name})
|
||||
(rx/catch on-failure)
|
||||
(rx/mapcat on-success)))))
|
||||
|
||||
(def ^:private create-project-schema
|
||||
|
@ -119,12 +87,9 @@
|
|||
rs/WatchEvent
|
||||
(-apply-watch [_ state s]
|
||||
(letfn [(on-success [_]
|
||||
(rs/swap #(stpr/dissoc-project % id)))
|
||||
(on-failure [e]
|
||||
(uum/error (tr "errors.delete-project")))]
|
||||
(rs/swap #(stpr/dissoc-project % id)))]
|
||||
(->> (rp/req :delete/project id)
|
||||
(rx/map on-success)
|
||||
(rx/catch on-failure)))))
|
||||
(rx/map on-success)))))
|
||||
|
||||
(defn delete-project
|
||||
[id]
|
||||
|
@ -161,3 +126,23 @@
|
|||
first page of the project."
|
||||
([projectid] (GoTo. projectid))
|
||||
([projectid pageid] (GoToPage. projectid pageid)))
|
||||
|
||||
;; --- Helpers
|
||||
|
||||
(defn sort-projects-by
|
||||
[ordering projs]
|
||||
(case ordering
|
||||
:name (sort-by :name projs)
|
||||
:created (reverse (sort-by :created-at projs))
|
||||
projs))
|
||||
|
||||
(defn contains-term?
|
||||
[phrase term]
|
||||
(str/contains? (str/lower phrase) (str/trim (str/lower term))))
|
||||
|
||||
(defn filter-projects-by
|
||||
[term projs]
|
||||
(if (str/blank? term)
|
||||
projs
|
||||
(filter #(contains-term? (:name %) term) projs)))
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
"errors.form.color" "Should be a valid color string"
|
||||
"errors.form.password-not-match" "Password does not match"
|
||||
|
||||
"errors.auth" "Username or passwords seems to be wrong."
|
||||
"errors.generic" "Something work has happened."
|
||||
"errors.auth.unauthorized" "Username or passwords seems to be wrong."
|
||||
"errors.profile.update-password" "Error updating password, probably your old password is wrong."
|
||||
})
|
||||
|
|
|
@ -7,17 +7,21 @@
|
|||
(ns uxbox.repo
|
||||
"A main interface for access to remote resources."
|
||||
(:refer-clojure :exclude [do])
|
||||
(:require [uxbox.repo.core :refer (request)]
|
||||
(:require [uxbox.repo.core :as core]
|
||||
[uxbox.repo.auth]
|
||||
[uxbox.repo.users]
|
||||
[uxbox.repo.projects]
|
||||
[uxbox.repo.pages]
|
||||
[httpurr.status :as status]
|
||||
[beicon.core :as rx]))
|
||||
|
||||
(defn req
|
||||
"Perform a side effectfull action accesing
|
||||
remote resources."
|
||||
([type]
|
||||
(request type nil))
|
||||
(core/request type nil))
|
||||
([type data]
|
||||
(request type data)))
|
||||
(core/request type data)))
|
||||
|
||||
(def client-error? status/client-error?)
|
||||
(def server-error? status/server-error?)
|
||||
|
|
|
@ -28,25 +28,11 @@
|
|||
(assoc response :body (t/decode body))
|
||||
response))
|
||||
|
||||
(defrecord Ok [status payload])
|
||||
(defrecord ServerError [status paylpad])
|
||||
(defrecord ClientError [status payload])
|
||||
(defrecord NotFound [payload])
|
||||
|
||||
(defn- handle-http-status
|
||||
[{:keys [body status] :as response}]
|
||||
(cond
|
||||
(http.status/success? response)
|
||||
(rx/of (->Ok status body))
|
||||
|
||||
(http.status/client-error? response)
|
||||
(rx/throw
|
||||
(if (= status 404)
|
||||
(->NotFound body)
|
||||
(->ClientError status body)))
|
||||
|
||||
(http.status/server-error? response)
|
||||
(rx/throw (->ServerError status body))))
|
||||
(if (http.status/success? response)
|
||||
(rx/of {:status status :payload body})
|
||||
(rx/throw {:status status :payload body})))
|
||||
|
||||
(def ^:private ^:const +headers+
|
||||
{"content-type" "application/transit+json"})
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
|
||||
(ns uxbox.rstore
|
||||
"Reactive storage management architecture helpers."
|
||||
(:require [beicon.core :as rx]))
|
||||
(:require [beicon.core :as rx]
|
||||
[uxbox.locales :refer (tr)]
|
||||
[uxbox.ui.messages :as uum]))
|
||||
|
||||
;; An abstraction for implement a simple state
|
||||
;; transition. The `-apply-update` function receives
|
||||
|
@ -89,8 +91,9 @@
|
|||
(defn- on-error
|
||||
"A default error handler."
|
||||
[e]
|
||||
(uum/error (tr "errors.generic"))
|
||||
(println "Unexpected error: " e)
|
||||
(js/console.error e.stack)
|
||||
(js/console.log (.-stack e))
|
||||
(rx/throw e))
|
||||
|
||||
(defn init
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
(ns uxbox.ui.messages
|
||||
(:require [sablono.core :as html :refer-macros [html]]
|
||||
[rum.core :as rum]
|
||||
[promesa.core :as p]
|
||||
[cuerdas.core :as str]
|
||||
[uxbox.rstore :as rs]
|
||||
[uxbox.ui.icons :as i]
|
||||
[uxbox.ui.mixins :as mx]
|
||||
[uxbox.util.data :refer (classnames)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue