mirror of
https://github.com/penpot/penpot.git
synced 2026-05-13 20:13:58 +00:00
234 lines
6.7 KiB
Clojure
234 lines
6.7 KiB
Clojure
;; 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) UXBOX Labs SL
|
|
|
|
(ns app.main.data.users
|
|
(:require
|
|
[app.config :as cf]
|
|
[app.common.data :as d]
|
|
[app.common.spec :as us]
|
|
[app.common.uuid :as uuid]
|
|
[app.main.data.media :as di]
|
|
[app.main.data.messages :as dm]
|
|
[app.main.repo :as rp]
|
|
[app.main.store :as st]
|
|
[app.util.avatars :as avatars]
|
|
[app.util.i18n :as i18n :refer [tr]]
|
|
[app.util.router :as rt]
|
|
[app.util.storage :refer [storage]]
|
|
[app.util.theme :as theme]
|
|
[beicon.core :as rx]
|
|
[cljs.spec.alpha :as s]
|
|
[cuerdas.core :as str]
|
|
[potok.core :as ptk]))
|
|
|
|
;; --- Common Specs
|
|
|
|
(s/def ::id ::us/uuid)
|
|
(s/def ::fullname ::us/string)
|
|
(s/def ::email ::us/email)
|
|
(s/def ::password ::us/string)
|
|
(s/def ::lang (s/nilable ::us/string))
|
|
(s/def ::theme (s/nilable ::us/string))
|
|
(s/def ::created-at ::us/inst)
|
|
(s/def ::password-1 ::us/string)
|
|
(s/def ::password-2 ::us/string)
|
|
(s/def ::password-old ::us/string)
|
|
|
|
(s/def ::profile
|
|
(s/keys :req-un [::id]
|
|
:opt-un [::created-at
|
|
::fullname
|
|
::email
|
|
::lang
|
|
::theme]))
|
|
|
|
(defn fetch-teams
|
|
[]
|
|
(letfn [(on-fetched [state data]
|
|
(let [teams (d/index-by :id data)]
|
|
(assoc state :teams teams)))]
|
|
(ptk/reify ::fetch-teams
|
|
ptk/WatchEvent
|
|
(watch [_ state s]
|
|
(->> (rp/query! :teams)
|
|
(rx/map (fn [data] #(on-fetched % data))))))))
|
|
|
|
(defn profile-fetched
|
|
[{:keys [fullname id] :as data}]
|
|
(us/verify ::profile data)
|
|
(ptk/reify ::profile-fetched
|
|
IDeref
|
|
(-deref [_] data)
|
|
|
|
ptk/UpdateEvent
|
|
(update [_ state]
|
|
(-> state
|
|
(assoc :profile-id id)
|
|
(assoc :profile data)))
|
|
|
|
ptk/EffectEvent
|
|
(effect [_ state stream]
|
|
(let [profile (:profile state)]
|
|
(swap! storage assoc :profile profile)
|
|
(i18n/set-locale! (:lang profile))
|
|
(some-> (:theme profile)
|
|
(theme/set-current-theme!))))))
|
|
|
|
;; --- Fetch Profile
|
|
|
|
(defn fetch-profile
|
|
[]
|
|
(ptk/reify ::fetch-profile
|
|
ptk/WatchEvent
|
|
(watch [_ state stream]
|
|
(->> (rp/query! :profile)
|
|
(rx/map profile-fetched)))))
|
|
|
|
(defn fetch-profile-and-teams
|
|
"Event used mainly on application bootstrap; it fetches the profile
|
|
and if and only if the fetched profile corresponds to an
|
|
authenticated user; proceed to fetch teams."
|
|
[]
|
|
(ptk/reify ::fetch-profile-and-teams
|
|
ptk/WatchEvent
|
|
(watch [_ state stream]
|
|
(rx/merge
|
|
(rx/of (fetch-profile))
|
|
(->> stream
|
|
(rx/filter (ptk/type? ::profile-fetched))
|
|
(rx/take 1)
|
|
(rx/map deref)
|
|
(rx/mapcat (fn [profile]
|
|
(if (= uuid/zero (:id profile))
|
|
(rx/empty)
|
|
(rx/of (fetch-teams))))))))))
|
|
|
|
;; --- Update Profile
|
|
|
|
(defn update-profile
|
|
[data]
|
|
(us/assert ::profile data)
|
|
(ptk/reify ::update-profile
|
|
ptk/WatchEvent
|
|
(watch [_ state stream]
|
|
(let [mdata (meta data)
|
|
on-success (:on-success mdata identity)
|
|
on-error (:on-error mdata #(rx/throw %))]
|
|
(->> (rp/mutation :update-profile data)
|
|
(rx/catch on-error)
|
|
(rx/mapcat
|
|
(fn [_]
|
|
(rx/merge
|
|
(->> stream
|
|
(rx/filter (ptk/type? ::profile-fetched))
|
|
(rx/take 1)
|
|
(rx/tap on-success)
|
|
(rx/ignore))
|
|
(rx/of (profile-fetched data))))))))))
|
|
|
|
|
|
;; --- Request Email Change
|
|
|
|
(defn request-email-change
|
|
[{:keys [email] :as data}]
|
|
(us/assert ::us/email email)
|
|
(ptk/reify ::request-email-change
|
|
ptk/WatchEvent
|
|
(watch [_ state stream]
|
|
(let [{:keys [on-error on-success]
|
|
:or {on-error identity
|
|
on-success identity}} (meta data)]
|
|
(->> (rp/mutation :request-email-change data)
|
|
(rx/tap on-success)
|
|
(rx/catch on-error))))))
|
|
|
|
;; --- Cancel Email Change
|
|
|
|
(def cancel-email-change
|
|
(ptk/reify ::cancel-email-change
|
|
ptk/WatchEvent
|
|
(watch [_ state stream]
|
|
(->> (rp/mutation :cancel-email-change {})
|
|
(rx/map (constantly (fetch-profile)))))))
|
|
|
|
;; --- Update Password (Form)
|
|
|
|
(s/def ::update-password
|
|
(s/keys :req-un [::password-1
|
|
::password-2
|
|
::password-old]))
|
|
|
|
(defn update-password
|
|
[data]
|
|
(us/verify ::update-password data)
|
|
(ptk/reify ::update-password
|
|
ptk/WatchEvent
|
|
(watch [_ state s]
|
|
(let [{:keys [on-error on-success]
|
|
:or {on-error identity
|
|
on-success identity}} (meta data)
|
|
params {:old-password (:password-old data)
|
|
:password (:password-1 data)}]
|
|
(->> (rp/mutation :update-profile-password params)
|
|
(rx/tap on-success)
|
|
(rx/catch (fn [err]
|
|
(on-error err)
|
|
(rx/empty)))
|
|
(rx/ignore))))))
|
|
|
|
|
|
(defn mark-onboarding-as-viewed
|
|
([] (mark-onboarding-as-viewed nil))
|
|
([{:keys [version]}]
|
|
(ptk/reify ::mark-oboarding-as-viewed
|
|
ptk/WatchEvent
|
|
(watch [_ state stream]
|
|
(let [version (or version (:main @cf/version))
|
|
props (-> (get-in state [:profile :props])
|
|
(assoc :onboarding-viewed true)
|
|
(assoc :release-notes-viewed version))]
|
|
(->> (rp/mutation :update-profile-props {:props props})
|
|
(rx/map (constantly (fetch-profile)))))))))
|
|
|
|
;; --- Update Photo
|
|
|
|
(defn update-photo
|
|
[file]
|
|
(us/verify ::di/blob file)
|
|
(ptk/reify ::update-photo
|
|
ptk/WatchEvent
|
|
(watch [_ state stream]
|
|
(let [on-success di/notify-finished-loading
|
|
on-error #(do (di/notify-finished-loading)
|
|
(di/process-error %))
|
|
|
|
prepare
|
|
(fn [file]
|
|
{:file file})]
|
|
|
|
(di/notify-start-loading)
|
|
(->> (rx/of file)
|
|
(rx/map di/validate-file)
|
|
(rx/map prepare)
|
|
(rx/mapcat #(rp/mutation :update-profile-photo %))
|
|
(rx/do on-success)
|
|
(rx/map (constantly (fetch-profile)))
|
|
(rx/catch on-error))))))
|
|
|
|
|
|
(defn fetch-users
|
|
[{:keys [team-id] :as params}]
|
|
(us/assert ::us/uuid team-id)
|
|
(letfn [(fetched [users state]
|
|
(->> users
|
|
(d/index-by :id)
|
|
(assoc state :users)))]
|
|
(ptk/reify ::fetch-team-users
|
|
ptk/WatchEvent
|
|
(watch [_ state stream]
|
|
(->> (rp/query :team-users {:team-id team-id})
|
|
(rx/map #(partial fetched %)))))))
|