Add expired subscription banner

This commit is contained in:
Marina López 2026-06-01 15:03:43 +02:00
parent e12e5f8373
commit fc3a95765d
6 changed files with 153 additions and 31 deletions

View File

@ -391,6 +391,24 @@
profile-id)
schema:subscription params)))
(def ^:private schema:subscription-warning
[:maybe
[:map {:title "SubscriptionWarning"}
[:type {:optional true} ::sm/text]
[:days-from-expiry {:optional true} ::sm/int]
[:days-until-expiry {:optional true} ::sm/int]
[:expiration-date {:optional true} schema:timestamp]]])
(defn- get-subscription-warning-api
[cfg {:keys [penpot-id profile-id] :as params}]
(let [baseuri (cf/get :nitrate-backend-uri)
penpot-id (or penpot-id profile-id)]
(request-to-nitrate cfg :get
(str baseuri
"/api/subscription-warning/"
penpot-id)
schema:subscription-warning params)))
(defn- get-connectivity-api
[cfg params]
(let [baseuri (cf/get :nitrate-backend-uri)]
@ -459,6 +477,7 @@
:delete-team (partial delete-team-api cfg)
:remove-team-from-org (partial remove-team-from-org-api cfg)
:get-subscription (partial get-subscription-api cfg)
:get-subscription-warning (partial get-subscription-warning-api cfg)
:connectivity (partial get-connectivity-api cfg)
:redeem-activation-code (partial redeem-activation-code-api cfg)}))
@ -527,6 +546,3 @@
:context {:team-id (:id team)
:organization-id (:organization-id params)}))
team))

View File

@ -59,6 +59,22 @@
[cfg _params]
(nitrate/call cfg :connectivity {}))
(def ^:private schema:subscription-warning
[:maybe
[:map {:title "SubscriptionWarning"}
[:type {:optional true} ::sm/text]
[:days-from-expiry {:optional true} ::sm/int]
[:days-until-expiry {:optional true} ::sm/int]
[:expiration-date {:optional true} ct/schema:inst]]])
(sv/defmethod ::get-subscription-warning
{::rpc/auth true
::doc/added "2.14"
::sm/params [:map]
::sm/result schema:subscription-warning}
[cfg {:keys [::rpc/profile-id]}]
(nitrate/call cfg :get-subscription-warning {:profile-id profile-id}))
(def ^:private schema:redeem-activation-code-params
[:map {:title "RedeemActivationCodeParams"}
[:activation-code ::sm/text]])

View File

