♻️ Refactor frontend code for adapt to new banners.

This commit is contained in:
Andrey Antukh 2020-05-26 13:56:32 +02:00
parent b331489741
commit a27828ed79
25 changed files with 387 additions and 369 deletions

View file

@ -57,7 +57,8 @@
params {:email email
:password password
:scope "webapp"}]
(->> (rp/mutation :login params)
(->> (rx/timer 100)
(rx/mapcat #(rp/mutation :login params))
(rx/tap on-success)
(rx/catch (fn [err]
(on-error err)

View file

@ -9,13 +9,13 @@
(ns uxbox.main.data.messages
(:require
[beicon.core :as rx]
[cljs.spec.alpha :as s]
[potok.core :as ptk]
[beicon.core :as rx]
[uxbox.common.data :as d]
[uxbox.common.exceptions :as ex]
[uxbox.common.pages :as cp]
[uxbox.common.spec :as us]
[uxbox.common.exceptions :as ex]
[uxbox.config :as cfg]))
(declare hide)
@ -33,10 +33,11 @@
ptk/WatchEvent
(watch [_ state stream]
(let [stoper (rx/filter (ptk/type? ::show) stream)]
(->> (rx/of hide)
(rx/delay (:timeout data))
(rx/take-until stoper))))))
(when (:timeout data)
(let [stoper (rx/filter (ptk/type? ::show) stream)]
(->> (rx/of hide)
(rx/delay (:timeout data))
(rx/take-until stoper)))))))
(def hide
(ptk/reify ::hide
@ -51,19 +52,29 @@
(defn error
[message & {:keys [timeout] :or {timeout 3000}}]
(show {:content message
:type :error
:timeout timeout}))
([content] (error content {}))
([content {:keys [timeout] :or {timeout 3000}}]
(show {:content content
:type :error
:timeout timeout})))
(defn info
[message & {:keys [timeout] :or {timeout 3000}}]
(show {:content message
:type :info
:timeout timeout}))
([content] (info content {}))
([content {:keys [timeout] :or {timeout 3000}}]
(show {:content content
:type :info
:timeout timeout})))
(defn success
[message & {:keys [timeout] :or {timeout 3000}}]
(show {:content message
:type :info
:timeout timeout}))
([content] (success content {}))
([content {:keys [timeout] :or {timeout 3000}}]
(show {:content content
:type :success
:timeout timeout})))
(defn warn
([content] (warn content {}))
([content {:keys [timeout] :or {timeout 3000}}]
(show {:content content
:type :warning
:timeout timeout})))

View file

