mirror of
https://github.com/penpot/penpot.git
synced 2025-02-15 11:38:24 -05:00
Overhaul of form data and errors handling.
This commit is contained in:
parent
e509daaeef
commit
e42b2ed7bf
8 changed files with 118 additions and 72 deletions
40
src/uxbox/data/forms.cljs
Normal file
40
src/uxbox/data/forms.cljs
Normal file
|
@ -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 <niwi@niwi.nz>
|
||||
|
||||
(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))
|
||||
|
||||
|
|
@ -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))))
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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"))
|
16
src/uxbox/ui/forms.cljs
Normal file
16
src/uxbox/ui/forms.cljs
Normal file
|
@ -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"))
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue