@@ -25,9 +25,7 @@ import { useParentModal } from '@/features/graph/providers/ParentModalProvider'
|
|||||||
type Props = {
|
type Props = {
|
||||||
initialVariableId?: string
|
initialVariableId?: string
|
||||||
autoFocus?: boolean
|
autoFocus?: boolean
|
||||||
onSelectVariable: (
|
onSelectVariable: (variable: Pick<Variable, 'id' | 'name'>) => void
|
||||||
variable: Pick<Variable, 'id' | 'name'> | undefined
|
|
||||||
) => void
|
|
||||||
} & InputProps
|
} & InputProps
|
||||||
|
|
||||||
export const VariableSearchInput = ({
|
export const VariableSearchInput = ({
|
||||||
@@ -70,7 +68,6 @@ export const VariableSearchInput = ({
|
|||||||
const onInputChange = (e: ChangeEvent<HTMLInputElement>) => {
|
const onInputChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||||
setInputValue(e.target.value)
|
setInputValue(e.target.value)
|
||||||
if (e.target.value === '') {
|
if (e.target.value === '') {
|
||||||
onSelectVariable(undefined)
|
|
||||||
setFilteredItems([...variables.slice(0, 50)])
|
setFilteredItems([...variables.slice(0, 50)])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,16 +10,19 @@ import { useEffect, useState } from 'react'
|
|||||||
import { useDebouncedCallback } from 'use-debounce'
|
import { useDebouncedCallback } from 'use-debounce'
|
||||||
import { env } from 'utils'
|
import { env } from 'utils'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
value?: number
|
||||||
|
debounceTimeout?: number
|
||||||
|
withVariableButton?: boolean
|
||||||
|
onValueChange: (value?: number) => void
|
||||||
|
} & NumberInputProps
|
||||||
|
|
||||||
export const SmartNumberInput = ({
|
export const SmartNumberInput = ({
|
||||||
value,
|
value,
|
||||||
onValueChange,
|
onValueChange,
|
||||||
debounceTimeout = 1000,
|
debounceTimeout = 1000,
|
||||||
...props
|
...props
|
||||||
}: {
|
}: Props) => {
|
||||||
value?: number
|
|
||||||
debounceTimeout?: number
|
|
||||||
onValueChange: (value?: number) => void
|
|
||||||
} & NumberInputProps) => {
|
|
||||||
const [currentValue, setCurrentValue] = useState(value?.toString() ?? '')
|
const [currentValue, setCurrentValue] = useState(value?.toString() ?? '')
|
||||||
const debounced = useDebouncedCallback(
|
const debounced = useDebouncedCallback(
|
||||||
onValueChange,
|
onValueChange,
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { featherIconsBaseProps } from '@/components/icons'
|
||||||
|
import { Icon, IconProps, useColorModeValue } from '@chakra-ui/react'
|
||||||
|
|
||||||
|
export const WaitIcon = (props: IconProps) => (
|
||||||
|
<Icon
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
color={useColorModeValue('purple.500', 'purple.300')}
|
||||||
|
{...featherIconsBaseProps}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<circle cx="12" cy="12" r="10"></circle>
|
||||||
|
<polyline points="12 6 12 12 16 14"></polyline>
|
||||||
|
</Icon>
|
||||||
|
)
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { Text } from '@chakra-ui/react'
|
||||||
|
import { WaitOptions } from 'models'
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
options: WaitOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
export const WaitNodeContent = ({ options: { secondsToWaitFor } }: Props) => (
|
||||||
|
<Text color={secondsToWaitFor ? 'currentcolor' : 'gray.500'} noOfLines={1}>
|
||||||
|
{secondsToWaitFor ? `Wait for ${secondsToWaitFor}s` : 'Configure...'}
|
||||||
|
</Text>
|
||||||
|
)
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import { Stack } from '@chakra-ui/react'
|
||||||
|
import { WaitOptions } from 'models'
|
||||||
|
import React from 'react'
|
||||||
|
import { Input } from '@/components/inputs'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
options: WaitOptions
|
||||||
|
onOptionsChange: (options: WaitOptions) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export const WaitSettings = ({ options, onOptionsChange }: Props) => {
|
||||||
|
const handleSecondsChange = (secondsToWaitFor: string | undefined) => {
|
||||||
|
onOptionsChange({ ...options, secondsToWaitFor })
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Stack spacing={4}>
|
||||||
|
<Input
|
||||||
|
label="Seconds to wait for:"
|
||||||
|
defaultValue={options.secondsToWaitFor}
|
||||||
|
onChange={handleSecondsChange}
|
||||||
|
placeholder="0"
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
)
|
||||||
|
}
|
||||||
26
apps/builder/src/features/blocks/logic/wait/wait.spec.ts
Normal file
26
apps/builder/src/features/blocks/logic/wait/wait.spec.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import test, { expect } from '@playwright/test'
|
||||||
|
import { typebotViewer } from 'utils/playwright/testHelpers'
|
||||||
|
import { importTypebotInDatabase } from 'utils/playwright/databaseActions'
|
||||||
|
import cuid from 'cuid'
|
||||||
|
import { getTestAsset } from '@/test/utils/playwright'
|
||||||
|
|
||||||
|
const typebotId = cuid()
|
||||||
|
|
||||||
|
test.describe('Wait block', () => {
|
||||||
|
test('wait should trigger', async ({ page }) => {
|
||||||
|
await importTypebotInDatabase(getTestAsset('typebots/logic/wait.json'), {
|
||||||
|
id: typebotId,
|
||||||
|
})
|
||||||
|
|
||||||
|
await page.goto(`/typebots/${typebotId}/edit`)
|
||||||
|
await page.click('text=Configure...')
|
||||||
|
await page.getByRole('textbox', { name: 'Seconds to wait for:' }).fill('3')
|
||||||
|
|
||||||
|
await page.click('text=Preview')
|
||||||
|
await typebotViewer(page).locator('text=Wait now').click()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
|
await expect(typebotViewer(page).locator('text="Hi there!"')).toBeHidden()
|
||||||
|
await page.waitForTimeout(3000)
|
||||||
|
await expect(typebotViewer(page).locator('text="Hi there!"')).toBeVisible()
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -36,6 +36,7 @@ import { TextInputIcon } from '@/features/blocks/inputs/textInput'
|
|||||||
import { EmbedBubbleIcon } from '@/features/blocks/bubbles/embed'
|
import { EmbedBubbleIcon } from '@/features/blocks/bubbles/embed'
|
||||||
import { GoogleAnalyticsLogo } from '@/features/blocks/integrations/googleAnalytics'
|
import { GoogleAnalyticsLogo } from '@/features/blocks/integrations/googleAnalytics'
|
||||||
import { AudioBubbleIcon } from '@/features/blocks/bubbles/audio'
|
import { AudioBubbleIcon } from '@/features/blocks/bubbles/audio'
|
||||||
|
import { WaitIcon } from '@/features/blocks/logic/wait/components/WaitIcon'
|
||||||
|
|
||||||
type BlockIconProps = { type: BlockType } & IconProps
|
type BlockIconProps = { type: BlockType } & IconProps
|
||||||
|
|
||||||
@@ -82,6 +83,8 @@ export const BlockIcon = ({ type, ...props }: BlockIconProps) => {
|
|||||||
return <RedirectIcon color={purple} {...props} />
|
return <RedirectIcon color={purple} {...props} />
|
||||||
case LogicBlockType.CODE:
|
case LogicBlockType.CODE:
|
||||||
return <CodeIcon color={purple} {...props} />
|
return <CodeIcon color={purple} {...props} />
|
||||||
|
case LogicBlockType.WAIT:
|
||||||
|
return <WaitIcon color={purple} {...props} />
|
||||||
case LogicBlockType.TYPEBOT_LINK:
|
case LogicBlockType.TYPEBOT_LINK:
|
||||||
return <TypebotLinkIcon color={purple} {...props} />
|
return <TypebotLinkIcon color={purple} {...props} />
|
||||||
case IntegrationBlockType.GOOGLE_SHEETS:
|
case IntegrationBlockType.GOOGLE_SHEETS:
|
||||||
|
|||||||
@@ -77,6 +77,8 @@ export const BlockTypeLabel = ({ type }: Props): JSX.Element => {
|
|||||||
<Text>Typebot</Text>
|
<Text>Typebot</Text>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)
|
)
|
||||||
|
case LogicBlockType.WAIT:
|
||||||
|
return <Text>Wait</Text>
|
||||||
case IntegrationBlockType.GOOGLE_SHEETS:
|
case IntegrationBlockType.GOOGLE_SHEETS:
|
||||||
return (
|
return (
|
||||||
<Tooltip label="Google Sheets">
|
<Tooltip label="Google Sheets">
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import { SendEmailContent } from '@/features/blocks/integrations/sendEmail'
|
|||||||
import { isInputBlock, isChoiceInput, blockHasItems } from 'utils'
|
import { isInputBlock, isChoiceInput, blockHasItems } from 'utils'
|
||||||
import { MakeComContent } from '@/features/blocks/integrations/makeCom'
|
import { MakeComContent } from '@/features/blocks/integrations/makeCom'
|
||||||
import { AudioBubbleNode } from '@/features/blocks/bubbles/audio'
|
import { AudioBubbleNode } from '@/features/blocks/bubbles/audio'
|
||||||
|
import { WaitNodeContent } from '@/features/blocks/logic/wait/components/WaitNodeContent'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
block: Block | StartBlock
|
block: Block | StartBlock
|
||||||
@@ -120,6 +121,9 @@ export const BlockNodeContent = ({ block, indices }: Props): JSX.Element => {
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
case LogicBlockType.WAIT: {
|
||||||
|
return <WaitNodeContent options={block.options} />
|
||||||
|
}
|
||||||
case LogicBlockType.TYPEBOT_LINK:
|
case LogicBlockType.TYPEBOT_LINK:
|
||||||
return <TypebotLinkNode block={block} />
|
return <TypebotLinkNode block={block} />
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ const getHelpDocUrl = (blockType: BlockWithOptions['type']): string | null => {
|
|||||||
return 'https://docs.typebot.io/editor/blocks/logic/redirect'
|
return 'https://docs.typebot.io/editor/blocks/logic/redirect'
|
||||||
case LogicBlockType.CODE:
|
case LogicBlockType.CODE:
|
||||||
return 'https://docs.typebot.io/editor/blocks/logic/code'
|
return 'https://docs.typebot.io/editor/blocks/logic/code'
|
||||||
|
case LogicBlockType.WAIT:
|
||||||
|
return 'https://docs.typebot.io/editor/blocks/logic/wait'
|
||||||
case InputBlockType.TEXT:
|
case InputBlockType.TEXT:
|
||||||
return 'https://docs.typebot.io/editor/blocks/inputs/text'
|
return 'https://docs.typebot.io/editor/blocks/inputs/text'
|
||||||
case InputBlockType.NUMBER:
|
case InputBlockType.NUMBER:
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import { ButtonsOptionsForm } from '@/features/blocks/inputs/buttons'
|
|||||||
import { ChatwootSettingsForm } from '@/features/blocks/integrations/chatwoot'
|
import { ChatwootSettingsForm } from '@/features/blocks/integrations/chatwoot'
|
||||||
import { MakeComSettings } from '@/features/blocks/integrations/makeCom'
|
import { MakeComSettings } from '@/features/blocks/integrations/makeCom'
|
||||||
import { HelpDocButton } from './HelpDocButton'
|
import { HelpDocButton } from './HelpDocButton'
|
||||||
|
import { WaitSettings } from '@/features/blocks/logic/wait/components/WaitSettings'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
block: BlockWithOptions
|
block: BlockWithOptions
|
||||||
@@ -212,6 +213,14 @@ export const BlockSettings = ({
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
case LogicBlockType.WAIT: {
|
||||||
|
return (
|
||||||
|
<WaitSettings
|
||||||
|
options={block.options}
|
||||||
|
onOptionsChange={handleOptionsChange}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
case IntegrationBlockType.GOOGLE_SHEETS: {
|
case IntegrationBlockType.GOOGLE_SHEETS: {
|
||||||
return (
|
return (
|
||||||
<GoogleSheetsSettingsBody
|
<GoogleSheetsSettingsBody
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import {
|
|||||||
Item,
|
Item,
|
||||||
ItemType,
|
ItemType,
|
||||||
LogicBlockType,
|
LogicBlockType,
|
||||||
|
defaultWaitOptions,
|
||||||
} from 'models'
|
} from 'models'
|
||||||
import {
|
import {
|
||||||
stubLength,
|
stubLength,
|
||||||
@@ -434,6 +435,8 @@ const parseDefaultBlockOptions = (type: BlockWithOptionsType): BlockOptions => {
|
|||||||
return defaultRedirectOptions
|
return defaultRedirectOptions
|
||||||
case LogicBlockType.CODE:
|
case LogicBlockType.CODE:
|
||||||
return defaultCodeOptions
|
return defaultCodeOptions
|
||||||
|
case LogicBlockType.WAIT:
|
||||||
|
return defaultWaitOptions
|
||||||
case LogicBlockType.TYPEBOT_LINK:
|
case LogicBlockType.TYPEBOT_LINK:
|
||||||
return {}
|
return {}
|
||||||
case IntegrationBlockType.GOOGLE_SHEETS:
|
case IntegrationBlockType.GOOGLE_SHEETS:
|
||||||
|
|||||||
@@ -13,9 +13,7 @@ import React from 'react'
|
|||||||
import { VariableSearchInput } from '@/components/VariableSearchInput'
|
import { VariableSearchInput } from '@/components/VariableSearchInput'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onSelectVariable: (
|
onSelectVariable: (variable: Pick<Variable, 'name' | 'id'>) => void
|
||||||
variable: Pick<Variable, 'name' | 'id'> | undefined
|
|
||||||
) => void
|
|
||||||
} & Omit<IconButtonProps, 'aria-label'>
|
} & Omit<IconButtonProps, 'aria-label'>
|
||||||
|
|
||||||
export const VariablesButton = ({ onSelectVariable, ...props }: Props) => {
|
export const VariablesButton = ({ onSelectVariable, ...props }: Props) => {
|
||||||
|
|||||||
1
apps/builder/src/test/assets/typebots/logic/wait.json
Normal file
1
apps/builder/src/test/assets/typebots/logic/wait.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"id":"clddbpdus00011asqclyl0vlw","createdAt":"2023-01-26T16:42:16.803Z","updatedAt":"2023-01-26T16:48:53.712Z","icon":null,"name":"My typebot","publishedTypebotId":null,"folderId":null,"groups":[{"id":"clddbpduq002ssq1a2h622bw0","title":"Start","blocks":[{"id":"clddbpduq002tsq1aghl4dh31","type":"start","label":"Start","groupId":"clddbpduq002ssq1a2h622bw0","outgoingEdgeId":"clddbq3yp000l3b6ss15lu48v"}],"graphCoordinates":{"x":0,"y":0}},{"id":"clddbpito000e3b6spz6qqipa","title":"Group #1","blocks":[{"id":"clddbpito000f3b6srs0cizys","type":"choice input","items":[{"id":"clddbpito000g3b6snvioor95","type":0,"blockId":"clddbpito000f3b6srs0cizys","content":"Wait now"}],"groupId":"clddbpito000e3b6spz6qqipa","options":{"buttonLabel":"Send","isMultipleChoice":false}},{"id":"clddbw55x000m3b6svz34enqq","groupId":"clddbpito000e3b6spz6qqipa","type":"Wait","options":{"secondsToWaitFor":""},"outgoingEdgeId":"clddbw6l4000n3b6st6le0hu9"}],"graphCoordinates":{"x":357.49609375,"y":148.40625}},{"id":"clddbpwh9000i3b6s9e1vdjrd","title":"Group #2","blocks":[{"id":"clddbpwh9000j3b6srnzdpbcx","type":"text","content":{"html":"<div>Hi there!</div>","richText":[{"type":"p","children":[{"text":"Hi there!"}]}],"plainText":"Hi there!"},"groupId":"clddbpwh9000i3b6s9e1vdjrd"}],"graphCoordinates":{"x":545.25,"y":447.36328125}}],"variables":[],"edges":[{"id":"clddbq3yp000l3b6ss15lu48v","to":{"groupId":"clddbpito000e3b6spz6qqipa"},"from":{"blockId":"clddbpduq002tsq1aghl4dh31","groupId":"clddbpduq002ssq1a2h622bw0"}},{"from":{"groupId":"clddbpito000e3b6spz6qqipa","blockId":"clddbw55x000m3b6svz34enqq"},"to":{"groupId":"clddbpwh9000i3b6s9e1vdjrd"},"id":"clddbw6l4000n3b6st6le0hu9"}],"theme":{"chat":{"inputs":{"color":"#303235","backgroundColor":"#FFFFFF","placeholderColor":"#9095A0"},"buttons":{"color":"#FFFFFF","backgroundColor":"#0042DA"},"hostAvatar":{"url":"https://avatars.githubusercontent.com/u/16015833?v=4","isEnabled":true},"hostBubbles":{"color":"#303235","backgroundColor":"#F7F8FF"},"guestBubbles":{"color":"#FFFFFF","backgroundColor":"#FF8E21"}},"general":{"font":"Open Sans","background":{"type":"Color","content":"#ffffff"}}},"settings":{"general":{"isBrandingEnabled":false,"isInputPrefillEnabled":true,"isResultSavingEnabled":true,"isHideQueryParamsEnabled":true,"isNewResultOnRefreshEnabled":false},"metadata":{"description":"Build beautiful conversational forms and embed them directly in your applications without a line of code. Triple your response rate and collect answers that has more value compared to a traditional form."},"typingEmulation":{"speed":300,"enabled":true,"maxDelay":1.5}},"publicId":null,"customDomain":null,"workspaceId":"proWorkspace","resultsTablePreferences":null,"isArchived":false,"isClosed":false}
|
||||||
@@ -14,14 +14,6 @@ The "Code" block allows you to execute Javascript code. If you want to set a var
|
|||||||
window.location.reload()
|
window.location.reload()
|
||||||
```
|
```
|
||||||
|
|
||||||
### Wait for 3 seconds
|
|
||||||
|
|
||||||
By default, Promises will be awaited. So something like this will work:
|
|
||||||
|
|
||||||
```js
|
|
||||||
return new Promise((res) => setTimeout(res, 3000))
|
|
||||||
```
|
|
||||||
|
|
||||||
### Post a message to parent
|
### Post a message to parent
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
|||||||
9
apps/docs/docs/editor/blocks/logic/wait.md
Normal file
9
apps/docs/docs/editor/blocks/logic/wait.md
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# Wait
|
||||||
|
|
||||||
|
The "Wait" block allows you to pause the conversation for a certain amount of seconds.
|
||||||
|
|
||||||
|
This can be useful if you want the bot to emphasize on what's been said or to wait before a redirection for example to make sure the user has read everything.
|
||||||
|
|
||||||
|
:::caution
|
||||||
|
This should be used wisely. If you want the bot to write slower or faster in a more general sense, you need to check the [Typing emulation settings](/editor/settings#typing-emulation)
|
||||||
|
:::
|
||||||
@@ -1446,59 +1446,193 @@
|
|||||||
{
|
{
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
"allOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
"type": "object",
|
"allOf": [
|
||||||
"properties": {
|
{
|
||||||
"id": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"groupId": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"outgoingEdgeId": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"id",
|
|
||||||
"groupId"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"Code"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"options": {
|
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"name": {
|
"id": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"content": {
|
"groupId": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"shouldExecuteInParentContext": {
|
"outgoingEdgeId": {
|
||||||
"type": "boolean"
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"name"
|
"id",
|
||||||
|
"groupId"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"content": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"shouldExecuteInParentContext": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"name"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"type",
|
||||||
|
"options"
|
||||||
],
|
],
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
},
|
]
|
||||||
"required": [
|
},
|
||||||
"type",
|
{
|
||||||
"options"
|
"allOf": [
|
||||||
],
|
{
|
||||||
"additionalProperties": false
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"groupId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"outgoingEdgeId": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"groupId"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Condition"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"blockId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"outgoingEdgeId": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"blockId"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "number",
|
||||||
|
"enum": [
|
||||||
|
1
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"content": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"logicalOperator": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"OR",
|
||||||
|
"AND"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"comparisons": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"variableId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"comparisonOperator": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Equal to",
|
||||||
|
"Not equal",
|
||||||
|
"Contains",
|
||||||
|
"Greater than",
|
||||||
|
"Less than",
|
||||||
|
"Is set"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"logicalOperator",
|
||||||
|
"comparisons"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"type",
|
||||||
|
"content"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"type",
|
||||||
|
"items"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -1529,104 +1663,28 @@
|
|||||||
"type": {
|
"type": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": [
|
"enum": [
|
||||||
"Condition"
|
"Redirect"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"items": {
|
"options": {
|
||||||
"type": "array",
|
"type": "object",
|
||||||
"items": {
|
"properties": {
|
||||||
"allOf": [
|
"url": {
|
||||||
{
|
"type": "string"
|
||||||
"type": "object",
|
},
|
||||||
"properties": {
|
"isNewTab": {
|
||||||
"id": {
|
"type": "boolean"
|
||||||
"type": "string"
|
}
|
||||||
},
|
},
|
||||||
"blockId": {
|
"required": [
|
||||||
"type": "string"
|
"isNewTab"
|
||||||
},
|
],
|
||||||
"outgoingEdgeId": {
|
"additionalProperties": false
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"id",
|
|
||||||
"blockId"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"type": {
|
|
||||||
"type": "number",
|
|
||||||
"enum": [
|
|
||||||
1
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"content": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"logicalOperator": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"OR",
|
|
||||||
"AND"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"comparisons": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"id": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"variableId": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"comparisonOperator": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"Equal to",
|
|
||||||
"Not equal",
|
|
||||||
"Contains",
|
|
||||||
"Greater than",
|
|
||||||
"Less than",
|
|
||||||
"Is set"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"value": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"logicalOperator",
|
|
||||||
"comparisons"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"type",
|
|
||||||
"content"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"type",
|
"type",
|
||||||
"items"
|
"options"
|
||||||
],
|
],
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
@@ -1661,22 +1719,19 @@
|
|||||||
"type": {
|
"type": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": [
|
"enum": [
|
||||||
"Redirect"
|
"Typebot link"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"url": {
|
"typebotId": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"isNewTab": {
|
"groupId": {
|
||||||
"type": "boolean"
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
|
||||||
"isNewTab"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -1717,17 +1772,20 @@
|
|||||||
"type": {
|
"type": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": [
|
"enum": [
|
||||||
"Typebot link"
|
"Set variable"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"typebotId": {
|
"variableId": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"groupId": {
|
"expressionToEvaluate": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"isCode": {
|
||||||
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
@@ -1770,20 +1828,14 @@
|
|||||||
"type": {
|
"type": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": [
|
"enum": [
|
||||||
"Set variable"
|
"Wait"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"variableId": {
|
"secondsToWaitFor": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
|
||||||
"expressionToEvaluate": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"isCode": {
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
@@ -4406,168 +4458,232 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"logic": {
|
"clientSideActions": {
|
||||||
"type": "object",
|
"type": "array",
|
||||||
"properties": {
|
"items": {
|
||||||
"redirect": {
|
"anyOf": [
|
||||||
"type": "object",
|
{
|
||||||
"properties": {
|
"anyOf": [
|
||||||
"url": {
|
{
|
||||||
"type": "string"
|
"anyOf": [
|
||||||
},
|
{
|
||||||
"isNewTab": {
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"isNewTab"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
"codeToExecute": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"content": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"args": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"id": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"value": {
|
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
"not": {}
|
"type": "object",
|
||||||
},
|
"properties": {
|
||||||
{
|
"codeToExecute": {
|
||||||
"anyOf": [
|
"type": "object",
|
||||||
{
|
"properties": {
|
||||||
"anyOf": [
|
"content": {
|
||||||
{
|
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
{
|
"args": {
|
||||||
"type": "number"
|
"type": "array",
|
||||||
}
|
"items": {
|
||||||
]
|
"type": "object",
|
||||||
},
|
"properties": {
|
||||||
{
|
"id": {
|
||||||
"type": "boolean"
|
"type": "string"
|
||||||
}
|
},
|
||||||
]
|
"value": {
|
||||||
}
|
"anyOf": [
|
||||||
],
|
{
|
||||||
"nullable": true
|
"not": {}
|
||||||
}
|
},
|
||||||
},
|
{
|
||||||
"required": [
|
"anyOf": [
|
||||||
"id"
|
{
|
||||||
],
|
"anyOf": [
|
||||||
"additionalProperties": false
|
{
|
||||||
}
|
"type": "string"
|
||||||
}
|
},
|
||||||
},
|
{
|
||||||
"required": [
|
"type": "number"
|
||||||
"content",
|
}
|
||||||
"args"
|
]
|
||||||
],
|
},
|
||||||
"additionalProperties": false
|
{
|
||||||
}
|
"type": "boolean"
|
||||||
},
|
}
|
||||||
"additionalProperties": false
|
]
|
||||||
},
|
}
|
||||||
"integrations": {
|
],
|
||||||
"type": "object",
|
"nullable": true
|
||||||
"properties": {
|
}
|
||||||
"chatwoot": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"codeToExecute": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"content": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"args": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"id": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"value": {
|
|
||||||
"anyOf": [
|
|
||||||
{
|
|
||||||
"not": {}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"anyOf": [
|
|
||||||
{
|
|
||||||
"anyOf": [
|
|
||||||
{
|
|
||||||
"type": "string"
|
|
||||||
},
|
},
|
||||||
{
|
"required": [
|
||||||
"type": "number"
|
"id"
|
||||||
}
|
],
|
||||||
]
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"content",
|
||||||
|
"args"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"codeToExecute"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"redirect": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"url": {
|
||||||
|
"type": "string"
|
||||||
},
|
},
|
||||||
{
|
"isNewTab": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
]
|
},
|
||||||
|
"required": [
|
||||||
|
"isNewTab"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"redirect"
|
||||||
],
|
],
|
||||||
"nullable": true
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"chatwoot": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"codeToExecute": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"content": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"args": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"not": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nullable": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"content",
|
||||||
|
"args"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"codeToExecute"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"id"
|
"chatwoot"
|
||||||
],
|
],
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
}
|
]
|
||||||
},
|
},
|
||||||
"required": [
|
{
|
||||||
"content",
|
"type": "object",
|
||||||
"args"
|
"properties": {
|
||||||
],
|
"googleAnalytics": {
|
||||||
"additionalProperties": false
|
"type": "object",
|
||||||
}
|
"properties": {
|
||||||
|
"trackingId": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"category": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"action": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"googleAnalytics"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"required": [
|
{
|
||||||
"codeToExecute"
|
"type": "object",
|
||||||
],
|
"properties": {
|
||||||
"additionalProperties": false
|
"wait": {
|
||||||
},
|
"type": "object",
|
||||||
"googleAnalytics": {
|
"properties": {
|
||||||
"type": "object",
|
"secondsToWaitFor": {
|
||||||
"properties": {
|
"type": "number"
|
||||||
"trackingId": {
|
}
|
||||||
"type": "string"
|
},
|
||||||
|
"required": [
|
||||||
|
"secondsToWaitFor"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"category": {
|
"required": [
|
||||||
"type": "string"
|
"wait"
|
||||||
},
|
],
|
||||||
"action": {
|
"additionalProperties": false
|
||||||
"type": "string"
|
}
|
||||||
},
|
]
|
||||||
"label": {
|
}
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"value": {
|
|
||||||
"type": "number"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
},
|
||||||
"sessionId": {
|
"sessionId": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { ExecuteLogicResponse } from '@/features/chat'
|
||||||
|
import { parseVariables } from '@/features/variables'
|
||||||
|
import { SessionState, WaitBlock } from 'models'
|
||||||
|
|
||||||
|
export const executeWait = async (
|
||||||
|
{ typebot: { variables } }: SessionState,
|
||||||
|
block: WaitBlock
|
||||||
|
): Promise<ExecuteLogicResponse> => {
|
||||||
|
if (!block.options.secondsToWaitFor)
|
||||||
|
return { outgoingEdgeId: block.outgoingEdgeId }
|
||||||
|
const parsedSecondsToWaitFor = parseVariables(variables)(
|
||||||
|
block.options.secondsToWaitFor
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
outgoingEdgeId: block.outgoingEdgeId,
|
||||||
|
// @ts-expect-error isNaN can be used with strings
|
||||||
|
clientSideActions: isNaN(parsedSecondsToWaitFor)
|
||||||
|
? undefined
|
||||||
|
: [{ wait: { secondsToWaitFor: parsedSecondsToWaitFor } }],
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ import { executeCondition } from '@/features/blocks/logic/condition/api'
|
|||||||
import { executeRedirect } from '@/features/blocks/logic/redirect/api'
|
import { executeRedirect } from '@/features/blocks/logic/redirect/api'
|
||||||
import { executeSetVariable } from '@/features/blocks/logic/setVariable/api'
|
import { executeSetVariable } from '@/features/blocks/logic/setVariable/api'
|
||||||
import { executeTypebotLink } from '@/features/blocks/logic/typebotLink/api'
|
import { executeTypebotLink } from '@/features/blocks/logic/typebotLink/api'
|
||||||
|
import { executeWait } from '@/features/blocks/logic/wait/api/utils/executeWait'
|
||||||
import { LogicBlock, LogicBlockType, SessionState } from 'models'
|
import { LogicBlock, LogicBlockType, SessionState } from 'models'
|
||||||
import { ExecuteLogicResponse } from '../../types'
|
import { ExecuteLogicResponse } from '../../types'
|
||||||
|
|
||||||
@@ -20,5 +21,7 @@ export const executeLogic =
|
|||||||
return executeCode(state, block)
|
return executeCode(state, block)
|
||||||
case LogicBlockType.TYPEBOT_LINK:
|
case LogicBlockType.TYPEBOT_LINK:
|
||||||
return executeTypebotLink(state, block)
|
return executeTypebotLink(state, block)
|
||||||
|
case LogicBlockType.WAIT:
|
||||||
|
return executeWait(state, block)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export { executeWait } from './utils/executeWait'
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { parseVariables } from '@/features/variables'
|
||||||
|
import { LogicState } from '@/types'
|
||||||
|
import { WaitBlock } from 'models'
|
||||||
|
|
||||||
|
export const executeWait = async (
|
||||||
|
block: WaitBlock,
|
||||||
|
{ typebot: { variables } }: LogicState
|
||||||
|
) => {
|
||||||
|
if (!block.options.secondsToWaitFor) return block.outgoingEdgeId
|
||||||
|
const parsedSecondsToWaitFor = parseVariables(variables)(
|
||||||
|
block.options.secondsToWaitFor
|
||||||
|
)
|
||||||
|
// @ts-expect-error isNaN can be used with strings
|
||||||
|
if (isNaN(parsedSecondsToWaitFor)) return block.outgoingEdgeId
|
||||||
|
await new Promise((resolve) =>
|
||||||
|
setTimeout(resolve, parseInt(parsedSecondsToWaitFor) * 1000)
|
||||||
|
)
|
||||||
|
return block.outgoingEdgeId
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import { executeCondition } from '@/features/blocks/logic/condition'
|
|||||||
import { executeRedirect } from '@/features/blocks/logic/redirect'
|
import { executeRedirect } from '@/features/blocks/logic/redirect'
|
||||||
import { executeSetVariable } from '@/features/blocks/logic/setVariable'
|
import { executeSetVariable } from '@/features/blocks/logic/setVariable'
|
||||||
import { executeTypebotLink } from '@/features/blocks/logic/typebotLink'
|
import { executeTypebotLink } from '@/features/blocks/logic/typebotLink'
|
||||||
|
import { executeWait } from '@/features/blocks/logic/wait'
|
||||||
import { LinkedTypebot } from '@/providers/TypebotProvider'
|
import { LinkedTypebot } from '@/providers/TypebotProvider'
|
||||||
import { EdgeId, LogicState } from '@/types'
|
import { EdgeId, LogicState } from '@/types'
|
||||||
import { LogicBlock, LogicBlockType } from 'models'
|
import { LogicBlock, LogicBlockType } from 'models'
|
||||||
@@ -26,5 +27,7 @@ export const executeLogic = async (
|
|||||||
return { nextEdgeId: await executeCode(block, context) }
|
return { nextEdgeId: await executeCode(block, context) }
|
||||||
case LogicBlockType.TYPEBOT_LINK:
|
case LogicBlockType.TYPEBOT_LINK:
|
||||||
return executeTypebotLink(block, context)
|
return executeTypebotLink(block, context)
|
||||||
|
case LogicBlockType.WAIT:
|
||||||
|
return { nextEdgeId: await executeWait(block, context) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
type Props = {
|
||||||
|
secondsToWaitFor: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export const executeWait = async ({ secondsToWaitFor }: Props) => {
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, secondsToWaitFor * 1000))
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ import { executeChatwoot } from '@/features/blocks/integrations/chatwoot'
|
|||||||
import { executeGoogleAnalyticsBlock } from '@/features/blocks/integrations/googleAnalytics/utils/executeGoogleAnalytics'
|
import { executeGoogleAnalyticsBlock } from '@/features/blocks/integrations/googleAnalytics/utils/executeGoogleAnalytics'
|
||||||
import { executeCode } from '@/features/blocks/logic/code'
|
import { executeCode } from '@/features/blocks/logic/code'
|
||||||
import { executeRedirect } from '@/features/blocks/logic/redirect'
|
import { executeRedirect } from '@/features/blocks/logic/redirect'
|
||||||
|
import { executeWait } from '@/features/blocks/logic/wait/utils/executeWait'
|
||||||
import type { ChatReply } from 'models'
|
import type { ChatReply } from 'models'
|
||||||
|
|
||||||
export const executeClientSideAction = async (
|
export const executeClientSideAction = async (
|
||||||
@@ -19,4 +20,7 @@ export const executeClientSideAction = async (
|
|||||||
if ('redirect' in clientSideAction) {
|
if ('redirect' in clientSideAction) {
|
||||||
executeRedirect(clientSideAction.redirect)
|
executeRedirect(clientSideAction.redirect)
|
||||||
}
|
}
|
||||||
|
if ('wait' in clientSideAction) {
|
||||||
|
await executeWait(clientSideAction.wait)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,4 +4,5 @@ export enum LogicBlockType {
|
|||||||
REDIRECT = 'Redirect',
|
REDIRECT = 'Redirect',
|
||||||
CODE = 'Code',
|
CODE = 'Code',
|
||||||
TYPEBOT_LINK = 'Typebot link',
|
TYPEBOT_LINK = 'Typebot link',
|
||||||
|
WAIT = 'Wait',
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,3 +5,4 @@ export * from './logicBlock'
|
|||||||
export * from './redirect'
|
export * from './redirect'
|
||||||
export * from './setVariable'
|
export * from './setVariable'
|
||||||
export * from './typebotLink'
|
export * from './typebotLink'
|
||||||
|
export * from './wait'
|
||||||
|
|||||||
@@ -4,17 +4,20 @@ import { conditionBlockSchema } from './condition'
|
|||||||
import { redirectOptionsSchema, redirectBlockSchema } from './redirect'
|
import { redirectOptionsSchema, redirectBlockSchema } from './redirect'
|
||||||
import { setVariableOptionsSchema, setVariableBlockSchema } from './setVariable'
|
import { setVariableOptionsSchema, setVariableBlockSchema } from './setVariable'
|
||||||
import { typebotLinkOptionsSchema, typebotLinkBlockSchema } from './typebotLink'
|
import { typebotLinkOptionsSchema, typebotLinkBlockSchema } from './typebotLink'
|
||||||
|
import { waitBlockSchema, waitOptionsSchema } from './wait'
|
||||||
|
|
||||||
const logicBlockOptionsSchema = codeOptionsSchema
|
const logicBlockOptionsSchema = codeOptionsSchema
|
||||||
.or(redirectOptionsSchema)
|
.or(redirectOptionsSchema)
|
||||||
.or(setVariableOptionsSchema)
|
.or(setVariableOptionsSchema)
|
||||||
.or(typebotLinkOptionsSchema)
|
.or(typebotLinkOptionsSchema)
|
||||||
|
.or(waitOptionsSchema)
|
||||||
|
|
||||||
export const logicBlockSchema = codeBlockSchema
|
export const logicBlockSchema = codeBlockSchema
|
||||||
.or(conditionBlockSchema)
|
.or(conditionBlockSchema)
|
||||||
.or(redirectBlockSchema)
|
.or(redirectBlockSchema)
|
||||||
.or(typebotLinkBlockSchema)
|
.or(typebotLinkBlockSchema)
|
||||||
.or(setVariableBlockSchema)
|
.or(setVariableBlockSchema)
|
||||||
|
.or(waitBlockSchema)
|
||||||
|
|
||||||
export type LogicBlock = z.infer<typeof logicBlockSchema>
|
export type LogicBlock = z.infer<typeof logicBlockSchema>
|
||||||
export type LogicBlockOptions = z.infer<typeof logicBlockOptionsSchema>
|
export type LogicBlockOptions = z.infer<typeof logicBlockOptionsSchema>
|
||||||
|
|||||||
19
packages/models/features/blocks/logic/wait.ts
Normal file
19
packages/models/features/blocks/logic/wait.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { z } from 'zod'
|
||||||
|
import { blockBaseSchema } from '../baseSchemas'
|
||||||
|
import { LogicBlockType } from './enums'
|
||||||
|
|
||||||
|
export const waitOptionsSchema = z.object({
|
||||||
|
secondsToWaitFor: z.string().optional(),
|
||||||
|
})
|
||||||
|
|
||||||
|
export const waitBlockSchema = blockBaseSchema.and(
|
||||||
|
z.object({
|
||||||
|
type: z.enum([LogicBlockType.WAIT]),
|
||||||
|
options: waitOptionsSchema,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
export const defaultWaitOptions: WaitOptions = {}
|
||||||
|
|
||||||
|
export type WaitBlock = z.infer<typeof waitBlockSchema>
|
||||||
|
export type WaitOptions = z.infer<typeof waitOptionsSchema>
|
||||||
@@ -184,6 +184,13 @@ const clientSideActionSchema = z
|
|||||||
googleAnalytics: googleAnalyticsOptionsSchema,
|
googleAnalytics: googleAnalyticsOptionsSchema,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
.or(
|
||||||
|
z.object({
|
||||||
|
wait: z.object({
|
||||||
|
secondsToWaitFor: z.number(),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
export const chatReplySchema = z.object({
|
export const chatReplySchema = z.object({
|
||||||
messages: z.array(chatMessageSchema),
|
messages: z.array(chatMessageSchema),
|
||||||
|
|||||||
Reference in New Issue
Block a user