Skip to content

Commit

Permalink
🐛 (limits) Fix storage limit trigger and e2e tests
Browse files Browse the repository at this point in the history
  • Loading branch information
baptisteArno committed Sep 27, 2022
1 parent 1e26703 commit 30dff2d
Show file tree
Hide file tree
Showing 52 changed files with 1,009 additions and 2,190 deletions.
11 changes: 9 additions & 2 deletions apps/builder/components/analytics/AnalyticsContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import { Flex, Spinner, useDisclosure } from '@chakra-ui/react'
import { StatsCards } from 'components/analytics/StatsCards'
import { Graph } from 'components/shared/Graph'
import { useToast } from 'components/shared/hooks/useToast'
import { ChangePlanModal } from 'components/shared/modals/ChangePlanModal'
import {
ChangePlanModal,
LimitReached,
} from 'components/shared/modals/ChangePlanModal'
import { GraphProvider, GroupsCoordinatesProvider } from 'contexts/GraphContext'
import { useTypebot } from 'contexts/TypebotContext/TypebotContext'
import { Stats } from 'models'
Expand Down Expand Up @@ -49,7 +52,11 @@ export const AnalyticsContent = ({ stats }: { stats?: Stats }) => {
<Spinner color="gray" />
</Flex>
)}
<ChangePlanModal onClose={onClose} isOpen={isOpen} />
<ChangePlanModal
onClose={onClose}
isOpen={isOpen}
type={LimitReached.ANALYTICS}
/>
<StatsCards stats={stats} pos="absolute" top={10} />
</Flex>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { Button, HStack, Tag, useDisclosure, Text } from '@chakra-ui/react'
import { Button, HStack, useDisclosure, Text } from '@chakra-ui/react'
import { FolderPlusIcon } from 'assets/icons'
import {
LimitReached,
ChangePlanModal,
} from 'components/shared/modals/ChangePlanModal'
import { PlanTag } from 'components/shared/PlanTag'
import { useWorkspace } from 'contexts/WorkspaceContext'
import { Plan } from 'db'
import React from 'react'
import { isFreePlan } from 'services/workspace'

