@ -50,7 +50,7 @@ test.describe.parallel('Buttons input block', () => {
|
||||
await page.click('[data-testid="block2-icon"]')
|
||||
await page.click('text=Multiple choice?')
|
||||
await page.fill('#button', 'Go')
|
||||
await page.getByPlaceholder('Select a variable').click()
|
||||
await page.getByPlaceholder('Select a variable').nth(1).click()
|
||||
await page.getByText('var1').click()
|
||||
await expect(page.getByText('Collectsvar1')).toBeVisible()
|
||||
await page.click('[data-testid="block2-icon"]')
|
||||
|
@ -0,0 +1,71 @@
|
||||
import { BlockIndices, ChoiceInputBlock, Variable } from 'models'
|
||||
import React from 'react'
|
||||
import { ItemNodesList } from '@/features/graph/components/Nodes/ItemNode'
|
||||
import {
|
||||
HStack,
|
||||
Stack,
|
||||
Tag,
|
||||
Text,
|
||||
useColorModeValue,
|
||||
Wrap,
|
||||
} from '@chakra-ui/react'
|
||||
import { useTypebot } from '@/features/editor'
|
||||
|
||||
type Props = {
|
||||
block: ChoiceInputBlock
|
||||
indices: BlockIndices
|
||||
}
|
||||
|
||||
export const ButtonsBlockNode = ({ block, indices }: Props) => {
|
||||
const { typebot } = useTypebot()
|
||||
const dynamicVariableName = typebot?.variables.find(
|
||||
(variable) => variable.id === block.options.dynamicVariableId
|
||||
)?.name
|
||||
|
||||
return (
|
||||
<Stack w="full">
|
||||
{block.options.variableId ? (
|
||||
<CollectVariableLabel
|
||||
variableId={block.options.variableId}
|
||||
variables={typebot?.variables}
|
||||
/>
|
||||
) : null}
|
||||
{block.options.dynamicVariableId ? (
|
||||
<Wrap spacing={1}>
|
||||
<Text>Display</Text>
|
||||
<Tag bg="orange.400" color="white">
|
||||
{dynamicVariableName}
|
||||
</Tag>
|
||||
<Text>buttons</Text>
|
||||
</Wrap>
|
||||
) : (
|
||||
<ItemNodesList block={block} indices={indices} />
|
||||
)}
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
|
||||
const CollectVariableLabel = ({
|
||||
variableId,
|
||||
variables,
|
||||
}: {
|
||||
variableId: string
|
||||
variables?: Variable[]
|
||||
}) => {
|
||||
const textColor = useColorModeValue('gray.600', 'gray.400')
|
||||
const variableName = variables?.find(
|
||||
(variable) => variable.id === variableId
|
||||
)?.name
|
||||
|
||||
if (!variableName) return null
|
||||
return (
|
||||
<HStack fontStyle="italic" spacing={1}>
|
||||
<Text fontSize="sm" color={textColor}>
|
||||
Collects
|
||||
</Text>
|
||||
<Tag bg="orange.400" color="white" size="sm">
|
||||
{variableName}
|
||||
</Tag>
|
||||
</HStack>
|
||||
)
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
import { Input } from '@/components/inputs'
|
||||
import { MoreInfoTooltip } from '@/components/MoreInfoTooltip'
|
||||
import { SwitchWithLabel } from '@/components/SwitchWithLabel'
|
||||
import { VariableSearchInput } from '@/components/VariableSearchInput'
|
||||
import { FormLabel, Stack } from '@chakra-ui/react'
|
||||
import { FormControl, FormLabel, Stack } from '@chakra-ui/react'
|
||||
import { ChoiceInputOptions, Variable } from 'models'
|
||||
import React from 'react'
|
||||
|
||||
@ -20,6 +21,8 @@ export const ButtonsOptionsForm = ({
|
||||
options && onOptionsChange({ ...options, buttonLabel })
|
||||
const handleVariableChange = (variable?: Variable) =>
|
||||
options && onOptionsChange({ ...options, variableId: variable?.id })
|
||||
const handleDynamicVariableChange = (variable?: Variable) =>
|
||||
options && onOptionsChange({ ...options, dynamicVariableId: variable?.id })
|
||||
|
||||
return (
|
||||
<Stack spacing={4}>
|
||||
@ -40,6 +43,19 @@ export const ButtonsOptionsForm = ({
|
||||
/>
|
||||
</Stack>
|
||||
)}
|
||||
<FormControl>
|
||||
<FormLabel>
|
||||
Dynamic items from variable:{' '}
|
||||
<MoreInfoTooltip>
|
||||
If defined, buttons will be dynamically displayed based on what the
|
||||
variable contains.
|
||||
</MoreInfoTooltip>
|
||||
</FormLabel>
|
||||
<VariableSearchInput
|
||||
initialVariableId={options?.dynamicVariableId}
|
||||
onSelectVariable={handleDynamicVariableChange}
|
||||
/>
|
||||
</FormControl>
|
||||
<Stack>
|
||||
<FormLabel mb="0" htmlFor="variable">
|
||||
Save answer in a variable:
|
@ -1,3 +1,3 @@
|
||||
export * from './ButtonsItemNode'
|
||||
export * from './ButtonsIcon'
|
||||
export * from './ButtonsOptionsForm'
|
||||
export * from './ButtonsBlockSettings'
|
||||
|
@ -6,21 +6,26 @@ export const getDeepKeys = (obj: any): string[] => {
|
||||
const subkeys = getDeepKeys(obj[key])
|
||||
keys = keys.concat(
|
||||
subkeys.map(function (subkey) {
|
||||
return key + '.' + subkey
|
||||
return key + parseKey(subkey)
|
||||
})
|
||||
)
|
||||
} else if (Array.isArray(obj[key])) {
|
||||
for (let i = 0; i < obj[key].length; i++) {
|
||||
const subkeys = getDeepKeys(obj[key][i])
|
||||
keys = keys.concat(
|
||||
subkeys.map(function (subkey) {
|
||||
return key + '[' + i + ']' + '.' + subkey
|
||||
})
|
||||
)
|
||||
}
|
||||
const subkeys = getDeepKeys(obj[key][0])
|
||||
keys = keys.concat(
|
||||
subkeys.map(function (subkey) {
|
||||
return `${key}.map(item => item${parseKey(subkey)})`
|
||||
})
|
||||
)
|
||||
} else {
|
||||
keys.push(key)
|
||||
}
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
const parseKey = (key: string) => {
|
||||
if (key.includes(' ') && !key.includes('.map((item) => item')) {
|
||||
return `['${key}']`
|
||||
}
|
||||
return `.${key}`
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ test.describe('Builder', () => {
|
||||
await page.click('text=Save in variables')
|
||||
await page.click('text=Add an entry >> nth=-1')
|
||||
await page.click('input[placeholder="Select the data"]')
|
||||
await page.click('text=data[0].name')
|
||||
await page.click('text=data.map(item => item.name)')
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -100,8 +100,7 @@ export const BlockNode = ({
|
||||
|
||||
useEffect(() => {
|
||||
if (query.blockId?.toString() === block.id) setOpenedBlockId(block.id)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [query])
|
||||
}, [block.id, query, setOpenedBlockId])
|
||||
|
||||
useEffect(() => {
|
||||
setIsConnecting(
|
||||
|
@ -33,20 +33,18 @@ import { GoogleSheetsNodeContent } from '@/features/blocks/integrations/googleSh
|
||||
import { GoogleAnalyticsNodeContent } from '@/features/blocks/integrations/googleAnalytics/components/GoogleAnalyticsNodeContent'
|
||||
import { ZapierContent } from '@/features/blocks/integrations/zapier'
|
||||
import { SendEmailContent } from '@/features/blocks/integrations/sendEmail'
|
||||
import { isInputBlock, isChoiceInput, blockHasItems } from 'utils'
|
||||
import { isInputBlock, isChoiceInput } from 'utils'
|
||||
import { MakeComContent } from '@/features/blocks/integrations/makeCom'
|
||||
import { AudioBubbleNode } from '@/features/blocks/bubbles/audio'
|
||||
import { WaitNodeContent } from '@/features/blocks/logic/wait/components/WaitNodeContent'
|
||||
import { ScriptNodeContent } from '@/features/blocks/logic/script/components/ScriptNodeContent'
|
||||
import { ButtonsBlockNode } from '@/features/blocks/inputs/buttons/components/ButtonsBlockNode'
|
||||
|
||||
type Props = {
|
||||
block: Block | StartBlock
|
||||
indices: BlockIndices
|
||||
}
|
||||
export const BlockNodeContent = ({ block, indices }: Props): JSX.Element => {
|
||||
if (blockHasItems(block))
|
||||
return <ItemNodesList block={block} indices={indices} />
|
||||
|
||||
if (
|
||||
isInputBlock(block) &&
|
||||
!isChoiceInput(block) &&
|
||||
@ -92,6 +90,9 @@ export const BlockNodeContent = ({ block, indices }: Props): JSX.Element => {
|
||||
case InputBlockType.URL: {
|
||||
return <UrlNodeContent placeholder={block.options.labels.placeholder} />
|
||||
}
|
||||
case InputBlockType.CHOICE: {
|
||||
return <ButtonsBlockNode block={block} indices={indices} />
|
||||
}
|
||||
case InputBlockType.PHONE: {
|
||||
return <PhoneNodeContent placeholder={block.options.labels.placeholder} />
|
||||
}
|
||||
@ -126,7 +127,8 @@ export const BlockNodeContent = ({ block, indices }: Props): JSX.Element => {
|
||||
}
|
||||
case LogicBlockType.TYPEBOT_LINK:
|
||||
return <TypebotLinkNode block={block} />
|
||||
|
||||
case LogicBlockType.CONDITION:
|
||||
return <ItemNodesList block={block} indices={indices} />
|
||||
case IntegrationBlockType.GOOGLE_SHEETS: {
|
||||
return (
|
||||
<GoogleSheetsNodeContent
|
||||
|
@ -1,9 +1,7 @@
|
||||
import {
|
||||
Flex,
|
||||
HStack,
|
||||
Portal,
|
||||
Stack,
|
||||
Tag,
|
||||
Text,
|
||||
useColorModeValue,
|
||||
useEventListener,
|
||||
@ -15,13 +13,7 @@ import {
|
||||
useGraph,
|
||||
} from '../../../providers'
|
||||
import { useTypebot } from '@/features/editor'
|
||||
import {
|
||||
BlockIndices,
|
||||
BlockWithItems,
|
||||
LogicBlockType,
|
||||
Item,
|
||||
Variable,
|
||||
} from 'models'
|
||||
import { BlockIndices, BlockWithItems, LogicBlockType, Item } from 'models'
|
||||
import React, { useEffect, useRef, useState } from 'react'
|
||||
import { ItemNode } from './ItemNode'
|
||||
import { SourceEndpoint } from '../../Endpoints'
|
||||
@ -137,17 +129,8 @@ export const ItemNodesList = ({
|
||||
elem && (placeholderRefs.current[idx] = elem)
|
||||
}
|
||||
|
||||
const collectedVariableId =
|
||||
'options' in block && block.options && block.options.variableId
|
||||
|
||||
return (
|
||||
<Stack flex={1} spacing={1} maxW="full" onClick={stopPropagating}>
|
||||
{collectedVariableId && (
|
||||
<CollectVariableLabel
|
||||
variableId={collectedVariableId}
|
||||
variables={typebot?.variables ?? []}
|
||||
/>
|
||||
)}
|
||||
<PlaceholderNode
|
||||
isVisible={showPlaceholders}
|
||||
isExpanded={expandedPlaceholderIndex === 0}
|
||||
@ -221,28 +204,3 @@ const DefaultItemNode = ({ block }: { block: BlockWithItems }) => {
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
const CollectVariableLabel = ({
|
||||
variableId,
|
||||
variables,
|
||||
}: {
|
||||
variableId: string
|
||||
variables: Variable[]
|
||||
}) => {
|
||||
const textColor = useColorModeValue('gray.600', 'gray.400')
|
||||
const variableName = variables.find(
|
||||
(variable) => variable.id === variableId
|
||||
)?.name
|
||||
|
||||
if (!variableName) return null
|
||||
return (
|
||||
<HStack fontStyle="italic" spacing={1}>
|
||||
<Text fontSize="sm" color={textColor}>
|
||||
Collects
|
||||
</Text>
|
||||
<Tag bg="orange.400" color="white" size="sm">
|
||||
{variableName}
|
||||
</Tag>
|
||||
</HStack>
|
||||
)
|
||||
}
|
||||
|
Reference in New Issue
Block a user