mirror of
https://github.com/Infisical/infisical.git
synced 2025-03-31 22:09:57 +00:00
Added limits to the number of projects in an org
This commit is contained in:
@ -17,8 +17,8 @@
|
||||
"starter": {
|
||||
"name": "Starter",
|
||||
"price-explanation": "up to 5 team members",
|
||||
"text": "Manage any project with 5 members for free!",
|
||||
"subtext": "$5 per member/month afterwards."
|
||||
"text": "Manage up to 3 project with up to 5 team members for free!",
|
||||
"subtext": ""
|
||||
},
|
||||
"professional": {
|
||||
"name": "Professional",
|
||||
|
@ -20,8 +20,8 @@ interface Props {
|
||||
export default function Plan({ plan }: Props) {
|
||||
return (
|
||||
<div
|
||||
className={`relative flex flex-col justify-between border-2 min-w-fit w-96 rounded-lg h-68 mr-4 bg-mineshaft-800 ${
|
||||
plan.name !== 'Starter' && plan.current === true ? 'border-primary' : 'border-chicago-700'
|
||||
className={`relative flex flex-col justify-between border min-w-fit w-96 rounded-lg h-68 mr-4 bg-mineshaft-800 ${
|
||||
plan.name !== 'Starter' && plan.current === true ? 'border-2 border-primary' : 'border-mineshaft-600'
|
||||
}
|
||||
`}
|
||||
>
|
||||
@ -41,13 +41,13 @@ export default function Plan({ plan }: Props) {
|
||||
<>
|
||||
{plan.buttonTextMain === 'Schedule a Demo' ? (
|
||||
<a href="/scheduledemo" target='_blank rel="noopener"'>
|
||||
<div className="relative z-10 mx-5 mt-3 mb-4 py-2 px-4 border border-1 border-gray-600 hover:text-black hover:border-primary text-gray-400 font-semibold hover:bg-primary bg-bunker duration-200 cursor-pointer rounded-md flex w-max">
|
||||
<div className="relative z-10 mx-5 mt-3 mb-4 py-2 px-4 border border-1 border-mineshaft-600 hover:text-black hover:border-primary text-gray-400 font-semibold hover:bg-primary bg-bunker duration-200 cursor-pointer rounded-md flex w-max">
|
||||
{plan.buttonTextMain}
|
||||
</div>
|
||||
</a>
|
||||
) : (
|
||||
<div
|
||||
className={`relative z-10 mx-5 mt-3 mb-4 py-2 px-4 border border-1 border-gray-600 text-gray-400 font-semibold ${
|
||||
className={`relative z-10 mx-5 mt-3 mb-4 py-2 px-4 border border-1 border-mineshaft-600 text-gray-400 font-semibold ${
|
||||
plan.buttonTextMain === 'Downgrade'
|
||||
? 'hover:bg-red hover:text-white hover:border-red'
|
||||
: 'hover:bg-primary hover:text-black hover:border-primary'
|
||||
@ -74,7 +74,7 @@ export default function Plan({ plan }: Props) {
|
||||
) : (
|
||||
<div
|
||||
className={`h-8 w-full rounded-b-md flex justify-center items-center z-10 ${
|
||||
plan.name !== 'Starter' && plan.current === true ? 'bg-primary' : 'bg-chicago-700'
|
||||
plan.name !== 'Starter' && plan.current === true ? 'bg-primary' : 'bg-mineshaft-400'
|
||||
}`}
|
||||
>
|
||||
<p className="text-xs text-black font-semibold">CURRENT PLAN</p>
|
||||
|
@ -16,7 +16,7 @@ const buttonVariants = cva(
|
||||
'button',
|
||||
'transition-all',
|
||||
'font-inter font-medium',
|
||||
'cursor-pointer',
|
||||
'cursor-default',
|
||||
'inline-flex items-center justify-center',
|
||||
'relative',
|
||||
'whitespace-nowrap'
|
||||
@ -24,7 +24,7 @@ const buttonVariants = cva(
|
||||
{
|
||||
variants: {
|
||||
colorSchema: {
|
||||
primary: ['bg-primary', 'text-black', 'border-primary bg-opacity-80 hover:bg-opacity-100'],
|
||||
primary: ['bg-primary', 'text-black', 'border-primary bg-opacity-90 hover:bg-opacity-100'],
|
||||
secondary: ['bg-mineshaft', 'text-gray-300', 'border-mineshaft hover:bg-opacity-80'],
|
||||
danger: ['bg-red', 'text-white', 'border-red hover:bg-opacity-90'],
|
||||
gray: ['bg-bunker-500', 'text-bunker-200']
|
||||
@ -40,7 +40,7 @@ const buttonVariants = cva(
|
||||
},
|
||||
isDisabled: {
|
||||
true: 'bg-mineshaft-700 border border-mineshaft-600 text-white opacity-50 cursor-not-allowed',
|
||||
false: 'border border-primary-400'
|
||||
false: 'border'
|
||||
},
|
||||
isFullWidth: {
|
||||
true: 'w-full',
|
||||
@ -111,7 +111,7 @@ const buttonVariants = cva(
|
||||
{
|
||||
colorSchema: 'secondary',
|
||||
variant: 'plain',
|
||||
className: 'text-mineshaft-300'
|
||||
className: 'text-mineshaft-300 hover:text-mineshaft-200 border-none'
|
||||
},
|
||||
{
|
||||
colorSchema: 'danger',
|
||||
|
@ -18,7 +18,7 @@ export const UpgradePlanModal = ({ text, isOpen, onOpenChange }: Props): JSX.Ele
|
||||
href={`/settings/billing/${localStorage.getItem('projectData.id') as string}`}
|
||||
key="upgrade-plan"
|
||||
>
|
||||
<Button className="mr-4">Upgrade Plan</Button>
|
||||
<Button className="mr-4 ml-2">Upgrade Plan</Button>
|
||||
</Link>,
|
||||
<ModalClose asChild key="upgrade-plan-cancel">
|
||||
<Button colorSchema="secondary" variant="plain">
|
||||
@ -27,8 +27,8 @@ export const UpgradePlanModal = ({ text, isOpen, onOpenChange }: Props): JSX.Ele
|
||||
</ModalClose>
|
||||
]}
|
||||
>
|
||||
<p className="mb-4 text-bunker-300">{text}</p>
|
||||
<p className="font-medium text-bunker-300">
|
||||
<p className="mb-2 text-bunker-300">{text}</p>
|
||||
<p className="text-bunker-300">
|
||||
Upgrade and get access to this, as well as to other powerful enhancements.
|
||||
</p>
|
||||
</ModalContent>
|
||||
|
@ -28,9 +28,11 @@ import {
|
||||
Modal,
|
||||
ModalContent,
|
||||
Select,
|
||||
SelectItem
|
||||
SelectItem,
|
||||
UpgradePlanModal
|
||||
} from '@app/components/v2';
|
||||
import { useOrganization, useUser, useWorkspace } from '@app/context';
|
||||
import { plans } from '@app/const';
|
||||
import { useOrganization, useSubscription, useUser, useWorkspace } from '@app/context';
|
||||
import { usePopUp } from '@app/hooks';
|
||||
import { fetchOrgUsers, useAddUserToWs, useCreateWorkspace, useUploadWsKey } from '@app/hooks/api';
|
||||
import getOrganizations from '@app/pages/api/organization/getOrgs';
|
||||
@ -57,13 +59,18 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
||||
const { workspaces, currentWorkspace } = useWorkspace();
|
||||
const { currentOrg } = useOrganization();
|
||||
const { user } = useUser();
|
||||
const { subscriptionPlan } = useSubscription();
|
||||
const host = window.location.origin;
|
||||
const isAddingProjectsAllowed =
|
||||
subscriptionPlan !== plans.starter || (subscriptionPlan === plans.starter && workspaces.length < 3) || host !== 'https://app.infisical.com';
|
||||
|
||||
const createWs = useCreateWorkspace();
|
||||
const uploadWsKey = useUploadWsKey();
|
||||
const addWsUser = useAddUserToWs();
|
||||
|
||||
const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([
|
||||
'addNewWs'
|
||||
'addNewWs',
|
||||
'upgradePlan'
|
||||
] as const);
|
||||
const {
|
||||
control,
|
||||
@ -274,7 +281,13 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
||||
colorSchema="primary"
|
||||
variant="outline_bg"
|
||||
size="sm"
|
||||
onClick={() => handlePopUpOpen('addNewWs')}
|
||||
onClick={() => {
|
||||
if (isAddingProjectsAllowed) {
|
||||
handlePopUpOpen('addNewWs')
|
||||
} else {
|
||||
handlePopUpOpen('upgradePlan');
|
||||
}
|
||||
}}
|
||||
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||
>
|
||||
Add Project
|
||||
@ -288,7 +301,13 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
||||
className="w-full bg-mineshaft-500 py-2 text-bunker-200 hover:bg-primary/90 hover:text-black"
|
||||
color="mineshaft"
|
||||
size="sm"
|
||||
onClick={() => handlePopUpOpen('addNewWs')}
|
||||
onClick={() => {
|
||||
if (isAddingProjectsAllowed) {
|
||||
handlePopUpOpen('addNewWs')
|
||||
} else {
|
||||
handlePopUpOpen('upgradePlan');
|
||||
}
|
||||
}}
|
||||
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||
>
|
||||
Add Project
|
||||
@ -464,6 +483,11 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
||||
</form>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
<UpgradePlanModal
|
||||
isOpen={popUp.upgradePlan.isOpen}
|
||||
onOpenChange={(isOpen) => handlePopUpToggle('upgradePlan', isOpen)}
|
||||
text="You have exceeded the number of projects allowed on the free plan."
|
||||
/>
|
||||
<main className="flex-1 overflow-y-auto overflow-x-hidden bg-bunker-800 dark:[color-scheme:dark]">
|
||||
{children}
|
||||
</main>
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Head from 'next/head';
|
||||
import { plans as plansConstant } from 'public/data/frequentConstants';
|
||||
|
||||
import Plan from '@app/components/billing/Plan';
|
||||
import NavHeader from '@app/components/navigation/NavHeader';
|
||||
import { plans as plansConstant } from '@app/const';
|
||||
|
||||
import getOrganizationSubscriptions from '../../api/organization/GetOrgSubscription';
|
||||
import getOrganizationUsers from '../../api/organization/GetOrgUsers';
|
||||
@ -32,7 +32,7 @@ export default function SettingsBilling() {
|
||||
name: 'Team',
|
||||
price: '$8',
|
||||
priceExplanation: t('billing.professional.price-explanation')!,
|
||||
text: 'For teams that want to improve their efficiency and security.',
|
||||
text: 'Unlimited members, up to 10 projects. Additional developer experience features.',
|
||||
buttonTextMain: t('billing.upgrade')!,
|
||||
buttonTextSecondary: t('billing.learn-more')!,
|
||||
current: currentPlan === plansConstant.team
|
||||
|
@ -11,7 +11,7 @@ export const ProjectIndexSecretsSection = ({
|
||||
onEnableBlindIndices
|
||||
}: Props) => {
|
||||
return (
|
||||
<div className="rounded-md bg-white/5 p-6">
|
||||
<div className="rounded-md bg-white/5 p-6 my-2">
|
||||
<p className="mb-4 text-xl font-semibold">Blind Indices</p>
|
||||
<p className="mb-4 text-sm text-gray-400">
|
||||
Your project, created before the introduction of blind indexing, contains unindexed secrets. To access individual secrets by name through the SDK and public API, please enable blind indexing.
|
||||
|
Reference in New Issue
Block a user