mirror of
https://github.com/penpot/penpot.git
synced 2025-05-31 23:01:37 +02:00
♻️ Refactor profile & language loading.
This commit is contained in:
parent
08dc1870bf
commit
406157c06c
7 changed files with 74 additions and 39 deletions
|
@ -9,3 +9,4 @@
|
||||||
(goog-define url "http://127.0.0.1:6060/api")
|
(goog-define url "http://127.0.0.1:6060/api")
|
||||||
(goog-define viewurl "/view/index.html")
|
(goog-define viewurl "/view/index.html")
|
||||||
(goog-define isdemo false)
|
(goog-define isdemo false)
|
||||||
|
(goog-define default-language "en")
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
(ns ^:figwheel-hooks uxbox.main
|
(ns ^:figwheel-hooks uxbox.main
|
||||||
(:require
|
(:require
|
||||||
[rumext.core :as mx]
|
[rumext.alpha :as mf]
|
||||||
[uxbox.main.data.auth :refer [logout]]
|
[uxbox.main.data.auth :refer [logout]]
|
||||||
[uxbox.main.data.users :as udu]
|
[uxbox.main.data.users :as udu]
|
||||||
[uxbox.main.locales.en :as en]
|
[uxbox.main.locales.en :as en]
|
||||||
|
@ -20,6 +20,7 @@
|
||||||
[uxbox.util.i18n :as i18n :refer [tr]]
|
[uxbox.util.i18n :as i18n :refer [tr]]
|
||||||
[uxbox.util.messages :as uum]
|
[uxbox.util.messages :as uum]
|
||||||
[uxbox.util.router :as rt]
|
[uxbox.util.router :as rt]
|
||||||
|
[uxbox.util.storage :refer [storage]]
|
||||||
[uxbox.util.timers :as ts]))
|
[uxbox.util.timers :as ts]))
|
||||||
|
|
||||||
;; --- i18n
|
;; --- i18n
|
||||||
|
@ -28,8 +29,8 @@
|
||||||
|
|
||||||
(i18n/update-locales! (fn [locales]
|
(i18n/update-locales! (fn [locales]
|
||||||
(-> locales
|
(-> locales
|
||||||
(assoc :en en/locales)
|
(assoc "en" en/locales)
|
||||||
(assoc :fr fr/locales))))
|
(assoc "fr" fr/locales))))
|
||||||
|
|
||||||
(i18n/on-locale-change!
|
(i18n/on-locale-change!
|
||||||
(fn [new old]
|
(fn [new old]
|
||||||
|
@ -60,11 +61,12 @@
|
||||||
(st/emit! #(assoc % :router router))
|
(st/emit! #(assoc % :router router))
|
||||||
(add-watch html-history/path ::main #(on-navigate router %4))
|
(add-watch html-history/path ::main #(on-navigate router %4))
|
||||||
|
|
||||||
(st/emit! (udu/fetch-profile))
|
(when (:auth storage)
|
||||||
|
(st/emit! (udu/fetch-profile)))
|
||||||
|
|
||||||
(mx/mount (ui/app) (dom/get-element "app"))
|
(mf/mount (ui/app) (dom/get-element "app"))
|
||||||
(mx/mount (lightbox) (dom/get-element "lightbox"))
|
(mf/mount (lightbox) (dom/get-element "lightbox"))
|
||||||
(mx/mount (loader) (dom/get-element "loader"))
|
(mf/mount (loader) (dom/get-element "loader"))
|
||||||
|
|
||||||
(on-navigate router cpath)))
|
(on-navigate router cpath)))
|
||||||
|
|
||||||
|
@ -76,9 +78,9 @@
|
||||||
(defn reinit
|
(defn reinit
|
||||||
[]
|
[]
|
||||||
(remove-watch html-history/path ::main)
|
(remove-watch html-history/path ::main)
|
||||||
(.unmountComponentAtNode js/ReactDOM (dom/get-element "app"))
|
(mf/unmount (dom/get-element "app"))
|
||||||
(.unmountComponentAtNode js/ReactDOM (dom/get-element "lightbox"))
|
(mf/unmount (dom/get-element "lightbox"))
|
||||||
(.unmountComponentAtNode js/ReactDOM (dom/get-element "loader"))
|
(mf/unmount (dom/get-element "loader"))
|
||||||
(init-ui))
|
(init-ui))
|
||||||
|
|
||||||
(defn ^:after-load after-load
|
(defn ^:after-load after-load
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
[uxbox.util.messages :as uum]
|
[uxbox.util.messages :as uum]
|
||||||
[uxbox.util.router :as rt]
|
[uxbox.util.router :as rt]
|
||||||
[uxbox.util.spec :as us]
|
[uxbox.util.spec :as us]
|
||||||
[uxbox.util.i18n :refer (tr)]
|
[uxbox.util.i18n :as i18n :refer [tr]]
|
||||||
[uxbox.util.storage :refer [storage]]))
|
[uxbox.util.storage :refer [storage]]))
|
||||||
|
|
||||||
(s/def ::username string?)
|
(s/def ::username string?)
|
||||||
|
@ -74,16 +74,26 @@
|
||||||
|
|
||||||
;; --- Logout
|
;; --- Logout
|
||||||
|
|
||||||
(defrecord Logout []
|
(defrecord ClearUserData []
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(swap! storage dissoc :auth)
|
|
||||||
(merge state (dissoc initial-state :route :router)))
|
(merge state (dissoc initial-state :route :router)))
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state s]
|
(watch [_ state s]
|
||||||
(->> (rp/req :auth/logout)
|
(->> (rp/req :auth/logout)
|
||||||
(rx/map (constantly (rt/nav :auth/login))))))
|
(rx/ignore)))
|
||||||
|
|
||||||
|
ptk/EffectEvent
|
||||||
|
(effect [_ state s]
|
||||||
|
(reset! storage {})
|
||||||
|
(i18n/set-default-locale!)))
|
||||||
|
|
||||||
|
(defrecord Logout []
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state s]
|
||||||
|
(rx/of (rt/nav :auth/login)
|
||||||
|
(->ClearUserData))))
|
||||||
|
|
||||||
(defn logout
|
(defn logout
|
||||||
[]
|
[]
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
[cljs.spec.alpha :as s]
|
[cljs.spec.alpha :as s]
|
||||||
[potok.core :as ptk]
|
[potok.core :as ptk]
|
||||||
[uxbox.main.repo :as rp]
|
[uxbox.main.repo :as rp]
|
||||||
[uxbox.util.i18n :refer (tr)]
|
[uxbox.util.i18n :as i18n :refer (tr)]
|
||||||
[uxbox.util.messages :as uum]
|
[uxbox.util.messages :as uum]
|
||||||
[uxbox.util.spec :as us]
|
[uxbox.util.spec :as us]
|
||||||
[uxbox.util.storage :refer [storage]]))
|
[uxbox.util.storage :refer [storage]]))
|
||||||
|
@ -24,7 +24,10 @@
|
||||||
|
|
||||||
ptk/EffectEvent
|
ptk/EffectEvent
|
||||||
(effect [this state stream]
|
(effect [this state stream]
|
||||||
(swap! storage assoc :profile data)))
|
(swap! storage assoc :profile data)
|
||||||
|
;; (prn "profile-fetched" data)
|
||||||
|
(when-let [lang (get-in data [:metadata :language])]
|
||||||
|
(i18n/set-current-locale! lang))))
|
||||||
|
|
||||||
(defn profile-fetched
|
(defn profile-fetched
|
||||||
[data]
|
[data]
|
||||||
|
@ -63,22 +66,28 @@
|
||||||
(letfn [(handle-error [{payload :payload}]
|
(letfn [(handle-error [{payload :payload}]
|
||||||
(on-error payload)
|
(on-error payload)
|
||||||
(rx/empty))]
|
(rx/empty))]
|
||||||
|
(let [data (-> (:profile state)
|
||||||
|
(assoc :fullname (:fullname data))
|
||||||
|
(assoc :email (:email data))
|
||||||
|
(assoc :username (:username data))
|
||||||
|
(assoc-in [:metadata :language] (:language data)))]
|
||||||
|
(prn "update-profile" data)
|
||||||
(->> (rp/req :update/profile data)
|
(->> (rp/req :update/profile data)
|
||||||
(rx/map :payload)
|
(rx/map :payload)
|
||||||
(rx/do on-success)
|
(rx/do on-success)
|
||||||
(rx/map profile-updated)
|
(rx/map profile-updated)
|
||||||
(rx/catch rp/client-error? handle-error)))))
|
(rx/catch rp/client-error? handle-error))))))
|
||||||
|
|
||||||
(s/def ::fullname string?)
|
(s/def ::fullname string?)
|
||||||
(s/def ::email us/email?)
|
(s/def ::email us/email?)
|
||||||
(s/def ::username string?)
|
(s/def ::username string?)
|
||||||
(s/def ::theme string?)
|
(s/def ::language string?)
|
||||||
|
|
||||||
(s/def ::update-profile
|
(s/def ::update-profile
|
||||||
(s/keys :req-un [::fullname
|
(s/keys :req-un [::fullname
|
||||||
::email
|
::email
|
||||||
::username
|
::language
|
||||||
::theme]))
|
::username]))
|
||||||
|
|
||||||
(defn update-profile
|
(defn update-profile
|
||||||
[data on-success on-error]
|
[data on-success on-error]
|
||||||
|
|
|
@ -28,17 +28,26 @@
|
||||||
(def assoc-error (partial fm/assoc-error :profile))
|
(def assoc-error (partial fm/assoc-error :profile))
|
||||||
(def clear-form (partial fm/clear-form :profile))
|
(def clear-form (partial fm/clear-form :profile))
|
||||||
|
|
||||||
|
(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 profile-ref
|
||||||
(-> (l/key :profile)
|
(-> (comp (l/key :profile)
|
||||||
|
(l/lens profile->form))
|
||||||
(l/derive st/state)))
|
(l/derive st/state)))
|
||||||
|
|
||||||
(s/def ::fullname ::fm/non-empty-string)
|
(s/def ::fullname ::fm/non-empty-string)
|
||||||
(s/def ::username ::fm/non-empty-string)
|
(s/def ::username ::fm/non-empty-string)
|
||||||
(s/def ::email ::fm/email)
|
(s/def ::email ::fm/email)
|
||||||
|
(s/def ::language #{"en" "fr"})
|
||||||
|
|
||||||
(s/def ::profile-form
|
(s/def ::profile-form
|
||||||
(s/keys :req-un [::fullname
|
(s/keys :req-un [::fullname
|
||||||
::username
|
::username
|
||||||
|
::language
|
||||||
::email]))
|
::email]))
|
||||||
|
|
||||||
(defn- on-error
|
(defn- on-error
|
||||||
|
@ -61,18 +70,13 @@
|
||||||
:mixins [mf/memo mf/reactive mf/sync-render (fm/clear-mixin st/store :profile)]
|
:mixins [mf/memo mf/reactive mf/sync-render (fm/clear-mixin st/store :profile)]
|
||||||
:render
|
:render
|
||||||
(fn [own props]
|
(fn [own props]
|
||||||
(let [data (merge {:theme "light"}
|
(let [data (merge {:language @i18n/locale}
|
||||||
(mf/react profile-ref)
|
(mf/react profile-ref)
|
||||||
(mf/react form-data))
|
(mf/react form-data))
|
||||||
errors (mf/react form-errors)
|
errors (mf/react form-errors)
|
||||||
valid? (fm/valid? ::profile-form data)
|
valid? (fm/valid? ::profile-form data)
|
||||||
theme (:theme data)
|
|
||||||
on-success #(st/emit! (clear-form))
|
on-success #(st/emit! (clear-form))
|
||||||
on-submit #(st/emit! (udu/update-profile data on-success on-error))
|
on-submit #(st/emit! (udu/update-profile data on-success on-error))]
|
||||||
on-lang-change (fn [event]
|
|
||||||
(let [lang (read-string (dom/event->value event))]
|
|
||||||
(prn "on-lang-change" lang)
|
|
||||||
(i18n/set-current-locale! lang)))]
|
|
||||||
[:form.profile-form
|
[:form.profile-form
|
||||||
[:span.user-settings-label (tr "settings.profile.section-basic-data")]
|
[:span.user-settings-label (tr "settings.profile.section-basic-data")]
|
||||||
[:input.input-text
|
[:input.input-text
|
||||||
|
@ -94,10 +98,10 @@
|
||||||
(fm/input-error errors :email)
|
(fm/input-error errors :email)
|
||||||
|
|
||||||
[:span.user-settings-label (tr "settings.profile.section-i18n-data")]
|
[:span.user-settings-label (tr "settings.profile.section-i18n-data")]
|
||||||
[:select.input-select {:value (pr-str (mf/deref i18n/locale))
|
[:select.input-select {:value (:language data)
|
||||||
:on-change on-lang-change}
|
:on-change #(on-field-change % :language)}
|
||||||
[:option {:value ":en"} "English"]
|
[:option {:value "en"} "English"]
|
||||||
[:option {:value ":fr"} "Français"]]
|
[:option {:value "fr"} "Français"]]
|
||||||
|
|
||||||
[:input.btn-primary
|
[:input.btn-primary
|
||||||
{:type "button"
|
{:type "button"
|
||||||
|
|
|
@ -8,11 +8,16 @@
|
||||||
(ns uxbox.util.i18n
|
(ns uxbox.util.i18n
|
||||||
"A i18n foundation."
|
"A i18n foundation."
|
||||||
(:require [cuerdas.core :as str]
|
(:require [cuerdas.core :as str]
|
||||||
[uxbox.util.storage :refer (storage)]))
|
[uxbox.config :as cfg]
|
||||||
|
[uxbox.util.storage :refer [storage]]))
|
||||||
|
|
||||||
(defonce locale (atom (get storage ::locale :en)))
|
(defonce locale (atom (get storage ::locale cfg/default-language)))
|
||||||
(defonce state (atom {}))
|
(defonce state (atom {}))
|
||||||
|
|
||||||
|
(defn set-default-locale!
|
||||||
|
[]
|
||||||
|
(set-current-locale! cfg/default-language))
|
||||||
|
|
||||||
(defn update-locales!
|
(defn update-locales!
|
||||||
[callback]
|
[callback]
|
||||||
(swap! state callback))
|
(swap! state callback))
|
||||||
|
|
|
@ -30,6 +30,10 @@
|
||||||
(when (not= *target* "nodejs")
|
(when (not= *target* "nodejs")
|
||||||
(add-watch data :sub #(persist alias %4)))
|
(add-watch data :sub #(persist alias %4)))
|
||||||
(reify
|
(reify
|
||||||
|
Object
|
||||||
|
(toString [_]
|
||||||
|
(str "Storage" (pr-str @data)))
|
||||||
|
|
||||||
ICounted
|
ICounted
|
||||||
(-count [_]
|
(-count [_]
|
||||||
(count @data))
|
(count @data))
|
||||||
|
@ -40,7 +44,7 @@
|
||||||
|
|
||||||
IReset
|
IReset
|
||||||
(-reset! [self newval]
|
(-reset! [self newval]
|
||||||
(-reset! data newval))
|
(reset! data newval))
|
||||||
|
|
||||||
ISwap
|
ISwap
|
||||||
(-swap! [self f]
|
(-swap! [self f]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue