diff --git a/src/uxbox/data/auth.cljs b/src/uxbox/data/auth.cljs index 40a9ca3a1..9cb2e0ae5 100644 --- a/src/uxbox/data/auth.cljs +++ b/src/uxbox/data/auth.cljs @@ -12,11 +12,12 @@ [uxbox.rstore :as rs] [uxbox.router :as r] [uxbox.state :as st] - [uxbox.schema :as sc] + [uxbox.schema :as us] [uxbox.locales :refer (tr)] [uxbox.data.projects :as udp] [uxbox.data.users :as udu] [uxbox.data.messages :as udm] + [uxbox.data.forms :as udf] [uxbox.util.storage :refer (storage)])) ;; --- Logged In @@ -80,3 +81,40 @@ (defn logout [] (->Logout)) + +;; --- Register + +(defrecord Register [data] + rs/WatchEvent + (-apply-watch [_ state stream] + (letfn [(on-error [{payload :payload}] + (->> (:payload payload) + (udf/assign-errors :register) + (rx/of)))] + (rx/merge + (->> (rp/req :auth/register data) + (rx/map :payload) + (rx/map (constantly ::registered)) + (rx/catch rp/client-error? on-error)) + (->> stream + (rx/filter #(= % ::registered)) + (rx/take 1) + (rx/map #(login data))) + (->> stream + (rx/filter logged-in?) + (rx/take 1) + (rx/map #(udf/clean :register))))))) + +(def register-schema + {:username [us/required us/string] + :fullname [us/required us/string] + :email [us/required us/email] + :password [us/required us/string]}) + +(defn register + "Create a register event instance." + [data] + (let [[errors data] (us/validate data register-schema)] + (if errors + (udf/assign-errors :register errors) + (Register. data)))) diff --git a/src/uxbox/repo/auth.cljs b/src/uxbox/repo/auth.cljs index a898d5aeb..4189ace27 100644 --- a/src/uxbox/repo/auth.cljs +++ b/src/uxbox/repo/auth.cljs @@ -30,3 +30,10 @@ :method :put :body data}] (send! params))) + +(defmethod request :auth/register + [_ data] + (let [params {:url (str url "/auth/register") + :method :post + :body data}] + (send! params))) diff --git a/src/uxbox/ui.cljs b/src/uxbox/ui.cljs index cfda3f147..e5f973141 100644 --- a/src/uxbox/ui.cljs +++ b/src/uxbox/ui.cljs @@ -31,7 +31,7 @@ ;; --- Constants -(def ^:const +unrestricted+ #{:auth/login}) +(def ^:const +unrestricted+ #{:auth/login :auth/register}) (def ^:const restricted? (complement +unrestricted+)) (def route-l @@ -76,7 +76,8 @@ (if (and (restricted? location) (not auth)) (do (p/schedule 0 #(r/go :auth/login)) nil) (case location - :auth/login (auth/login) + :auth/login (auth/login-page) + :auth/register (auth/register-page) :dashboard/projects (dashboard/projects-page) :dashboard/elements (dashboard/elements-page) :dashboard/icons (dashboard/icons-page) diff --git a/src/uxbox/ui/auth.cljs b/src/uxbox/ui/auth.cljs index cad763888..19f4f2c6f 100644 --- a/src/uxbox/ui/auth.cljs +++ b/src/uxbox/ui/auth.cljs @@ -5,86 +5,8 @@ ;; Copyright (c) 2016 Andrey Antukh (ns uxbox.ui.auth - (:require [sablono.core :as html :refer-macros [html]] - [lentes.core :as l] - [cuerdas.core :as str] - [rum.core :as rum] - [uxbox.router :as rt] - [uxbox.state :as st] - [uxbox.rstore :as rs] - [uxbox.data.auth :as da] - [uxbox.data.messages :as udm] - [uxbox.util.dom :as dom] - [uxbox.ui.icons :as i] - [uxbox.ui.messages :as uum] - [uxbox.ui.navigation :as nav] - [uxbox.ui.mixins :as mx])) + (:require [uxbox.ui.auth.login :as login] + [uxbox.ui.auth.register :as register])) -;; --- Login - -(defn- login-submit - [event local] - (dom/prevent-default event) - (let [form (:form @local)] - (rs/emit! (da/login {:username (:email form) - :password (:password form)})))) - -(defn- login-submit-enabled? - [local] - (let [form (:form @local)] - (and (not (str/empty? (:email form ""))) - (not (str/empty? (:password form "")))))) - -(defn- login-field-change - [local field event] - (let [value (str/trim (dom/event->value event))] - (swap! local assoc-in [:form field] value))) - -(defn- login-render - [own local] - (let [on-submit #(login-submit % local) - submit-enabled? (login-submit-enabled? local) - form (:form @local)] - (html - [:div.login - [:div.login-body - (uum/messages) - [:a i/logo] - [:form {:on-submit on-submit} - [:div.login-content - [:input.input-text - {:name "email" - :ref "email" - :value (:email form "") - :on-change #(login-field-change local :email %) - :placeholder "Email or Username" - :type "text"}] - [:input.input-text - {:name "password" - :ref "password" - :value (:password form "") - :on-change #(login-field-change local :password %) - :placeholder "Password" - :type "password"}] - [:input.btn-primary - {:name "login" - :class (when-not submit-enabled? "btn-disabled") - :disabled (not submit-enabled?) - :value "Continue" - :type "submit"}] - [:div.login-links - [:a {:on-click #(rt/go :auth/recover-password)} "Forgot your password?"] - [:a {:on-click #(rt/go :auth/register)} "Don't have an account?"]]]]]]))) - -(defn- login-will-mount - [own] - (when @st/auth-l - (rt/go :dashboard/projects)) - own) - -(def ^:const login - (mx/component - {:render #(login-render % (:rum/local %)) - :will-mount login-will-mount - :name "login" - :mixins [(mx/local)]})) +(def login-page login/login-page) +(def register-page register/register-page) diff --git a/src/uxbox/ui/auth/login.cljs b/src/uxbox/ui/auth/login.cljs new file mode 100644 index 000000000..9725b6d58 --- /dev/null +++ b/src/uxbox/ui/auth/login.cljs @@ -0,0 +1,88 @@ +;; 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.ui.auth.login + (:require [sablono.core :as html :refer-macros [html]] + [lentes.core :as l] + [cuerdas.core :as str] + [rum.core :as rum] + [uxbox.router :as rt] + [uxbox.state :as st] + [uxbox.rstore :as rs] + [uxbox.data.auth :as da] + [uxbox.data.messages :as udm] + [uxbox.util.dom :as dom] + [uxbox.ui.icons :as i] + [uxbox.ui.messages :as uum] + [uxbox.ui.navigation :as nav] + [uxbox.ui.mixins :as mx])) + +(defn- login-submit + [event local] + (dom/prevent-default event) + (let [form (:form @local)] + (rs/emit! (da/login {:username (:email form) + :password (:password form)})))) + +(defn- login-submit-enabled? + [local] + (let [form (:form @local)] + (and (not (str/empty? (:email form ""))) + (not (str/empty? (:password form "")))))) + +(defn- login-field-change + [local field event] + (let [value (str/trim (dom/event->value event))] + (swap! local assoc-in [:form field] value))) + +(defn- login-page-render + [own local] + (let [on-submit #(login-submit % local) + submit-enabled? (login-submit-enabled? local) + form (:form @local)] + (html + [:div.login + [:div.login-body + (uum/messages) + [:a i/logo] + [:form {:on-submit on-submit} + [:div.login-content + [:input.input-text + {:name "email" + :ref "email" + :value (:email form "") + :on-change #(login-field-change local :email %) + :placeholder "Email or Username" + :type "text"}] + [:input.input-text + {:name "password" + :ref "password" + :value (:password form "") + :on-change #(login-field-change local :password %) + :placeholder "Password" + :type "password"}] + [:input.btn-primary + {:name "login" + :class (when-not submit-enabled? "btn-disabled") + :disabled (not submit-enabled?) + :value "Continue" + :type "submit"}] + [:div.login-links + [:a {:on-click #(rt/go :auth/recover-password)} "Forgot your password?"] + [:a {:on-click #(rt/go :auth/register)} "Don't have an account?"]]]]]]))) + +(defn- login-page-will-mount + [own] + (when @st/auth-l + (rt/go :dashboard/projects)) + own) + +(def login-page + (mx/component + {:render #(login-page-render % (:rum/local %)) + :will-mount login-page-will-mount + :name "login-page" + :mixins [(mx/local)]})) diff --git a/src/uxbox/ui/auth/register.cljs b/src/uxbox/ui/auth/register.cljs new file mode 100644 index 000000000..791c5b8cd --- /dev/null +++ b/src/uxbox/ui/auth/register.cljs @@ -0,0 +1,121 @@ +;; 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.ui.auth.register + (:require [sablono.core :as html :refer-macros [html]] + [lentes.core :as l] + [cuerdas.core :as str] + [rum.core :as rum] + [uxbox.router :as rt] + [uxbox.state :as st] + [uxbox.rstore :as rs] + [uxbox.schema :as us] + [uxbox.data.auth :as uda] + [uxbox.data.messages :as udm] + [uxbox.data.forms :as udf] + [uxbox.ui.forms :as forms] + [uxbox.ui.icons :as i] + [uxbox.ui.messages :as uum] + [uxbox.ui.navigation :as nav] + [uxbox.ui.mixins :as mx] + [uxbox.util.dom :as dom])) + + +;; --- Constants + +(def form-data + (-> (l/in [:forms :register]) + (l/focus-atom st/state))) + +(def form-errors + (-> (l/in [:errors :register]) + (l/focus-atom st/state))) + +(def set-value! + (partial udf/assign-field-value :register)) + +;; --- Register Form + +(defn- register-form-render + [own] + (let [form (rum/react form-data) + errors (rum/react form-errors) + valid? (us/valid? form uda/register-schema)] + (letfn [(on-change [field event] + (let [value (dom/event->value event)] + (rs/emit! (set-value! field value)))) + (on-submit [event] + (dom/prevent-default event) + (rs/emit! (uda/register form)))] + (html + [:form {:on-submit on-submit} + [:div.login-content + [:input.input-text + {:name "fullname" + :value (:fullname form "") + :on-change (partial on-change :fullname) + :placeholder "Full Name" + :type "text"}] + (forms/input-error errors :fullname) + + [:input.input-text + {:name "username" + :value (:username form "") + :on-change (partial on-change :username) + :placeholder "Username" + :type "text"}] + (forms/input-error errors :username) + + [:input.input-text + {:name "email" + :ref "email" + :value (:email form "") + :on-change (partial on-change :email) + :placeholder "Email" + :type "text"}] + (forms/input-error errors :email) + + [:input.input-text + {:name "password" + :ref "password" + :value (:password form "") + :on-change (partial on-change :password) + :placeholder "Password" + :type "password"}] + (forms/input-error errors :password) + + [:input.btn-primary + {:name "login" + :class (when-not valid? "btn-disabled") + :disabled (not valid?) + :value "Register" + :type "submit"}] + [:div.login-links + ;; [:a {:on-click #(rt/go :auth/recover-password)} "Forgot your password?"] + [:a {:on-click #(rt/go :auth/login)} "Already have an account?"]]]])))) + +(def register-form + (mx/component + {:render register-form-render + :name "register-form" + :mixins [mx/static rum/reactive]})) + +;; --- Register Page + +(defn- register-page-render + [own] + (html + [:div.login + [:div.login-body + (uum/messages) + [:a i/logo] + (register-form)]])) + +(def register-page + (mx/component + {:render register-page-render + :name "register-page" + :mixins [mx/static]}))