diff --git a/frontend/src/uxbox/main.cljs b/frontend/src/uxbox/main.cljs index 54b688651..552c10b8d 100644 --- a/frontend/src/uxbox/main.cljs +++ b/frontend/src/uxbox/main.cljs @@ -67,7 +67,7 @@ (add-watch html-history/path ::main #(on-navigate router %4)) (when (:auth storage) - (st/emit! (udu/fetch-profile))) + (st/emit! udu/fetch-profile)) (mf/mount (mf/element ui/app) (dom/get-element "app")) (mf/mount (lightbox) (dom/get-element "lightbox")) diff --git a/frontend/src/uxbox/main/data/auth.cljs b/frontend/src/uxbox/main/data/auth.cljs index 591d1513d..a6d80b6c4 100644 --- a/frontend/src/uxbox/main/data/auth.cljs +++ b/frontend/src/uxbox/main/data/auth.cljs @@ -25,8 +25,6 @@ ;; --- Logged In -;; TODO: add spec - (defn logged-in [data] (reify @@ -40,7 +38,7 @@ ptk/WatchEvent (watch [this state s] (swap! storage assoc :auth data) - (rx/of (du/fetch-profile) + (rx/of du/fetch-profile (rt/navigate :dashboard/projects))))) (defn logged-in? diff --git a/frontend/src/uxbox/main/data/pages.cljs b/frontend/src/uxbox/main/data/pages.cljs index 8c85f7cf7..2b79fcfea 100644 --- a/frontend/src/uxbox/main/data/pages.cljs +++ b/frontend/src/uxbox/main/data/pages.cljs @@ -139,46 +139,44 @@ [state id] (update state :packed-pages dissoc id)) - - ;; --- Pages Fetched -(deftype PagesFetched [id pages] - IDeref - (-deref [_] (list id pages)) - - ptk/UpdateEvent - (update [_ state] - (let [get-order #(get-in % [:metadata :order]) - pages (sort-by get-order pages) - page-ids (into [] (map :id) pages)] - (as-> state $ - (assoc-in $ [:projects id :pages] page-ids) - (reduce unpack-page $ pages) - (reduce assoc-packed-page $ pages))))) - (defn pages-fetched [id pages] - {:pre [(uuid? id) (coll? pages)]} - (PagesFetched. id pages)) + (s/assert ::us/uuid id) + (s/assert ::us/coll pages) + (reify + IDeref + (-deref [_] (list id pages)) + + ptk/EventType + (type [_] ::page-fetched) + + ptk/UpdateEvent + (update [_ state] + (let [get-order #(get-in % [:metadata :order]) + pages (sort-by get-order pages) + page-ids (into [] (map :id) pages)] + (as-> state $ + (assoc-in $ [:projects id :pages] page-ids) + (reduce unpack-page $ pages) + (reduce assoc-packed-page $ pages)))))) (defn pages-fetched? [v] - (instance? PagesFetched v)) + (= ::page-fetched (ptk/type v))) ;; --- Fetch Pages (by project id) -(deftype FetchPages [id] - ptk/WatchEvent - (watch [_ state s] - (->> (rp/req :fetch/pages-by-project {:project id}) - (rx/map :payload) - (rx/map #(pages-fetched id %))))) - (defn fetch-pages [id] - {:pre [(uuid? id)]} - (FetchPages. id)) + (s/assert ::us/uuid id) + (reify + ptk/WatchEvent + (watch [_ state s] + (->> (rp/req :fetch/pages-by-project {:project id}) + (rx/map :payload) + (rx/map #(pages-fetched id %)))))) ;; --- Page Created @@ -189,7 +187,7 @@ (defn page-created [data] - (s/assert ::page-created-event data) + (s/assert ::page-created-params data) (reify ptk/UpdateEvent (update [_ state] @@ -203,14 +201,14 @@ (watch [_ state stream] (rx/of (rehash-pages (:project data)))))) -;; --- Create Page +;; --- Create Page Form -(s/def ::created-page-params +(s/def ::form-created-page-params (s/keys :req-un [::name ::project ::width ::height])) -(defn create-page +(defn form->create-page [{:keys [name project width height layout] :as data}] - (s/assert ::created-page-params data) + (s/assert ::form-created-page-params data) (reify ptk/WatchEvent (watch [this state s] @@ -232,6 +230,25 @@ (rx/map :payload) (rx/map page-created)))))) +;; --- Update Page Form + +(s/def ::form-update-page-params + (s/keys :req-un [::id ::name ::width ::height])) + +(defn form->update-page + [{:keys [id name width height] :as data}] + (s/assert ::form-update-page-params data) + (reify + IPageUpdate + ptk/UpdateEvent + (update [_ state] + (update-in state [:pages id] + (fn [page] + (-> (assoc page :name name) + (assoc-in [:name] name) + (assoc-in [:metadata :width] width) + (assoc-in [:metadata :height] height))))))) + ;; --- Page Persisted (defn page-persisted @@ -321,10 +338,9 @@ ;; --- Update Page -(defn update-page - [id data] +(defn update-page-attrs + [{:keys [id] :as data}] (s/assert ::page-entity data) - (s/assert ::id id) (reify IPageUpdate ptk/UpdateEvent @@ -381,27 +397,6 @@ pages (vec (concat before [page-id] after))] (assoc-in state [:projects project-id :pages] pages))))) -;; --- Persist Page Form -;; -;; A specialized event for persist data -;; from the update page form. - -(s/def ::persist-page-update-form-params - (s/keys :req-un [::id ::name ::width ::height])) - -(defn persist-page-update-form - [{:keys [id name width height] :as data}] - (s/assert ::persist-page-update-form-params data) - (reify - ptk/UpdateEvent - (update [_ state] - (update-in state [:pages id] - (fn [page] - (-> (assoc page :name name) - (assoc-in [:name] name) - (assoc-in [:metadata :width] width) - (assoc-in [:metadata :height] height))))))) - ;; --- Delete Page (by id) (defn delete-page @@ -419,31 +414,28 @@ ;; --- Watch Page Changes -(deftype WatchPageChanges [id] - ptk/WatchEvent - (watch [_ state stream] - (let [stopper (->> stream - (rx/filter #(= % ::stop-page-watcher)) - (rx/take 1))] - (rx/merge - (->> stream - (rx/filter #(or (satisfies? IPageUpdate %) - (= ::page-update %))) - (rx/take-until stopper) - (rx/debounce 1000) - (rx/mapcat #(rx/merge (rx/of (persist-page id)) - (->> (rx/filter page-persisted? stream) - (rx/take 1) - (rx/ignore))))) - (->> stream - (rx/filter #(satisfies? IMetadataUpdate %)) - (rx/take-until stopper) - (rx/debounce 1000) - (rx/mapcat #(rx/merge (rx/of (persist-metadata id)) - (->> (rx/filter metadata-persisted? stream) - (rx/take 1) - (rx/ignore))))))))) - (defn watch-page-changes [id] - (WatchPageChanges. id)) + (s/assert ::us/uuid id) + (reify + ptk/WatchEvent + (watch [_ state stream] + (let [stopper (rx/filter #(= % ::stop-page-watcher) stream)] + (->> (rx/merge + (->> stream + (rx/filter #(or (satisfies? IPageUpdate %) + (= ::page-update %))) + (rx/debounce 1000) + (rx/mapcat #(rx/merge (rx/of (persist-page id)) + (->> (rx/filter page-persisted? stream) + (rx/take 1) + (rx/ignore))))) + (->> stream + (rx/filter #(satisfies? IMetadataUpdate %)) + (rx/debounce 1000) + (rx/mapcat #(rx/merge (rx/of (persist-metadata id)) + (->> (rx/filter metadata-persisted? stream) + (rx/take 1) + (rx/ignore)))))) + (rx/take-until stopper)))))) + diff --git a/frontend/src/uxbox/main/data/projects.cljs b/frontend/src/uxbox/main/data/projects.cljs index 9d4bb03a3..d6cb20b59 100644 --- a/frontend/src/uxbox/main/data/projects.cljs +++ b/frontend/src/uxbox/main/data/projects.cljs @@ -173,7 +173,7 @@ (rx/map :payload) (rx/mapcat (fn [{:keys [id] :as project}] (rx/of #(assoc-project % project) - (udp/create-page (assoc params :project id))))))))) + (udp/form->create-page (assoc params :project id))))))))) ;; --- Go To Project diff --git a/frontend/src/uxbox/main/data/users.cljs b/frontend/src/uxbox/main/data/users.cljs index 93919375f..c5290e555 100644 --- a/frontend/src/uxbox/main/data/users.cljs +++ b/frontend/src/uxbox/main/data/users.cljs @@ -2,7 +2,7 @@ ;; 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 +;; Copyright (c) 2016-2019 Andrey Antukh (ns uxbox.main.data.users (:require @@ -15,62 +15,64 @@ [uxbox.util.spec :as us] [uxbox.util.storage :refer [storage]])) +;; --- Common Specs + +(s/def ::id uuid?) +(s/def ::username string?) +(s/def ::fullname string?) +(s/def ::email ::us/email) +(s/def ::password string?) +(s/def ::language string?) +(s/def ::photo string?) +(s/def ::created-at inst?) +(s/def ::password-1 string?) +(s/def ::password-2 string?) +(s/def ::password-old string?) + ;; --- Profile Fetched +(s/def ::profile-fetched-params + (s/keys :req-un [::id + ::username + ::fullname + ::email + ::created-at + ::photo])) + (defn profile-fetched [data] + (s/assert ::profile-fetched-params data) (reify ptk/UpdateEvent - (update [this state] + (update [_ state] (assoc state :profile data)) ptk/EffectEvent - (effect [this state stream] + (effect [_ state stream] (swap! storage assoc :profile data) - ;; (prn "profile-fetched" data) (when-let [lang (get-in data [:metadata :language])] (i18n/set-current-locale! lang))))) ;; --- Fetch Profile -(deftype FetchProfile [] - ptk/WatchEvent - (watch [_ state s] - (->> (rp/req :fetch/profile) - (rx/map :payload) - (rx/map profile-fetched)))) - -(defn fetch-profile - [] - (FetchProfile.)) - -;; --- Profile Updated - -(deftype ProfileUpdated [data] - ptk/WatchEvent - (watch [_ state s] - (rx/of (profile-fetched data) - (uum/info (tr "settings.profile.profile-saved"))))) - -(defn profile-updated - [data] - (ProfileUpdated. data)) +(def fetch-profile + (reify + ptk/WatchEvent + (watch [_ state s] + (->> (rp/req :fetch/profile) + (rx/map :payload) + (rx/map profile-fetched))))) ;; --- Update Profile -(s/def ::fullname string?) -(s/def ::email ::us/email) -(s/def ::password string?) -(s/def ::language string?) - (s/def ::update-profile-params (s/keys :req-un [::fullname ::email ::username ::language])) -(defn update-profile - [data {:keys [on-success on-error]}] +(defn form->update-profile + [data on-success on-error] (s/assert ::update-profile-params data) (s/assert ::us/fn on-error) (s/assert ::us/fn on-success) @@ -88,16 +90,11 @@ (->> (rp/req :update/profile data) (rx/map :payload) (rx/do on-success) - (rx/map profile-updated) - ;; (rx/map profile-fetched) + (rx/map profile-fetched) (rx/catch rp/client-error? handle-error))))))) ;; --- Update Password (Form) -(s/def ::password-1 string?) -(s/def ::password-2 string?) -(s/def ::password-old string?) - (s/def ::update-password-params (s/keys :req-un [::password-1 ::password-2 @@ -128,7 +125,7 @@ (watch [_ state stream] (->> (rp/req :update/profile-photo {:file file}) (rx/do done) - (rx/map fetch-profile)))) + (rx/map (constantly fetch-profile))))) (defn update-photo ([file] (update-photo file (constantly nil))) diff --git a/frontend/src/uxbox/main/ui/auth/login.cljs b/frontend/src/uxbox/main/ui/auth/login.cljs index a37c7e6ed..5510e02f2 100644 --- a/frontend/src/uxbox/main/ui/auth/login.cljs +++ b/frontend/src/uxbox/main/ui/auth/login.cljs @@ -7,20 +7,21 @@ (ns uxbox.main.ui.auth.login (:require - [rumext.alpha :as mf] [cljs.spec.alpha :as s] + [rumext.alpha :as mf] [uxbox.builtins.icons :as i] [uxbox.config :as cfg] [uxbox.main.data.auth :as da] [uxbox.main.store :as st] [uxbox.main.ui.messages :refer [messages-widget]] [uxbox.util.dom :as dom] - [uxbox.util.forms :as fm2] + [uxbox.util.forms :as fm] [uxbox.util.i18n :refer [tr]] - [uxbox.util.router :as rt])) + [uxbox.util.router :as rt] + [uxbox.util.spec :as us])) -(s/def ::username ::fm2/not-empty-string) -(s/def ::password ::fm2/not-empty-string) +(s/def ::username ::us/not-empty-string) +(s/def ::password ::us/not-empty-string) (s/def ::login-form (s/keys :req-un [::username ::password])) @@ -44,8 +45,7 @@ (mf/defc login-form [] - (let [{:keys [data] :as form} (fm2/use-form ::login-form {})] - (prn "login-form" form) + (let [{:keys [data] :as form} (fm/use-form ::login-form {})] [:form {:on-submit #(on-submit % form)} [:div.login-content (when cfg/isdemo @@ -55,18 +55,18 @@ {:name "username" :tab-index "2" :value (:username data "") - :class (fm2/error-class form :username) - :on-blur (fm2/on-input-blur form :username) - :on-change (fm2/on-input-change form :username) + :class (fm/error-class form :username) + :on-blur (fm/on-input-blur form :username) + :on-change (fm/on-input-change form :username) :placeholder (tr "auth.email-or-username") :type "text"}] [:input.input-text {:name "password" :tab-index "3" :value (:password data "") - :class (fm2/error-class form :password) - :on-blur (fm2/on-input-blur form :password) - :on-change (fm2/on-input-change form :password) + :class (fm/error-class form :password) + :on-blur (fm/on-input-blur form :password) + :on-change (fm/on-input-change form :password) :placeholder (tr "auth.password") :type "password"}] [:input.btn-primary diff --git a/frontend/src/uxbox/main/ui/settings/profile.cljs b/frontend/src/uxbox/main/ui/settings/profile.cljs index 82ec47fe5..0897eec68 100644 --- a/frontend/src/uxbox/main/ui/settings/profile.cljs +++ b/frontend/src/uxbox/main/ui/settings/profile.cljs @@ -66,10 +66,8 @@ (dom/prevent-default event) (let [data (:clean-data 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)))) + on-error #(on-error % form)] + (st/emit! (udu/form->update-profile data on-success on-error)))) ;; --- Profile Form diff --git a/frontend/src/uxbox/main/ui/users.cljs b/frontend/src/uxbox/main/ui/users.cljs index 6283c8706..bf2004f8c 100644 --- a/frontend/src/uxbox/main/ui/users.cljs +++ b/frontend/src/uxbox/main/ui/users.cljs @@ -49,7 +49,7 @@ (l/derive st/state))) (mf/defc user - [_] + [props] (let [open (mf/use-state false) profile (mf/deref profile-ref) photo (if (str/empty? (:photo profile "")) diff --git a/frontend/src/uxbox/main/ui/workspace/sidebar/options/page.cljs b/frontend/src/uxbox/main/ui/workspace/sidebar/options/page.cljs index 980a6962f..861f3c3d0 100644 --- a/frontend/src/uxbox/main/ui/workspace/sidebar/options/page.cljs +++ b/frontend/src/uxbox/main/ui/workspace/sidebar/options/page.cljs @@ -43,8 +43,8 @@ (on-name-change [event] (let [value (-> (dom/event->value event) (str/trim))] - (st/emit! (->> (assoc page :name value) - (udp/update-page (:id page)))))) + (st/emit! (-> (assoc page :name value) + (udp/update-page-attrs))))) (show-color-picker [event] (let [x (.-clientX event) diff --git a/frontend/src/uxbox/main/ui/workspace/sidebar/sitemap_forms.cljs b/frontend/src/uxbox/main/ui/workspace/sidebar/sitemap_forms.cljs index 4ec95b741..15c16e69e 100644 --- a/frontend/src/uxbox/main/ui/workspace/sidebar/sitemap_forms.cljs +++ b/frontend/src/uxbox/main/ui/workspace/sidebar/sitemap_forms.cljs @@ -43,8 +43,8 @@ (modal/hide!) (let [data (:clean-data form)] (if (nil? (:id data)) - (st/emit! (udp/create-page data)) - (st/emit! (udp/persist-page-update-form data))))) + (st/emit! (udp/form->create-page data)) + (st/emit! (udp/form->update-page data))))) (defn- swap-size [event {:keys [data] :as form}] diff --git a/frontend/src/uxbox/util/spec.cljs b/frontend/src/uxbox/util/spec.cljs index 904f0392d..6d706668d 100644 --- a/frontend/src/uxbox/util/spec.cljs +++ b/frontend/src/uxbox/util/spec.cljs @@ -54,6 +54,7 @@ (s/def ::inst inst?) (s/def ::keyword keyword?) (s/def ::fn fn?) +(s/def ::coll coll?) (s/def ::not-empty-string (s/and string? #(not (str/empty? %))))