Expand All @@ -26,7 +28,7 @@ export const CreateFolderButton = ({ isLoading, onClick }: Props) => {
>
<HStack>
<Text>Create a folder</Text>
{isFreePlan(workspace) && <Tag colorScheme="orange">Pro</Tag>}
{isFreePlan(workspace) && <PlanTag plan={Plan.STARTER} />}
</HStack>
<ChangePlanModal
isOpen={isOpen}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const useUsage = (workspaceId?: string) => {
{ totalChatsUsed: number; totalStorageUsed: number },
Error
>(workspaceId ? `/api/workspaces/${workspaceId}/usage` : null, fetcher, {
dedupingInterval: env('E2E_TEST') === 'enabled' ? 0 : undefined,
dedupingInterval: env('E2E_TEST') === 'true' ? 0 : undefined,
})
return {
data,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const useInvoicesQuery = (stripeId?: string | null) => {
stripeId ? `/api/stripe/invoices?stripeId=${stripeId}` : null,
fetcher,
{
dedupingInterval: env('E2E_TEST') === 'enabled' ? 0 : undefined,
dedupingInterval: env('E2E_TEST') === 'true' ? 0 : undefined,
}
)
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const MembersList = () => {
})

const handleDeleteMemberClick = (memberId: string) => async () => {
if (!workspace || !members || !invitations) return
if (!workspace) return
await deleteMember(workspace.id, memberId)
mutate({
members: members.filter((m) => m.userId !== memberId),
Expand All @@ -34,7 +34,7 @@ export const MembersList = () => {

const handleSelectNewRole =
(memberId: string) => async (role: WorkspaceRole) => {
if (!workspace || !members || !invitations) return
if (!workspace) return
await updateMember(workspace.id, { userId: memberId, role })
mutate({
members: members.map((m) =>
Expand All @@ -45,7 +45,7 @@ export const MembersList = () => {
}

const handleDeleteInvitationClick = (id: string) => async () => {
if (!workspace || !members || !invitations) return
if (!workspace) return
await deleteInvitation({ workspaceId: workspace.id, id })
mutate({
invitations: invitations.filter((i) => i.id !== id),
Expand All @@ -55,33 +55,31 @@ export const MembersList = () => {

const handleSelectNewInvitationRole =
(id: string) => async (type: WorkspaceRole) => {
if (!workspace || !members || !invitations) return
if (!workspace) return
await updateInvitation({ workspaceId: workspace.id, id, type })
mutate({
invitations: invitations.map((i) => (i.id === id ? { ...i, type } : i)),
members,
})
}

const handleNewInvitation = (invitation: WorkspaceInvitation) => {
if (!members || !invitations) return
mutate({
const handleNewInvitation = async (invitation: WorkspaceInvitation) => {
await mutate({
members,
invitations: [...invitations, invitation],
})
}

const handleNewMember = (member: Member) => {
if (!members || !invitations) return
mutate({
const handleNewMember = async (member: Member) => {
await mutate({
members: [...members, member],
invitations,
})
}

const canInviteNewMember = checkCanInviteMember({
plan: workspace?.plan,
currentMembersCount: [...(members ?? []), ...(invitations ?? [])].length,
currentMembersCount: [...members, ...invitations].length,
})

return (
Expand All @@ -103,7 +101,7 @@ export const MembersList = () => {
isLocked={!canInviteNewMember}
/>
)}
{members?.map((member) => (
{members.map((member) => (
<MemberItem
key={member.userId}
email={member.email ?? ''}
Expand All @@ -116,7 +114,7 @@ export const MembersList = () => {
canEdit={canEdit}
/>
))}
{invitations?.map((invitation) => (
{invitations.map((invitation) => (
<MemberItem
key={invitation.email}
email={invitation.email ?? ''}
Expand Down
10 changes: 4 additions & 6 deletions apps/builder/components/editor/BlocksSideBar/BlockTypeLabel.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { HStack, Tag, Text, Tooltip } from '@chakra-ui/react'
import { HStack, Text, Tooltip } from '@chakra-ui/react'
import { PlanTag } from 'components/shared/PlanTag'
import { useWorkspace } from 'contexts/WorkspaceContext'
import { Plan } from 'db'
import {
BubbleBlockType,
InputBlockType,
Expand Down Expand Up @@ -52,11 +54,7 @@ export const BlockTypeLabel = ({ type }: Props): JSX.Element => {
<Tooltip label="Upload Files">
<HStack>
<Text>File</Text>
{isFreePlan(workspace) && (
<Tag colorScheme="orange" size="sm">
Pro
</Tag>
)}
{isFreePlan(workspace) && <PlanTag plan={Plan.STARTER} />}
</HStack>
</Tooltip>
)
Expand Down
28 changes: 15 additions & 13 deletions apps/builder/components/settings/GeneralSettingsForm.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import { Flex, FormLabel, Stack, Switch, useDisclosure } from '@chakra-ui/react'
import {
Flex,
FormLabel,
Stack,
Switch,
Tag,
useDisclosure,
} from '@chakra-ui/react'
import { ChangePlanModal } from 'components/shared/modals/ChangePlanModal'
ChangePlanModal,
LimitReached,
} from 'components/shared/modals/ChangePlanModal'
import { PlanTag } from 'components/shared/PlanTag'
import { SwitchWithLabel } from 'components/shared/SwitchWithLabel'
import { useWorkspace } from 'contexts/WorkspaceContext'
import { Plan } from 'db'
import { GeneralSettings } from 'models'
import React from 'react'
import { isFreePlan } from 'services/workspace'
Expand All @@ -25,9 +23,9 @@ export const GeneralSettingsForm = ({
}: Props) => {
const { isOpen, onOpen, onClose } = useDisclosure()
const { workspace } = useWorkspace()
const isUserFreePlan = isFreePlan(workspace)
const isWorkspaceFreePlan = isFreePlan(workspace)
const handleSwitchChange = () => {
if (generalSettings?.isBrandingEnabled && isUserFreePlan) return
if (generalSettings?.isBrandingEnabled && isWorkspaceFreePlan) return
onGeneralSettingsChange({
...generalSettings,
isBrandingEnabled: !generalSettings?.isBrandingEnabled,
Expand Down Expand Up @@ -56,15 +54,19 @@ export const GeneralSettingsForm = ({

return (
<Stack spacing={6}>
<ChangePlanModal isOpen={isOpen} onClose={onClose} />
<ChangePlanModal
isOpen={isOpen}
onClose={onClose}
type={LimitReached.BRAND}
/>
<Flex
justifyContent="space-between"
align="center"
onClick={isUserFreePlan ? onOpen : undefined}
onClick={isWorkspaceFreePlan ? onOpen : undefined}
>
<FormLabel htmlFor="branding" mb="0">
Typebot.io branding{' '}
{isUserFreePlan && <Tag colorScheme="orange">Pro</Tag>}
{isWorkspaceFreePlan && <PlanTag plan={Plan.STARTER} />}
</FormLabel>
<Switch
id="branding"
Expand Down
5 changes: 2 additions & 3 deletions apps/builder/components/share/EditableUrl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,10 @@ export const EditableUrl = ({
<Tooltip label="Edit">
<EditablePreview
mx={1}
bgColor="blue.500"
color="white"
borderWidth="1px"
px={3}
rounded="md"
cursor="pointer"
cursor="text"
display="flex"
fontWeight="semibold"
/>
Expand Down
29 changes: 15 additions & 14 deletions apps/builder/components/share/ShareContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,20 @@ import {
HStack,
IconButton,
Stack,
Tag,
Wrap,
Text,
} from '@chakra-ui/react'
import { TrashIcon } from 'assets/icons'
import { UpgradeButton } from 'components/shared/buttons/UpgradeButton'
import { useToast } from 'components/shared/hooks/useToast'
import { LimitReached } from 'components/shared/modals/ChangePlanModal'
import { PlanTag } from 'components/shared/PlanTag'
import { useTypebot } from 'contexts/TypebotContext/TypebotContext'
import { useWorkspace } from 'contexts/WorkspaceContext'
import { Plan } from 'db'
import React from 'react'
import { parseDefaultPublicId } from 'services/typebots'
import { isFreePlan } from 'services/workspace'
import { isWorkspaceProPlan } from 'services/workspace'
import { getViewerUrl, isDefined, isNotDefined } from 'utils'
import { CustomDomainsDropdown } from './customDomain/CustomDomainsDropdown'
import { EditableUrl } from './EditableUrl'
Expand Down Expand Up @@ -80,19 +82,18 @@ export const ShareContent = () => {
/>
</HStack>
)}
{isFreePlan(workspace) ? (
<UpgradeButton colorScheme="gray">
<Text mr="2">Add my domain</Text>{' '}
<Tag colorScheme="orange">Pro</Tag>
</UpgradeButton>
{isWorkspaceProPlan(workspace) &&
isNotDefined(typebot?.customDomain) ? (
<CustomDomainsDropdown
onCustomDomainSelect={handleCustomDomainChange}
/>
) : (
<>
{isNotDefined(typebot?.customDomain) && (
<CustomDomainsDropdown
onCustomDomainSelect={handleCustomDomainChange}
/>
)}
</>
<UpgradeButton
colorScheme="gray"
limitReachedType={LimitReached.CUSTOM_DOMAIN}
>
<Text mr="2">Add my domain</Text> <PlanTag plan={Plan.PRO} />
</UpgradeButton>
)}
</Stack>

Expand Down
31 changes: 23 additions & 8 deletions apps/builder/components/shared/Graph/Edges/DropOffEdge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
computeSourceCoordinates,
computeDropOffPath,
} from 'services/graph'
import { isFreePlan } from 'services/workspace'
import { isWorkspaceProPlan } from 'services/workspace'
import { byId, isDefined } from 'utils'

type Props = {
Expand All @@ -28,7 +28,7 @@ export const DropOffEdge = ({
const { sourceEndpoints, graphPosition } = useGraph()
const { publishedTypebot } = useTypebot()

const isUserOnFreePlan = isFreePlan(workspace)
const isProPlan = isWorkspaceProPlan(workspace)

const totalAnswers = useMemo(
() => answersCounts.find((a) => a.groupId === groupId)?.totalAnswers,
Expand Down Expand Up @@ -95,7 +95,7 @@ export const DropOffEdge = ({
>
<Tooltip
label="Unlock Drop-off rate by upgrading to Pro plan"
isDisabled={!isUserOnFreePlan}
isDisabled={isProPlan}
>
<VStack
bgColor={'red.500'}
Expand All @@ -105,13 +105,28 @@ export const DropOffEdge = ({
justifyContent="center"
w="full"
h="full"
filter={isUserOnFreePlan ? 'blur(4px)' : ''}
onClick={isUserOnFreePlan ? onUnlockProPlanClick : undefined}
cursor={isUserOnFreePlan ? 'pointer' : 'auto'}
onClick={isProPlan ? undefined : onUnlockProPlanClick}
cursor={isProPlan ? 'auto' : 'pointer'}
>
<Text>{isUserOnFreePlan ? 'X' : dropOffRate}%</Text>
<Text filter={isProPlan ? '' : 'blur(2px)'}>
{isProPlan ? (
dropOffRate
) : (
<Text as="span" filter="blur(2px)">
X
</Text>
)}
%
</Text>
<Tag colorScheme="red">
{isUserOnFreePlan ? 'n' : totalDroppedUser} users
{isProPlan ? (
totalDroppedUser
) : (
<Text as="span" filter="blur(3px)" mr="1">
NN
</Text>
)}{' '}
users
</Tag>
</VStack>
</Tooltip>
Expand Down
1 change: 0 additions & 1 deletion apps/builder/components/shared/Graph/Edges/Edges.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ export const Edges = ({
pos="absolute"
left="0"
top="0"
pointerEvents="none"
shapeRendering="geometricPrecision"
>
<DrawingEdge />
Expand Down
10 changes: 5 additions & 5 deletions apps/builder/components/shared/PlanTag.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
import { Tag } from '@chakra-ui/react'
import { Tag, TagProps } from '@chakra-ui/react'
import { Plan } from 'db'

export const PlanTag = ({ plan }: { plan?: Plan }) => {
export const PlanTag = ({ plan, ...props }: { plan?: Plan } & TagProps) => {
switch (plan) {
case Plan.LIFETIME:
case Plan.PRO: {
return (
<Tag colorScheme="blue" data-testid="plan-tag">
<Tag colorScheme="blue" data-testid="pro-plan-tag" {...props}>
Pro
</Tag>
)
}
case Plan.OFFERED:
case Plan.STARTER: {
return (
<Tag colorScheme="orange" data-testid="plan-tag">
<Tag colorScheme="orange" data-testid="starter-plan-tag" {...props}>
Starter
</Tag>
)
}
default: {
return (
<Tag colorScheme="gray" data-testid="plan-tag">
<Tag colorScheme="gray" data-testid="free-plan-tag" {...props}>
Free
</Tag>
)
Expand Down
Loading

0 comments on commit 30dff2d

Please sign in to comment.