2
0

♻️ Add a new unlimited plan

Closes #273
This commit is contained in:
Baptiste Arnaud
2023-01-27 15:00:07 +01:00
parent 4f78dda640
commit 409e7643ad
12 changed files with 49 additions and 12 deletions

View File

@ -34,6 +34,7 @@ export const BillingContent = () => {
</HStack>
{workspace.plan !== Plan.CUSTOM &&
workspace.plan !== Plan.LIFETIME &&
workspace.plan !== Plan.UNLIMITED &&
workspace.plan !== Plan.OFFERED && <ChangePlanForm />}
</Stack>

View File

@ -136,7 +136,12 @@ export const UsageContent = ({ workspace }: Props) => {
>
{storageToReadable(totalStorageUsed)}
</Skeleton>
<Text>/ {workspaceStorageLimit} GB</Text>
<Text>
/{' '}
{workspaceStorageLimit === -1
? 'Unlimited'
: `${workspaceStorageLimit} GB`}
</Text>
</HStack>
</Flex>
<Progress

View File

@ -8,6 +8,7 @@ export const planColorSchemes: Record<Plan, ThemeTypings['colorSchemes']> = {
[Plan.STARTER]: 'orange',
[Plan.FREE]: 'gray',
[Plan.CUSTOM]: 'yellow',
[Plan.UNLIMITED]: 'yellow',
}
export const PlanTag = ({
@ -64,12 +65,23 @@ export const PlanTag = ({
return (
<Tag
colorScheme={planColorSchemes[Plan.CUSTOM]}
data-testid="free-plan-tag"
data-testid="custom-plan-tag"
{...props}
>
Custom
</Tag>
)
}
case Plan.UNLIMITED: {
return (
<Tag
colorScheme={planColorSchemes[Plan.UNLIMITED]}
data-testid="custom-unlimite-tag"
{...props}
>
Unlimited
</Tag>
)
}
}
}

View File

@ -12,6 +12,8 @@ export const planToReadable = (plan?: Plan) => {
return 'Offered'
case Plan.PRO:
return 'Pro'
case Plan.UNLIMITED:
return 'Unlimited'
}
}
@ -22,4 +24,5 @@ export const isProPlan = (workspace?: Pick<Workspace, 'plan'>) =>
isDefined(workspace) &&
(workspace.plan === Plan.PRO ||
workspace.plan === Plan.LIFETIME ||
workspace.plan === Plan.CUSTOM)
workspace.plan === Plan.CUSTOM ||
workspace.plan === Plan.UNLIMITED)

View File

@ -106,7 +106,10 @@ export const MembersList = () => {
)}
{workspace && (
<Heading fontSize="2xl">
Members ({currentMembersCount}/{getSeatsLimit(workspace)})
Members{' '}
{getSeatsLimit(workspace) === -1
? ''
: `(${currentMembersCount}/${getSeatsLimit(workspace)})`}
</Heading>
)}
{workspace?.id && canEdit && (

View File

@ -12,8 +12,12 @@ export function checkCanInviteMember({
}) {
if (!plan || !currentMembersCount) return false
return (
getSeatsLimit({ plan, customSeatsLimit: customSeatsLimit ?? null }) >
currentMembersCount
)
const seatsLimit = getSeatsLimit({
plan,
customSeatsLimit: customSeatsLimit ?? null,
})
if (seatsLimit === -1) return true
return seatsLimit > currentMembersCount
}

View File

@ -1,7 +1,7 @@
import { Plan } from 'db'
export const parseWorkspaceDefaultPlan = (userEmail: string) => {
if (process.env.ADMIN_EMAIL === userEmail) return Plan.LIFETIME
if (process.env.ADMIN_EMAIL === userEmail) return Plan.UNLIMITED
const defaultPlan = process.env.DEFAULT_WORKSPACE_PLAN as Plan | undefined
if (defaultPlan && Object.values(Plan).includes(defaultPlan))
return defaultPlan

View File

@ -16,7 +16,7 @@ import { SponsorButton } from '../../../src/js/SponsorButton.jsx'
| NEXTAUTH_URL | | The builder base URL. Should be the publicly accessible URL (i.e. `https://typebot.domain.com`) |
| NEXT_PUBLIC_VIEWER_URL | | The viewer base URL. Should be the publicly accessible URL (i.e. `https://bot.domain.com`) |
| NEXTAUTH_URL_INTERNAL | | The internal builder base URL. You have to set it only when `NEXTAUTH_URL` can't be reached by your builder container / server. For a docker deployment, you should set it to `http://localhost:3000`. |
| DEFAULT_WORKSPACE_PLAN | FREE | Default workspace plan on user creation or when a user creates a new workspace. Possible values are `FREE`, `STARTER`, `PRO`, `LIFETIME`. The default plan for admin user is `LIFETIME` |
| DEFAULT_WORKSPACE_PLAN | FREE | Default workspace plan on user creation or when a user creates a new workspace. Possible values are `FREE`, `STARTER`, `PRO`, `LIFETIME`, `UNLIMITED`. The default plan for admin user is `UNLIMITED` |
| DISABLE_SIGNUP | false | To disable new sign ups but still be able to sign in with existing users or admin email |
## Email (Auth, notifications)

View File

@ -32,7 +32,7 @@ const handler = async (
const typebotId = req.query.typebotId as string
const blockId = req.query.blockId as string
if (!filePath) return badRequest(res, 'Missing filePath or fileType')
const hasReachedStorageLimit = await checkStorageLimit(typebotId)
const hasReachedStorageLimit = await checkIfStorageLimitReached(typebotId)
const typebot = (await prisma.publicTypebot.findFirst({
where: { typebotId },
})) as unknown as PublicTypebot
@ -59,7 +59,9 @@ const handler = async (
return methodNotAllowed(res)
}
const checkStorageLimit = async (typebotId: string): Promise<boolean> => {
const checkIfStorageLimitReached = async (
typebotId: string
): Promise<boolean> => {
const typebot = await prisma.typebot.findUnique({
where: { id: typebotId },
include: {
@ -94,6 +96,7 @@ const checkStorageLimit = async (typebotId: string): Promise<boolean> => {
const hasSentFirstEmail = workspace.storageLimitFirstEmailSentAt !== null
const hasSentSecondEmail = workspace.storageLimitSecondEmailSentAt !== null
const storageLimit = getStorageLimit(typebot.workspace)
if (storageLimit === -1) return false
const storageLimitBytes = storageLimit * 1024 * 1024 * 1024
if (
totalStorageUsed >= storageLimitBytes * LIMIT_EMAIL_TRIGGER_PERCENT &&

View File

@ -0,0 +1,2 @@
-- AlterEnum
ALTER TYPE "Plan" ADD VALUE 'UNLIMITED';

View File

@ -314,6 +314,7 @@ enum Plan {
LIFETIME
OFFERED
CUSTOM
UNLIMITED
}
enum CollaborationType {

View File

@ -33,6 +33,7 @@ export const chatsLimit = {
},
[Plan.OFFERED]: { totalIncluded: infinity },
[Plan.LIFETIME]: { totalIncluded: infinity },
[Plan.UNLIMITED]: { totalIncluded: infinity },
} as const
export const storageLimit = {
@ -60,6 +61,7 @@ export const storageLimit = {
},
[Plan.OFFERED]: { totalIncluded: 2 },
[Plan.LIFETIME]: { totalIncluded: 10 },
[Plan.UNLIMITED]: { totalIncluded: infinity },
} as const
export const seatsLimit = {
@ -75,6 +77,7 @@ export const seatsLimit = {
},
[Plan.OFFERED]: { totalIncluded: 2 },
[Plan.LIFETIME]: { totalIncluded: 8 },
[Plan.UNLIMITED]: { totalIncluded: infinity },
} as const
export const getChatsLimit = ({