🚸 (engine) Improve engine v2 client loading and timings
Client actions are triggered after the correct bubble block. If the send message request is longer than 1s we show a loading chunk Closes #276
This commit is contained in:
@@ -3231,7 +3231,19 @@
|
||||
"messages": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [
|
||||
"allOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -3239,36 +3251,65 @@
|
||||
{
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"text"
|
||||
]
|
||||
},
|
||||
"content": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"html": {
|
||||
"type": "string"
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"text"
|
||||
]
|
||||
},
|
||||
"plainText": {
|
||||
"type": "string"
|
||||
"content": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"html": {
|
||||
"type": "string"
|
||||
},
|
||||
"plainText": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"html",
|
||||
"plainText"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"html",
|
||||
"plainText"
|
||||
"type",
|
||||
"content"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"image"
|
||||
]
|
||||
},
|
||||
"content": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"content"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"content"
|
||||
],
|
||||
"additionalProperties": false
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
@@ -3276,7 +3317,7 @@
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"image"
|
||||
"video"
|
||||
]
|
||||
},
|
||||
"content": {
|
||||
@@ -3284,6 +3325,17 @@
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"url",
|
||||
"youtube",
|
||||
"vimeo"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
@@ -3303,7 +3355,7 @@
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"video"
|
||||
"audio"
|
||||
]
|
||||
},
|
||||
"content": {
|
||||
@@ -3311,17 +3363,6 @@
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"url",
|
||||
"youtube",
|
||||
"vimeo"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
@@ -3341,7 +3382,7 @@
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"audio"
|
||||
"embed"
|
||||
]
|
||||
},
|
||||
"content": {
|
||||
@@ -3349,8 +3390,14 @@
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string"
|
||||
},
|
||||
"height": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"height"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
@@ -3361,37 +3408,6 @@
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"embed"
|
||||
]
|
||||
},
|
||||
"content": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string"
|
||||
},
|
||||
"height": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"height"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"content"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -4461,7 +4477,16 @@
|
||||
"clientSideActions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"anyOf": [
|
||||
"allOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"lastBubbleBlockId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -4469,88 +4494,163 @@
|
||||
{
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"codeToExecute": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"content": {
|
||||
"type": "string"
|
||||
},
|
||||
"args": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"anyOf": [
|
||||
{
|
||||
"not": {}
|
||||
"codeToExecute": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"content": {
|
||||
"type": "string"
|
||||
},
|
||||
"args": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"value": {
|
||||
"anyOf": [
|
||||
{
|
||||
"not": {}
|
||||
},
|
||||
{
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "number"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "number"
|
||||
"type": "boolean"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
}
|
||||
]
|
||||
],
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id"
|
||||
],
|
||||
"nullable": true
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"content",
|
||||
"args"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"content",
|
||||
"args"
|
||||
"codeToExecute"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"redirect": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string"
|
||||
},
|
||||
"isNewTab": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"isNewTab"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"redirect"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"codeToExecute"
|
||||
],
|
||||
"additionalProperties": false
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"redirect": {
|
||||
"chatwoot": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string"
|
||||
},
|
||||
"isNewTab": {
|
||||
"type": "boolean"
|
||||
"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": [
|
||||
"isNewTab"
|
||||
"codeToExecute"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"redirect"
|
||||
"chatwoot"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -4559,71 +4659,30 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"chatwoot": {
|
||||
"googleAnalytics": {
|
||||
"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
|
||||
"trackingId": {
|
||||
"type": "string"
|
||||
},
|
||||
"category": {
|
||||
"type": "string"
|
||||
},
|
||||
"action": {
|
||||
"type": "string"
|
||||
},
|
||||
"label": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"codeToExecute"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"chatwoot"
|
||||
"googleAnalytics"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -4632,55 +4691,25 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"googleAnalytics": {
|
||||
"wait": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"trackingId": {
|
||||
"type": "string"
|
||||
},
|
||||
"category": {
|
||||
"type": "string"
|
||||
},
|
||||
"action": {
|
||||
"type": "string"
|
||||
},
|
||||
"label": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"secondsToWaitFor": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"secondsToWaitFor"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"googleAnalytics"
|
||||
"wait"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"wait": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"secondsToWaitFor": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"secondsToWaitFor"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"wait"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -51,13 +51,15 @@ if (window.$chatwoot) {
|
||||
|
||||
export const executeChatwootBlock = (
|
||||
{ typebot: { variables }, isPreview }: SessionState,
|
||||
block: ChatwootBlock
|
||||
block: ChatwootBlock,
|
||||
lastBubbleBlockId?: string
|
||||
): ExecuteIntegrationResponse => {
|
||||
const chatwootCode = parseChatwootOpenCode(block.options)
|
||||
return {
|
||||
outgoingEdgeId: block.outgoingEdgeId,
|
||||
clientSideActions: [
|
||||
{
|
||||
lastBubbleBlockId,
|
||||
chatwoot: {
|
||||
codeToExecute: {
|
||||
content: parseVariables(variables, { fieldToParse: 'id' })(
|
||||
|
||||
@@ -4,12 +4,14 @@ import { GoogleAnalyticsBlock, SessionState } from 'models'
|
||||
|
||||
export const executeGoogleAnalyticsBlock = (
|
||||
{ typebot: { variables } }: SessionState,
|
||||
block: GoogleAnalyticsBlock
|
||||
block: GoogleAnalyticsBlock,
|
||||
lastBubbleBlockId?: string
|
||||
): ExecuteIntegrationResponse => ({
|
||||
outgoingEdgeId: block.outgoingEdgeId,
|
||||
clientSideActions: [
|
||||
{
|
||||
googleAnalytics: deepParseVariable(variables)(block.options),
|
||||
lastBubbleBlockId,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
@@ -8,7 +8,8 @@ import { CodeBlock, SessionState } from 'models'
|
||||
|
||||
export const executeCode = (
|
||||
{ typebot: { variables } }: SessionState,
|
||||
block: CodeBlock
|
||||
block: CodeBlock,
|
||||
lastBubbleBlockId?: string
|
||||
): ExecuteLogicResponse => {
|
||||
if (!block.options.content) return { outgoingEdgeId: block.outgoingEdgeId }
|
||||
|
||||
@@ -30,6 +31,7 @@ export const executeCode = (
|
||||
content,
|
||||
args,
|
||||
},
|
||||
lastBubbleBlockId,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -5,13 +5,15 @@ import { sanitizeUrl } from 'utils'
|
||||
|
||||
export const executeRedirect = (
|
||||
{ typebot: { variables } }: SessionState,
|
||||
block: RedirectBlock
|
||||
block: RedirectBlock,
|
||||
lastBubbleBlockId?: string
|
||||
): ExecuteLogicResponse => {
|
||||
if (!block.options?.url) return { outgoingEdgeId: block.outgoingEdgeId }
|
||||
const formattedUrl = sanitizeUrl(parseVariables(variables)(block.options.url))
|
||||
return {
|
||||
clientSideActions: [
|
||||
{
|
||||
lastBubbleBlockId,
|
||||
redirect: { url: formattedUrl, isNewTab: block.options.isNewTab },
|
||||
},
|
||||
],
|
||||
|
||||
@@ -4,19 +4,29 @@ import { SessionState, WaitBlock } from 'models'
|
||||
|
||||
export const executeWait = async (
|
||||
{ typebot: { variables } }: SessionState,
|
||||
block: WaitBlock
|
||||
block: WaitBlock,
|
||||
lastBubbleBlockId?: string
|
||||
): Promise<ExecuteLogicResponse> => {
|
||||
if (!block.options.secondsToWaitFor)
|
||||
return { outgoingEdgeId: block.outgoingEdgeId }
|
||||
const parsedSecondsToWaitFor = parseVariables(variables)(
|
||||
block.options.secondsToWaitFor
|
||||
const parsedSecondsToWaitFor = safeParseInt(
|
||||
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 } }],
|
||||
clientSideActions: parsedSecondsToWaitFor
|
||||
? [
|
||||
{
|
||||
wait: { secondsToWaitFor: parsedSecondsToWaitFor },
|
||||
lastBubbleBlockId,
|
||||
},
|
||||
]
|
||||
: undefined,
|
||||
}
|
||||
}
|
||||
|
||||
const safeParseInt = (value: string) => {
|
||||
const parsedValue = parseInt(value)
|
||||
return isNaN(parsedValue) ? undefined : parsedValue
|
||||
}
|
||||
|
||||
@@ -132,6 +132,7 @@ const parseRetryMessage = (
|
||||
return {
|
||||
messages: [
|
||||
{
|
||||
id: block.id,
|
||||
type: BubbleBlockType.TEXT,
|
||||
content: {
|
||||
plainText: retryMessage,
|
||||
|
||||
@@ -29,6 +29,7 @@ export const executeGroup =
|
||||
currentReply?.clientSideActions
|
||||
let logs: ChatReply['logs'] = currentReply?.logs
|
||||
let nextEdgeId = null
|
||||
let lastBubbleBlockId: string | undefined
|
||||
|
||||
let newSessionState = state
|
||||
|
||||
@@ -39,6 +40,7 @@ export const executeGroup =
|
||||
messages.push(
|
||||
deepParseVariable(newSessionState.typebot.variables)(block)
|
||||
)
|
||||
lastBubbleBlockId = block.id
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -63,9 +65,9 @@ export const executeGroup =
|
||||
logs,
|
||||
}
|
||||
const executionResponse = isLogicBlock(block)
|
||||
? await executeLogic(newSessionState)(block)
|
||||
? await executeLogic(newSessionState, lastBubbleBlockId)(block)
|
||||
: isIntegrationBlock(block)
|
||||
? await executeIntegration(newSessionState)(block)
|
||||
? await executeIntegration(newSessionState, lastBubbleBlockId)(block)
|
||||
: null
|
||||
|
||||
if (!executionResponse) continue
|
||||
|
||||
@@ -7,15 +7,15 @@ import { IntegrationBlock, IntegrationBlockType, SessionState } from 'models'
|
||||
import { ExecuteIntegrationResponse } from '../../types'
|
||||
|
||||
export const executeIntegration =
|
||||
(state: SessionState) =>
|
||||
(state: SessionState, lastBubbleBlockId?: string) =>
|
||||
async (block: IntegrationBlock): Promise<ExecuteIntegrationResponse> => {
|
||||
switch (block.type) {
|
||||
case IntegrationBlockType.GOOGLE_SHEETS:
|
||||
return executeGoogleSheetBlock(state, block)
|
||||
case IntegrationBlockType.CHATWOOT:
|
||||
return executeChatwootBlock(state, block)
|
||||
return executeChatwootBlock(state, block, lastBubbleBlockId)
|
||||
case IntegrationBlockType.GOOGLE_ANALYTICS:
|
||||
return executeGoogleAnalyticsBlock(state, block)
|
||||
return executeGoogleAnalyticsBlock(state, block, lastBubbleBlockId)
|
||||
case IntegrationBlockType.EMAIL:
|
||||
return executeSendEmailBlock(state, block)
|
||||
case IntegrationBlockType.WEBHOOK:
|
||||
|
||||
@@ -8,7 +8,7 @@ import { LogicBlock, LogicBlockType, SessionState } from 'models'
|
||||
import { ExecuteLogicResponse } from '../../types'
|
||||
|
||||
export const executeLogic =
|
||||
(state: SessionState) =>
|
||||
(state: SessionState, lastBubbleBlockId?: string) =>
|
||||
async (block: LogicBlock): Promise<ExecuteLogicResponse> => {
|
||||
switch (block.type) {
|
||||
case LogicBlockType.SET_VARIABLE:
|
||||
@@ -16,12 +16,12 @@ export const executeLogic =
|
||||
case LogicBlockType.CONDITION:
|
||||
return executeCondition(state, block)
|
||||
case LogicBlockType.REDIRECT:
|
||||
return executeRedirect(state, block)
|
||||
return executeRedirect(state, block, lastBubbleBlockId)
|
||||
case LogicBlockType.CODE:
|
||||
return executeCode(state, block)
|
||||
return executeCode(state, block, lastBubbleBlockId)
|
||||
case LogicBlockType.TYPEBOT_LINK:
|
||||
return executeTypebotLink(state, block)
|
||||
case LogicBlockType.WAIT:
|
||||
return executeWait(state, block)
|
||||
return executeWait(state, block, lastBubbleBlockId)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user