2
0

Add conditional choice items

Allows you to conditonnally display an item from the Buttons or the Picture choice input

Closes #546
This commit is contained in:
Baptiste Arnaud
2023-06-05 17:33:43 +02:00
parent acaa1c6223
commit ef0a2d9dc6
18 changed files with 404 additions and 157 deletions

View File

@@ -0,0 +1,17 @@
import { ChoiceInputBlock, Variable } from '@typebot.io/schemas'
import { executeCondition } from '../../logic/condition/executeCondition'
export const filterChoiceItems =
(variables: Variable[]) =>
(block: ChoiceInputBlock): ChoiceInputBlock => {
const filteredItems = block.items.filter((item) => {
if (item.displayCondition?.isEnabled && item.displayCondition?.condition)
return executeCondition(variables)(item.displayCondition.condition)
return true
})
return {
...block,
items: filteredItems,
}
}

View File

@@ -8,6 +8,7 @@ import { isDefined } from '@typebot.io/lib'
import { deepParseVariables } from '@/features/variables/deepParseVariable'
import { transformStringVariablesToList } from '@/features/variables/transformVariablesToList'
import { updateVariables } from '@/features/variables/updateVariables'
import { filterChoiceItems } from './filterChoiceItems'
export const injectVariableValuesInButtonsInputBlock =
(state: SessionState) =>
@@ -30,7 +31,9 @@ export const injectVariableValuesInButtonsInputBlock =
})),
}
}
return deepParseVariables(state.typebot.variables)(block)
return deepParseVariables(state.typebot.variables)(
filterChoiceItems(state.typebot.variables)(block)
)
}
const getVariableValue =

View File

@@ -0,0 +1,17 @@
import { PictureChoiceBlock, Variable } from '@typebot.io/schemas'
import { executeCondition } from '../../logic/condition/executeCondition'
export const filterPictureChoiceItems =
(variables: Variable[]) =>
(block: PictureChoiceBlock): PictureChoiceBlock => {
const filteredItems = block.items.filter((item) => {
if (item.displayCondition?.isEnabled && item.displayCondition?.condition)
return executeCondition(variables)(item.displayCondition.condition)
return true
})
return {
...block,
items: filteredItems,
}
}

View File

@@ -6,6 +6,7 @@ import {
} from '@typebot.io/schemas'
import { isDefined } from '@typebot.io/lib'
import { deepParseVariables } from '@/features/variables/deepParseVariable'
import { filterPictureChoiceItems } from './filterPictureChoiceItems'
export const injectVariableValuesInPictureChoiceBlock =
(variables: SessionState['typebot']['variables']) =>
@@ -51,5 +52,7 @@ export const injectVariableValuesInPictureChoiceBlock =
})),
}
}
return deepParseVariables(variables)(block)
return deepParseVariables(variables)(
filterPictureChoiceItems(variables)(block)
)
}

View File

@@ -1,34 +1,20 @@
import { findUniqueVariableValue } from '@/features/variables/findUniqueVariableValue'
import { isNotDefined, isDefined } from '@typebot.io/lib'
import {
Comparison,
ComparisonOperators,
ConditionBlock,
Condition,
LogicalOperator,
SessionState,
Variable,
} from '@typebot.io/schemas'
import { isNotDefined, isDefined } from '@typebot.io/lib'
import { ExecuteLogicResponse } from '@/features/chat/types'
import { findUniqueVariableValue } from '@/features/variables/findUniqueVariableValue'
import { parseVariables } from '@/features/variables/parseVariables'
import { parseVariables } from 'bot-engine'
export const executeCondition = (
{ typebot: { variables } }: SessionState,
block: ConditionBlock
): ExecuteLogicResponse => {
const passedCondition = block.items.find((item) => {
const { content } = item
const isConditionPassed =
content.logicalOperator === LogicalOperator.AND
? content.comparisons.every(executeComparison(variables))
: content.comparisons.some(executeComparison(variables))
return isConditionPassed
})
return {
outgoingEdgeId: passedCondition
? passedCondition.outgoingEdgeId
: block.outgoingEdgeId,
}
}
export const executeCondition =
(variables: Variable[]) =>
(condition: Condition): boolean =>
condition.logicalOperator === LogicalOperator.AND
? condition.comparisons.every(executeComparison(variables))
: condition.comparisons.some(executeComparison(variables))
const executeComparison =
(variables: Variable[]) =>

View File

@@ -0,0 +1,17 @@
import { ConditionBlock, SessionState } from '@typebot.io/schemas'
import { ExecuteLogicResponse } from '@/features/chat/types'
import { executeCondition } from './executeCondition'
export const executeConditionBlock = (
{ typebot: { variables } }: SessionState,
block: ConditionBlock
): ExecuteLogicResponse => {
const passedCondition = block.items.find((item) =>
executeCondition(variables)(item.content)
)
return {
outgoingEdgeId: passedCondition
? passedCondition.outgoingEdgeId
: block.outgoingEdgeId,
}
}

View File

@@ -55,7 +55,7 @@ export const executeGroup =
if (isInputBlock(block))
return {
messages,
input: await injectVariablesValueInBlock(newSessionState)(block),
input: await parseInput(newSessionState)(block),
newSessionState: {
...newSessionState,
currentBlock: {
@@ -183,7 +183,7 @@ const parseBubbleBlock =
}
}
const injectVariablesValueInBlock =
const parseInput =
(state: SessionState) =>
async (block: InputBlock): Promise<ChatReply['input']> => {
switch (block.type) {

View File

@@ -4,7 +4,7 @@ import { ExecuteLogicResponse } from '../types'
import { executeScript } from '@/features/blocks/logic/script/executeScript'
import { executeJumpBlock } from '@/features/blocks/logic/jump/executeJumpBlock'
import { executeRedirect } from '@/features/blocks/logic/redirect/executeRedirect'
import { executeCondition } from '@/features/blocks/logic/condition/executeCondition'
import { executeConditionBlock } from '@/features/blocks/logic/condition/executeConditionBlock'
import { executeSetVariable } from '@/features/blocks/logic/setVariable/executeSetVariable'
import { executeTypebotLink } from '@/features/blocks/logic/typebotLink/executeTypebotLink'
import { executeAbTest } from '@/features/blocks/logic/abTest/executeAbTest'
@@ -16,7 +16,7 @@ export const executeLogic =
case LogicBlockType.SET_VARIABLE:
return executeSetVariable(state, block)
case LogicBlockType.CONDITION:
return executeCondition(state, block)
return executeConditionBlock(state, block)
case LogicBlockType.REDIRECT:
return executeRedirect(state, block)
case LogicBlockType.SCRIPT: