2
0

♻️ Remove storage limit related code

This commit is contained in:
Baptiste Arnaud
2023-09-20 16:06:53 +02:00
parent 7d57e8dd06
commit d7dc5fb5fb
25 changed files with 44 additions and 493 deletions

View File

@@ -27,7 +27,6 @@ export const createCheckoutSession = authenticatedProcedure
plan: z.enum([Plan.STARTER, Plan.PRO]),
returnUrl: z.string(),
additionalChats: z.number(),
additionalStorage: z.number(),
vat: z
.object({
type: z.string(),
@@ -53,7 +52,6 @@ export const createCheckoutSession = authenticatedProcedure
plan,
returnUrl,
additionalChats,
additionalStorage,
isYearly,
},
ctx: { user },
@@ -119,7 +117,6 @@ export const createCheckoutSession = authenticatedProcedure
plan,
returnUrl,
additionalChats,
additionalStorage,
isYearly,
})
@@ -142,7 +139,6 @@ type Props = {
plan: 'STARTER' | 'PRO'
returnUrl: string
additionalChats: number
additionalStorage: number
isYearly: boolean
userId: string
}
@@ -156,7 +152,6 @@ export const createCheckoutSessionUrl =
plan,
returnUrl,
additionalChats,
additionalStorage,
isYearly,
}: Props) => {
const session = await stripe.checkout.sessions.create({
@@ -173,17 +168,11 @@ export const createCheckoutSessionUrl =
workspaceId,
plan,
additionalChats,
additionalStorage,
},
currency,
billing_address_collection: 'required',
automatic_tax: { enabled: true },
line_items: parseSubscriptionItems(
plan,
additionalChats,
additionalStorage,
isYearly
),
line_items: parseSubscriptionItems(plan, additionalChats, isYearly),
})
return session.url

View File

@@ -19,9 +19,7 @@ export const getUsage = authenticatedProcedure
workspaceId: z.string(),
})
)
.output(
z.object({ totalChatsUsed: z.number(), totalStorageUsed: z.number() })
)
.output(z.object({ totalChatsUsed: z.number() }))
.query(async ({ input: { workspaceId }, ctx: { user } }) => {
const workspace = await prisma.workspace.findFirst({
where: {
@@ -55,20 +53,8 @@ export const getUsage = authenticatedProcedure
},
},
})
const {
_sum: { storageUsed: totalStorageUsed },
} = await prisma.answer.aggregate({
where: {
storageUsed: { gt: 0 },
result: {
typebotId: { in: workspace.typebots.map((typebot) => typebot.id) },
},
},
_sum: { storageUsed: true },
})
return {
totalChatsUsed,
totalStorageUsed: totalStorageUsed ?? 0,
}
})

View File

@@ -7,8 +7,8 @@ import { workspaceSchema } from '@typebot.io/schemas'
import Stripe from 'stripe'
import { isDefined } from '@typebot.io/lib'
import { z } from 'zod'
import { getChatsLimit, getStorageLimit } from '@typebot.io/lib/pricing'
import { chatPriceIds, storagePriceIds } from './getSubscription'
import { getChatsLimit } from '@typebot.io/lib/pricing'
import { chatPriceIds } from './getSubscription'
import { createCheckoutSessionUrl } from './createCheckoutSession'
import { isAdminWriteWorkspaceForbidden } from '@/features/workspace/helpers/isAdminWriteWorkspaceForbidden'
import { getUsage } from '@typebot.io/lib/api/getUsage'
@@ -31,7 +31,6 @@ export const updateSubscription = authenticatedProcedure
workspaceId: z.string(),
plan: z.enum([Plan.STARTER, Plan.PRO]),
additionalChats: z.number(),
additionalStorage: z.number(),
currency: z.enum(['usd', 'eur']),
isYearly: z.boolean(),
})
@@ -48,7 +47,6 @@ export const updateSubscription = authenticatedProcedure
workspaceId,
plan,
additionalChats,
additionalStorage,
currency,
isYearly,
returnUrl,
@@ -100,9 +98,6 @@ export const updateSubscription = authenticatedProcedure
const currentAdditionalChatsItemId = subscription?.items.data.find(
(item) => chatPriceIds.includes(item.price.id)
)?.id
const currentAdditionalStorageItemId = subscription?.items.data.find(
(item) => storagePriceIds.includes(item.price.id)
)?.id
const frequency = isYearly ? 'yearly' : 'monthly'
const items = [
@@ -123,18 +118,6 @@ export const updateSubscription = authenticatedProcedure
}),
deleted: subscription ? additionalChats === 0 : undefined,
},
additionalStorage === 0 && !currentAdditionalStorageItemId
? undefined
: {
id: currentAdditionalStorageItemId,
price: priceIds[plan].storage[frequency],
quantity: getStorageLimit({
plan,
additionalStorageIndex: additionalStorage,
customStorageLimit: null,
}),
deleted: subscription ? additionalStorage === 0 : undefined,
},
].filter(isDefined)
if (subscription) {
@@ -151,7 +134,6 @@ export const updateSubscription = authenticatedProcedure
plan,
returnUrl,
additionalChats,
additionalStorage,
isYearly,
})
@@ -175,7 +157,6 @@ export const updateSubscription = authenticatedProcedure
data: {
plan,
additionalChatsIndex: additionalChats,
additionalStorageIndex: additionalStorage,
isQuarantined,
},
})
@@ -188,7 +169,6 @@ export const updateSubscription = authenticatedProcedure
data: {
plan,
additionalChatsIndex: additionalChats,
additionalStorageIndex: additionalStorage,
},
},
])

