From cc320215ac1302ff37c47f24385a5eade3f595d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Sun, 10 Apr 2016 20:27:25 +0200 Subject: [PATCH 01/12] Improve errors management on password change --- src/uxbox/locales/en.cljs | 6 +++++- src/uxbox/ui/settings/password.cljs | 17 +++++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/uxbox/locales/en.cljs b/src/uxbox/locales/en.cljs index ce2f1e2349..a9e2e141c2 100644 --- a/src/uxbox/locales/en.cljs +++ b/src/uxbox/locales/en.cljs @@ -40,5 +40,9 @@ "history.alert-message" "You are seeng version %s" "errors.auth" "Username or passwords seems to be wrong." - + "errors.update-password" "Error updating password, probably your old password is wrong." + "old-password-needed" "Old password needed." + "new-password-needed" "New password needed." + "password-too-short" "The new password is too short." + "password-doesnt-match" "The passwords doesn't match." }) diff --git a/src/uxbox/ui/settings/password.cljs b/src/uxbox/ui/settings/password.cljs index 363e9bf1e4..07caab2e99 100644 --- a/src/uxbox/ui/settings/password.cljs +++ b/src/uxbox/ui/settings/password.cljs @@ -9,9 +9,11 @@ (:require [sablono.core :as html :refer-macros [html]] [rum.core :as rum] [cuerdas.core :as str] + [uxbox.locales :as t :refer (tr)] [uxbox.router :as r] [uxbox.rstore :as rs] [uxbox.ui.icons :as i] + [uxbox.ui.messages :as uum] [uxbox.ui.mixins :as mx] [uxbox.util.dom :as dom] [uxbox.data.users :as udu] @@ -22,12 +24,13 @@ (defn password-form-render [own] (let [local (:rum/local own) - valid? (and (not (str/empty? (:password-1 @local))) - (not (str/empty? (:password-2 @local))) - (= 6 (count (:password-1 @local ""))) - (= (:password-1 @local) - (:password-2 @local)))] - (println "valid?" valid?) + invalid-reason (cond + (= 0 (count (:old-password @local))) "old-password-needed" + (= 0 (count (:password-1 @local))) "new-password-needed" + (> 6 (count (:password-1 @local ""))) "password-too-short" + (not= (:password-1 @local) (:password-2 @local)) "password-doesnt-match" + :else nil) + valid? (nil? invalid-reason)] (letfn [(on-field-change [field event] (let [value (dom/event->value event)] (swap! local assoc field value))) @@ -38,6 +41,7 @@ (html [:form.password-form + (uum/messages) [:span.user-settings-label "Change password"] [:input.input-text {:type "password" @@ -54,6 +58,7 @@ :value (:password-2 @local "") :on-change (partial on-field-change :password-2) :placeholder "Confirm password"}] + (when-not valid? [:span (tr invalid-reason)]) [:input.btn-primary {:type "button" :class (when-not valid? "btn-disabled") From 3d7936707890a5faee702a1fdf04013481497b47 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 11 Apr 2016 22:29:16 +0300 Subject: [PATCH 02/12] Replace bouncer with funcool/struct. --- project.clj | 2 +- src/uxbox/data/dashboard.cljs | 11 ++- src/uxbox/data/shapes.cljs | 3 +- src/uxbox/data/workspace.cljs | 3 +- src/uxbox/schema.cljs | 133 +++++++++++++++++----------------- 5 files changed, 73 insertions(+), 79 deletions(-) diff --git a/project.clj b/project.clj index 28cc3c4415..6151364f57 100644 --- a/project.clj +++ b/project.clj @@ -20,13 +20,13 @@ [cljsjs/react "15.0.0-rc.2-0"] [cljsjs/react-dom "15.0.0-rc.2-0"] [cljsjs/moment "2.10.6-3"] + [funcool/struct "0.1.0-SNAPSHOT"] [funcool/lentes "1.0.1"] [funcool/httpurr "0.6.0-SNAPSHOT"] [funcool/promesa "1.1.1"] [funcool/beicon "1.1.1"] [funcool/cuerdas "0.7.1"] [funcool/hodgepodge "0.1.4"] - [bouncer "1.0.0"] [bidi "2.0.4"]] :plugins [[lein-ancient "0.6.7"]] :clean-targets ^{:protect false} ["resources/public/js" "target"] diff --git a/src/uxbox/data/dashboard.cljs b/src/uxbox/data/dashboard.cljs index 72acd89a5c..6ca4034c35 100644 --- a/src/uxbox/data/dashboard.cljs +++ b/src/uxbox/data/dashboard.cljs @@ -10,21 +10,20 @@ [uxbox.router :as r] [uxbox.state :as st] [uxbox.schema :as sc] - [uxbox.repo :as rp] - [bouncer.validators :as v])) + [uxbox.repo :as rp])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Schemas ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (def ^:static +color-replace-schema+ - {:id [v/required sc/uuid] + {:id [sc/required sc/uuid] :from [sc/color] - :to [v/required sc/color]}) + :to [sc/required sc/color]}) (def ^:static +remove-color-schema+ - {:id [v/required sc/uuid] - :color [v/required sc/color]}) + {:id [sc/required sc/uuid] + :color [sc/required sc/color]}) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Helpers diff --git a/src/uxbox/data/shapes.cljs b/src/uxbox/data/shapes.cljs index d59429aa03..24a522cb53 100644 --- a/src/uxbox/data/shapes.cljs +++ b/src/uxbox/data/shapes.cljs @@ -6,8 +6,7 @@ ;; Copyright (c) 2015-2016 Juan de la Cruz (ns uxbox.data.shapes - (:require [bouncer.validators :as v] - [beicon.core :as rx] + (:require [beicon.core :as rx] [uxbox.shapes :as sh] [uxbox.rstore :as rs] [uxbox.router :as r] diff --git a/src/uxbox/data/workspace.cljs b/src/uxbox/data/workspace.cljs index b4ed057205..bfcce6a654 100644 --- a/src/uxbox/data/workspace.cljs +++ b/src/uxbox/data/workspace.cljs @@ -6,8 +6,7 @@ ;; Copyright (c) 2015-2016 Juan de la Cruz (ns uxbox.data.workspace - (:require [bouncer.validators :as v] - [beicon.core :as rx] + (:require [beicon.core :as rx] [uxbox.constants :as c] [uxbox.shapes :as sh] [uxbox.rstore :as rs] diff --git a/src/uxbox/schema.cljs b/src/uxbox/schema.cljs index 14c7da155c..ab2195d532 100644 --- a/src/uxbox/schema.cljs +++ b/src/uxbox/schema.cljs @@ -6,89 +6,86 @@ ;; Copyright (c) 2015-2016 Juan de la Cruz (ns uxbox.schema - (:refer-clojure :exclude [keyword uuid vector boolean]) - (:require [bouncer.core :as b] - [bouncer.validators :as v] - [cuerdas.core :as str] + (:refer-clojure :exclude [keyword uuid vector boolean map set]) + (:require [struct.core :as st] + [uxbox.locales :refer (tr)] [uxbox.shapes :refer (shape?)])) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Validators -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; (def datetime +;; {:message "must be an instant" +;; :optional true +;; :validate #(instance? Instant %)}) -(v/defvalidator keyword - "Validates maybe-an-int is a valid integer. - For use with validation functions such as `validate` or `valid?`" - {:default-message-format "%s must be a keyword"} - [v] - (cljs.core/keyword? v)) +(def required + (assoc st/required :message "errors.form.required")) -(v/defvalidator uuid - "Validates maybe-an-int is a valid integer. - For use with validation functions such as `validate` or `valid?`" - {:default-message-format "%s must be a uuid instance"} - [v] - (instance? cljs.core.UUID v)) +(def string + (assoc st/string :message "errors.form.string")) -(v/defvalidator color - "Validates if a string is a valid color." - {:default-message-format "%s must be a valid hex color"} - [v] - (not (nil? (re-find #"^#[0-9A-Fa-f]{6}$" v)))) +(def number + (assoc st/number :message "errors.form.number")) -(v/defvalidator shape-type - "Validates if a keyword is a shape type." - {:default-message-format "%s must be a shape type keyword."} - [v] - (shape? v)) +(def integer + (assoc st/integer :message "errors.form.integer")) -(v/defvalidator vector - "Validats if `v` is vector." - {:default-message-format "%s must be a vector instance."} - [v] - (vector? v)) +(def boolean + (assoc st/boolean :message "errors.form.bool")) -(v/defvalidator function - "Validats if `v` is function." - {:default-message-format "%s must be a function."} - [v] - (fn? v)) +(def identical-to + (assoc st/identical-to :message "errors.form.identical-to")) -(def ^:const +email-re+ - #"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$") +;; (def in-range st/in-range) +;; (def uuid-like st/uuid-like) +(def uuid st/uuid) +(def keyword st/keyword) +;; (def integer-like st/integer-like) +;; (def boolean-like st/boolean-like) +;; (def email st/email) +;; (def function st/function) +;; (def positive st/positive) +;; (def validate st/validate) +;; (def validate! st/validate!) -(v/defvalidator email - "Validate if `v` is a valid email." - {:default-message-format "% must be a valid email."} - [v] - (clojure.core/boolean (re-seq +email-re+ v))) +(def max-len + {:message "errors.form.max-len" + :optional true + :validate (fn [v n] + (let [len (count v)] + (>= len v)))}) -(def required v/required) -(def number v/number) -(def integer v/integer) -(def boolean v/boolean) -(def string v/string) +(def min-len + {:message "errors.form.min-len" + :optional true + :validate (fn [v n] + (>= (count v) n))}) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Public Api -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(def color + {:message "errors.form.color" + :optional true + :validate #(not (nil? (re-find #"^#[0-9A-Fa-f]{6}$" %)))}) + +(def shape-type + {:message "should be shape" + :optional true + :validate #(shape? %)}) (defn validate - ([schema] #(validate schema %)) - ([schema data] (first (b/validate data schema)))) + [data schema] + (let [opts {:strip true + :translate tr}] + (st/validate data schema opts))) (defn validate! - ([schema] #(validate! schema %)) - ([schema data] - (when-let [errors (validate schema data)] - (throw (ex-info "Invalid data" errors))))) + [data schema] + (when-let [errors (first (validate schema data))] + (throw (ex-info "Invalid data" errors)))) -(defn valid? - [validator data] - (let [result (validator data)] - (if result - result - (let [message (:default-message-format (meta validator)) - message (str/format message data)] - (throw (ex-info message {})))))) +;; (defn valid? +;; [validator data] +;; (let [result (validator data)] +;; (if result +;; result +;; (let [message (:default-message-format (meta validator)) +;; message (str/format message data)] +;; (throw (ex-info message {})))))) From 6eba3d4764baf51a02a0a79d7b729ea4105544b2 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 11 Apr 2016 22:30:51 +0300 Subject: [PATCH 03/12] Add improvements to form helpers. --- src/uxbox/ui/form.cljs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/uxbox/ui/form.cljs b/src/uxbox/ui/form.cljs index 6816007e0c..b517fe0948 100644 --- a/src/uxbox/ui/form.cljs +++ b/src/uxbox/ui/form.cljs @@ -4,17 +4,21 @@ (defn validate! [local schema] - (if-let [errors (sc/validate schema @local)] - (swap! local assoc :errors errors) - (swap! local assoc :errors nil))) + (let [[errors data] (sc/validate (:form @local) schema)] + (if errors + (do + (swap! local assoc :errors errors) + nil) + (do + (swap! local assoc :errors nil) + data)))) (defn input-error [local name] (when-let [errors (get-in @local [:errors name])] - [:div.errors - [:ul {} - (for [error errors] - [:li error])]])) + [:ul.form-errors + (for [error errors] + [:li {:key error} error])])) (defn error-class [local name] From f81975aa6c1bc12fb1d8369525130e77525c8308 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 11 Apr 2016 22:31:04 +0300 Subject: [PATCH 04/12] Improve error messages on settings/password page. --- src/uxbox/data/users.cljs | 4 +- src/uxbox/locales/en.cljs | 15 +++++--- src/uxbox/ui/settings/password.cljs | 57 +++++++++++++++++++---------- 3 files changed, 49 insertions(+), 27 deletions(-) diff --git a/src/uxbox/data/users.cljs b/src/uxbox/data/users.cljs index 237610b599..5957512022 100644 --- a/src/uxbox/data/users.cljs +++ b/src/uxbox/data/users.cljs @@ -65,11 +65,11 @@ rs/WatchEvent (-apply-watch [_ state s] (letfn [(on-error [err] - (uum/error (tr "errors.update-password")) + (uum/error (tr "errors.profile.update-password")) (rx/empty))] (->> (rp/req :update/password {:old-password old-password :password password}) (rx/catch on-error))))) (defn update-password - [old-password password] + [{:keys [old-password password]}] (UpdatePassword. old-password password)) diff --git a/src/uxbox/locales/en.cljs b/src/uxbox/locales/en.cljs index a9e2e141c2..13f7dea8bc 100644 --- a/src/uxbox/locales/en.cljs +++ b/src/uxbox/locales/en.cljs @@ -38,11 +38,16 @@ "ds.help.line" "Line (Ctrl + L)" "history.alert-message" "You are seeng version %s" + "errors.form.required" "This field is mandatory" + "errors.form.string" "Should be string" + "errors.form.number" "Invalid number" + "errors.form.integer" "Invalid integer" + "errors.form.bool" "Should be bool" + "errors.form.min-len" "Should be great than %s" + "errors.form.max-len" "Should be less than %s" + "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.update-password" "Error updating password, probably your old password is wrong." - "old-password-needed" "Old password needed." - "new-password-needed" "New password needed." - "password-too-short" "The new password is too short." - "password-doesnt-match" "The passwords doesn't match." + "errors.profile.update-password" "Error updating password, probably your old password is wrong." }) diff --git a/src/uxbox/ui/settings/password.cljs b/src/uxbox/ui/settings/password.cljs index 07caab2e99..625bddb7a9 100644 --- a/src/uxbox/ui/settings/password.cljs +++ b/src/uxbox/ui/settings/password.cljs @@ -9,56 +9,72 @@ (:require [sablono.core :as html :refer-macros [html]] [rum.core :as rum] [cuerdas.core :as str] + [uxbox.schema :as sc] [uxbox.locales :as t :refer (tr)] [uxbox.router :as r] [uxbox.rstore :as rs] + [uxbox.data.users :as udu] [uxbox.ui.icons :as i] + [uxbox.ui.form :as form] [uxbox.ui.messages :as uum] [uxbox.ui.mixins :as mx] - [uxbox.util.dom :as dom] - [uxbox.data.users :as udu] - [uxbox.ui.dashboard.header :refer (header)])) + [uxbox.ui.dashboard.header :refer (header)] + [uxbox.util.dom :as dom])) ;; --- Password Form +(def password-form-schema + [[:password-1 sc/required sc/string [sc/min-len 6]] + [:password-2 sc/required sc/string + [sc/identical-to :password-1 :message "errors.form.password-not-match"]] + [:old-password sc/required sc/string]]) + +(defn field-errors + [errors field] + (when-let [errors (get errors field)] + (html + [:ul + (for [error errors] + [:li {:key error} error])]))) + (defn password-form-render [own] (let [local (:rum/local own) - invalid-reason (cond - (= 0 (count (:old-password @local))) "old-password-needed" - (= 0 (count (:password-1 @local))) "new-password-needed" - (> 6 (count (:password-1 @local ""))) "password-too-short" - (not= (:password-1 @local) (:password-2 @local)) "password-doesnt-match" - :else nil) - valid? (nil? invalid-reason)] + form (:form @local) + errors (:errors @local) + valid? true #_(nil? invalid-reason)] (letfn [(on-field-change [field event] (let [value (dom/event->value event)] - (swap! local assoc field value))) + (swap! local assoc-in [:form field] value))) (on-submit [event] - (let [password (:password-1 @local) - old-password (:old-password @local)] - (rs/emit! (udu/update-password old-password password))))] - + (when-let [data (form/validate! local password-form-schema)] + (let [params {:password (:password-1 form) + :old-password (:old-password form)}] + (rs/emit! (udu/update-password params)))))] (html [:form.password-form - (uum/messages) [:span.user-settings-label "Change password"] [:input.input-text {:type "password" - :value (:old-password @local "") + :class (form/error-class local :old-password) + :value (:old-password form "") :on-change (partial on-field-change :old-password) :placeholder "Old password"}] + (form/input-error local :old-password) [:input.input-text {:type "password" - :value (:password-1 @local "") + :class (form/error-class local :password-1) + :value (:password-1 form "") :on-change (partial on-field-change :password-1) :placeholder "New password"}] + (form/input-error local :password-1) [:input.input-text {:type "password" - :value (:password-2 @local "") + :class (form/error-class local :password-2) + :value (:password-2 form "") :on-change (partial on-field-change :password-2) :placeholder "Confirm password"}] - (when-not valid? [:span (tr invalid-reason)]) + (form/input-error local :password-2) [:input.btn-primary {:type "button" :class (when-not valid? "btn-disabled") @@ -79,6 +95,7 @@ (html [:main.dashboard-main (header) + (uum/messages) [:section.dashboard-content.user-settings [:div.user-settings-nav [:ul.user-settings-nav-inside From b37196621cbe02ad6b5c62747410061105168638 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 11 Apr 2016 23:39:55 +0300 Subject: [PATCH 05/12] Add info message type. --- src/uxbox/ui/messages.cljs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/uxbox/ui/messages.cljs b/src/uxbox/ui/messages.cljs index 98a59781a7..220cecd77f 100644 --- a/src/uxbox/ui/messages.cljs +++ b/src/uxbox/ui/messages.cljs @@ -54,6 +54,20 @@ :tsem tsem :content message})))) +(defn info + ([message] (info message nil)) + ([message {:keys [timeout] :or {timeout 6000}}] + (when-let [prev @+message+] + (clean-prev-msgstate! prev)) + (let [timeout' (+ timeout +animation-timeout+) + tsem-main (set-timeout! timeout' #(reset! +message+ nil)) + tsem (set-timeout! timeout #(swap! +message+ assoc :state :hide))] + (reset! +message+ {:type :notification/info + :state :normal + :tsem-main tsem-main + :tsem tsem + :content message})))) + (defn dialog [& {:keys [message on-accept on-cancel] :or {on-cancel (constantly nil)} From e509daaeef08cf72518cf27b554d3c59d12549c8 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 11 Apr 2016 23:40:09 +0300 Subject: [PATCH 06/12] Add missing locale for password success update message. --- src/uxbox/locales/en.cljs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/uxbox/locales/en.cljs b/src/uxbox/locales/en.cljs index 13f7dea8bc..5363f59245 100644 --- a/src/uxbox/locales/en.cljs +++ b/src/uxbox/locales/en.cljs @@ -37,6 +37,8 @@ "ds.help.circle" "Circle (Ctrl + E)" "ds.help.line" "Line (Ctrl + L)" + "profile.password-saved" "Password saved successfully!" + "history.alert-message" "You are seeng version %s" "errors.form.required" "This field is mandatory" "errors.form.string" "Should be string" From e42b2ed7bf1ad8100ff3abd7774cfad9d4cd9afd Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 11 Apr 2016 23:40:40 +0300 Subject: [PATCH 07/12] Overhaul of form data and errors handling. --- src/uxbox/data/forms.cljs | 40 +++++++++++++++++++++ src/uxbox/data/users.cljs | 37 +++++++++++++++---- src/uxbox/schema.cljs | 13 +++---- src/uxbox/ui/dashboard/colors.cljs | 2 +- src/uxbox/ui/dashboard/icons.cljs | 1 - src/uxbox/ui/form.cljs | 26 -------------- src/uxbox/ui/forms.cljs | 16 +++++++++ src/uxbox/ui/settings/password.cljs | 55 ++++++++++++++--------------- 8 files changed, 118 insertions(+), 72 deletions(-) create mode 100644 src/uxbox/data/forms.cljs delete mode 100644 src/uxbox/ui/form.cljs create mode 100644 src/uxbox/ui/forms.cljs diff --git a/src/uxbox/data/forms.cljs b/src/uxbox/data/forms.cljs new file mode 100644 index 0000000000..78d527f1c5 --- /dev/null +++ b/src/uxbox/data/forms.cljs @@ -0,0 +1,40 @@ +;; This Source Code Form is subject to the terms of the Mozilla Public +;; License, v. 2.0. If a copy of the MPL was not distributed with this +;; file, You can obtain one at http://mozilla.org/MPL/2.0/. +;; +;; Copyright (c) 2016 Andrey Antukh + +(ns uxbox.data.forms + (:require [beicon.core :as rx] + [promesa.core :as p] + [uxbox.repo :as rp] + [uxbox.rstore :as rs] + [uxbox.state :as st] + [uxbox.schema :as sc] + [uxbox.locales :refer (tr)] + [uxbox.ui.messages :as uum])) + +;; --- Assign Errors + +(defrecord AssignErrors [type errors] + rs/UpdateEvent + (-apply-update [_ state] + (assoc-in state [:errors type] errors))) + +(defn assign-errors + ([type] (assign-errors type nil)) + ([type errors] + (FormErrors. type errors))) + +;; --- Assign Field Value + +(defrecord AssignFieldValue [type field value] + rs/UpdateEvent + (-apply-update [_ state] + (assoc-in state [:forms type field] value))) + +(defn assign-field-value + [type field value] + (AssignFieldValue. type field value)) + + diff --git a/src/uxbox/data/users.cljs b/src/uxbox/data/users.cljs index 5957512022..b3ca6f604a 100644 --- a/src/uxbox/data/users.cljs +++ b/src/uxbox/data/users.cljs @@ -12,6 +12,7 @@ [uxbox.state :as st] [uxbox.schema :as sc] [uxbox.locales :refer (tr)] + [uxbox.data.forms :as forms] [uxbox.ui.messages :as uum])) ;; --- Profile Fetched @@ -59,17 +60,41 @@ [data] (UpdateProfile. data)) +;; --- Password Updated + +(defrecord PasswordUpdated [] + rs/UpdateEvent + (-apply-update [_ state] + (assoc-in state [:forms :profile/password] {})) + + rs/EffectEvent + (-apply-effect [_ state] + (uum/info (tr "profile.password-saved")))) + ;; --- Update Password -(defrecord UpdatePassword [old-password password] +(defrecord UpdatePassword [data] rs/WatchEvent (-apply-watch [_ state s] (letfn [(on-error [err] - (uum/error (tr "errors.profile.update-password")) + (uum/error (tr "errors.profile.update-password") {:timeout 3000}) (rx/empty))] - (->> (rp/req :update/password {:old-password old-password :password password}) - (rx/catch on-error))))) + (let [params {:old-password (:old-password data) + :password (:password-1 data)}] + (->> (rp/req :update/password params) + (rx/map #(->PasswordUpdated)) + (rx/catch on-error)))))) + +(def update-password-schema + [[:password-1 sc/required sc/string [sc/min-len 6]] + [:password-2 sc/required sc/string + [sc/identical-to :password-1 :message "errors.form.password-not-match"]] + [:old-password sc/required sc/string]]) (defn update-password - [{:keys [old-password password]}] - (UpdatePassword. old-password password)) + [data] + (let [[errors data] (sc/validate data update-password-schema)] + (println errors) + (if errors + (forms/assign-errors :profile/password errors) + (UpdatePassword. data)))) diff --git a/src/uxbox/schema.cljs b/src/uxbox/schema.cljs index ab2195d532..ef8d6f3b2a 100644 --- a/src/uxbox/schema.cljs +++ b/src/uxbox/schema.cljs @@ -80,12 +80,7 @@ (when-let [errors (first (validate schema data))] (throw (ex-info "Invalid data" errors)))) -;; (defn valid? -;; [validator data] -;; (let [result (validator data)] -;; (if result -;; result -;; (let [message (:default-message-format (meta validator)) -;; message (str/format message data)] -;; (throw (ex-info message {})))))) - +(defn valid? + [data schema] + (let [[errors data] (validate data schema)] + (not errors))) diff --git a/src/uxbox/ui/dashboard/colors.cljs b/src/uxbox/ui/dashboard/colors.cljs index 5cb798bcdd..7cde68edd4 100644 --- a/src/uxbox/ui/dashboard/colors.cljs +++ b/src/uxbox/ui/dashboard/colors.cljs @@ -17,7 +17,7 @@ [uxbox.library :as library] [uxbox.data.dashboard :as dd] [uxbox.ui.icons :as i] - [uxbox.ui.form :as form] + [uxbox.ui.forms :as form] [uxbox.ui.lightbox :as lightbox] [uxbox.ui.colorpicker :refer (colorpicker)] [uxbox.ui.mixins :as mx] diff --git a/src/uxbox/ui/dashboard/icons.cljs b/src/uxbox/ui/dashboard/icons.cljs index 8aec7ccc76..b397cef288 100644 --- a/src/uxbox/ui/dashboard/icons.cljs +++ b/src/uxbox/ui/dashboard/icons.cljs @@ -15,7 +15,6 @@ [uxbox.library :as library] [uxbox.data.dashboard :as dd] [uxbox.ui.icons :as i] - [uxbox.ui.form :as form] [uxbox.ui.shapes.core :as uusc] [uxbox.ui.lightbox :as lightbox] [uxbox.ui.mixins :as mx] diff --git a/src/uxbox/ui/form.cljs b/src/uxbox/ui/form.cljs deleted file mode 100644 index b517fe0948..0000000000 --- a/src/uxbox/ui/form.cljs +++ /dev/null @@ -1,26 +0,0 @@ -(ns uxbox.ui.form - (:require [sablono.core :refer-macros [html]] - [uxbox.schema :as sc])) - -(defn validate! - [local schema] - (let [[errors data] (sc/validate (:form @local) schema)] - (if errors - (do - (swap! local assoc :errors errors) - nil) - (do - (swap! local assoc :errors nil) - data)))) - -(defn input-error - [local name] - (when-let [errors (get-in @local [:errors name])] - [:ul.form-errors - (for [error errors] - [:li {:key error} error])])) - -(defn error-class - [local name] - (when (get-in @local [:errors name]) - "invalid")) diff --git a/src/uxbox/ui/forms.cljs b/src/uxbox/ui/forms.cljs new file mode 100644 index 0000000000..78ec63fc8f --- /dev/null +++ b/src/uxbox/ui/forms.cljs @@ -0,0 +1,16 @@ +(ns uxbox.ui.forms + (:require [sablono.core :refer-macros [html]] + [uxbox.schema :as sc])) + +(defn input-error + [errors field] + (when-let [errors (get errors field)] + (html + [:ul.form-errors + (for [error errors] + [:li {:key error} error])]))) + +(defn error-class + [errors field] + (when (get errors field) + "invalid")) diff --git a/src/uxbox/ui/settings/password.cljs b/src/uxbox/ui/settings/password.cljs index 625bddb7a9..57b786eac5 100644 --- a/src/uxbox/ui/settings/password.cljs +++ b/src/uxbox/ui/settings/password.cljs @@ -8,14 +8,17 @@ (ns uxbox.ui.settings.password (:require [sablono.core :as html :refer-macros [html]] [rum.core :as rum] + [lentes.core :as l] [cuerdas.core :as str] [uxbox.schema :as sc] + [uxbox.state :as st] [uxbox.locales :as t :refer (tr)] [uxbox.router :as r] [uxbox.rstore :as rs] [uxbox.data.users :as udu] + [uxbox.data.forms :as udf] [uxbox.ui.icons :as i] - [uxbox.ui.form :as form] + [uxbox.ui.forms :as forms] [uxbox.ui.messages :as uum] [uxbox.ui.mixins :as mx] [uxbox.ui.dashboard.header :refer (header)] @@ -23,58 +26,52 @@ ;; --- Password Form -(def password-form-schema - [[:password-1 sc/required sc/string [sc/min-len 6]] - [:password-2 sc/required sc/string - [sc/identical-to :password-1 :message "errors.form.password-not-match"]] - [:old-password sc/required sc/string]]) +(def formdata + (-> (l/in [:forms :profile/password]) + (l/focus-atom st/state))) -(defn field-errors - [errors field] - (when-let [errors (get errors field)] - (html - [:ul - (for [error errors] - [:li {:key error} error])]))) +(def formerrors + (-> (l/in [:errors :profile/password]) + (l/focus-atom st/state))) + +(def assign-field-value + (partial udf/assign-field-value :profile/password)) (defn password-form-render [own] - (let [local (:rum/local own) - form (:form @local) - errors (:errors @local) - valid? true #_(nil? invalid-reason)] + (let [form (rum/react formdata) + errors (rum/react formerrors) + valid? (sc/valid? form udu/update-password-schema)] + (println valid?) (letfn [(on-field-change [field event] (let [value (dom/event->value event)] - (swap! local assoc-in [:form field] value))) + (rs/emit! (assign-field-value field value)))) (on-submit [event] - (when-let [data (form/validate! local password-form-schema)] - (let [params {:password (:password-1 form) - :old-password (:old-password form)}] - (rs/emit! (udu/update-password params)))))] + (rs/emit! (udu/update-password form)))] (html [:form.password-form [:span.user-settings-label "Change password"] [:input.input-text {:type "password" - :class (form/error-class local :old-password) + :class (forms/error-class errors :old-password) :value (:old-password form "") :on-change (partial on-field-change :old-password) :placeholder "Old password"}] - (form/input-error local :old-password) + (forms/input-error errors :old-password) [:input.input-text {:type "password" - :class (form/error-class local :password-1) + :class (forms/error-class errors :password-1) :value (:password-1 form "") :on-change (partial on-field-change :password-1) :placeholder "New password"}] - (form/input-error local :password-1) + (forms/input-error errors :password-1) [:input.input-text {:type "password" - :class (form/error-class local :password-2) + :class (forms/error-class errors :password-2) :value (:password-2 form "") :on-change (partial on-field-change :password-2) :placeholder "Confirm password"}] - (form/input-error local :password-2) + (forms/input-error errors :password-2) [:input.btn-primary {:type "button" :class (when-not valid? "btn-disabled") @@ -86,7 +83,7 @@ (mx/component {:render password-form-render :name "password-form" - :mixins [mx/static (mx/local)]})) + :mixins [mx/static (mx/local) rum/reactive]})) ;; --- Password Page From 5624adcedff3ba56fa24a17b46b530be78fd562b Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 12 Apr 2016 22:23:16 +0300 Subject: [PATCH 08/12] Remove some validations. --- src/uxbox/data/auth.cljs | 5 --- src/uxbox/data/dashboard.cljs | 23 +--------- src/uxbox/data/pages.cljs | 13 +++--- src/uxbox/data/projects.cljs | 41 ++++++++++++------ src/uxbox/data/shapes.cljs | 63 --------------------------- src/uxbox/data/users.cljs | 1 - src/uxbox/schema.cljs | 6 ++- src/uxbox/ui/dashboard/colors.cljs | 69 +++++++++++++++--------------- 8 files changed, 75 insertions(+), 146 deletions(-) diff --git a/src/uxbox/data/auth.cljs b/src/uxbox/data/auth.cljs index 9b70b6437d..664b275d13 100644 --- a/src/uxbox/data/auth.cljs +++ b/src/uxbox/data/auth.cljs @@ -64,13 +64,8 @@ (dp/fetch-projects) (udu/fetch-profile)))))))) -(def ^:const ^:private +login-schema+ - {:username [sc/required sc/string] - :password [sc/required sc/string]}) - (defn login [params] - (sc/validate! +login-schema+ params) (map->Login params)) ;; --- Logout diff --git a/src/uxbox/data/dashboard.cljs b/src/uxbox/data/dashboard.cljs index 6ca4034c35..4a0e888726 100644 --- a/src/uxbox/data/dashboard.cljs +++ b/src/uxbox/data/dashboard.cljs @@ -12,22 +12,7 @@ [uxbox.schema :as sc] [uxbox.repo :as rp])) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Schemas -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(def ^:static +color-replace-schema+ - {:id [sc/required sc/uuid] - :from [sc/color] - :to [sc/required sc/color]}) - -(def ^:static +remove-color-schema+ - {:id [sc/required sc/uuid] - :color [sc/required sc/color]}) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Helpers -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; --- Helpers (defn assoc-page "A reduce function for assoc the page @@ -36,9 +21,7 @@ (let [uuid (:id page)] (update-in state [:pages-by-id] assoc uuid page))) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Events -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; --- Events (defn merge-if-not-exists [map & maps] @@ -139,7 +122,6 @@ (defn replace-color "Add or replace color in a collection." [{:keys [id from to] :as params}] - (sc/validate! +color-replace-schema+ params) (reify rs/UpdateEvent (-apply-update [_ state] @@ -153,7 +135,6 @@ (defn remove-color "Remove color in a collection." [{:keys [id color] :as params}] - (sc/validate! +remove-color-schema+ params) (reify rs/UpdateEvent (-apply-update [_ state] diff --git a/src/uxbox/data/pages.cljs b/src/uxbox/data/pages.cljs index 6495445526..0ec5dcc6d6 100644 --- a/src/uxbox/data/pages.cljs +++ b/src/uxbox/data/pages.cljs @@ -74,7 +74,7 @@ (rx/mapcat on-created) (rx/catch on-failed)))))) -(def ^:static +create-page-schema+ +(def ^:private create-page-schema {:name [sc/required sc/string] :layout [sc/required sc/string] :width [sc/required sc/integer] @@ -83,8 +83,8 @@ (defn create-page [data] - (sc/validate! +create-page-schema+ data) - (map->CreatePage data)) + (-> (sc/validate! data create-page-schema) + (map->CreatePage))) ;; --- Sync Page @@ -171,7 +171,7 @@ (rx/map on-success) (rx/catch on-failure))))) -(def ^:const +update-page-schema+ +(def ^:private update-page-schema {:name [sc/required sc/string] :width [sc/required sc/integer] :height [sc/required sc/integer] @@ -179,8 +179,9 @@ (defn update-page-metadata [data] - (sc/validate! +update-page-schema+ data) - (map->UpdatePageMetadata (dissoc data :data))) + (-> (sc/validate! data update-page-schema) + (dissoc :data) + (map->UpdatePageMetadata))) ;; --- Delete Page (by id) diff --git a/src/uxbox/data/projects.cljs b/src/uxbox/data/projects.cljs index b1e9e0dd2d..38d9112149 100644 --- a/src/uxbox/data/projects.cljs +++ b/src/uxbox/data/projects.cljs @@ -70,33 +70,48 @@ [] (FetchProjects.)) +;; --- Project Created + +(defrecord ProjectCreated [project] + rs/UpdateEvent + (-apply-update [_ state] + (stpr/assoc-project state project))) + +(defn project-created + [data] + (ProjectCreated. data)) + ;; --- Create Project (defrecord CreateProject [name width height layout] rs/WatchEvent (-apply-watch [this state s] - (letfn [(on-success [project] - (rx/of (rs/swap #(stpr/assoc-project % project)) - (udp/create-page (assoc (into {} this) - :project (:id project) - :name "Page 1" - :data nil)))) + (letfn [(on-success [{project :payload}] + (rx/of + (project-created project) + (udp/create-page {:width width + :height height + :layout layout + :project (:id project) + :name "Page 1" + :data nil}))) (on-failure [err] - (uum/error (tr "errors.create-project")))] + (uum/error (tr "errors.create-project")) + (rx/empty))] (->> (rp/req :create/project {:name name}) - (rx/mapcat on-success) - (rx/catch on-failure))))) + (rx/catch on-failure) + (rx/mapcat on-success))))) -(def ^:static +project-schema+ +(def ^:private create-project-schema {:name [sc/required sc/string] :width [sc/required sc/integer] :height [sc/required sc/integer] :layout [sc/required sc/string]}) (defn create-project - [{:keys [name width height layout] :as data}] - (sc/validate! +project-schema+ data) - (map->CreateProject data)) + [params] + (-> (sc/validate! params create-project-schema) + (map->CreateProject))) ;; --- Delete Project (by id) diff --git a/src/uxbox/data/shapes.cljs b/src/uxbox/data/shapes.cljs index 24a522cb53..c7de4ab5e0 100644 --- a/src/uxbox/data/shapes.cljs +++ b/src/uxbox/data/shapes.cljs @@ -19,63 +19,9 @@ [uxbox.util.geom.point :as gpt] [uxbox.util.data :refer (index-of)])) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Schemas -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(def ^:static +shape-schema+ - {:x [sc/integer] - :y [sc/integer] - :width [sc/integer] - :height [sc/integer] - :type [sc/required sc/shape-type]}) - -(def ^:static +shape-size-schema+ - {:width [sc/integer] - :height [sc/integer] - :lock [sc/boolean]}) - -(def ^:static +shape-fill-attrs-schema+ - {:color [sc/color] - :opacity [sc/number]}) - -(def ^:static +shape-stroke-attrs-schema+ - {:color [sc/color] - :width [sc/integer] - :type [sc/keyword] - :opacity [sc/number]}) - -(def ^:static +shape-line-attrs-schema+ - {:x1 [sc/integer] - :y1 [sc/integer] - :x2 [sc/integer] - :y2 [sc/integer]}) - -(def ^:static +shape-font-attrs-schema+ - {:family [sc/string] - :style [sc/string] - :weight [sc/string] - :align [sc/string] - :size [sc/number] - :letter-spacing [sc/number] - :line-height [sc/number]}) - -(def ^:static +shape-radius-attrs-schema+ - {:rx [sc/integer] - :ry [sc/integer]}) - -(def ^:static +shape-position-schema+ - {:x [sc/integer] - :y [sc/integer]}) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Events (explicit) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - (defn add-shape "Create and add shape to the current selected page." [shape] - (sc/validate! +shape-schema+ shape) (reify udp/IPageUpdate rs/UpdateEvent @@ -113,7 +59,6 @@ (defn update-line-attrs [sid {:keys [x1 y1 x2 y2] :as opts}] - (sc/validate! +shape-line-attrs-schema+ opts) (reify udp/IPageUpdate rs/UpdateEvent @@ -144,7 +89,6 @@ WARN: only works with shapes that works with height and width such are ::rect" [sid {:keys [width height] :as opts}] - (sc/validate! +shape-size-schema+ opts) (reify udp/IPageUpdate rs/UpdateEvent @@ -164,7 +108,6 @@ (defn update-position "Update the start position coordenate of the shape." [sid {:keys [x y] :as opts}] - (sc/validate! +shape-position-schema+ opts) (reify rs/UpdateEvent (-apply-update [_ state] @@ -182,7 +125,6 @@ (defn update-fill-attrs [sid {:keys [color opacity] :as opts}] - (sc/validate! +shape-fill-attrs-schema+ opts) (reify udp/IPageUpdate rs/UpdateEvent @@ -195,7 +137,6 @@ (defn update-font-attrs [sid {:keys [family style weight size align letter-spacing line-height] :as opts}] - (sc/validate! +shape-font-attrs-schema+ opts) (reify udp/IPageUpdate rs/UpdateEvent @@ -212,7 +153,6 @@ (defn update-stroke-attrs [sid {:keys [color opacity type width] :as opts}] - (sc/validate! +shape-stroke-attrs-schema+ opts) (reify udp/IPageUpdate rs/UpdateEvent @@ -226,7 +166,6 @@ (defn update-radius-attrs [sid {:keys [rx ry] :as opts}] - (sc/validate! +shape-radius-attrs-schema+ opts) (reify udp/IPageUpdate rs/UpdateEvent @@ -463,7 +402,6 @@ "Update the fill related attributed on selected shapes." [opts] - (sc/validate! +shape-fill-attrs-schema+ opts) (reify rs/WatchEvent (-apply-watch [_ state s] @@ -476,7 +414,6 @@ "Update the fill related attributed on selected shapes." [opts] - (sc/validate! +shape-stroke-attrs-schema+ opts) (reify rs/WatchEvent (-apply-watch [_ state s] diff --git a/src/uxbox/data/users.cljs b/src/uxbox/data/users.cljs index b3ca6f604a..5c0f63c567 100644 --- a/src/uxbox/data/users.cljs +++ b/src/uxbox/data/users.cljs @@ -94,7 +94,6 @@ (defn update-password [data] (let [[errors data] (sc/validate data update-password-schema)] - (println errors) (if errors (forms/assign-errors :profile/password errors) (UpdatePassword. data)))) diff --git a/src/uxbox/schema.cljs b/src/uxbox/schema.cljs index ef8d6f3b2a..183169dc34 100644 --- a/src/uxbox/schema.cljs +++ b/src/uxbox/schema.cljs @@ -77,8 +77,10 @@ (defn validate! [data schema] - (when-let [errors (first (validate schema data))] - (throw (ex-info "Invalid data" errors)))) + (let [[errors data] (validate data schema)] + (if errors + (throw (ex-info "Invalid data" errors)) + data))) (defn valid? [data schema] diff --git a/src/uxbox/ui/dashboard/colors.cljs b/src/uxbox/ui/dashboard/colors.cljs index 7cde68edd4..35e9881d01 100644 --- a/src/uxbox/ui/dashboard/colors.cljs +++ b/src/uxbox/ui/dashboard/colors.cljs @@ -187,44 +187,43 @@ ;; --- Colors Create / Edit Lightbox -(def ^:const ^:private +color-form-schema+ - {:hex [sc/required sc/color]}) - (defn- color-lightbox-render [own {:keys [coll color]}] - (let [local (:rum/local own)] - (letfn [(submit [e] - (if-let [errors (sc/validate +color-form-schema+ @local)] - (swap! local assoc :errors errors) - (let [params {:id (:id coll) :from color - :to (:hex @local)}] - (rs/emit! (dd/replace-color params)) - (lightbox/close!)))) - (on-change [e] - (let [value (str/trim (dom/event->value e))] - (swap! local assoc :hex value)))] - (html - [:div.lightbox-body - [:h3 "New color"] - [:form - [:div.row-flex - [:input#color-hex.input-text - {:placeholder "#" - :class (form/error-class local :hex) - :on-change on-change - :value (or (:hex @local) color "") - :type "text"}]] - [:div.row-flex.center.color-picker-default - (colorpicker - :value (or (:hex @local) color "#00ccff") - :on-change #(swap! local assoc :hex %))] + (html + [:p "TODO"])) + ;; (let [local (:rum/local own)] + ;; (letfn [(submit [e] + ;; (if-let [errors (sc/validate +color-form-schema+ @local)] + ;; (swap! local assoc :errors errors) + ;; (let [params {:id (:id coll) :from color + ;; :to (:hex @local)}] + ;; (rs/emit! (dd/replace-color params)) + ;; (lightbox/close!)))) + ;; (on-change [e] + ;; (let [value (str/trim (dom/event->value e))] + ;; (swap! local assoc :hex value)))] + ;; (html + ;; [:div.lightbox-body + ;; [:h3 "New color"] + ;; [:form + ;; [:div.row-flex + ;; [:input#color-hex.input-text + ;; {:placeholder "#" + ;; :class (form/error-class local :hex) + ;; :on-change on-change + ;; :value (or (:hex @local) color "") + ;; :type "text"}]] + ;; [:div.row-flex.center.color-picker-default + ;; (colorpicker + ;; :value (or (:hex @local) color "#00ccff") + ;; :on-change #(swap! local assoc :hex %))] - [:input#project-btn.btn-primary - {:value "+ Add color" - :on-click submit - :type "button"}]] - [:a.close {:on-click #(lightbox/close!)} - i/close]])))) + ;; [:input#project-btn.btn-primary + ;; {:value "+ Add color" + ;; :on-click submit + ;; :type "button"}]] + ;; [:a.close {:on-click #(lightbox/close!)} + ;; i/close]])))) (def color-lightbox (mx/component From 58444fd363a934d2295379bdb8d219c4e9ca8e30 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 12 Apr 2016 22:23:49 +0300 Subject: [PATCH 09/12] Fix wrong class reference on forms events. --- src/uxbox/data/forms.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uxbox/data/forms.cljs b/src/uxbox/data/forms.cljs index 78d527f1c5..cc7c6b8a91 100644 --- a/src/uxbox/data/forms.cljs +++ b/src/uxbox/data/forms.cljs @@ -24,7 +24,7 @@ (defn assign-errors ([type] (assign-errors type nil)) ([type errors] - (FormErrors. type errors))) + (AssignErrors. type errors))) ;; --- Assign Field Value From a264cea1d6f456a642e19140569b556a74e24dcb Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 12 Apr 2016 22:31:12 +0300 Subject: [PATCH 10/12] More improvements to validation api. --- src/uxbox/data/pages.cljs | 9 ++++++--- src/uxbox/schema.cljs | 23 ++++++++++++++--------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/uxbox/data/pages.cljs b/src/uxbox/data/pages.cljs index 0ec5dcc6d6..acae8ebdb5 100644 --- a/src/uxbox/data/pages.cljs +++ b/src/uxbox/data/pages.cljs @@ -172,15 +172,18 @@ (rx/catch on-failure))))) (def ^:private update-page-schema - {:name [sc/required sc/string] + {:id [sc/required] + :project [sc/required] + :version [sc/required] + :name [sc/required sc/string] :width [sc/required sc/integer] :height [sc/required sc/integer] :layout [sc/required sc/string]}) (defn update-page-metadata [data] - (-> (sc/validate! data update-page-schema) - (dissoc :data) + (-> (sc/validate! data update-page-schema {:strip false}) + (dissoc data :data) (map->UpdatePageMetadata))) ;; --- Delete Page (by id) diff --git a/src/uxbox/schema.cljs b/src/uxbox/schema.cljs index 183169dc34..c2674f3834 100644 --- a/src/uxbox/schema.cljs +++ b/src/uxbox/schema.cljs @@ -70,17 +70,22 @@ :validate #(shape? %)}) (defn validate - [data schema] - (let [opts {:strip true - :translate tr}] - (st/validate data schema opts))) + ([data schema] + (validate data schema nil)) + ([data schema opts] + (let [opts (merge {:strip true + :translate tr} + opts)] + (st/validate data schema opts)))) (defn validate! - [data schema] - (let [[errors data] (validate data schema)] - (if errors - (throw (ex-info "Invalid data" errors)) - data))) + ([data schema] + (validate! data schema nil)) + ([data schema opts] + (let [[errors data] (validate data schema opts)] + (if errors + (throw (ex-info "Invalid data" errors)) + data)))) (defn valid? [data schema] From 63e5e68fc64e6ce995528f72a0f97b9ebc10f056 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 12 Apr 2016 22:56:13 +0300 Subject: [PATCH 11/12] Add some annotations on locales api. --- src/uxbox/locales.cljs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/uxbox/locales.cljs b/src/uxbox/locales.cljs index 90658ab2a8..630b624ae3 100644 --- a/src/uxbox/locales.cljs +++ b/src/uxbox/locales.cljs @@ -17,6 +17,9 @@ (defonce +locale+ (get local-storage ::locale :en)) +;; A marker type that is used just for mark +;; a parameter that reprsentes the counter. + (deftype C [val] IDeref (-deref [o] val)) @@ -29,6 +32,8 @@ [r] (instance? C r)) +;; A main public api for translate strings. + (defn tr "Translate the string." ([t] From c314a4cde9f83fcdf2b8c4eeed119c313bbaf1cd Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 12 Apr 2016 22:57:00 +0300 Subject: [PATCH 12/12] Minor change on translation approach on form errors. --- src/uxbox/data/users.cljs | 10 +++++++--- src/uxbox/locales/en.cljs | 3 +++ src/uxbox/schema.cljs | 3 +-- src/uxbox/ui/forms.cljs | 3 ++- src/uxbox/ui/settings/password.cljs | 1 - 5 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/uxbox/data/users.cljs b/src/uxbox/data/users.cljs index 5c0f63c567..67f2a94369 100644 --- a/src/uxbox/data/users.cljs +++ b/src/uxbox/data/users.cljs @@ -76,9 +76,13 @@ (defrecord UpdatePassword [data] rs/WatchEvent (-apply-watch [_ state s] - (letfn [(on-error [err] - (uum/error (tr "errors.profile.update-password") {:timeout 3000}) - (rx/empty))] + (letfn [(on-error [{payload :payload :as data}] + (if (= (:type payload) :form/validation) + (rx/of + (forms/assign-errors :profile/password (:payload payload))) + (do + (uum/error (tr "errors.profile.update-password") {:timeout 3000}) + (rx/empty))))] (let [params {:old-password (:old-password data) :password (:password-1 data)}] (->> (rp/req :update/password params) diff --git a/src/uxbox/locales/en.cljs b/src/uxbox/locales/en.cljs index 5363f59245..7f4bf4d949 100644 --- a/src/uxbox/locales/en.cljs +++ b/src/uxbox/locales/en.cljs @@ -40,6 +40,9 @@ "profile.password-saved" "Password saved successfully!" "history.alert-message" "You are seeng version %s" + + "errors.api.form.old-password-not-match" "Incorrect old password" + "errors.form.required" "This field is mandatory" "errors.form.string" "Should be string" "errors.form.number" "Invalid number" diff --git a/src/uxbox/schema.cljs b/src/uxbox/schema.cljs index c2674f3834..1aba210cfa 100644 --- a/src/uxbox/schema.cljs +++ b/src/uxbox/schema.cljs @@ -73,8 +73,7 @@ ([data schema] (validate data schema nil)) ([data schema opts] - (let [opts (merge {:strip true - :translate tr} + (let [opts (merge {:strip true} opts)] (st/validate data schema opts)))) diff --git a/src/uxbox/ui/forms.cljs b/src/uxbox/ui/forms.cljs index 78ec63fc8f..a6ec2cffd2 100644 --- a/src/uxbox/ui/forms.cljs +++ b/src/uxbox/ui/forms.cljs @@ -1,5 +1,6 @@ (ns uxbox.ui.forms (:require [sablono.core :refer-macros [html]] + [uxbox.locales :refer (tr)] [uxbox.schema :as sc])) (defn input-error @@ -8,7 +9,7 @@ (html [:ul.form-errors (for [error errors] - [:li {:key error} error])]))) + [:li {:key error} (tr error)])]))) (defn error-class [errors field] diff --git a/src/uxbox/ui/settings/password.cljs b/src/uxbox/ui/settings/password.cljs index 57b786eac5..8fb06436c7 100644 --- a/src/uxbox/ui/settings/password.cljs +++ b/src/uxbox/ui/settings/password.cljs @@ -42,7 +42,6 @@ (let [form (rum/react formdata) errors (rum/react formerrors) valid? (sc/valid? form udu/update-password-schema)] - (println valid?) (letfn [(on-field-change [field event] (let [value (dom/event->value event)] (rs/emit! (assign-field-value field value))))