@ -13,20 +13,22 @@
[cuerdas.core :as str]
[potok.core :as ptk]
[rumext.alpha :as mf]
[uxbox.main.ui.icons :as i]
[uxbox.common.data :as d]
[uxbox.common.exceptions :as ex]
[uxbox.common.uuid :as uuid]
[uxbox.main.data.auth :refer [logout]]
[uxbox.main.data.messages :as dm]
[uxbox.main.refs :as refs]
[uxbox.main.store :as st]
[uxbox.main.ui.dashboard :refer [dashboard]]
[uxbox.main.ui.static :refer [not-found-page not-authorized-page]]
[uxbox.main.ui.auth :refer [auth verify-token]]
[uxbox.main.ui.dashboard :refer [dashboard]]
[uxbox.main.ui.icons :as i]
[uxbox.main.ui.messages :as msgs]
[uxbox.main.ui.settings :as settings]
[uxbox.main.ui.static :refer [not-found-page not-authorized-page]]
[uxbox.main.ui.viewer :refer [viewer-page]]
[uxbox.main.ui.workspace :as workspace]
[uxbox.util.i18n :refer [tr]]
[uxbox.util.i18n :as i18n :refer [tr t]]
[uxbox.util.timers :as ts]))
;; --- Routes
@ -84,62 +86,63 @@
(mf/defc app-container
{::mf/wrap [#(mf/catch % {:fallback app-error})]}
[{:keys [route] :as props}]
(case (get-in route [:data :name])
[:*
[:& msgs/notifications]
(case (get-in route [:data :name])
(:auth-login
:auth-register
:auth-goodbye
:auth-recovery-request
:auth-recovery)
[:& auth {:route route}]
(:auth-login
:auth-register
:auth-goodbye
:auth-recovery-request
:auth-recovery)
[:& auth {:route route}]
:auth-verify-token
[:& verify-token {:route route}]
:auth-verify-token
[:& verify-token {:route route}]
(:settings-profile
:settings-password
:settings-options)
[:& settings/settings {:route route}]
(:settings-profile
:settings-password
:settings-options)
[:& settings/settings {:route route}]
:debug-icons-preview
(when *assert*
[:& i/debug-icons-preview])
:debug-icons-preview
(when *assert*
[:& i/debug-icons-preview])
(:dashboard-search
:dashboard-team
:dashboard-project
:dashboard-library-icons
:dashboard-library-icons-index
:dashboard-library-images
:dashboard-library-images-index
:dashboard-library-palettes
:dashboard-library-palettes-index)
[:& dashboard {:route route}]
(:dashboard-search
:dashboard-team
:dashboard-project
:dashboard-library-icons
:dashboard-library-icons-index
:dashboard-library-images
:dashboard-library-images-index
:dashboard-library-palettes
:dashboard-library-palettes-index)
[:& dashboard {:route route}]
:viewer
(let [index (d/parse-integer (get-in route [:params :query :index]))
token (get-in route [:params :query :token])
page-id (uuid (get-in route [:params :path :page-id]))]
[:& viewer-page {:page-id page-id
:index index
:token token}])
:viewer
(let [index (d/parse-integer (get-in route [:params :query :index]))
token (get-in route [:params :query :token])
page-id (uuid (get-in route [:params :path :page-id]))]
[:& viewer-page {:page-id page-id
:index index
:token token}])
:workspace
(let [project-id (uuid (get-in route [:params :path :project-id]))
file-id (uuid (get-in route [:params :path :file-id]))
page-id (uuid (get-in route [:params :query :page-id]))]
[:& workspace/workspace {:project-id project-id
:file-id file-id
:page-id page-id
:key file-id}])
:workspace
(let [project-id (uuid (get-in route [:params :path :project-id]))
file-id (uuid (get-in route [:params :path :file-id]))
page-id (uuid (get-in route [:params :query :page-id]))]
[:& workspace/workspace {:project-id project-id
:file-id file-id
:page-id page-id
:key file-id}])
:not-authorized
[:& not-authorized-page]
:not-authorized
[:& not-authorized-page]
:not-found
[:& not-found-page]
:not-found
[:& not-found-page]
nil))
nil)])
(mf/defc app
[]

View file

@ -17,7 +17,6 @@
[uxbox.main.data.users :as du]
[uxbox.main.data.messages :as dm]
[uxbox.main.store :as st]
[uxbox.main.ui.messages :refer [messages]]
[uxbox.main.ui.auth.login :refer [login-page]]
[uxbox.main.ui.auth.recovery :refer [recovery-page]]
[uxbox.main.ui.auth.recovery-request :refer [recovery-request-page]]
@ -37,28 +36,19 @@
[{:keys [route] :as props}]
(let [section (get-in route [:data :name])
locale (mf/deref i18n/locale)]
[:*
[:& messages]
[:div.auth
[:section.auth-sidebar
[:a.logo {:href "/#/"} i/logo]
[:span.tagline (t locale "auth.sidebar-tagline")]]
[:div.msg-banner.error
[:div.msg-content
[:div.icon i/msg-error]
[:span "Lorem ipsum dolor sit amet"]
[:div.close-button i/close]]]
[:div.auth
[:section.auth-sidebar
[:a.logo {:href "/#/"} i/logo]
[:span.tagline (t locale "auth.sidebar-tagline")]]
[:section.auth-content
(case section
:auth-register [:& register-page {:locale locale}]
:auth-login [:& login-page {:locale locale}]
:auth-goodbye [:& goodbye-page {:locale locale}]
:auth-recovery-request [:& recovery-request-page {:locale locale}]
:auth-recovery [:& recovery-page {:locale locale
:params (:query-params route)}])]]]))
[:section.auth-content
(case section
:auth-register [:& register-page {:locale locale}]
:auth-login [:& login-page {:locale locale}]
:auth-goodbye [:& goodbye-page {:locale locale}]
:auth-recovery-request [:& recovery-request-page {:locale locale}]
:auth-recovery [:& recovery-page {:locale locale
:params (:query-params route)}])]]))
(defn- handle-email-verified
[data]

View file

@ -18,6 +18,7 @@
[uxbox.main.data.auth :as da]
[uxbox.main.repo :as rp]
[uxbox.main.store :as st]
[uxbox.main.ui.messages :as msgs]
[uxbox.main.data.messages :as dm]
[uxbox.main.ui.components.forms :refer [input submit-button form]]
[uxbox.util.object :as obj]
@ -32,16 +33,6 @@
(s/def ::login-form
(s/keys :req-un [::email ::password]))
(defn- on-error
[form error]
(st/emit! (dm/error (tr "errors.auth.unauthorized"))))
(defn- on-submit
[form event]
(let [params (with-meta (:clean-data form)
{:on-error (partial on-error form)})]
(st/emit! (da/login params))))
(defn- login-with-google
[event]
(dom/prevent-default event)
@ -51,23 +42,43 @@
(mf/defc login-form
[{:keys [locale] :as props}]
[:& form {:on-submit on-submit
:spec ::login-form
:initial {}}
[:& input
{:name :email
:type "text"
:tab-index "2"
:help-icon i/at
:label (t locale "auth.email-label")}]
[:& input
{:type "password"
:name :password
:tab-index "3"
:help-icon i/eye
:label (t locale "auth.password-label")}]
[:& submit-button
{:label (t locale "auth.login-submit-label")}]])
(let [error? (mf/use-state false)
on-error
(fn [form event]
(reset! error? true))
on-submit
(fn [form event]
(reset! error? false)
(let [params (with-meta (:clean-data form)
{:on-error on-error})]
(st/emit! (da/login params))))]
[:*
(when @error?
[:& msgs/inline-banner
{:type :warning
:content (t locale "errors.auth.unauthorized")
:on-close #(reset! error? false)}])
[:& form {:on-submit on-submit
:spec ::login-form
:initial {}}
[:& input
{:name :email
:type "text"
:tab-index "2"
:help-icon i/at
:label (t locale "auth.email-label")}]
[:& input
{:type "password"
:name :password
:tab-index "3"
:help-icon i/eye
:label (t locale "auth.password-label")}]
[:& submit-button
{:label (t locale "auth.login-submit-label")}]]]))
(mf/defc login-page
[{:keys [locale] :as props}]

View file

@ -18,7 +18,6 @@
[uxbox.main.data.messages :as dm]
[uxbox.main.store :as st]
[uxbox.main.ui.components.forms :refer [input submit-button form]]
[uxbox.main.ui.messages :refer [messages]]
[uxbox.main.ui.navigation :as nav]
[uxbox.util.dom :as dom]
[uxbox.util.forms :as fm]

View file

@ -19,7 +19,6 @@
[uxbox.main.data.messages :as dm]
[uxbox.main.store :as st]
[uxbox.main.ui.components.forms :refer [input submit-button form]]
[uxbox.main.ui.messages :refer [messages]]
[uxbox.main.ui.navigation :as nav]
[uxbox.util.dom :as dom]
[uxbox.util.forms :as fm]

View file

@ -18,9 +18,9 @@
[uxbox.main.data.auth :as uda]
[uxbox.main.store :as st]
[uxbox.main.data.auth :as da]
[uxbox.main.ui.messages :refer [messages]]
[uxbox.main.ui.components.forms :refer [input submit-button form]]
[uxbox.main.ui.navigation :as nav]
[uxbox.main.ui.messages :as msgs]
[uxbox.util.dom :as dom]
[uxbox.util.forms :as fm]
[uxbox.util.i18n :refer [tr t]]
@ -28,14 +28,10 @@
(mf/defc demo-warning
[_]
[:div.msg-inline.warning.quick
[:div.icon i/msg-warning]
[:span.msg-text
"WARNING: This is a service, DO NOT USE for real work, the projects will be periodicaly wiped."]
[:div.close-button i/close]])
[:& msgs/inline-banner
{:type :warning
:content (tr "auth.demo-warning")}])
(s/def ::fullname ::fm/not-empty-string)
(s/def ::password ::fm/not-empty-string)

View file

@ -13,6 +13,7 @@
[rumext.alpha :as mf]
[uxbox.main.ui.icons :as i]
[uxbox.common.exceptions :as ex]
[uxbox.common.uuid :as uuid]
[uxbox.common.spec :as us]
[uxbox.main.refs :as refs]
[uxbox.main.ui.dashboard.sidebar :refer [sidebar]]
@ -21,7 +22,7 @@
[uxbox.main.ui.dashboard.recent-files :refer [recent-files-page]]
[uxbox.main.ui.dashboard.library :refer [library-page]]
[uxbox.main.ui.dashboard.profile :refer [profile-section]]
[uxbox.main.ui.messages :refer [messages]]))
[uxbox.util.i18n :as i18n :refer [t]]))
(defn ^boolean uuid-str?
[s]
@ -53,6 +54,8 @@
(uuid-str? library-id)
(assoc :library-id (uuid library-id)))))
(declare global-notifications)
(mf/defc dashboard
[{:keys [route] :as props}]
@ -61,7 +64,7 @@
{:keys [search-term team-id project-id library-id library-section] :as params}
(parse-params route profile)]
[:*
[:& messages]
[:& global-notifications {:profile profile}]
[:section.dashboard-layout
[:div.main-logo i/logo-icon]
[:& profile-section {:profile profile}]
@ -91,3 +94,17 @@
:dashboard-project
[:& project-page {:team-id team-id
:project-id project-id}])]]]))
(mf/defc global-notifications
[{:keys [profile] :as props}]
(let [locale (mf/deref i18n/locale)]
(when (and profile
(not= uuid/zero (:id profile))
(= (:pending-email profile)
(:email profile)))
[:section.banner.error.quick
[:div.content
[:div.icon i/msg-warning]
[:span (t locale "settings.notifications.email-not-verified" (:email profile))]]])))

