@@ -4,13 +4,9 @@ import {
|
||||
importTypebotInDatabase,
|
||||
} from '@typebot.io/lib/playwright/databaseActions'
|
||||
import { parseDefaultGroupWithBlock } from '@typebot.io/lib/playwright/databaseHelpers'
|
||||
import {
|
||||
defaultChoiceInputOptions,
|
||||
InputBlockType,
|
||||
ItemType,
|
||||
} from '@typebot.io/schemas'
|
||||
import { createId } from '@paralleldrive/cuid2'
|
||||
import { getTestAsset } from '@/test/utils/playwright'
|
||||
import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/constants'
|
||||
|
||||
test.describe.parallel('Buttons input block', () => {
|
||||
test('can edit button items', async ({ page }) => {
|
||||
@@ -23,11 +19,8 @@ test.describe.parallel('Buttons input block', () => {
|
||||
items: [
|
||||
{
|
||||
id: 'choice1',
|
||||
blockId: 'block1',
|
||||
type: ItemType.BUTTON,
|
||||
},
|
||||
],
|
||||
options: { ...defaultChoiceInputOptions },
|
||||
}),
|
||||
},
|
||||
])
|
||||
|
||||
@@ -13,12 +13,12 @@ type Props = {
|
||||
export const ButtonsBlockNode = ({ block, indices }: Props) => {
|
||||
const { typebot } = useTypebot()
|
||||
const dynamicVariableName = typebot?.variables.find(
|
||||
(variable) => variable.id === block.options.dynamicVariableId
|
||||
(variable) => variable.id === block.options?.dynamicVariableId
|
||||
)?.name
|
||||
|
||||
return (
|
||||
<Stack w="full">
|
||||
{block.options.dynamicVariableId ? (
|
||||
{block.options?.dynamicVariableId ? (
|
||||
<Wrap spacing={1}>
|
||||
<Text>Display</Text>
|
||||
<Tag bg="orange.400" color="white">
|
||||
@@ -29,7 +29,7 @@ export const ButtonsBlockNode = ({ block, indices }: Props) => {
|
||||
) : (
|
||||
<ItemNodesList block={block} indices={indices} />
|
||||
)}
|
||||
{block.options.variableId ? (
|
||||
{block.options?.variableId ? (
|
||||
<SetVariableLabel
|
||||
variableId={block.options.variableId}
|
||||
variables={typebot?.variables}
|
||||
|
||||
@@ -2,49 +2,53 @@ import { TextInput } from '@/components/inputs'
|
||||
import { MoreInfoTooltip } from '@/components/MoreInfoTooltip'
|
||||
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
||||
import { FormControl, FormLabel, Stack } from '@chakra-ui/react'
|
||||
import {
|
||||
ChoiceInputOptions,
|
||||
Variable,
|
||||
defaultChoiceInputOptions,
|
||||
} from '@typebot.io/schemas'
|
||||
import { ChoiceInputBlock, Variable } from '@typebot.io/schemas'
|
||||
import React from 'react'
|
||||
import { SwitchWithRelatedSettings } from '@/components/SwitchWithRelatedSettings'
|
||||
import { defaultChoiceInputOptions } from '@typebot.io/schemas/features/blocks/inputs/choice/constants'
|
||||
|
||||
type Props = {
|
||||
options?: ChoiceInputOptions
|
||||
onOptionsChange: (options: ChoiceInputOptions) => void
|
||||
options?: ChoiceInputBlock['options']
|
||||
onOptionsChange: (options: ChoiceInputBlock['options']) => void
|
||||
}
|
||||
|
||||
export const ButtonsBlockSettings = ({ options, onOptionsChange }: Props) => {
|
||||
const updateIsMultiple = (isMultipleChoice: boolean) =>
|
||||
options && onOptionsChange({ ...options, isMultipleChoice })
|
||||
onOptionsChange({ ...options, isMultipleChoice })
|
||||
const updateIsSearchable = (isSearchable: boolean) =>
|
||||
options && onOptionsChange({ ...options, isSearchable })
|
||||
onOptionsChange({ ...options, isSearchable })
|
||||
const updateButtonLabel = (buttonLabel: string) =>
|
||||
options && onOptionsChange({ ...options, buttonLabel })
|
||||
onOptionsChange({ ...options, buttonLabel })
|
||||
const updateSearchInputPlaceholder = (searchInputPlaceholder: string) =>
|
||||
options && onOptionsChange({ ...options, searchInputPlaceholder })
|
||||
onOptionsChange({ ...options, searchInputPlaceholder })
|
||||
const updateSaveVariable = (variable?: Variable) =>
|
||||
options && onOptionsChange({ ...options, variableId: variable?.id })
|
||||
onOptionsChange({ ...options, variableId: variable?.id })
|
||||
const updateDynamicDataVariable = (variable?: Variable) =>
|
||||
options && onOptionsChange({ ...options, dynamicVariableId: variable?.id })
|
||||
onOptionsChange({ ...options, dynamicVariableId: variable?.id })
|
||||
|
||||
return (
|
||||
<Stack spacing={4}>
|
||||
<SwitchWithRelatedSettings
|
||||
label="Multiple choice?"
|
||||
initialValue={options?.isMultipleChoice ?? false}
|
||||
initialValue={
|
||||
options?.isMultipleChoice ??
|
||||
defaultChoiceInputOptions.isMultipleChoice
|
||||
}
|
||||
onCheckChange={updateIsMultiple}
|
||||
>
|
||||
<TextInput
|
||||
label="Submit button label:"
|
||||
defaultValue={options?.buttonLabel ?? 'Send'}
|
||||
defaultValue={
|
||||
options?.buttonLabel ?? defaultChoiceInputOptions.buttonLabel
|
||||
}
|
||||
onChange={updateButtonLabel}
|
||||
/>
|
||||
</SwitchWithRelatedSettings>
|
||||
<SwitchWithRelatedSettings
|
||||
label="Is searchable?"
|
||||
initialValue={options?.isSearchable ?? false}
|
||||
initialValue={
|
||||
options?.isSearchable ?? defaultChoiceInputOptions.isSearchable
|
||||
}
|
||||
onCheckChange={updateIsSearchable}
|
||||
>
|
||||
<TextInput
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
} from '@chakra-ui/react'
|
||||
import { PlusIcon, SettingsIcon } from '@/components/icons'
|
||||
import { useTypebot } from '@/features/editor/providers/TypebotProvider'
|
||||
import { ButtonItem, Item, ItemIndices, ItemType } from '@typebot.io/schemas'
|
||||
import { ButtonItem, Item, ItemIndices } from '@typebot.io/schemas'
|
||||
import React, { useRef, useState } from 'react'
|
||||
import { isNotDefined } from '@typebot.io/lib'
|
||||
import { useGraph } from '@/features/graph/providers/GraphProvider'
|
||||
@@ -54,7 +54,7 @@ export const ButtonsItemNode = ({ item, indices, isMouseOver }: Props) => {
|
||||
|
||||
const handlePlusClick = () => {
|
||||
const itemIndex = indices.itemIndex + 1
|
||||
createItem({ type: ItemType.BUTTON }, { ...indices, itemIndex })
|
||||
createItem({}, { ...indices, itemIndex })
|
||||
}
|
||||
|
||||
const updateItemSettings = (settings: Omit<ButtonItem, 'content'>) => {
|
||||
|
||||
@@ -2,7 +2,8 @@ import React from 'react'
|
||||
import { Stack } from '@chakra-ui/react'
|
||||
import { SwitchWithRelatedSettings } from '@/components/SwitchWithRelatedSettings'
|
||||
import { ConditionForm } from '@/features/blocks/logic/condition/components/ConditionForm'
|
||||
import { ButtonItem, Condition, LogicalOperator } from '@typebot.io/schemas'
|
||||
import { ButtonItem, Condition } from '@typebot.io/schemas'
|
||||
import { LogicalOperator } from '@typebot.io/schemas/features/blocks/logic/condition/constants'
|
||||
|
||||
type Props = {
|
||||
item: ButtonItem
|
||||
|
||||
@@ -3,12 +3,13 @@ import { TextInput } from '@/components/inputs'
|
||||
import { SwitchWithLabel } from '@/components/inputs/SwitchWithLabel'
|
||||
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
||||
import { FormLabel, Stack } from '@chakra-ui/react'
|
||||
import { DateInputOptions, Variable } from '@typebot.io/schemas'
|
||||
import { DateInputBlock, Variable } from '@typebot.io/schemas'
|
||||
import React from 'react'
|
||||
import { defaultDateInputOptions } from '@typebot.io/schemas/features/blocks/inputs/date/constants'
|
||||
|
||||
type Props = {
|
||||
options: DateInputOptions
|
||||
onOptionsChange: (options: DateInputOptions) => void
|
||||
options: DateInputBlock['options']
|
||||
onOptionsChange: (options: DateInputBlock['options']) => void
|
||||
}
|
||||
|
||||
export const DateInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
@@ -41,47 +42,56 @@ export const DateInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
<Stack spacing={4}>
|
||||
<SwitchWithRelatedSettings
|
||||
label="Is range?"
|
||||
initialValue={options.isRange}
|
||||
initialValue={options?.isRange ?? defaultDateInputOptions.isRange}
|
||||
onCheckChange={updateIsRange}
|
||||
>
|
||||
<TextInput
|
||||
label="From label:"
|
||||
defaultValue={options.labels.from}
|
||||
defaultValue={options?.labels?.from}
|
||||
onChange={updateFromLabel}
|
||||
/>
|
||||
<TextInput
|
||||
label="To label:"
|
||||
defaultValue={options.labels.to}
|
||||
defaultValue={
|
||||
options?.labels?.to ?? defaultDateInputOptions.labels.to
|
||||
}
|
||||
onChange={updateToLabel}
|
||||
/>
|
||||
</SwitchWithRelatedSettings>
|
||||
<SwitchWithLabel
|
||||
label="With time?"
|
||||
initialValue={options.hasTime}
|
||||
initialValue={options?.hasTime ?? defaultDateInputOptions.hasTime}
|
||||
onCheckChange={updateHasTime}
|
||||
/>
|
||||
<TextInput
|
||||
label="Button label:"
|
||||
defaultValue={options.labels.button}
|
||||
defaultValue={
|
||||
options?.labels?.button ?? defaultDateInputOptions.labels.button
|
||||
}
|
||||
onChange={updateButtonLabel}
|
||||
/>
|
||||
<TextInput
|
||||
label="Min:"
|
||||
defaultValue={options.min}
|
||||
placeholder={options.hasTime ? 'YYYY-MM-DDTHH:mm' : 'YYYY-MM-DD'}
|
||||
defaultValue={options?.min}
|
||||
placeholder={options?.hasTime ? 'YYYY-MM-DDTHH:mm' : 'YYYY-MM-DD'}
|
||||
onChange={updateMin}
|
||||
/>
|
||||
<TextInput
|
||||
label="Max:"
|
||||
defaultValue={options.max}
|
||||
placeholder={options.hasTime ? 'YYYY-MM-DDTHH:mm' : 'YYYY-MM-DD'}
|
||||
defaultValue={options?.max}
|
||||
placeholder={options?.hasTime ? 'YYYY-MM-DDTHH:mm' : 'YYYY-MM-DD'}
|
||||
onChange={updateMax}
|
||||
/>
|
||||
<TextInput
|
||||
label="Format:"
|
||||
defaultValue={options.format}
|
||||
moreInfoTooltip="Popular formats: dd/MM/yyyy, MM/dd/yy, yyyy-MM-dd"
|
||||
placeholder={options.hasTime ? 'dd/MM/yyyy HH:mm' : 'dd/MM/yyyy'}
|
||||
defaultValue={
|
||||
options?.format ??
|
||||
(options?.hasTime
|
||||
? defaultDateInputOptions.formatWithTime
|
||||
: defaultDateInputOptions.format)
|
||||
}
|
||||
moreInfoTooltip="i.e dd/MM/yyyy, MM/dd/yy, yyyy-MM-dd"
|
||||
placeholder={options?.hasTime ? 'dd/MM/yyyy HH:mm' : 'dd/MM/yyyy'}
|
||||
onChange={updateFormat}
|
||||
/>
|
||||
<Stack>
|
||||
@@ -89,7 +99,7 @@ export const DateInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
Save answer in a variable:
|
||||
</FormLabel>
|
||||
<VariableSearchInput
|
||||
initialVariableId={options.variableId}
|
||||
initialVariableId={options?.variableId}
|
||||
onSelectVariable={updateVariable}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import test, { expect } from '@playwright/test'
|
||||
import { createTypebots } from '@typebot.io/lib/playwright/databaseActions'
|
||||
import { parseDefaultGroupWithBlock } from '@typebot.io/lib/playwright/databaseHelpers'
|
||||
import { defaultDateInputOptions, InputBlockType } from '@typebot.io/schemas'
|
||||
import { createId } from '@paralleldrive/cuid2'
|
||||
import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/constants'
|
||||
|
||||
test.describe('Date input block', () => {
|
||||
test('options should work', async ({ page }) => {
|
||||
@@ -12,7 +12,6 @@ test.describe('Date input block', () => {
|
||||
id: typebotId,
|
||||
...parseDefaultGroupWithBlock({
|
||||
type: InputBlockType.DATE,
|
||||
options: defaultDateInputOptions,
|
||||
}),
|
||||
},
|
||||
])
|
||||
|
||||
@@ -2,15 +2,19 @@ import React from 'react'
|
||||
import { Text } from '@chakra-ui/react'
|
||||
import { EmailInputBlock } from '@typebot.io/schemas'
|
||||
import { WithVariableContent } from '@/features/graph/components/nodes/block/WithVariableContent'
|
||||
import { defaultEmailInputOptions } from '@typebot.io/schemas/features/blocks/inputs/email/constants'
|
||||
|
||||
type Props = {
|
||||
variableId?: string
|
||||
placeholder: EmailInputBlock['options']['labels']['placeholder']
|
||||
options: EmailInputBlock['options']
|
||||
}
|
||||
|
||||
export const EmailInputNodeContent = ({ variableId, placeholder }: Props) =>
|
||||
export const EmailInputNodeContent = ({
|
||||
options: { variableId, labels } = {},
|
||||
}: Props) =>
|
||||
variableId ? (
|
||||
<WithVariableContent variableId={variableId} />
|
||||
) : (
|
||||
<Text color={'gray.500'}>{placeholder}</Text>
|
||||
<Text color={'gray.500'}>
|
||||
{labels?.placeholder ?? defaultEmailInputOptions.labels.placeholder}
|
||||
</Text>
|
||||
)
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
import { TextInput } from '@/components/inputs'
|
||||
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
||||
import { FormLabel, Stack } from '@chakra-ui/react'
|
||||
import {
|
||||
EmailInputOptions,
|
||||
Variable,
|
||||
invalidEmailDefaultRetryMessage,
|
||||
} from '@typebot.io/schemas'
|
||||
import { EmailInputBlock, Variable } from '@typebot.io/schemas'
|
||||
import { defaultEmailInputOptions } from '@typebot.io/schemas/features/blocks/inputs/email/constants'
|
||||
import React from 'react'
|
||||
|
||||
type Props = {
|
||||
options: EmailInputOptions
|
||||
onOptionsChange: (options: EmailInputOptions) => void
|
||||
options: EmailInputBlock['options']
|
||||
onOptionsChange: (options: EmailInputBlock['options']) => void
|
||||
}
|
||||
|
||||
export const EmailInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
const handlePlaceholderChange = (placeholder: string) =>
|
||||
onOptionsChange({ ...options, labels: { ...options.labels, placeholder } })
|
||||
onOptionsChange({ ...options, labels: { ...options?.labels, placeholder } })
|
||||
const handleButtonLabelChange = (button: string) =>
|
||||
onOptionsChange({ ...options, labels: { ...options.labels, button } })
|
||||
onOptionsChange({ ...options, labels: { ...options?.labels, button } })
|
||||
const handleVariableChange = (variable?: Variable) =>
|
||||
onOptionsChange({ ...options, variableId: variable?.id })
|
||||
const handleRetryMessageChange = (retryMessageContent: string) =>
|
||||
@@ -27,18 +24,24 @@ export const EmailInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
<Stack spacing={4}>
|
||||
<TextInput
|
||||
label="Placeholder:"
|
||||
defaultValue={options.labels.placeholder}
|
||||
defaultValue={
|
||||
options?.labels?.placeholder ??
|
||||
defaultEmailInputOptions.labels.placeholder
|
||||
}
|
||||
onChange={handlePlaceholderChange}
|
||||
/>
|
||||
<TextInput
|
||||
label="Button label:"
|
||||
defaultValue={options.labels.button}
|
||||
defaultValue={
|
||||
options?.labels?.button ?? defaultEmailInputOptions.labels.button
|
||||
}
|
||||
onChange={handleButtonLabelChange}
|
||||
/>
|
||||
<TextInput
|
||||
label="Retry message:"
|
||||
defaultValue={
|
||||
options.retryMessageContent ?? invalidEmailDefaultRetryMessage
|
||||
options?.retryMessageContent ??
|
||||
defaultEmailInputOptions.retryMessageContent
|
||||
}
|
||||
onChange={handleRetryMessageChange}
|
||||
/>
|
||||
@@ -47,7 +50,7 @@ export const EmailInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
Save answer in a variable:
|
||||
</FormLabel>
|
||||
<VariableSearchInput
|
||||
initialVariableId={options.variableId}
|
||||
initialVariableId={options?.variableId}
|
||||
onSelectVariable={handleVariableChange}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import test, { expect } from '@playwright/test'
|
||||
import { createTypebots } from '@typebot.io/lib/playwright/databaseActions'
|
||||
import { parseDefaultGroupWithBlock } from '@typebot.io/lib/playwright/databaseHelpers'
|
||||
import {
|
||||
defaultEmailInputOptions,
|
||||
InputBlockType,
|
||||
invalidEmailDefaultRetryMessage,
|
||||
} from '@typebot.io/schemas'
|
||||
import { createId } from '@paralleldrive/cuid2'
|
||||
import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/constants'
|
||||
import { defaultEmailInputOptions } from '@typebot.io/schemas/features/blocks/inputs/email/constants'
|
||||
|
||||
test.describe('Email input block', () => {
|
||||
test('options should work', async ({ page }) => {
|
||||
@@ -16,7 +13,6 @@ test.describe('Email input block', () => {
|
||||
id: typebotId,
|
||||
...parseDefaultGroupWithBlock({
|
||||
type: InputBlockType.EMAIL,
|
||||
options: defaultEmailInputOptions,
|
||||
}),
|
||||
},
|
||||
])
|
||||
@@ -39,7 +35,7 @@ test.describe('Email input block', () => {
|
||||
await expect(page.locator('text=Your email...')).toBeVisible()
|
||||
await page.getByLabel('Button label:').fill('Go')
|
||||
await page.fill(
|
||||
`input[value="${invalidEmailDefaultRetryMessage}"]`,
|
||||
`input[value="${defaultEmailInputOptions.retryMessageContent}"]`,
|
||||
'Try again bro'
|
||||
)
|
||||
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
import { WithVariableContent } from '@/features/graph/components/nodes/block/WithVariableContent'
|
||||
import { Text } from '@chakra-ui/react'
|
||||
import { FileInputOptions } from '@typebot.io/schemas'
|
||||
import { FileInputBlock } from '@typebot.io/schemas'
|
||||
|
||||
type Props = {
|
||||
options: FileInputOptions
|
||||
options: FileInputBlock['options']
|
||||
}
|
||||
|
||||
export const FileInputContent = ({
|
||||
options: { isMultipleAllowed, variableId },
|
||||
}: Props) =>
|
||||
variableId ? (
|
||||
<WithVariableContent variableId={variableId} />
|
||||
export const FileInputContent = ({ options }: Props) =>
|
||||
options?.variableId ? (
|
||||
<WithVariableContent variableId={options.variableId} />
|
||||
) : (
|
||||
<Text noOfLines={1} pr="6">
|
||||
Collect {isMultipleAllowed ? 'files' : 'file'}
|
||||
Collect {options?.isMultipleAllowed ? 'files' : 'file'}
|
||||
</Text>
|
||||
)
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
import { FormLabel, Stack } from '@chakra-ui/react'
|
||||
import { CodeEditor } from '@/components/inputs/CodeEditor'
|
||||
import { FileInputOptions, Variable } from '@typebot.io/schemas'
|
||||
import { FileInputBlock, Variable } from '@typebot.io/schemas'
|
||||
import React from 'react'
|
||||
import { TextInput } from '@/components/inputs'
|
||||
import { SwitchWithLabel } from '@/components/inputs/SwitchWithLabel'
|
||||
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
||||
import { defaultFileInputOptions } from '@typebot.io/schemas/features/blocks/inputs/file/constants'
|
||||
|
||||
type Props = {
|
||||
options: FileInputOptions
|
||||
onOptionsChange: (options: FileInputOptions) => void
|
||||
options: FileInputBlock['options']
|
||||
onOptionsChange: (options: FileInputBlock['options']) => void
|
||||
}
|
||||
|
||||
export const FileInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
const handleButtonLabelChange = (button: string) =>
|
||||
onOptionsChange({ ...options, labels: { ...options.labels, button } })
|
||||
onOptionsChange({ ...options, labels: { ...options?.labels, button } })
|
||||
|
||||
const handlePlaceholderLabelChange = (placeholder: string) =>
|
||||
onOptionsChange({ ...options, labels: { ...options.labels, placeholder } })
|
||||
onOptionsChange({ ...options, labels: { ...options?.labels, placeholder } })
|
||||
|
||||
const handleMultipleFilesChange = (isMultipleAllowed: boolean) =>
|
||||
onOptionsChange({ ...options, isMultipleAllowed })
|
||||
@@ -28,21 +29,24 @@ export const FileInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
onOptionsChange({ ...options, isRequired })
|
||||
|
||||
const updateClearButtonLabel = (clear: string) =>
|
||||
onOptionsChange({ ...options, labels: { ...options.labels, clear } })
|
||||
onOptionsChange({ ...options, labels: { ...options?.labels, clear } })
|
||||
|
||||
const updateSkipButtonLabel = (skip: string) =>
|
||||
onOptionsChange({ ...options, labels: { ...options.labels, skip } })
|
||||
onOptionsChange({ ...options, labels: { ...options?.labels, skip } })
|
||||
|
||||
return (
|
||||
<Stack spacing={4}>
|
||||
<SwitchWithLabel
|
||||
label="Required?"
|
||||
initialValue={options.isRequired ?? true}
|
||||
initialValue={options?.isRequired ?? defaultFileInputOptions.isRequired}
|
||||
onCheckChange={handleRequiredChange}
|
||||
/>
|
||||
<SwitchWithLabel
|
||||
label="Allow multiple files?"
|
||||
initialValue={options.isMultipleAllowed}
|
||||
initialValue={
|
||||
options?.isMultipleAllowed ??
|
||||
defaultFileInputOptions.isMultipleAllowed
|
||||
}
|
||||
onCheckChange={handleMultipleFilesChange}
|
||||
/>
|
||||
<Stack>
|
||||
@@ -50,35 +54,44 @@ export const FileInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
<CodeEditor
|
||||
lang="html"
|
||||
onChange={handlePlaceholderLabelChange}
|
||||
defaultValue={options.labels.placeholder}
|
||||
defaultValue={
|
||||
options?.labels?.placeholder ??
|
||||
defaultFileInputOptions.labels.placeholder
|
||||
}
|
||||
height={'100px'}
|
||||
withVariableButton={false}
|
||||
/>
|
||||
</Stack>
|
||||
<TextInput
|
||||
label="Button label:"
|
||||
defaultValue={options.labels.button}
|
||||
defaultValue={
|
||||
options?.labels?.button ?? defaultFileInputOptions.labels.button
|
||||
}
|
||||
onChange={handleButtonLabelChange}
|
||||
withVariableButton={false}
|
||||
/>
|
||||
<TextInput
|
||||
label="Clear button label:"
|
||||
defaultValue={options.labels.clear ?? ''}
|
||||
defaultValue={
|
||||
options?.labels?.clear ?? defaultFileInputOptions.labels.clear
|
||||
}
|
||||
onChange={updateClearButtonLabel}
|
||||
withVariableButton={false}
|
||||
/>
|
||||
<TextInput
|
||||
label="Skip button label:"
|
||||
defaultValue={options.labels.skip ?? ''}
|
||||
defaultValue={
|
||||
options?.labels?.skip ?? defaultFileInputOptions.labels.skip
|
||||
}
|
||||
onChange={updateSkipButtonLabel}
|
||||
withVariableButton={false}
|
||||
/>
|
||||
<Stack>
|
||||
<FormLabel mb="0" htmlFor="variable">
|
||||
Save upload URL{options.isMultipleAllowed ? 's' : ''} in a variable:
|
||||
Save upload URL{options?.isMultipleAllowed ? 's' : ''} in a variable:
|
||||
</FormLabel>
|
||||
<VariableSearchInput
|
||||
initialVariableId={options.variableId}
|
||||
initialVariableId={options?.variableId}
|
||||
onSelectVariable={handleVariableChange}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import test, { expect } from '@playwright/test'
|
||||
import { createTypebots } from '@typebot.io/lib/playwright/databaseActions'
|
||||
import { parseDefaultGroupWithBlock } from '@typebot.io/lib/playwright/databaseHelpers'
|
||||
import { defaultFileInputOptions, InputBlockType } from '@typebot.io/schemas'
|
||||
import { createId } from '@paralleldrive/cuid2'
|
||||
import { freeWorkspaceId } from '@typebot.io/lib/playwright/databaseSetup'
|
||||
import { getTestAsset } from '@/test/utils/playwright'
|
||||
import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/constants'
|
||||
|
||||
test.describe.configure({ mode: 'parallel' })
|
||||
|
||||
@@ -15,7 +15,6 @@ test('options should work', async ({ page }) => {
|
||||
id: typebotId,
|
||||
...parseDefaultGroupWithBlock({
|
||||
type: InputBlockType.FILE,
|
||||
options: defaultFileInputOptions,
|
||||
}),
|
||||
},
|
||||
])
|
||||
@@ -59,8 +58,8 @@ test.describe('Free workspace', () => {
|
||||
id: typebotId,
|
||||
...parseDefaultGroupWithBlock({
|
||||
type: InputBlockType.FILE,
|
||||
options: defaultFileInputOptions,
|
||||
}),
|
||||
version: '6',
|
||||
workspaceId: freeWorkspaceId,
|
||||
},
|
||||
])
|
||||
|
||||
@@ -1,25 +1,29 @@
|
||||
import { TextInput, NumberInput } from '@/components/inputs'
|
||||
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
||||
import { FormLabel, Stack } from '@chakra-ui/react'
|
||||
import { NumberInputOptions, Variable } from '@typebot.io/schemas'
|
||||
import { NumberInputBlock, Variable } from '@typebot.io/schemas'
|
||||
import { defaultNumberInputOptions } from '@typebot.io/schemas/features/blocks/inputs/number/constants'
|
||||
import React from 'react'
|
||||
|
||||
type Props = {
|
||||
options: NumberInputOptions
|
||||
onOptionsChange: (options: NumberInputOptions) => void
|
||||
options: NumberInputBlock['options']
|
||||
onOptionsChange: (options: NumberInputBlock['options']) => void
|
||||
}
|
||||
|
||||
export const NumberInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
const handlePlaceholderChange = (placeholder: string) =>
|
||||
onOptionsChange({ ...options, labels: { ...options.labels, placeholder } })
|
||||
onOptionsChange({ ...options, labels: { ...options?.labels, placeholder } })
|
||||
const handleButtonLabelChange = (button: string) =>
|
||||
onOptionsChange({ ...options, labels: { ...options.labels, button } })
|
||||
const handleMinChange = (min?: NumberInputOptions['min']) =>
|
||||
onOptionsChange({ ...options, min })
|
||||
const handleMaxChange = (max?: NumberInputOptions['max']) =>
|
||||
onOptionsChange({ ...options, max })
|
||||
const handleStepChange = (step?: NumberInputOptions['step']) =>
|
||||
onOptionsChange({ ...options, step })
|
||||
onOptionsChange({ ...options, labels: { ...options?.labels, button } })
|
||||
const handleMinChange = (
|
||||
min?: NonNullable<NumberInputBlock['options']>['min']
|
||||
) => onOptionsChange({ ...options, min })
|
||||
const handleMaxChange = (
|
||||
max?: NonNullable<NumberInputBlock['options']>['max']
|
||||
) => onOptionsChange({ ...options, max })
|
||||
const handleStepChange = (
|
||||
step?: NonNullable<NumberInputBlock['options']>['step']
|
||||
) => onOptionsChange({ ...options, step })
|
||||
const handleVariableChange = (variable?: Variable) => {
|
||||
onOptionsChange({ ...options, variableId: variable?.id })
|
||||
}
|
||||
@@ -28,27 +32,32 @@ export const NumberInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
<Stack spacing={4}>
|
||||
<TextInput
|
||||
label="Placeholder:"
|
||||
defaultValue={options.labels.placeholder}
|
||||
defaultValue={
|
||||
options?.labels?.placeholder ??
|
||||
defaultNumberInputOptions.labels.placeholder
|
||||
}
|
||||
onChange={handlePlaceholderChange}
|
||||
/>
|
||||
<TextInput
|
||||
label="Button label:"
|
||||
defaultValue={options?.labels?.button ?? 'Send'}
|
||||
defaultValue={
|
||||
options?.labels?.button ?? defaultNumberInputOptions.labels.button
|
||||
}
|
||||
onChange={handleButtonLabelChange}
|
||||
/>
|
||||
<NumberInput
|
||||
label="Min:"
|
||||
defaultValue={options.min}
|
||||
defaultValue={options?.min}
|
||||
onValueChange={handleMinChange}
|
||||
/>
|
||||
<NumberInput
|
||||
label="Max:"
|
||||
defaultValue={options.max}
|
||||
defaultValue={options?.max}
|
||||
onValueChange={handleMaxChange}
|
||||
/>
|
||||
<NumberInput
|
||||
label="Step:"
|
||||
defaultValue={options.step}
|
||||
defaultValue={options?.step}
|
||||
onValueChange={handleStepChange}
|
||||
/>
|
||||
<Stack>
|
||||
@@ -56,7 +65,7 @@ export const NumberInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
Save answer in a variable:
|
||||
</FormLabel>
|
||||
<VariableSearchInput
|
||||
initialVariableId={options.variableId}
|
||||
initialVariableId={options?.variableId}
|
||||
onSelectVariable={handleVariableChange}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
@@ -2,15 +2,19 @@ import React from 'react'
|
||||
import { Text } from '@chakra-ui/react'
|
||||
import { NumberInputBlock } from '@typebot.io/schemas'
|
||||
import { WithVariableContent } from '@/features/graph/components/nodes/block/WithVariableContent'
|
||||
import { defaultNumberInputOptions } from '@typebot.io/schemas/features/blocks/inputs/number/constants'
|
||||
|
||||
type Props = {
|
||||
variableId?: string
|
||||
placeholder: NumberInputBlock['options']['labels']['placeholder']
|
||||
options: NumberInputBlock['options']
|
||||
}
|
||||
|
||||
export const NumberNodeContent = ({ variableId, placeholder }: Props) =>
|
||||
export const NumberNodeContent = ({
|
||||
options: { variableId, labels } = {},
|
||||
}: Props) =>
|
||||
variableId ? (
|
||||
<WithVariableContent variableId={variableId} />
|
||||
) : (
|
||||
<Text color={'gray.500'}>{placeholder}</Text>
|
||||
<Text color={'gray.500'}>
|
||||
{labels?.placeholder ?? defaultNumberInputOptions.labels.placeholder}
|
||||
</Text>
|
||||
)
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import test, { expect } from '@playwright/test'
|
||||
import { createTypebots } from '@typebot.io/lib/playwright/databaseActions'
|
||||
import { parseDefaultGroupWithBlock } from '@typebot.io/lib/playwright/databaseHelpers'
|
||||
import { defaultNumberInputOptions, InputBlockType } from '@typebot.io/schemas'
|
||||
import { createId } from '@paralleldrive/cuid2'
|
||||
import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/constants'
|
||||
import { defaultNumberInputOptions } from '@typebot.io/schemas/features/blocks/inputs/number/constants'
|
||||
|
||||
test.describe('Number input block', () => {
|
||||
test('options should work', async ({ page }) => {
|
||||
@@ -12,7 +13,6 @@ test.describe('Number input block', () => {
|
||||
id: typebotId,
|
||||
...parseDefaultGroupWithBlock({
|
||||
type: InputBlockType.NUMBER,
|
||||
options: defaultNumberInputOptions,
|
||||
}),
|
||||
},
|
||||
])
|
||||
|
||||
@@ -7,7 +7,7 @@ type Props = {
|
||||
|
||||
export const PaymentInputContent = ({ block }: Props) => {
|
||||
if (
|
||||
!block.options.amount ||
|
||||
!block.options?.amount ||
|
||||
!block.options.credentialsId ||
|
||||
!block.options.currency
|
||||
)
|
||||
|
||||
@@ -11,11 +11,7 @@ import {
|
||||
AccordionPanel,
|
||||
} from '@chakra-ui/react'
|
||||
import { DropdownList } from '@/components/DropdownList'
|
||||
import {
|
||||
PaymentAddress,
|
||||
PaymentInputOptions,
|
||||
PaymentProvider,
|
||||
} from '@typebot.io/schemas'
|
||||
import { PaymentAddress, PaymentInputBlock } from '@typebot.io/schemas'
|
||||
import React, { ChangeEvent } from 'react'
|
||||
import { currencies } from '../currencies'
|
||||
import { StripeConfigModal } from './StripeConfigModal'
|
||||
@@ -23,10 +19,14 @@ import { CredentialsDropdown } from '@/features/credentials/components/Credentia
|
||||
import { TextInput } from '@/components/inputs'
|
||||
import { useWorkspace } from '@/features/workspace/WorkspaceProvider'
|
||||
import { PaymentAddressSettings } from './PaymentAddressSettings'
|
||||
import {
|
||||
PaymentProvider,
|
||||
defaultPaymentInputOptions,
|
||||
} from '@typebot.io/schemas/features/blocks/inputs/payment/constants'
|
||||
|
||||
type Props = {
|
||||
options: PaymentInputOptions
|
||||
onOptionsChange: (options: PaymentInputOptions) => void
|
||||
options: PaymentInputBlock['options']
|
||||
onOptionsChange: (options: PaymentInputBlock['options']) => void
|
||||
}
|
||||
|
||||
export const PaymentSettings = ({ options, onOptionsChange }: Props) => {
|
||||
@@ -62,43 +62,43 @@ export const PaymentSettings = ({ options, onOptionsChange }: Props) => {
|
||||
const updateName = (name: string) =>
|
||||
onOptionsChange({
|
||||
...options,
|
||||
additionalInformation: { ...options.additionalInformation, name },
|
||||
additionalInformation: { ...options?.additionalInformation, name },
|
||||
})
|
||||
|
||||
const updateEmail = (email: string) =>
|
||||
onOptionsChange({
|
||||
...options,
|
||||
additionalInformation: { ...options.additionalInformation, email },
|
||||
additionalInformation: { ...options?.additionalInformation, email },
|
||||
})
|
||||
|
||||
const updatePhoneNumber = (phoneNumber: string) =>
|
||||
onOptionsChange({
|
||||
...options,
|
||||
additionalInformation: { ...options.additionalInformation, phoneNumber },
|
||||
additionalInformation: { ...options?.additionalInformation, phoneNumber },
|
||||
})
|
||||
|
||||
const updateButtonLabel = (button: string) =>
|
||||
onOptionsChange({
|
||||
...options,
|
||||
labels: { ...options.labels, button },
|
||||
labels: { ...options?.labels, button },
|
||||
})
|
||||
|
||||
const updateSuccessLabel = (success: string) =>
|
||||
onOptionsChange({
|
||||
...options,
|
||||
labels: { ...options.labels, success },
|
||||
labels: { ...options?.labels, success },
|
||||
})
|
||||
|
||||
const updateDescription = (description: string) =>
|
||||
onOptionsChange({
|
||||
...options,
|
||||
additionalInformation: { ...options.additionalInformation, description },
|
||||
additionalInformation: { ...options?.additionalInformation, description },
|
||||
})
|
||||
|
||||
const updateAddress = (address: PaymentAddress) =>
|
||||
onOptionsChange({
|
||||
...options,
|
||||
additionalInformation: { ...options.additionalInformation, address },
|
||||
additionalInformation: { ...options?.additionalInformation, address },
|
||||
})
|
||||
|
||||
return (
|
||||
@@ -108,7 +108,7 @@ export const PaymentSettings = ({ options, onOptionsChange }: Props) => {
|
||||
<DropdownList
|
||||
onItemSelect={updateProvider}
|
||||
items={Object.values(PaymentProvider)}
|
||||
currentItem={options.provider}
|
||||
currentItem={options?.provider ?? defaultPaymentInputOptions.provider}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack>
|
||||
@@ -117,7 +117,7 @@ export const PaymentSettings = ({ options, onOptionsChange }: Props) => {
|
||||
<CredentialsDropdown
|
||||
type="stripe"
|
||||
workspaceId={workspace.id}
|
||||
currentCredentialsId={options.credentialsId}
|
||||
currentCredentialsId={options?.credentialsId}
|
||||
onCredentialsSelect={updateCredentials}
|
||||
onCreateNewClick={onOpen}
|
||||
credentialsName="Stripe account"
|
||||
@@ -128,14 +128,14 @@ export const PaymentSettings = ({ options, onOptionsChange }: Props) => {
|
||||
<TextInput
|
||||
label="Price amount:"
|
||||
onChange={updateAmount}
|
||||
defaultValue={options.amount ?? ''}
|
||||
defaultValue={options?.amount}
|
||||
placeholder="30.00"
|
||||
/>
|
||||
<Stack>
|
||||
<Text>Currency:</Text>
|
||||
<Select
|
||||
placeholder="Select option"
|
||||
value={options.currency}
|
||||
value={options?.currency ?? defaultPaymentInputOptions.currency}
|
||||
onChange={updateCurrency}
|
||||
>
|
||||
{currencies.map((currency) => (
|
||||
@@ -149,14 +149,16 @@ export const PaymentSettings = ({ options, onOptionsChange }: Props) => {
|
||||
<TextInput
|
||||
label="Button label:"
|
||||
onChange={updateButtonLabel}
|
||||
defaultValue={options.labels.button}
|
||||
placeholder="Pay"
|
||||
defaultValue={
|
||||
options?.labels?.button ?? defaultPaymentInputOptions.labels.button
|
||||
}
|
||||
/>
|
||||
<TextInput
|
||||
label="Success message:"
|
||||
onChange={updateSuccessLabel}
|
||||
defaultValue={options.labels.success ?? 'Success'}
|
||||
placeholder="Success"
|
||||
defaultValue={
|
||||
options?.labels?.success ?? defaultPaymentInputOptions.labels.success
|
||||
}
|
||||
/>
|
||||
<Accordion allowToggle>
|
||||
<AccordionItem>
|
||||
@@ -167,30 +169,30 @@ export const PaymentSettings = ({ options, onOptionsChange }: Props) => {
|
||||
<AccordionPanel py={4} as={Stack} spacing="6">
|
||||
<TextInput
|
||||
label="Description:"
|
||||
defaultValue={options.additionalInformation?.description ?? ''}
|
||||
defaultValue={options?.additionalInformation?.description}
|
||||
onChange={updateDescription}
|
||||
placeholder="A digital product"
|
||||
/>
|
||||
<TextInput
|
||||
label="Name:"
|
||||
defaultValue={options.additionalInformation?.name ?? ''}
|
||||
defaultValue={options?.additionalInformation?.name}
|
||||
onChange={updateName}
|
||||
placeholder="John Smith"
|
||||
/>
|
||||
<TextInput
|
||||
label="Email:"
|
||||
defaultValue={options.additionalInformation?.email ?? ''}
|
||||
defaultValue={options?.additionalInformation?.email}
|
||||
onChange={updateEmail}
|
||||
placeholder="john@gmail.com"
|
||||
/>
|
||||
<TextInput
|
||||
label="Phone number:"
|
||||
defaultValue={options.additionalInformation?.phoneNumber ?? ''}
|
||||
defaultValue={options?.additionalInformation?.phoneNumber}
|
||||
onChange={updatePhoneNumber}
|
||||
placeholder="+33XXXXXXXXX"
|
||||
/>
|
||||
<PaymentAddressSettings
|
||||
address={options.additionalInformation?.address}
|
||||
address={options?.additionalInformation?.address}
|
||||
onAddressChange={updateAddress}
|
||||
/>
|
||||
</AccordionPanel>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import test, { expect } from '@playwright/test'
|
||||
import { createTypebots } from '@typebot.io/lib/playwright/databaseActions'
|
||||
import { parseDefaultGroupWithBlock } from '@typebot.io/lib/playwright/databaseHelpers'
|
||||
import { defaultPaymentInputOptions, InputBlockType } from '@typebot.io/schemas'
|
||||
import { createId } from '@paralleldrive/cuid2'
|
||||
import { stripePaymentForm } from '@/test/utils/selectorUtils'
|
||||
import { env } from '@typebot.io/env'
|
||||
import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/constants'
|
||||
|
||||
test.describe('Payment input block', () => {
|
||||
test('Can configure Stripe account', async ({ page }) => {
|
||||
@@ -14,7 +14,6 @@ test.describe('Payment input block', () => {
|
||||
id: typebotId,
|
||||
...parseDefaultGroupWithBlock({
|
||||
type: InputBlockType.PAYMENT,
|
||||
options: defaultPaymentInputOptions,
|
||||
}),
|
||||
},
|
||||
])
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
import { TextInput } from '@/components/inputs'
|
||||
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
||||
import { FormLabel, Stack } from '@chakra-ui/react'
|
||||
import { PhoneNumberInputOptions, Variable } from '@typebot.io/schemas'
|
||||
import { PhoneNumberInputBlock, Variable } from '@typebot.io/schemas'
|
||||
import React from 'react'
|
||||
import { CountryCodeSelect } from './CountryCodeSelect'
|
||||
import { defaultPhoneInputOptions } from '@typebot.io/schemas/features/blocks/inputs/phone/constants'
|
||||
|
||||
type Props = {
|
||||
options: PhoneNumberInputOptions
|
||||
onOptionsChange: (options: PhoneNumberInputOptions) => void
|
||||
options: PhoneNumberInputBlock['options']
|
||||
onOptionsChange: (options: PhoneNumberInputBlock['options']) => void
|
||||
}
|
||||
|
||||
export const PhoneInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
const handlePlaceholderChange = (placeholder: string) =>
|
||||
onOptionsChange({ ...options, labels: { ...options.labels, placeholder } })
|
||||
onOptionsChange({ ...options, labels: { ...options?.labels, placeholder } })
|
||||
const handleButtonLabelChange = (button: string) =>
|
||||
onOptionsChange({ ...options, labels: { ...options.labels, button } })
|
||||
onOptionsChange({ ...options, labels: { ...options?.labels, button } })
|
||||
const handleVariableChange = (variable?: Variable) =>
|
||||
onOptionsChange({ ...options, variableId: variable?.id })
|
||||
const handleRetryMessageChange = (retryMessageContent: string) =>
|
||||
@@ -26,12 +27,17 @@ export const PhoneInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
<Stack spacing={4}>
|
||||
<TextInput
|
||||
label="Placeholder:"
|
||||
defaultValue={options.labels.placeholder}
|
||||
defaultValue={
|
||||
options?.labels?.placeholder ??
|
||||
defaultPhoneInputOptions.labels.placeholder
|
||||
}
|
||||
onChange={handlePlaceholderChange}
|
||||
/>
|
||||
<TextInput
|
||||
label="Button label:"
|
||||
defaultValue={options.labels.button}
|
||||
defaultValue={
|
||||
options?.labels?.button ?? defaultPhoneInputOptions.labels.button
|
||||
}
|
||||
onChange={handleButtonLabelChange}
|
||||
/>
|
||||
<Stack>
|
||||
@@ -40,12 +46,15 @@ export const PhoneInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
</FormLabel>
|
||||
<CountryCodeSelect
|
||||
onSelect={handleDefaultCountryChange}
|
||||
countryCode={options.defaultCountryCode}
|
||||
countryCode={options?.defaultCountryCode}
|
||||
/>
|
||||
</Stack>
|
||||
<TextInput
|
||||
label="Retry message:"
|
||||
defaultValue={options.retryMessageContent}
|
||||
defaultValue={
|
||||
options?.retryMessageContent ??
|
||||
defaultPhoneInputOptions.retryMessageContent
|
||||
}
|
||||
onChange={handleRetryMessageChange}
|
||||
/>
|
||||
<Stack>
|
||||
@@ -53,7 +62,7 @@ export const PhoneInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
Save answer in a variable:
|
||||
</FormLabel>
|
||||
<VariableSearchInput
|
||||
initialVariableId={options.variableId}
|
||||
initialVariableId={options?.variableId}
|
||||
onSelectVariable={handleVariableChange}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
import React from 'react'
|
||||
import { Text } from '@chakra-ui/react'
|
||||
import { PhoneNumberInputOptions } from '@typebot.io/schemas'
|
||||
import { WithVariableContent } from '@/features/graph/components/nodes/block/WithVariableContent'
|
||||
import { PhoneNumberInputBlock } from '@typebot.io/schemas'
|
||||
import { defaultPhoneInputOptions } from '@typebot.io/schemas/features/blocks/inputs/phone/constants'
|
||||
|
||||
type Props = {
|
||||
variableId?: string
|
||||
placeholder: PhoneNumberInputOptions['labels']['placeholder']
|
||||
options: PhoneNumberInputBlock['options']
|
||||
}
|
||||
|
||||
export const PhoneNodeContent = ({ variableId, placeholder }: Props) =>
|
||||
export const PhoneNodeContent = ({
|
||||
options: { variableId, labels } = {},
|
||||
}: Props) =>
|
||||
variableId ? (
|
||||
<WithVariableContent variableId={variableId} />
|
||||
) : (
|
||||
<Text color={'gray.500'}>{placeholder}</Text>
|
||||
<Text color={'gray.500'}>
|
||||
{labels?.placeholder ?? defaultPhoneInputOptions.labels.placeholder}
|
||||
</Text>
|
||||
)
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import test, { expect } from '@playwright/test'
|
||||
import { createTypebots } from '@typebot.io/lib/playwright/databaseActions'
|
||||
import { parseDefaultGroupWithBlock } from '@typebot.io/lib/playwright/databaseHelpers'
|
||||
import { defaultPhoneInputOptions, InputBlockType } from '@typebot.io/schemas'
|
||||
import { createId } from '@paralleldrive/cuid2'
|
||||
import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/constants'
|
||||
import { defaultPhoneInputOptions } from '@typebot.io/schemas/features/blocks/inputs/phone/constants'
|
||||
|
||||
test.describe('Phone input block', () => {
|
||||
test('options should work', async ({ page }) => {
|
||||
@@ -12,7 +13,6 @@ test.describe('Phone input block', () => {
|
||||
id: typebotId,
|
||||
...parseDefaultGroupWithBlock({
|
||||
type: InputBlockType.PHONE,
|
||||
options: defaultPhoneInputOptions,
|
||||
}),
|
||||
},
|
||||
])
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
} from '@chakra-ui/react'
|
||||
import { ImageIcon, PlusIcon } from '@/components/icons'
|
||||
import { useTypebot } from '@/features/editor/providers/TypebotProvider'
|
||||
import { ItemIndices, ItemType } from '@typebot.io/schemas'
|
||||
import { ItemIndices } from '@typebot.io/schemas'
|
||||
import React, { useRef } from 'react'
|
||||
import { PictureChoiceItem } from '@typebot.io/schemas/features/blocks/inputs/pictureChoice'
|
||||
import { useGraph } from '@/features/graph/providers/GraphProvider'
|
||||
@@ -40,7 +40,7 @@ export const PictureChoiceItemNode = ({
|
||||
const handlePlusClick = (e: React.MouseEvent) => {
|
||||
e.stopPropagation()
|
||||
const itemIndex = indices.itemIndex + 1
|
||||
createItem({ type: ItemType.PICTURE_CHOICE }, { ...indices, itemIndex })
|
||||
createItem({}, { ...indices, itemIndex })
|
||||
}
|
||||
|
||||
const handleMouseDown = (e: React.MouseEvent) => e.stopPropagation()
|
||||
|
||||
@@ -13,7 +13,8 @@ import {
|
||||
import { ImageUploadContent } from '@/components/ImageUploadContent'
|
||||
import { SwitchWithRelatedSettings } from '@/components/SwitchWithRelatedSettings'
|
||||
import { ConditionForm } from '@/features/blocks/logic/condition/components/ConditionForm'
|
||||
import { Condition, LogicalOperator } from '@typebot.io/schemas'
|
||||
import { Condition } from '@typebot.io/schemas'
|
||||
import { LogicalOperator } from '@typebot.io/schemas/features/blocks/logic/condition/constants'
|
||||
|
||||
type Props = {
|
||||
workspaceId: string
|
||||
|
||||
@@ -15,12 +15,12 @@ export const PictureChoiceNode = ({ block, indices }: Props) => {
|
||||
const { typebot } = useTypebot()
|
||||
const dynamicVariableName = typebot?.variables.find(
|
||||
(variable) =>
|
||||
variable.id === block.options.dynamicItems?.pictureSrcsVariableId
|
||||
variable.id === block.options?.dynamicItems?.pictureSrcsVariableId
|
||||
)?.name
|
||||
|
||||
return (
|
||||
<Stack w="full">
|
||||
{block.options.dynamicItems?.isEnabled && dynamicVariableName ? (
|
||||
{block.options?.dynamicItems?.isEnabled && dynamicVariableName ? (
|
||||
<Wrap spacing={1}>
|
||||
<Text>Display</Text>
|
||||
<Tag bg="orange.400" color="white">
|
||||
@@ -31,7 +31,7 @@ export const PictureChoiceNode = ({ block, indices }: Props) => {
|
||||
) : (
|
||||
<ItemNodesList block={block} indices={indices} />
|
||||
)}
|
||||
{block.options.variableId ? (
|
||||
{block.options?.variableId ? (
|
||||
<SetVariableLabel
|
||||
variableId={block.options.variableId}
|
||||
variables={typebot?.variables}
|
||||
|
||||
@@ -3,11 +3,9 @@ import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
||||
import { FormLabel, Stack } from '@chakra-ui/react'
|
||||
import { Variable } from '@typebot.io/schemas'
|
||||
import React from 'react'
|
||||
import {
|
||||
PictureChoiceBlock,
|
||||
defaultPictureChoiceOptions,
|
||||
} from '@typebot.io/schemas/features/blocks/inputs/pictureChoice'
|
||||
import { PictureChoiceBlock } from '@typebot.io/schemas/features/blocks/inputs/pictureChoice'
|
||||
import { SwitchWithRelatedSettings } from '@/components/SwitchWithRelatedSettings'
|
||||
import { defaultPictureChoiceOptions } from '@typebot.io/schemas/features/blocks/inputs/pictureChoice/constants'
|
||||
|
||||
type Props = {
|
||||
options?: PictureChoiceBlock['options']
|
||||
@@ -16,52 +14,48 @@ type Props = {
|
||||
|
||||
export const PictureChoiceSettings = ({ options, onOptionsChange }: Props) => {
|
||||
const updateIsMultiple = (isMultipleChoice: boolean) =>
|
||||
options && onOptionsChange({ ...options, isMultipleChoice })
|
||||
onOptionsChange({ ...options, isMultipleChoice })
|
||||
const updateButtonLabel = (buttonLabel: string) =>
|
||||
options && onOptionsChange({ ...options, buttonLabel })
|
||||
onOptionsChange({ ...options, buttonLabel })
|
||||
const updateSaveVariable = (variable?: Variable) =>
|
||||
options && onOptionsChange({ ...options, variableId: variable?.id })
|
||||
onOptionsChange({ ...options, variableId: variable?.id })
|
||||
const updateSearchInputPlaceholder = (searchInputPlaceholder: string) =>
|
||||
options && onOptionsChange({ ...options, searchInputPlaceholder })
|
||||
onOptionsChange({ ...options, searchInputPlaceholder })
|
||||
const updateIsSearchable = (isSearchable: boolean) =>
|
||||
options && onOptionsChange({ ...options, isSearchable })
|
||||
onOptionsChange({ ...options, isSearchable })
|
||||
|
||||
const updateIsDynamicItemsEnabled = (isEnabled: boolean) =>
|
||||
options &&
|
||||
onOptionsChange({
|
||||
...options,
|
||||
dynamicItems: {
|
||||
...options.dynamicItems,
|
||||
...options?.dynamicItems,
|
||||
isEnabled,
|
||||
},
|
||||
})
|
||||
|
||||
const updateDynamicItemsPictureSrcsVariable = (variable?: Variable) =>
|
||||
options &&
|
||||
onOptionsChange({
|
||||
...options,
|
||||
dynamicItems: {
|
||||
...options.dynamicItems,
|
||||
...options?.dynamicItems,
|
||||
pictureSrcsVariableId: variable?.id,
|
||||
},
|
||||
})
|
||||
|
||||
const updateDynamicItemsTitlesVariable = (variable?: Variable) =>
|
||||
options &&
|
||||
onOptionsChange({
|
||||
...options,
|
||||
dynamicItems: {
|
||||
...options.dynamicItems,
|
||||
...options?.dynamicItems,
|
||||
titlesVariableId: variable?.id,
|
||||
},
|
||||
})
|
||||
|
||||
const updateDynamicItemsDescriptionsVariable = (variable?: Variable) =>
|
||||
options &&
|
||||
onOptionsChange({
|
||||
...options,
|
||||
dynamicItems: {
|
||||
...options.dynamicItems,
|
||||
...options?.dynamicItems,
|
||||
descriptionsVariableId: variable?.id,
|
||||
},
|
||||
})
|
||||
@@ -70,7 +64,9 @@ export const PictureChoiceSettings = ({ options, onOptionsChange }: Props) => {
|
||||
<Stack spacing={4}>
|
||||
<SwitchWithRelatedSettings
|
||||
label="Is searchable?"
|
||||
initialValue={options?.isSearchable ?? false}
|
||||
initialValue={
|
||||
options?.isSearchable ?? defaultPictureChoiceOptions.isSearchable
|
||||
}
|
||||
onCheckChange={updateIsSearchable}
|
||||
>
|
||||
<TextInput
|
||||
@@ -84,19 +80,27 @@ export const PictureChoiceSettings = ({ options, onOptionsChange }: Props) => {
|
||||
</SwitchWithRelatedSettings>
|
||||
<SwitchWithRelatedSettings
|
||||
label="Multiple choice?"
|
||||
initialValue={options?.isMultipleChoice ?? false}
|
||||
initialValue={
|
||||
options?.isMultipleChoice ??
|
||||
defaultPictureChoiceOptions.isMultipleChoice
|
||||
}
|
||||
onCheckChange={updateIsMultiple}
|
||||
>
|
||||
<TextInput
|
||||
label="Submit button label:"
|
||||
defaultValue={options?.buttonLabel ?? 'Send'}
|
||||
defaultValue={
|
||||
options?.buttonLabel ?? defaultPictureChoiceOptions.buttonLabel
|
||||
}
|
||||
onChange={updateButtonLabel}
|
||||
/>
|
||||
</SwitchWithRelatedSettings>
|
||||
|
||||
<SwitchWithRelatedSettings
|
||||
label="Dynamic items?"
|
||||
initialValue={options?.dynamicItems?.isEnabled ?? false}
|
||||
initialValue={
|
||||
options?.dynamicItems?.isEnabled ??
|
||||
defaultPictureChoiceOptions.dynamicItems.isEnabled
|
||||
}
|
||||
onCheckChange={updateIsDynamicItemsEnabled}
|
||||
>
|
||||
<Stack>
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import test, { expect } from '@playwright/test'
|
||||
import { createTypebots } from '@typebot.io/lib/playwright/databaseActions'
|
||||
import { parseDefaultGroupWithBlock } from '@typebot.io/lib/playwright/databaseHelpers'
|
||||
import { InputBlockType, ItemType } from '@typebot.io/schemas'
|
||||
import { createId } from '@paralleldrive/cuid2'
|
||||
import { defaultPictureChoiceOptions } from '@typebot.io/schemas/features/blocks/inputs/pictureChoice'
|
||||
import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/constants'
|
||||
|
||||
const firstImageSrc =
|
||||
'https://images.unsplash.com/flagged/photo-1575517111839-3a3843ee7f5d?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2940&q=80'
|
||||
@@ -25,10 +24,8 @@ test.describe.parallel('Picture choice input block', () => {
|
||||
items: [
|
||||
{
|
||||
id: 'choice1',
|
||||
type: ItemType.PICTURE_CHOICE,
|
||||
},
|
||||
],
|
||||
options: { ...defaultPictureChoiceOptions },
|
||||
}),
|
||||
},
|
||||
])
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { WithVariableContent } from '@/features/graph/components/nodes/block/WithVariableContent'
|
||||
import { Text } from '@chakra-ui/react'
|
||||
import { RatingInputBlock } from '@typebot.io/schemas'
|
||||
import { defaultRatingInputOptions } from '@typebot.io/schemas/features/blocks/inputs/rating/constants'
|
||||
|
||||
type Props = {
|
||||
variableId?: string
|
||||
@@ -12,7 +13,7 @@ export const RatingInputContent = ({ variableId, block }: Props) =>
|
||||
<WithVariableContent variableId={variableId} />
|
||||
) : (
|
||||
<Text noOfLines={1} pr="6">
|
||||
Rate from {block.options.buttonType === 'Icons' ? 1 : 0} to{' '}
|
||||
{block.options.length}
|
||||
Rate from {block.options?.buttonType === 'Icons' ? 1 : 0} to{' '}
|
||||
{block.options?.length ?? defaultRatingInputOptions.length}
|
||||
</Text>
|
||||
)
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import { FormLabel, Stack } from '@chakra-ui/react'
|
||||
import { DropdownList } from '@/components/DropdownList'
|
||||
import { RatingInputOptions, Variable } from '@typebot.io/schemas'
|
||||
import { RatingInputBlock, Variable } from '@typebot.io/schemas'
|
||||
import React from 'react'
|
||||
import { SwitchWithLabel } from '@/components/inputs/SwitchWithLabel'
|
||||
import { TextInput } from '@/components/inputs'
|
||||
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
||||
import { defaultRatingInputOptions } from '@typebot.io/schemas/features/blocks/inputs/rating/constants'
|
||||
|
||||
type Props = {
|
||||
options: RatingInputOptions
|
||||
onOptionsChange: (options: RatingInputOptions) => void
|
||||
options: RatingInputBlock['options']
|
||||
onOptionsChange: (options: RatingInputBlock['options']) => void
|
||||
}
|
||||
|
||||
export const RatingInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
@@ -21,20 +22,20 @@ export const RatingInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
const handleCustomIconCheck = (isEnabled: boolean) =>
|
||||
onOptionsChange({
|
||||
...options,
|
||||
customIcon: { ...options.customIcon, isEnabled },
|
||||
customIcon: { ...options?.customIcon, isEnabled },
|
||||
})
|
||||
|
||||
const handleIconSvgChange = (svg: string) =>
|
||||
onOptionsChange({ ...options, customIcon: { ...options.customIcon, svg } })
|
||||
onOptionsChange({ ...options, customIcon: { ...options?.customIcon, svg } })
|
||||
|
||||
const handleLeftLabelChange = (left: string) =>
|
||||
onOptionsChange({ ...options, labels: { ...options.labels, left } })
|
||||
onOptionsChange({ ...options, labels: { ...options?.labels, left } })
|
||||
|
||||
const handleRightLabelChange = (right: string) =>
|
||||
onOptionsChange({ ...options, labels: { ...options.labels, right } })
|
||||
onOptionsChange({ ...options, labels: { ...options?.labels, right } })
|
||||
|
||||
const handleButtonLabelChange = (button: string) =>
|
||||
onOptionsChange({ ...options, labels: { ...options.labels, button } })
|
||||
onOptionsChange({ ...options, labels: { ...options?.labels, button } })
|
||||
|
||||
const handleVariableChange = (variable?: Variable) =>
|
||||
onOptionsChange({ ...options, variableId: variable?.id })
|
||||
@@ -42,6 +43,11 @@ export const RatingInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
const handleOneClickSubmitChange = (isOneClickSubmitEnabled: boolean) =>
|
||||
onOptionsChange({ ...options, isOneClickSubmitEnabled })
|
||||
|
||||
const length = options?.length ?? defaultRatingInputOptions.length
|
||||
const isOneClickSubmitEnabled =
|
||||
options?.isOneClickSubmitEnabled ??
|
||||
defaultRatingInputOptions.isOneClickSubmitEnabled
|
||||
|
||||
return (
|
||||
<Stack spacing={4}>
|
||||
<Stack>
|
||||
@@ -51,7 +57,7 @@ export const RatingInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
<DropdownList
|
||||
onItemSelect={handleLengthChange}
|
||||
items={[3, 4, 5, 6, 7, 8, 9, 10]}
|
||||
currentItem={options.length}
|
||||
currentItem={length}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
@@ -62,18 +68,23 @@ export const RatingInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
<DropdownList
|
||||
onItemSelect={handleTypeChange}
|
||||
items={['Icons', 'Numbers'] as const}
|
||||
currentItem={options.buttonType}
|
||||
currentItem={
|
||||
options?.buttonType ?? defaultRatingInputOptions.buttonType
|
||||
}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
{options.buttonType === 'Icons' && (
|
||||
{options?.buttonType === 'Icons' && (
|
||||
<SwitchWithLabel
|
||||
label="Custom icon?"
|
||||
initialValue={options.customIcon.isEnabled}
|
||||
initialValue={
|
||||
options?.customIcon?.isEnabled ??
|
||||
defaultRatingInputOptions.customIcon.isEnabled
|
||||
}
|
||||
onCheckChange={handleCustomIconCheck}
|
||||
/>
|
||||
)}
|
||||
{options.buttonType === 'Icons' && options.customIcon.isEnabled && (
|
||||
{options?.buttonType === 'Icons' && options.customIcon?.isEnabled && (
|
||||
<TextInput
|
||||
label="Icon SVG:"
|
||||
defaultValue={options.customIcon.svg}
|
||||
@@ -82,27 +93,29 @@ export const RatingInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
/>
|
||||
)}
|
||||
<TextInput
|
||||
label={`${options.buttonType === 'Icons' ? '1' : '0'} label:`}
|
||||
defaultValue={options.labels.left}
|
||||
label={`${options?.buttonType === 'Icons' ? '1' : '0'} label:`}
|
||||
defaultValue={options?.labels?.left}
|
||||
onChange={handleLeftLabelChange}
|
||||
placeholder="Not likely at all"
|
||||
/>
|
||||
<TextInput
|
||||
label={`${options.length} label:`}
|
||||
defaultValue={options.labels.right}
|
||||
label={`${length} label:`}
|
||||
defaultValue={options?.labels?.right}
|
||||
onChange={handleRightLabelChange}
|
||||
placeholder="Extremely likely"
|
||||
/>
|
||||
<SwitchWithLabel
|
||||
label="One click submit"
|
||||
moreInfoContent='If enabled, the answer will be submitted as soon as the user clicks on a rating instead of showing the "Send" button.'
|
||||
initialValue={options.isOneClickSubmitEnabled ?? false}
|
||||
initialValue={isOneClickSubmitEnabled}
|
||||
onCheckChange={handleOneClickSubmitChange}
|
||||
/>
|
||||
{!options.isOneClickSubmitEnabled && (
|
||||
{!isOneClickSubmitEnabled && (
|
||||
<TextInput
|
||||
label="Button label:"
|
||||
defaultValue={options.labels.button}
|
||||
defaultValue={
|
||||
options?.labels?.button ?? defaultRatingInputOptions.labels.button
|
||||
}
|
||||
onChange={handleButtonLabelChange}
|
||||
/>
|
||||
)}
|
||||
@@ -111,7 +124,7 @@ export const RatingInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
Save answer in a variable:
|
||||
</FormLabel>
|
||||
<VariableSearchInput
|
||||
initialVariableId={options.variableId}
|
||||
initialVariableId={options?.variableId}
|
||||
onSelectVariable={handleVariableChange}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import test, { expect } from '@playwright/test'
|
||||
import { createTypebots } from '@typebot.io/lib/playwright/databaseActions'
|
||||
import { parseDefaultGroupWithBlock } from '@typebot.io/lib/playwright/databaseHelpers'
|
||||
import { defaultRatingInputOptions, InputBlockType } from '@typebot.io/schemas'
|
||||
import { createId } from '@paralleldrive/cuid2'
|
||||
import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/constants'
|
||||
|
||||
const boxSvg = `<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@@ -24,7 +24,6 @@ test('options should work', async ({ page }) => {
|
||||
id: typebotId,
|
||||
...parseDefaultGroupWithBlock({
|
||||
type: InputBlockType.RATING,
|
||||
options: defaultRatingInputOptions,
|
||||
}),
|
||||
},
|
||||
])
|
||||
|
||||
@@ -1,29 +1,25 @@
|
||||
import React from 'react'
|
||||
import { Text } from '@chakra-ui/react'
|
||||
import { TextInputOptions } from '@typebot.io/schemas'
|
||||
import { WithVariableContent } from '@/features/graph/components/nodes/block/WithVariableContent'
|
||||
import { TextInputBlock } from '@typebot.io/schemas'
|
||||
import { defaultTextInputOptions } from '@typebot.io/schemas/features/blocks/inputs/text/constants'
|
||||
|
||||
type Props = {
|
||||
placeholder: TextInputOptions['labels']['placeholder']
|
||||
isLong: TextInputOptions['isLong']
|
||||
variableId?: string
|
||||
options: TextInputBlock['options']
|
||||
}
|
||||
|
||||
export const TextInputNodeContent = ({
|
||||
placeholder,
|
||||
isLong,
|
||||
variableId,
|
||||
}: Props) => {
|
||||
if (variableId)
|
||||
export const TextInputNodeContent = ({ options }: Props) => {
|
||||
if (options?.variableId)
|
||||
return (
|
||||
<WithVariableContent
|
||||
variableId={variableId}
|
||||
h={isLong ? '100px' : 'auto'}
|
||||
variableId={options?.variableId}
|
||||
h={options.isLong ? '100px' : 'auto'}
|
||||
/>
|
||||
)
|
||||
return (
|
||||
<Text color={'gray.500'} h={isLong ? '100px' : 'auto'}>
|
||||
{placeholder}
|
||||
<Text color={'gray.500'} h={options?.isLong ? '100px' : 'auto'}>
|
||||
{options?.labels?.placeholder ??
|
||||
defaultTextInputOptions.labels.placeholder}
|
||||
</Text>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,19 +2,20 @@ import { TextInput } from '@/components/inputs'
|
||||
import { SwitchWithLabel } from '@/components/inputs/SwitchWithLabel'
|
||||
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
||||
import { FormLabel, Stack } from '@chakra-ui/react'
|
||||
import { TextInputOptions, Variable } from '@typebot.io/schemas'
|
||||
import { TextInputBlock, Variable } from '@typebot.io/schemas'
|
||||
import { defaultTextInputOptions } from '@typebot.io/schemas/features/blocks/inputs/text/constants'
|
||||
import React from 'react'
|
||||
|
||||
type Props = {
|
||||
options: TextInputOptions
|
||||
onOptionsChange: (options: TextInputOptions) => void
|
||||
options: TextInputBlock['options']
|
||||
onOptionsChange: (options: TextInputBlock['options']) => void
|
||||
}
|
||||
|
||||
export const TextInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
const handlePlaceholderChange = (placeholder: string) =>
|
||||
onOptionsChange({ ...options, labels: { ...options.labels, placeholder } })
|
||||
onOptionsChange({ ...options, labels: { ...options?.labels, placeholder } })
|
||||
const handleButtonLabelChange = (button: string) =>
|
||||
onOptionsChange({ ...options, labels: { ...options.labels, button } })
|
||||
onOptionsChange({ ...options, labels: { ...options?.labels, button } })
|
||||
const handleLongChange = (isLong: boolean) =>
|
||||
onOptionsChange({ ...options, isLong })
|
||||
const handleVariableChange = (variable?: Variable) =>
|
||||
@@ -24,17 +25,22 @@ export const TextInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
<Stack spacing={4}>
|
||||
<SwitchWithLabel
|
||||
label="Long text?"
|
||||
initialValue={options?.isLong ?? false}
|
||||
initialValue={options?.isLong ?? defaultTextInputOptions.isLong}
|
||||
onCheckChange={handleLongChange}
|
||||
/>
|
||||
<TextInput
|
||||
label="Placeholder:"
|
||||
defaultValue={options.labels.placeholder}
|
||||
defaultValue={
|
||||
options?.labels?.placeholder ??
|
||||
defaultTextInputOptions.labels.placeholder
|
||||
}
|
||||
onChange={handlePlaceholderChange}
|
||||
/>
|
||||
<TextInput
|
||||
label="Button label:"
|
||||
defaultValue={options.labels.button}
|
||||
defaultValue={
|
||||
options?.labels?.button ?? defaultTextInputOptions.labels.button
|
||||
}
|
||||
onChange={handleButtonLabelChange}
|
||||
/>
|
||||
<Stack>
|
||||
@@ -42,7 +48,7 @@ export const TextInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
Save answer in a variable:
|
||||
</FormLabel>
|
||||
<VariableSearchInput
|
||||
initialVariableId={options.variableId}
|
||||
initialVariableId={options?.variableId}
|
||||
onSelectVariable={handleVariableChange}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import test, { expect } from '@playwright/test'
|
||||
import { createTypebots } from '@typebot.io/lib/playwright/databaseActions'
|
||||
import { parseDefaultGroupWithBlock } from '@typebot.io/lib/playwright/databaseHelpers'
|
||||
import { defaultTextInputOptions, InputBlockType } from '@typebot.io/schemas'
|
||||
import { createId } from '@paralleldrive/cuid2'
|
||||
import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/constants'
|
||||
import { defaultTextInputOptions } from '@typebot.io/schemas/features/blocks/inputs/text/constants'
|
||||
|
||||
test.describe.parallel('Text input block', () => {
|
||||
test('options should work', async ({ page }) => {
|
||||
@@ -12,7 +13,6 @@ test.describe.parallel('Text input block', () => {
|
||||
id: typebotId,
|
||||
...parseDefaultGroupWithBlock({
|
||||
type: InputBlockType.TEXT,
|
||||
options: defaultTextInputOptions,
|
||||
}),
|
||||
},
|
||||
])
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
import { TextInput } from '@/components/inputs'
|
||||
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
||||
import { FormLabel, Stack } from '@chakra-ui/react'
|
||||
import { UrlInputOptions, Variable } from '@typebot.io/schemas'
|
||||
import { UrlInputBlock, Variable } from '@typebot.io/schemas'
|
||||
import { defaultUrlInputOptions } from '@typebot.io/schemas/features/blocks/inputs/url/constants'
|
||||
import React from 'react'
|
||||
|
||||
type Props = {
|
||||
options: UrlInputOptions
|
||||
onOptionsChange: (options: UrlInputOptions) => void
|
||||
options: UrlInputBlock['options']
|
||||
onOptionsChange: (options: UrlInputBlock['options']) => void
|
||||
}
|
||||
|
||||
export const UrlInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
const handlePlaceholderChange = (placeholder: string) =>
|
||||
onOptionsChange({ ...options, labels: { ...options.labels, placeholder } })
|
||||
onOptionsChange({ ...options, labels: { ...options?.labels, placeholder } })
|
||||
const handleButtonLabelChange = (button: string) =>
|
||||
onOptionsChange({ ...options, labels: { ...options.labels, button } })
|
||||
onOptionsChange({ ...options, labels: { ...options?.labels, button } })
|
||||
const handleVariableChange = (variable?: Variable) =>
|
||||
onOptionsChange({ ...options, variableId: variable?.id })
|
||||
const handleRetryMessageChange = (retryMessageContent: string) =>
|
||||
@@ -23,17 +24,25 @@ export const UrlInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
<Stack spacing={4}>
|
||||
<TextInput
|
||||
label="Placeholder:"
|
||||
defaultValue={options.labels.placeholder}
|
||||
defaultValue={
|
||||
options?.labels?.placeholder ??
|
||||
defaultUrlInputOptions.labels.placeholder
|
||||
}
|
||||
onChange={handlePlaceholderChange}
|
||||
/>
|
||||
<TextInput
|
||||
label="Button label:"
|
||||
defaultValue={options.labels.button}
|
||||
defaultValue={
|
||||
options?.labels?.button ?? defaultUrlInputOptions.labels.button
|
||||
}
|
||||
onChange={handleButtonLabelChange}
|
||||
/>
|
||||
<TextInput
|
||||
label="Retry message:"
|
||||
defaultValue={options.retryMessageContent}
|
||||
defaultValue={
|
||||
options?.retryMessageContent ??
|
||||
defaultUrlInputOptions.retryMessageContent
|
||||
}
|
||||
onChange={handleRetryMessageChange}
|
||||
/>
|
||||
<Stack>
|
||||
@@ -41,7 +50,7 @@ export const UrlInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
Save answer in a variable:
|
||||
</FormLabel>
|
||||
<VariableSearchInput
|
||||
initialVariableId={options.variableId}
|
||||
initialVariableId={options?.variableId}
|
||||
onSelectVariable={handleVariableChange}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
import React from 'react'
|
||||
import { Text } from '@chakra-ui/react'
|
||||
import { UrlInputOptions } from '@typebot.io/schemas'
|
||||
import { WithVariableContent } from '@/features/graph/components/nodes/block/WithVariableContent'
|
||||
import { UrlInputBlock } from '@typebot.io/schemas'
|
||||
import { defaultUrlInputOptions } from '@typebot.io/schemas/features/blocks/inputs/url/constants'
|
||||
|
||||
type Props = {
|
||||
variableId?: string
|
||||
placeholder: UrlInputOptions['labels']['placeholder']
|
||||
options: UrlInputBlock['options']
|
||||
}
|
||||
|
||||
export const UrlNodeContent = ({ placeholder, variableId }: Props) =>
|
||||
variableId ? (
|
||||
<WithVariableContent variableId={variableId} />
|
||||
export const UrlNodeContent = ({ options }: Props) =>
|
||||
options?.variableId ? (
|
||||
<WithVariableContent variableId={options.variableId} />
|
||||
) : (
|
||||
<Text color={'gray.500'} w="90%">
|
||||
{placeholder}
|
||||
{options?.labels?.placeholder ??
|
||||
defaultUrlInputOptions.labels.placeholder}
|
||||
</Text>
|
||||
)
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import test, { expect } from '@playwright/test'
|
||||
import { createTypebots } from '@typebot.io/lib/playwright/databaseActions'
|
||||
import { parseDefaultGroupWithBlock } from '@typebot.io/lib/playwright/databaseHelpers'
|
||||
import { defaultUrlInputOptions, InputBlockType } from '@typebot.io/schemas'
|
||||
import { createId } from '@paralleldrive/cuid2'
|
||||
import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/constants'
|
||||
import { defaultUrlInputOptions } from '@typebot.io/schemas/features/blocks/inputs/url/constants'
|
||||
|
||||
test.describe('Url input block', () => {
|
||||
test('options should work', async ({ page }) => {
|
||||
@@ -12,7 +13,6 @@ test.describe('Url input block', () => {
|
||||
id: typebotId,
|
||||
...parseDefaultGroupWithBlock({
|
||||
type: InputBlockType.URL,
|
||||
options: defaultUrlInputOptions,
|
||||
}),
|
||||
},
|
||||
])
|
||||
|
||||
Reference in New Issue
Block a user