mirror of
https://github.com/penpot/penpot.git
synced 2025-05-31 13:06:12 +02:00
🚧 More work on better forms and data validation.
This commit is contained in:
parent
04a5038ff4
commit
689cc5f3e7
21 changed files with 641 additions and 618 deletions
|
@ -7,10 +7,10 @@
|
|||
(ns uxbox.main.ui.auth
|
||||
(:require [uxbox.main.ui.auth.login :as login]
|
||||
[uxbox.main.ui.auth.register :as register]
|
||||
[uxbox.main.ui.auth.recovery-request :as recovery-request]
|
||||
[uxbox.main.ui.auth.recovery :as recovery]))
|
||||
#_[uxbox.main.ui.auth.recovery-request :as recovery-request]
|
||||
#_[uxbox.main.ui.auth.recovery :as recovery]))
|
||||
|
||||
(def login-page login/login-page)
|
||||
(def register-page register/register-page)
|
||||
(def recovery-page recovery/recovery-page)
|
||||
(def recovery-request-page recovery-request/recovery-request-page)
|
||||
;; (def recovery-page recovery/recovery-page)
|
||||
;; (def recovery-request-page recovery-request/recovery-request-page)
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
(ns uxbox.main.ui.auth.login
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[struct.core :as s]
|
||||
[struct.alpha :as s]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.config :as cfg]
|
||||
[uxbox.main.data.auth :as da]
|
||||
|
@ -19,9 +19,9 @@
|
|||
[uxbox.util.i18n :refer [tr]]
|
||||
[uxbox.util.router :as rt]))
|
||||
|
||||
(s/defs login-form-spec
|
||||
{:username [fm/required fm/string]
|
||||
:password [fm/required fm/string]})
|
||||
(s/defs ::login-form
|
||||
(s/dict :username (s/&& ::s/string ::fm/not-empty-string)
|
||||
:password (s/&& ::s/string ::fm/not-empty-string)))
|
||||
|
||||
(defn- on-submit
|
||||
[event form]
|
||||
|
@ -42,7 +42,7 @@
|
|||
|
||||
(mf/defc login-form
|
||||
[]
|
||||
(let [{:keys [data] :as form} (fm/use-form {:initial {} :spec login-form-spec})]
|
||||
(let [{:keys [data] :as form} (fm/use-form ::login-form {})]
|
||||
[:form {:on-submit #(on-submit % form)}
|
||||
[:div.login-content
|
||||
(when cfg/isdemo
|
||||
|
@ -84,6 +84,6 @@
|
|||
[]
|
||||
[:div.login
|
||||
[:div.login-body
|
||||
(messages-widget)
|
||||
[:& messages-widget]
|
||||
[:a i/logo]
|
||||
[:& login-form]]])
|
||||
|
|
|
@ -21,62 +21,62 @@
|
|||
[uxbox.util.i18n :refer (tr)]
|
||||
[uxbox.util.router :as rt]))
|
||||
|
||||
(def form-data (fm/focus-data :recovery st/state))
|
||||
(def form-errors (fm/focus-errors :recovery st/state))
|
||||
;; (def form-data (fm/focus-data :recovery st/state))
|
||||
;; (def form-errors (fm/focus-errors :recovery st/state))
|
||||
|
||||
(def assoc-value (partial fm/assoc-value :recovery))
|
||||
(def assoc-errors (partial fm/assoc-errors :recovery))
|
||||
(def clear-form (partial fm/clear-form :recovery))
|
||||
;; (def assoc-value (partial fm/assoc-value :recovery))
|
||||
;; (def assoc-errors (partial fm/assoc-errors :recovery))
|
||||
;; (def clear-form (partial fm/clear-form :recovery))
|
||||
|
||||
;; --- Recovery Form
|
||||
;; ;; --- Recovery Form
|
||||
|
||||
(s/def ::password ::fm/non-empty-string)
|
||||
(s/def ::recovery-form
|
||||
(s/keys :req-un [::password]))
|
||||
;; (s/def ::password ::fm/non-empty-string)
|
||||
;; (s/def ::recovery-form
|
||||
;; (s/keys :req-un [::password]))
|
||||
|
||||
(mx/defc recovery-form
|
||||
{:mixins [mx/static mx/reactive]}
|
||||
[token]
|
||||
(let [data (merge (mx/react form-data) {:token token})
|
||||
valid? (fm/valid? ::recovery-form data)]
|
||||
(letfn [(on-change [field event]
|
||||
(let [value (dom/event->value event)]
|
||||
(st/emit! (assoc-value field value))))
|
||||
(on-submit [event]
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (uda/recovery data)
|
||||
(clear-form)))]
|
||||
[:form {:on-submit on-submit}
|
||||
[:div.login-content
|
||||
[:input.input-text
|
||||
{:name "password"
|
||||
:value (:password data "")
|
||||
:on-change (partial on-change :password)
|
||||
:placeholder (tr "recover.password.placeholder")
|
||||
:type "password"}]
|
||||
[:input.btn-primary
|
||||
{:name "login"
|
||||
:class (when-not valid? "btn-disabled")
|
||||
:disabled (not valid?)
|
||||
:value (tr "recover.recover-password")
|
||||
:type "submit"}]
|
||||
[:div.login-links
|
||||
[:a {:on-click #(st/emit! (rt/navigate :auth/login))} (tr "recover.go-back")]]]])))
|
||||
;; (mx/defc recovery-form
|
||||
;; {:mixins [mx/static mx/reactive]}
|
||||
;; [token]
|
||||
;; (let [data (merge (mx/react form-data) {:token token})
|
||||
;; valid? (fm/valid? ::recovery-form data)]
|
||||
;; (letfn [(on-change [field event]
|
||||
;; (let [value (dom/event->value event)]
|
||||
;; (st/emit! (assoc-value field value))))
|
||||
;; (on-submit [event]
|
||||
;; (dom/prevent-default event)
|
||||
;; (st/emit! (uda/recovery data)
|
||||
;; (clear-form)))]
|
||||
;; [:form {:on-submit on-submit}
|
||||
;; [:div.login-content
|
||||
;; [:input.input-text
|
||||
;; {:name "password"
|
||||
;; :value (:password data "")
|
||||
;; :on-change (partial on-change :password)
|
||||
;; :placeholder (tr "recover.password.placeholder")
|
||||
;; :type "password"}]
|
||||
;; [:input.btn-primary
|
||||
;; {:name "login"
|
||||
;; :class (when-not valid? "btn-disabled")
|
||||
;; :disabled (not valid?)
|
||||
;; :value (tr "recover.recover-password")
|
||||
;; :type "submit"}]
|
||||
;; [:div.login-links
|
||||
;; [:a {:on-click #(st/emit! (rt/navigate :auth/login))} (tr "recover.go-back")]]]])))
|
||||
|
||||
;; --- Recovery Page
|
||||
;; ;; --- Recovery Page
|
||||
|
||||
(defn- recovery-page-init
|
||||
[own]
|
||||
(let [[token] (::mx/args own)]
|
||||
(st/emit! (uda/validate-recovery-token token))
|
||||
own))
|
||||
;; (defn- recovery-page-init
|
||||
;; [own]
|
||||
;; (let [[token] (::mx/args own)]
|
||||
;; (st/emit! (uda/validate-recovery-token token))
|
||||
;; own))
|
||||
|
||||
(mx/defc recovery-page
|
||||
{:mixins [mx/static (fm/clear-mixin st/store :recovery)]
|
||||
:init recovery-page-init}
|
||||
[token]
|
||||
[:div.login
|
||||
[:div.login-body
|
||||
(messages-widget)
|
||||
[:a i/logo]
|
||||
(recovery-form token)]])
|
||||
;; (mx/defc recovery-page
|
||||
;; {:mixins [mx/static (fm/clear-mixin st/store :recovery)]
|
||||
;; :init recovery-page-init}
|
||||
;; [token]
|
||||
;; [:div.login
|
||||
;; [:div.login-body
|
||||
;; (messages-widget)
|
||||
;; [:a i/logo]
|
||||
;; (recovery-form token)]])
|
||||
|
|
|
@ -20,52 +20,52 @@
|
|||
[rumext.core :as mx :include-macros true]
|
||||
[uxbox.util.router :as rt]))
|
||||
|
||||
(def form-data (fm/focus-data :recovery-request st/state))
|
||||
(def form-errors (fm/focus-errors :recovery-request st/state))
|
||||
;; (def form-data (fm/focus-data :recovery-request st/state))
|
||||
;; (def form-errors (fm/focus-errors :recovery-request st/state))
|
||||
|
||||
(def assoc-value (partial fm/assoc-value :profile-password))
|
||||
(def assoc-errors (partial fm/assoc-errors :profile-password))
|
||||
(def clear-form (partial fm/clear-form :profile-password))
|
||||
;; (def assoc-value (partial fm/assoc-value :profile-password))
|
||||
;; (def assoc-errors (partial fm/assoc-errors :profile-password))
|
||||
;; (def clear-form (partial fm/clear-form :profile-password))
|
||||
|
||||
(s/def ::username ::fm/non-empty-string)
|
||||
(s/def ::recovery-request-form (s/keys :req-un [::username]))
|
||||
;; (s/def ::username ::fm/non-empty-string)
|
||||
;; (s/def ::recovery-request-form (s/keys :req-un [::username]))
|
||||
|
||||
(mx/defc recovery-request-form
|
||||
{:mixins [mx/static mx/reactive]}
|
||||
[]
|
||||
(let [data (mx/react form-data)
|
||||
valid? (fm/valid? ::recovery-request-form data)]
|
||||
(letfn [(on-change [event]
|
||||
(let [value (dom/event->value event)]
|
||||
(st/emit! (assoc-value :username value))))
|
||||
(on-submit [event]
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (uda/recovery-request data)
|
||||
(clear-form)))]
|
||||
[:form {:on-submit on-submit}
|
||||
[:div.login-content
|
||||
[:input.input-text
|
||||
{:name "username"
|
||||
:value (:username data "")
|
||||
:on-change on-change
|
||||
:placeholder (tr "recovery-request.username-or-email.placeholder")
|
||||
:type "text"}]
|
||||
[:input.btn-primary
|
||||
{:name "login"
|
||||
:class (when-not valid? "btn-disabled")
|
||||
:disabled (not valid?)
|
||||
:value (tr "recovery-request.recover-password")
|
||||
:type "submit"}]
|
||||
[:div.login-links
|
||||
[:a {:on-click #(st/emit! (rt/navigate :auth/login))} (tr "recovery-request.go-back")]]]])))
|
||||
;; (mx/defc recovery-request-form
|
||||
;; {:mixins [mx/static mx/reactive]}
|
||||
;; []
|
||||
;; (let [data (mx/react form-data)
|
||||
;; valid? (fm/valid? ::recovery-request-form data)]
|
||||
;; (letfn [(on-change [event]
|
||||
;; (let [value (dom/event->value event)]
|
||||
;; (st/emit! (assoc-value :username value))))
|
||||
;; (on-submit [event]
|
||||
;; (dom/prevent-default event)
|
||||
;; (st/emit! (uda/recovery-request data)
|
||||
;; (clear-form)))]
|
||||
;; [:form {:on-submit on-submit}
|
||||
;; [:div.login-content
|
||||
;; [:input.input-text
|
||||
;; {:name "username"
|
||||
;; :value (:username data "")
|
||||
;; :on-change on-change
|
||||
;; :placeholder (tr "recovery-request.username-or-email.placeholder")
|
||||
;; :type "text"}]
|
||||
;; [:input.btn-primary
|
||||
;; {:name "login"
|
||||
;; :class (when-not valid? "btn-disabled")
|
||||
;; :disabled (not valid?)
|
||||
;; :value (tr "recovery-request.recover-password")
|
||||
;; :type "submit"}]
|
||||
;; [:div.login-links
|
||||
;; [:a {:on-click #(st/emit! (rt/navigate :auth/login))} (tr "recovery-request.go-back")]]]])))
|
||||
|
||||
;; --- Recovery Request Page
|
||||
;; ;; --- Recovery Request Page
|
||||
|
||||
(mx/defc recovery-request-page
|
||||
{:mixins [mx/static (fm/clear-mixin st/store :recovery-request)]}
|
||||
[]
|
||||
[:div.login
|
||||
[:div.login-body
|
||||
(messages-widget)
|
||||
[:a i/logo]
|
||||
(recovery-request-form)]])
|
||||
;; (mx/defc recovery-request-page
|
||||
;; {:mixins [mx/static (fm/clear-mixin st/store :recovery-request)]}
|
||||
;; []
|
||||
;; [:div.login
|
||||
;; [:div.login-body
|
||||
;; (messages-widget)
|
||||
;; [:a i/logo]
|
||||
;; (recovery-request-form)]])
|
||||
|
|
|
@ -6,118 +6,131 @@
|
|||
;; Copyright (c) 2015-2017 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
|
||||
(ns uxbox.main.ui.auth.register
|
||||
(:require [cljs.spec.alpha :as s :include-macros true]
|
||||
[lentes.core :as l]
|
||||
[cuerdas.core :as str]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.data.auth :as uda]
|
||||
[uxbox.main.ui.messages :refer [messages-widget]]
|
||||
[uxbox.main.ui.navigation :as nav]
|
||||
[uxbox.util.i18n :refer (tr)]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.forms :as fm]
|
||||
[rumext.core :as mx :include-macros true]
|
||||
[uxbox.util.router :as rt]))
|
||||
(:require
|
||||
[cuerdas.core :as str]
|
||||
[lentes.core :as l]
|
||||
[rumext.alpha :as mf]
|
||||
[struct.alpha :as s]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.data.auth :as uda]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.ui.messages :refer [messages-widget]]
|
||||
[uxbox.main.ui.navigation :as nav]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.forms :as fm]
|
||||
[uxbox.util.i18n :refer [tr]]
|
||||
[uxbox.util.router :as rt]))
|
||||
|
||||
(def form-data (fm/focus-data :register st/state))
|
||||
(def form-errors (fm/focus-errors :register st/state))
|
||||
(s/defs ::register-form
|
||||
(s/dict :username (s/&& ::s/string ::fm/not-empty-string)
|
||||
:fullname (s/&& ::s/string ::fm/not-empty-string)
|
||||
:password (s/&& ::s/string ::fm/not-empty-string)
|
||||
:email ::s/email))
|
||||
|
||||
(def assoc-value (partial fm/assoc-value :register))
|
||||
(def assoc-error (partial fm/assoc-error :register))
|
||||
(def clear-form (partial fm/clear-form :register))
|
||||
(defn- on-error
|
||||
[error form]
|
||||
(case (:code error)
|
||||
:uxbox.services.users/registration-disabled
|
||||
(st/emit! (tr "errors.api.form.registration-disabled"))
|
||||
|
||||
;; TODO: add better password validation
|
||||
:uxbox.services.users/email-already-exists
|
||||
(swap! form assoc-in [:errors :email]
|
||||
{:type ::api
|
||||
:message "errors.api.form.email-already-exists"})
|
||||
|
||||
(s/def ::username ::fm/non-empty-string)
|
||||
(s/def ::fullname ::fm/non-empty-string)
|
||||
(s/def ::password ::fm/non-empty-string)
|
||||
(s/def ::email ::fm/email)
|
||||
:uxbox.services.users/username-already-exists
|
||||
(swap! form assoc-in [:errors :username]
|
||||
{:type ::api
|
||||
:message "errors.api.form.username-already-exists"})))
|
||||
|
||||
(s/def ::register-form
|
||||
(s/keys :req-un [::username
|
||||
::fullname
|
||||
::email
|
||||
::password]))
|
||||
(defn- on-submit
|
||||
[event form]
|
||||
(dom/prevent-default event)
|
||||
(let [data (:clean-data form)
|
||||
on-error #(on-error % form)]
|
||||
(st/emit! (uda/register data on-error))))
|
||||
|
||||
(mx/defc register-form
|
||||
{:mixins [mx/static mx/reactive
|
||||
(fm/clear-mixin st/store :register)]}
|
||||
[]
|
||||
(let [data (mx/react form-data)
|
||||
errors (mx/react form-errors)
|
||||
valid? (fm/valid? ::register-form data)]
|
||||
(letfn [(on-change [field event]
|
||||
(let [value (dom/event->value event)]
|
||||
(st/emit! (assoc-value field value))))
|
||||
(on-error [{:keys [type code] :as payload}]
|
||||
(case code
|
||||
:uxbox.services.users/registration-disabled
|
||||
(st/emit! (tr "errors.api.form.registration-disabled"))
|
||||
:uxbox.services.users/email-already-exists
|
||||
(st/emit! (assoc-error :email (tr "errors.api.form.email-already-exists")))
|
||||
:uxbox.services.users/username-already-exists
|
||||
(st/emit! (assoc-error :username (tr "errors.api.form.username-already-exists")))))
|
||||
(on-submit [event]
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (uda/register data on-error)))]
|
||||
[:form {:on-submit on-submit}
|
||||
[:div.login-content
|
||||
[:input.input-text
|
||||
{:name "fullname"
|
||||
:tab-index "2"
|
||||
:value (:fullname data "")
|
||||
:on-change (partial on-change :fullname)
|
||||
:placeholder (tr "register.fullname.placeholder")
|
||||
:type "text"}]
|
||||
(fm/input-error errors :fullname)
|
||||
(mf/defc register-form
|
||||
[props]
|
||||
(let [{:keys [data] :as form} (fm/use-form ::register-form {})]
|
||||
(prn "register-form" form)
|
||||
[:form {:on-submit #(on-submit % form)}
|
||||
[:div.login-content
|
||||
[:input.input-text
|
||||
{:name "fullname"
|
||||
:tab-index "1"
|
||||
:value (:fullname data "")
|
||||
:class (fm/error-class form :fullname)
|
||||
:on-blur (fm/on-input-blur form :fullname)
|
||||
:on-change (fm/on-input-change form :fullname)
|
||||
:placeholder (tr "register.fullname.placeholder")
|
||||
:type "text"}]
|
||||
|
||||
[:input.input-text
|
||||
{:name "username"
|
||||
:tab-index "3"
|
||||
:value (:username data "")
|
||||
:on-change (partial on-change :username)
|
||||
:placeholder (tr "register.username.placeholder")
|
||||
:type "text"}]
|
||||
(fm/input-error errors :username)
|
||||
[:& fm/field-error {:form form
|
||||
:type #{::api}
|
||||
:field :fullname}]
|
||||
|
||||
[:input.input-text
|
||||
{:name "email"
|
||||
:tab-index "4"
|
||||
:ref "email"
|
||||
:value (:email data "")
|
||||
:on-change (partial on-change :email)
|
||||
:placeholder (tr "register.email.placeholder")
|
||||
:type "text"}]
|
||||
(fm/input-error errors :email)
|
||||
[:input.input-text
|
||||
{:type "text"
|
||||
:name "username"
|
||||
:tab-index "2"
|
||||
:class (fm/error-class form :username)
|
||||
:on-blur (fm/on-input-blur form :username)
|
||||
:on-change (fm/on-input-change form :username)
|
||||
:value (:username data "")
|
||||
:placeholder (tr "settings.profile.your-username")}]
|
||||
|
||||
[:input.input-text
|
||||
{:name "password"
|
||||
:tab-index "5"
|
||||
:ref "password"
|
||||
:value (:password data "")
|
||||
:on-change (partial on-change :password)
|
||||
:placeholder (tr "register.password.placeholder")
|
||||
:type "password"}]
|
||||
(fm/input-error errors :password)
|
||||
[:& fm/field-error {:form form
|
||||
:type #{::api}
|
||||
:field :username}]
|
||||
|
||||
[:input.btn-primary
|
||||
{:name "login"
|
||||
:tab-index "6"
|
||||
:class (when-not valid? "btn-disabled")
|
||||
:disabled (not valid?)
|
||||
:value (tr "register.get-started")
|
||||
:type "submit"}]
|
||||
[:div.login-links
|
||||
[:a {:on-click #(st/emit! (rt/navigate :auth/login))} (tr "register.already-have-account")]]]])))
|
||||
[:input.input-text
|
||||
{:type "email"
|
||||
:name "email"
|
||||
:tab-index "3"
|
||||
:class (fm/error-class form :email)
|
||||
:on-blur (fm/on-input-blur form :email)
|
||||
:on-change (fm/on-input-change form :email)
|
||||
:value (:email data "")
|
||||
:placeholder (tr "settings.profile.your-email")}]
|
||||
|
||||
[:& fm/field-error {:form form
|
||||
:type #{::api}
|
||||
:field :email}]
|
||||
|
||||
|
||||
[:input.input-text
|
||||
{:name "password"
|
||||
:tab-index "4"
|
||||
:value (:password data "")
|
||||
:class (fm/error-class form :password)
|
||||
:on-blur (fm/on-input-blur form :password)
|
||||
:on-change (fm/on-input-change form :password)
|
||||
:placeholder (tr "register.password.placeholder")
|
||||
:type "password"}]
|
||||
|
||||
[:& fm/field-error {:form form
|
||||
:type #{::api}
|
||||
:field :email}]
|
||||
|
||||
|
||||
[:input.btn-primary
|
||||
{:type "submit"
|
||||
:tab-index "5"
|
||||
:class (when-not (:valid form) "btn-disabled")
|
||||
:disabled (not (:valid form))
|
||||
:value (tr "register.get-started")}]
|
||||
|
||||
[:div.login-links
|
||||
[:a {:on-click #(st/emit! (rt/nav :auth/login))}
|
||||
(tr "register.already-have-account")]]]]))
|
||||
|
||||
;; --- Register Page
|
||||
|
||||
(mx/defc register-page
|
||||
{:mixins [mx/static]}
|
||||
[own]
|
||||
(mf/defc register-page
|
||||
[props]
|
||||
[:div.login
|
||||
[:div.login-body
|
||||
(messages-widget)
|
||||
[:a i/logo]
|
||||
(register-form)]])
|
||||
[:& register-form]]])
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
[{:keys [route] :as props}]
|
||||
(let [[section type id] (parse-route route)]
|
||||
[:main.dashboard-main
|
||||
(messages-widget)
|
||||
[:& messages-widget]
|
||||
[:& header {:section section}]
|
||||
(case section
|
||||
:dashboard/icons
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
(-> (l/key :projects)
|
||||
(l/derive st/state)))
|
||||
|
||||
|
||||
;; --- Helpers
|
||||
|
||||
(defn sort-projects-by
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
(ns uxbox.main.ui.dashboard.projects-forms
|
||||
(:require
|
||||
[cljs.spec.alpha :as s]
|
||||
[struct.alpha :as s]
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.data.projects :as udp]
|
||||
|
@ -17,10 +17,10 @@
|
|||
[uxbox.util.forms :as fm]
|
||||
[uxbox.util.i18n :as t :refer [tr]]))
|
||||
|
||||
(def project-form-spec
|
||||
{:name [fm/required fm/string]
|
||||
:width [fm/required fm/number-str]
|
||||
:height [fm/required fm/number-str]})
|
||||
(s/defs ::project-form
|
||||
(s/dict :name (s/&& ::s/string ::fm/not-empty-string)
|
||||
:width ::s/number-str
|
||||
:height ::s/number-str))
|
||||
|
||||
(def defaults
|
||||
{:name ""
|
||||
|
@ -44,13 +44,14 @@
|
|||
|
||||
(mf/defc create-project-form
|
||||
[props]
|
||||
(let [{:keys [data errors] :as form} (fm/use-form {:initial defaults :spec project-form-spec})]
|
||||
(let [{:keys [data] :as form} (fm/use-form ::project-form defaults)]
|
||||
[:form {:on-submit #(on-submit % form)}
|
||||
[:input.input-text
|
||||
{:placeholder "New project name"
|
||||
:type "text"
|
||||
:name "name"
|
||||
:value (:name data)
|
||||
:class (fm/error-class form :name)
|
||||
:on-blur (fm/on-input-blur form :name)
|
||||
:on-change (fm/on-input-change form :name)
|
||||
:auto-focus true}]
|
||||
|
@ -63,6 +64,7 @@
|
|||
:type "number"
|
||||
:min 0
|
||||
:max 5000
|
||||
:class (fm/error-class form :width)
|
||||
:on-blur (fm/on-input-blur form :width)
|
||||
:on-change (fm/on-input-change form :width)
|
||||
:value (:width data)}]]
|
||||
|
@ -75,6 +77,7 @@
|
|||
:name "height"
|
||||
:min 0
|
||||
:max 5000
|
||||
:class (fm/error-class form :height)
|
||||
:on-blur (fm/on-input-blur form :height)
|
||||
:on-change (fm/on-input-change form :height)
|
||||
:value (:height data)}]]]
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
(ns uxbox.main.ui.messages
|
||||
(:require [lentes.core :as l]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.util.messages :as uum]
|
||||
[rumext.core :as mx :include-macros true]))
|
||||
(:require
|
||||
[lentes.core :as l]
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.util.messages :as um]))
|
||||
|
||||
(def ^:private message-ref
|
||||
(def ^:private message-iref
|
||||
(-> (l/key :message)
|
||||
(l/derive st/state)))
|
||||
|
||||
(mx/defc messages-widget
|
||||
{:mixins [mx/static mx/reactive]}
|
||||
(mf/defc messages-widget
|
||||
[]
|
||||
(let [message (mx/react message-ref)
|
||||
on-close #(st/emit! (uum/hide))]
|
||||
(uum/messages-widget (assoc message :on-close on-close))))
|
||||
(let [message (mf/deref message-iref)
|
||||
on-close #(st/emit! (um/hide))]
|
||||
[:& um/messages-widget {:message message
|
||||
:on-close on-close}]))
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
[{:keys [route] :as props}]
|
||||
(let [section (get-in route [:data :name])]
|
||||
[:main.dashboard-main
|
||||
(messages-widget)
|
||||
[:& messages-widget]
|
||||
[:& header {:section section}]
|
||||
(case section
|
||||
:settings/profile (mf/element profile/profile-page)
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
(ns uxbox.main.ui.settings.password
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[struct.core :as s]
|
||||
[struct.alpha :as s]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.data.users :as udu]
|
||||
[uxbox.main.store :as st]
|
||||
|
@ -36,14 +36,14 @@
|
|||
:on-error on-error}]
|
||||
(st/emit! (udu/update-password data opts)))))
|
||||
|
||||
(s/defs password-form-spec
|
||||
{:password-1 [s/required s/string]
|
||||
:password-2 [s/required s/string [s/identical-to :password-1]]
|
||||
:password-old [s/required s/string]})
|
||||
(s/defs ::password-form
|
||||
(s/dict :password-1 (s/&& ::s/string ::fm/not-empty-string)
|
||||
:password-2 (s/&& ::s/string ::fm/not-empty-string)
|
||||
:password-old (s/&& ::s/string ::fm/not-empty-string)))
|
||||
|
||||
(mf/defc password-form
|
||||
[props]
|
||||
(let [{:keys [data] :as form} (fm/use-form {:initial {} :spec password-form-spec})]
|
||||
(let [{:keys [data] :as form} (fm/use-form ::password-form {})]
|
||||
[:form.password-form {:on-submit #(on-submit % form)}
|
||||
[:span.user-settings-label (tr "settings.password.change-password")]
|
||||
[:input.input-text
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
[cuerdas.core :as str]
|
||||
[lentes.core :as l]
|
||||
[rumext.alpha :as mf]
|
||||
[struct.core :as s]
|
||||
[struct.alpha :as s]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.data.users :as udu]
|
||||
[uxbox.main.store :as st]
|
||||
|
@ -18,27 +18,28 @@
|
|||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.forms :as fm]
|
||||
[uxbox.util.i18n :as i18n :refer [tr]]
|
||||
[uxbox.util.interop :refer [iterable->seq]]))
|
||||
[uxbox.util.interop :refer [iterable->seq]]
|
||||
[uxbox.util.messages :as um]))
|
||||
|
||||
(defn profile->form
|
||||
|
||||
(defn- profile->form
|
||||
[profile]
|
||||
(let [language (get-in profile [:metadata :language])]
|
||||
(-> (select-keys profile [:fullname :username :email])
|
||||
(cond-> language (assoc :language language)))))
|
||||
|
||||
(def profile-ref
|
||||
(def ^:private profile-ref
|
||||
(-> (l/key :profile)
|
||||
(l/derive st/state)))
|
||||
|
||||
(s/defs profile-form-spec
|
||||
{:fullname [fm/required fm/string]
|
||||
:username [fm/required fm/string]
|
||||
:email [fm/required fm/email]
|
||||
:language [fm/required fm/string]})
|
||||
(s/defs ::profile-form
|
||||
(s/dict :fullname (s/&& ::s/string ::fm/not-empty-string)
|
||||
:username (s/&& ::s/string ::fm/not-empty-string)
|
||||
:language (s/&& ::s/string ::fm/not-empty-string)
|
||||
:email ::s/email))
|
||||
|
||||
(defn- on-error
|
||||
[error form]
|
||||
(prn "on-error" error form)
|
||||
(case (:code error)
|
||||
:uxbox.services.users/email-already-exists
|
||||
(swap! form assoc-in [:errors :email]
|
||||
|
@ -57,18 +58,20 @@
|
|||
|
||||
(defn- on-submit
|
||||
[event form]
|
||||
(prn "on-submit" form)
|
||||
(dom/prevent-default event)
|
||||
(let [data (:clean-data form)
|
||||
opts {:on-success #(prn "On Success" %)
|
||||
:on-error #(on-error % form)}]
|
||||
on-success #(st/emit! (um/info (tr "settings.profile.profile-saved")))
|
||||
on-error #(on-error % form)
|
||||
opts {:on-success on-success
|
||||
:on-error on-error}]
|
||||
(st/emit! (udu/update-profile data opts))))
|
||||
|
||||
;; --- Profile Form
|
||||
|
||||
(mf/defc profile-form
|
||||
[props]
|
||||
(let [{:keys [data] :as form} (fm/use-form {:initial initial-data
|
||||
:spec profile-form-spec})]
|
||||
(prn "profile-form" form)
|
||||
(let [{:keys [data] :as form} (fm/use-form ::profile-form initial-data)]
|
||||
[:form.profile-form {:on-submit #(on-submit % form)}
|
||||
[:span.user-settings-label (tr "settings.profile.section-basic-data")]
|
||||
[:input.input-text
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
[:li {:on-click #(on-click % :settings/notifications)}
|
||||
i/mail
|
||||
[:span (tr "ds.user.notifications")]]
|
||||
[:li {:on-click #(on-click % (da/logout))}
|
||||
[:li {:on-click #(on-click % da/logout)}
|
||||
i/exit
|
||||
[:span (tr "ds.user.exit")]]]))
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
(:require
|
||||
[beicon.core :as rx]
|
||||
[lentes.core :as l]
|
||||
[rumext.core :as mx]
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.main.constants :as c]
|
||||
[uxbox.main.data.history :as udh]
|
||||
|
@ -86,7 +85,7 @@
|
|||
(mf/use-effect #(subscribe canvas page)
|
||||
#js [(:id page)])
|
||||
[:*
|
||||
(messages-widget)
|
||||
[:& messages-widget]
|
||||
[:& header {:page page
|
||||
:flags flags
|
||||
:key (:id page)}]
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
;; 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) 2015-2016 Andrey Antukh <niwi@niwi.nz>
|
||||
;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
;; Copyright (c) 2015-2019 Andrey Antukh <niwi@niwi.nz>
|
||||
;; Copyright (c) 2015-2019 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
|
||||
(ns uxbox.main.ui.workspace.sidebar.sitemap-forms
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[struct.alpha :as s]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.constants :as c]
|
||||
[uxbox.main.data.pages :as udp]
|
||||
|
@ -17,12 +18,12 @@
|
|||
[uxbox.util.forms :as fm]
|
||||
[uxbox.util.i18n :refer [tr]]))
|
||||
|
||||
(def page-form-spec
|
||||
{:id [fm/uuid]
|
||||
:project [fm/uuid]
|
||||
:name [fm/required fm/string]
|
||||
:width [fm/required fm/number-str]
|
||||
:height [fm/required fm/number-str]})
|
||||
(s/defs ::page-form
|
||||
(s/dict :id (s/opt ::s/uuid)
|
||||
:project ::s/uuid
|
||||
:name (s/&& ::s/string ::fm/not-empty-string)
|
||||
:width ::s/number-str
|
||||
:height ::s/number-str))
|
||||
|
||||
(def defaults
|
||||
{:name ""
|
||||
|
@ -52,13 +53,13 @@
|
|||
|
||||
(mf/defc page-form
|
||||
[{:keys [page] :as props}]
|
||||
(let [{:keys [data errors] :as form} (fm/use-form {:initial #(initial-data page)
|
||||
:spec page-form-spec})]
|
||||
(let [{:keys [data] :as form} (fm/use-form ::page-form #(initial-data page))]
|
||||
[:form {:on-submit #(on-submit % form)}
|
||||
[:input.input-text
|
||||
{:placeholder "Page name"
|
||||
:type "text"
|
||||
:name "name"
|
||||
:class (fm/error-class form :name)
|
||||
:on-blur (fm/on-input-blur form :name)
|
||||
:on-change (fm/on-input-change form :name)
|
||||
:value (:name data)
|
||||
|
@ -72,6 +73,7 @@
|
|||
:type "number"
|
||||
:min 0
|
||||
:max 5000
|
||||
:class (fm/error-class form :width)
|
||||
:on-blur (fm/on-input-blur form :width)
|
||||
:on-change (fm/on-input-change form :width)
|
||||
:value (:width data)}]]
|
||||
|
@ -84,12 +86,14 @@
|
|||
:type "number"
|
||||
:min 0
|
||||
:max 5000
|
||||
:class (fm/error-class form :height)
|
||||
:on-blur (fm/on-input-blur form :height)
|
||||
:on-change (fm/on-input-change form :height)
|
||||
:value (:height data)}]]]
|
||||
[:input.btn-primary
|
||||
{:value "Go go go!"
|
||||
:type "submit"
|
||||
:class (when-not (:valid form) "btn-disabled")
|
||||
:disabled (not (:valid form))}]]))
|
||||
|
||||
(mf/defc page-form-dialog
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue