diff --git a/backend/src/app/nitrate.clj b/backend/src/app/nitrate.clj index 14c1da0e99..690ba662fb 100644 --- a/backend/src/app/nitrate.clj +++ b/backend/src/app/nitrate.clj @@ -87,6 +87,10 @@ [:map [:valid ::sm/boolean]]) +(def ^:private schema:connectivity + [:map + [:licenses ::sm/boolean]]) + (defn- get-team-org [cfg {:keys [team-id] :as params}] (let [baseuri (cf/get :nitrate-backend-uri)] @@ -97,6 +101,11 @@ (let [baseuri (cf/get :nitrate-backend-uri)] (request-to-nitrate cfg :get (str baseuri "/api/users/" (str profile-id)) schema:user params))) +(defn- get-connectivity + [cfg params] + (let [baseuri (cf/get :nitrate-backend-uri)] + (request-to-nitrate cfg :get (str baseuri "/api/connectivity") schema:connectivity params))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; INITIALIZATION ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -105,7 +114,8 @@ [_ cfg] (when (contains? cf/flags :nitrate) {:get-team-org (partial get-team-org cfg) - :is-valid-user (partial is-valid-user cfg)})) + :is-valid-user (partial is-valid-user cfg) + :connectivity (partial get-connectivity cfg)})) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; UTILS @@ -128,3 +138,7 @@ (let [params (assoc (or params {}) :team-id (:id team)) org (call cfg :get-team-org params)] (assoc team :organization-id (:id org) :organization-name (:name org)))) + +(defn connectivity + [cfg] + (call cfg :connectivity {})) diff --git a/backend/src/app/rpc.clj b/backend/src/app/rpc.clj index 487e8eb668..4b47c19451 100644 --- a/backend/src/app/rpc.clj +++ b/backend/src/app/rpc.clj @@ -262,6 +262,7 @@ 'app.rpc.commands.ldap 'app.rpc.commands.management 'app.rpc.commands.media + 'app.rpc.commands.nitrate 'app.rpc.commands.profile 'app.rpc.commands.projects 'app.rpc.commands.search diff --git a/backend/src/app/rpc/commands/nitrate.clj b/backend/src/app/rpc/commands/nitrate.clj new file mode 100644 index 0000000000..5313817fd3 --- /dev/null +++ b/backend/src/app/rpc/commands/nitrate.clj @@ -0,0 +1,20 @@ +(ns app.rpc.commands.nitrate + (:require + [app.common.schema :as sm] + [app.nitrate :as nitrate] + [app.rpc :as-alias rpc] + [app.rpc.doc :as-alias doc] + [app.util.services :as sv])) + + +(def schema:connectivity + [:map {:title "nitrate-connectivity"} + [:licenses ::sm/boolean]]) + +(sv/defmethod ::get-nitrate-connectivity + {::rpc/auth false + ::doc/added "1.18" + ::sm/params [:map] + ::sm/result schema:connectivity} + [cfg _params] + (nitrate/connectivity cfg)) diff --git a/frontend/src/app/main/data/nitrate.cljs b/frontend/src/app/main/data/nitrate.cljs new file mode 100644 index 0000000000..14c32a5021 --- /dev/null +++ b/frontend/src/app/main/data/nitrate.cljs @@ -0,0 +1,15 @@ +(ns app.main.data.nitrate + (:require + [app.main.data.modal :as modal] + [app.main.repo :as rp] + [beicon.v2.core :as rx] + [potok.v2.core :as ptk])) + +(defn show-nitrate-popup + [] + (ptk/reify ::show-nitrate-popup + ptk/WatchEvent + (watch [_ _ _] + (->> (rp/cmd! ::get-nitrate-connectivity {}) + (rx/map (fn [connectivity] + (modal/show :nitrate-form (or connectivity {})))))))) diff --git a/frontend/src/app/main/ui/dashboard/sidebar.cljs b/frontend/src/app/main/ui/dashboard/sidebar.cljs index a5e158c8a7..a293f11bfe 100644 --- a/frontend/src/app/main/ui/dashboard/sidebar.cljs +++ b/frontend/src/app/main/ui/dashboard/sidebar.cljs @@ -16,6 +16,7 @@ [app.main.data.dashboard :as dd] [app.main.data.event :as ev] [app.main.data.modal :as modal] + [app.main.data.nitrate :as dnt] [app.main.data.notifications :as ntf] [app.main.data.team :as dtm] [app.main.refs :as refs] @@ -304,7 +305,7 @@ (if (:nitrate-licence profile) ;; TODO update when org creation route is ready (dom/open-new-window "/control-center/org/create") - (st/emit! (modal/show :nitrate-form {})))))] + (st/emit! (dnt/show-nitrate-popup)))))] [:> dropdown-menu* props @@ -550,7 +551,7 @@ (if (:nitrate-licence profile) ;; TODO update when org creation route is ready (dom/open-new-window "/control-center/org/create") - (st/emit! (modal/show :nitrate-form {})))))] + (st/emit! (dnt/show-nitrate-popup)))))] (if empty? [:div {:class (stl/css :nitrate-orgs-empty)} [:span {:class (stl/css :nitrate-penpot-icon)} diff --git a/frontend/src/app/main/ui/dashboard/subscription.cljs b/frontend/src/app/main/ui/dashboard/subscription.cljs index 44f35f6f32..be502bb46f 100644 --- a/frontend/src/app/main/ui/dashboard/subscription.cljs +++ b/frontend/src/app/main/ui/dashboard/subscription.cljs @@ -6,7 +6,7 @@ [app.common.data.macros :as dm] [app.config :as cf] [app.main.data.event :as ev] - [app.main.data.modal :as modal] + [app.main.data.nitrate :as dnt] [app.main.router :as rt] [app.main.store :as st] [app.main.ui.components.dropdown-menu :refer [dropdown-menu-item*]] @@ -121,7 +121,7 @@ (let [handle-click (mf/use-fn (fn [] - (st/emit! (modal/show :nitrate-form {}))))] + (st/emit! (dnt/show-nitrate-popup))))] ;; TODO add translations for this texts when we have the definitive ones [:div {:class (stl/css :nitrate-banner :highlighted)} diff --git a/frontend/src/app/main/ui/nitrate/nitrate_form.cljs b/frontend/src/app/main/ui/nitrate/nitrate_form.cljs index 516dcd0420..a1ff926499 100644 --- a/frontend/src/app/main/ui/nitrate/nitrate_form.cljs +++ b/frontend/src/app/main/ui/nitrate/nitrate_form.cljs @@ -22,10 +22,12 @@ (mf/defc nitrate-form-modal* {::mf/register modal/components - ::mf/register-as :nitrate-form} - [] + ::mf/register-as :nitrate-form + ::mf/wrap-props true} + [connectivity] - (let [initial (mf/with-memo [] + (let [show-buttons (:licenses connectivity) + initial (mf/with-memo [] {:subscription "yearly"}) form (fm/use-form :schema schema:nitrate-form :initial initial) @@ -55,26 +57,35 @@ "Sail ho shrouds spirits boom mizzenmast yardarm. Pinnace holystone mizzenmast quarter crow's nest nipperkin grog yardarm hempen halter furl."] [:p {:class (stl/css :modal-text-large)} "Deadlights jack lad schooner scallywag dance the hempen jig carouser broadside cable strike colors."] - [:p {:class (stl/css :modal-text-large)} - [:& fm/form {:form form} - [:& fm/radio-buttons - {:options [{:label "Price Tag Montly" :value "monthly"} - {:label "Price Tag Yearly (Discount)" :value "yearly"}] - :name :subscription - :class (stl/css :radio-btns)}]]] + (if show-buttons + [:& fm/form {:form form} + [:p {:class (stl/css :modal-text-large)} - [:p {:class (stl/css :modal-text-large :modal-buttons-section)} - [:div {:class (stl/css :modal-buttons-section)} - [:> button* {:variant "primary" - :on-click on-click - :class (stl/css :modal-button)} - "UPGRADE TO NITRATE"] - [:div {:class (stl/css :modal-text-small :modal-info)} - "Cancel anytime before your next billing cycle."]]] + [:& fm/radio-buttons + {:options [{:label "Price Tag Montly" :value "monthly"} + {:label "Price Tag Yearly (Discount)" :value "yearly"}] + :name :subscription + :class (stl/css :radio-btns)}]] + + [:p {:class (stl/css :modal-text-large :modal-buttons-section)} + [:div {:class (stl/css :modal-buttons-section)} + [:> button* {:variant "primary" + :on-click on-click + :class (stl/css :modal-button)} + "UPGRADE TO NITRATE"] + [:div {:class (stl/css :modal-text-small :modal-info)} + "Cancel anytime before your next billing cycle."]]] - [:p {:class (stl/css :modal-text-medium)} - [:a {:class (stl/css :link)} - "See my current plan"]]]]]])) + [:p {:class (stl/css :modal-text-medium)} + [:a {:class (stl/css :link)} + "See my current plan"]]] + + [:div {:class (stl/css :contact)} + [:p {:class (stl/css :modal-text-large)} + "Contact us to upgrade to Nitrate:"] + [:p {:class (stl/css :modal-text-large)} + [:a {:class (stl/css :link) :href "mailto:sales@penpot.app"} + "sales@penpot.app"]]])]]]])) diff --git a/frontend/src/app/main/ui/nitrate/nitrate_form.scss b/frontend/src/app/main/ui/nitrate/nitrate_form.scss index ad1d32d3c8..e32150a91c 100644 --- a/frontend/src/app/main/ui/nitrate/nitrate_form.scss +++ b/frontend/src/app/main/ui/nitrate/nitrate_form.scss @@ -89,3 +89,8 @@ padding: var(--sp-l) 0 0 0; gap: 0; } + +.contact { + margin-block-start: $sz-96; + color: var(--color-foreground-primary); +}