🐛 Fix downgrade to Professional bypassing warning modal (#10814)

* 🐛 Fix downgrade to Professional bypassing warning modal

* 📎 Code review
This commit is contained in:
María Valderrama 2026-07-24 14:08:11 +02:00 committed by GitHub
parent 8142f4949e
commit 62880cb58c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 49 additions and 18 deletions

View File

@ -93,7 +93,7 @@
:profile-id profile-id
:team-permissions team-permissions}))
(def go-to-subscription-url (u/join cf/public-uri "#/settings/subscriptions"))
(def go-to-subscription-url (dm/str (u/join cf/public-uri "#/settings/subscriptions")))
(def go-to-ac-url (build-admin-console-url ""))

View File

@ -502,10 +502,11 @@
open-contact-sales-modal
(mf/use-fn
(mf/deps nitrate-license)
(fn [current-subscription subscription-type]
(fn [current-subscription subscription-type & [has-billing-access?]]
(if (= current-subscription "unlimited")
(st/emit! (dnt/show-nitrate-popup :nitrate-dialog {:nitrate-license nitrate-license :show-contact-sales-option true}))
(st/emit! (modal/show :nitrate-contact-sales-dialog {:subscription-type subscription-type})))))
(st/emit! (modal/show :nitrate-contact-sales-dialog {:subscription-type subscription-type
:has-billing-access? has-billing-access?})))))
open-cancel-contact-sales-modal
(mf/use-fn
@ -701,10 +702,9 @@
(tr "subscription.settings.professional.teams-editors-benefit")
(tr "subscription.settings.professional.selfhost.community-support"))]
:cta-text (tr "subscription.settings.subscribe")
:cta-link (if (and (contains? cf/flags :nitrate) nitrate? (= subscription-type "nitrate"))
(if (and (:licenses connectivity) (not (:manual nitrate-license)))
dnt/go-to-nitrate-billing
open-cancel-contact-sales-modal)
:cta-link (if (and (contains? cf/flags :nitrate) nitrate?)
#(open-contact-sales-modal subscription-type "Professional"
(and (:licenses connectivity) (not (:manual nitrate-license))))
go-to-payments)
:cta-text-with-icon (tr "subscription.settings.more-information")
:cta-link-with-icon go-to-pricing-page
@ -827,11 +827,17 @@
(mf/defc nitrate-contact-sales-dialog
{::mf/register modal/components
::mf/register-as :nitrate-contact-sales-dialog}
[{:keys [subscription-type]}]
[{:keys [subscription-type has-billing-access?]}]
(let [handle-close-dialog
(mf/use-fn
(fn []
(modal/hide!)))]
(modal/hide!)))
handle-continue-click
(mf/use-fn
(fn []
(modal/hide!)
(dnt/go-to-nitrate-billing)))]
[:div {:class (stl/css :modal-overlay)}
[:div {:class (stl/css :modal-dialog)}
@ -848,15 +854,24 @@
[:li {:class (stl/css :downgrade-item)} (tr "nitrate.contact-sales.downgrade-teams-available")]
[:li {:class (stl/css :downgrade-item)} (tr "nitrate.contact-sales.downgrade-storage-limited")]]
[:div {:class (stl/css :downgrade-warning)}
(tr "nitrate.contact-sales.downgrade-contact-info")]
[:div {:class (stl/css :action-buttons)}
[:> button* {:variant "secondary"
:type "button"
:on-click handle-close-dialog} (tr "ds.confirm-cancel")]
[:> button* {:variant "primary"
:type "button"
:on-click #(dom/open-new-window "mailto:sales@penpot.app?subject=Switch%20to%20the%20Unlimited%20plan")} (tr "nitrate.contact-sales.button")]]]]]))
(if has-billing-access?
[:div {:class (stl/css :action-buttons)}
[:> button* {:variant "secondary"
:type "button"
:on-click handle-close-dialog} (tr "ds.confirm-cancel")]
[:> button* {:variant "primary"
:type "button"
:on-click handle-continue-click} (tr "labels.continue")]]
[:*
[:div {:class (stl/css :downgrade-warning)}
(tr "nitrate.contact-sales.downgrade-contact-info")]
[:div {:class (stl/css :action-buttons)}
[:> button* {:variant "secondary"
:type "button"
:on-click handle-close-dialog} (tr "ds.confirm-cancel")]
[:> button* {:variant "primary"
:type "button"
:on-click #(dom/open-new-window (dm/str "mailto:sales@penpot.app?subject=Switch%20to%20the%20" subscription-type "%20plan"))} (tr "nitrate.contact-sales.button")]]])]]]))
(mf/defc nitrate-cancel-contact-sales-dialog
{::mf/register modal/components

View File

@ -64,3 +64,19 @@
(u/uri "https://localhost:3449/#/settings/subscriptions"))]
(t/is (= "https://localhost:3449/#/settings/subscriptions?subscription=nitrate-checkout-error"
(:error-callback callbacks))))))
(t/deftest go-to-subscription-url-is-a-string
(t/testing "must be a string so licenses/billing?callback=... survives query encoding"
(t/is (string? dnt/go-to-subscription-url))
(t/is (not (u/uri? dnt/go-to-subscription-url)))))
(t/deftest build-admin-console-billing-url-encodes-string-callback
(t/testing "billing callback query param round-trips as a real URL string"
(let [public-uri (u/uri "https://localhost:3449/")
callback "https://localhost:3449/#/settings/subscriptions"
href (dnt/build-admin-console-url
public-uri
"licenses/billing"
{:callback callback})
parsed (-> href u/uri :query u/query-string->map :callback)]
(t/is (= callback parsed)))))