View File

@@ -85,7 +85,6 @@ test('should display valid usage', async ({ page }) => {
await injectFakeResults({
count: 10,
typebotId: usageTypebotId,
fakeStorage: 1100 * 1024 * 1024,
})
await page.click('text=Free workspace')
await page.click('text="Usage Workspace"')
@@ -101,7 +100,6 @@ test('should display valid usage', async ({ page }) => {
await injectFakeResults({
typebotId: usageTypebotId,
count: 1090,
fakeStorage: 1200 * 1024 * 1024,
})
await page.click('text="Settings"')
await page.click('text="Billing & Usage"')
@@ -140,7 +138,7 @@ test('plan changes should work', async ({ page }) => {
quantity: 1,
},
],
{ plan: Plan.STARTER, additionalChatsIndex: 0, additionalStorageIndex: 0 }
{ plan: Plan.STARTER, additionalChatsIndex: 0 }
)
// Update plan with additional quotas

View File

@@ -84,7 +84,6 @@ export const ChangePlanForm = ({ workspace }: Props) => {
plan,
workspaceId: workspace.id,
additionalChats: selectedChatsLimitIndex,
additionalStorage: selectedStorageLimitIndex,
currency:
data?.subscription?.currency ??
(guessIfUserIsEuropean() ? 'eur' : 'usd'),

View File

@@ -26,7 +26,6 @@ export type PreCheckoutModalProps = {
plan: 'STARTER' | 'PRO'
workspaceId: string
additionalChats: number
additionalStorage: number
currency: 'eur' | 'usd'
isYearly: boolean
}

View File

@@ -23,8 +23,6 @@ import {
computePrice,
formatPrice,
getChatsLimit,
getStorageLimit,
storageLimit,
} from '@typebot.io/lib/pricing'
import { FeaturesList } from './FeaturesList'
import { MoreInfoTooltip } from '@/components/MoreInfoTooltip'
@@ -35,7 +33,6 @@ type Props = {
workspace: Pick<
Workspace,
| 'additionalChatsIndex'
| 'additionalStorageIndex'
| 'plan'
| 'customChatsLimit'
| 'customStorageLimit'
@@ -80,25 +77,18 @@ export const ProPlanPricingCard = ({
return
}
setSelectedChatsLimitIndex(workspace.additionalChatsIndex ?? 0)
setSelectedStorageLimitIndex(workspace.additionalStorageIndex ?? 0)
}, [
selectedChatsLimitIndex,
selectedStorageLimitIndex,
workspace.additionalChatsIndex,
workspace.additionalStorageIndex,
workspace?.plan,
])
const workspaceChatsLimit = workspace ? getChatsLimit(workspace) : undefined
const workspaceStorageLimit = workspace
? getStorageLimit(workspace)
: undefined
const isCurrentPlan =
chatsLimit[Plan.PRO].graduatedPrice[selectedChatsLimitIndex ?? 0]
.totalIncluded === workspaceChatsLimit &&
storageLimit[Plan.PRO].graduatedPrice[selectedStorageLimitIndex ?? 0]
.totalIncluded === workspaceStorageLimit &&
isYearly === currentSubscription?.isYearly
const getButtonLabel = () => {
@@ -110,10 +100,7 @@ export const ProPlanPricingCard = ({
if (workspace?.plan === Plan.PRO) {
if (isCurrentPlan) return scopedT('upgradeButton.current')
if (
selectedChatsLimitIndex !== workspace.additionalChatsIndex ||
selectedStorageLimitIndex !== workspace.additionalStorageIndex
)
if (selectedChatsLimitIndex !== workspace.additionalChatsIndex)
return t('update')
}
return t('upgrade')
@@ -135,7 +122,6 @@ export const ProPlanPricingCard = ({
computePrice(
Plan.PRO,
selectedChatsLimitIndex ?? 0,
selectedStorageLimitIndex ?? 0,
isYearly ? 'yearly' : 'monthly'
) ?? NaN
@@ -238,40 +224,6 @@ export const ProPlanPricingCard = ({
</Text>
<MoreInfoTooltip>{scopedT('chatsTooltip')}</MoreInfoTooltip>
</HStack>,
<HStack key="test">
<Text>
<Menu>
<MenuButton
as={Button}
rightIcon={<ChevronLeftIcon transform="rotate(-90deg)" />}
size="sm"
isLoading={selectedStorageLimitIndex === undefined}
>
{selectedStorageLimitIndex !== undefined
? parseNumberWithCommas(
storageLimit.PRO.graduatedPrice[
selectedStorageLimitIndex
].totalIncluded
)
: undefined}
</MenuButton>
<MenuList>
{storageLimit.PRO.graduatedPrice.map((price, index) => (
<MenuItem
key={index}
onClick={() => setSelectedStorageLimitIndex(index)}
>
{parseNumberWithCommas(price.totalIncluded)}
</MenuItem>
))}
</MenuList>
</Menu>{' '}
{scopedT('storageLimit')}
</Text>
<MoreInfoTooltip>
{scopedT('storageLimitTooltip')}
</MoreInfoTooltip>
</HStack>,
scopedT('pro.customDomains'),
scopedT('pro.analytics'),
]}

View File

@@ -19,8 +19,6 @@ import {
computePrice,
formatPrice,
getChatsLimit,
getStorageLimit,
storageLimit,
} from '@typebot.io/lib/pricing'
import { FeaturesList } from './FeaturesList'
import { MoreInfoTooltip } from '@/components/MoreInfoTooltip'
@@ -31,7 +29,6 @@ type Props = {
workspace: Pick<
Workspace,
| 'additionalChatsIndex'
| 'additionalStorageIndex'
| 'plan'
| 'customChatsLimit'
| 'customStorageLimit'
@@ -76,25 +73,18 @@ export const StarterPlanPricingCard = ({
return
}
setSelectedChatsLimitIndex(workspace.additionalChatsIndex ?? 0)
setSelectedStorageLimitIndex(workspace.additionalStorageIndex ?? 0)
}, [
selectedChatsLimitIndex,
selectedStorageLimitIndex,
workspace.additionalChatsIndex,
workspace.additionalStorageIndex,
workspace?.plan,
])
const workspaceChatsLimit = workspace ? getChatsLimit(workspace) : undefined
const workspaceStorageLimit = workspace
? getStorageLimit(workspace)
: undefined
const isCurrentPlan =
chatsLimit[Plan.STARTER].graduatedPrice[selectedChatsLimitIndex ?? 0]
.totalIncluded === workspaceChatsLimit &&
storageLimit[Plan.STARTER].graduatedPrice[selectedStorageLimitIndex ?? 0]
.totalIncluded === workspaceStorageLimit &&
isYearly === currentSubscription?.isYearly
const getButtonLabel = () => {
@@ -109,7 +99,6 @@ export const StarterPlanPricingCard = ({
if (
selectedChatsLimitIndex !== workspace.additionalChatsIndex ||
selectedStorageLimitIndex !== workspace.additionalStorageIndex ||
isYearly !== currentSubscription?.isYearly
)
return t('update')
@@ -133,7 +122,6 @@ export const StarterPlanPricingCard = ({
computePrice(
Plan.STARTER,
selectedChatsLimitIndex ?? 0,
selectedStorageLimitIndex ?? 0,
isYearly ? 'yearly' : 'monthly'
) ?? NaN
@@ -185,40 +173,6 @@ export const StarterPlanPricingCard = ({
</Text>
<MoreInfoTooltip>{scopedT('chatsTooltip')}</MoreInfoTooltip>
</HStack>,
<HStack key="test">
<Text>
<Menu>
<MenuButton
as={Button}
rightIcon={<ChevronLeftIcon transform="rotate(-90deg)" />}
size="sm"
isLoading={selectedStorageLimitIndex === undefined}
>
{selectedStorageLimitIndex !== undefined
? parseNumberWithCommas(
storageLimit.STARTER.graduatedPrice[
selectedStorageLimitIndex
].totalIncluded
)
: undefined}
</MenuButton>
<MenuList>
{storageLimit.STARTER.graduatedPrice.map((price, index) => (
<MenuItem
key={index}
onClick={() => setSelectedStorageLimitIndex(index)}
>
{parseNumberWithCommas(price.totalIncluded)}
</MenuItem>
))}
</MenuList>
</Menu>{' '}
{scopedT('storageLimit')}
</Text>
<MoreInfoTooltip>
{scopedT('storageLimitTooltip')}
</MoreInfoTooltip>
</HStack>,
scopedT('starter.brandingRemoved'),
scopedT('starter.fileUploadBlock'),
scopedT('starter.createFolders'),

View File

@@ -1,10 +1,9 @@
import { getChatsLimit, getStorageLimit } from '@typebot.io/lib/pricing'
import { getChatsLimit } from '@typebot.io/lib/pricing'
import { priceIds } from '@typebot.io/lib/api/pricing'
export const parseSubscriptionItems = (
plan: 'STARTER' | 'PRO',
additionalChats: number,
additionalStorage: number,
isYearly: boolean
) => {
const frequency = isYearly ? 'yearly' : 'monthly'
@@ -13,33 +12,18 @@ export const parseSubscriptionItems = (
price: priceIds[plan].base[frequency],
quantity: 1,
},
]
.concat(
additionalChats > 0
? [
{
price: priceIds[plan].chats[frequency],
quantity: getChatsLimit({
plan,
additionalChatsIndex: additionalChats,
customChatsLimit: null,
}),
},
]
: []
)
.concat(
additionalStorage > 0
? [
{
price: priceIds[plan].storage[frequency],
quantity: getStorageLimit({
plan,
additionalStorageIndex: additionalStorage,
customStorageLimit: null,
}),
},
]
: []
)
].concat(
additionalChats > 0
? [
{
price: priceIds[plan].chats[frequency],
quantity: getChatsLimit({
plan,
additionalChatsIndex: additionalChats,
customChatsLimit: null,
}),
},
]
: []
)
}

View File

@@ -33,11 +33,10 @@ export const DashboardPage = () => {
})
useEffect(() => {
const { subscribePlan, chats, storage, isYearly, claimCustomPlan } =
const { subscribePlan, chats, isYearly, claimCustomPlan } =
router.query as {
subscribePlan: Plan | undefined
chats: string | undefined
storage: string | undefined
isYearly: string | undefined
claimCustomPlan: string | undefined
}
@@ -55,7 +54,6 @@ export const DashboardPage = () => {
plan: subscribePlan as 'PRO' | 'STARTER',
workspaceId: workspace.id,
additionalChats: chats ? parseInt(chats) : 0,
additionalStorage: storage ? parseInt(storage) : 0,
currency: guessIfUserIsEuropean() ? 'eur' : 'usd',
isYearly: isYearly === 'false' ? false : true,
})

View File

@@ -47,15 +47,13 @@ const webhookHandler = async (req: NextApiRequest, res: NextApiResponse) => {
| {
plan: 'STARTER' | 'PRO'
additionalChats: string
additionalStorage: string
workspaceId: string
userId: string
}
| { claimableCustomPlanId: string; userId: string }
if ('plan' in metadata) {
const { workspaceId, plan, additionalChats, additionalStorage } =
metadata
if (!workspaceId || !plan || !additionalChats || !additionalStorage)
const { workspaceId, plan, additionalChats } = metadata
if (!workspaceId || !plan || !additionalChats)
return res
.status(500)
.send({ message: `Couldn't retrieve valid metadata` })
@@ -65,7 +63,6 @@ const webhookHandler = async (req: NextApiRequest, res: NextApiResponse) => {
plan,
stripeId: session.customer as string,
additionalChatsIndex: parseInt(additionalChats),
additionalStorageIndex: parseInt(additionalStorage),
isQuarantined: false,
},
include: {
@@ -88,7 +85,6 @@ const webhookHandler = async (req: NextApiRequest, res: NextApiResponse) => {
data: {
plan,
additionalChatsIndex: parseInt(additionalChats),
additionalStorageIndex: parseInt(additionalStorage),
},
},
])
@@ -124,7 +120,6 @@ const webhookHandler = async (req: NextApiRequest, res: NextApiResponse) => {
data: {
plan: Plan.CUSTOM,
additionalChatsIndex: 0,
additionalStorageIndex: 0,
},
},
])
@@ -154,7 +149,6 @@ const webhookHandler = async (req: NextApiRequest, res: NextApiResponse) => {
data: {
plan: Plan.FREE,
additionalChatsIndex: 0,
additionalStorageIndex: 0,
customChatsLimit: null,
customStorageLimit: null,
customSeatsLimit: null,
@@ -179,7 +173,6 @@ const webhookHandler = async (req: NextApiRequest, res: NextApiResponse) => {
data: {
plan: Plan.FREE,
additionalChatsIndex: 0,
additionalStorageIndex: 0,
},
},
])

View File

@@ -18,10 +18,7 @@ const stripe = new Stripe(env.STRIPE_SECRET_KEY ?? '', {
export const addSubscriptionToWorkspace = async (
workspaceId: string,
items: Stripe.SubscriptionCreateParams.Item[],
metadata: Pick<
Workspace,
'additionalChatsIndex' | 'additionalStorageIndex' | 'plan'
>
metadata: Pick<Workspace, 'additionalChatsIndex' | 'plan'>
) => {
const { id: stripeId } = await stripe.customers.create({
email: 'test-user@gmail.com',

View File

@@ -232,15 +232,11 @@
},
"additionalChatsIndex": {
"type": "number"
},
"additionalStorageIndex": {
"type": "number"
}
},
"required": [
"plan",
"additionalChatsIndex",
"additionalStorageIndex"
"additionalChatsIndex"
],
"additionalProperties": false
}
@@ -320,21 +316,13 @@
"chatsLimit": {
"type": "number"
},
"storageLimit": {
"type": "number"
},
"totalChatsUsed": {
"type": "number"
},
"totalStorageUsed": {
"type": "number"
}
},
"required": [
"chatsLimit",
"storageLimit",
"totalChatsUsed",
"totalStorageUsed"
"totalChatsUsed"
],
"additionalProperties": false
}
@@ -30391,9 +30379,6 @@
"additionalChats": {
"type": "number"
},
"additionalStorage": {
"type": "number"
},
"vat": {
"type": "object",
"properties": {
@@ -30422,7 +30407,6 @@
"plan",
"returnUrl",
"additionalChats",
"additionalStorage",
"isYearly"
],
"additionalProperties": false
@@ -30492,9 +30476,6 @@
"additionalChats": {
"type": "number"
},
"additionalStorage": {
"type": "number"
},
"currency": {
"type": "string",
"enum": [
@@ -30511,7 +30492,6 @@
"workspaceId",
"plan",
"additionalChats",
"additionalStorage",
"currency",
"isYearly"
],
@@ -30767,14 +30747,10 @@
"properties": {
"totalChatsUsed": {
"type": "number"
},
"totalStorageUsed": {
"type": "number"
}
},
"required": [
"totalChatsUsed",
"totalStorageUsed"
"totalChatsUsed"
],
"additionalProperties": false
}

View File

@@ -24,7 +24,6 @@ import {
formatPrice,
prices,
seatsLimit,
storageLimit,
} from '@typebot.io/lib/pricing'
import { parseNumberWithCommas } from '@typebot.io/lib'
@@ -85,22 +84,6 @@ export const PlanComparisonTables = () => (
<Td>2 GB</Td>
<Td>10 GB</Td>
</Tr>
<Tr>
<Td>Additional Storage</Td>
<Td />
<Td>
{formatPrice(storageLimit.STARTER.graduatedPrice[1].price)} per{' '}
{storageLimit.STARTER.graduatedPrice[1].totalIncluded -
storageLimit.STARTER.graduatedPrice[0].totalIncluded}{' '}
GB
</Td>
<Td>
{formatPrice(storageLimit.PRO.graduatedPrice[1].price)} per{' '}
{storageLimit.PRO.graduatedPrice[1].totalIncluded -
storageLimit.PRO.graduatedPrice[0].totalIncluded}{' '}
GB
</Td>
</Tr>
<Tr>
<Td>Members</Td>
<Td>Just you</Td>

View File

@@ -15,12 +15,7 @@ import { Plan } from '@typebot.io/prisma'
import Link from 'next/link'
import React, { useState } from 'react'
import { parseNumberWithCommas } from '@typebot.io/lib'
import {
chatsLimit,
computePrice,
seatsLimit,
storageLimit,
} from '@typebot.io/lib/pricing'
import { chatsLimit, computePrice, seatsLimit } from '@typebot.io/lib/pricing'
import { PricingCard } from './PricingCard'
type Props = {
@@ -30,14 +25,11 @@ type Props = {
export const ProPlanCard = ({ isYearly }: Props) => {
const [selectedChatsLimitIndex, setSelectedChatsLimitIndex] =
useState<number>(0)
const [selectedStorageLimitIndex, setSelectedStorageLimitIndex] =
useState<number>(0)
const price =
computePrice(
Plan.PRO,
selectedChatsLimitIndex ?? 0,
selectedStorageLimitIndex ?? 0,
isYearly ? 'yearly' : 'monthly'
) ?? NaN
@@ -93,46 +85,6 @@ export const ProPlanCard = ({ isYearly }: Props) => {
</chakra.span>
</Tooltip>
</HStack>,
<HStack key="storage" spacing={1.5}>
<Menu>
<MenuButton
as={Button}
rightIcon={<ChevronDownIcon />}
size="sm"
variant="outline"
isLoading={selectedStorageLimitIndex === undefined}
>
{selectedStorageLimitIndex !== undefined
? parseNumberWithCommas(
storageLimit.PRO.graduatedPrice[selectedStorageLimitIndex]
.totalIncluded
)
: undefined}
</MenuButton>
<MenuList>
{storageLimit.PRO.graduatedPrice.map((price, index) => (
<MenuItem
key={index}
onClick={() => setSelectedStorageLimitIndex(index)}
>
{parseNumberWithCommas(price.totalIncluded)}
</MenuItem>
))}
</MenuList>
</Menu>{' '}
<Text>GB of storage</Text>
<Tooltip
hasArrow
placement="top"
label="You accumulate storage for every file that your user upload
into your bot. If you delete the result, it will free up the
space."
>
<chakra.span cursor="pointer" h="7">
<HelpCircleIcon />
</chakra.span>
</Tooltip>
</HStack>,
'Custom domains',
'In-depth analytics',
],
@@ -142,7 +94,7 @@ export const ProPlanCard = ({ isYearly }: Props) => {
button={
<Button
as={Link}
href={`https://app.typebot.io/register?subscribePlan=${Plan.PRO}&chats=${selectedChatsLimitIndex}&storage=${selectedStorageLimitIndex}&isYearly=${isYearly}`}
href={`https://app.typebot.io/register?subscribePlan=${Plan.PRO}&chats=${selectedChatsLimitIndex}&isYearly=${isYearly}`}
colorScheme="blue"
size="lg"
w="full"

View File

@@ -15,12 +15,7 @@ import { Plan } from '@typebot.io/prisma'
import Link from 'next/link'
import React, { useState } from 'react'
import { parseNumberWithCommas } from '@typebot.io/lib'
import {
chatsLimit,
computePrice,
seatsLimit,
storageLimit,
} from '@typebot.io/lib/pricing'
import { chatsLimit, computePrice, seatsLimit } from '@typebot.io/lib/pricing'
import { PricingCard } from './PricingCard'
type Props = {
@@ -29,14 +24,11 @@ type Props = {
export const StarterPlanCard = ({ isYearly }: Props) => {
const [selectedChatsLimitIndex, setSelectedChatsLimitIndex] =
useState<number>(0)
const [selectedStorageLimitIndex, setSelectedStorageLimitIndex] =
useState<number>(0)
const price =
computePrice(
Plan.STARTER,
selectedChatsLimitIndex ?? 0,
selectedStorageLimitIndex ?? 0,
isYearly ? 'yearly' : 'monthly'
) ?? NaN
@@ -90,48 +82,6 @@ export const StarterPlanCard = ({ isYearly }: Props) => {
</chakra.span>
</Tooltip>
</HStack>,
<HStack key="storage" spacing={1.5}>
<Menu>
<MenuButton
as={Button}
rightIcon={<ChevronDownIcon />}
size="sm"
variant="outline"
isLoading={selectedStorageLimitIndex === undefined}
colorScheme="orange"
>
{selectedStorageLimitIndex !== undefined
? parseNumberWithCommas(
storageLimit.STARTER.graduatedPrice[
selectedStorageLimitIndex
].totalIncluded
)
: undefined}
</MenuButton>
<MenuList>
{storageLimit.STARTER.graduatedPrice.map((price, index) => (
<MenuItem
key={index}
onClick={() => setSelectedStorageLimitIndex(index)}
>
{parseNumberWithCommas(price.totalIncluded)}
</MenuItem>
))}
</MenuList>
</Menu>{' '}
<Text>GB of storage</Text>
<Tooltip
hasArrow
placement="top"
label="You accumulate storage for every file that your user upload
into your bot. If you delete the result, it will free up the
space."
>
<chakra.span cursor="pointer" h="7">
<HelpCircleIcon />
</chakra.span>
</Tooltip>
</HStack>,
'Branding removed',
'Collect files from users',
'Create folders',
@@ -142,7 +92,7 @@ export const StarterPlanCard = ({ isYearly }: Props) => {
button={
<Button
as={Link}
href={`https://app.typebot.io/register?subscribePlan=${Plan.STARTER}&chats=${selectedChatsLimitIndex}&storage=${selectedStorageLimitIndex}&isYearly=${isYearly}`}
href={`https://app.typebot.io/register?subscribePlan=${Plan.STARTER}&chats=${selectedChatsLimitIndex}&isYearly=${isYearly}`}
colorScheme="orange"
size="lg"
w="full"

View File

@@ -3,17 +3,10 @@ import { createId } from '@paralleldrive/cuid2'
import { parse } from 'papaparse'
import { readFileSync } from 'fs'
import { isDefined } from '@typebot.io/lib'
import {
createWorkspaces,
importTypebotInDatabase,
injectFakeResults,
} from '@typebot.io/lib/playwright/databaseActions'
import { importTypebotInDatabase } from '@typebot.io/lib/playwright/databaseActions'
import { getTestAsset } from '@/test/utils/playwright'
import { Plan } from '@typebot.io/prisma'
import { env } from '@typebot.io/env'
const THREE_GIGABYTES = 3 * 1024 * 1024 * 1024
test('should work as expected', async ({ page, browser }) => {
const typebotId = createId()
await importTypebotInDatabase(getTestAsset('typebots/fileUpload.json'), {
@@ -75,22 +68,3 @@ test('should work as expected', async ({ page, browser }) => {
await page2.goto(urls[0])
await expect(page2.locator('pre')).toBeHidden()
})
test.describe('Storage limit is reached', () => {
const typebotId = createId()
const workspaceId = createId()
test.beforeAll(async () => {
await createWorkspaces([{ id: workspaceId, plan: Plan.STARTER }])
await importTypebotInDatabase(getTestAsset('typebots/fileUpload.json'), {
id: typebotId,
publicId: `${typebotId}-public`,
workspaceId,
})
await injectFakeResults({
typebotId,
count: 20,
fakeStorage: THREE_GIGABYTES,
})
})
})

View File

@@ -1,10 +1,10 @@
import test, { expect } from '@playwright/test'
import { createId } from '@paralleldrive/cuid2'
import { importTypebotInDatabase } from '@typebot.io/lib/playwright/databaseActions'
import { getTestAsset } from '@/test/utils/playwright'
import { SmtpCredentials } from '@typebot.io/schemas'
import { env } from '@typebot.io/env'
import { createSmtpCredentials } from './utils/databaseActions'
import { getTestAsset } from './utils/playwright'
export const mockSmtpCredentials: SmtpCredentials['data'] = {
from: {