From 6d2cd7da59ce5b648e03e6fd1823dec9057a7b0d Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 13 Apr 2016 20:09:23 +0300 Subject: [PATCH] Simplify error handling on events that communicate with backend. --- src/uxbox/data/auth.cljs | 7 ++-- src/uxbox/data/history.cljs | 24 ++++--------- src/uxbox/data/pages.cljs | 46 ++++++------------------- src/uxbox/data/projects.cljs | 65 ++++++++++++++---------------------- src/uxbox/locales/en.cljs | 3 +- src/uxbox/repo.cljs | 10 ++++-- src/uxbox/repo/core.cljs | 20 ++--------- src/uxbox/rstore.cljs | 7 ++-- src/uxbox/ui/messages.cljs | 2 -- 9 files changed, 63 insertions(+), 121 deletions(-) diff --git a/src/uxbox/data/auth.cljs b/src/uxbox/data/auth.cljs index 664b275d1..db85c3352 100644 --- a/src/uxbox/data/auth.cljs +++ b/src/uxbox/data/auth.cljs @@ -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) diff --git a/src/uxbox/data/history.cljs b/src/uxbox/data/history.cljs index 9f7014c5b..37df2a60b 100644 --- a/src/uxbox/data/history.cljs +++ b/src/uxbox/data/history.cljs @@ -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)))))))) diff --git a/src/uxbox/data/pages.cljs b/src/uxbox/data/pages.cljs index acae8ebdb..56bd97ecd 100644 --- a/src/uxbox/data/pages.cljs +++ b/src/uxbox/data/pages.cljs @@ -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))) diff --git a/src/uxbox/data/projects.cljs b/src/uxbox/data/projects.cljs index 38d911214..243b7b439 100644 --- a/src/uxbox/data/projects.cljs +++ b/src/uxbox/data/projects.cljs @@ -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))) + diff --git a/src/uxbox/locales/en.cljs b/src/uxbox/locales/en.cljs index 7f4bf4d94..8a5843c6a 100644 --- a/src/uxbox/locales/en.cljs +++ b/src/uxbox/locales/en.cljs @@ -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." }) diff --git a/src/uxbox/repo.cljs b/src/uxbox/repo.cljs index c4cb39438..f57521358 100644 --- a/src/uxbox/repo.cljs +++ b/src/uxbox/repo.cljs @@ -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?) diff --git a/src/uxbox/repo/core.cljs b/src/uxbox/repo/core.cljs index 18105b4e7..85a212376 100644 --- a/src/uxbox/repo/core.cljs +++ b/src/uxbox/repo/core.cljs @@ -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"}) diff --git a/src/uxbox/rstore.cljs b/src/uxbox/rstore.cljs index 946359564..535ac2ac7 100644 --- a/src/uxbox/rstore.cljs +++ b/src/uxbox/rstore.cljs @@ -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 diff --git a/src/uxbox/ui/messages.cljs b/src/uxbox/ui/messages.cljs index 220cecd77..c47fe0b20 100644 --- a/src/uxbox/ui/messages.cljs +++ b/src/uxbox/ui/messages.cljs @@ -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)]