Skip to content

Commit

Permalink
✨ Add WhatsApp integration beta test (#722)
Browse files Browse the repository at this point in the history
Related to #401
  • Loading branch information
baptisteArno committed Aug 29, 2023
1 parent 036b407 commit b852b4a
Show file tree
Hide file tree
Showing 136 changed files with 6,662 additions and 5,351 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ Interested in self-hosting Typebot on your server? Take a look at the [self-host

You are awesome, lets build great software together. Head over to the [Contribute guidelines](https://github.com/baptisteArno/typebot.io/blob/main/CONTRIBUTING.md) to get started. 💪

## Run the project locally

Follow the [Get started](https://github.com/baptisteArno/typebot.io/blob/main/CONTRIBUTING.md#get-started) section of the Contributing guide.

### Top contributors

<a href="https://github.com/baptistearno/typebot.io/graphs/contributors">
Expand Down
12 changes: 12 additions & 0 deletions apps/builder/next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@ const nextConfig = {
},
]
},
async rewrites() {
return process.env.NEXT_PUBLIC_POSTHOG_KEY
? [
{
source: '/ingest/:path*',
destination:
(process.env.NEXT_PUBLIC_POSTHOG_HOST ??
'https://app.posthog.com') + '/:path*',
},
]
: []
},
}

const sentryWebpackPluginOptions = {
Expand Down
4 changes: 3 additions & 1 deletion apps/builder/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"got": "12.6.0",
"immer": "10.0.2",
"jsonwebtoken": "9.0.1",
"libphonenumber-js": "1.10.37",
"micro": "10.0.1",
"micro-cors": "0.1.1",
"minio": "7.1.1",
Expand All @@ -76,6 +77,7 @@
"nodemailer": "6.9.3",
"nprogress": "0.2.0",
"papaparse": "5.4.1",
"posthog-js": "^1.77.1",
"posthog-node": "3.1.1",
"prettier": "2.8.8",
"qs": "6.11.2",
Expand Down Expand Up @@ -114,9 +116,9 @@
"@types/react": "18.2.15",
"@types/tinycolor2": "1.4.3",
"dotenv-cli": "^7.2.1",
"next-runtime-env": "^1.6.2",
"eslint": "8.44.0",
"eslint-config-custom": "workspace:*",
"next-runtime-env": "^1.6.2",
"superjson": "^1.12.4",
"typescript": "5.1.6",
"zod": "3.21.4"
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions apps/builder/src/components/DropdownList.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {
Button,
ButtonProps,
chakra,
Menu,
MenuButton,
MenuButtonProps,
MenuItem,
MenuList,
Portal,
Expand All @@ -27,7 +27,7 @@ export const DropdownList = <T extends readonly any[]>({
items,
placeholder = '',
...props
}: Props<T> & MenuButtonProps) => {
}: Props<T> & ButtonProps) => {
const handleMenuItemClick = (operator: T[number]) => () => {
onItemSelect(operator)
}
Expand Down
2 changes: 1 addition & 1 deletion apps/builder/src/components/TextLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const TextLink = ({
>
<chakra.span textDecor="underline" display="inline-block" {...textProps}>
{isExternal ? (
<HStack spacing={1}>
<HStack as="span" spacing={1}>
<chakra.span noOfLines={noOfLines} maxW="100%">
{children}
</chakra.span>
Expand Down
37 changes: 29 additions & 8 deletions apps/builder/src/components/Toast.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Flex,
HStack,
IconButton,
Expand Down Expand Up @@ -35,6 +40,7 @@ export const Toast = ({
onClose,
}: ToastProps) => {
const bgColor = useColorModeValue('white', 'gray.800')
const detailsLabelColor = useColorModeValue('gray.600', 'gray.400')

return (
<Flex
Expand All @@ -56,14 +62,29 @@ export const Toast = ({
</Stack>

{details && (
<CodeEditor
isReadOnly
value={details.content}
lang={details.lang}
minWidth="300px"
maxHeight="200px"
maxWidth="calc(450px - 100px)"
/>
<Accordion allowToggle>
<AccordionItem>
<AccordionButton
justifyContent="space-between"
fontSize="sm"
py="1"
color={detailsLabelColor}
>
Details
<AccordionIcon />
</AccordionButton>
<AccordionPanel>
<CodeEditor
isReadOnly
value={details.content}
lang={details.lang}
minWidth="300px"
maxHeight="200px"
maxWidth="calc(450px - 100px)"
/>
</AccordionPanel>
</AccordionItem>
</Accordion>
)}
{(secondaryButton || primaryButton) && (
<HStack>
Expand Down
8 changes: 6 additions & 2 deletions apps/builder/src/components/inputs/SwitchWithLabel.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
FormControl,
FormControlProps,
FormLabel,
HStack,
Switch,
Expand All @@ -13,13 +14,15 @@ export type SwitchWithLabelProps = {
initialValue: boolean
moreInfoContent?: string
onCheckChange: (isChecked: boolean) => void
} & SwitchProps
justifyContent?: FormControlProps['justifyContent']
} & Omit<SwitchProps, 'value' | 'justifyContent'>

export const SwitchWithLabel = ({
label,
initialValue,
moreInfoContent,
onCheckChange,
justifyContent = 'space-between',
...switchProps
}: SwitchWithLabelProps) => {
const [isChecked, setIsChecked] = useState(initialValue)
Expand All @@ -28,8 +31,9 @@ export const SwitchWithLabel = ({
setIsChecked(!isChecked)
onCheckChange(!isChecked)
}

return (
<FormControl as={HStack} justifyContent="space-between">
<FormControl as={HStack} justifyContent={justifyContent}>
<FormLabel mb="0">
{label}
{moreInfoContent && (
Expand Down
10 changes: 9 additions & 1 deletion apps/builder/src/components/inputs/TextInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,13 @@ export type TextInputProps = {
isDisabled?: boolean
} & Pick<
InputProps,
'autoComplete' | 'onFocus' | 'onKeyUp' | 'type' | 'autoFocus' | 'size'
| 'autoComplete'
| 'onFocus'
| 'onKeyUp'
| 'type'
| 'autoFocus'
| 'size'
| 'maxWidth'
>

export const TextInput = forwardRef(function TextInput(
Expand All @@ -56,6 +62,7 @@ export const TextInput = forwardRef(function TextInput(
onFocus,
onKeyUp,
size,
maxWidth,
}: TextInputProps,
ref
) {
Expand Down Expand Up @@ -122,6 +129,7 @@ export const TextInput = forwardRef(function TextInput(
onBlur={updateCarretPosition}
onChange={(e) => changeValue(e.target.value)}
size={size}
maxWidth={maxWidth}
/>
)

Expand Down
60 changes: 60 additions & 0 deletions apps/builder/src/components/logos/WhatsAppLogo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { IconProps, Icon } from '@chakra-ui/react'

export const WhatsAppLogo = (props: IconProps) => (
<Icon viewBox="0 0 163 164" {...props}>
<g filter="url(#filter0_f_1006_58)">
<path
d="M48.5649 132.648L50.7999 133.972C60.1869 139.543 70.9499 142.49 81.9259 142.495H81.9489C115.656 142.495 143.088 115.069 143.102 81.3599C143.108 65.0249 136.753 49.6639 125.207 38.1089C119.544 32.4103 112.807 27.8915 105.386 24.8141C97.9646 21.7368 90.0068 20.162 81.9729 20.1809C48.2399 20.1809 20.8069 47.6039 20.7949 81.3109C20.7783 92.8208 24.0195 104.101 30.1439 113.846L31.5989 116.158L25.4199 138.716L48.5649 132.648ZM7.75391 156.192L18.1929 118.078C11.7549 106.924 8.36791 94.2699 8.37191 81.3059C8.38891 40.7499 41.3929 7.75586 81.9499 7.75586C101.631 7.76586 120.104 15.4249 133.997 29.3279C147.89 43.2309 155.534 61.7109 155.527 81.3649C155.509 121.918 122.5 154.918 81.9489 154.918H81.9169C69.6039 154.913 57.5049 151.824 46.7579 145.964L7.75391 156.192Z"
fill="#B3B3B3"
/>
</g>
<path
d="M7 155.436L17.439 117.322C10.9899 106.141 7.60242 93.4575 7.618 80.55C7.635 39.994 40.639 7 81.196 7C100.877 7.01 119.35 14.669 133.243 28.572C147.136 42.475 154.78 60.955 154.773 80.609C154.755 121.162 121.746 154.162 81.195 154.162H81.163C68.85 154.157 56.751 151.068 46.004 145.208L7 155.436Z"
fill="white"
/>
<path
d="M81.2171 19.425C47.4841 19.425 20.0511 46.848 20.0391 80.555C20.0225 92.065 23.2637 103.345 29.3881 113.09L30.8431 115.403L24.6641 137.961L47.8101 131.892L50.0451 133.216C59.4321 138.787 70.1951 141.733 81.1711 141.739H81.1941C114.901 141.739 142.334 114.313 142.347 80.604C142.373 72.5696 140.804 64.6099 137.732 57.1858C134.661 49.7617 130.147 43.0207 124.452 37.353C118.789 31.6543 112.052 27.1354 104.631 24.0581C97.2092 20.9807 89.2512 19.406 81.2171 19.425Z"
fill="url(#paint0_linear_1006_58)"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M62.8046 49.801C61.4266 46.74 59.9766 46.678 58.6676 46.625L55.1436 46.582C53.9176 46.582 51.9256 47.042 50.2416 48.882C48.5576 50.722 43.8066 55.169 43.8066 64.214C43.8066 73.259 50.3946 81.999 51.3126 83.227C52.2306 84.455 64.0306 103.608 82.7176 110.977C98.2466 117.101 101.407 115.883 104.779 115.577C108.151 115.271 115.656 111.13 117.187 106.837C118.718 102.544 118.719 98.866 118.26 98.097C117.801 97.328 116.575 96.871 114.735 95.951C112.895 95.031 103.858 90.584 102.173 89.97C100.488 89.356 99.2626 89.051 98.0356 90.891C96.8086 92.731 93.2896 96.87 92.2166 98.097C91.1436 99.324 90.0726 99.478 88.2326 98.559C86.3926 97.64 80.4726 95.698 73.4486 89.435C67.9836 84.562 64.2946 78.544 63.2206 76.705C62.1466 74.866 63.1066 73.87 64.0286 72.954C64.8536 72.13 65.8666 70.807 66.7876 69.734C67.7086 68.661 68.0116 67.894 68.6236 66.669C69.2356 65.444 68.9306 64.368 68.4706 63.449C68.0106 62.53 64.4386 53.437 62.8046 49.801Z"
fill="white"
/>
<defs>
<filter
id="filter0_f_1006_58"
x="0.691906"
y="0.69386"
width="161.897"
height="162.56"
filterUnits="userSpaceOnUse"
colorInterpolationFilters="sRGB"
>
<feFlood floodOpacity="0" result="BackgroundImageFix" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="BackgroundImageFix"
result="shape"
/>
<feGaussianBlur
stdDeviation="3.531"
result="effect1_foregroundBlur_1006_58"
/>
</filter>
<linearGradient
id="paint0_linear_1006_58"
x1="79.9481"
y1="26.765"
x2="80.5681"
y2="131.29"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#57D163" />
<stop offset="1" stopColor="#23B33A" />
</linearGradient>
</defs>
</Icon>
)
7 changes: 6 additions & 1 deletion apps/builder/src/features/account/UserProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { useToast } from '@/hooks/useToast'
import { updateUserQuery } from './queries/updateUserQuery'
import { useDebouncedCallback } from 'use-debounce'
import { env } from '@typebot.io/env'
import { identifyUser } from '../telemetry/posthog'

export const userContext = createContext<{
user?: User
Expand Down Expand Up @@ -37,7 +38,11 @@ export const UserProvider = ({ children }: { children: ReactNode }) => {
)
const parsedUser = session.user as User
setUser(parsedUser)
if (parsedUser?.id) setSentryUser({ id: parsedUser.id })

if (parsedUser?.id) {
setSentryUser({ id: parsedUser.id })
identifyUser(parsedUser.id)
}
}, [session, user])

useEffect(() => {
Expand Down
32 changes: 32 additions & 0 deletions apps/builder/src/features/account/components/ApiTokensModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {
Modal,
ModalBody,
ModalContent,
ModalFooter,
ModalHeader,
ModalOverlay,
} from '@chakra-ui/react'
import { ApiTokensList } from './ApiTokensList'
import { useUser } from '../hooks/useUser'

type Props = {
isOpen: boolean
onClose: () => void
}
export const ApiTokensModal = ({ isOpen, onClose }: Props) => {
const { user } = useUser()

if (!user) return
return (
<Modal isOpen={isOpen} onClose={onClose} size="xl">
<ModalOverlay />
<ModalContent>
<ModalHeader />
<ModalBody>
<ApiTokensList user={user} />
</ModalBody>
<ModalFooter />
</ModalContent>
</Modal>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
InputGroup,
InputRightElement,
} from '@chakra-ui/react'
import React, { FormEvent, useState } from 'react'
import React, { FormEvent, useRef, useState } from 'react'
import { createApiTokenQuery } from '../queries/createApiTokenQuery'
import { ApiTokenFromServer } from '../types'

Expand All @@ -32,6 +32,7 @@ export const CreateTokenModal = ({
onClose,
onNewToken,
}: Props) => {
const inputRef = useRef<HTMLInputElement>(null)
const scopedT = useScopedI18n('account.apiTokens.createModal')
const [name, setName] = useState('')
const [isSubmitting, setIsSubmitting] = useState(false)
Expand All @@ -47,8 +48,9 @@ export const CreateTokenModal = ({
}
setIsSubmitting(false)
}

return (
<Modal isOpen={isOpen} onClose={onClose}>
<Modal isOpen={isOpen} onClose={onClose} initialFocusRef={inputRef}>
<ModalOverlay />
<ModalContent>
<ModalHeader>
Expand All @@ -58,7 +60,7 @@ export const CreateTokenModal = ({
{newTokenValue ? (
<ModalBody as={Stack} spacing="4">
<Text>
{scopedT('copyInstruction')}
{scopedT('copyInstruction')}{' '}
<strong>{scopedT('securityWarning')}</strong>
</Text>
<InputGroup size="md">
Expand All @@ -72,6 +74,7 @@ export const CreateTokenModal = ({
<ModalBody as="form" onSubmit={createToken}>
<Text mb="4">{scopedT('nameInput.label')}</Text>
<Input
ref={inputRef}
placeholder={scopedT('nameInput.placeholder')}
onChange={(e) => setName(e.target.value)}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ export const PaymentSettings = ({ options, onOptionsChange }: Props) => {
currentCredentialsId={options.credentialsId}
onCredentialsSelect={updateCredentials}
onCreateNewClick={onOpen}
credentialsName="Stripe account"
/>
)}
</Stack>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ test.describe('Payment input block', () => {

await page.goto(`/typebots/${typebotId}/edit`)
await page.click('text=Configure...')
await page.getByRole('button', { name: 'Select an account' }).click()
await page.click('text=Connect new')
await page.getByRole('button', { name: 'Add Stripe account' }).click()
await page.fill('[placeholder="Typebot"]', 'My Stripe Account')
await page.fill('[placeholder="sk_test_..."]', env.STRIPE_SECRET_KEY ?? '')
await page.fill('[placeholder="sk_live_..."]', env.STRIPE_SECRET_KEY ?? '')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ export const GoogleSheetsSettings = ({
currentCredentialsId={options?.credentialsId}
onCredentialsSelect={handleCredentialsIdChange}
onCreateNewClick={handleCreateNewClick}
credentialsName="Sheets account"
/>
)}
<GoogleSheetConnectModal
Expand Down
Loading

4 comments on commit b852b4a

@vercel
Copy link

@vercel vercel bot commented on b852b4a Aug 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on b852b4a Aug 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

docs – ./apps/docs

docs-git-main-typebot-io.vercel.app
docs-typebot-io.vercel.app
docs.typebot.io

@vercel
Copy link

@vercel vercel bot commented on b852b4a Aug 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

builder-v2 – ./apps/builder

builder-v2-git-main-typebot-io.vercel.app
app.typebot.io
builder-v2-typebot-io.vercel.app

@vercel
Copy link

@vercel vercel bot commented on b852b4a Aug 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

viewer-v2 – ./apps/viewer

bii.bj
1stop.au
wasap.nl
x.cr8.ai
yobot.me
klujo.com
me.cr8.ai
sifuim.co
wachat.io
wassep.io
247987.com
8jours.top
aginap.com
ai.mprs.in
bee.cr8.ai
bot.aws.bj
bot.bbc.bj
cat.cr8.ai
finplex.be
jxi.cr8.ai
nepkit.com
pig.cr8.ai
sat.cr8.ai
typebot.io
wachats.me
wsapio.com
zamrin.net
blogely.com
bot.aipr.kr
bot.kloo.me
broprio.com
bull.cr8.ai
docs.cr8.ai
getyour.sbs
icon.cr8.ai
minipost.uk
mole.cr8.ai
nurraysa.me
team.cr8.ai
wolf.cr8.ai
ai.meant.com
alphamen.pro
bet7k.online
bot.afric.ai
bot.grace.bj
cinecorn.com
ezbooking.ai
gniorder.com
help.taxt.co
kusamint.com
panther.cr7.ai
panther.cr8.ai
pay.sifuim.com
penguin.cr8.ai
segredomeu.com
talk.gocare.io
test.bot.gives
ticketfute.com
unicorn.cr8.ai
whats-app.chat
apo.nigerias.io
aso.nigerias.io
viewer-v2-typebot-io.vercel.app
mdb.assessoria.jbatista.progenbr.com
mdb.assessoria.mauricio.progenbr.com
mdb.evento.autocadastro.progenbr.com
form.shopmercedesbenzsouthorlando.com
mdb.evento.equipeinterna.progenbr.com
bot.studiotecnicoimmobiliaremerelli.it
mdb.assessoria.boaventura.progenbr.com
mdb.assessoria.jtrebesqui.progenbr.com
pesquisa.escolamodacomproposito.com.br
anamnese.clinicaramosodontologia.com.br
gabinete.baleia.formulario.progenbr.com
mdb.assessoria.carreirinha.progenbr.com
chrome-os-inquiry-system.itschromeos.com
mdb.assessoria.paulomarques.progenbr.com
viewer-v2-git-main-typebot-io.vercel.app
main-menu-for-itschromeos.itschromeos.com
mdb.assessoria.qrcode.ademir.progenbr.com
mdb.assessoria.qrcode.arthur.progenbr.com
mdb.assessoria.qrcode.danilo.progenbr.com
mdb.assessoria.qrcode.marcao.progenbr.com
mdb.assessoria.qrcode.marcio.progenbr.com
mdb.assessoria.qrcode.aloisio.progenbr.com
mdb.assessoria.qrcode.girotto.progenbr.com
mdb.assessoria.qrcode.marinho.progenbr.com
mdb.assessoria.qrcode.rodrigo.progenbr.com
mdb.assessoria.carlosalexandre.progenbr.com
mdb.assessoria.qrcode.desideri.progenbr.com
mdb.assessoria.qrcode.fernanda.progenbr.com
mdb.assessoria.qrcode.jbatista.progenbr.com
mdb.assessoria.qrcode.mauricio.progenbr.com
mdb.assessoria.fernanda.regional.progenbr.com
mdb.assessoria.qrcode.boaventura.progenbr.com
mdb.assessoria.qrcode.jtrebesqui.progenbr.com
mdb.assessoria.qrcode.carreirinha.progenbr.com
mdb.assessoria.qrcode.paulomarques.progenbr.com
mdb.assessoria.qrcode.carlosalexandre.progenbr.com
mdb.assessoria.qrcode.fernanda.regional.progenbr.com

Please sign in to comment.