mirror of
https://github.com/penpot/penpot.git
synced 2025-06-09 22:33:14 +02:00
Replace funcool/struct with cljs.spec.
As a result, one dependency less.
This commit is contained in:
parent
6bc6ee68b6
commit
1aa236e812
12 changed files with 440 additions and 391 deletions
|
@ -6,38 +6,45 @@
|
|||
;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
|
||||
(ns uxbox.main.ui.auth.login
|
||||
(:require [lentes.core :as l]
|
||||
(:require [cljs.spec :as s :include-macros true]
|
||||
[lentes.core :as l]
|
||||
[cuerdas.core :as str]
|
||||
[potok.core :as ptk]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.config :as cfg]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.data.auth :as da]
|
||||
[uxbox.main.ui.messages :refer [messages-widget]]
|
||||
[uxbox.main.ui.navigation :as nav]
|
||||
[uxbox.util.mixins :as mx :include-macros true]
|
||||
[uxbox.util.router :as rt]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.forms :as forms]))
|
||||
[uxbox.util.forms :as fm]
|
||||
[uxbox.util.mixins :as mx :include-macros true]
|
||||
[uxbox.util.router :as rt]))
|
||||
|
||||
(def form-data (forms/focus-data :login st/state))
|
||||
(def set-value! (partial forms/set-value! st/store :login))
|
||||
(def form-data (fm/focus-data :login st/state))
|
||||
(def form-errors (fm/focus-errors :login st/state))
|
||||
|
||||
(def assoc-value (partial fm/assoc-value :login))
|
||||
(def assoc-errors (partial fm/assoc-errors :login))
|
||||
(def clear-form (partial fm/clear-form :login))
|
||||
|
||||
(s/def ::username ::fm/non-empty-string)
|
||||
(s/def ::password ::fm/non-empty-string)
|
||||
|
||||
(s/def ::login-form
|
||||
(s/keys :req-un [::username ::password]))
|
||||
|
||||
(def +login-form+
|
||||
{:email [forms/required forms/string]
|
||||
:password [forms/required forms/string]})
|
||||
|
||||
(mx/defc login-form
|
||||
{:mixins [mx/static mx/reactive]}
|
||||
[]
|
||||
(let [data (mx/react form-data)
|
||||
valid? (forms/valid? data +login-form+)]
|
||||
valid? (fm/valid? ::login-form data)]
|
||||
(letfn [(on-change [event field]
|
||||
(let [value (dom/event->value event)]
|
||||
(set-value! field value)))
|
||||
(st/emit! (assoc-value field value))))
|
||||
(on-submit [event]
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (da/login {:username (:email data)
|
||||
(st/emit! (da/login {:username (:username data)
|
||||
:password (:password data)})))]
|
||||
[:form {:on-submit on-submit}
|
||||
[:div.login-content
|
||||
|
@ -52,8 +59,8 @@
|
|||
{:name "email"
|
||||
:tab-index "2"
|
||||
:ref "email"
|
||||
:value (:email data "")
|
||||
:on-change #(on-change % :email)
|
||||
:value (:username data "")
|
||||
:on-change #(on-change % :username)
|
||||
:placeholder "Email or Username"
|
||||
:type "text"}]
|
||||
[:input.input-text
|
||||
|
@ -80,7 +87,7 @@
|
|||
"Don't have an account?"]]]])))
|
||||
|
||||
(mx/defc login-page
|
||||
{:mixins [mx/static (forms/clear-mixin st/store :login)]
|
||||
{:mixins [mx/static (fm/clear-mixin st/store :login)]
|
||||
:will-mount (fn [own]
|
||||
(when @st/auth-ref
|
||||
(st/emit! (rt/navigate :dashboard/projects)))
|
||||
|
|
|
@ -6,42 +6,44 @@
|
|||
;; Copyright (c) 2015-2017 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
|
||||
(ns uxbox.main.ui.auth.recovery
|
||||
(:require [lentes.core :as l]
|
||||
(:require [cljs.spec :as s :include-macros true]
|
||||
[lentes.core :as l]
|
||||
[cuerdas.core :as str]
|
||||
[potok.core :as ptk]
|
||||
[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.router :as rt]
|
||||
[uxbox.util.forms :as forms]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.forms :as fm]
|
||||
[uxbox.util.mixins :as mx :include-macros true]
|
||||
[uxbox.util.dom :as dom]))
|
||||
[uxbox.util.router :as rt]))
|
||||
|
||||
(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))
|
||||
|
||||
;; --- Recovery Form
|
||||
|
||||
(def form-data (forms/focus-data :recovery st/state))
|
||||
(def set-value! (partial forms/set-value! st/store :recovery))
|
||||
|
||||
(def +recovery-form+
|
||||
{:password [forms/required forms/string]})
|
||||
(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? (forms/valid? data +recovery-form+)]
|
||||
(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)]
|
||||
(set-value! field value)))
|
||||
(st/emit! (assoc-value field value))))
|
||||
(on-submit [event]
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (uda/recovery data)
|
||||
(forms/clear-form :recovery)
|
||||
(forms/clear-errors :recovery)))]
|
||||
(clear-form)))]
|
||||
[:form {:on-submit on-submit}
|
||||
[:div.login-content
|
||||
[:input.input-text
|
||||
|
@ -68,7 +70,7 @@
|
|||
own))
|
||||
|
||||
(mx/defc recovery-page
|
||||
{:mixins [mx/static (forms/clear-mixin st/store :recovery)]
|
||||
{:mixins [mx/static (fm/clear-mixin st/store :recovery)]
|
||||
:will-mount recovery-page-will-mount}
|
||||
[token]
|
||||
[:div.login
|
||||
|
|
|
@ -6,45 +6,47 @@
|
|||
;; Copyright (c) 2015-2017 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
|
||||
(ns uxbox.main.ui.auth.recovery-request
|
||||
(:require [lentes.core :as l]
|
||||
(:require [cljs.spec :as s :include-macros true]
|
||||
[lentes.core :as l]
|
||||
[cuerdas.core :as str]
|
||||
[potok.core :as ptk]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.data.auth :as uda]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.ui.messages :refer [messages-widget]]
|
||||
[uxbox.main.ui.navigation :as nav]
|
||||
[uxbox.util.router :as rt]
|
||||
[uxbox.util.forms :as forms]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.forms :as fm]
|
||||
[uxbox.util.mixins :as mx :include-macros true]
|
||||
[uxbox.util.dom :as dom]))
|
||||
[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 (forms/focus-data :recovery-request st/state))
|
||||
(def set-value! (partial forms/set-value! st/store :recovery-request))
|
||||
(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 +recovery-request-form+
|
||||
{:username [forms/required forms/string]})
|
||||
(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? (forms/valid? data +recovery-request-form+)]
|
||||
(letfn [(on-change [field event]
|
||||
valid? (fm/valid? ::recovery-request-form data)]
|
||||
(letfn [(on-change [event]
|
||||
(let [value (dom/event->value event)]
|
||||
(set-value! field value)))
|
||||
(st/emit! (assoc-value :username value))))
|
||||
(on-submit [event]
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (uda/recovery-request data)
|
||||
(forms/clear-form :recovery-request)
|
||||
(forms/clear-errors :recovery-request)))]
|
||||
(clear-form)))]
|
||||
[:form {:on-submit on-submit}
|
||||
[:div.login-content
|
||||
[:input.input-text
|
||||
{:name "username"
|
||||
:value (:username data "")
|
||||
:on-change (partial on-change :username)
|
||||
:on-change on-change
|
||||
:placeholder "username or email address"
|
||||
:type "text"}]
|
||||
[:input.btn-primary
|
||||
|
@ -59,7 +61,7 @@
|
|||
;; --- Recovery Request Page
|
||||
|
||||
(mx/defc recovery-request-page
|
||||
{:mixins [mx/static (forms/clear-mixin st/store :recovery-request)]}
|
||||
{:mixins [mx/static (fm/clear-mixin st/store :recovery-request)]}
|
||||
[]
|
||||
[:div.login
|
||||
[:div.login-body
|
||||
|
|
|
@ -2,52 +2,59 @@
|
|||
;; 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-2017 Andrey Antukh <niwi@niwi.nz>
|
||||
;; Copyright (c) 2015-2017 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
|
||||
(ns uxbox.main.ui.auth.register
|
||||
(:require [lentes.core :as l]
|
||||
(:require [cljs.spec :as s :include-macros true]
|
||||
[lentes.core :as l]
|
||||
[cuerdas.core :as str]
|
||||
[potok.core :as ptk]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.data.auth :as uda]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.ui.messages :refer [messages-widget]]
|
||||
[uxbox.main.ui.navigation :as nav]
|
||||
[uxbox.util.router :as rt]
|
||||
[uxbox.util.forms :as forms]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.forms :as fm]
|
||||
[uxbox.util.mixins :as mx :include-macros true]
|
||||
[uxbox.util.dom :as dom]))
|
||||
[uxbox.util.router :as rt]))
|
||||
|
||||
;; --- Register Form
|
||||
(def form-data (fm/focus-data :register st/state))
|
||||
(def form-errors (fm/focus-errors :register st/state))
|
||||
|
||||
(def form-data (forms/focus-data :register st/state))
|
||||
(def form-errors (forms/focus-errors :register st/state))
|
||||
(def set-value! (partial forms/set-value! st/store :register))
|
||||
(def set-error! (partial forms/set-error! st/store :register))
|
||||
(def assoc-value (partial fm/assoc-value :register))
|
||||
(def assoc-error (partial fm/assoc-error :register))
|
||||
(def clear-form (partial fm/clear-form :register))
|
||||
|
||||
(def +register-form+
|
||||
{:username [forms/required forms/string]
|
||||
:fullname [forms/required forms/string]
|
||||
:email [forms/required forms/email]
|
||||
:password [forms/required forms/string]})
|
||||
;; TODO: add better password validation
|
||||
|
||||
(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)
|
||||
|
||||
(s/def ::register-form
|
||||
(s/keys :req-un [::username
|
||||
::fullname
|
||||
::email
|
||||
::password]))
|
||||
|
||||
(mx/defc register-form
|
||||
{:mixins [mx/static mx/reactive
|
||||
(forms/clear-mixin st/store :register)]}
|
||||
(fm/clear-mixin st/store :register)]}
|
||||
[]
|
||||
(let [data (mx/react form-data)
|
||||
errors (mx/react form-errors)
|
||||
valid? (forms/valid? data +register-form+)]
|
||||
valid? (fm/valid? ::register-form data)]
|
||||
(letfn [(on-change [field event]
|
||||
(let [value (dom/event->value event)]
|
||||
(set-value! field value)))
|
||||
(st/emit! (assoc-value field value))))
|
||||
(on-error [{:keys [type code] :as payload}]
|
||||
(case code
|
||||
:uxbox.services.users/email-already-exists
|
||||
(set-error! :email "Email already exists")
|
||||
(st/emit! (assoc-error :email "Email already exists"))
|
||||
:uxbox.services.users/username-already-exists
|
||||
(set-error! :username "Username already exists")))
|
||||
(st/emit! (assoc-error :username "Username already exists"))))
|
||||
(on-submit [event]
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (uda/register data on-error)))]
|
||||
|
@ -60,7 +67,7 @@
|
|||
:on-change (partial on-change :fullname)
|
||||
:placeholder "Full Name"
|
||||
:type "text"}]
|
||||
(forms/input-error errors :fullname)
|
||||
(fm/input-error errors :fullname)
|
||||
|
||||
[:input.input-text
|
||||
{:name "username"
|
||||
|
@ -69,7 +76,7 @@
|
|||
:on-change (partial on-change :username)
|
||||
:placeholder "Username"
|
||||
:type "text"}]
|
||||
(forms/input-error errors :username)
|
||||
(fm/input-error errors :username)
|
||||
|
||||
[:input.input-text
|
||||
{:name "email"
|
||||
|
@ -79,7 +86,7 @@
|
|||
:on-change (partial on-change :email)
|
||||
:placeholder "Email"
|
||||
:type "text"}]
|
||||
(forms/input-error errors :email)
|
||||
(fm/input-error errors :email)
|
||||
|
||||
[:input.input-text
|
||||
{:name "password"
|
||||
|
@ -89,7 +96,7 @@
|
|||
:on-change (partial on-change :password)
|
||||
:placeholder "Password"
|
||||
:type "password"}]
|
||||
(forms/input-error errors :password)
|
||||
(fm/input-error errors :password)
|
||||
|
||||
[:input.btn-primary
|
||||
{:name "login"
|
||||
|
|
|
@ -209,7 +209,7 @@
|
|||
(sort-projects-by ordering))]
|
||||
(letfn [(on-click [e]
|
||||
(dom/prevent-default e)
|
||||
(udl/open! :new-project))]
|
||||
(udl/open! :create-project))]
|
||||
[:section.dashboard-grid
|
||||
[:h2 "Your projects"]
|
||||
[:div.dashboard-grid-content
|
||||
|
|
|
@ -6,42 +6,44 @@
|
|||
;; Copyright (c) 2015-2017 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
|
||||
(ns uxbox.main.ui.dashboard.projects-createform
|
||||
(:require [lentes.core :as l]
|
||||
(:require [cljs.spec :as s :include-macros true]
|
||||
[lentes.core :as l]
|
||||
[cuerdas.core :as str]
|
||||
[potok.core :as ptk]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.constants :as c]
|
||||
[uxbox.main.exports :as exports]
|
||||
[uxbox.main.data.projects :as udp]
|
||||
[uxbox.main.data.lightbox :as udl]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.ui.dashboard.header :refer [header]]
|
||||
[uxbox.main.ui.lightbox :as lbx]
|
||||
[uxbox.main.ui.keyboard :as kbd]
|
||||
[uxbox.util.data :refer [read-string parse-int]]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.forms :as fm]
|
||||
[uxbox.util.i18n :as t :refer [tr]]
|
||||
[uxbox.util.router :as r]
|
||||
[uxbox.util.forms :as forms]
|
||||
[uxbox.util.data :refer [read-string]]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.blob :as blob]
|
||||
[uxbox.util.mixins :as mx :include-macros true]
|
||||
[uxbox.util.time :as dt]))
|
||||
|
||||
(def form-data (forms/focus-data :create-project st/state))
|
||||
(def form-errors (forms/focus-errors :create-project st/state))
|
||||
(def set-value! (partial forms/set-value! st/store :create-project))
|
||||
(def set-error! (partial forms/set-error! st/store :create-project))
|
||||
(def clear! (partial forms/clear! st/store :create-project))
|
||||
(def form-data (fm/focus-data :create-project st/state))
|
||||
(def form-errors (fm/focus-errors :create-project st/state))
|
||||
|
||||
(def ^:private create-project-form
|
||||
{:name [forms/required forms/string]
|
||||
:width [forms/required forms/integer]
|
||||
:height [forms/required forms/integer]
|
||||
:layout [forms/required forms/string]})
|
||||
(def assoc-value (partial fm/assoc-value :create-project))
|
||||
(def clear-form (partial fm/clear-form :create-project))
|
||||
|
||||
;; --- Lightbox: Layout input
|
||||
(s/def ::name ::fm/non-empty-string)
|
||||
(s/def ::layout ::fm/non-empty-string)
|
||||
(s/def ::width number?)
|
||||
(s/def ::height number?)
|
||||
|
||||
(s/def ::project-form
|
||||
(s/keys :req-un [::name
|
||||
::width
|
||||
::height
|
||||
::layout]))
|
||||
|
||||
;; --- Create Project Form
|
||||
|
||||
(mx/defc layout-input
|
||||
{:mixins [mx/static]}
|
||||
[data layout-id]
|
||||
(let [layout (get c/page-layouts layout-id)]
|
||||
[:div
|
||||
|
@ -51,17 +53,15 @@
|
|||
:name "project-layout"
|
||||
:value (:name layout)
|
||||
:checked (when (= layout-id (:layout data)) "checked")
|
||||
:on-change #(do
|
||||
(set-value! :layout layout-id)
|
||||
(set-value! :width (:width layout))
|
||||
(set-value! :height (:height layout)))}]
|
||||
:on-change #(st/emit! (assoc-value :layout layout-id)
|
||||
(assoc-value :width (:width layout))
|
||||
(assoc-value :height (:height layout)))}]
|
||||
[:label {:value (:name layout)
|
||||
:for layout-id}
|
||||
(:name layout)]]))
|
||||
|
||||
;; --- Lightbox: Layout selector
|
||||
|
||||
(mx/defc layout-selector
|
||||
{:mixins [mx/static]}
|
||||
[data]
|
||||
[:div.input-radio.radio-primary
|
||||
(layout-input data "mobile")
|
||||
|
@ -69,70 +69,84 @@
|
|||
(layout-input data "notebook")
|
||||
(layout-input data "desktop")])
|
||||
|
||||
;; -- New Project Lightbox
|
||||
|
||||
(mx/defcs new-project-lightbox
|
||||
{:mixins [mx/static mx/reactive
|
||||
(forms/clear-mixin st/store :create-project)]}
|
||||
[own]
|
||||
(mx/defc create-project-form
|
||||
{:mixins [mx/reactive mx/static]}
|
||||
[]
|
||||
(let [data (merge c/project-defaults (mx/react form-data))
|
||||
errors (mx/react form-errors)
|
||||
valid? (forms/valid? data create-project-form)]
|
||||
valid? (fm/valid? ::project-form data)]
|
||||
(println data)
|
||||
(println valid?)
|
||||
(letfn [(on-submit [event]
|
||||
(dom/prevent-default event)
|
||||
(when valid?
|
||||
(st/emit! (udp/create-project data))
|
||||
(udl/close!)))
|
||||
(set-value [event attr]
|
||||
(set-value! attr (dom/event->value event)))
|
||||
|
||||
(update-size [field e]
|
||||
(let [value (dom/event->value e)
|
||||
value (parse-int value)]
|
||||
(st/emit! (assoc-value field value))))
|
||||
|
||||
(update-name [e]
|
||||
(let [value (dom/event->value e)]
|
||||
(st/emit! (assoc-value :name value))))
|
||||
(swap-size []
|
||||
(set-value! :width (:height data))
|
||||
(set-value! :height (:width data)))
|
||||
(close []
|
||||
(udl/close!)
|
||||
(clear!))]
|
||||
[:div.lightbox-body
|
||||
[:h3 "New project"]
|
||||
[:form {:on-submit on-submit}
|
||||
[:input#project-name.input-text
|
||||
{:placeholder "New project name"
|
||||
:type "text"
|
||||
:value (:name data)
|
||||
:auto-focus true
|
||||
:on-change #(set-value % :name)}]
|
||||
[:div.project-size
|
||||
[:div.input-element.pixels
|
||||
[:span "Width"]
|
||||
[:input#project-witdh.input-text
|
||||
{:placeholder "Width"
|
||||
:type "number"
|
||||
:min 0 ;;TODO check this value
|
||||
:max 666666 ;;TODO check this value
|
||||
:value (:width data)
|
||||
:on-change #(set-value % :width)}]]
|
||||
[:a.toggle-layout {:on-click swap-size} i/toggle]
|
||||
[:div.input-element.pixels
|
||||
[:span "Height"]
|
||||
[:input#project-height.input-text
|
||||
{:placeholder "Height"
|
||||
:type "number"
|
||||
:min 0 ;;TODO check this value
|
||||
:max 666666 ;;TODO check this value
|
||||
:value (:height data)
|
||||
:on-change #(set-value % :height)}]]]
|
||||
(st/emit! (assoc-value :width (:height data))
|
||||
(assoc-value :height (:width data))))]
|
||||
[:form {:on-submit on-submit}
|
||||
[:input#project-name.input-text
|
||||
{:placeholder "New project name"
|
||||
:type "text"
|
||||
:value (:name data)
|
||||
:auto-focus true
|
||||
:on-change update-name}]
|
||||
[:div.project-size
|
||||
[:div.input-element.pixels
|
||||
[:span "Width"]
|
||||
[:input#project-witdh.input-text
|
||||
{:placeholder "Width"
|
||||
:type "number"
|
||||
:min 0 ;;TODO check this value
|
||||
:max 666666 ;;TODO check this value
|
||||
:value (:width data)
|
||||
:on-change (partial update-size :width)}]]
|
||||
[:a.toggle-layout {:on-click swap-size} i/toggle]
|
||||
[:div.input-element.pixels
|
||||
[:span "Height"]
|
||||
[:input#project-height.input-text
|
||||
{:placeholder "Height"
|
||||
:type "number"
|
||||
:min 0 ;;TODO check this value
|
||||
:max 666666 ;;TODO check this value
|
||||
:value (:height data)
|
||||
:on-change (partial update-size :height)}]]]
|
||||
|
||||
;; Layout selector
|
||||
(layout-selector data)
|
||||
;; Layout selector
|
||||
(layout-selector data)
|
||||
|
||||
;; Submit
|
||||
[:input#project-btn.btn-primary
|
||||
{:value "Go go go!"
|
||||
:class (when-not valid? "btn-disabled")
|
||||
:disabled (not valid?)
|
||||
:type "submit"}]]
|
||||
[:a.close {:on-click #(udl/close!)} i/close]])))
|
||||
;; Submit
|
||||
[:input#project-btn.btn-primary
|
||||
{:value "Go go go!"
|
||||
:class (when-not valid? "btn-disabled")
|
||||
:disabled (not valid?)
|
||||
:type "submit"}]])))
|
||||
|
||||
(defmethod lbx/render-lightbox :new-project
|
||||
;; --- Create Project Lightbox
|
||||
|
||||
(mx/defcs create-project-lightbox
|
||||
{:mixins [mx/static mx/reactive
|
||||
(fm/clear-mixin st/store :create-project)]}
|
||||
[own]
|
||||
(letfn [(close []
|
||||
(udl/close!)
|
||||
(st/emit! (clear-form)))]
|
||||
[:div.lightbox-body
|
||||
[:h3 "New project"]
|
||||
(create-project-form)
|
||||
[:a.close {:on-click #(udl/close!)} i/close]]))
|
||||
|
||||
(defmethod lbx/render-lightbox :create-project
|
||||
[_]
|
||||
(new-project-lightbox))
|
||||
(create-project-lightbox))
|
||||
|
||||
|
|
|
@ -2,11 +2,12 @@
|
|||
;; 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>
|
||||
;; Copyright (c) 2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
;; Copyright (c) 2016-2017 Andrey Antukh <niwi@niwi.nz>
|
||||
;; Copyright (c) 2016-2017 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
|
||||
(ns uxbox.main.ui.settings.password
|
||||
(:require [lentes.core :as l]
|
||||
(:require [cljs.spec :as s :include-macros true]
|
||||
[lentes.core :as l]
|
||||
[cuerdas.core :as str]
|
||||
[potok.core :as ptk]
|
||||
[uxbox.main.store :as st]
|
||||
|
@ -14,57 +15,75 @@
|
|||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.ui.messages :refer [messages-widget]]
|
||||
[uxbox.main.ui.settings.header :refer [header]]
|
||||
[uxbox.util.forms :as forms]
|
||||
[uxbox.util.i18n :refer [tr]]
|
||||
[uxbox.util.forms :as fm]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.messages :as um]
|
||||
[uxbox.util.mixins :as mx :include-macros true]))
|
||||
|
||||
(def form-data (fm/focus-data :profile-password st/state))
|
||||
(def form-errors (fm/focus-errors :profile-password st/state))
|
||||
|
||||
(def form-data (forms/focus-data :profile-password st/state))
|
||||
(def form-errors (forms/focus-errors :profile-password st/state))
|
||||
(def set-value! (partial forms/set-value! st/store :profile-password))
|
||||
(def set-errors! (partial forms/set-errors! st/store :profile-password))
|
||||
(def assoc-value (partial fm/assoc-value :profile-password))
|
||||
(def assoc-error (partial fm/assoc-error :profile-password))
|
||||
(def clear-form (partial fm/clear-form :profile-password))
|
||||
|
||||
(def +password-form+
|
||||
[[:password-1 forms/required forms/string [forms/min-len 6]]
|
||||
[:password-2 forms/required forms/string
|
||||
[forms/identical-to :password-1 :message "errors.form.password-not-match"]]
|
||||
[:old-password forms/required forms/string]])
|
||||
;; TODO: add better password validation
|
||||
|
||||
(s/def ::password-1 ::fm/non-empty-string)
|
||||
(s/def ::password-2 ::fm/non-empty-string)
|
||||
(s/def ::password-old ::fm/non-empty-string)
|
||||
|
||||
(s/def ::password-form
|
||||
(s/keys :req-un [::password-1
|
||||
::password-2
|
||||
::password-old]))
|
||||
|
||||
(mx/defc password-form
|
||||
{:mixins [mx/reactive mx/static]}
|
||||
[]
|
||||
(let [data (mx/react form-data)
|
||||
errors (mx/react form-errors)
|
||||
valid? (forms/valid? data +password-form+)]
|
||||
valid? (fm/valid? ::password-form data)]
|
||||
(letfn [(on-change [field event]
|
||||
(let [value (dom/event->value event)]
|
||||
(set-value! field value)))
|
||||
(st/emit! (assoc-value field value))))
|
||||
(on-success []
|
||||
(st/emit! (um/info (tr "settings.password-saved"))))
|
||||
(on-error [{:keys [code] :as payload}]
|
||||
(case code
|
||||
:uxbox.services.users/old-password-not-match
|
||||
(st/emit! (assoc-error :password-old "Wrong old password"))
|
||||
|
||||
:else
|
||||
(throw (ex-info "unexpected" {:error payload}))))
|
||||
(on-submit [event]
|
||||
(println "on-submit" data)
|
||||
#_(st/emit! (udu/update-password form)))]
|
||||
(st/emit! (udu/update-password data
|
||||
:on-success on-success
|
||||
:on-error on-error)))]
|
||||
[:form.password-form
|
||||
[:span.user-settings-label "Change password"]
|
||||
[:input.input-text
|
||||
{:type "password"
|
||||
:class (forms/error-class errors :old-password)
|
||||
:value (:old-password data "")
|
||||
:on-change (partial on-change :old-password)
|
||||
:class (fm/error-class errors :password-old)
|
||||
:value (:password-old data "")
|
||||
:on-change (partial on-change :password-old)
|
||||
:placeholder "Old password"}]
|
||||
(forms/input-error errors :old-password)
|
||||
(fm/input-error errors :password-old)
|
||||
[:input.input-text
|
||||
{:type "password"
|
||||
:class (forms/error-class errors :password-1)
|
||||
:class (fm/error-class errors :password-1)
|
||||
:value (:password-1 data "")
|
||||
:on-change (partial on-change :password-1)
|
||||
:placeholder "New password"}]
|
||||
(forms/input-error errors :password-1)
|
||||
(fm/input-error errors :password-1)
|
||||
[:input.input-text
|
||||
{:type "password"
|
||||
:class (forms/error-class errors :password-2)
|
||||
:class (fm/error-class errors :password-2)
|
||||
:value (:password-2 data "")
|
||||
:on-change (partial on-change :password-2)
|
||||
:placeholder "Confirm password"}]
|
||||
(forms/input-error errors :password-2)
|
||||
(fm/input-error errors :password-2)
|
||||
[:input.btn-primary
|
||||
{:type "button"
|
||||
:class (when-not valid? "btn-disabled")
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
;; Copyright (c) 2016-2017 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
|
||||
(ns uxbox.main.ui.settings.profile
|
||||
(:require [cuerdas.core :as str]
|
||||
(:require [cljs.spec :as s :include-macros true]
|
||||
[cuerdas.core :as str]
|
||||
[lentes.core :as l]
|
||||
[potok.core :as ptk]
|
||||
[uxbox.main.store :as st]
|
||||
|
@ -14,52 +15,58 @@
|
|||
[uxbox.main.ui.settings.header :refer [header]]
|
||||
[uxbox.main.ui.messages :refer [messages-widget]]
|
||||
[uxbox.main.data.users :as udu]
|
||||
[uxbox.util.forms :as forms]
|
||||
[uxbox.util.forms :as fm]
|
||||
[uxbox.util.router :as r]
|
||||
[uxbox.util.mixins :as mx :include-macros true]
|
||||
[uxbox.util.interop :refer [iterable->seq]]
|
||||
[uxbox.util.dom :as dom]))
|
||||
|
||||
|
||||
(def form-data (forms/focus-data :profile st/state))
|
||||
(def form-errors (forms/focus-errors :profile st/state))
|
||||
(def set-value! (partial forms/set-value! st/store :profile))
|
||||
(def set-error! (partial forms/set-error! st/store :profile))
|
||||
(def clear! (partial forms/clear! st/store :profile))
|
||||
(def form-data (fm/focus-data :profile st/state))
|
||||
(def form-errors (fm/focus-errors :profile st/state))
|
||||
|
||||
(def assoc-value (partial fm/assoc-value :profile))
|
||||
(def assoc-error (partial fm/assoc-error :profile))
|
||||
(def clear-form (partial fm/clear-form :profile))
|
||||
|
||||
(def profile-ref
|
||||
(-> (l/key :profile)
|
||||
(l/derive st/state)))
|
||||
|
||||
(def +profile-form+
|
||||
{:fullname [forms/required forms/string]
|
||||
:email [forms/required forms/email]
|
||||
:username [forms/required forms/string]})
|
||||
(s/def ::fullname ::fm/non-empty-string)
|
||||
(s/def ::username ::fm/non-empty-string)
|
||||
(s/def ::email ::fm/email)
|
||||
|
||||
(s/def ::profile-form
|
||||
(s/keys :req-un [::fullname
|
||||
::username
|
||||
::email]))
|
||||
|
||||
;; --- Profile Form
|
||||
|
||||
(mx/defc profile-form
|
||||
{:mixins [mx/static mx/reactive
|
||||
(forms/clear-mixin st/store :profile)]}
|
||||
(fm/clear-mixin st/store :profile)]}
|
||||
[]
|
||||
;; TODO: properly persist theme
|
||||
(let [data (merge {:theme "light"}
|
||||
(mx/react profile-ref)
|
||||
(mx/react form-data))
|
||||
errors (mx/react form-errors)
|
||||
valid? (forms/valid? data +profile-form+)
|
||||
valid? (fm/valid? ::profile-form data)
|
||||
theme (:theme data)]
|
||||
(letfn [(on-change [field event]
|
||||
(let [value (dom/event->value event)]
|
||||
(set-value! field value)))
|
||||
(st/emit! (assoc-value field value))))
|
||||
(on-error [{:keys [code] :as payload}]
|
||||
(case code
|
||||
:uxbox.services.users/email-already-exists
|
||||
(set-error! :email "Email already exists")
|
||||
(st/emit! (assoc-error :email "Email already exists"))
|
||||
:uxbox.services.users/username-already-exists
|
||||
(set-error! :username "Username already exists")))
|
||||
(st/emit! (assoc-error :username "Username already exists"))))
|
||||
(on-success [_]
|
||||
(st/emit! (clear-form)))
|
||||
(on-submit [event]
|
||||
(st/emit! (udu/update-profile data clear! on-error)))]
|
||||
(st/emit! (udu/update-profile data on-success on-error)))]
|
||||
[:form.profile-form
|
||||
[:span.user-settings-label "Name, username and email"]
|
||||
[:input.input-text
|
||||
|
@ -72,14 +79,14 @@
|
|||
:on-change (partial on-change :username)
|
||||
:value (:username data "")
|
||||
:placeholder "Your username"}]
|
||||
(forms/input-error errors :username)
|
||||
(fm/input-error errors :username)
|
||||
|
||||
[:input.input-text
|
||||
{:type "email"
|
||||
:on-change (partial on-change :email)
|
||||
:value (:email data "")
|
||||
:placeholder "Your email"}]
|
||||
(forms/input-error errors :email)
|
||||
[:input.input-text
|
||||
{:type "email"
|
||||
:on-change (partial on-change :email)
|
||||
:value (:email data "")
|
||||
:placeholder "Your email"}]
|
||||
(fm/input-error errors :email)
|
||||
|
||||
#_[:span.user-settings-label "Choose a color theme"]
|
||||
#_[:div.input-radio.radio-primary
|
||||
|
|
|
@ -6,41 +6,49 @@
|
|||
;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
|
||||
(ns uxbox.main.ui.workspace.sidebar.sitemap-pageform
|
||||
(:require [lentes.core :as l]
|
||||
[cuerdas.core :as str]
|
||||
[potok.core :as ptk]
|
||||
(:require [cljs.spec :as s :include-macros true]
|
||||
[lentes.core :as l]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.constants :as c]
|
||||
[uxbox.main.data.pages :as udp]
|
||||
[uxbox.main.data.workspace :as dw]
|
||||
[uxbox.main.data.lightbox :as udl]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.ui.lightbox :as lbx]
|
||||
[uxbox.util.i18n :refer (tr)]
|
||||
[uxbox.util.data :refer [parse-int]]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.forms :as fm]
|
||||
[uxbox.util.i18n :refer [tr]]
|
||||
[uxbox.util.router :as r]
|
||||
[uxbox.util.forms :as forms]
|
||||
[uxbox.util.mixins :as mx :include-macros true]
|
||||
[uxbox.util.data :refer (deep-merge parse-int)]
|
||||
[uxbox.util.dom :as dom]))
|
||||
[uxbox.util.mixins :as mx :include-macros true]))
|
||||
|
||||
(def form-data (forms/focus-data :workspace-page-form st/state))
|
||||
(def set-value! (partial forms/set-value! st/store :workspace-page-form))
|
||||
|
||||
(def form-data (fm/focus-data :workspace-page-form st/state))
|
||||
(def form-errors (fm/focus-errors :workspace-page-form st/state))
|
||||
|
||||
(def assoc-value (partial fm/assoc-value :workspace-page-form))
|
||||
(def assoc-error (partial fm/assoc-error :workspace-page-form))
|
||||
(def clear-form (partial fm/clear-form :workspace-page-form))
|
||||
|
||||
;; --- Lightbox
|
||||
|
||||
(def +page-form+
|
||||
{:name [forms/required forms/string]
|
||||
:width [forms/required forms/number]
|
||||
:height [forms/required forms/number]
|
||||
:layout [forms/required forms/string]})
|
||||
(s/def ::name ::fm/non-empty-string)
|
||||
(s/def ::layout ::fm/non-empty-string)
|
||||
(s/def ::width number?)
|
||||
(s/def ::height number?)
|
||||
|
||||
(s/def ::page-form
|
||||
(s/keys :req-un [::name
|
||||
::width
|
||||
::height
|
||||
::layout]))
|
||||
|
||||
(mx/defc layout-input
|
||||
[data id]
|
||||
(let [{:keys [id name width height]} (get c/page-layouts id)]
|
||||
(letfn [(on-change [event]
|
||||
(set-value! :layout id)
|
||||
(set-value! :width width)
|
||||
(set-value! :height height))]
|
||||
(st/emit! (assoc-value :layout id)
|
||||
(assoc-value :width width)
|
||||
(assoc-value :height height)))]
|
||||
[:div
|
||||
[:input {:type "radio"
|
||||
:id id
|
||||
|
@ -57,18 +65,18 @@
|
|||
(select-keys page [:name :id :project])
|
||||
(select-keys metadata [:width :height :layout])
|
||||
(mx/react form-data))
|
||||
valid? (forms/valid? data +page-form+)]
|
||||
valid? (fm/valid? ::page-form data)]
|
||||
(letfn [(update-size [field e]
|
||||
(let [value (dom/event->value e)
|
||||
value (parse-int value)]
|
||||
(set-value! field value)))
|
||||
(st/emit! (assoc-value field value))))
|
||||
(update-name [e]
|
||||
(let [value (dom/event->value e)]
|
||||
(set-value! :name value)))
|
||||
(st/emit! (assoc-value :name value))))
|
||||
(toggle-sizes []
|
||||
(let [{:keys [width height]} data]
|
||||
(set-value! :width height)
|
||||
(set-value! :height width)))
|
||||
(st/emit! (assoc-value :width width)
|
||||
(assoc-value :height height))))
|
||||
(on-cancel [e]
|
||||
(dom/prevent-default e)
|
||||
(udl/close!))
|
||||
|
@ -119,7 +127,7 @@
|
|||
:type "button"}]])))
|
||||
|
||||
(mx/defc page-form-lightbox
|
||||
{:mixins [mx/static (forms/clear-mixin st/store :workspace-page-form)]}
|
||||
{:mixins [mx/static (fm/clear-mixin st/store :workspace-page-form)]}
|
||||
[{:keys [id] :as page}]
|
||||
(letfn [(on-cancel [event]
|
||||
(dom/prevent-default event)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue