2
0

🚸 (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:
Baptiste Arnaud
2023-01-27 10:54:59 +01:00
parent a738897dbb
commit 4f78dda640
16 changed files with 408 additions and 262 deletions

View File

@@ -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
}
]
}

View File

@@ -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' })(

View File

@@ -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,
},
],
})

View File

@@ -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,
},
],
}

View File

@@ -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 },
},
],

View File

@@ -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
}

View File

@@ -132,6 +132,7 @@ const parseRetryMessage = (
return {
messages: [
{
id: block.id,
type: BubbleBlockType.TEXT,
content: {
plainText: retryMessage,

View File

@@ -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

View File

@@ -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:

View File

@@ -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)
}
}