From 918836d6cf26022921da9b37c37ef65c2ac112d7 Mon Sep 17 00:00:00 2001 From: Baptiste Arnaud Date: Wed, 19 Jun 2024 15:27:45 +0200 Subject: [PATCH] :zap: (embed) Option to add a wait event for the embed bubble Closes #1590 --- apps/builder/src/components/TableList.tsx | 20 ++++----- .../embed/components/EmbedBubbleContent.tsx | 19 +++++++- .../embed/components/EmbedUploadContent.tsx | 41 +++++++++++++++++- apps/docs/editor/blocks/bubbles/embed.mdx | 21 +++++++++ .../docs/images/blocks/bubbles/embed-wait.jpg | Bin 0 -> 92359 bytes .../features/chat/api/legacy/sendMessageV1.ts | 15 +++++-- .../features/chat/api/legacy/sendMessageV2.ts | 15 +++++-- .../bot-engine/apiHandlers/continueChat.ts | 10 +++-- packages/bot-engine/apiHandlers/startChat.ts | 9 +++- .../apiHandlers/startChatPreview.ts | 8 +++- packages/bot-engine/continueBotFlow.ts | 7 +++ packages/bot-engine/executeGroup.ts | 35 +++++++++++---- packages/bot-engine/saveStateToDatabase.ts | 8 ++-- packages/embeds/js/package.json | 2 +- .../js/src/components/bubbles/HostBubble.tsx | 1 + .../bubbles/embed/components/EmbedBubble.tsx | 23 ++++++++++ packages/embeds/nextjs/package.json | 2 +- packages/embeds/react/package.json | 2 +- .../features/blocks/bubbles/embed/schema.ts | 7 +++ packages/schemas/features/chat/schema.ts | 1 - 20 files changed, 200 insertions(+), 46 deletions(-) create mode 100644 apps/docs/images/blocks/bubbles/embed-wait.jpg diff --git a/apps/builder/src/components/TableList.tsx b/apps/builder/src/components/TableList.tsx index 7f1a8f8d6..a12716346 100644 --- a/apps/builder/src/components/TableList.tsx +++ b/apps/builder/src/components/TableList.tsx @@ -15,25 +15,23 @@ const defaultItem = { id: createId(), } -type ItemWithId = T & { id: string } - export type TableListItemProps = { item: T onItemChange: (item: T) => void } -type Props = { - initialItems?: ItemWithId[] +type Props = { + initialItems?: T[] isOrdered?: boolean addLabel?: string newItemDefaultProps?: Partial hasDefaultItem?: boolean ComponentBetweenItems?: (props: unknown) => JSX.Element - onItemsChange: (items: ItemWithId[]) => void + onItemsChange: (items: T[]) => void children: (props: TableListItemProps) => JSX.Element } -export const TableList = ({ +export const TableList = ({ initialItems, isOrdered, addLabel = 'Add', @@ -45,7 +43,7 @@ export const TableList = ({ }: Props) => { const [items, setItems] = useState( addIdsIfMissing(initialItems) ?? - (hasDefaultItem ? ([defaultItem] as ItemWithId[]) : []) + (hasDefaultItem ? ([defaultItem] as T[]) : []) ) const [showDeleteIndex, setShowDeleteIndex] = useState(null) @@ -56,14 +54,14 @@ export const TableList = ({ const createItem = () => { const id = createId() - const newItem = { id, ...newItemDefaultProps } as ItemWithId + const newItem = { id, ...newItemDefaultProps } as T setItems([...items, newItem]) onItemsChange([...items, newItem]) } const insertItem = (itemIndex: number) => () => { const id = createId() - const newItem = { id } as ItemWithId + const newItem = { id } as T const newItems = [...items] newItems.splice(itemIndex + 1, 0, newItem) setItems(newItems) @@ -96,7 +94,7 @@ export const TableList = ({ return ( {items.map((item, itemIndex) => ( - + {itemIndex !== 0 && ComponentBetweenItems && ( )} @@ -185,7 +183,7 @@ export const TableList = ({ ) } -const addIdsIfMissing = (items?: T[]): ItemWithId[] | undefined => +const addIdsIfMissing = (items?: T[]): T[] | undefined => items?.map((item) => ({ id: createId(), ...item, diff --git a/apps/builder/src/features/blocks/bubbles/embed/components/EmbedBubbleContent.tsx b/apps/builder/src/features/blocks/bubbles/embed/components/EmbedBubbleContent.tsx index 66f1499ee..6c1b28826 100644 --- a/apps/builder/src/features/blocks/bubbles/embed/components/EmbedBubbleContent.tsx +++ b/apps/builder/src/features/blocks/bubbles/embed/components/EmbedBubbleContent.tsx @@ -1,14 +1,29 @@ import { useTranslate } from '@tolgee/react' -import { Text } from '@chakra-ui/react' +import { Stack, Text } from '@chakra-ui/react' import { EmbedBubbleBlock } from '@typebot.io/schemas' +import { SetVariableLabel } from '@/components/SetVariableLabel' +import { useTypebot } from '@/features/editor/providers/TypebotProvider' type Props = { block: EmbedBubbleBlock } export const EmbedBubbleContent = ({ block }: Props) => { + const { typebot } = useTypebot() const { t } = useTranslate() if (!block.content?.url) return {t('clickToEdit')} - return {t('editor.blocks.bubbles.embed.node.show.text')} + return ( + + {t('editor.blocks.bubbles.embed.node.show.text')} + {typebot && + block.content.waitForEvent?.isEnabled && + block.content.waitForEvent.saveDataInVariableId && ( + + )} + + ) } diff --git a/apps/builder/src/features/blocks/bubbles/embed/components/EmbedUploadContent.tsx b/apps/builder/src/features/blocks/bubbles/embed/components/EmbedUploadContent.tsx index 7bd29fd9e..b2d9da477 100644 --- a/apps/builder/src/features/blocks/bubbles/embed/components/EmbedUploadContent.tsx +++ b/apps/builder/src/features/blocks/bubbles/embed/components/EmbedUploadContent.tsx @@ -1,9 +1,11 @@ import { TextInput, NumberInput } from '@/components/inputs' import { Stack, Text } from '@chakra-ui/react' -import { EmbedBubbleBlock } from '@typebot.io/schemas' +import { EmbedBubbleBlock, Variable } from '@typebot.io/schemas' import { sanitizeUrl } from '@typebot.io/lib' import { useTranslate } from '@tolgee/react' import { defaultEmbedBubbleContent } from '@typebot.io/schemas/features/blocks/bubbles/embed/constants' +import { SwitchWithRelatedSettings } from '@/components/SwitchWithRelatedSettings' +import { VariableSearchInput } from '@/components/inputs/VariableSearchInput' type Props = { content: EmbedBubbleBlock['content'] @@ -23,6 +25,24 @@ export const EmbedUploadContent = ({ content, onSubmit }: Props) => { height?: NonNullable['height'] ) => height && onSubmit({ ...content, height }) + const updateWaitEventName = (name: string) => + onSubmit({ ...content, waitForEvent: { ...content?.waitForEvent, name } }) + + const updateWaitForEventEnabled = (isEnabled: boolean) => + onSubmit({ + ...content, + waitForEvent: { ...content?.waitForEvent, isEnabled }, + }) + + const updateSaveDataInVariableId = (variable?: Pick) => + onSubmit({ + ...content, + waitForEvent: { + ...content?.waitForEvent, + saveDataInVariableId: variable?.id, + }, + }) + return ( @@ -43,8 +63,25 @@ export const EmbedUploadContent = ({ content, onSubmit }: Props) => { defaultValue={content?.height ?? defaultEmbedBubbleContent.height} onValueChange={handleHeightChange} suffix={t('editor.blocks.bubbles.embed.settings.numberInput.unit')} - width="150px" + direction="row" /> + + + + ) } diff --git a/apps/docs/editor/blocks/bubbles/embed.mdx b/apps/docs/editor/blocks/bubbles/embed.mdx index 2be3668fe..26c9bab42 100644 --- a/apps/docs/editor/blocks/bubbles/embed.mdx +++ b/apps/docs/editor/blocks/bubbles/embed.mdx @@ -35,3 +35,24 @@ The Embed bubble block allows you to display a website or an iframe to your user For this, you'll need to select the pdf file you want to embed. Right click > Preview > More actions > Open in a new window. Now click More actions > Embed item. Copy the embed code and paste it in the Embed bubble block configuration. + +## Wait for event + +Enable this if you are the owner of the website you want to embed and would like to continue the bot flow only when an event from the embed is sent to the bot. This event dispatch needs to be executed in the embed website. Here is an example: + +```js +window.parent.postMessage( + { name: 'My event', data: 'Custom data passed to the typebot variable' }, + '*' +) +``` + +You can choose the name of the event, it needs to match what you've set in the Embed bubble block configuration. + + + Embed bubble + diff --git a/apps/docs/images/blocks/bubbles/embed-wait.jpg b/apps/docs/images/blocks/bubbles/embed-wait.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bc81f50468f004261f3099b56153c8b992b5eaf8 GIT binary patch literal 92359 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 xs^D*3Q4AUJQKce-W8DXynwK4Zcpxkhj?##` message.type === 'custom-embed' + hasEmbedBubbleWithWaitEvent: messages.some( + (message) => + message.type === 'custom-embed' || + (message.type === BubbleBlockType.EMBED && + message.content.waitForEvent?.isEnabled) ), setVariableHistory, }) @@ -199,8 +203,11 @@ export const sendMessageV1 = publicProcedure logs: allLogs, clientSideActions, visitedEdges, - hasCustomEmbedBubble: messages.some( - (message) => message.type === 'custom-embed' + hasEmbedBubbleWithWaitEvent: messages.some( + (message) => + message.type === 'custom-embed' || + (message.type === BubbleBlockType.EMBED && + message.content.waitForEvent?.isEnabled) ), setVariableHistory, }) diff --git a/apps/viewer/src/features/chat/api/legacy/sendMessageV2.ts b/apps/viewer/src/features/chat/api/legacy/sendMessageV2.ts index ddf4c7a79..982890630 100644 --- a/apps/viewer/src/features/chat/api/legacy/sendMessageV2.ts +++ b/apps/viewer/src/features/chat/api/legacy/sendMessageV2.ts @@ -11,6 +11,7 @@ import { chatReplySchema, sendMessageInputSchema, } from '@typebot.io/schemas/features/chat/legacy/schema' +import { BubbleBlockType } from '@typebot.io/schemas/features/blocks/bubbles/constants' export const sendMessageV2 = publicProcedure .meta({ @@ -136,8 +137,11 @@ export const sendMessageV2 = publicProcedure logs: allLogs, clientSideActions, visitedEdges, - hasCustomEmbedBubble: messages.some( - (message) => message.type === 'custom-embed' + hasEmbedBubbleWithWaitEvent: messages.some( + (message) => + message.type === 'custom-embed' || + (message.type === BubbleBlockType.EMBED && + message.content.waitForEvent?.isEnabled) ), setVariableHistory, }) @@ -198,8 +202,11 @@ export const sendMessageV2 = publicProcedure logs: allLogs, clientSideActions, visitedEdges, - hasCustomEmbedBubble: messages.some( - (message) => message.type === 'custom-embed' + hasEmbedBubbleWithWaitEvent: messages.some( + (message) => + message.type === 'custom-embed' || + (message.type === BubbleBlockType.EMBED && + message.content.waitForEvent?.isEnabled) ), setVariableHistory, }) diff --git a/packages/bot-engine/apiHandlers/continueChat.ts b/packages/bot-engine/apiHandlers/continueChat.ts index 6d3f1d5ce..0ae019c7b 100644 --- a/packages/bot-engine/apiHandlers/continueChat.ts +++ b/packages/bot-engine/apiHandlers/continueChat.ts @@ -1,11 +1,12 @@ import { TRPCError } from '@trpc/server' -import { isDefined, isNotDefined } from '@typebot.io/lib/utils' +import { isDefined, isNotDefined, isNotEmpty } from '@typebot.io/lib/utils' import { getSession } from '../queries/getSession' import { continueBotFlow } from '../continueBotFlow' import { filterPotentiallySensitiveLogs } from '../logs/filterPotentiallySensitiveLogs' import { parseDynamicTheme } from '../parseDynamicTheme' import { saveStateToDatabase } from '../saveStateToDatabase' import { computeCurrentProgress } from '../computeCurrentProgress' +import { BubbleBlockType } from '@typebot.io/schemas/features/blocks/bubbles/constants' type Props = { origin: string | undefined @@ -77,8 +78,11 @@ export const continueChat = async ({ clientSideActions, visitedEdges, setVariableHistory, - hasCustomEmbedBubble: messages.some( - (message) => message.type === 'custom-embed' + hasEmbedBubbleWithWaitEvent: messages.some( + (message) => + message.type === 'custom-embed' || + (message.type === BubbleBlockType.EMBED && + message.content.waitForEvent?.isEnabled) ), }) diff --git a/packages/bot-engine/apiHandlers/startChat.ts b/packages/bot-engine/apiHandlers/startChat.ts index 5776f417e..b351aabd7 100644 --- a/packages/bot-engine/apiHandlers/startChat.ts +++ b/packages/bot-engine/apiHandlers/startChat.ts @@ -1,8 +1,10 @@ +import { BubbleBlockType } from '@typebot.io/schemas/features/blocks/bubbles/constants' import { computeCurrentProgress } from '../computeCurrentProgress' import { filterPotentiallySensitiveLogs } from '../logs/filterPotentiallySensitiveLogs' import { restartSession } from '../queries/restartSession' import { saveStateToDatabase } from '../saveStateToDatabase' import { startSession } from '../startSession' +import { isNotEmpty } from '@typebot.io/lib' type Props = { origin: string | undefined @@ -74,8 +76,11 @@ export const startChat = async ({ clientSideActions, visitedEdges, setVariableHistory, - hasCustomEmbedBubble: messages.some( - (message) => message.type === 'custom-embed' + hasEmbedBubbleWithWaitEvent: messages.some( + (message) => + message.type === 'custom-embed' || + (message.type === BubbleBlockType.EMBED && + message.content.waitForEvent?.isEnabled) ), }) diff --git a/packages/bot-engine/apiHandlers/startChatPreview.ts b/packages/bot-engine/apiHandlers/startChatPreview.ts index e2f488ee6..542bd1415 100644 --- a/packages/bot-engine/apiHandlers/startChatPreview.ts +++ b/packages/bot-engine/apiHandlers/startChatPreview.ts @@ -3,6 +3,7 @@ import { restartSession } from '../queries/restartSession' import { saveStateToDatabase } from '../saveStateToDatabase' import { startSession } from '../startSession' import { computeCurrentProgress } from '../computeCurrentProgress' +import { BubbleBlockType } from '@typebot.io/schemas/features/blocks/bubbles/constants' type Props = { message?: string @@ -69,8 +70,11 @@ export const startChatPreview = async ({ clientSideActions, visitedEdges, setVariableHistory, - hasCustomEmbedBubble: messages.some( - (message) => message.type === 'custom-embed' + hasEmbedBubbleWithWaitEvent: messages.some( + (message) => + message.type === 'custom-embed' || + (message.type === BubbleBlockType.EMBED && + message.content.waitForEvent?.isEnabled) ), initialSessionId: sessionId, }) diff --git a/packages/bot-engine/continueBotFlow.ts b/packages/bot-engine/continueBotFlow.ts index 4d4742b99..f26181fe4 100644 --- a/packages/bot-engine/continueBotFlow.ts +++ b/packages/bot-engine/continueBotFlow.ts @@ -145,6 +145,13 @@ export const continueBotFlow = async ( } } } + } else if ( + block.type === BubbleBlockType.EMBED && + block.content?.waitForEvent?.saveDataInVariableId + ) { + variableToUpdate = state.typebotsQueue[0].typebot.variables.find( + (v) => v.id === block.content?.waitForEvent?.saveDataInVariableId + ) } if (variableToUpdate) { diff --git a/packages/bot-engine/executeGroup.ts b/packages/bot-engine/executeGroup.ts index 1861803ba..2cd9349f4 100644 --- a/packages/bot-engine/executeGroup.ts +++ b/packages/bot-engine/executeGroup.ts @@ -6,7 +6,7 @@ import { SessionState, SetVariableHistoryItem, } from '@typebot.io/schemas' -import { isNotEmpty } from '@typebot.io/lib' +import { isEmpty, isNotEmpty } from '@typebot.io/lib' import { isBubbleBlock, isInputBlock, @@ -32,6 +32,7 @@ import { BubbleBlockWithDefinedContent, parseBubbleBlock, } from './parseBubbleBlock' +import { BubbleBlockType } from '@typebot.io/schemas/features/blocks/bubbles/constants' type ContextProps = { version: 1 | 2 @@ -95,14 +96,30 @@ export const executeGroup = async ( if (isBubbleBlock(block)) { if (!block.content || (firstBubbleWasStreamed && index === 0)) continue - messages.push( - parseBubbleBlock(block as BubbleBlockWithDefinedContent, { - version, - variables: newSessionState.typebotsQueue[0].typebot.variables, - typebotVersion: newSessionState.typebotsQueue[0].typebot.version, - textBubbleContentFormat, - }) - ) + const message = parseBubbleBlock(block as BubbleBlockWithDefinedContent, { + version, + variables: newSessionState.typebotsQueue[0].typebot.variables, + typebotVersion: newSessionState.typebotsQueue[0].typebot.version, + textBubbleContentFormat, + }) + messages.push(message) + if ( + message.type === BubbleBlockType.EMBED && + message.content.waitForEvent?.isEnabled + ) { + return { + messages, + newSessionState: { + ...newSessionState, + currentBlockId: block.id, + }, + clientSideActions, + logs, + visitedEdges, + setVariableHistory, + } + } + lastBubbleBlockId = block.id continue } diff --git a/packages/bot-engine/saveStateToDatabase.ts b/packages/bot-engine/saveStateToDatabase.ts index 0241deddc..4231ee98d 100644 --- a/packages/bot-engine/saveStateToDatabase.ts +++ b/packages/bot-engine/saveStateToDatabase.ts @@ -17,7 +17,7 @@ type Props = { clientSideActions: ContinueChatResponse['clientSideActions'] visitedEdges: VisitedEdge[] setVariableHistory: SetVariableHistoryItem[] - hasCustomEmbedBubble?: boolean + hasEmbedBubbleWithWaitEvent?: boolean initialSessionId?: string } @@ -28,7 +28,7 @@ export const saveStateToDatabase = async ({ clientSideActions, visitedEdges, setVariableHistory, - hasCustomEmbedBubble, + hasEmbedBubbleWithWaitEvent, initialSessionId, }: Props) => { const containsSetVariableClientSideAction = clientSideActions?.some( @@ -36,7 +36,9 @@ export const saveStateToDatabase = async ({ ) const isCompleted = Boolean( - !input && !containsSetVariableClientSideAction && !hasCustomEmbedBubble + !input && + !containsSetVariableClientSideAction && + !hasEmbedBubbleWithWaitEvent ) const queries: Prisma.PrismaPromise[] = [] diff --git a/packages/embeds/js/package.json b/packages/embeds/js/package.json index e7468c3fa..fff491368 100644 --- a/packages/embeds/js/package.json +++ b/packages/embeds/js/package.json @@ -1,6 +1,6 @@ { "name": "@typebot.io/js", - "version": "0.2.88", + "version": "0.2.89", "description": "Javascript library to display typebots on your website", "type": "module", "main": "dist/index.js", diff --git a/packages/embeds/js/src/components/bubbles/HostBubble.tsx b/packages/embeds/js/src/components/bubbles/HostBubble.tsx index 99056677d..6c883843d 100644 --- a/packages/embeds/js/src/components/bubbles/HostBubble.tsx +++ b/packages/embeds/js/src/components/bubbles/HostBubble.tsx @@ -51,6 +51,7 @@ export const HostBubble = (props: Props) => ( diff --git a/packages/embeds/js/src/features/blocks/bubbles/embed/components/EmbedBubble.tsx b/packages/embeds/js/src/features/blocks/bubbles/embed/components/EmbedBubble.tsx index 861d7968d..84a241bae 100644 --- a/packages/embeds/js/src/features/blocks/bubbles/embed/components/EmbedBubble.tsx +++ b/packages/embeds/js/src/features/blocks/bubbles/embed/components/EmbedBubble.tsx @@ -4,10 +4,12 @@ import { createSignal, onCleanup, onMount } from 'solid-js' import { clsx } from 'clsx' import { EmbedBubbleBlock } from '@typebot.io/schemas' import { defaultEmbedBubbleContent } from '@typebot.io/schemas/features/blocks/bubbles/embed/constants' +import { isNotEmpty } from '@typebot.io/lib/utils' type Props = { content: EmbedBubbleBlock['content'] onTransitionEnd?: (ref?: HTMLDivElement) => void + onCompleted?: (data?: string) => void } let typingTimeout: NodeJS.Timeout @@ -20,9 +22,29 @@ export const EmbedBubble = (props: Props) => { props.onTransitionEnd ? true : false ) + const handleMessage = ( + event: MessageEvent<{ name?: string; data?: string }> + ) => { + if ( + props.content?.waitForEvent?.isEnabled && + isNotEmpty(event.data.name) && + event.data.name === props.content?.waitForEvent.name + ) { + props.onCompleted?.( + props.content.waitForEvent.saveDataInVariableId && event.data.data + ? event.data.data + : undefined + ) + window.removeEventListener('message', handleMessage) + } + } + onMount(() => { typingTimeout = setTimeout(() => { setIsTyping(false) + if (props.content?.waitForEvent?.isEnabled) { + window.addEventListener('message', handleMessage) + } setTimeout(() => { props.onTransitionEnd?.(ref) }, showAnimationDuration) @@ -31,6 +53,7 @@ export const EmbedBubble = (props: Props) => { onCleanup(() => { if (typingTimeout) clearTimeout(typingTimeout) + window.removeEventListener('message', handleMessage) }) return ( diff --git a/packages/embeds/nextjs/package.json b/packages/embeds/nextjs/package.json index 935d2f802..226d259c8 100644 --- a/packages/embeds/nextjs/package.json +++ b/packages/embeds/nextjs/package.json @@ -1,6 +1,6 @@ { "name": "@typebot.io/nextjs", - "version": "0.2.88", + "version": "0.2.89", "description": "Convenient library to display typebots on your Next.js website", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/embeds/react/package.json b/packages/embeds/react/package.json index f2d3e9f4d..77350456d 100644 --- a/packages/embeds/react/package.json +++ b/packages/embeds/react/package.json @@ -1,6 +1,6 @@ { "name": "@typebot.io/react", - "version": "0.2.88", + "version": "0.2.89", "description": "Convenient library to display typebots on your React app", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/schemas/features/blocks/bubbles/embed/schema.ts b/packages/schemas/features/blocks/bubbles/embed/schema.ts index a58d92f2b..834704535 100644 --- a/packages/schemas/features/blocks/bubbles/embed/schema.ts +++ b/packages/schemas/features/blocks/bubbles/embed/schema.ts @@ -6,6 +6,13 @@ import { BubbleBlockType } from '../constants' export const embedBubbleContentSchema = z.object({ url: z.string().optional(), height: z.number().or(variableStringSchema).optional(), + waitForEvent: z + .object({ + isEnabled: z.boolean().optional(), + name: z.string().optional(), + saveDataInVariableId: z.string().optional(), + }) + .optional(), }) export const embedBubbleBlockSchema = blockBaseSchema.merge( diff --git a/packages/schemas/features/chat/schema.ts b/packages/schemas/features/chat/schema.ts index 828fb3299..5000698ab 100644 --- a/packages/schemas/features/chat/schema.ts +++ b/packages/schemas/features/chat/schema.ts @@ -16,7 +16,6 @@ import { import { logSchema } from '../result' import { settingsSchema, themeSchema } from '../typebot' import { - textBubbleContentSchema, imageBubbleContentSchema, videoBubbleContentSchema, audioBubbleContentSchema,