@ -133,6 +133,10 @@
[]
(rp/cmd! ::get-nitrate-connectivity {}))
(defn fetch-subscription-warning
[]
(rp/cmd! ::get-subscription-warning {}))
(defn is-valid-license?
[profile]
(and (contains? cf/flags :nitrate)

View File

@ -4,6 +4,7 @@
(:require-macros [app.main.style :as stl])
(:require
[app.common.data.macros :as dm]
[app.common.time :as ct]
[app.config :as cf]
[app.main.data.event :as ev]
[app.main.data.nitrate :as dnt]
@ -16,6 +17,7 @@
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[app.util.keyboard :as kbd]
[beicon.v2.core :as rx]
[lambdaisland.uri :as u]
[rumext.v2 :as mf]))
@ -119,6 +121,20 @@
[{:keys [profile teams]}]
(let [nitrate? (dnt/is-valid-license? profile)
nitrate-license (:subscription profile)
manual-license? (:manual nitrate-license)
subscription-warning* (mf/use-state nil)
subscription-warning (deref subscription-warning*)
days-until-expiry (or (:days-until-expiry subscription-warning)
(:daysUntilExpiry subscription-warning)
(:days-from-expiry subscription-warning)
(:daysFromExpiry subscription-warning))
expiration-date (or (:expiration-date subscription-warning)
(:expirationDate subscription-warning))
expiration-date-text (when expiration-date
(ct/format-inst expiration-date "MMMM d"))
show-subscription-warning? (and manual-license?
(some? days-until-expiry)
(some? expiration-date-text))
subscription-type (if nitrate? (:type nitrate-license) (get-subscription-type (-> profile :props :subscription)))
no-orgs-created? (mf/with-memo [teams]
(->> teams
@ -134,34 +150,64 @@
(st/emit! (dnt/show-nitrate-popup :nitrate-form)))))
handle-go-to-cc
(mf/use-fn dnt/go-to-nitrate-ac-create-org)]
(mf/use-fn dnt/go-to-nitrate-ac-create-org)
;; TODO add translations for this texts when we have the definitive ones
(if (and nitrate? no-orgs-created?)
;; Banner for users with active nitrate license but no organizations created
[:div {:class (stl/css :nitrate-banner :highlighted)}
[:div {:class (stl/css :nitrate-content)}
[:span {:class (stl/css :nitrate-title)} (tr "subscription.banner.see-enterprise")]]
[:div {:class (stl/css :nitrate-content)}
[:span {:class (stl/css :nitrate-info)} (tr "subscription.banner.create-org-info")]
[:> button* {:variant "primary"
:type "button"
:class (stl/css :nitrate-bottom-button)
:on-click handle-go-to-cc} (tr "nitrate.activation-success.create-org")]]]
handle-go-to-subscription
(mf/use-fn #(st/emit! (rt/nav :settings-subscription)))]
;; Banner for users without nitrate license
(when (not nitrate?)
[:div {:class (stl/css :nitrate-banner :highlighted)}
[:div {:class (stl/css :nitrate-content)}
[:span {:class (stl/css :nitrate-title)} (tr "subscription.dashboard.banner.unlock-features")]]
[:div {:class (stl/css :nitrate-content)}
[:span {:class (stl/css :nitrate-info)} (tr "subscription.dashboard.banner.unlock-features-description")]
[:> button* {:variant "primary"
:type "button"
:class (stl/css :nitrate-bottom-button)
:on-click handle-click} (if (:subscription profile)
(tr "subscription.dashboard.banner.upgrade-nitrate")
(tr "nitrate.form.try-free"))]]]))))
(mf/with-effect [manual-license?]
(if manual-license?
(->> (dnt/fetch-subscription-warning)
(rx/subs! #(reset! subscription-warning* %)))
(reset! subscription-warning* nil)))
[:*
;; TODO add translations for this texts when we have the definitive ones
(if (and nitrate? no-orgs-created? (not show-subscription-warning?))
;; Banner for users with active nitrate license but no organizations created
[:div {:class (stl/css :nitrate-banner :highlighted)}
[:div {:class (stl/css :nitrate-content)}
[:span {:class (stl/css :nitrate-title)} (tr "subscription.banner.see-enterprise")]]
[:div {:class (stl/css :nitrate-content)}
[:span {:class (stl/css :nitrate-info)} (tr "subscription.banner.create-org-info")]
[:> button* {:variant "primary"
:type "button"
:class (stl/css :nitrate-bottom-button)
:on-click handle-go-to-cc} (tr "nitrate.activation-success.create-org")]]]
;; Banner for users without nitrate license
(when (not nitrate?)
[:div {:class (stl/css :nitrate-banner :highlighted)}
[:div {:class (stl/css :nitrate-content)}
[:span {:class (stl/css :nitrate-title)} (tr "subscription.dashboard.banner.unlock-features")]]
[:div {:class (stl/css :nitrate-content)}
[:span {:class (stl/css :nitrate-info)} (tr "subscription.dashboard.banner.unlock-features-description")]
[:> button* {:variant "primary"
:type "button"
:class (stl/css :nitrate-bottom-button)
:on-click handle-click} (if (:subscription profile)
(tr "subscription.dashboard.banner.upgrade-nitrate")
(tr "nitrate.form.try-free"))]]]))
;; Banner for users with nitrate license almost expired or expired
(when show-subscription-warning?
[:div {:class (stl/css :nitrate-banner :highlighted)}
[:div {:class (stl/css :nitrate-content)}
[:span {:class (stl/css :nitrate-title)}
(tr "subscription.dashboard.banner.renew-subscription")]]
[:div {:class (stl/css :nitrate-content)}
[:span {:class (stl/css :nitrate-info)}
(if (neg? days-until-expiry)
(tr "subscription.dashboard.banner.subscription-expired"
expiration-date-text)
(tr "subscription.dashboard.banner.subscription-expire-days"
days-until-expiry
expiration-date-text))]
[:> button* {:variant "primary"
:type "button"
:class (stl/css :nitrate-bottom-button)
:on-click handle-go-to-subscription}
(tr "subscription.dashboard.banner.renew")]]])]))
(mf/defc nitrate-current-plan*
[{:keys [profile]}]

View File

@ -5812,7 +5812,27 @@ msgstr "Inviting people while on the Unlimited plan"
msgid "subscription.dashboard.upgrade-plan.power-up"
msgstr "Power up"
#: src/app/main/ui/settings/subscription.cljs:409
msgid "subscription.dashboard.banner.unlock-features"
msgstr "Unlock Enterprise features"
msgid "subscription.dashboard.banner.unlock-features-description"
msgstr "Set fine-grained permissions and keep your design operations secure, without compromising the open-source freedom your team already loves."
msgid "subscription.dashboard.banner.renew-subscription"
msgstr "Renew your subscription"
msgid "subscription.dashboard.banner.subscription-expire-days"
msgstr "Your Enterprise subscription expires in %s days (%s)"
msgid "subscription.dashboard.banner.subscription-expired"
msgstr "Your Enterprise subscription has expired. (%s)"
msgid "subscription.dashboard.banner.renew"
msgstr "Renew"
msgid "subscription.dashboard.banner.upgrade-nitrate"
msgstr "Get started with Enterprise"
msgid "subscription.error.nitrate.checkout-cancelled"
msgstr "Payment was not completed. Try again whenever you're ready."

View File

@ -5674,7 +5674,27 @@ msgstr "Invita a personas mientras estás en el plan Unlimited"
msgid "subscription.dashboard.upgrade-plan.power-up"
msgstr "Mejora"
#: src/app/main/ui/settings/subscription.cljs:409
msgid "subscription.dashboard.banner.unlock-features"
msgstr "Desbloquea las funciones Enterprise"
msgid "subscription.dashboard.banner.unlock-features-description"
msgstr "Establece permisos detallados y garantiza la seguridad de tus operaciones de diseño, sin renunciar a la libertad del código abierto que tanto valora tu equipo."
msgid "subscription.dashboard.banner.renew-subscription"
msgstr "Renueva tu suscripción"
msgid "subscription.dashboard.banner.subscription-expire-days"
msgstr "Tu suscripción Enterprise caduca en %s días (%s)"
msgid "subscription.dashboard.banner.subscription-expired"
msgstr "Tu suscripción Enterprise ha caducado. (%s)"
msgid "subscription.dashboard.banner.renew"
msgstr "Renovar"
msgid "subscription.dashboard.banner.upgrade-nitrate"
msgstr "Empieza a utilizar Enterprise"
msgid "subscription.error.nitrate.checkout-cancelled"
msgstr "El pago no se completó. Inténtalo de nuevo cuando quieras."