@@ -15,25 +15,23 @@ const defaultItem = {
|
||||
id: createId(),
|
||||
}
|
||||
|
||||
type ItemWithId<T> = T & { id: string }
|
||||
|
||||
export type TableListItemProps<T> = {
|
||||
item: T
|
||||
onItemChange: (item: T) => void
|
||||
}
|
||||
|
||||
type Props<T> = {
|
||||
initialItems?: ItemWithId<T>[]
|
||||
type Props<T extends object> = {
|
||||
initialItems?: T[]
|
||||
isOrdered?: boolean
|
||||
addLabel?: string
|
||||
newItemDefaultProps?: Partial<T>
|
||||
hasDefaultItem?: boolean
|
||||
ComponentBetweenItems?: (props: unknown) => JSX.Element
|
||||
onItemsChange: (items: ItemWithId<T>[]) => void
|
||||
onItemsChange: (items: T[]) => void
|
||||
children: (props: TableListItemProps<T>) => JSX.Element
|
||||
}
|
||||
|
||||
export const TableList = <T,>({
|
||||
export const TableList = <T extends object>({
|
||||
initialItems,
|
||||
isOrdered,
|
||||
addLabel = 'Add',
|
||||
@@ -45,7 +43,7 @@ export const TableList = <T,>({
|
||||
}: Props<T>) => {
|
||||
const [items, setItems] = useState(
|
||||
addIdsIfMissing(initialItems) ??
|
||||
(hasDefaultItem ? ([defaultItem] as ItemWithId<T>[]) : [])
|
||||
(hasDefaultItem ? ([defaultItem] as T[]) : [])
|
||||
)
|
||||
const [showDeleteIndex, setShowDeleteIndex] = useState<number | null>(null)
|
||||
|
||||
@@ -56,14 +54,14 @@ export const TableList = <T,>({
|
||||
|
||||
const createItem = () => {
|
||||
const id = createId()
|
||||
const newItem = { id, ...newItemDefaultProps } as ItemWithId<T>
|
||||
const newItem = { id, ...newItemDefaultProps } as T
|
||||
setItems([...items, newItem])
|
||||
onItemsChange([...items, newItem])
|
||||
}
|
||||
|
||||
const insertItem = (itemIndex: number) => () => {
|
||||
const id = createId()
|
||||
const newItem = { id } as ItemWithId<T>
|
||||
const newItem = { id } as T
|
||||
const newItems = [...items]
|
||||
newItems.splice(itemIndex + 1, 0, newItem)
|
||||
setItems(newItems)
|
||||
@@ -96,7 +94,7 @@ export const TableList = <T,>({
|
||||
return (
|
||||
<Stack spacing={0}>
|
||||
{items.map((item, itemIndex) => (
|
||||
<Box key={item.id}>
|
||||
<Box key={'id' in item ? (item.id as string) : itemIndex}>
|
||||
{itemIndex !== 0 && 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) => ({
|
||||
id: createId(),
|
||||
...item,
|
||||
|
||||
@@ -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 <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 { 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<EmbedBubbleBlock['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 (
|
||||
<Stack p="2" spacing={6}>
|
||||
<Stack>
|
||||
@@ -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"
|
||||
/>
|
||||
<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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
<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 { parseDynamicTheme } from '@typebot.io/bot-engine/parseDynamicTheme'
|
||||
import { isDefined } from '@typebot.io/lib/utils'
|
||||
import { BubbleBlockType } from '@typebot.io/schemas/features/blocks/bubbles/constants'
|
||||
|
||||
export const sendMessageV1 = publicProcedure
|
||||
.meta({
|
||||
@@ -136,8 +137,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,
|
||||
})
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user