From a5eba8e722ed3ad0c33043b8eefe530bd890a6cc Mon Sep 17 00:00:00 2001 From: Vladyslav Matsiiako Date: Thu, 26 Jan 2023 16:32:51 -0800 Subject: [PATCH] Updated the billing engine for Cloud --- frontend/public/data/frequentConstants.ts | 17 ++++ .../dialog/AddUpdateEnvironmentDialog.tsx | 2 +- .../components/basic/dialog/AddUserDialog.tsx | 8 +- .../basic/dialog/DeleteActionModal.tsx | 4 +- .../components/basic/dialog/UpgradePlan.tsx | 86 +++++++++++++++++++ .../basic/table/EnvironmentsTable.tsx | 59 +++++++++++-- frontend/src/pages/settings/billing/[id].tsx | 33 ++++--- frontend/src/pages/settings/org/[id].tsx | 10 ++- 8 files changed, 192 insertions(+), 27 deletions(-) create mode 100644 frontend/src/components/basic/dialog/UpgradePlan.tsx diff --git a/frontend/public/data/frequentConstants.ts b/frontend/public/data/frequentConstants.ts index d2beee6d2..2ff525e54 100644 --- a/frontend/public/data/frequentConstants.ts +++ b/frontend/public/data/frequentConstants.ts @@ -30,8 +30,25 @@ const reverseContextNetlifyMapping: Mapping = { "Production": "production" } +const plansDev: Mapping = { + "starter": "prod_Mb4ATFT5QAHoPM", + "team": "prod_NEpD2WMXUS2eDn", + "professional": "prod_Mb4CetZ2jE7jdl", + "enterprise": "licence_key_required" +} + +const plansProd: Mapping = { + "starter": "prod_Mb8oR5XNwyFTul", + "team": "prod_NEp7fAB3UJWK6A", + "professional": "prod_Mb8pUIpA0OUi5N", + "enterprise": "licence_key_required" +} + +const plans = plansProd || plansDev; + export { contextNetlifyMapping, envMapping, + plans, reverseContextNetlifyMapping, reverseEnvMapping} diff --git a/frontend/src/components/basic/dialog/AddUpdateEnvironmentDialog.tsx b/frontend/src/components/basic/dialog/AddUpdateEnvironmentDialog.tsx index fc216a35a..70e9b0f47 100644 --- a/frontend/src/components/basic/dialog/AddUpdateEnvironmentDialog.tsx +++ b/frontend/src/components/basic/dialog/AddUpdateEnvironmentDialog.tsx @@ -86,7 +86,7 @@ export const AddUpdateEnvironmentDialog = ({ leaveFrom='opacity-100 scale-100' leaveTo='opacity-0 scale-95' > - + - {currentPlan === STRIPE_PRODUCT_STARTER && ( + {currentPlan === plans.starter && (
+ +
+
+ + + + + + + ); +}; + +export default UpgradePlanModal; diff --git a/frontend/src/components/basic/table/EnvironmentsTable.tsx b/frontend/src/components/basic/table/EnvironmentsTable.tsx index 2a3b3fb0e..8ff7d9f0a 100644 --- a/frontend/src/components/basic/table/EnvironmentsTable.tsx +++ b/frontend/src/components/basic/table/EnvironmentsTable.tsx @@ -1,9 +1,13 @@ +import { useEffect, useState } from 'react'; import { faPencil, faPlus, faX } from '@fortawesome/free-solid-svg-icons'; +import { plans } from 'public/data/frequentConstants'; import { usePopUp } from '../../../hooks/usePopUp'; +import getOrganizationSubscriptions from '../../../pages/api/organization/GetOrgSubscription'; import Button from '../buttons/Button'; import { AddUpdateEnvironmentDialog } from '../dialog/AddUpdateEnvironmentDialog'; import DeleteActionModal from '../dialog/DeleteActionModal'; +import UpgradePlanModal from '../dialog/UpgradePlan'; type Env = { name: string; slug: string }; @@ -17,8 +21,24 @@ type Props = { const EnvironmentTable = ({ data = [], onCreateEnv, onDeleteEnv, onUpdateEnv }: Props) => { const { popUp, handlePopUpOpen, handlePopUpClose } = usePopUp([ 'createUpdateEnv', - 'deleteEnv' + 'deleteEnv', + 'upgradePlan' ] as const); + const [plan, setPlan] = useState(''); + const host = window.location.origin; + + useEffect(() => { + // on initial load - run auth check + (async () => { + const orgId = localStorage.getItem('orgData.id') as string; + const subscriptions = await getOrganizationSubscriptions({ + orgId + }); + setPlan(subscriptions.data[0].plan.product); + })(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + const onEnvCreateCB = async (env: Env) => { try { @@ -63,7 +83,13 @@ const EnvironmentTable = ({ data = [], onCreateEnv, onDeleteEnv, onUpdateEnv }:
-
+
); diff --git a/frontend/src/pages/settings/billing/[id].tsx b/frontend/src/pages/settings/billing/[id].tsx index e3cd22191..1f90afcd4 100644 --- a/frontend/src/pages/settings/billing/[id].tsx +++ b/frontend/src/pages/settings/billing/[id].tsx @@ -1,10 +1,10 @@ import { useEffect, useState } from 'react'; import Head from 'next/head'; import { useTranslation } from 'next-i18next'; +import { plans as plansConstant } from 'public/data/frequentConstants'; import Plan from '@app/components/billing/Plan'; import NavHeader from '@app/components/navigation/NavHeader'; -import { STRIPE_PRODUCT_PRO, STRIPE_PRODUCT_STARTER } from '@app/components/utilities/config'; import { getTranslatedServerSideProps } from '@app/components/utilities/withTranslateProps'; import getOrganizationSubscriptions from '../../api/organization/GetOrgSubscription'; @@ -26,24 +26,34 @@ export default function SettingsBilling() { subtext: t('billing:starter.subtext')!, buttonTextMain: t('billing:downgrade')!, buttonTextSecondary: t('billing:learn-more')!, - current: currentPlan === STRIPE_PRODUCT_STARTER + current: currentPlan === plansConstant.starter }, { key: 2, - name: t('billing:professional.name')!, - price: '$9', + name: 'Team', + price: '$7', priceExplanation: t('billing:professional.price-explanation')!, - subtext: t('billing:professional.subtext')!, - text: t('billing:professional.text')!, + text: 'For teams that want to improve their efficiency and security.', buttonTextMain: t('billing:upgrade')!, buttonTextSecondary: t('billing:learn-more')!, - current: currentPlan === STRIPE_PRODUCT_PRO + current: currentPlan === plansConstant.team }, { key: 3, + name: t('billing:professional.name')!, + price: '$14', + priceExplanation: t('billing:professional.price-explanation')!, + text: t('billing:enterprise.text')!, + subtext: t('billing:professional.subtext')!, + buttonTextMain: t('billing:upgrade')!, + buttonTextSecondary: t('billing:learn-more')!, + current: currentPlan === plansConstant.professional + }, + { + key: 4, name: t('billing:enterprise.name')!, price: t('billing:custom-pricing')!, - text: t('billing:enterprise.text')!, + text: 'Boost the security and efficiency of your engineering teams.', buttonTextMain: t('billing:schedule-demo')!, buttonTextSecondary: t('billing:learn-more')!, current: false @@ -57,7 +67,7 @@ export default function SettingsBilling() { orgId }); - setCurrentPlan(subscriptions.data[0].plan.id); + setCurrentPlan(subscriptions.data[0].plan.product); const orgUsers = await getOrganizationUsers({ orgId }); @@ -80,9 +90,10 @@ export default function SettingsBilling() {

{t('billing:description')}

-
+

{t('billing:subscription')}

-
+
If you are looking to get an annual plan, please reach out to team@infisical.com
+
{plans.map((plan) => ( ))} diff --git a/frontend/src/pages/settings/org/[id].tsx b/frontend/src/pages/settings/org/[id].tsx index 15fcf07cf..bb25d0a5c 100644 --- a/frontend/src/pages/settings/org/[id].tsx +++ b/frontend/src/pages/settings/org/[id].tsx @@ -5,10 +5,12 @@ import { useRouter } from 'next/router'; import { useTranslation } from 'next-i18next'; import { faCheck, faMagnifyingGlass, faPlus, faX } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { plans } from 'public/data/frequentConstants'; import Button from '@app/components/basic/buttons/Button'; import AddIncidentContactDialog from '@app/components/basic/dialog/AddIncidentContactDialog'; import AddUserDialog from '@app/components/basic/dialog/AddUserDialog'; +import UpgradePlanModal from '@app/components/basic/dialog/UpgradePlan'; import InputField from '@app/components/basic/InputField'; import UserTable from '@app/components/basic/table/UserTable'; import NavHeader from '@app/components/navigation/NavHeader'; @@ -29,6 +31,7 @@ import getWorkspaces from '../../api/workspace/getWorkspaces'; export default function SettingsOrg() { const [buttonReady, setButtonReady] = useState(false); const router = useRouter(); + const host = window.location.origin; const [orgName, setOrgName] = useState(''); const [emailUser, setEmailUser] = useState(''); const [workspaceToBeDeletedName, setWorkspaceToBeDeletedName] = useState(''); @@ -212,7 +215,7 @@ export default function SettingsOrg() { {t('section-members:org-members-description')}

+ = 5 && currentPlan === plans.starter && host === 'https://app.infisical.com'} + onClose={closeAddUserModal} + text="You can add more members if you switch to Infisical's Team plan." + /> {/* */}