mirror of
https://github.com/penpot/penpot.git
synced 2026-04-25 11:18:36 +00:00
✨ Allow login dialog on settings
This commit is contained in:
parent
7f53860296
commit
1f05511add
@ -26,6 +26,7 @@
|
||||
- Improved text layer resizing: Allow double-click on text bounding box to set auto-width/auto-height [Taiga #11577](https://tree.taiga.io/project/penpot/issue/11577)
|
||||
- Improve text layer auto-resize: auto-width switches to auto-height on horizontal resize, and only switches to fixed on vertical resize [Taiga #11578](https://tree.taiga.io/project/penpot/issue/11578)
|
||||
- Highlight first font in font selector search. Apply only on Enter or click. [Taiga #11579](https://tree.taiga.io/project/penpot/issue/11579)
|
||||
- Add the ability to show login dialog on profile settings [Github #6871](https://github.com/penpot/penpot/pull/6871)
|
||||
|
||||
### :bug: Bugs fixed
|
||||
|
||||
|
||||
@ -102,23 +102,27 @@
|
||||
(print-trace! error)
|
||||
(print-data! error))))
|
||||
|
||||
;; We receive a explicit authentication error;
|
||||
;; If the uri is for workspace, dashboard or view assign the
|
||||
;; exception for the 'Oops' page. Otherwise this explicitly clears
|
||||
;; all profile data and redirect the user to the login page. This is
|
||||
;; here and not in app.main.errors because of circular dependency.
|
||||
;; We receive a explicit authentication error; If the uri is for
|
||||
;; workspace, dashboard, viewer or settings, then assign the exception
|
||||
;; for show the error page. Otherwise this explicitly clears all
|
||||
;; profile data and redirect the user to the login page. This is here
|
||||
;; and not in app.main.errors because of circular dependency.
|
||||
(defmethod ptk/handle-error :authentication
|
||||
[e]
|
||||
(let [msg (tr "errors.auth.unable-to-login")
|
||||
uri (.-href glob/location)
|
||||
show-oops? (or (str/includes? uri "workspace")
|
||||
(str/includes? uri "dashboard")
|
||||
(str/includes? uri "view"))]
|
||||
(if show-oops?
|
||||
(st/async-emit! (rt/assign-exception e))
|
||||
[error]
|
||||
(let [message (tr "errors.auth.unable-to-login")
|
||||
uri (rt/get-current-href)
|
||||
|
||||
show-error?
|
||||
(or (str/includes? uri "workspace")
|
||||
(str/includes? uri "dashboard")
|
||||
(str/includes? uri "view")
|
||||
(str/includes? uri "settings"))]
|
||||
|
||||
(if show-error?
|
||||
(st/async-emit! (rt/assign-exception error))
|
||||
(do
|
||||
(st/emit! (da/logout))
|
||||
(ts/schedule 500 #(st/emit! (ntf/warn msg)))))))
|
||||
(ts/schedule 500 #(st/emit! (ntf/warn message)))))))
|
||||
|
||||
;; Error that happens on an active business model validation does not
|
||||
;; passes an validation (example: profile can't leave a team). From
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
[app.main.data.team :as dtm]
|
||||
[app.main.errors :as errors]
|
||||
[app.main.repo :as rp]
|
||||
[app.main.router :as rt]
|
||||
[app.main.store :as st]
|
||||
@ -130,7 +131,10 @@
|
||||
(assoc query-params :team-id (:default-team-id profile))))))
|
||||
|
||||
:else
|
||||
(st/emit! (rt/assign-exception {:type :not-found})))))))))
|
||||
(st/emit! (rt/assign-exception {:type :not-found}))))
|
||||
|
||||
(fn [cause]
|
||||
(errors/on-error cause)))))))
|
||||
|
||||
(defn init-routes
|
||||
[]
|
||||
|
||||
@ -42,7 +42,7 @@
|
||||
|
||||
(mf/with-effect [profile]
|
||||
(when (nil? profile)
|
||||
(st/emit! (rt/nav :auth-login))))
|
||||
(st/emit! (rt/assign-exception {:type :authentication}))))
|
||||
|
||||
[:*
|
||||
[:> modal-container*]
|
||||
|
||||
@ -69,9 +69,8 @@
|
||||
[:div {:class (stl/css :main-message)} (tr "errors.invite-invalid")]
|
||||
[:div {:class (stl/css :desc-message)} (tr "errors.invite-invalid.info")]])
|
||||
|
||||
(mf/defc login-dialog
|
||||
{::mf/props :obj}
|
||||
[{:keys [show-dialog]}]
|
||||
(mf/defc login-dialog*
|
||||
[]
|
||||
(let [current-section (mf/use-state :login)
|
||||
user-email (mf/use-state "")
|
||||
register-token (mf/use-state "")
|
||||
@ -94,9 +93,7 @@
|
||||
|
||||
success-login
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
(reset! show-dialog false)
|
||||
(st/emit! (rt/reload true))))
|
||||
#(st/emit! (rt/reload true)))
|
||||
|
||||
success-register
|
||||
(mf/use-fn
|
||||
@ -117,7 +114,7 @@
|
||||
(reset! current-section :recovery-email-sent)))
|
||||
|
||||
on-nav-root
|
||||
(mf/use-fn #(st/emit! (rt/nav-root)))]
|
||||
(mf/use-fn #(st/emit! (rt/nav :auth-login {})))]
|
||||
|
||||
[:div {:class (stl/css :overlay)}
|
||||
[:div {:class (stl/css :dialog-login)}
|
||||
@ -203,11 +200,9 @@
|
||||
[:button {:on-click on-click} button-text]]]]))
|
||||
|
||||
(mf/defc request-access*
|
||||
[{:keys [file-id team-id is-default is-workspace]}]
|
||||
(let [profile (mf/deref refs/profile)
|
||||
requested* (mf/use-state {:sent false :already-requested false})
|
||||
[{:keys [file-id team-id is-default is-workspace profile]}]
|
||||
(let [requested* (mf/use-state {:sent false :already-requested false})
|
||||
requested (deref requested*)
|
||||
show-dialog (mf/use-state true)
|
||||
|
||||
on-close
|
||||
(mf/use-fn
|
||||
@ -237,90 +232,47 @@
|
||||
(st/emit! (dcm/create-team-access-request
|
||||
(with-meta params mdata))))))]
|
||||
|
||||
[:*
|
||||
(if (some? file-id)
|
||||
(if is-workspace
|
||||
[:div {:class (stl/css :workspace)}
|
||||
[:div {:class (stl/css :workspace-left)}
|
||||
i/logo-icon
|
||||
[:div
|
||||
[:div {:class (stl/css :project-name)} (tr "not-found.no-permission.project-name")]
|
||||
[:div {:class (stl/css :file-name)} (tr "not-found.no-permission.penpot-file")]]]
|
||||
[:div {:class (stl/css :workspace-right)}]]
|
||||
(cond
|
||||
is-default
|
||||
[:& request-dialog {:title (tr "not-found.no-permission.project")
|
||||
:button-text (tr "not-found.no-permission.go-dashboard")
|
||||
:on-close on-close}]
|
||||
|
||||
[:div {:class (stl/css :viewer)}
|
||||
;; FIXME: the viewer header was never designed to be reused
|
||||
;; from other parts of the application, and this code looks
|
||||
;; like a fast workaround reusing it as-is without a proper
|
||||
;; component adaptation for be able to use it easily it on
|
||||
;; viewer context or static error page context
|
||||
[:& viewer.header/header {:project
|
||||
{:name (tr "not-found.no-permission.project-name")}
|
||||
:index 0
|
||||
:file {:name (tr "not-found.no-permission.penpot-file")}
|
||||
:page nil
|
||||
:frame nil
|
||||
:permissions {:is-logged true}
|
||||
:zoom 1
|
||||
:section :interactions
|
||||
:shown-thumbnails false
|
||||
:interactions-mode nil}]])
|
||||
(and (some? file-id) (:already-requested requested))
|
||||
[:& request-dialog {:title (tr "not-found.no-permission.already-requested.file")
|
||||
:content [(tr "not-found.no-permission.already-requested.or-others.file")]
|
||||
:button-text (tr "not-found.no-permission.go-dashboard")
|
||||
:on-close on-close}]
|
||||
|
||||
[:div {:class (stl/css :dashboard)}
|
||||
[:div {:class (stl/css :dashboard-sidebar)}
|
||||
[:> sidebar*
|
||||
{:team nil
|
||||
:projects []
|
||||
:project (:default-project-id profile)
|
||||
:profile profile
|
||||
:section :dashboard-projects
|
||||
:search-term ""}]]])
|
||||
(:already-requested requested)
|
||||
[:& request-dialog {:title (tr "not-found.no-permission.already-requested.project")
|
||||
:content [(tr "not-found.no-permission.already-requested.or-others.project")]
|
||||
:button-text (tr "not-found.no-permission.go-dashboard")
|
||||
:on-close on-close}]
|
||||
|
||||
(when @show-dialog
|
||||
(cond
|
||||
(nil? profile)
|
||||
[:& login-dialog {:show-dialog show-dialog}]
|
||||
(:sent requested)
|
||||
[:& request-dialog {:title (tr "not-found.no-permission.done.success")
|
||||
:content [(tr "not-found.no-permission.done.remember")]
|
||||
:button-text (tr "not-found.no-permission.go-dashboard")
|
||||
:on-close on-close}]
|
||||
|
||||
is-default
|
||||
[:& request-dialog {:title (tr "not-found.no-permission.project")
|
||||
:button-text (tr "not-found.no-permission.go-dashboard")
|
||||
:on-close on-close}]
|
||||
(some? file-id)
|
||||
[:& request-dialog {:title (tr "not-found.no-permission.file")
|
||||
:content [(tr "not-found.no-permission.you-can-ask.file")
|
||||
(tr "not-found.no-permission.if-approves")]
|
||||
:button-text (tr "not-found.no-permission.ask")
|
||||
:on-button-click on-request-access
|
||||
:cancel-text (tr "not-found.no-permission.go-dashboard")
|
||||
:on-close on-close}]
|
||||
|
||||
(and (some? file-id) (:already-requested requested))
|
||||
[:& request-dialog {:title (tr "not-found.no-permission.already-requested.file")
|
||||
:content [(tr "not-found.no-permission.already-requested.or-others.file")]
|
||||
:button-text (tr "not-found.no-permission.go-dashboard")
|
||||
:on-close on-close}]
|
||||
|
||||
(:already-requested requested)
|
||||
[:& request-dialog {:title (tr "not-found.no-permission.already-requested.project")
|
||||
:content [(tr "not-found.no-permission.already-requested.or-others.project")]
|
||||
:button-text (tr "not-found.no-permission.go-dashboard")
|
||||
:on-close on-close}]
|
||||
|
||||
(:sent requested)
|
||||
[:& request-dialog {:title (tr "not-found.no-permission.done.success")
|
||||
:content [(tr "not-found.no-permission.done.remember")]
|
||||
:button-text (tr "not-found.no-permission.go-dashboard")
|
||||
:on-close on-close}]
|
||||
|
||||
(some? file-id)
|
||||
[:& request-dialog {:title (tr "not-found.no-permission.file")
|
||||
:content [(tr "not-found.no-permission.you-can-ask.file")
|
||||
(tr "not-found.no-permission.if-approves")]
|
||||
:button-text (tr "not-found.no-permission.ask")
|
||||
:on-button-click on-request-access
|
||||
:cancel-text (tr "not-found.no-permission.go-dashboard")
|
||||
:on-close on-close}]
|
||||
|
||||
(some? team-id)
|
||||
[:& request-dialog {:title (tr "not-found.no-permission.project")
|
||||
:content [(tr "not-found.no-permission.you-can-ask.project")
|
||||
(tr "not-found.no-permission.if-approves")]
|
||||
:button-text (tr "not-found.no-permission.ask")
|
||||
:on-button-click on-request-access
|
||||
:cancel-text (tr "not-found.no-permission.go-dashboard")
|
||||
:on-close on-close}]))]))
|
||||
(some? team-id)
|
||||
[:& request-dialog {:title (tr "not-found.no-permission.project")
|
||||
:content [(tr "not-found.no-permission.you-can-ask.project")
|
||||
(tr "not-found.no-permission.if-approves")]
|
||||
:button-text (tr "not-found.no-permission.ask")
|
||||
:on-button-click on-request-access
|
||||
:cancel-text (tr "not-found.no-permission.go-dashboard")
|
||||
:on-close on-close}])))
|
||||
|
||||
(mf/defc not-found*
|
||||
[]
|
||||
@ -484,29 +436,77 @@
|
||||
|
||||
[:> internal-error* props])))
|
||||
|
||||
(mf/defc context-wrapper*
|
||||
[{:keys [is-workspace is-dashboard is-viewer profile children]}]
|
||||
[:*
|
||||
(cond
|
||||
is-workspace
|
||||
[:div {:class (stl/css :workspace)}
|
||||
[:div {:class (stl/css :workspace-left)}
|
||||
i/logo-icon
|
||||
[:div
|
||||
[:div {:class (stl/css :project-name)} (tr "not-found.no-permission.project-name")]
|
||||
[:div {:class (stl/css :file-name)} (tr "not-found.no-permission.penpot-file")]]]
|
||||
[:div {:class (stl/css :workspace-right)}]]
|
||||
|
||||
is-viewer
|
||||
[:div {:class (stl/css :viewer)}
|
||||
;; FIXME: the viewer header was never designed to be reused
|
||||
;; from other parts of the application, and this code looks
|
||||
;; like a fast workaround reusing it as-is without a proper
|
||||
;; component adaptation for be able to use it easily it on
|
||||
;; viewer context or static error page context
|
||||
[:& viewer.header/header {:project
|
||||
{:name (tr "not-found.no-permission.project-name")}
|
||||
:index 0
|
||||
:file {:name (tr "not-found.no-permission.penpot-file")}
|
||||
:page nil
|
||||
:frame nil
|
||||
:permissions {:is-logged true}
|
||||
:zoom 1
|
||||
:section :interactions
|
||||
:shown-thumbnails false
|
||||
:interactions-mode nil}]]
|
||||
|
||||
is-dashboard
|
||||
[:div {:class (stl/css :dashboard)}
|
||||
[:div {:class (stl/css :dashboard-sidebar)}
|
||||
[:> sidebar*
|
||||
{:team nil
|
||||
:projects []
|
||||
:project (:default-project-id profile)
|
||||
:profile profile
|
||||
:section :dashboard-projects
|
||||
:search-term ""}]]])
|
||||
|
||||
children])
|
||||
|
||||
(mf/defc exception-page*
|
||||
{::mf/props :obj}
|
||||
[{:keys [data route] :as props}]
|
||||
|
||||
(let [type (:type data)
|
||||
path (:path route)
|
||||
(let [type (:type data)
|
||||
path (:path route)
|
||||
|
||||
params (:query-params route)
|
||||
params (:query-params route)
|
||||
|
||||
workspace? (str/includes? path "workspace")
|
||||
dashboard? (str/includes? path "dashboard")
|
||||
view? (str/includes? path "view")
|
||||
workspace? (str/includes? path "workspace")
|
||||
dashboard? (str/includes? path "dashboard")
|
||||
view? (str/includes? path "view")
|
||||
|
||||
;; We store the request access info int this state
|
||||
info* (mf/use-state nil)
|
||||
info (deref info*)
|
||||
info* (mf/use-state nil)
|
||||
info (deref info*)
|
||||
|
||||
loaded? (get info :loaded false)
|
||||
loaded? (get info :loaded false)
|
||||
profile (mf/deref refs/profile)
|
||||
|
||||
auth-error?
|
||||
(= type :authentication)
|
||||
|
||||
request-access?
|
||||
(and
|
||||
(or (= type :not-found)
|
||||
(= type :authentication))
|
||||
(or (= type :not-found) auth-error?)
|
||||
(or workspace? dashboard? view?)
|
||||
(or (:file-id info)
|
||||
(:team-id info)))]
|
||||
@ -517,11 +517,25 @@
|
||||
(rx/subs! (partial reset! info*)
|
||||
(partial reset! info* {:loaded true})))))
|
||||
|
||||
(when loaded?
|
||||
(if request-access?
|
||||
[:> request-access* {:file-id (:file-id info)
|
||||
:team-id (:team-id info)
|
||||
:is-default (:team-default info)
|
||||
:is-workspace workspace?}]
|
||||
[:> exception-section* props]))))
|
||||
|
||||
(if auth-error?
|
||||
[:> context-wrapper*
|
||||
{:is-workspace workspace?
|
||||
:is-dashboard dashboard?
|
||||
:is-viewer view?
|
||||
:profile profile}
|
||||
[:> login-dialog* {}]]
|
||||
|
||||
(when loaded?
|
||||
(if request-access?
|
||||
[:> context-wrapper* {:is-workspace workspace?
|
||||
:is-dashboard dashboard?
|
||||
:is-viewer view?
|
||||
:profile profile}
|
||||
[:> request-access* {:file-id (:file-id info)
|
||||
:team-id (:team-id info)
|
||||
:is-default (:team-default info)
|
||||
:is-workspace workspace?}]]
|
||||
|
||||
[:> exception-section* props])))))
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user