mirror of https://github.com/penpot/penpot.git
Merge pull request #6871 from penpot/niwinz-develop-login-enhancements
✨ Allow login dialog on settings
This commit is contained in:
commit
42ef01b339
|
|
@ -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*]
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.schema :as sm]
|
||||
[app.main.data.auth :as da]
|
||||
[app.main.data.event :as ev]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.profile :as du]
|
||||
|
|
@ -96,7 +97,7 @@
|
|||
handle-accept-dialog (mf/use-fn
|
||||
(fn []
|
||||
(st/emit! (ptk/event ::ev/event {::ev/name "open-subscription-management"
|
||||
::ev/origin "profile"
|
||||
::ev/origin "settings"
|
||||
:section "subscription-management-modal"}))
|
||||
(let [current-href (rt/get-current-href)
|
||||
returnUrl (js/encodeURIComponent current-href)
|
||||
|
|
@ -212,43 +213,69 @@
|
|||
|
||||
(mf/defc subscription-page*
|
||||
[{:keys [profile]}]
|
||||
(let [route (mf/deref refs/route)
|
||||
params (:params route)
|
||||
params-subscription (:subscription (:query params))
|
||||
show-trial-subscription-modal (or (= params-subscription "subscription-to-penpot-unlimited")
|
||||
(= params-subscription "subscription-to-penpot-enterprise"))
|
||||
show-subscription-success-modal (or (= params-subscription "subscribed-to-penpot-unlimited")
|
||||
(= params-subscription "subscribed-to-penpot-enterprise"))
|
||||
subscription (:subscription (:props profile))
|
||||
subscription-type (get-subscription-type subscription)
|
||||
subscription-is-trial (= (:status subscription) "trialing")
|
||||
teams* (mf/use-state nil)
|
||||
teams (deref teams*)
|
||||
locale (mf/deref i18n/locale)
|
||||
penpot-member (dt/format-date-locale-short (:created-at profile) {:locale locale})
|
||||
subscription-member (dt/format-date-locale-short (:start-date subscription) {:locale locale})
|
||||
go-to-pricing-page (mf/use-fn
|
||||
(fn []
|
||||
(st/emit! (ptk/event ::ev/event {::ev/name "explore-pricing-click" ::ev/origin "settings" :section "subscription"}))
|
||||
(dom/open-new-window "https://penpot.app/pricing")))
|
||||
go-to-payments (mf/use-fn
|
||||
(fn []
|
||||
(st/emit! (ptk/event ::ev/event {::ev/name "open-subscription-management"
|
||||
::ev/origin "profile"
|
||||
:section "subscription"}))
|
||||
(let [current-href (rt/get-current-href)
|
||||
returnUrl (js/encodeURIComponent current-href)
|
||||
href (dm/str "payments/subscriptions/show?returnUrl=" returnUrl)]
|
||||
(st/emit! (rt/nav-raw :href href)))))
|
||||
open-subscription-modal (mf/use-fn
|
||||
(mf/deps teams)
|
||||
(fn [subscription-type]
|
||||
(st/emit! (ptk/event ::ev/event {::ev/name "open-subscription-modal"
|
||||
::ev/origin "settings:in-app"}))
|
||||
(st/emit!
|
||||
(modal/show :management-dialog
|
||||
{:subscription-type subscription-type
|
||||
:teams teams :subscribe-to-trial (not subscription)}))))]
|
||||
(let [route (mf/deref refs/route)
|
||||
authenticated? (da/is-authenticated? profile)
|
||||
|
||||
teams* (mf/use-state nil)
|
||||
teams (deref teams*)
|
||||
|
||||
locale (mf/deref i18n/locale)
|
||||
|
||||
params-subscription
|
||||
(-> route :params :query :subscription)
|
||||
|
||||
show-trial-subscription-modal?
|
||||
(or (= params-subscription "subscription-to-penpot-unlimited")
|
||||
(= params-subscription "subscription-to-penpot-enterprise"))
|
||||
|
||||
show-subscription-success-modal?
|
||||
(or (= params-subscription "subscribed-to-penpot-unlimited")
|
||||
(= params-subscription "subscribed-to-penpot-enterprise"))
|
||||
|
||||
subscription
|
||||
(-> profile :props :subscription)
|
||||
|
||||
subscription-type
|
||||
(get-subscription-type subscription)
|
||||
|
||||
subscription-is-trial?
|
||||
(= (:status subscription) "trialing")
|
||||
|
||||
member-since
|
||||
(dt/format-date-locale-short (:created-at profile) {:locale locale})
|
||||
|
||||
subscribed-since
|
||||
(dt/format-date-locale-short (:start-date subscription) {:locale locale})
|
||||
|
||||
go-to-pricing-page
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
(st/emit! (ev/event {::ev/name "explore-pricing-click"
|
||||
::ev/origin "settings"
|
||||
:section "subscription"}))
|
||||
(dom/open-new-window "https://penpot.app/pricing")))
|
||||
|
||||
go-to-payments
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
(st/emit! (ev/event {::ev/name "open-subscription-management"
|
||||
::ev/origin "settings"
|
||||
:section "subscription"}))
|
||||
(let [current-href (rt/get-current-href)
|
||||
returnUrl (js/encodeURIComponent current-href)
|
||||
href (dm/str "payments/subscriptions/show?returnUrl=" returnUrl)]
|
||||
(st/emit! (rt/nav-raw :href href)))))
|
||||
|
||||
open-subscription-modal
|
||||
(mf/use-fn
|
||||
(mf/deps teams)
|
||||
(fn [subscription-type]
|
||||
(st/emit! (ev/event {::ev/name "open-subscription-modal"
|
||||
::ev/origin "settings:in-app"}))
|
||||
(st/emit!
|
||||
(modal/show :management-dialog
|
||||
{:subscription-type subscription-type
|
||||
:teams teams :subscribe-to-trial (not subscription)}))))]
|
||||
|
||||
(mf/with-effect []
|
||||
(->> (rp/cmd! :get-owned-teams)
|
||||
|
|
@ -258,33 +285,35 @@
|
|||
(mf/with-effect []
|
||||
(dom/set-html-title (tr "subscription.labels")))
|
||||
|
||||
(mf/with-effect [show-trial-subscription-modal subscription]
|
||||
(when show-trial-subscription-modal
|
||||
(st/emit!
|
||||
(ptk/event ::ev/event {::ev/name "open-subscription-modal"
|
||||
::ev/origin "settings:from-pricing-page"})
|
||||
(modal/show :management-dialog
|
||||
{:subscription-type (if (= params-subscription "subscription-to-penpot-unlimited")
|
||||
"unlimited"
|
||||
"enterprise")
|
||||
:teams teams
|
||||
:subscribe-to-trial (not subscription)})
|
||||
(rt/nav :settings-subscription {} {::rt/replace true}))))
|
||||
(mf/with-effect [authenticated? show-subscription-success-modal? show-trial-subscription-modal? subscription]
|
||||
(when ^boolean authenticated?
|
||||
(cond
|
||||
^boolean show-trial-subscription-modal?
|
||||
|
||||
(mf/with-effect [show-subscription-success-modal subscription]
|
||||
(when show-subscription-success-modal
|
||||
(st/emit!
|
||||
(modal/show :subscription-success
|
||||
{:subscription-name (if (= params-subscription "subscribed-to-penpot-unlimited")
|
||||
(tr "subscription.settings.unlimited-trial")
|
||||
(tr "subscription.settings.enterprise-trial"))})
|
||||
(du/update-profile-props {:subscription
|
||||
(-> subscription
|
||||
(assoc :type (if (= params-subscription "subscribed-to-penpot-unlimited")
|
||||
"unlimited"
|
||||
"enterprise"))
|
||||
(assoc :status "trialing"))})
|
||||
(rt/nav :settings-subscription {} {::rt/replace true}))))
|
||||
(st/emit!
|
||||
(ptk/event ::ev/event {::ev/name "open-subscription-modal"
|
||||
::ev/origin "settings:from-pricing-page"})
|
||||
(modal/show :management-dialog
|
||||
{:subscription-type (if (= params-subscription "subscription-to-penpot-unlimited")
|
||||
"unlimited"
|
||||
"enterprise")
|
||||
:teams teams
|
||||
:subscribe-to-trial (not subscription)})
|
||||
(rt/nav :settings-subscription {} {::rt/replace true}))
|
||||
|
||||
^boolean show-subscription-success-modal?
|
||||
(st/emit!
|
||||
(modal/show :subscription-success
|
||||
{:subscription-name (if (= params-subscription "subscribed-to-penpot-unlimited")
|
||||
(tr "subscription.settings.unlimited-trial")
|
||||
(tr "subscription.settings.enterprise-trial"))})
|
||||
(du/update-profile-props {:subscription
|
||||
(-> subscription
|
||||
(assoc :type (if (= params-subscription "subscribed-to-penpot-unlimited")
|
||||
"unlimited"
|
||||
"enterprise"))
|
||||
(assoc :status "trialing"))})
|
||||
(rt/nav :settings-subscription {} {::rt/replace true})))))
|
||||
|
||||
[:section {:class (stl/css :dashboard-section)}
|
||||
[:div {:class (stl/css :dashboard-content)}
|
||||
|
|
@ -301,7 +330,7 @@
|
|||
(tr "subscription.settings.professional.storage")]}]
|
||||
|
||||
"unlimited"
|
||||
(if subscription-is-trial
|
||||
(if subscription-is-trial?
|
||||
[:> plan-card* {:card-title (tr "subscription.settings.unlimited-trial")
|
||||
:card-title-icon i/character-u
|
||||
:benefits-title (tr "subscription.settings.benefits.all-professional-benefits")
|
||||
|
|
@ -325,7 +354,7 @@
|
|||
:editors (-> profile :props :subscription :quantity)}])
|
||||
|
||||
"enterprise"
|
||||
(if subscription-is-trial
|
||||
(if subscription-is-trial?
|
||||
[:> plan-card* {:card-title (tr "subscription.settings.enterprise-trial")
|
||||
:card-title-icon i/character-e
|
||||
:benefits-title (tr "subscription.settings.benefits.all-professional-benefits")
|
||||
|
|
@ -344,13 +373,16 @@
|
|||
:cta-link go-to-payments}]))
|
||||
|
||||
[:div {:class (stl/css :membership-container)}
|
||||
(when subscription-member [:div {:class (stl/css :membership)}
|
||||
[:span {:class (stl/css :subscription-member)} i/crown]
|
||||
[:span {:class (stl/css :membership-date)} (tr "subscription.settings.support-us-since" subscription-member)]])
|
||||
(when subscribed-since
|
||||
[:div {:class (stl/css :membership)}
|
||||
[:span {:class (stl/css :subscription-member)} i/crown]
|
||||
[:span {:class (stl/css :membership-date)}
|
||||
(tr "subscription.settings.support-us-since" subscribed-since)]])
|
||||
|
||||
[:div {:class (stl/css :membership)}
|
||||
[:span {:class (stl/css :penpot-member)} i/user]
|
||||
[:span {:class (stl/css :membership-date)} (tr "subscription.settings.member-since" penpot-member)]]]]
|
||||
[:span {:class (stl/css :membership-date)}
|
||||
(tr "subscription.settings.member-since" member-since)]]]]
|
||||
|
||||
[:div {:class (stl/css :other-subscriptions)}
|
||||
[:h3 {:class (stl/css :plan-section-title)} (tr "subscription.settings.other-plans")]
|
||||
|
|
|
|||
|
|
@ -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…
Reference in New Issue