@ -15,25 +15,23 @@ const defaultItem = {
|
|||||||
id: createId(),
|
id: createId(),
|
||||||
}
|
}
|
||||||
|
|
||||||
type ItemWithId<T> = T & { id: string }
|
|
||||||
|
|
||||||
export type TableListItemProps<T> = {
|
export type TableListItemProps<T> = {
|
||||||
item: T
|
item: T
|
||||||
onItemChange: (item: T) => void
|
onItemChange: (item: T) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
type Props<T> = {
|
type Props<T extends object> = {
|
||||||
initialItems?: ItemWithId<T>[]
|
initialItems?: T[]
|
||||||
isOrdered?: boolean
|
isOrdered?: boolean
|
||||||
addLabel?: string
|
addLabel?: string
|
||||||
newItemDefaultProps?: Partial<T>
|
newItemDefaultProps?: Partial<T>
|
||||||
hasDefaultItem?: boolean
|
hasDefaultItem?: boolean
|
||||||
ComponentBetweenItems?: (props: unknown) => JSX.Element
|
ComponentBetweenItems?: (props: unknown) => JSX.Element
|
||||||
onItemsChange: (items: ItemWithId<T>[]) => void
|
onItemsChange: (items: T[]) => void
|
||||||
children: (props: TableListItemProps<T>) => JSX.Element
|
children: (props: TableListItemProps<T>) => JSX.Element
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TableList = <T,>({
|
export const TableList = <T extends object>({
|
||||||
initialItems,
|
initialItems,
|
||||||
isOrdered,
|
isOrdered,
|
||||||
addLabel = 'Add',
|
addLabel = 'Add',
|
||||||
@ -45,7 +43,7 @@ export const TableList = <T,>({
|
|||||||
}: Props<T>) => {
|
}: Props<T>) => {
|
||||||
const [items, setItems] = useState(
|
const [items, setItems] = useState(
|
||||||
addIdsIfMissing(initialItems) ??
|
addIdsIfMissing(initialItems) ??
|
||||||
(hasDefaultItem ? ([defaultItem] as ItemWithId<T>[]) : [])
|
(hasDefaultItem ? ([defaultItem] as T[]) : [])
|
||||||
)
|
)
|
||||||
const [showDeleteIndex, setShowDeleteIndex] = useState<number | null>(null)
|
const [showDeleteIndex, setShowDeleteIndex] = useState<number | null>(null)
|
||||||
|
|
||||||
@ -56,14 +54,14 @@ export const TableList = <T,>({
|
|||||||
|
|
||||||
const createItem = () => {
|
const createItem = () => {
|
||||||
const id = createId()
|
const id = createId()
|
||||||
const newItem = { id, ...newItemDefaultProps } as ItemWithId<T>
|
const newItem = { id, ...newItemDefaultProps } as T
|
||||||
setItems([...items, newItem])
|
setItems([...items, newItem])
|
||||||
onItemsChange([...items, newItem])
|
onItemsChange([...items, newItem])
|
||||||
}
|
}
|
||||||
|
|
||||||
const insertItem = (itemIndex: number) => () => {
|
const insertItem = (itemIndex: number) => () => {
|
||||||
const id = createId()
|
const id = createId()
|
||||||
const newItem = { id } as ItemWithId<T>
|
const newItem = { id } as T
|
||||||
const newItems = [...items]
|
const newItems = [...items]
|
||||||
newItems.splice(itemIndex + 1, 0, newItem)
|
newItems.splice(itemIndex + 1, 0, newItem)
|
||||||
setItems(newItems)
|
setItems(newItems)
|
||||||
@ -96,7 +94,7 @@ export const TableList = <T,>({
|
|||||||
return (
|
return (
|
||||||
<Stack spacing={0}>
|
<Stack spacing={0}>
|
||||||
{items.map((item, itemIndex) => (
|
{items.map((item, itemIndex) => (
|
||||||
<Box key={item.id}>
|
<Box key={'id' in item ? (item.id as string) : itemIndex}>
|
||||||
{itemIndex !== 0 && ComponentBetweenItems && (
|
{itemIndex !== 0 && ComponentBetweenItems && (
|
||||||
<ComponentBetweenItems />
|
<ComponentBetweenItems />
|
||||||
)}
|
)}
|
||||||
@ -185,7 +183,7 @@ export const TableList = <T,>({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const addIdsIfMissing = <T,>(items?: T[]): ItemWithId<T>[] | undefined =>
|
const addIdsIfMissing = <T,>(items?: T[]): T[] | undefined =>
|
||||||
items?.map((item) => ({
|
items?.map((item) => ({
|
||||||
id: createId(),
|
id: createId(),
|
||||||
...item,
|
...item,
|
||||||
|
@ -1,14 +1,29 @@
|
|||||||
import { useTranslate } from '@tolgee/react'
|
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 { EmbedBubbleBlock } from '@typebot.io/schemas'
|
||||||
|
import { SetVariableLabel } from '@/components/SetVariableLabel'
|
||||||
|
import { useTypebot } from '@/features/editor/providers/TypebotProvider'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
block: EmbedBubbleBlock
|
block: EmbedBubbleBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
export const EmbedBubbleContent = ({ block }: Props) => {
|
export const EmbedBubbleContent = ({ block }: Props) => {
|
||||||
|
const { typebot } = useTypebot()
|
||||||
const { t } = useTranslate()
|
const { t } = useTranslate()
|
||||||
if (!block.content?.url)
|
if (!block.content?.url)
|
||||||
return <Text color="gray.500">{t('clickToEdit')}</Text>
|
return <Text color="gray.500">{t('clickToEdit')}</Text>
|
||||||
return <Text>{t('editor.blocks.bubbles.embed.node.show.text')}</Text>
|
return (
|
||||||
|
<Stack>
|
||||||
|
<Text>{t('editor.blocks.bubbles.embed.node.show.text')}</Text>
|
||||||
|
{typebot &&
|
||||||
|
block.content.waitForEvent?.isEnabled &&
|
||||||
|
block.content.waitForEvent.saveDataInVariableId && (
|
||||||
|
<SetVariableLabel
|
||||||
|
variables={typebot.variables}
|
||||||
|
variableId={block.content.waitForEvent.saveDataInVariableId}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import { TextInput, NumberInput } from '@/components/inputs'
|
import { TextInput, NumberInput } from '@/components/inputs'
|
||||||
import { Stack, Text } from '@chakra-ui/react'
|
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 { sanitizeUrl } from '@typebot.io/lib'
|
||||||
import { useTranslate } from '@tolgee/react'
|
import { useTranslate } from '@tolgee/react'
|
||||||
import { defaultEmbedBubbleContent } from '@typebot.io/schemas/features/blocks/bubbles/embed/constants'
|
import { defaultEmbedBubbleContent } from '@typebot.io/schemas/features/blocks/bubbles/embed/constants'
|
||||||
|
import { SwitchWithRelatedSettings } from '@/components/SwitchWithRelatedSettings'
|
||||||
|
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
content: EmbedBubbleBlock['content']
|
content: EmbedBubbleBlock['content']
|
||||||
@ -23,6 +25,24 @@ export const EmbedUploadContent = ({ content, onSubmit }: Props) => {
|
|||||||
height?: NonNullable<EmbedBubbleBlock['content']>['height']
|
height?: NonNullable<EmbedBubbleBlock['content']>['height']
|
||||||
) => height && onSubmit({ ...content, 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<Variable, 'id'>) =>
|
||||||
|
onSubmit({
|
||||||
|
...content,
|
||||||
|
waitForEvent: {
|
||||||
|
...content?.waitForEvent,
|
||||||
|
saveDataInVariableId: variable?.id,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack p="2" spacing={6}>
|
<Stack p="2" spacing={6}>
|
||||||
<Stack>
|
<Stack>
|
||||||
@ -43,8 +63,25 @@ export const EmbedUploadContent = ({ content, onSubmit }: Props) => {
|
|||||||
defaultValue={content?.height ?? defaultEmbedBubbleContent.height}
|
defaultValue={content?.height ?? defaultEmbedBubbleContent.height}
|
||||||
onValueChange={handleHeightChange}
|
onValueChange={handleHeightChange}
|
||||||
suffix={t('editor.blocks.bubbles.embed.settings.numberInput.unit')}
|
suffix={t('editor.blocks.bubbles.embed.settings.numberInput.unit')}
|
||||||
width="150px"
|
direction="row"
|
||||||
/>
|
/>
|
||||||
|
<SwitchWithRelatedSettings
|
||||||
|
label="Wait for event?"
|
||||||
|
initialValue={content?.waitForEvent?.isEnabled ?? false}
|
||||||
|
onCheckChange={updateWaitForEventEnabled}
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
direction="row"
|
||||||
|
label="Name:"
|
||||||
|
defaultValue={content?.waitForEvent?.name}
|
||||||
|
onChange={updateWaitEventName}
|
||||||
|
/>
|
||||||
|
<VariableSearchInput
|
||||||
|
onSelectVariable={updateSaveDataInVariableId}
|
||||||
|
initialVariableId={content?.waitForEvent?.saveDataInVariableId}
|
||||||
|
label="Save data in variable"
|
||||||
|
/>
|
||||||
|
</SwitchWithRelatedSettings>
|
||||||
</Stack>
|
</Stack>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -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.
|
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.
|
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.
|
||||||
|
|
||||||
|
<Frame>
|
||||||
|
<img
|
||||||
|
src="/images/blocks/bubbles/embed-wait.jpg"
|
||||||
|
alt="Embed bubble"
|
||||||
|
className="rounded-lg"
|
||||||
|
/>
|
||||||
|
</Frame>
|
||||||
|
BIN
apps/docs/images/blocks/bubbles/embed-wait.jpg
Normal file
BIN
apps/docs/images/blocks/bubbles/embed-wait.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 90 KiB |
@ -11,6 +11,7 @@ import { restartSession } from '@typebot.io/bot-engine/queries/restartSession'
|
|||||||
import { continueBotFlow } from '@typebot.io/bot-engine/continueBotFlow'
|
import { continueBotFlow } from '@typebot.io/bot-engine/continueBotFlow'
|
||||||
import { parseDynamicTheme } from '@typebot.io/bot-engine/parseDynamicTheme'
|
import { parseDynamicTheme } from '@typebot.io/bot-engine/parseDynamicTheme'
|
||||||
import { isDefined } from '@typebot.io/lib/utils'
|
import { isDefined } from '@typebot.io/lib/utils'
|
||||||
|
import { BubbleBlockType } from '@typebot.io/schemas/features/blocks/bubbles/constants'
|
||||||
|
|
||||||
export const sendMessageV1 = publicProcedure
|
export const sendMessageV1 = publicProcedure
|
||||||
.meta({
|
.meta({
|
||||||
@ -136,8 +137,11 @@ export const sendMessageV1 = publicProcedure
|
|||||||
logs: allLogs,
|
logs: allLogs,
|
||||||
clientSideActions,
|
clientSideActions,
|
||||||
visitedEdges,
|
visitedEdges,
|
||||||
hasCustomEmbedBubble: messages.some(
|
hasEmbedBubbleWithWaitEvent: messages.some(
|
||||||
(message) => message.type === 'custom-embed'
|
(message) =>
|
||||||
|
message.type === 'custom-embed' ||
|
||||||
|
(message.type === BubbleBlockType.EMBED &&
|
||||||
|
message.content.waitForEvent?.isEnabled)
|
||||||
),
|
),
|
||||||
setVariableHistory,
|
setVariableHistory,
|
||||||
})
|
})
|
||||||
@ -199,8 +203,11 @@ export const sendMessageV1 = publicProcedure
|
|||||||
logs: allLogs,
|
logs: allLogs,
|
||||||
clientSideActions,
|
clientSideActions,
|
||||||
visitedEdges,
|
visitedEdges,
|
||||||
hasCustomEmbedBubble: messages.some(
|
hasEmbedBubbleWithWaitEvent: messages.some(
|
||||||
(message) => message.type === 'custom-embed'
|
(message) =>
|
||||||
|
message.type === 'custom-embed' ||
|
||||||
|
(message.type === BubbleBlockType.EMBED &&
|
||||||
|
message.content.waitForEvent?.isEnabled)
|
||||||
),
|
),
|
||||||
setVariableHistory,
|
setVariableHistory,
|
||||||
})
|
})
|
||||||
|
@ -11,6 +11,7 @@ import {
|
|||||||
chatReplySchema,
|
chatReplySchema,
|
||||||
sendMessageInputSchema,
|
sendMessageInputSchema,
|
||||||
} from '@typebot.io/schemas/features/chat/legacy/schema'
|
} from '@typebot.io/schemas/features/chat/legacy/schema'
|
||||||
|
import { BubbleBlockType } from '@typebot.io/schemas/features/blocks/bubbles/constants'
|
||||||
|
|
||||||
export const sendMessageV2 = publicProcedure
|
export const sendMessageV2 = publicProcedure
|
||||||
.meta({
|
.meta({
|
||||||
@ -136,8 +137,11 @@ export const sendMessageV2 = publicProcedure
|
|||||||
logs: allLogs,
|
logs: allLogs,
|
||||||
clientSideActions,
|
clientSideActions,
|
||||||
visitedEdges,
|
visitedEdges,
|
||||||
hasCustomEmbedBubble: messages.some(
|
hasEmbedBubbleWithWaitEvent: messages.some(
|
||||||
(message) => message.type === 'custom-embed'
|
(message) =>
|
||||||
|
message.type === 'custom-embed' ||
|
||||||
|
(message.type === BubbleBlockType.EMBED &&
|
||||||
|
message.content.waitForEvent?.isEnabled)
|
||||||
),
|
),
|
||||||
setVariableHistory,
|
setVariableHistory,
|
||||||
})
|
})
|
||||||
@ -198,8 +202,11 @@ export const sendMessageV2 = publicProcedure
|
|||||||
logs: allLogs,
|
logs: allLogs,
|
||||||
clientSideActions,
|
clientSideActions,
|
||||||
visitedEdges,
|
visitedEdges,
|
||||||
hasCustomEmbedBubble: messages.some(
|
hasEmbedBubbleWithWaitEvent: messages.some(
|
||||||
(message) => message.type === 'custom-embed'
|
(message) =>
|
||||||
|
message.type === 'custom-embed' ||
|
||||||
|
(message.type === BubbleBlockType.EMBED &&
|
||||||
|
message.content.waitForEvent?.isEnabled)
|
||||||
),
|
),
|
||||||
setVariableHistory,
|
setVariableHistory,
|
||||||
})
|
})
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import { TRPCError } from '@trpc/server'
|
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 { getSession } from '../queries/getSession'
|
||||||
import { continueBotFlow } from '../continueBotFlow'
|
import { continueBotFlow } from '../continueBotFlow'
|
||||||
import { filterPotentiallySensitiveLogs } from '../logs/filterPotentiallySensitiveLogs'
|
import { filterPotentiallySensitiveLogs } from '../logs/filterPotentiallySensitiveLogs'
|
||||||
import { parseDynamicTheme } from '../parseDynamicTheme'
|
import { parseDynamicTheme } from '../parseDynamicTheme'
|
||||||
import { saveStateToDatabase } from '../saveStateToDatabase'
|
import { saveStateToDatabase } from '../saveStateToDatabase'
|
||||||
import { computeCurrentProgress } from '../computeCurrentProgress'
|
import { computeCurrentProgress } from '../computeCurrentProgress'
|
||||||
|
import { BubbleBlockType } from '@typebot.io/schemas/features/blocks/bubbles/constants'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
origin: string | undefined
|
origin: string | undefined
|
||||||
@ -77,8 +78,11 @@ export const continueChat = async ({
|
|||||||
clientSideActions,
|
clientSideActions,
|
||||||
visitedEdges,
|
visitedEdges,
|
||||||
setVariableHistory,
|
setVariableHistory,
|
||||||
hasCustomEmbedBubble: messages.some(
|
hasEmbedBubbleWithWaitEvent: messages.some(
|
||||||
(message) => message.type === 'custom-embed'
|
(message) =>
|
||||||
|
message.type === 'custom-embed' ||
|
||||||
|
(message.type === BubbleBlockType.EMBED &&
|
||||||
|
message.content.waitForEvent?.isEnabled)
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
|
import { BubbleBlockType } from '@typebot.io/schemas/features/blocks/bubbles/constants'
|
||||||
import { computeCurrentProgress } from '../computeCurrentProgress'
|
import { computeCurrentProgress } from '../computeCurrentProgress'
|
||||||
import { filterPotentiallySensitiveLogs } from '../logs/filterPotentiallySensitiveLogs'
|
import { filterPotentiallySensitiveLogs } from '../logs/filterPotentiallySensitiveLogs'
|
||||||
import { restartSession } from '../queries/restartSession'
|
import { restartSession } from '../queries/restartSession'
|
||||||
import { saveStateToDatabase } from '../saveStateToDatabase'
|
import { saveStateToDatabase } from '../saveStateToDatabase'
|
||||||
import { startSession } from '../startSession'
|
import { startSession } from '../startSession'
|
||||||
|
import { isNotEmpty } from '@typebot.io/lib'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
origin: string | undefined
|
origin: string | undefined
|
||||||
@ -74,8 +76,11 @@ export const startChat = async ({
|
|||||||
clientSideActions,
|
clientSideActions,
|
||||||
visitedEdges,
|
visitedEdges,
|
||||||
setVariableHistory,
|
setVariableHistory,
|
||||||
hasCustomEmbedBubble: messages.some(
|
hasEmbedBubbleWithWaitEvent: messages.some(
|
||||||
(message) => message.type === 'custom-embed'
|
(message) =>
|
||||||
|
message.type === 'custom-embed' ||
|
||||||
|
(message.type === BubbleBlockType.EMBED &&
|
||||||
|
message.content.waitForEvent?.isEnabled)
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ import { restartSession } from '../queries/restartSession'
|
|||||||
import { saveStateToDatabase } from '../saveStateToDatabase'
|
import { saveStateToDatabase } from '../saveStateToDatabase'
|
||||||
import { startSession } from '../startSession'
|
import { startSession } from '../startSession'
|
||||||
import { computeCurrentProgress } from '../computeCurrentProgress'
|
import { computeCurrentProgress } from '../computeCurrentProgress'
|
||||||
|
import { BubbleBlockType } from '@typebot.io/schemas/features/blocks/bubbles/constants'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
message?: string
|
message?: string
|
||||||
@ -69,8 +70,11 @@ export const startChatPreview = async ({
|
|||||||
clientSideActions,
|
clientSideActions,
|
||||||
visitedEdges,
|
visitedEdges,
|
||||||
setVariableHistory,
|
setVariableHistory,
|
||||||
hasCustomEmbedBubble: messages.some(
|
hasEmbedBubbleWithWaitEvent: messages.some(
|
||||||
(message) => message.type === 'custom-embed'
|
(message) =>
|
||||||
|
message.type === 'custom-embed' ||
|
||||||
|
(message.type === BubbleBlockType.EMBED &&
|
||||||
|
message.content.waitForEvent?.isEnabled)
|
||||||
),
|
),
|
||||||
initialSessionId: sessionId,
|
initialSessionId: sessionId,
|
||||||
})
|
})
|
||||||
|
@ -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) {
|
if (variableToUpdate) {
|
||||||
|
@ -6,7 +6,7 @@ import {
|
|||||||
SessionState,
|
SessionState,
|
||||||
SetVariableHistoryItem,
|
SetVariableHistoryItem,
|
||||||
} from '@typebot.io/schemas'
|
} from '@typebot.io/schemas'
|
||||||
import { isNotEmpty } from '@typebot.io/lib'
|
import { isEmpty, isNotEmpty } from '@typebot.io/lib'
|
||||||
import {
|
import {
|
||||||
isBubbleBlock,
|
isBubbleBlock,
|
||||||
isInputBlock,
|
isInputBlock,
|
||||||
@ -32,6 +32,7 @@ import {
|
|||||||
BubbleBlockWithDefinedContent,
|
BubbleBlockWithDefinedContent,
|
||||||
parseBubbleBlock,
|
parseBubbleBlock,
|
||||||
} from './parseBubbleBlock'
|
} from './parseBubbleBlock'
|
||||||
|
import { BubbleBlockType } from '@typebot.io/schemas/features/blocks/bubbles/constants'
|
||||||
|
|
||||||
type ContextProps = {
|
type ContextProps = {
|
||||||
version: 1 | 2
|
version: 1 | 2
|
||||||
@ -95,14 +96,30 @@ export const executeGroup = async (
|
|||||||
|
|
||||||
if (isBubbleBlock(block)) {
|
if (isBubbleBlock(block)) {
|
||||||
if (!block.content || (firstBubbleWasStreamed && index === 0)) continue
|
if (!block.content || (firstBubbleWasStreamed && index === 0)) continue
|
||||||
messages.push(
|
const message = parseBubbleBlock(block as BubbleBlockWithDefinedContent, {
|
||||||
parseBubbleBlock(block as BubbleBlockWithDefinedContent, {
|
version,
|
||||||
version,
|
variables: newSessionState.typebotsQueue[0].typebot.variables,
|
||||||
variables: newSessionState.typebotsQueue[0].typebot.variables,
|
typebotVersion: newSessionState.typebotsQueue[0].typebot.version,
|
||||||
typebotVersion: newSessionState.typebotsQueue[0].typebot.version,
|
textBubbleContentFormat,
|
||||||
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
|
lastBubbleBlockId = block.id
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ type Props = {
|
|||||||
clientSideActions: ContinueChatResponse['clientSideActions']
|
clientSideActions: ContinueChatResponse['clientSideActions']
|
||||||
visitedEdges: VisitedEdge[]
|
visitedEdges: VisitedEdge[]
|
||||||
setVariableHistory: SetVariableHistoryItem[]
|
setVariableHistory: SetVariableHistoryItem[]
|
||||||
hasCustomEmbedBubble?: boolean
|
hasEmbedBubbleWithWaitEvent?: boolean
|
||||||
initialSessionId?: string
|
initialSessionId?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ export const saveStateToDatabase = async ({
|
|||||||
clientSideActions,
|
clientSideActions,
|
||||||
visitedEdges,
|
visitedEdges,
|
||||||
setVariableHistory,
|
setVariableHistory,
|
||||||
hasCustomEmbedBubble,
|
hasEmbedBubbleWithWaitEvent,
|
||||||
initialSessionId,
|
initialSessionId,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const containsSetVariableClientSideAction = clientSideActions?.some(
|
const containsSetVariableClientSideAction = clientSideActions?.some(
|
||||||
@ -36,7 +36,9 @@ export const saveStateToDatabase = async ({
|
|||||||
)
|
)
|
||||||
|
|
||||||
const isCompleted = Boolean(
|
const isCompleted = Boolean(
|
||||||
!input && !containsSetVariableClientSideAction && !hasCustomEmbedBubble
|
!input &&
|
||||||
|
!containsSetVariableClientSideAction &&
|
||||||
|
!hasEmbedBubbleWithWaitEvent
|
||||||
)
|
)
|
||||||
|
|
||||||
const queries: Prisma.PrismaPromise<any>[] = []
|
const queries: Prisma.PrismaPromise<any>[] = []
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@typebot.io/js",
|
"name": "@typebot.io/js",
|
||||||
"version": "0.2.88",
|
"version": "0.2.89",
|
||||||
"description": "Javascript library to display typebots on your website",
|
"description": "Javascript library to display typebots on your website",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
|
@ -51,6 +51,7 @@ export const HostBubble = (props: Props) => (
|
|||||||
<EmbedBubble
|
<EmbedBubble
|
||||||
content={props.message.content as EmbedBubbleBlock['content']}
|
content={props.message.content as EmbedBubbleBlock['content']}
|
||||||
onTransitionEnd={props.onTransitionEnd}
|
onTransitionEnd={props.onTransitionEnd}
|
||||||
|
onCompleted={props.onCompleted}
|
||||||
/>
|
/>
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={props.message.type === 'custom-embed'}>
|
<Match when={props.message.type === 'custom-embed'}>
|
||||||
|
@ -4,10 +4,12 @@ import { createSignal, onCleanup, onMount } from 'solid-js'
|
|||||||
import { clsx } from 'clsx'
|
import { clsx } from 'clsx'
|
||||||
import { EmbedBubbleBlock } from '@typebot.io/schemas'
|
import { EmbedBubbleBlock } from '@typebot.io/schemas'
|
||||||
import { defaultEmbedBubbleContent } from '@typebot.io/schemas/features/blocks/bubbles/embed/constants'
|
import { defaultEmbedBubbleContent } from '@typebot.io/schemas/features/blocks/bubbles/embed/constants'
|
||||||
|
import { isNotEmpty } from '@typebot.io/lib/utils'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
content: EmbedBubbleBlock['content']
|
content: EmbedBubbleBlock['content']
|
||||||
onTransitionEnd?: (ref?: HTMLDivElement) => void
|
onTransitionEnd?: (ref?: HTMLDivElement) => void
|
||||||
|
onCompleted?: (data?: string) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
let typingTimeout: NodeJS.Timeout
|
let typingTimeout: NodeJS.Timeout
|
||||||
@ -20,9 +22,29 @@ export const EmbedBubble = (props: Props) => {
|
|||||||
props.onTransitionEnd ? true : false
|
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(() => {
|
onMount(() => {
|
||||||
typingTimeout = setTimeout(() => {
|
typingTimeout = setTimeout(() => {
|
||||||
setIsTyping(false)
|
setIsTyping(false)
|
||||||
|
if (props.content?.waitForEvent?.isEnabled) {
|
||||||
|
window.addEventListener('message', handleMessage)
|
||||||
|
}
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
props.onTransitionEnd?.(ref)
|
props.onTransitionEnd?.(ref)
|
||||||
}, showAnimationDuration)
|
}, showAnimationDuration)
|
||||||
@ -31,6 +53,7 @@ export const EmbedBubble = (props: Props) => {
|
|||||||
|
|
||||||
onCleanup(() => {
|
onCleanup(() => {
|
||||||
if (typingTimeout) clearTimeout(typingTimeout)
|
if (typingTimeout) clearTimeout(typingTimeout)
|
||||||
|
window.removeEventListener('message', handleMessage)
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@typebot.io/nextjs",
|
"name": "@typebot.io/nextjs",
|
||||||
"version": "0.2.88",
|
"version": "0.2.89",
|
||||||
"description": "Convenient library to display typebots on your Next.js website",
|
"description": "Convenient library to display typebots on your Next.js website",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@typebot.io/react",
|
"name": "@typebot.io/react",
|
||||||
"version": "0.2.88",
|
"version": "0.2.89",
|
||||||
"description": "Convenient library to display typebots on your React app",
|
"description": "Convenient library to display typebots on your React app",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
|
@ -6,6 +6,13 @@ import { BubbleBlockType } from '../constants'
|
|||||||
export const embedBubbleContentSchema = z.object({
|
export const embedBubbleContentSchema = z.object({
|
||||||
url: z.string().optional(),
|
url: z.string().optional(),
|
||||||
height: z.number().or(variableStringSchema).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(
|
export const embedBubbleBlockSchema = blockBaseSchema.merge(
|
||||||
|
@ -16,7 +16,6 @@ import {
|
|||||||
import { logSchema } from '../result'
|
import { logSchema } from '../result'
|
||||||
import { settingsSchema, themeSchema } from '../typebot'
|
import { settingsSchema, themeSchema } from '../typebot'
|
||||||
import {
|
import {
|
||||||
textBubbleContentSchema,
|
|
||||||
imageBubbleContentSchema,
|
imageBubbleContentSchema,
|
||||||
videoBubbleContentSchema,
|
videoBubbleContentSchema,
|
||||||
audioBubbleContentSchema,
|
audioBubbleContentSchema,
|
||||||
|
Reference in New Issue
Block a user