View file

@ -10,41 +10,56 @@
[uxbox.util.i18n :as i18n :refer [t]]
[uxbox.util.timers :as ts]))
;; --- Main Component (entry point)
(defn- type->icon
[type]
(case type
:warning i/msg-warning
:error i/msg-error
:success i/msg-success
:info i/msg-info))
(declare notification)
(mf/defc messages
[]
(let [message (mf/deref refs/message)]
(when message
[:& notification {:type (:type message)
:status (:status message)
:content (:content message)}])))
(mf/defc messages-widget
[]
(let [message (mf/deref refs/message)
message {:type :error
:content "Hello world!"}]
[:& notification {:type (:type message)
:status (:status message)
:content (:content message)}]))
;; --- Notification Component
(mf/defc notification
[{:keys [type status content] :as props}]
(let [on-close #(st/emit! dm/hide)
klass (classnames
:error (= type :error)
:info (= type :info)
:hide-message (= status :hide)
(mf/defc notification-item
[{:keys [type status on-close quick? content] :as props}]
(let [klass (dom/classnames
:fixed true
:success (= type :success)
:quick false)]
[:div.message {:class klass}
[:a.close-button {:on-click on-close} i/close]
[:div.message-content
[:span content]]]))
:error (= type :error)
:info (= type :info)
:warning (= type :warning)
:hide (= status :hide)
:quick quick?)]
[:section.banner {:class klass}
[:div.content
[:div.icon (type->icon type)]
[:span content]]
[:div.btn-close {:on-click on-close} i/close]]))
(mf/defc notifications
[]
(let [message (mf/deref refs/message)
on-close #(st/emit! dm/hide)]
(when message
[:& notification-item {:type (:type message)
:quick? (boolean (:timeout message))
:status (:status message)
:content (:content message)
:on-close on-close}])))
(mf/defc inline-banner
{::mf/wrap [mf/memo]}
[{:keys [type on-close content children] :as props}]
[:div.inline-banner {:class (dom/classnames
:warning (= type :warning)
:error (= type :error)
:success (= type :success)
:info (= type :info)
:quick (not on-close))}
[:div.icon (type->icon type)]
[:div.content
[:div.main
[:span.text content]
[:div.btn-close {:on-click on-close} i/close]]
(when children
[:div.extra
children])]])

View file

@ -17,7 +17,6 @@
[uxbox.main.store :as st]
[uxbox.util.router :as rt]
[uxbox.main.ui.dashboard.profile :refer [profile-section]]
[uxbox.main.ui.messages :refer [messages]]
[uxbox.main.ui.settings.header :refer [header]]
[uxbox.main.ui.settings.password :refer [password-page]]
[uxbox.main.ui.settings.options :refer [options-page]]
@ -28,7 +27,6 @@
(let [section (get-in route [:data :name])
profile (mf/deref refs/profile)]
[:main.settings-main
[:& messages]
[:div.settings-content
[:& header {:section section :profile profile}]
(case section

View file

@ -17,6 +17,7 @@
[uxbox.main.data.auth :as da]
[uxbox.main.data.users :as du]
[uxbox.main.ui.components.forms :refer [input submit-button form]]
[uxbox.main.ui.messages :as msgs]
[uxbox.main.data.messages :as dm]
[uxbox.main.store :as st]
[uxbox.main.refs :as refs]
@ -36,9 +37,7 @@
(= (:code error) :uxbox.services.mutations.profile/email-already-exists)
(swap! form (fn [data]
(let [error {:message (tr "errors.email-already-exists")}]
(-> data
(assoc-in [:errors :email-1] error)
(assoc-in [:errors :email-2] error)))))
(assoc-in data [:errors :email-1] error))))
:else
(let [msg (tr "errors.unexpected-error")]
@ -55,11 +54,9 @@
[:section.modal-content.generic-form
[:h2 (t locale "settings.change-email-title")]
[:span.featured-note
[:span.text
[:span "Well send you an email to your current email "]
[:strong (:email profile)]
[:span " to verify your identity."]]]
[:& msgs/inline-banner
{:type :info
:content (t locale "settings.change-email-info" (:email profile))}]
[:& form {:on-submit on-submit
:spec ::email-change-form
@ -80,12 +77,10 @@
[:section.modal-content.generic-form.confirmation
[:h2 (t locale "settings.verification-sent-title")]
[:span.featured-note
[:span.icon i/trash]
[:span.text
[:span (str/format "We have sent you an email to “")]
[:strong (:email profile)]
[:span "” Please follow the instructions to verify the email."]]]
[:& msgs/inline-banner
{:type :info
:content (t locale "settings.change-email-info2" (:email profile))}]
[:button.btn-primary.btn-large
{:on-click #(modal/hide!)}

View file

@ -19,6 +19,7 @@
[uxbox.main.ui.settings.change-email :refer [change-email-modal]]
[uxbox.main.ui.settings.delete-account :refer [delete-account-modal]]
[uxbox.main.ui.modal :as modal]
[uxbox.main.ui.messages :as msgs]
[uxbox.main.data.messages :as dm]
[uxbox.main.store :as st]
[uxbox.main.refs :as refs]
@ -73,20 +74,17 @@
(t locale "settings.change-email-label")]]
(not= (:pending-email prof) (:email prof))
[:span.featured-note
[:span.icon i/trash]
[:span.text
[:span "There is a pending change of your email to "]
[:strong (:pending-email prof)]
[:span "."] [:br]
[:a {:on-click #(st/emit! udu/cancel-email-change)}
"Dismiss"]]]
[:& msgs/inline-banner
{:type :info
:content (t locale "settings.change-email-info3" (:pending-email prof))}
[:div.btn-secondary.btn-small
{:on-click #(st/emit! udu/cancel-email-change)}
(t locale "settings.cancel-email-change")]]
:else
[:span.featured-note.warning
[:span.text
[:span "There is a pending email validation."]]])
[:& msgs/inline-banner
{:type :info
:content (t locale "settings.email-verification-pending")}])
[:& submit-button
{:label (t locale "settings.profile-submit-label")}]

View file

@ -22,7 +22,6 @@
[uxbox.main.ui.components.dropdown :refer [dropdown]]
[uxbox.main.ui.hooks :as hooks]
[uxbox.main.ui.keyboard :as kbd]
[uxbox.main.ui.messages :refer [messages]]
[uxbox.main.ui.viewer.header :refer [header]]
[uxbox.main.ui.viewer.thumbnails :refer [thumbnails-panel]]
[uxbox.main.ui.viewer.shapes :refer [frame-svg]]
@ -87,23 +86,21 @@
(mf/use-effect on-mount)
(hooks/use-shortcuts dv/shortcuts)
[:*
[:& messages]
[:div.viewer-layout {:class (classnames :fullscreen fullscreen?)
:ref container}
[:div.viewer-layout {:class (classnames :fullscreen fullscreen?)
:ref container}
[:& header {:data data
:toggle-fullscreen toggle-fullscreen
:fullscreen? fullscreen?
:local local
:index index}]
[:div.viewer-content {:on-click on-click}
(when (:show-thumbnails local)
[:& thumbnails-panel {:index index
:data data}])
[:& main-panel {:data data
:local local
:index index}]]]]))
[:& header {:data data
:toggle-fullscreen toggle-fullscreen
:fullscreen? fullscreen?
:local local
:index index}]
[:div.viewer-content {:on-click on-click}
(when (:show-thumbnails local)
[:& thumbnails-panel {:index index
:data data}])
[:& main-panel {:data data
:local local
:index index}]]]))
;; --- Component: Viewer Page

View file

@ -22,7 +22,6 @@
[uxbox.main.ui.confirm]
[uxbox.main.ui.keyboard :as kbd]
[uxbox.main.ui.hooks :as hooks]
[uxbox.main.ui.messages :refer [messages]]
[uxbox.main.ui.workspace.viewport :refer [viewport coordinates]]
[uxbox.main.ui.workspace.colorpalette :refer [colorpalette]]
[uxbox.main.ui.workspace.context-menu :refer [context-menu]]
@ -117,12 +116,11 @@
(let [file (mf/deref refs/workspace-file)
project (mf/deref refs/workspace-project)
layout (mf/deref refs/workspace-layout)]
[:*
[:section
[:& header {:file file
:project project
:layout layout}]
[:& messages]
[:& context-menu]
(if (and (and file project)