0
Fork 0
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:
Andrey Antukh 2016-04-11 23:40:40 +03:00
parent e509daaeef
commit e42b2ed7bf
No known key found for this signature in database
GPG key ID: 4DFEBCB8316A8B95
8 changed files with 118 additions and 72 deletions

40
src/uxbox/data/forms.cljs Normal file
View 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))

View file

@ -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))))

View file

@ -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)))

View file

@ -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]

View file

@ -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]

View file

@ -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
View 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"))

View file

@ -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