♻️ Introduce typebot v6 with events (#1013)

Closes #885
This commit is contained in:
Baptiste Arnaud
2023-11-08 15:34:16 +01:00
committed by GitHub
parent 68e4fc71fb
commit 35300eaf34
634 changed files with 58971 additions and 31449 deletions

View File

@@ -1,6 +1,6 @@
import React, { useState } from 'react'
import { useAnswers } from '../../../providers/AnswersProvider'
import { InputBlock, InputBlockType } from '@typebot.io/schemas'
import { InputBlock } from '@typebot.io/schemas'
import { GuestBubble } from './bubbles/GuestBubble'
import { byId } from '@typebot.io/lib'
import { InputSubmitContent } from '@/types'
@@ -17,6 +17,9 @@ import { ChoiceForm } from '@/features/blocks/inputs/buttons'
import { PaymentForm } from '@/features/blocks/inputs/payment'
import { RatingForm } from '@/features/blocks/inputs/rating'
import { FileUploadForm } from '@/features/blocks/inputs/fileUpload'
import { defaultSettings } from '@typebot.io/schemas/features/typebot/settings/constants'
import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/constants'
import { getBlockById } from '@typebot.io/lib/getBlockById'
export const InputChatBlock = ({
block,
@@ -39,9 +42,11 @@ export const InputChatBlock = ({
const [answer, setAnswer] = useState<string>()
const [isEditting, setIsEditting] = useState(false)
const { variableId } = block.options
const { variableId } = block.options ?? {}
const defaultValue =
(typebot.settings.general.isInputPrefillEnabled ?? true) && variableId
(typebot.settings.general?.isInputPrefillEnabled ??
defaultSettings.general.isInputPrefillEnabled) &&
variableId
? typebot.variables.find(
(variable) =>
variable.name === typebot.variables.find(byId(variableId))?.name
@@ -51,14 +56,17 @@ export const InputChatBlock = ({
const handleSubmit = async ({ label, value, itemId }: InputSubmitContent) => {
setAnswer(label ?? value)
const isRetry = !isInputValid(value, block.type)
if (!isRetry && addAnswer)
if (!isRetry && addAnswer) {
const { group } = getBlockById(block.id, typebot.groups)
await addAnswer(typebot.variables)({
blockId: block.id,
groupId: block.groupId,
groupId: group.id,
content: value,
variableId,
uploadedFiles: block.type === InputBlockType.FILE,
})
}
if (!isEditting) onTransitionEnd({ label, value, itemId }, isRetry)
setIsEditting(false)
}
@@ -66,11 +74,11 @@ export const InputChatBlock = ({
if (isLoading) return null
if (answer) {
const avatarUrl = typebot.theme.chat.guestAvatar?.url
const avatarUrl = typebot.theme.chat?.guestAvatar?.url
return (
<GuestBubble
message={answer}
showAvatar={typebot.theme.chat.guestAvatar?.isEnabled ?? false}
showAvatar={typebot.theme.chat?.guestAvatar?.isEnabled ?? false}
avatarSrc={avatarUrl && parseVariables(typebot.variables)(avatarUrl)}
/>
)
@@ -160,7 +168,7 @@ const Input = ({
<PaymentForm
options={block.options}
onSuccess={() =>
onSubmit({ value: block.options.labels.success ?? 'Success' })
onSubmit({ value: block.options?.labels?.success ?? 'Success' })
}
/>
)

View File

@@ -3,7 +3,8 @@ import { EmbedBubble } from '@/features/blocks/bubbles/embed'
import { ImageBubble } from '@/features/blocks/bubbles/image'
import { TextBubble } from '@/features/blocks/bubbles/textBubble'
import { VideoBubble } from '@/features/blocks/bubbles/video'
import { BubbleBlock, BubbleBlockType } from '@typebot.io/schemas'
import { BubbleBlock } from '@typebot.io/schemas'
import { BubbleBlockType } from '@typebot.io/schemas/features/blocks/bubbles/constants'
type Props = {
block: BubbleBlock
@@ -23,7 +24,7 @@ export const HostBubble = ({ block, onTransitionEnd }: Props) => {
case BubbleBlockType.AUDIO:
return (
<AudioBubble
url={block.content.url}
url={block.content?.url}
onTransitionEnd={onTransitionEnd}
/>
)

View File

@@ -15,7 +15,6 @@ import {
import {
BubbleBlock,
InputBlock,
LogicBlockType,
PublicTypebot,
Block,
} from '@typebot.io/schemas'
@@ -30,6 +29,8 @@ import { executeIntegration } from '@/utils/executeIntegration'
import { executeLogic } from '@/utils/executeLogic'
import { blockCanBeRetried, parseRetryBlock } from '@/utils/inputs'
import { PopupBlockedToast } from '../PopupBlockedToast'
import { LogicBlockType } from '@typebot.io/schemas/features/blocks/logic/constants'
import { getBlockById } from '@typebot.io/lib/getBlockById'
type ChatGroupProps = {
blocks: Block[]
@@ -143,19 +144,20 @@ export const ChatGroup = ({
if (blockedPopupUrl) setBlockedPopupUrl(blockedPopupUrl)
const isRedirecting =
currentBlock.type === LogicBlockType.REDIRECT &&
currentBlock.options.isNewTab === false
currentBlock.options?.isNewTab === false
if (isRedirecting) return
nextEdgeId
? onGroupEnd({ edgeId: nextEdgeId, updatedTypebot: linkedTypebot })
: displayNextBlock()
}
if (isIntegrationBlock(currentBlock)) {
const { group } = getBlockById(currentBlock.id, typebot.groups)
const nextEdgeId = await executeIntegration({
block: currentBlock,
context: {
apiHost,
typebotId: currentTypebotId,
groupId: currentBlock.groupId,
groupId: group.id,
blockId: currentBlock.id,
variables: typebot.variables,
isPreview,
@@ -181,10 +183,12 @@ export const ChatGroup = ({
scroll()
const currentBlock = [...processedBlocks].pop()
if (currentBlock) {
if (isRetry && blockCanBeRetried(currentBlock))
if (isRetry && blockCanBeRetried(currentBlock)) {
const { group } = getBlockById(currentBlock.id, typebot.groups)
return insertBlockInStack(
parseRetryBlock(currentBlock, typebot.variables, createEdge)
parseRetryBlock(currentBlock, group.id, typebot.variables, createEdge)
)
}
if (
isInputBlock(currentBlock) &&
currentBlock.options?.variableId &&
@@ -196,7 +200,7 @@ export const ChatGroup = ({
)
}
const isSingleChoiceBlock =
isChoiceInput(currentBlock) && !currentBlock.options.isMultipleChoice
isChoiceInput(currentBlock) && !currentBlock.options?.isMultipleChoice
if (isSingleChoiceBlock) {
const nextEdgeId = currentBlock.items.find(
byId(answerContent?.itemId)
@@ -214,7 +218,7 @@ export const ChatGroup = ({
nextBlock ? insertBlockInStack(nextBlock) : onGroupEnd({})
}
const avatarSrc = typebot.theme.chat.hostAvatar?.url
const avatarSrc = typebot.theme.chat?.hostAvatar?.url
return (
<div className="flex w-full" data-group-name={groupTitle}>
@@ -224,10 +228,10 @@ export const ChatGroup = ({
key={idx}
displayChunk={chunk}
hostAvatar={{
isEnabled: typebot.theme.chat.hostAvatar?.isEnabled ?? true,
isEnabled: typebot.theme.chat?.hostAvatar?.isEnabled ?? true,
src: avatarSrc && parseVariables(typebot.variables)(avatarSrc),
}}
hasGuestAvatar={typebot.theme.chat.guestAvatar?.isEnabled ?? false}
hasGuestAvatar={typebot.theme.chat?.guestAvatar?.isEnabled ?? false}
onDisplayNextBlock={displayNextBlock}
keepShowingHostAvatar={keepShowingHostAvatar}
blockedPopupUrl={blockedPopupUrl}

View File

@@ -57,7 +57,7 @@ export const ConversationContainer = ({
if (!nextGroup) return
onNewGroupVisible({
id: 'edgeId',
from: { groupId: 'block', blockId: 'block' },
from: { blockId: 'block' },
to: { groupId },
})
return setDisplayedGroups([

View File

@@ -7,7 +7,6 @@ import { ConversationContainer } from './ConversationContainer'
import { AnswersProvider } from '../providers/AnswersProvider'
import {
AnswerInput,
BackgroundType,
Edge,
PublicTypebot,
VariableWithValue,
@@ -16,6 +15,7 @@ import { Log } from '@typebot.io/prisma'
import { LiteBadge } from './LiteBadge'
import { isNotEmpty } from '@typebot.io/lib'
import { getViewerUrl } from '@typebot.io/lib/getViewerUrl'
import { BackgroundType } from '@typebot.io/schemas/features/typebot/theme/constants'
export type TypebotViewerProps = {
typebot: Omit<PublicTypebot, 'updatedAt' | 'createdAt'>
@@ -78,7 +78,7 @@ export const TypebotViewer = ({
<style
dangerouslySetInnerHTML={{
__html: `@import url('https://fonts.googleapis.com/css2?family=${
typebot.theme.general.font ?? 'Open Sans'
typebot.theme.general?.font ?? 'Open Sans'
}:ital,wght@0,300;0,400;0,600;1,300;1,400;1,600&display=swap');`,
}}
/>
@@ -112,7 +112,7 @@ export const TypebotViewer = ({
startGroupId={startGroupId}
/>
</div>
{typebot.settings.general.isBrandingEnabled && <LiteBadge />}
{typebot.settings.general?.isBrandingEnabled && <LiteBadge />}
</div>
</AnswersProvider>
</TypebotProvider>