🌐 Add translation keys for input blocks (#1114)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Integrated localization support across various components using the `useTranslate` hook for dynamic translations. - **Enhancements** - Replaced hardcoded text with localized strings to support multiple languages in the user interface. - **User Interface** - Updated labels, placeholders, tooltips, and button texts to utilize translated content for a multilingual experience. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Baptiste Arnaud <baptiste.arnaud95@gmail.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import { useColorModeValue, HStack, Tag, Text } from '@chakra-ui/react'
|
import { useColorModeValue, HStack, Tag, Text } from '@chakra-ui/react'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
import { Variable } from '@typebot.io/schemas'
|
import { Variable } from '@typebot.io/schemas'
|
||||||
|
|
||||||
export const SetVariableLabel = ({
|
export const SetVariableLabel = ({
|
||||||
@@ -8,6 +9,7 @@ export const SetVariableLabel = ({
|
|||||||
variableId: string
|
variableId: string
|
||||||
variables?: Variable[]
|
variables?: Variable[]
|
||||||
}) => {
|
}) => {
|
||||||
|
const { t } = useTranslate()
|
||||||
const textColor = useColorModeValue('gray.600', 'gray.400')
|
const textColor = useColorModeValue('gray.600', 'gray.400')
|
||||||
const variableName = variables?.find(
|
const variableName = variables?.find(
|
||||||
(variable) => variable.id === variableId
|
(variable) => variable.id === variableId
|
||||||
@@ -17,7 +19,7 @@ export const SetVariableLabel = ({
|
|||||||
return (
|
return (
|
||||||
<HStack fontStyle="italic" spacing={1}>
|
<HStack fontStyle="italic" spacing={1}>
|
||||||
<Text fontSize="sm" color={textColor}>
|
<Text fontSize="sm" color={textColor}>
|
||||||
Set
|
{t('variables.set')}
|
||||||
</Text>
|
</Text>
|
||||||
<Tag bg="orange.400" color="white" size="sm">
|
<Tag bg="orange.400" color="white" size="sm">
|
||||||
{variableName}
|
{variableName}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import { byId, isDefined, isNotDefined } from '@typebot.io/lib'
|
|||||||
import { useOutsideClick } from '@/hooks/useOutsideClick'
|
import { useOutsideClick } from '@/hooks/useOutsideClick'
|
||||||
import { useParentModal } from '@/features/graph/providers/ParentModalProvider'
|
import { useParentModal } from '@/features/graph/providers/ParentModalProvider'
|
||||||
import { MoreInfoTooltip } from '../MoreInfoTooltip'
|
import { MoreInfoTooltip } from '../MoreInfoTooltip'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
initialVariableId: string | undefined
|
initialVariableId: string | undefined
|
||||||
@@ -78,6 +79,7 @@ export const VariableSearchInput = ({
|
|||||||
const createVariableItemRef = useRef<HTMLButtonElement | null>(null)
|
const createVariableItemRef = useRef<HTMLButtonElement | null>(null)
|
||||||
const itemsRef = useRef<(HTMLButtonElement | null)[]>([])
|
const itemsRef = useRef<(HTMLButtonElement | null)[]>([])
|
||||||
const { ref: parentModalRef } = useParentModal()
|
const { ref: parentModalRef } = useParentModal()
|
||||||
|
const { t } = useTranslate()
|
||||||
|
|
||||||
useOutsideClick({
|
useOutsideClick({
|
||||||
ref: dropdownRef,
|
ref: dropdownRef,
|
||||||
@@ -137,7 +139,7 @@ export const VariableSearchInput = ({
|
|||||||
const handleRenameVariableClick =
|
const handleRenameVariableClick =
|
||||||
(variable: Variable) => (e: React.MouseEvent) => {
|
(variable: Variable) => (e: React.MouseEvent) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
const name = prompt('Rename variable', variable.name)
|
const name = prompt(t('variables.rename'), variable.name)
|
||||||
if (!name) return
|
if (!name) return
|
||||||
updateVariable(variable.id, { name })
|
updateVariable(variable.id, { name })
|
||||||
setFilteredItems(
|
setFilteredItems(
|
||||||
@@ -221,7 +223,7 @@ export const VariableSearchInput = ({
|
|||||||
onChange={onInputChange}
|
onChange={onInputChange}
|
||||||
onFocus={openDropdown}
|
onFocus={openDropdown}
|
||||||
onKeyDown={handleKeyUp}
|
onKeyDown={handleKeyUp}
|
||||||
placeholder={placeholder ?? 'Select a variable'}
|
placeholder={placeholder ?? t('variables.select')}
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
{...inputProps}
|
{...inputProps}
|
||||||
/>
|
/>
|
||||||
@@ -255,7 +257,7 @@ export const VariableSearchInput = ({
|
|||||||
: 'transparent'
|
: 'transparent'
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Create
|
{t('create')}
|
||||||
<Tag colorScheme="orange" ml="1">
|
<Tag colorScheme="orange" ml="1">
|
||||||
<Text noOfLines={0} display="block">
|
<Text noOfLines={0} display="block">
|
||||||
{inputValue}
|
{inputValue}
|
||||||
@@ -296,13 +298,13 @@ export const VariableSearchInput = ({
|
|||||||
<HStack>
|
<HStack>
|
||||||
<IconButton
|
<IconButton
|
||||||
icon={<EditIcon />}
|
icon={<EditIcon />}
|
||||||
aria-label="Rename variable"
|
aria-label={t('variables.rename')}
|
||||||
size="xs"
|
size="xs"
|
||||||
onClick={handleRenameVariableClick(item)}
|
onClick={handleRenameVariableClick(item)}
|
||||||
/>
|
/>
|
||||||
<IconButton
|
<IconButton
|
||||||
icon={<TrashIcon />}
|
icon={<TrashIcon />}
|
||||||
aria-label="Remove variable"
|
aria-label={t('variables.remove')}
|
||||||
size="xs"
|
size="xs"
|
||||||
onClick={handleDeleteVariableClick(item)}
|
onClick={handleDeleteVariableClick(item)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Stack, Tag, Text, Wrap } from '@chakra-ui/react'
|
|||||||
import { useTypebot } from '@/features/editor/providers/TypebotProvider'
|
import { useTypebot } from '@/features/editor/providers/TypebotProvider'
|
||||||
import { SetVariableLabel } from '@/components/SetVariableLabel'
|
import { SetVariableLabel } from '@/components/SetVariableLabel'
|
||||||
import { ItemNodesList } from '@/features/graph/components/nodes/item/ItemNodesList'
|
import { ItemNodesList } from '@/features/graph/components/nodes/item/ItemNodesList'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
block: ChoiceInputBlock
|
block: ChoiceInputBlock
|
||||||
@@ -12,6 +13,7 @@ type Props = {
|
|||||||
|
|
||||||
export const ButtonsBlockNode = ({ block, indices }: Props) => {
|
export const ButtonsBlockNode = ({ block, indices }: Props) => {
|
||||||
const { typebot } = useTypebot()
|
const { typebot } = useTypebot()
|
||||||
|
const { t } = useTranslate()
|
||||||
const dynamicVariableName = typebot?.variables.find(
|
const dynamicVariableName = typebot?.variables.find(
|
||||||
(variable) => variable.id === block.options?.dynamicVariableId
|
(variable) => variable.id === block.options?.dynamicVariableId
|
||||||
)?.name
|
)?.name
|
||||||
@@ -20,11 +22,11 @@ export const ButtonsBlockNode = ({ block, indices }: Props) => {
|
|||||||
<Stack w="full">
|
<Stack w="full">
|
||||||
{block.options?.dynamicVariableId ? (
|
{block.options?.dynamicVariableId ? (
|
||||||
<Wrap spacing={1}>
|
<Wrap spacing={1}>
|
||||||
<Text>Display</Text>
|
<Text>{t('blocks.inputs.button.variables.display.label')}</Text>
|
||||||
<Tag bg="orange.400" color="white">
|
<Tag bg="orange.400" color="white">
|
||||||
{dynamicVariableName}
|
{dynamicVariableName}
|
||||||
</Tag>
|
</Tag>
|
||||||
<Text>buttons</Text>
|
<Text>{t('blocks.inputs.button.variables.buttons.label')}</Text>
|
||||||
</Wrap>
|
</Wrap>
|
||||||
) : (
|
) : (
|
||||||
<ItemNodesList block={block} indices={indices} />
|
<ItemNodesList block={block} indices={indices} />
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { ChoiceInputBlock, Variable } from '@typebot.io/schemas'
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { SwitchWithRelatedSettings } from '@/components/SwitchWithRelatedSettings'
|
import { SwitchWithRelatedSettings } from '@/components/SwitchWithRelatedSettings'
|
||||||
import { defaultChoiceInputOptions } from '@typebot.io/schemas/features/blocks/inputs/choice/constants'
|
import { defaultChoiceInputOptions } from '@typebot.io/schemas/features/blocks/inputs/choice/constants'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
options?: ChoiceInputBlock['options']
|
options?: ChoiceInputBlock['options']
|
||||||
@@ -13,6 +14,7 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const ButtonsBlockSettings = ({ options, onOptionsChange }: Props) => {
|
export const ButtonsBlockSettings = ({ options, onOptionsChange }: Props) => {
|
||||||
|
const { t } = useTranslate()
|
||||||
const updateIsMultiple = (isMultipleChoice: boolean) =>
|
const updateIsMultiple = (isMultipleChoice: boolean) =>
|
||||||
onOptionsChange({ ...options, isMultipleChoice })
|
onOptionsChange({ ...options, isMultipleChoice })
|
||||||
const updateIsSearchable = (isSearchable: boolean) =>
|
const updateIsSearchable = (isSearchable: boolean) =>
|
||||||
@@ -29,7 +31,7 @@ export const ButtonsBlockSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
return (
|
return (
|
||||||
<Stack spacing={4}>
|
<Stack spacing={4}>
|
||||||
<SwitchWithRelatedSettings
|
<SwitchWithRelatedSettings
|
||||||
label="Multiple choice?"
|
label={t('blocks.inputs.settings.multipleChoice.label')}
|
||||||
initialValue={
|
initialValue={
|
||||||
options?.isMultipleChoice ??
|
options?.isMultipleChoice ??
|
||||||
defaultChoiceInputOptions.isMultipleChoice
|
defaultChoiceInputOptions.isMultipleChoice
|
||||||
@@ -37,35 +39,34 @@ export const ButtonsBlockSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
onCheckChange={updateIsMultiple}
|
onCheckChange={updateIsMultiple}
|
||||||
>
|
>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Submit button label:"
|
label={t('blocks.inputs.settings.submitButton.label')}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
options?.buttonLabel ?? defaultChoiceInputOptions.buttonLabel
|
options?.buttonLabel ?? t('blocks.inputs.settings.buttonText.label')
|
||||||
}
|
}
|
||||||
onChange={updateButtonLabel}
|
onChange={updateButtonLabel}
|
||||||
/>
|
/>
|
||||||
</SwitchWithRelatedSettings>
|
</SwitchWithRelatedSettings>
|
||||||
<SwitchWithRelatedSettings
|
<SwitchWithRelatedSettings
|
||||||
label="Is searchable?"
|
label={t('blocks.inputs.settings.isSearchable.label')}
|
||||||
initialValue={
|
initialValue={
|
||||||
options?.isSearchable ?? defaultChoiceInputOptions.isSearchable
|
options?.isSearchable ?? defaultChoiceInputOptions.isSearchable
|
||||||
}
|
}
|
||||||
onCheckChange={updateIsSearchable}
|
onCheckChange={updateIsSearchable}
|
||||||
>
|
>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Input placeholder:"
|
label={t('blocks.inputs.settings.input.placeholder.label')}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
options?.searchInputPlaceholder ??
|
options?.searchInputPlaceholder ??
|
||||||
defaultChoiceInputOptions.searchInputPlaceholder
|
t('blocks.inputs.settings.input.filterOptions.label')
|
||||||
}
|
}
|
||||||
onChange={updateSearchInputPlaceholder}
|
onChange={updateSearchInputPlaceholder}
|
||||||
/>
|
/>
|
||||||
</SwitchWithRelatedSettings>
|
</SwitchWithRelatedSettings>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<FormLabel>
|
<FormLabel>
|
||||||
Dynamic data:{' '}
|
{t('blocks.inputs.button.settings.dynamicData.label')}{' '}
|
||||||
<MoreInfoTooltip>
|
<MoreInfoTooltip>
|
||||||
If defined, buttons will be dynamically displayed based on what the
|
{t('blocks.inputs.button.settings.dynamicData.infoText.label')}
|
||||||
variable contains.
|
|
||||||
</MoreInfoTooltip>
|
</MoreInfoTooltip>
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<VariableSearchInput
|
<VariableSearchInput
|
||||||
@@ -75,7 +76,7 @@ export const ButtonsBlockSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
</FormControl>
|
</FormControl>
|
||||||
<Stack>
|
<Stack>
|
||||||
<FormLabel mb="0" htmlFor="variable">
|
<FormLabel mb="0" htmlFor="variable">
|
||||||
Save answer in a variable:
|
{t('blocks.inputs.settings.saveAnswer.label')}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<VariableSearchInput
|
<VariableSearchInput
|
||||||
initialVariableId={options?.variableId}
|
initialVariableId={options?.variableId}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import React, { useRef, useState } from 'react'
|
|||||||
import { isNotDefined } from '@typebot.io/lib'
|
import { isNotDefined } from '@typebot.io/lib'
|
||||||
import { useGraph } from '@/features/graph/providers/GraphProvider'
|
import { useGraph } from '@/features/graph/providers/GraphProvider'
|
||||||
import { ButtonsItemSettings } from './ButtonsItemSettings'
|
import { ButtonsItemSettings } from './ButtonsItemSettings'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
item: ButtonItem
|
item: ButtonItem
|
||||||
@@ -29,9 +30,12 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const ButtonsItemNode = ({ item, indices, isMouseOver }: Props) => {
|
export const ButtonsItemNode = ({ item, indices, isMouseOver }: Props) => {
|
||||||
|
const { t } = useTranslate()
|
||||||
const { deleteItem, updateItem, createItem } = useTypebot()
|
const { deleteItem, updateItem, createItem } = useTypebot()
|
||||||
const { openedItemId, setOpenedItemId } = useGraph()
|
const { openedItemId, setOpenedItemId } = useGraph()
|
||||||
const [itemValue, setItemValue] = useState(item.content ?? 'Click to edit')
|
const [itemValue, setItemValue] = useState(
|
||||||
|
item.content ?? t('blocks.inputs.button.clickToEdit.label')
|
||||||
|
)
|
||||||
const editableRef = useRef<HTMLDivElement | null>(null)
|
const editableRef = useRef<HTMLDivElement | null>(null)
|
||||||
const ref = useRef<HTMLDivElement | null>(null)
|
const ref = useRef<HTMLDivElement | null>(null)
|
||||||
const arrowColor = useColorModeValue('white', 'gray.800')
|
const arrowColor = useColorModeValue('white', 'gray.800')
|
||||||
@@ -47,8 +51,16 @@ export const ButtonsItemNode = ({ item, indices, isMouseOver }: Props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleKeyPress = (e: React.KeyboardEvent<HTMLDivElement>) => {
|
const handleKeyPress = (e: React.KeyboardEvent<HTMLDivElement>) => {
|
||||||
if (e.key === 'Escape' && itemValue === 'Click to edit') deleteItem(indices)
|
if (
|
||||||
if (e.key === 'Enter' && itemValue !== '' && itemValue !== 'Click to edit')
|
e.key === 'Escape' &&
|
||||||
|
itemValue === t('blocks.inputs.button.clickToEdit.label')
|
||||||
|
)
|
||||||
|
deleteItem(indices)
|
||||||
|
if (
|
||||||
|
e.key === 'Enter' &&
|
||||||
|
itemValue !== '' &&
|
||||||
|
itemValue !== t('blocks.inputs.button.clickToEdit.label')
|
||||||
|
)
|
||||||
handlePlusClick()
|
handlePlusClick()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +94,11 @@ export const ButtonsItemNode = ({ item, indices, isMouseOver }: Props) => {
|
|||||||
>
|
>
|
||||||
<EditablePreview
|
<EditablePreview
|
||||||
w="full"
|
w="full"
|
||||||
color={item.content !== 'Click to edit' ? 'inherit' : 'gray.500'}
|
color={
|
||||||
|
item.content !== t('blocks.inputs.button.clickToEdit.label')
|
||||||
|
? 'inherit'
|
||||||
|
: 'gray.500'
|
||||||
|
}
|
||||||
cursor="pointer"
|
cursor="pointer"
|
||||||
/>
|
/>
|
||||||
<EditableInput onMouseDownCapture={(e) => e.stopPropagation()} />
|
<EditableInput onMouseDownCapture={(e) => e.stopPropagation()} />
|
||||||
@@ -101,7 +117,7 @@ export const ButtonsItemNode = ({ item, indices, isMouseOver }: Props) => {
|
|||||||
>
|
>
|
||||||
<Flex bgColor={useColorModeValue('white', 'gray.800')} rounded="md">
|
<Flex bgColor={useColorModeValue('white', 'gray.800')} rounded="md">
|
||||||
<IconButton
|
<IconButton
|
||||||
aria-label="Open settings"
|
aria-label={t('blocks.inputs.button.openSettings.ariaLabel')}
|
||||||
icon={<SettingsIcon />}
|
icon={<SettingsIcon />}
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
@@ -121,7 +137,7 @@ export const ButtonsItemNode = ({ item, indices, isMouseOver }: Props) => {
|
|||||||
unmountOnExit
|
unmountOnExit
|
||||||
>
|
>
|
||||||
<IconButton
|
<IconButton
|
||||||
aria-label="Add item"
|
aria-label={t('blocks.inputs.button.addItem.ariaLabel')}
|
||||||
icon={<PlusIcon />}
|
icon={<PlusIcon />}
|
||||||
size="xs"
|
size="xs"
|
||||||
shadow="md"
|
shadow="md"
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { SwitchWithRelatedSettings } from '@/components/SwitchWithRelatedSetting
|
|||||||
import { ConditionForm } from '@/features/blocks/logic/condition/components/ConditionForm'
|
import { ConditionForm } from '@/features/blocks/logic/condition/components/ConditionForm'
|
||||||
import { ButtonItem, Condition } from '@typebot.io/schemas'
|
import { ButtonItem, Condition } from '@typebot.io/schemas'
|
||||||
import { LogicalOperator } from '@typebot.io/schemas/features/blocks/logic/condition/constants'
|
import { LogicalOperator } from '@typebot.io/schemas/features/blocks/logic/condition/constants'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
item: ButtonItem
|
item: ButtonItem
|
||||||
@@ -11,6 +12,8 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const ButtonsItemSettings = ({ item, onSettingsChange }: Props) => {
|
export const ButtonsItemSettings = ({ item, onSettingsChange }: Props) => {
|
||||||
|
const { t } = useTranslate()
|
||||||
|
|
||||||
const updateIsDisplayConditionEnabled = (isEnabled: boolean) =>
|
const updateIsDisplayConditionEnabled = (isEnabled: boolean) =>
|
||||||
onSettingsChange({
|
onSettingsChange({
|
||||||
...item,
|
...item,
|
||||||
@@ -32,8 +35,10 @@ export const ButtonsItemSettings = ({ item, onSettingsChange }: Props) => {
|
|||||||
return (
|
return (
|
||||||
<Stack spacing={4}>
|
<Stack spacing={4}>
|
||||||
<SwitchWithRelatedSettings
|
<SwitchWithRelatedSettings
|
||||||
label="Display condition"
|
label={t('blocks.inputs.settings.displayCondition.label')}
|
||||||
moreInfoContent="Only display this item if a condition is met."
|
moreInfoContent={t(
|
||||||
|
'blocks.inputs.button.buttonSettings.displayCondition.infoText.label'
|
||||||
|
)}
|
||||||
initialValue={item.displayCondition?.isEnabled ?? false}
|
initialValue={item.displayCondition?.isEnabled ?? false}
|
||||||
onCheckChange={updateIsDisplayConditionEnabled}
|
onCheckChange={updateIsDisplayConditionEnabled}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { FormLabel, Stack } from '@chakra-ui/react'
|
|||||||
import { DateInputBlock, Variable } from '@typebot.io/schemas'
|
import { DateInputBlock, Variable } from '@typebot.io/schemas'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { defaultDateInputOptions } from '@typebot.io/schemas/features/blocks/inputs/date/constants'
|
import { defaultDateInputOptions } from '@typebot.io/schemas/features/blocks/inputs/date/constants'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
options: DateInputBlock['options']
|
options: DateInputBlock['options']
|
||||||
@@ -13,6 +14,7 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const DateInputSettings = ({ options, onOptionsChange }: Props) => {
|
export const DateInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||||
|
const { t } = useTranslate()
|
||||||
const updateFromLabel = (from: string) =>
|
const updateFromLabel = (from: string) =>
|
||||||
onOptionsChange({ ...options, labels: { ...options?.labels, from } })
|
onOptionsChange({ ...options, labels: { ...options?.labels, from } })
|
||||||
const updateToLabel = (to: string) =>
|
const updateToLabel = (to: string) =>
|
||||||
@@ -41,64 +43,69 @@ export const DateInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
return (
|
return (
|
||||||
<Stack spacing={4}>
|
<Stack spacing={4}>
|
||||||
<SwitchWithRelatedSettings
|
<SwitchWithRelatedSettings
|
||||||
label="Is range?"
|
label={t('blocks.inputs.date.settings.isRange.label')}
|
||||||
initialValue={options?.isRange ?? defaultDateInputOptions.isRange}
|
initialValue={options?.isRange ?? defaultDateInputOptions.isRange}
|
||||||
onCheckChange={updateIsRange}
|
onCheckChange={updateIsRange}
|
||||||
>
|
>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="From label:"
|
label={t('blocks.inputs.date.settings.from.label')}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
options?.labels?.from ?? defaultDateInputOptions.labels.from
|
options?.labels?.from ?? defaultDateInputOptions.labels.from
|
||||||
}
|
}
|
||||||
onChange={updateFromLabel}
|
onChange={updateFromLabel}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="To label:"
|
label={t('blocks.inputs.date.settings.to.label')}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
options?.labels?.to ?? defaultDateInputOptions.labels.to
|
options?.labels?.to ??
|
||||||
|
t('blocks.inputs.date.settings.toInputValue.label')
|
||||||
}
|
}
|
||||||
onChange={updateToLabel}
|
onChange={updateToLabel}
|
||||||
/>
|
/>
|
||||||
</SwitchWithRelatedSettings>
|
</SwitchWithRelatedSettings>
|
||||||
<SwitchWithLabel
|
<SwitchWithLabel
|
||||||
label="With time?"
|
label={t('blocks.inputs.date.settings.withTime.label')}
|
||||||
initialValue={options?.hasTime ?? defaultDateInputOptions.hasTime}
|
initialValue={options?.hasTime ?? defaultDateInputOptions.hasTime}
|
||||||
onCheckChange={updateHasTime}
|
onCheckChange={updateHasTime}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Button label:"
|
label={t('blocks.inputs.settings.button.label')}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
options?.labels?.button ?? defaultDateInputOptions.labels.button
|
options?.labels?.button ?? defaultDateInputOptions.labels.button
|
||||||
}
|
}
|
||||||
onChange={updateButtonLabel}
|
onChange={updateButtonLabel}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Min:"
|
label={t('blocks.inputs.settings.min.label')}
|
||||||
defaultValue={options?.min}
|
defaultValue={options?.min}
|
||||||
placeholder={options?.hasTime ? 'YYYY-MM-DDTHH:mm' : 'YYYY-MM-DD'}
|
placeholder={options?.hasTime ? 'YYYY-MM-DDTHH:mm' : 'YYYY-MM-DD'}
|
||||||
onChange={updateMin}
|
onChange={updateMin}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Max:"
|
label={t('blocks.inputs.settings.max.label')}
|
||||||
defaultValue={options?.max}
|
defaultValue={options?.max}
|
||||||
placeholder={options?.hasTime ? 'YYYY-MM-DDTHH:mm' : 'YYYY-MM-DD'}
|
placeholder={options?.hasTime ? 'YYYY-MM-DDTHH:mm' : 'YYYY-MM-DD'}
|
||||||
onChange={updateMax}
|
onChange={updateMax}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Format:"
|
label={t('blocks.inputs.date.settings.format.label')}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
options?.format ??
|
options?.format ??
|
||||||
(options?.hasTime
|
(options?.hasTime
|
||||||
? defaultDateInputOptions.formatWithTime
|
? defaultDateInputOptions.formatWithTime
|
||||||
: defaultDateInputOptions.format)
|
: defaultDateInputOptions.format)
|
||||||
}
|
}
|
||||||
moreInfoTooltip="i.e dd/MM/yyyy, MM/dd/yy, yyyy-MM-dd"
|
moreInfoTooltip={`
|
||||||
|
${t(
|
||||||
|
'blocks.inputs.date.settings.format.example.label'
|
||||||
|
)} dd/MM/yyyy, MM/dd/yy, yyyy-MM-dd
|
||||||
|
`}
|
||||||
placeholder={options?.hasTime ? 'dd/MM/yyyy HH:mm' : 'dd/MM/yyyy'}
|
placeholder={options?.hasTime ? 'dd/MM/yyyy HH:mm' : 'dd/MM/yyyy'}
|
||||||
onChange={updateFormat}
|
onChange={updateFormat}
|
||||||
/>
|
/>
|
||||||
<Stack>
|
<Stack>
|
||||||
<FormLabel mb="0" htmlFor="variable">
|
<FormLabel mb="0" htmlFor="variable">
|
||||||
Save answer in a variable:
|
{t('blocks.inputs.settings.saveAnswer.label')}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<VariableSearchInput
|
<VariableSearchInput
|
||||||
initialVariableId={options?.variableId}
|
initialVariableId={options?.variableId}
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Text } from '@chakra-ui/react'
|
import { Text } from '@chakra-ui/react'
|
||||||
import { WithVariableContent } from '@/features/graph/components/nodes/block/WithVariableContent'
|
import { WithVariableContent } from '@/features/graph/components/nodes/block/WithVariableContent'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
variableId?: string
|
variableId?: string
|
||||||
}
|
}
|
||||||
export const DateNodeContent = ({ variableId }: Props) =>
|
export const DateNodeContent = ({ variableId }: Props) => {
|
||||||
variableId ? (
|
const { t } = useTranslate()
|
||||||
|
|
||||||
|
return variableId ? (
|
||||||
<WithVariableContent variableId={variableId} />
|
<WithVariableContent variableId={variableId} />
|
||||||
) : (
|
) : (
|
||||||
<Text color={'gray.500'}>Pick a date...</Text>
|
<Text color={'gray.500'}>{t('blocks.inputs.date.placeholder.label')}</Text>
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { TextInput } from '@/components/inputs'
|
import { TextInput } from '@/components/inputs'
|
||||||
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
||||||
import { FormLabel, Stack } from '@chakra-ui/react'
|
import { FormLabel, Stack } from '@chakra-ui/react'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
import { EmailInputBlock, Variable } from '@typebot.io/schemas'
|
import { EmailInputBlock, Variable } from '@typebot.io/schemas'
|
||||||
import { defaultEmailInputOptions } from '@typebot.io/schemas/features/blocks/inputs/email/constants'
|
import { defaultEmailInputOptions } from '@typebot.io/schemas/features/blocks/inputs/email/constants'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
@@ -11,6 +12,7 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const EmailInputSettings = ({ options, onOptionsChange }: Props) => {
|
export const EmailInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||||
|
const { t } = useTranslate()
|
||||||
const handlePlaceholderChange = (placeholder: string) =>
|
const handlePlaceholderChange = (placeholder: string) =>
|
||||||
onOptionsChange({ ...options, labels: { ...options?.labels, placeholder } })
|
onOptionsChange({ ...options, labels: { ...options?.labels, placeholder } })
|
||||||
const handleButtonLabelChange = (button: string) =>
|
const handleButtonLabelChange = (button: string) =>
|
||||||
@@ -23,7 +25,7 @@ export const EmailInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
return (
|
return (
|
||||||
<Stack spacing={4}>
|
<Stack spacing={4}>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Placeholder:"
|
label={t('blocks.inputs.settings.placeholder.label')}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
options?.labels?.placeholder ??
|
options?.labels?.placeholder ??
|
||||||
defaultEmailInputOptions.labels.placeholder
|
defaultEmailInputOptions.labels.placeholder
|
||||||
@@ -31,14 +33,14 @@ export const EmailInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
onChange={handlePlaceholderChange}
|
onChange={handlePlaceholderChange}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Button label:"
|
label={t('blocks.inputs.settings.button.label')}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
options?.labels?.button ?? defaultEmailInputOptions.labels.button
|
options?.labels?.button ?? defaultEmailInputOptions.labels.button
|
||||||
}
|
}
|
||||||
onChange={handleButtonLabelChange}
|
onChange={handleButtonLabelChange}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Retry message:"
|
label={t('blocks.inputs.settings.retryMessage.label')}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
options?.retryMessageContent ??
|
options?.retryMessageContent ??
|
||||||
defaultEmailInputOptions.retryMessageContent
|
defaultEmailInputOptions.retryMessageContent
|
||||||
@@ -47,7 +49,7 @@ export const EmailInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
/>
|
/>
|
||||||
<Stack>
|
<Stack>
|
||||||
<FormLabel mb="0" htmlFor="variable">
|
<FormLabel mb="0" htmlFor="variable">
|
||||||
Save answer in a variable:
|
{t('blocks.inputs.settings.saveAnswer.label')}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<VariableSearchInput
|
<VariableSearchInput
|
||||||
initialVariableId={options?.variableId}
|
initialVariableId={options?.variableId}
|
||||||
|
|||||||
@@ -1,16 +1,22 @@
|
|||||||
import { WithVariableContent } from '@/features/graph/components/nodes/block/WithVariableContent'
|
import { WithVariableContent } from '@/features/graph/components/nodes/block/WithVariableContent'
|
||||||
import { Text } from '@chakra-ui/react'
|
import { Text } from '@chakra-ui/react'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
import { FileInputBlock } from '@typebot.io/schemas'
|
import { FileInputBlock } from '@typebot.io/schemas'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
options: FileInputBlock['options']
|
options: FileInputBlock['options']
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FileInputContent = ({ options }: Props) =>
|
export const FileInputContent = ({ options }: Props) => {
|
||||||
options?.variableId ? (
|
const { t } = useTranslate()
|
||||||
|
|
||||||
|
return options?.variableId ? (
|
||||||
<WithVariableContent variableId={options.variableId} />
|
<WithVariableContent variableId={options.variableId} />
|
||||||
) : (
|
) : (
|
||||||
<Text noOfLines={1} pr="6">
|
<Text noOfLines={1} pr="6">
|
||||||
Collect {options?.isMultipleAllowed ? 'files' : 'file'}
|
{options?.isMultipleAllowed
|
||||||
|
? t('blocks.inputs.file.collectMultiple.label')
|
||||||
|
: t('blocks.inputs.file.collectSingle.label')}
|
||||||
</Text>
|
</Text>
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { TextInput } from '@/components/inputs'
|
|||||||
import { SwitchWithLabel } from '@/components/inputs/SwitchWithLabel'
|
import { SwitchWithLabel } from '@/components/inputs/SwitchWithLabel'
|
||||||
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
||||||
import { defaultFileInputOptions } from '@typebot.io/schemas/features/blocks/inputs/file/constants'
|
import { defaultFileInputOptions } from '@typebot.io/schemas/features/blocks/inputs/file/constants'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
options: FileInputBlock['options']
|
options: FileInputBlock['options']
|
||||||
@@ -13,6 +14,8 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const FileInputSettings = ({ options, onOptionsChange }: Props) => {
|
export const FileInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||||
|
const { t } = useTranslate()
|
||||||
|
|
||||||
const handleButtonLabelChange = (button: string) =>
|
const handleButtonLabelChange = (button: string) =>
|
||||||
onOptionsChange({ ...options, labels: { ...options?.labels, button } })
|
onOptionsChange({ ...options, labels: { ...options?.labels, button } })
|
||||||
|
|
||||||
@@ -37,12 +40,12 @@ export const FileInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
return (
|
return (
|
||||||
<Stack spacing={4}>
|
<Stack spacing={4}>
|
||||||
<SwitchWithLabel
|
<SwitchWithLabel
|
||||||
label="Required?"
|
label={t('blocks.inputs.file.settings.required.label')}
|
||||||
initialValue={options?.isRequired ?? defaultFileInputOptions.isRequired}
|
initialValue={options?.isRequired ?? defaultFileInputOptions.isRequired}
|
||||||
onCheckChange={handleRequiredChange}
|
onCheckChange={handleRequiredChange}
|
||||||
/>
|
/>
|
||||||
<SwitchWithLabel
|
<SwitchWithLabel
|
||||||
label="Allow multiple files?"
|
label={t('blocks.inputs.file.settings.allowMultiple.label')}
|
||||||
initialValue={
|
initialValue={
|
||||||
options?.isMultipleAllowed ??
|
options?.isMultipleAllowed ??
|
||||||
defaultFileInputOptions.isMultipleAllowed
|
defaultFileInputOptions.isMultipleAllowed
|
||||||
@@ -50,7 +53,9 @@ export const FileInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
onCheckChange={handleMultipleFilesChange}
|
onCheckChange={handleMultipleFilesChange}
|
||||||
/>
|
/>
|
||||||
<Stack>
|
<Stack>
|
||||||
<FormLabel mb="0">Placeholder:</FormLabel>
|
<FormLabel mb="0">
|
||||||
|
{t('blocks.inputs.settings.placeholder.label')}
|
||||||
|
</FormLabel>
|
||||||
<CodeEditor
|
<CodeEditor
|
||||||
lang="html"
|
lang="html"
|
||||||
onChange={handlePlaceholderLabelChange}
|
onChange={handlePlaceholderLabelChange}
|
||||||
@@ -63,7 +68,7 @@ export const FileInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Button label:"
|
label={t('blocks.inputs.settings.button.label')}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
options?.labels?.button ?? defaultFileInputOptions.labels.button
|
options?.labels?.button ?? defaultFileInputOptions.labels.button
|
||||||
}
|
}
|
||||||
@@ -71,7 +76,7 @@ export const FileInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
withVariableButton={false}
|
withVariableButton={false}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Clear button label:"
|
label={t('blocks.inputs.file.settings.clear.label')}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
options?.labels?.clear ?? defaultFileInputOptions.labels.clear
|
options?.labels?.clear ?? defaultFileInputOptions.labels.clear
|
||||||
}
|
}
|
||||||
@@ -79,7 +84,7 @@ export const FileInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
withVariableButton={false}
|
withVariableButton={false}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Skip button label:"
|
label={t('blocks.inputs.file.settings.skip.label')}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
options?.labels?.skip ?? defaultFileInputOptions.labels.skip
|
options?.labels?.skip ?? defaultFileInputOptions.labels.skip
|
||||||
}
|
}
|
||||||
@@ -88,7 +93,9 @@ export const FileInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
/>
|
/>
|
||||||
<Stack>
|
<Stack>
|
||||||
<FormLabel mb="0" htmlFor="variable">
|
<FormLabel mb="0" htmlFor="variable">
|
||||||
Save upload URL{options?.isMultipleAllowed ? 's' : ''} in a variable:
|
{options?.isMultipleAllowed
|
||||||
|
? t('blocks.inputs.file.settings.saveMultipleUpload.label')
|
||||||
|
: t('blocks.inputs.file.settings.saveSingleUpload.label')}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<VariableSearchInput
|
<VariableSearchInput
|
||||||
initialVariableId={options?.variableId}
|
initialVariableId={options?.variableId}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { TextInput, NumberInput } from '@/components/inputs'
|
import { TextInput, NumberInput } from '@/components/inputs'
|
||||||
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
||||||
import { FormLabel, Stack } from '@chakra-ui/react'
|
import { FormLabel, Stack } from '@chakra-ui/react'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
import { NumberInputBlock, Variable } from '@typebot.io/schemas'
|
import { NumberInputBlock, Variable } from '@typebot.io/schemas'
|
||||||
import { defaultNumberInputOptions } from '@typebot.io/schemas/features/blocks/inputs/number/constants'
|
import { defaultNumberInputOptions } from '@typebot.io/schemas/features/blocks/inputs/number/constants'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
@@ -11,6 +12,7 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const NumberInputSettings = ({ options, onOptionsChange }: Props) => {
|
export const NumberInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||||
|
const { t } = useTranslate()
|
||||||
const handlePlaceholderChange = (placeholder: string) =>
|
const handlePlaceholderChange = (placeholder: string) =>
|
||||||
onOptionsChange({ ...options, labels: { ...options?.labels, placeholder } })
|
onOptionsChange({ ...options, labels: { ...options?.labels, placeholder } })
|
||||||
const handleButtonLabelChange = (button: string) =>
|
const handleButtonLabelChange = (button: string) =>
|
||||||
@@ -31,7 +33,7 @@ export const NumberInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
return (
|
return (
|
||||||
<Stack spacing={4}>
|
<Stack spacing={4}>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Placeholder:"
|
label={t('blocks.inputs.settings.placeholder.label')}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
options?.labels?.placeholder ??
|
options?.labels?.placeholder ??
|
||||||
defaultNumberInputOptions.labels.placeholder
|
defaultNumberInputOptions.labels.placeholder
|
||||||
@@ -39,30 +41,30 @@ export const NumberInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
onChange={handlePlaceholderChange}
|
onChange={handlePlaceholderChange}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Button label:"
|
label={t('blocks.inputs.settings.button.label')}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
options?.labels?.button ?? defaultNumberInputOptions.labels.button
|
options?.labels?.button ?? defaultNumberInputOptions.labels.button
|
||||||
}
|
}
|
||||||
onChange={handleButtonLabelChange}
|
onChange={handleButtonLabelChange}
|
||||||
/>
|
/>
|
||||||
<NumberInput
|
<NumberInput
|
||||||
label="Min:"
|
label={t('blocks.inputs.settings.min.label')}
|
||||||
defaultValue={options?.min}
|
defaultValue={options?.min}
|
||||||
onValueChange={handleMinChange}
|
onValueChange={handleMinChange}
|
||||||
/>
|
/>
|
||||||
<NumberInput
|
<NumberInput
|
||||||
label="Max:"
|
label={t('blocks.inputs.settings.max.label')}
|
||||||
defaultValue={options?.max}
|
defaultValue={options?.max}
|
||||||
onValueChange={handleMaxChange}
|
onValueChange={handleMaxChange}
|
||||||
/>
|
/>
|
||||||
<NumberInput
|
<NumberInput
|
||||||
label="Step:"
|
label={t('blocks.inputs.number.settings.step.label')}
|
||||||
defaultValue={options?.step}
|
defaultValue={options?.step}
|
||||||
onValueChange={handleStepChange}
|
onValueChange={handleStepChange}
|
||||||
/>
|
/>
|
||||||
<Stack>
|
<Stack>
|
||||||
<FormLabel mb="0" htmlFor="variable">
|
<FormLabel mb="0" htmlFor="variable">
|
||||||
Save answer in a variable:
|
{t('blocks.inputs.settings.saveAnswer.label')}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<VariableSearchInput
|
<VariableSearchInput
|
||||||
initialVariableId={options?.variableId}
|
initialVariableId={options?.variableId}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { TextInput } from '@/components/inputs'
|
import { TextInput } from '@/components/inputs'
|
||||||
import { PaymentAddress } from '@typebot.io/schemas'
|
import { PaymentAddress } from '@typebot.io/schemas'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
address: PaymentAddress
|
address: PaymentAddress
|
||||||
@@ -16,6 +17,8 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const PaymentAddressSettings = ({ address, onAddressChange }: Props) => {
|
export const PaymentAddressSettings = ({ address, onAddressChange }: Props) => {
|
||||||
|
const { t } = useTranslate()
|
||||||
|
|
||||||
const updateCountry = (country: string) =>
|
const updateCountry = (country: string) =>
|
||||||
onAddressChange({
|
onAddressChange({
|
||||||
...address,
|
...address,
|
||||||
@@ -56,37 +59,41 @@ export const PaymentAddressSettings = ({ address, onAddressChange }: Props) => {
|
|||||||
<Accordion allowToggle>
|
<Accordion allowToggle>
|
||||||
<AccordionItem>
|
<AccordionItem>
|
||||||
<AccordionButton justifyContent="space-between">
|
<AccordionButton justifyContent="space-between">
|
||||||
Address
|
{t('blocks.inputs.payment.settings.address.label')}
|
||||||
<AccordionIcon />
|
<AccordionIcon />
|
||||||
</AccordionButton>
|
</AccordionButton>
|
||||||
<AccordionPanel py={4} as={Stack} spacing="4">
|
<AccordionPanel py={4} as={Stack} spacing="4">
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Country:"
|
label={t('blocks.inputs.payment.settings.address.country.label')}
|
||||||
defaultValue={address?.country ?? ''}
|
defaultValue={address?.country ?? ''}
|
||||||
onChange={updateCountry}
|
onChange={updateCountry}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Line 1:"
|
label={t('blocks.inputs.payment.settings.address.line.label', {
|
||||||
|
line: '1',
|
||||||
|
})}
|
||||||
defaultValue={address?.line1 ?? ''}
|
defaultValue={address?.line1 ?? ''}
|
||||||
onChange={updateLine1}
|
onChange={updateLine1}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Line 2:"
|
label={t('blocks.inputs.payment.settings.address.line.label', {
|
||||||
|
line: '2',
|
||||||
|
})}
|
||||||
defaultValue={address?.line2 ?? ''}
|
defaultValue={address?.line2 ?? ''}
|
||||||
onChange={updateLine2}
|
onChange={updateLine2}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="City:"
|
label={t('blocks.inputs.payment.settings.address.city.label')}
|
||||||
defaultValue={address?.city ?? ''}
|
defaultValue={address?.city ?? ''}
|
||||||
onChange={updateCity}
|
onChange={updateCity}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="State:"
|
label={t('blocks.inputs.payment.settings.address.state.label')}
|
||||||
defaultValue={address?.state ?? ''}
|
defaultValue={address?.state ?? ''}
|
||||||
onChange={updateState}
|
onChange={updateState}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Postal code:"
|
label={t('blocks.inputs.payment.settings.address.postalCode.label')}
|
||||||
defaultValue={address?.postalCode ?? ''}
|
defaultValue={address?.postalCode ?? ''}
|
||||||
onChange={updatePostalCode}
|
onChange={updatePostalCode}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Text } from '@chakra-ui/react'
|
import { Text } from '@chakra-ui/react'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
import { PaymentInputBlock } from '@typebot.io/schemas'
|
import { PaymentInputBlock } from '@typebot.io/schemas'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -6,15 +7,22 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const PaymentInputContent = ({ block }: Props) => {
|
export const PaymentInputContent = ({ block }: Props) => {
|
||||||
|
const { t } = useTranslate()
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!block.options?.amount ||
|
!block.options?.amount ||
|
||||||
!block.options.credentialsId ||
|
!block.options.credentialsId ||
|
||||||
!block.options.currency
|
!block.options.currency
|
||||||
)
|
)
|
||||||
return <Text color="gray.500">Configure...</Text>
|
return (
|
||||||
|
<Text color="gray.500">
|
||||||
|
{t('blocks.inputs.payment.placeholder.label')}
|
||||||
|
</Text>
|
||||||
|
)
|
||||||
return (
|
return (
|
||||||
<Text noOfLines={1} pr="6">
|
<Text noOfLines={1} pr="6">
|
||||||
Collect {block.options.amount} {block.options.currency}
|
{t('blocks.inputs.payment.collect.label')} {block.options.amount}{' '}
|
||||||
|
{block.options.currency}
|
||||||
</Text>
|
</Text>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import {
|
|||||||
PaymentProvider,
|
PaymentProvider,
|
||||||
defaultPaymentInputOptions,
|
defaultPaymentInputOptions,
|
||||||
} from '@typebot.io/schemas/features/blocks/inputs/payment/constants'
|
} from '@typebot.io/schemas/features/blocks/inputs/payment/constants'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
options: PaymentInputBlock['options']
|
options: PaymentInputBlock['options']
|
||||||
@@ -32,6 +33,7 @@ type Props = {
|
|||||||
export const PaymentSettings = ({ options, onOptionsChange }: Props) => {
|
export const PaymentSettings = ({ options, onOptionsChange }: Props) => {
|
||||||
const { workspace } = useWorkspace()
|
const { workspace } = useWorkspace()
|
||||||
const { isOpen, onOpen, onClose } = useDisclosure()
|
const { isOpen, onOpen, onClose } = useDisclosure()
|
||||||
|
const { t } = useTranslate()
|
||||||
|
|
||||||
const updateProvider = (provider: PaymentProvider) => {
|
const updateProvider = (provider: PaymentProvider) => {
|
||||||
onOptionsChange({
|
onOptionsChange({
|
||||||
@@ -104,7 +106,7 @@ export const PaymentSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
return (
|
return (
|
||||||
<Stack spacing={4}>
|
<Stack spacing={4}>
|
||||||
<Stack>
|
<Stack>
|
||||||
<Text>Provider:</Text>
|
<Text>{t('blocks.inputs.payment.settings.provider.label')}</Text>
|
||||||
<DropdownList
|
<DropdownList
|
||||||
onItemSelect={updateProvider}
|
onItemSelect={updateProvider}
|
||||||
items={Object.values(PaymentProvider)}
|
items={Object.values(PaymentProvider)}
|
||||||
@@ -112,7 +114,7 @@ export const PaymentSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
<Stack>
|
<Stack>
|
||||||
<Text>Account:</Text>
|
<Text>{t('blocks.inputs.payment.settings.account.label')}</Text>
|
||||||
{workspace && (
|
{workspace && (
|
||||||
<CredentialsDropdown
|
<CredentialsDropdown
|
||||||
type="stripe"
|
type="stripe"
|
||||||
@@ -120,19 +122,24 @@ export const PaymentSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
currentCredentialsId={options?.credentialsId}
|
currentCredentialsId={options?.credentialsId}
|
||||||
onCredentialsSelect={updateCredentials}
|
onCredentialsSelect={updateCredentials}
|
||||||
onCreateNewClick={onOpen}
|
onCreateNewClick={onOpen}
|
||||||
credentialsName="Stripe account"
|
credentialsName={t(
|
||||||
|
'blocks.inputs.payment.settings.accountText.label',
|
||||||
|
{
|
||||||
|
provider: 'Stripe',
|
||||||
|
}
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
<HStack>
|
<HStack>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Price amount:"
|
label={t('blocks.inputs.payment.settings.priceAmount.label')}
|
||||||
onChange={updateAmount}
|
onChange={updateAmount}
|
||||||
defaultValue={options?.amount}
|
defaultValue={options?.amount}
|
||||||
placeholder="30.00"
|
placeholder="30.00"
|
||||||
/>
|
/>
|
||||||
<Stack>
|
<Stack>
|
||||||
<Text>Currency:</Text>
|
<Text>{t('blocks.inputs.payment.settings.currency.label')}</Text>
|
||||||
<Select
|
<Select
|
||||||
placeholder="Select option"
|
placeholder="Select option"
|
||||||
value={options?.currency ?? defaultPaymentInputOptions.currency}
|
value={options?.currency ?? defaultPaymentInputOptions.currency}
|
||||||
@@ -147,14 +154,14 @@ export const PaymentSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
</Stack>
|
</Stack>
|
||||||
</HStack>
|
</HStack>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Button label:"
|
label={t('blocks.inputs.settings.button.label')}
|
||||||
onChange={updateButtonLabel}
|
onChange={updateButtonLabel}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
options?.labels?.button ?? defaultPaymentInputOptions.labels.button
|
options?.labels?.button ?? defaultPaymentInputOptions.labels.button
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Success message:"
|
label={t('blocks.inputs.payment.settings.successMessage.label')}
|
||||||
onChange={updateSuccessLabel}
|
onChange={updateSuccessLabel}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
options?.labels?.success ?? defaultPaymentInputOptions.labels.success
|
options?.labels?.success ?? defaultPaymentInputOptions.labels.success
|
||||||
@@ -163,30 +170,38 @@ export const PaymentSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
<Accordion allowToggle>
|
<Accordion allowToggle>
|
||||||
<AccordionItem>
|
<AccordionItem>
|
||||||
<AccordionButton justifyContent="space-between">
|
<AccordionButton justifyContent="space-between">
|
||||||
Additional information
|
{t('blocks.inputs.payment.settings.additionalInformation.label')}
|
||||||
<AccordionIcon />
|
<AccordionIcon />
|
||||||
</AccordionButton>
|
</AccordionButton>
|
||||||
<AccordionPanel py={4} as={Stack} spacing="6">
|
<AccordionPanel py={4} as={Stack} spacing="6">
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Description:"
|
label={t('blocks.inputs.settings.description.label')}
|
||||||
defaultValue={options?.additionalInformation?.description}
|
defaultValue={options?.additionalInformation?.description}
|
||||||
onChange={updateDescription}
|
onChange={updateDescription}
|
||||||
placeholder="A digital product"
|
placeholder={t(
|
||||||
|
'blocks.inputs.payment.settings.additionalInformation.description.placeholder.label'
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Name:"
|
label={t(
|
||||||
|
'blocks.inputs.payment.settings.additionalInformation.name.label'
|
||||||
|
)}
|
||||||
defaultValue={options?.additionalInformation?.name}
|
defaultValue={options?.additionalInformation?.name}
|
||||||
onChange={updateName}
|
onChange={updateName}
|
||||||
placeholder="John Smith"
|
placeholder="John Smith"
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Email:"
|
label={t(
|
||||||
|
'blocks.inputs.payment.settings.additionalInformation.email.label'
|
||||||
|
)}
|
||||||
defaultValue={options?.additionalInformation?.email}
|
defaultValue={options?.additionalInformation?.email}
|
||||||
onChange={updateEmail}
|
onChange={updateEmail}
|
||||||
placeholder="john@gmail.com"
|
placeholder="john@gmail.com"
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Phone number:"
|
label={t(
|
||||||
|
'blocks.inputs.payment.settings.additionalInformation.phone.label'
|
||||||
|
)}
|
||||||
defaultValue={options?.additionalInformation?.phoneNumber}
|
defaultValue={options?.additionalInformation?.phoneNumber}
|
||||||
onChange={updatePhoneNumber}
|
onChange={updatePhoneNumber}
|
||||||
placeholder="+33XXXXXXXXX"
|
placeholder="+33XXXXXXXXX"
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import { StripeCredentials } from '@typebot.io/schemas'
|
|||||||
import { trpc } from '@/lib/trpc'
|
import { trpc } from '@/lib/trpc'
|
||||||
import { isNotEmpty } from '@typebot.io/lib'
|
import { isNotEmpty } from '@typebot.io/lib'
|
||||||
import { useUser } from '@/features/account/hooks/useUser'
|
import { useUser } from '@/features/account/hooks/useUser'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
@@ -35,6 +36,7 @@ export const StripeConfigModal = ({
|
|||||||
onNewCredentials,
|
onNewCredentials,
|
||||||
onClose,
|
onClose,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
|
const { t } = useTranslate()
|
||||||
const { user } = useUser()
|
const { user } = useUser()
|
||||||
const { workspace } = useWorkspace()
|
const { workspace } = useWorkspace()
|
||||||
const [isCreating, setIsCreating] = useState(false)
|
const [isCreating, setIsCreating] = useState(false)
|
||||||
@@ -122,13 +124,17 @@ export const StripeConfigModal = ({
|
|||||||
<Modal isOpen={isOpen} onClose={onClose}>
|
<Modal isOpen={isOpen} onClose={onClose}>
|
||||||
<ModalOverlay />
|
<ModalOverlay />
|
||||||
<ModalContent>
|
<ModalContent>
|
||||||
<ModalHeader>Connect Stripe account</ModalHeader>
|
<ModalHeader>
|
||||||
|
{t('blocks.inputs.payment.settings.stripeConfig.title.label')}
|
||||||
|
</ModalHeader>
|
||||||
<ModalCloseButton />
|
<ModalCloseButton />
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<Stack as="form" spacing={4}>
|
<Stack as="form" spacing={4}>
|
||||||
<TextInput
|
<TextInput
|
||||||
isRequired
|
isRequired
|
||||||
label="Account name:"
|
label={t(
|
||||||
|
'blocks.inputs.payment.settings.stripeConfig.accountName.label'
|
||||||
|
)}
|
||||||
onChange={handleNameChange}
|
onChange={handleNameChange}
|
||||||
placeholder="Typebot"
|
placeholder="Typebot"
|
||||||
withVariableButton={false}
|
withVariableButton={false}
|
||||||
@@ -136,9 +142,13 @@ export const StripeConfigModal = ({
|
|||||||
/>
|
/>
|
||||||
<Stack>
|
<Stack>
|
||||||
<FormLabel>
|
<FormLabel>
|
||||||
Test keys:{' '}
|
{t(
|
||||||
|
'blocks.inputs.payment.settings.stripeConfig.testKeys.label'
|
||||||
|
)}{' '}
|
||||||
<MoreInfoTooltip>
|
<MoreInfoTooltip>
|
||||||
Will be used when previewing the bot.
|
{t(
|
||||||
|
'blocks.inputs.payment.settings.stripeConfig.testKeys.infoText.label'
|
||||||
|
)}
|
||||||
</MoreInfoTooltip>
|
</MoreInfoTooltip>
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<HStack>
|
<HStack>
|
||||||
@@ -157,7 +167,11 @@ export const StripeConfigModal = ({
|
|||||||
</HStack>
|
</HStack>
|
||||||
</Stack>
|
</Stack>
|
||||||
<Stack>
|
<Stack>
|
||||||
<FormLabel>Live keys:</FormLabel>
|
<FormLabel>
|
||||||
|
{t(
|
||||||
|
'blocks.inputs.payment.settings.stripeConfig.liveKeys.label'
|
||||||
|
)}
|
||||||
|
</FormLabel>
|
||||||
<HStack>
|
<HStack>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<TextInput
|
<TextInput
|
||||||
@@ -179,9 +193,11 @@ export const StripeConfigModal = ({
|
|||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<Text>
|
<Text>
|
||||||
(You can find your keys{' '}
|
({t('blocks.inputs.payment.settings.stripeConfig.findKeys.label')}{' '}
|
||||||
<TextLink href="https://dashboard.stripe.com/apikeys" isExternal>
|
<TextLink href="https://dashboard.stripe.com/apikeys" isExternal>
|
||||||
here
|
{t(
|
||||||
|
'blocks.inputs.payment.settings.stripeConfig.findKeys.here.label'
|
||||||
|
)}
|
||||||
</TextLink>
|
</TextLink>
|
||||||
)
|
)
|
||||||
</Text>
|
</Text>
|
||||||
@@ -199,7 +215,7 @@ export const StripeConfigModal = ({
|
|||||||
}
|
}
|
||||||
isLoading={isCreating}
|
isLoading={isCreating}
|
||||||
>
|
>
|
||||||
Connect
|
{t('connect')}
|
||||||
</Button>
|
</Button>
|
||||||
</ModalFooter>
|
</ModalFooter>
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Select } from '@chakra-ui/react'
|
import { Select } from '@chakra-ui/react'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
import React, { ChangeEvent } from 'react'
|
import React, { ChangeEvent } from 'react'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -7,12 +8,15 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const CountryCodeSelect = ({ countryCode, onSelect }: Props) => {
|
export const CountryCodeSelect = ({ countryCode, onSelect }: Props) => {
|
||||||
|
const { t } = useTranslate()
|
||||||
const handleOnChange = (e: ChangeEvent<HTMLSelectElement>) => {
|
const handleOnChange = (e: ChangeEvent<HTMLSelectElement>) => {
|
||||||
onSelect(e.target.value)
|
onSelect(e.target.value)
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Select
|
<Select
|
||||||
placeholder="International"
|
placeholder={t(
|
||||||
|
'blocks.inputs.phone.settings.international.placeholder.label'
|
||||||
|
)}
|
||||||
value={countryCode}
|
value={countryCode}
|
||||||
onChange={handleOnChange}
|
onChange={handleOnChange}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { FormLabel, Stack } from '@chakra-ui/react'
|
|||||||
import { PhoneNumberInputBlock, Variable } from '@typebot.io/schemas'
|
import { PhoneNumberInputBlock, Variable } from '@typebot.io/schemas'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { CountryCodeSelect } from './CountryCodeSelect'
|
import { CountryCodeSelect } from './CountryCodeSelect'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
import { defaultPhoneInputOptions } from '@typebot.io/schemas/features/blocks/inputs/phone/constants'
|
import { defaultPhoneInputOptions } from '@typebot.io/schemas/features/blocks/inputs/phone/constants'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -12,6 +13,7 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const PhoneInputSettings = ({ options, onOptionsChange }: Props) => {
|
export const PhoneInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||||
|
const { t } = useTranslate()
|
||||||
const handlePlaceholderChange = (placeholder: string) =>
|
const handlePlaceholderChange = (placeholder: string) =>
|
||||||
onOptionsChange({ ...options, labels: { ...options?.labels, placeholder } })
|
onOptionsChange({ ...options, labels: { ...options?.labels, placeholder } })
|
||||||
const handleButtonLabelChange = (button: string) =>
|
const handleButtonLabelChange = (button: string) =>
|
||||||
@@ -26,7 +28,7 @@ export const PhoneInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
return (
|
return (
|
||||||
<Stack spacing={4}>
|
<Stack spacing={4}>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Placeholder:"
|
label={t('blocks.inputs.settings.placeholder.label')}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
options?.labels?.placeholder ??
|
options?.labels?.placeholder ??
|
||||||
defaultPhoneInputOptions.labels.placeholder
|
defaultPhoneInputOptions.labels.placeholder
|
||||||
@@ -34,7 +36,7 @@ export const PhoneInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
onChange={handlePlaceholderChange}
|
onChange={handlePlaceholderChange}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Button label:"
|
label={t('blocks.inputs.settings.button.label')}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
options?.labels?.button ?? defaultPhoneInputOptions.labels.button
|
options?.labels?.button ?? defaultPhoneInputOptions.labels.button
|
||||||
}
|
}
|
||||||
@@ -42,7 +44,7 @@ export const PhoneInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
/>
|
/>
|
||||||
<Stack>
|
<Stack>
|
||||||
<FormLabel mb="0" htmlFor="button">
|
<FormLabel mb="0" htmlFor="button">
|
||||||
Default country:
|
{t('blocks.inputs.phone.settings.defaultCountry.label')}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<CountryCodeSelect
|
<CountryCodeSelect
|
||||||
onSelect={handleDefaultCountryChange}
|
onSelect={handleDefaultCountryChange}
|
||||||
@@ -50,7 +52,7 @@ export const PhoneInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Retry message:"
|
label={t('blocks.inputs.settings.retryMessage.label')}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
options?.retryMessageContent ??
|
options?.retryMessageContent ??
|
||||||
defaultPhoneInputOptions.retryMessageContent
|
defaultPhoneInputOptions.retryMessageContent
|
||||||
@@ -59,7 +61,7 @@ export const PhoneInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
/>
|
/>
|
||||||
<Stack>
|
<Stack>
|
||||||
<FormLabel mb="0" htmlFor="variable">
|
<FormLabel mb="0" htmlFor="variable">
|
||||||
Save answer in a variable:
|
{t('blocks.inputs.settings.saveAnswer.label')}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<VariableSearchInput
|
<VariableSearchInput
|
||||||
initialVariableId={options?.variableId}
|
initialVariableId={options?.variableId}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { SwitchWithRelatedSettings } from '@/components/SwitchWithRelatedSetting
|
|||||||
import { ConditionForm } from '@/features/blocks/logic/condition/components/ConditionForm'
|
import { ConditionForm } from '@/features/blocks/logic/condition/components/ConditionForm'
|
||||||
import { Condition } from '@typebot.io/schemas'
|
import { Condition } from '@typebot.io/schemas'
|
||||||
import { LogicalOperator } from '@typebot.io/schemas/features/blocks/logic/condition/constants'
|
import { LogicalOperator } from '@typebot.io/schemas/features/blocks/logic/condition/constants'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
workspaceId: string
|
workspaceId: string
|
||||||
@@ -31,6 +32,8 @@ export const PictureChoiceItemSettings = ({
|
|||||||
item,
|
item,
|
||||||
onItemChange,
|
onItemChange,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
|
const { t } = useTranslate()
|
||||||
|
|
||||||
const updateTitle = (title: string) => onItemChange({ ...item, title })
|
const updateTitle = (title: string) => onItemChange({ ...item, title })
|
||||||
|
|
||||||
const updateImage = (pictureSrc: string) => {
|
const updateImage = (pictureSrc: string) => {
|
||||||
@@ -61,13 +64,17 @@ export const PictureChoiceItemSettings = ({
|
|||||||
return (
|
return (
|
||||||
<Stack spacing={4}>
|
<Stack spacing={4}>
|
||||||
<HStack>
|
<HStack>
|
||||||
<Text fontWeight="medium">Image:</Text>
|
<Text fontWeight="medium">
|
||||||
|
{t('blocks.inputs.picture.itemSettings.image.label')}
|
||||||
|
</Text>
|
||||||
<Popover isLazy>
|
<Popover isLazy>
|
||||||
{({ onClose }) => (
|
{({ onClose }) => (
|
||||||
<>
|
<>
|
||||||
<PopoverTrigger>
|
<PopoverTrigger>
|
||||||
<Button size="sm">
|
<Button size="sm">
|
||||||
{item.pictureSrc ? 'Change image' : 'Pick an image'}
|
{item.pictureSrc
|
||||||
|
? t('blocks.inputs.picture.itemSettings.image.change.label')
|
||||||
|
: t('blocks.inputs.picture.itemSettings.image.pick.label')}
|
||||||
</Button>
|
</Button>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent p="4" w="500px">
|
<PopoverContent p="4" w="500px">
|
||||||
@@ -91,17 +98,17 @@ export const PictureChoiceItemSettings = ({
|
|||||||
</Popover>
|
</Popover>
|
||||||
</HStack>
|
</HStack>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Title:"
|
label={t('blocks.inputs.picture.itemSettings.title.label')}
|
||||||
defaultValue={item.title}
|
defaultValue={item.title}
|
||||||
onChange={updateTitle}
|
onChange={updateTitle}
|
||||||
/>
|
/>
|
||||||
<Textarea
|
<Textarea
|
||||||
label="Description:"
|
label={t('blocks.inputs.settings.description.label')}
|
||||||
defaultValue={item.description}
|
defaultValue={item.description}
|
||||||
onChange={updateDescription}
|
onChange={updateDescription}
|
||||||
/>
|
/>
|
||||||
<SwitchWithRelatedSettings
|
<SwitchWithRelatedSettings
|
||||||
label="Display condition"
|
label={t('blocks.inputs.settings.displayCondition.label')}
|
||||||
initialValue={item.displayCondition?.isEnabled ?? false}
|
initialValue={item.displayCondition?.isEnabled ?? false}
|
||||||
onCheckChange={updateIsDisplayConditionEnabled}
|
onCheckChange={updateIsDisplayConditionEnabled}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { useTypebot } from '@/features/editor/providers/TypebotProvider'
|
|||||||
import { SetVariableLabel } from '@/components/SetVariableLabel'
|
import { SetVariableLabel } from '@/components/SetVariableLabel'
|
||||||
import { ItemNodesList } from '@/features/graph/components/nodes/item/ItemNodesList'
|
import { ItemNodesList } from '@/features/graph/components/nodes/item/ItemNodesList'
|
||||||
import { PictureChoiceBlock } from '@typebot.io/schemas/features/blocks/inputs/pictureChoice'
|
import { PictureChoiceBlock } from '@typebot.io/schemas/features/blocks/inputs/pictureChoice'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
block: PictureChoiceBlock
|
block: PictureChoiceBlock
|
||||||
@@ -12,6 +13,7 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const PictureChoiceNode = ({ block, indices }: Props) => {
|
export const PictureChoiceNode = ({ block, indices }: Props) => {
|
||||||
|
const { t } = useTranslate()
|
||||||
const { typebot } = useTypebot()
|
const { typebot } = useTypebot()
|
||||||
const dynamicVariableName = typebot?.variables.find(
|
const dynamicVariableName = typebot?.variables.find(
|
||||||
(variable) =>
|
(variable) =>
|
||||||
@@ -22,11 +24,17 @@ export const PictureChoiceNode = ({ block, indices }: Props) => {
|
|||||||
<Stack w="full">
|
<Stack w="full">
|
||||||
{block.options?.dynamicItems?.isEnabled && dynamicVariableName ? (
|
{block.options?.dynamicItems?.isEnabled && dynamicVariableName ? (
|
||||||
<Wrap spacing={1}>
|
<Wrap spacing={1}>
|
||||||
<Text>Display</Text>
|
<Text>
|
||||||
|
{t('blocks.inputs.picture.settings.dynamicVariables.display.label')}
|
||||||
|
</Text>
|
||||||
<Tag bg="orange.400" color="white">
|
<Tag bg="orange.400" color="white">
|
||||||
{dynamicVariableName}
|
{dynamicVariableName}
|
||||||
</Tag>
|
</Tag>
|
||||||
<Text>pictures</Text>
|
<Text>
|
||||||
|
{t(
|
||||||
|
'blocks.inputs.picture.settings.dynamicVariables.pictures.label'
|
||||||
|
)}
|
||||||
|
</Text>
|
||||||
</Wrap>
|
</Wrap>
|
||||||
) : (
|
) : (
|
||||||
<ItemNodesList block={block} indices={indices} />
|
<ItemNodesList block={block} indices={indices} />
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import React from 'react'
|
|||||||
import { PictureChoiceBlock } from '@typebot.io/schemas/features/blocks/inputs/pictureChoice'
|
import { PictureChoiceBlock } from '@typebot.io/schemas/features/blocks/inputs/pictureChoice'
|
||||||
import { SwitchWithRelatedSettings } from '@/components/SwitchWithRelatedSettings'
|
import { SwitchWithRelatedSettings } from '@/components/SwitchWithRelatedSettings'
|
||||||
import { defaultPictureChoiceOptions } from '@typebot.io/schemas/features/blocks/inputs/pictureChoice/constants'
|
import { defaultPictureChoiceOptions } from '@typebot.io/schemas/features/blocks/inputs/pictureChoice/constants'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
options?: PictureChoiceBlock['options']
|
options?: PictureChoiceBlock['options']
|
||||||
@@ -13,6 +14,8 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const PictureChoiceSettings = ({ options, onOptionsChange }: Props) => {
|
export const PictureChoiceSettings = ({ options, onOptionsChange }: Props) => {
|
||||||
|
const { t } = useTranslate()
|
||||||
|
|
||||||
const updateIsMultiple = (isMultipleChoice: boolean) =>
|
const updateIsMultiple = (isMultipleChoice: boolean) =>
|
||||||
onOptionsChange({ ...options, isMultipleChoice })
|
onOptionsChange({ ...options, isMultipleChoice })
|
||||||
const updateButtonLabel = (buttonLabel: string) =>
|
const updateButtonLabel = (buttonLabel: string) =>
|
||||||
@@ -63,14 +66,14 @@ export const PictureChoiceSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
return (
|
return (
|
||||||
<Stack spacing={4}>
|
<Stack spacing={4}>
|
||||||
<SwitchWithRelatedSettings
|
<SwitchWithRelatedSettings
|
||||||
label="Is searchable?"
|
label={t('blocks.inputs.settings.isSearchable.label')}
|
||||||
initialValue={
|
initialValue={
|
||||||
options?.isSearchable ?? defaultPictureChoiceOptions.isSearchable
|
options?.isSearchable ?? defaultPictureChoiceOptions.isSearchable
|
||||||
}
|
}
|
||||||
onCheckChange={updateIsSearchable}
|
onCheckChange={updateIsSearchable}
|
||||||
>
|
>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Input placeholder:"
|
label={t('blocks.inputs.settings.input.placeholder.label')}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
options?.searchInputPlaceholder ??
|
options?.searchInputPlaceholder ??
|
||||||
defaultPictureChoiceOptions.searchInputPlaceholder
|
defaultPictureChoiceOptions.searchInputPlaceholder
|
||||||
@@ -79,7 +82,7 @@ export const PictureChoiceSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
/>
|
/>
|
||||||
</SwitchWithRelatedSettings>
|
</SwitchWithRelatedSettings>
|
||||||
<SwitchWithRelatedSettings
|
<SwitchWithRelatedSettings
|
||||||
label="Multiple choice?"
|
label={t('blocks.inputs.settings.multipleChoice.label')}
|
||||||
initialValue={
|
initialValue={
|
||||||
options?.isMultipleChoice ??
|
options?.isMultipleChoice ??
|
||||||
defaultPictureChoiceOptions.isMultipleChoice
|
defaultPictureChoiceOptions.isMultipleChoice
|
||||||
@@ -87,7 +90,7 @@ export const PictureChoiceSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
onCheckChange={updateIsMultiple}
|
onCheckChange={updateIsMultiple}
|
||||||
>
|
>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Submit button label:"
|
label={t('blocks.inputs.settings.submitButton.label')}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
options?.buttonLabel ?? defaultPictureChoiceOptions.buttonLabel
|
options?.buttonLabel ?? defaultPictureChoiceOptions.buttonLabel
|
||||||
}
|
}
|
||||||
@@ -96,7 +99,7 @@ export const PictureChoiceSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
</SwitchWithRelatedSettings>
|
</SwitchWithRelatedSettings>
|
||||||
|
|
||||||
<SwitchWithRelatedSettings
|
<SwitchWithRelatedSettings
|
||||||
label="Dynamic items?"
|
label={t('blocks.inputs.picture.settings.dynamicItems.label')}
|
||||||
initialValue={
|
initialValue={
|
||||||
options?.dynamicItems?.isEnabled ??
|
options?.dynamicItems?.isEnabled ??
|
||||||
defaultPictureChoiceOptions.dynamicItems.isEnabled
|
defaultPictureChoiceOptions.dynamicItems.isEnabled
|
||||||
@@ -105,7 +108,7 @@ export const PictureChoiceSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
>
|
>
|
||||||
<Stack>
|
<Stack>
|
||||||
<FormLabel mb="0" htmlFor="variable">
|
<FormLabel mb="0" htmlFor="variable">
|
||||||
Images:
|
{t('blocks.inputs.picture.settings.dynamicItems.images.label')}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<VariableSearchInput
|
<VariableSearchInput
|
||||||
initialVariableId={options?.dynamicItems?.pictureSrcsVariableId}
|
initialVariableId={options?.dynamicItems?.pictureSrcsVariableId}
|
||||||
@@ -114,7 +117,7 @@ export const PictureChoiceSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
</Stack>
|
</Stack>
|
||||||
<Stack>
|
<Stack>
|
||||||
<FormLabel mb="0" htmlFor="variable">
|
<FormLabel mb="0" htmlFor="variable">
|
||||||
Titles:
|
{t('blocks.inputs.picture.settings.dynamicItems.titles.label')}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<VariableSearchInput
|
<VariableSearchInput
|
||||||
initialVariableId={options?.dynamicItems?.titlesVariableId}
|
initialVariableId={options?.dynamicItems?.titlesVariableId}
|
||||||
@@ -123,7 +126,9 @@ export const PictureChoiceSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
</Stack>
|
</Stack>
|
||||||
<Stack>
|
<Stack>
|
||||||
<FormLabel mb="0" htmlFor="variable">
|
<FormLabel mb="0" htmlFor="variable">
|
||||||
Descriptions:
|
{t(
|
||||||
|
'blocks.inputs.picture.settings.dynamicItems.descriptions.label'
|
||||||
|
)}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<VariableSearchInput
|
<VariableSearchInput
|
||||||
initialVariableId={options?.dynamicItems?.descriptionsVariableId}
|
initialVariableId={options?.dynamicItems?.descriptionsVariableId}
|
||||||
@@ -134,7 +139,7 @@ export const PictureChoiceSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
|
|
||||||
<Stack>
|
<Stack>
|
||||||
<FormLabel mb="0" htmlFor="variable">
|
<FormLabel mb="0" htmlFor="variable">
|
||||||
Save answer in a variable:
|
{t('blocks.inputs.settings.saveAnswer.label')}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<VariableSearchInput
|
<VariableSearchInput
|
||||||
initialVariableId={options?.variableId}
|
initialVariableId={options?.variableId}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { WithVariableContent } from '@/features/graph/components/nodes/block/WithVariableContent'
|
import { WithVariableContent } from '@/features/graph/components/nodes/block/WithVariableContent'
|
||||||
import { Text } from '@chakra-ui/react'
|
import { Text } from '@chakra-ui/react'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
import { RatingInputBlock } from '@typebot.io/schemas'
|
import { RatingInputBlock } from '@typebot.io/schemas'
|
||||||
import { defaultRatingInputOptions } from '@typebot.io/schemas/features/blocks/inputs/rating/constants'
|
import { defaultRatingInputOptions } from '@typebot.io/schemas/features/blocks/inputs/rating/constants'
|
||||||
|
|
||||||
@@ -8,12 +9,17 @@ type Props = {
|
|||||||
block: RatingInputBlock
|
block: RatingInputBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
export const RatingInputContent = ({ variableId, block }: Props) =>
|
export const RatingInputContent = ({ variableId, block }: Props) => {
|
||||||
variableId ? (
|
const { t } = useTranslate()
|
||||||
|
|
||||||
|
return variableId ? (
|
||||||
<WithVariableContent variableId={variableId} />
|
<WithVariableContent variableId={variableId} />
|
||||||
) : (
|
) : (
|
||||||
<Text noOfLines={1} pr="6">
|
<Text noOfLines={1} pr="6">
|
||||||
Rate from {block.options?.buttonType === 'Icons' ? 1 : 0} to{' '}
|
{t('blocks.inputs.rating.from.label')}{' '}
|
||||||
|
{block.options?.buttonType === 'Icons' ? 1 : 0}{' '}
|
||||||
|
{t('blocks.inputs.rating.to.label')}{' '}
|
||||||
{block.options?.length ?? defaultRatingInputOptions.length}
|
{block.options?.length ?? defaultRatingInputOptions.length}
|
||||||
</Text>
|
</Text>
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { SwitchWithLabel } from '@/components/inputs/SwitchWithLabel'
|
|||||||
import { TextInput } from '@/components/inputs'
|
import { TextInput } from '@/components/inputs'
|
||||||
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
||||||
import { defaultRatingInputOptions } from '@typebot.io/schemas/features/blocks/inputs/rating/constants'
|
import { defaultRatingInputOptions } from '@typebot.io/schemas/features/blocks/inputs/rating/constants'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
options: RatingInputBlock['options']
|
options: RatingInputBlock['options']
|
||||||
@@ -13,6 +14,8 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const RatingInputSettings = ({ options, onOptionsChange }: Props) => {
|
export const RatingInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||||
|
const { t } = useTranslate()
|
||||||
|
|
||||||
const handleLengthChange = (length: number) =>
|
const handleLengthChange = (length: number) =>
|
||||||
onOptionsChange({ ...options, length })
|
onOptionsChange({ ...options, length })
|
||||||
|
|
||||||
@@ -52,7 +55,7 @@ export const RatingInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
<Stack spacing={4}>
|
<Stack spacing={4}>
|
||||||
<Stack>
|
<Stack>
|
||||||
<FormLabel mb="0" htmlFor="button">
|
<FormLabel mb="0" htmlFor="button">
|
||||||
Maximum:
|
{t('blocks.inputs.rating.settings.maximum.label')}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<DropdownList
|
<DropdownList
|
||||||
onItemSelect={handleLengthChange}
|
onItemSelect={handleLengthChange}
|
||||||
@@ -63,7 +66,7 @@ export const RatingInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
|
|
||||||
<Stack>
|
<Stack>
|
||||||
<FormLabel mb="0" htmlFor="button">
|
<FormLabel mb="0" htmlFor="button">
|
||||||
Type:
|
{t('blocks.inputs.rating.settings.type.label')}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<DropdownList
|
<DropdownList
|
||||||
onItemSelect={handleTypeChange}
|
onItemSelect={handleTypeChange}
|
||||||
@@ -76,7 +79,7 @@ export const RatingInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
|
|
||||||
{options?.buttonType === 'Icons' && (
|
{options?.buttonType === 'Icons' && (
|
||||||
<SwitchWithLabel
|
<SwitchWithLabel
|
||||||
label="Custom icon?"
|
label={t('blocks.inputs.rating.settings.customIcon.label')}
|
||||||
initialValue={
|
initialValue={
|
||||||
options?.customIcon?.isEnabled ??
|
options?.customIcon?.isEnabled ??
|
||||||
defaultRatingInputOptions.customIcon.isEnabled
|
defaultRatingInputOptions.customIcon.isEnabled
|
||||||
@@ -86,33 +89,43 @@ export const RatingInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
)}
|
)}
|
||||||
{options?.buttonType === 'Icons' && options.customIcon?.isEnabled && (
|
{options?.buttonType === 'Icons' && options.customIcon?.isEnabled && (
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Icon SVG:"
|
label={t('blocks.inputs.rating.settings.iconSVG.label')}
|
||||||
defaultValue={options.customIcon.svg}
|
defaultValue={options.customIcon.svg}
|
||||||
onChange={handleIconSvgChange}
|
onChange={handleIconSvgChange}
|
||||||
placeholder="<svg>...</svg>"
|
placeholder="<svg>...</svg>"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<TextInput
|
<TextInput
|
||||||
label={`${options?.buttonType === 'Icons' ? '1' : '0'} label:`}
|
label={t('blocks.inputs.rating.settings.rateLabel.label', {
|
||||||
|
rate: options?.buttonType === 'Icons' ? '1' : '0',
|
||||||
|
})}
|
||||||
defaultValue={options?.labels?.left}
|
defaultValue={options?.labels?.left}
|
||||||
onChange={handleLeftLabelChange}
|
onChange={handleLeftLabelChange}
|
||||||
placeholder="Not likely at all"
|
placeholder={t(
|
||||||
|
'blocks.inputs.rating.settings.notLikely.placeholder.label'
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label={`${length} label:`}
|
label={t('blocks.inputs.rating.settings.rateLabel.label', {
|
||||||
|
rate: length,
|
||||||
|
})}
|
||||||
defaultValue={options?.labels?.right}
|
defaultValue={options?.labels?.right}
|
||||||
onChange={handleRightLabelChange}
|
onChange={handleRightLabelChange}
|
||||||
placeholder="Extremely likely"
|
placeholder={t(
|
||||||
|
'blocks.inputs.rating.settings.extremelyLikely.placeholder.label'
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
<SwitchWithLabel
|
<SwitchWithLabel
|
||||||
label="One click submit"
|
label={t('blocks.inputs.rating.settings.oneClickSubmit.label')}
|
||||||
moreInfoContent='If enabled, the answer will be submitted as soon as the user clicks on a rating instead of showing the "Send" button.'
|
moreInfoContent={t(
|
||||||
|
'blocks.inputs.rating.settings.oneClickSubmit.infoText.label'
|
||||||
|
)}
|
||||||
initialValue={isOneClickSubmitEnabled}
|
initialValue={isOneClickSubmitEnabled}
|
||||||
onCheckChange={handleOneClickSubmitChange}
|
onCheckChange={handleOneClickSubmitChange}
|
||||||
/>
|
/>
|
||||||
{!isOneClickSubmitEnabled && (
|
{!isOneClickSubmitEnabled && (
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Button label:"
|
label={t('blocks.inputs.settings.button.label')}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
options?.labels?.button ?? defaultRatingInputOptions.labels.button
|
options?.labels?.button ?? defaultRatingInputOptions.labels.button
|
||||||
}
|
}
|
||||||
@@ -121,7 +134,7 @@ export const RatingInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
)}
|
)}
|
||||||
<Stack>
|
<Stack>
|
||||||
<FormLabel mb="0" htmlFor="variable">
|
<FormLabel mb="0" htmlFor="variable">
|
||||||
Save answer in a variable:
|
{t('blocks.inputs.settings.saveAnswer.label')}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<VariableSearchInput
|
<VariableSearchInput
|
||||||
initialVariableId={options?.variableId}
|
initialVariableId={options?.variableId}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { TextInput } from '@/components/inputs'
|
|||||||
import { SwitchWithLabel } from '@/components/inputs/SwitchWithLabel'
|
import { SwitchWithLabel } from '@/components/inputs/SwitchWithLabel'
|
||||||
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
||||||
import { FormLabel, Stack } from '@chakra-ui/react'
|
import { FormLabel, Stack } from '@chakra-ui/react'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
import { TextInputBlock, Variable } from '@typebot.io/schemas'
|
import { TextInputBlock, Variable } from '@typebot.io/schemas'
|
||||||
import { defaultTextInputOptions } from '@typebot.io/schemas/features/blocks/inputs/text/constants'
|
import { defaultTextInputOptions } from '@typebot.io/schemas/features/blocks/inputs/text/constants'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
@@ -12,6 +13,7 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const TextInputSettings = ({ options, onOptionsChange }: Props) => {
|
export const TextInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||||
|
const { t } = useTranslate()
|
||||||
const handlePlaceholderChange = (placeholder: string) =>
|
const handlePlaceholderChange = (placeholder: string) =>
|
||||||
onOptionsChange({ ...options, labels: { ...options?.labels, placeholder } })
|
onOptionsChange({ ...options, labels: { ...options?.labels, placeholder } })
|
||||||
const handleButtonLabelChange = (button: string) =>
|
const handleButtonLabelChange = (button: string) =>
|
||||||
@@ -24,12 +26,12 @@ export const TextInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
return (
|
return (
|
||||||
<Stack spacing={4}>
|
<Stack spacing={4}>
|
||||||
<SwitchWithLabel
|
<SwitchWithLabel
|
||||||
label="Long text?"
|
label={t('blocks.inputs.text.settings.longText.label')}
|
||||||
initialValue={options?.isLong ?? defaultTextInputOptions.isLong}
|
initialValue={options?.isLong ?? defaultTextInputOptions.isLong}
|
||||||
onCheckChange={handleLongChange}
|
onCheckChange={handleLongChange}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Placeholder:"
|
label={t('blocks.inputs.settings.placeholder.label')}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
options?.labels?.placeholder ??
|
options?.labels?.placeholder ??
|
||||||
defaultTextInputOptions.labels.placeholder
|
defaultTextInputOptions.labels.placeholder
|
||||||
@@ -37,7 +39,7 @@ export const TextInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
onChange={handlePlaceholderChange}
|
onChange={handlePlaceholderChange}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Button label:"
|
label={t('blocks.inputs.settings.button.label')}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
options?.labels?.button ?? defaultTextInputOptions.labels.button
|
options?.labels?.button ?? defaultTextInputOptions.labels.button
|
||||||
}
|
}
|
||||||
@@ -45,7 +47,7 @@ export const TextInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
/>
|
/>
|
||||||
<Stack>
|
<Stack>
|
||||||
<FormLabel mb="0" htmlFor="variable">
|
<FormLabel mb="0" htmlFor="variable">
|
||||||
Save answer in a variable:
|
{t('blocks.inputs.settings.saveAnswer.label')}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<VariableSearchInput
|
<VariableSearchInput
|
||||||
initialVariableId={options?.variableId}
|
initialVariableId={options?.variableId}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { TextInput } from '@/components/inputs'
|
import { TextInput } from '@/components/inputs'
|
||||||
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
||||||
import { FormLabel, Stack } from '@chakra-ui/react'
|
import { FormLabel, Stack } from '@chakra-ui/react'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
import { UrlInputBlock, Variable } from '@typebot.io/schemas'
|
import { UrlInputBlock, Variable } from '@typebot.io/schemas'
|
||||||
import { defaultUrlInputOptions } from '@typebot.io/schemas/features/blocks/inputs/url/constants'
|
import { defaultUrlInputOptions } from '@typebot.io/schemas/features/blocks/inputs/url/constants'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
@@ -11,6 +12,7 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const UrlInputSettings = ({ options, onOptionsChange }: Props) => {
|
export const UrlInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||||
|
const { t } = useTranslate()
|
||||||
const handlePlaceholderChange = (placeholder: string) =>
|
const handlePlaceholderChange = (placeholder: string) =>
|
||||||
onOptionsChange({ ...options, labels: { ...options?.labels, placeholder } })
|
onOptionsChange({ ...options, labels: { ...options?.labels, placeholder } })
|
||||||
const handleButtonLabelChange = (button: string) =>
|
const handleButtonLabelChange = (button: string) =>
|
||||||
@@ -23,7 +25,7 @@ export const UrlInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
return (
|
return (
|
||||||
<Stack spacing={4}>
|
<Stack spacing={4}>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Placeholder:"
|
label={t('blocks.inputs.settings.placeholder.label')}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
options?.labels?.placeholder ??
|
options?.labels?.placeholder ??
|
||||||
defaultUrlInputOptions.labels.placeholder
|
defaultUrlInputOptions.labels.placeholder
|
||||||
@@ -31,14 +33,14 @@ export const UrlInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
onChange={handlePlaceholderChange}
|
onChange={handlePlaceholderChange}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Button label:"
|
label={t('blocks.inputs.settings.button.label')}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
options?.labels?.button ?? defaultUrlInputOptions.labels.button
|
options?.labels?.button ?? defaultUrlInputOptions.labels.button
|
||||||
}
|
}
|
||||||
onChange={handleButtonLabelChange}
|
onChange={handleButtonLabelChange}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Retry message:"
|
label={t('blocks.inputs.settings.retryMessage.label')}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
options?.retryMessageContent ??
|
options?.retryMessageContent ??
|
||||||
defaultUrlInputOptions.retryMessageContent
|
defaultUrlInputOptions.retryMessageContent
|
||||||
@@ -47,7 +49,7 @@ export const UrlInputSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
/>
|
/>
|
||||||
<Stack>
|
<Stack>
|
||||||
<FormLabel mb="0" htmlFor="variable">
|
<FormLabel mb="0" htmlFor="variable">
|
||||||
Save answer in a variable:
|
{t('blocks.inputs.settings.saveAnswer.label')}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<VariableSearchInput
|
<VariableSearchInput
|
||||||
initialVariableId={options?.variableId}
|
initialVariableId={options?.variableId}
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ type Props = {
|
|||||||
options: UrlInputBlock['options']
|
options: UrlInputBlock['options']
|
||||||
}
|
}
|
||||||
|
|
||||||
export const UrlNodeContent = ({ options }: Props) =>
|
export const UrlNodeContent = ({ options }: Props) => {
|
||||||
options?.variableId ? (
|
return options?.variableId ? (
|
||||||
<WithVariableContent variableId={options.variableId} />
|
<WithVariableContent variableId={options.variableId} />
|
||||||
) : (
|
) : (
|
||||||
<Text color={'gray.500'} w="90%">
|
<Text color={'gray.500'} w="90%">
|
||||||
@@ -17,3 +17,4 @@ export const UrlNodeContent = ({ options }: Props) =>
|
|||||||
defaultUrlInputOptions.labels.placeholder}
|
defaultUrlInputOptions.labels.placeholder}
|
||||||
</Text>
|
</Text>
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,11 +5,14 @@ import { TableListItemProps } from '@/components/TableList'
|
|||||||
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
||||||
import { TextInput } from '@/components/inputs'
|
import { TextInput } from '@/components/inputs'
|
||||||
import { ComparisonOperators } from '@typebot.io/schemas/features/blocks/logic/condition/constants'
|
import { ComparisonOperators } from '@typebot.io/schemas/features/blocks/logic/condition/constants'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
|
|
||||||
export const ComparisonItem = ({
|
export const ComparisonItem = ({
|
||||||
item,
|
item,
|
||||||
onItemChange,
|
onItemChange,
|
||||||
}: TableListItemProps<Comparison>) => {
|
}: TableListItemProps<Comparison>) => {
|
||||||
|
const { t } = useTranslate()
|
||||||
|
|
||||||
const handleSelectVariable = (variable?: Variable) => {
|
const handleSelectVariable = (variable?: Variable) => {
|
||||||
if (variable?.id === item.variableId) return
|
if (variable?.id === item.variableId) return
|
||||||
onItemChange({ ...item, variableId: variable?.id })
|
onItemChange({ ...item, variableId: variable?.id })
|
||||||
@@ -31,13 +34,15 @@ export const ComparisonItem = ({
|
|||||||
<VariableSearchInput
|
<VariableSearchInput
|
||||||
initialVariableId={item.variableId}
|
initialVariableId={item.variableId}
|
||||||
onSelectVariable={handleSelectVariable}
|
onSelectVariable={handleSelectVariable}
|
||||||
placeholder="Search for a variable"
|
placeholder={t('variables.search')}
|
||||||
/>
|
/>
|
||||||
<DropdownList
|
<DropdownList
|
||||||
currentItem={item.comparisonOperator}
|
currentItem={item.comparisonOperator}
|
||||||
onItemSelect={handleSelectComparisonOperator}
|
onItemSelect={handleSelectComparisonOperator}
|
||||||
items={Object.values(ComparisonOperators)}
|
items={Object.values(ComparisonOperators)}
|
||||||
placeholder="Select an operator"
|
placeholder={t(
|
||||||
|
'blocks.inputs.button.buttonSettings.displayCondition.selectOperator.label'
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
{item.comparisonOperator !== ComparisonOperators.IS_SET &&
|
{item.comparisonOperator !== ComparisonOperators.IS_SET &&
|
||||||
item.comparisonOperator !== ComparisonOperators.IS_EMPTY && (
|
item.comparisonOperator !== ComparisonOperators.IS_EMPTY && (
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Stack, Wrap, Tag, Text, useColorModeValue } from '@chakra-ui/react'
|
import { Stack, Wrap, Tag, Text, useColorModeValue } from '@chakra-ui/react'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
import { byId } from '@typebot.io/lib'
|
import { byId } from '@typebot.io/lib'
|
||||||
import { Condition, Variable } from '@typebot.io/schemas'
|
import { Condition, Variable } from '@typebot.io/schemas'
|
||||||
import { ComparisonOperators } from '@typebot.io/schemas/features/blocks/logic/condition/constants'
|
import { ComparisonOperators } from '@typebot.io/schemas/features/blocks/logic/condition/constants'
|
||||||
@@ -15,6 +16,7 @@ export const ConditionContent = ({
|
|||||||
size = 'sm',
|
size = 'sm',
|
||||||
displaySemicolon,
|
displaySemicolon,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
|
const { t } = useTranslate()
|
||||||
const comparisonValueBg = useColorModeValue('gray.200', 'gray.700')
|
const comparisonValueBg = useColorModeValue('gray.200', 'gray.700')
|
||||||
return (
|
return (
|
||||||
<Stack>
|
<Stack>
|
||||||
@@ -22,7 +24,11 @@ export const ConditionContent = ({
|
|||||||
const variable = variables.find(byId(comparison.variableId))
|
const variable = variables.find(byId(comparison.variableId))
|
||||||
return (
|
return (
|
||||||
<Wrap key={comparison.id} spacing={1} noOfLines={1}>
|
<Wrap key={comparison.id} spacing={1} noOfLines={1}>
|
||||||
{idx === 0 && <Text fontSize={size}>IF</Text>}
|
{idx === 0 && (
|
||||||
|
<Text fontSize={size}>
|
||||||
|
{t('blocks.inputs.button.conditionContent.if.label')}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
{idx > 0 && (
|
{idx > 0 && (
|
||||||
<Text fontSize={size}>{condition.logicalOperator ?? ''}</Text>
|
<Text fontSize={size}>{condition.logicalOperator ?? ''}</Text>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
LogicalOperator,
|
LogicalOperator,
|
||||||
defaultConditionItemContent,
|
defaultConditionItemContent,
|
||||||
} from '@typebot.io/schemas/features/blocks/logic/condition/constants'
|
} from '@typebot.io/schemas/features/blocks/logic/condition/constants'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
condition: Condition | undefined
|
condition: Condition | undefined
|
||||||
@@ -15,6 +16,7 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const ConditionForm = ({ condition, onConditionChange }: Props) => {
|
export const ConditionForm = ({ condition, onConditionChange }: Props) => {
|
||||||
|
const { t } = useTranslate()
|
||||||
const handleComparisonsChange = (comparisons: Comparison[]) =>
|
const handleComparisonsChange = (comparisons: Comparison[]) =>
|
||||||
onConditionChange({ ...condition, comparisons })
|
onConditionChange({ ...condition, comparisons })
|
||||||
const handleLogicalOperatorChange = (logicalOperator: LogicalOperator) =>
|
const handleLogicalOperatorChange = (logicalOperator: LogicalOperator) =>
|
||||||
@@ -36,7 +38,9 @@ export const ConditionForm = ({ condition, onConditionChange }: Props) => {
|
|||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
)}
|
)}
|
||||||
addLabel="Add a comparison"
|
addLabel={t(
|
||||||
|
'blocks.inputs.button.buttonSettings.addComparisonButton.label'
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{(props) => <ComparisonItem {...props} />}
|
{(props) => <ComparisonItem {...props} />}
|
||||||
</TableList>
|
</TableList>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { useToast } from '../../../hooks/useToast'
|
|||||||
import { Credentials } from '@typebot.io/schemas'
|
import { Credentials } from '@typebot.io/schemas'
|
||||||
import { trpc } from '@/lib/trpc'
|
import { trpc } from '@/lib/trpc'
|
||||||
import { useWorkspace } from '@/features/workspace/WorkspaceProvider'
|
import { useWorkspace } from '@/features/workspace/WorkspaceProvider'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
|
|
||||||
type Props = Omit<ButtonProps, 'type'> & {
|
type Props = Omit<ButtonProps, 'type'> & {
|
||||||
type: Credentials['type']
|
type: Credentials['type']
|
||||||
@@ -36,6 +37,7 @@ export const CredentialsDropdown = ({
|
|||||||
credentialsName,
|
credentialsName,
|
||||||
...props
|
...props
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
|
const { t } = useTranslate()
|
||||||
const { showToast } = useToast()
|
const { showToast } = useToast()
|
||||||
const { currentRole } = useWorkspace()
|
const { currentRole } = useWorkspace()
|
||||||
const { data, refetch } = trpc.credentials.listCredentials.useQuery({
|
const { data, refetch } = trpc.credentials.listCredentials.useQuery({
|
||||||
@@ -62,7 +64,7 @@ export const CredentialsDropdown = ({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const defaultCredentialsLabel =
|
const defaultCredentialsLabel =
|
||||||
defaultCredentialLabel ?? `Select ${credentialsName}`
|
defaultCredentialLabel ?? `${t('select')} ${credentialsName}`
|
||||||
|
|
||||||
const currentCredential = data?.credentials.find(
|
const currentCredential = data?.credentials.find(
|
||||||
(c) => c.id === currentCredentialsId
|
(c) => c.id === currentCredentialsId
|
||||||
@@ -91,7 +93,7 @@ export const CredentialsDropdown = ({
|
|||||||
isDisabled={currentRole === 'GUEST'}
|
isDisabled={currentRole === 'GUEST'}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
Add {credentialsName}
|
{t('add')} {credentialsName}
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -140,7 +142,9 @@ export const CredentialsDropdown = ({
|
|||||||
{credentials.name}
|
{credentials.name}
|
||||||
<IconButton
|
<IconButton
|
||||||
icon={<TrashIcon />}
|
icon={<TrashIcon />}
|
||||||
aria-label="Remove credentials"
|
aria-label={t(
|
||||||
|
'blocks.inputs.payment.settings.credentials.removeCredentials.label'
|
||||||
|
)}
|
||||||
size="xs"
|
size="xs"
|
||||||
onClick={deleteCredentials(credentials.id)}
|
onClick={deleteCredentials(credentials.id)}
|
||||||
isLoading={isDeleting === credentials.id}
|
isLoading={isDeleting === credentials.id}
|
||||||
@@ -156,7 +160,7 @@ export const CredentialsDropdown = ({
|
|||||||
icon={<PlusIcon />}
|
icon={<PlusIcon />}
|
||||||
onClick={onCreateNewClick}
|
onClick={onCreateNewClick}
|
||||||
>
|
>
|
||||||
Connect new
|
{t('blocks.inputs.payment.settings.credentials.connectNew.label')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -31,9 +31,11 @@ const groupsActions = (setTypebot: SetTypebot): GroupsActions => ({
|
|||||||
id,
|
id,
|
||||||
block,
|
block,
|
||||||
indices,
|
indices,
|
||||||
|
groupLabel,
|
||||||
...graphCoordinates
|
...graphCoordinates
|
||||||
}: Coordinates & {
|
}: Coordinates & {
|
||||||
id: string
|
id: string
|
||||||
|
groupLabel?: string
|
||||||
block: BlockV6 | BlockV6['type']
|
block: BlockV6 | BlockV6['type']
|
||||||
indices: BlockIndices
|
indices: BlockIndices
|
||||||
}) =>
|
}) =>
|
||||||
@@ -42,7 +44,7 @@ const groupsActions = (setTypebot: SetTypebot): GroupsActions => ({
|
|||||||
const newGroup: GroupV6 = {
|
const newGroup: GroupV6 = {
|
||||||
id,
|
id,
|
||||||
graphCoordinates,
|
graphCoordinates,
|
||||||
title: `Group #${typebot.groups.length + 1}`,
|
title: `${groupLabel ?? 'Group'} #${typebot.groups.length + 1}`,
|
||||||
blocks: [],
|
blocks: [],
|
||||||
}
|
}
|
||||||
typebot.groups.push(newGroup)
|
typebot.groups.push(newGroup)
|
||||||
|
|||||||
@@ -2,9 +2,11 @@ import { MenuList, MenuItem } from '@chakra-ui/react'
|
|||||||
import { CopyIcon, TrashIcon } from '@/components/icons'
|
import { CopyIcon, TrashIcon } from '@/components/icons'
|
||||||
import { useTypebot } from '@/features/editor/providers/TypebotProvider'
|
import { useTypebot } from '@/features/editor/providers/TypebotProvider'
|
||||||
import { BlockIndices } from '@typebot.io/schemas'
|
import { BlockIndices } from '@typebot.io/schemas'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
|
|
||||||
type Props = { indices: BlockIndices }
|
type Props = { indices: BlockIndices }
|
||||||
export const BlockNodeContextMenu = ({ indices }: Props) => {
|
export const BlockNodeContextMenu = ({ indices }: Props) => {
|
||||||
|
const { t } = useTranslate()
|
||||||
const { deleteBlock, duplicateBlock } = useTypebot()
|
const { deleteBlock, duplicateBlock } = useTypebot()
|
||||||
|
|
||||||
const handleDuplicateClick = () => duplicateBlock(indices)
|
const handleDuplicateClick = () => duplicateBlock(indices)
|
||||||
@@ -14,10 +16,10 @@ export const BlockNodeContextMenu = ({ indices }: Props) => {
|
|||||||
return (
|
return (
|
||||||
<MenuList>
|
<MenuList>
|
||||||
<MenuItem icon={<CopyIcon />} onClick={handleDuplicateClick}>
|
<MenuItem icon={<CopyIcon />} onClick={handleDuplicateClick}>
|
||||||
Duplicate
|
{t('duplicate')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem icon={<TrashIcon />} onClick={handleDeleteClick}>
|
<MenuItem icon={<TrashIcon />} onClick={handleDeleteClick}>
|
||||||
Delete
|
{t('delete')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</MenuList>
|
</MenuList>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
import { BlockWithOptions } from '@typebot.io/schemas'
|
import { BlockWithOptions } from '@typebot.io/schemas'
|
||||||
import { getHelpDocUrl } from '@/features/graph/helpers/getHelpDocUrl'
|
import { getHelpDocUrl } from '@/features/graph/helpers/getHelpDocUrl'
|
||||||
import { useForgedBlock } from '@/features/forge/hooks/useForgedBlock'
|
import { useForgedBlock } from '@/features/forge/hooks/useForgedBlock'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
blockType: BlockWithOptions['type']
|
blockType: BlockWithOptions['type']
|
||||||
@@ -16,6 +17,7 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const SettingsHoverBar = ({ blockType, onExpandClick }: Props) => {
|
export const SettingsHoverBar = ({ blockType, onExpandClick }: Props) => {
|
||||||
|
const { t } = useTranslate()
|
||||||
const { blockDef } = useForgedBlock(blockType)
|
const { blockDef } = useForgedBlock(blockType)
|
||||||
const helpDocUrl = getHelpDocUrl(blockType, blockDef)
|
const helpDocUrl = getHelpDocUrl(blockType, blockDef)
|
||||||
return (
|
return (
|
||||||
@@ -46,7 +48,7 @@ export const SettingsHoverBar = ({ blockType, onExpandClick }: Props) => {
|
|||||||
href={helpDocUrl}
|
href={helpDocUrl}
|
||||||
isExternal
|
isExternal
|
||||||
>
|
>
|
||||||
Help
|
{t('help')}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</HStack>
|
</HStack>
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
import { MenuList, MenuItem } from '@chakra-ui/react'
|
import { MenuList, MenuItem } from '@chakra-ui/react'
|
||||||
import { CopyIcon, TrashIcon } from '@/components/icons'
|
import { CopyIcon, TrashIcon } from '@/components/icons'
|
||||||
import { useTypebot } from '@/features/editor/providers/TypebotProvider'
|
import { useTypebot } from '@/features/editor/providers/TypebotProvider'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
|
|
||||||
export const GroupNodeContextMenu = ({
|
export const GroupNodeContextMenu = ({
|
||||||
groupIndex,
|
groupIndex,
|
||||||
}: {
|
}: {
|
||||||
groupIndex: number
|
groupIndex: number
|
||||||
}) => {
|
}) => {
|
||||||
|
const { t } = useTranslate()
|
||||||
const { deleteGroup, duplicateGroup } = useTypebot()
|
const { deleteGroup, duplicateGroup } = useTypebot()
|
||||||
|
|
||||||
const handleDeleteClick = () => deleteGroup(groupIndex)
|
const handleDeleteClick = () => deleteGroup(groupIndex)
|
||||||
@@ -16,10 +18,10 @@ export const GroupNodeContextMenu = ({
|
|||||||
return (
|
return (
|
||||||
<MenuList>
|
<MenuList>
|
||||||
<MenuItem icon={<CopyIcon />} onClick={handleDuplicateClick}>
|
<MenuItem icon={<CopyIcon />} onClick={handleDuplicateClick}>
|
||||||
Duplicate
|
{t('duplicate')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem icon={<TrashIcon />} onClick={handleDeleteClick}>
|
<MenuItem icon={<TrashIcon />} onClick={handleDeleteClick}>
|
||||||
Delete
|
{t('delete')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</MenuList>
|
</MenuList>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import { Coordinates } from '@dnd-kit/utilities'
|
|||||||
import { BlockSourceEndpoint } from '../../endpoints/BlockSourceEndpoint'
|
import { BlockSourceEndpoint } from '../../endpoints/BlockSourceEndpoint'
|
||||||
import { LogicBlockType } from '@typebot.io/schemas/features/blocks/logic/constants'
|
import { LogicBlockType } from '@typebot.io/schemas/features/blocks/logic/constants'
|
||||||
import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/constants'
|
import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/constants'
|
||||||
|
import { useTranslate } from '@tolgee/react'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
block: BlockWithItems
|
block: BlockWithItems
|
||||||
@@ -192,6 +193,8 @@ const DefaultItemNode = ({
|
|||||||
block: BlockWithItems
|
block: BlockWithItems
|
||||||
groupId: string
|
groupId: string
|
||||||
}) => {
|
}) => {
|
||||||
|
const { t } = useTranslate()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
px="4"
|
px="4"
|
||||||
@@ -205,7 +208,9 @@ const DefaultItemNode = ({
|
|||||||
cursor="not-allowed"
|
cursor="not-allowed"
|
||||||
>
|
>
|
||||||
<Text color="gray.500">
|
<Text color="gray.500">
|
||||||
{block.type === LogicBlockType.CONDITION ? 'Else' : 'Default'}
|
{block.type === LogicBlockType.CONDITION
|
||||||
|
? t('blocks.inputs.button.else.label')
|
||||||
|
: t('blocks.inputs.button.default.label')}
|
||||||
</Text>
|
</Text>
|
||||||
<BlockSourceEndpoint
|
<BlockSourceEndpoint
|
||||||
source={{
|
source={{
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
"account.preferences.graphNavigation.trackpad.label": "Trackpad",
|
"account.preferences.graphNavigation.trackpad.label": "Trackpad",
|
||||||
"account.preferences.language.heading": "Language",
|
"account.preferences.language.heading": "Language",
|
||||||
"account.preferences.language.tooltip": "The translations are not complete yet. It is a work in progress. \uD83E\uDD13",
|
"account.preferences.language.tooltip": "The translations are not complete yet. It is a work in progress. \uD83E\uDD13",
|
||||||
|
"add": "Add",
|
||||||
"analytics.completionRateLabel": "Completion rate",
|
"analytics.completionRateLabel": "Completion rate",
|
||||||
"analytics.notAvailableLabel": "Not available",
|
"analytics.notAvailableLabel": "Not available",
|
||||||
"analytics.startsLabel": "Starts",
|
"analytics.startsLabel": "Starts",
|
||||||
@@ -112,7 +113,103 @@
|
|||||||
"billing.usage.heading": "Usage",
|
"billing.usage.heading": "Usage",
|
||||||
"billing.usage.unlimited": "Unlimited",
|
"billing.usage.unlimited": "Unlimited",
|
||||||
"blocks.bubbles.embed.blockCard.tooltip": "Embed a pdf, an iframe, a website...",
|
"blocks.bubbles.embed.blockCard.tooltip": "Embed a pdf, an iframe, a website...",
|
||||||
|
"blocks.inputs.button.addItem.ariaLabel": "Add item",
|
||||||
|
"blocks.inputs.button.buttonSettings.addComparisonButton.label": "Add comparison",
|
||||||
|
"blocks.inputs.button.buttonSettings.displayCondition.infoText.label": "Only display this item if a condition is met.",
|
||||||
|
"blocks.inputs.button.buttonSettings.displayCondition.selectOperator.label": "Select an operator",
|
||||||
|
"blocks.inputs.button.clickToEdit.label": "Click to edit",
|
||||||
|
"blocks.inputs.button.conditionContent.if.label": "IF",
|
||||||
|
"blocks.inputs.button.default.label": "Default",
|
||||||
|
"blocks.inputs.button.else.label": "Else",
|
||||||
|
"blocks.inputs.button.openSettings.ariaLabel": "Open settings",
|
||||||
|
"blocks.inputs.button.settings.dynamicData.infoText.label": "If defined, buttons will be dynamically displayed based on what the variable contains.",
|
||||||
|
"blocks.inputs.button.settings.dynamicData.label": "Dynamic data:",
|
||||||
|
"blocks.inputs.button.variables.buttons.label": "buttons",
|
||||||
|
"blocks.inputs.button.variables.display.label": "Display",
|
||||||
|
"blocks.inputs.date.placeholder.label": "Pick a date...",
|
||||||
|
"blocks.inputs.date.settings.format.example.label": "i.e",
|
||||||
|
"blocks.inputs.date.settings.format.label": "Format:",
|
||||||
|
"blocks.inputs.date.settings.from.label": "From label:",
|
||||||
|
"blocks.inputs.date.settings.isRange.label": "Is range?",
|
||||||
|
"blocks.inputs.date.settings.to.label": "To label:",
|
||||||
|
"blocks.inputs.date.settings.toInputValue.label": "To:",
|
||||||
|
"blocks.inputs.date.settings.withTime.label": "With time?",
|
||||||
|
"blocks.inputs.file.collectMultiple.label": "Collect files",
|
||||||
|
"blocks.inputs.file.collectSingle.label": "Collect file",
|
||||||
|
"blocks.inputs.file.settings.allowMultiple.label": "Allow multiple files?",
|
||||||
|
"blocks.inputs.file.settings.clear.label": "Clear button label:",
|
||||||
|
"blocks.inputs.file.settings.required.label": "Required?",
|
||||||
|
"blocks.inputs.file.settings.saveMultipleUpload.label": "Save upload URLs in a variable:",
|
||||||
|
"blocks.inputs.file.settings.saveSingleUpload.label": "Save upload URL in a variable:",
|
||||||
|
"blocks.inputs.file.settings.skip.label": "Skip button label:",
|
||||||
"blocks.inputs.fileUpload.blockCard.tooltip": "Upload Files",
|
"blocks.inputs.fileUpload.blockCard.tooltip": "Upload Files",
|
||||||
|
"blocks.inputs.number.settings.step.label": "Step:",
|
||||||
|
"blocks.inputs.payment.collect.label": "Coletar",
|
||||||
|
"blocks.inputs.payment.placeholder.label": "Configure...",
|
||||||
|
"blocks.inputs.payment.settings.account.label": "Account:",
|
||||||
|
"blocks.inputs.payment.settings.accountText.label": "{provider} account",
|
||||||
|
"blocks.inputs.payment.settings.additionalInformation.description.placeholder.label": "A digital product",
|
||||||
|
"blocks.inputs.payment.settings.additionalInformation.email.label": "Email:",
|
||||||
|
"blocks.inputs.payment.settings.additionalInformation.label": "Additional information",
|
||||||
|
"blocks.inputs.payment.settings.additionalInformation.name.label": "Name:",
|
||||||
|
"blocks.inputs.payment.settings.additionalInformation.phone.label": "Phone number:",
|
||||||
|
"blocks.inputs.payment.settings.address.city.label": "City:",
|
||||||
|
"blocks.inputs.payment.settings.address.country.label": "Country:",
|
||||||
|
"blocks.inputs.payment.settings.address.label": "Address",
|
||||||
|
"blocks.inputs.payment.settings.address.line.label": "Line {line}:",
|
||||||
|
"blocks.inputs.payment.settings.address.postalCode.label": "Postal code:",
|
||||||
|
"blocks.inputs.payment.settings.address.state.label": "State:",
|
||||||
|
"blocks.inputs.payment.settings.credentials.connectNew.label": "Connect new",
|
||||||
|
"blocks.inputs.payment.settings.credentials.removeCredentials.label": "Remove credentials",
|
||||||
|
"blocks.inputs.payment.settings.currency.label": "Currency:",
|
||||||
|
"blocks.inputs.payment.settings.priceAmount.label": "Price amount:",
|
||||||
|
"blocks.inputs.payment.settings.provider.label": "Provider:",
|
||||||
|
"blocks.inputs.payment.settings.stripeConfig.accountName.label": "Account name:",
|
||||||
|
"blocks.inputs.payment.settings.stripeConfig.findKeys.here.label": "here",
|
||||||
|
"blocks.inputs.payment.settings.stripeConfig.findKeys.label": "You can find your keys",
|
||||||
|
"blocks.inputs.payment.settings.stripeConfig.liveKeys.label": "Live keys:",
|
||||||
|
"blocks.inputs.payment.settings.stripeConfig.testKeys.infoText.label": "Will be used when previewing the bot.",
|
||||||
|
"blocks.inputs.payment.settings.stripeConfig.testKeys.label": "Test keys:",
|
||||||
|
"blocks.inputs.payment.settings.stripeConfig.title.label": "Connect Stripe account",
|
||||||
|
"blocks.inputs.payment.settings.successMessage.label": "Success message:",
|
||||||
|
"blocks.inputs.phone.settings.defaultCountry.label": "Default country:",
|
||||||
|
"blocks.inputs.phone.settings.international.placeholder.label": "International",
|
||||||
|
"blocks.inputs.picture.itemSettings.image.change.label": "Change image",
|
||||||
|
"blocks.inputs.picture.itemSettings.image.label": "Image:",
|
||||||
|
"blocks.inputs.picture.itemSettings.image.pick.label": "Pick an image",
|
||||||
|
"blocks.inputs.picture.itemSettings.title.label": "Title:",
|
||||||
|
"blocks.inputs.picture.settings.dynamicItems.descriptions.label": "Descriptions:",
|
||||||
|
"blocks.inputs.picture.settings.dynamicItems.images.label": "Images:",
|
||||||
|
"blocks.inputs.picture.settings.dynamicItems.label": "Dynamic items?",
|
||||||
|
"blocks.inputs.picture.settings.dynamicItems.titles.label": "Titles:",
|
||||||
|
"blocks.inputs.picture.settings.dynamicVariables.display.label": "Display",
|
||||||
|
"blocks.inputs.picture.settings.dynamicVariables.pictures.label": "pictures",
|
||||||
|
"blocks.inputs.rating.from.label": "Rate from",
|
||||||
|
"blocks.inputs.rating.settings.customIcon.label": "Custom icon?",
|
||||||
|
"blocks.inputs.rating.settings.extremelyLikely.placeholder.label": "Extremely likely",
|
||||||
|
"blocks.inputs.rating.settings.iconSVG.label": "Icon SVG:",
|
||||||
|
"blocks.inputs.rating.settings.maximum.label": "Maximum:",
|
||||||
|
"blocks.inputs.rating.settings.notLikely.placeholder.label": "Not likely at all",
|
||||||
|
"blocks.inputs.rating.settings.oneClickSubmit.infoText.label": "If enabled, the answer will be submitted as soon as the user clicks on a rating instead of showing the \"Send\" button.",
|
||||||
|
"blocks.inputs.rating.settings.oneClickSubmit.label": "One click submit",
|
||||||
|
"blocks.inputs.rating.settings.rateLabel.label": "{rate} label",
|
||||||
|
"blocks.inputs.rating.settings.type.label": "Type:",
|
||||||
|
"blocks.inputs.rating.to.label": "to",
|
||||||
|
"blocks.inputs.settings.button.label": "Button label:",
|
||||||
|
"blocks.inputs.settings.buttonText.label": "Send",
|
||||||
|
"blocks.inputs.settings.description.label": "Description:",
|
||||||
|
"blocks.inputs.settings.displayCondition.label": "Display condition",
|
||||||
|
"blocks.inputs.settings.input.filterOptions.label": "Filter the options...",
|
||||||
|
"blocks.inputs.settings.input.placeholder.label": "Input placeholder:",
|
||||||
|
"blocks.inputs.settings.isSearchable.label": "Is searchable?",
|
||||||
|
"blocks.inputs.settings.max.label": "Max:",
|
||||||
|
"blocks.inputs.settings.min.label": "Min:",
|
||||||
|
"blocks.inputs.settings.multipleChoice.label": "Multiple choice?",
|
||||||
|
"blocks.inputs.settings.placeholder.label": "Placeholder:",
|
||||||
|
"blocks.inputs.settings.retryMessage.label": "Retry message:",
|
||||||
|
"blocks.inputs.settings.saveAnswer.label": "Save the answer in a variable:",
|
||||||
|
"blocks.inputs.settings.submitButton.label": "Submit button label:",
|
||||||
|
"blocks.inputs.text.settings.longText.label": "Long text?",
|
||||||
"blocks.integrations.googleAnalytics.blockCard.tooltip": "Google Analytics",
|
"blocks.integrations.googleAnalytics.blockCard.tooltip": "Google Analytics",
|
||||||
"blocks.integrations.googleSheets.blockCard.tooltip": "Google Sheets",
|
"blocks.integrations.googleSheets.blockCard.tooltip": "Google Sheets",
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
@@ -124,13 +221,16 @@
|
|||||||
"colorPicker.colorValue.ariaLabel": "Color value",
|
"colorPicker.colorValue.ariaLabel": "Color value",
|
||||||
"colorPicker.pickColor.ariaLabel": "Pick a color",
|
"colorPicker.pickColor.ariaLabel": "Pick a color",
|
||||||
"confirmModal.defaultTitle": "Are you sure?",
|
"confirmModal.defaultTitle": "Are you sure?",
|
||||||
|
"connect": "Connect",
|
||||||
"copied": "Copied",
|
"copied": "Copied",
|
||||||
"copy": "Copy",
|
"copy": "Copy",
|
||||||
|
"create": "Create",
|
||||||
"dashboard.header.settingsButton.label": "Settings & Members",
|
"dashboard.header.settingsButton.label": "Settings & Members",
|
||||||
"dashboard.redirectionMessage": "You are being redirected...",
|
"dashboard.redirectionMessage": "You are being redirected...",
|
||||||
"dashboard.title": "My typebots",
|
"dashboard.title": "My typebots",
|
||||||
"delete": "Delete",
|
"delete": "Delete",
|
||||||
"downgrade": "Downgrade",
|
"downgrade": "Downgrade",
|
||||||
|
"duplicate": "Duplicate",
|
||||||
"editor.blockCard.logicBlock.tooltip.code.label": "Execute Javascript code",
|
"editor.blockCard.logicBlock.tooltip.code.label": "Execute Javascript code",
|
||||||
"editor.blockCard.logicBlock.tooltip.jump.label": "Fast forward the flow to another group",
|
"editor.blockCard.logicBlock.tooltip.jump.label": "Fast forward the flow to another group",
|
||||||
"editor.blockCard.logicBlock.tooltip.typebotLink.label": "Link and jump to another typebot",
|
"editor.blockCard.logicBlock.tooltip.typebotLink.label": "Link and jump to another typebot",
|
||||||
@@ -238,6 +338,7 @@
|
|||||||
"folders.typebotButton.live": "Live",
|
"folders.typebotButton.live": "Live",
|
||||||
"folders.typebotButton.showMoreOptions": "Show more options",
|
"folders.typebotButton.showMoreOptions": "Show more options",
|
||||||
"folders.typebotButton.unpublish": "Unpublish",
|
"folders.typebotButton.unpublish": "Unpublish",
|
||||||
|
"help": "Help",
|
||||||
"pending": "Pending",
|
"pending": "Pending",
|
||||||
"preview.restartButton.label": "Restart",
|
"preview.restartButton.label": "Restart",
|
||||||
"publish.error.label": "Error while publishing typebot",
|
"publish.error.label": "Error while publishing typebot",
|
||||||
@@ -258,6 +359,7 @@
|
|||||||
"remove": "Remove",
|
"remove": "Remove",
|
||||||
"rename": "Rename",
|
"rename": "Rename",
|
||||||
"save": "Save",
|
"save": "Save",
|
||||||
|
"select": "Select",
|
||||||
"share.button.label": "Share",
|
"share.button.label": "Share",
|
||||||
"share.button.popover.ariaLabel": "Open share popover",
|
"share.button.popover.ariaLabel": "Open share popover",
|
||||||
"share.button.popover.collaboratorsFetch.error.label": "Couldn't fetch collaborators",
|
"share.button.popover.collaboratorsFetch.error.label": "Couldn't fetch collaborators",
|
||||||
@@ -355,6 +457,11 @@
|
|||||||
"upgrade": "Upgrade",
|
"upgrade": "Upgrade",
|
||||||
"variables.button.searchInput.placeholder": "Search for a variable",
|
"variables.button.searchInput.placeholder": "Search for a variable",
|
||||||
"variables.button.tooltip": "Insert a variable",
|
"variables.button.tooltip": "Insert a variable",
|
||||||
|
"variables.remove": "Remove variable",
|
||||||
|
"variables.rename": "Rename variable",
|
||||||
|
"variables.search": "Search for a variable",
|
||||||
|
"variables.select": "Select a variable",
|
||||||
|
"variables.set": "Set",
|
||||||
"video.aspectRatioInput.label": "Aspect ratio",
|
"video.aspectRatioInput.label": "Aspect ratio",
|
||||||
"video.aspectRatioInput.moreInfoTooltip": "Example: \"16/9\" or \"9/16\"",
|
"video.aspectRatioInput.moreInfoTooltip": "Example: \"16/9\" or \"9/16\"",
|
||||||
"video.maxWidthInput.label": "Max width",
|
"video.maxWidthInput.label": "Max width",
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
"account.preferences.graphNavigation.trackpad.label": "Trackpad",
|
"account.preferences.graphNavigation.trackpad.label": "Trackpad",
|
||||||
"account.preferences.language.heading": "Idioma",
|
"account.preferences.language.heading": "Idioma",
|
||||||
"account.preferences.language.tooltip": "As traduções ainda não estão completas. É um trabalho em andamento. \uD83E\uDD13",
|
"account.preferences.language.tooltip": "As traduções ainda não estão completas. É um trabalho em andamento. \uD83E\uDD13",
|
||||||
|
"add": "Adicionar",
|
||||||
"analytics.completionRateLabel": "Taxa de conclusão",
|
"analytics.completionRateLabel": "Taxa de conclusão",
|
||||||
"analytics.notAvailableLabel": "Não disponível",
|
"analytics.notAvailableLabel": "Não disponível",
|
||||||
"analytics.startsLabel": "Inícios",
|
"analytics.startsLabel": "Inícios",
|
||||||
@@ -112,7 +113,103 @@
|
|||||||
"billing.usage.heading": "Uso",
|
"billing.usage.heading": "Uso",
|
||||||
"billing.usage.unlimited": "Ilimitado",
|
"billing.usage.unlimited": "Ilimitado",
|
||||||
"blocks.bubbles.embed.blockCard.tooltip": "Incorporar pdf, iframe, website...",
|
"blocks.bubbles.embed.blockCard.tooltip": "Incorporar pdf, iframe, website...",
|
||||||
|
"blocks.inputs.button.addItem.ariaLabel": "Adicionar item",
|
||||||
|
"blocks.inputs.button.buttonSettings.addComparisonButton.label": "Adicionar comparação",
|
||||||
|
"blocks.inputs.button.buttonSettings.displayCondition.infoText.label": "Apenas exiba esse item se a condição for cumprida.",
|
||||||
|
"blocks.inputs.button.buttonSettings.displayCondition.selectOperator.label": "Selecione um operador",
|
||||||
|
"blocks.inputs.button.clickToEdit.label": "Clique para editar",
|
||||||
|
"blocks.inputs.button.conditionContent.if.label": "SE",
|
||||||
|
"blocks.inputs.button.default.label": "Padrão",
|
||||||
|
"blocks.inputs.button.else.label": "Senão",
|
||||||
|
"blocks.inputs.button.openSettings.ariaLabel": "Abrir configurações",
|
||||||
|
"blocks.inputs.button.settings.dynamicData.infoText.label": "Se definido, os botões serão exibidos dinamicamente com base no que a variável contém.",
|
||||||
|
"blocks.inputs.button.settings.dynamicData.label": "Dados dinâmicos:",
|
||||||
|
"blocks.inputs.button.variables.buttons.label": "botões",
|
||||||
|
"blocks.inputs.button.variables.display.label": "Exibir",
|
||||||
|
"blocks.inputs.date.placeholder.label": "Escolha uma data...",
|
||||||
|
"blocks.inputs.date.settings.format.example.label": "Ex:",
|
||||||
|
"blocks.inputs.date.settings.format.label": "Formatar:",
|
||||||
|
"blocks.inputs.date.settings.from.label": "Legenda de:",
|
||||||
|
"blocks.inputs.date.settings.isRange.label": "Intervalo?",
|
||||||
|
"blocks.inputs.date.settings.to.label": "Legenda até:",
|
||||||
|
"blocks.inputs.date.settings.toInputValue.label": "Até:",
|
||||||
|
"blocks.inputs.date.settings.withTime.label": "Com tempo?",
|
||||||
|
"blocks.inputs.file.collectMultiple.label": "Coletar arquivos",
|
||||||
|
"blocks.inputs.file.collectSingle.label": "Coletar arquivo",
|
||||||
|
"blocks.inputs.file.settings.allowMultiple.label": "Permitir múltiplos arquivos?",
|
||||||
|
"blocks.inputs.file.settings.clear.label": "Legenda do botão de limpar:",
|
||||||
|
"blocks.inputs.file.settings.required.label": "Obrigatório?",
|
||||||
|
"blocks.inputs.file.settings.saveMultipleUpload.label": "Salve as URLs carregadas numa variável:",
|
||||||
|
"blocks.inputs.file.settings.saveSingleUpload.label": "Salve a URL carregada numa variável:",
|
||||||
|
"blocks.inputs.file.settings.skip.label": "Legenda do botão de pular:",
|
||||||
"blocks.inputs.fileUpload.blockCard.tooltip": "Anexar arquivos",
|
"blocks.inputs.fileUpload.blockCard.tooltip": "Anexar arquivos",
|
||||||
|
"blocks.inputs.number.settings.step.label": "Intervalo",
|
||||||
|
"blocks.inputs.payment.collect.label": "Coletar",
|
||||||
|
"blocks.inputs.payment.placeholder.label": "Configure...",
|
||||||
|
"blocks.inputs.payment.settings.account.label": "Conta:",
|
||||||
|
"blocks.inputs.payment.settings.accountText.label": "conta {provider}",
|
||||||
|
"blocks.inputs.payment.settings.additionalInformation.description.placeholder.label": "Um produto digital",
|
||||||
|
"blocks.inputs.payment.settings.additionalInformation.email.label": "Email:",
|
||||||
|
"blocks.inputs.payment.settings.additionalInformation.label": "Informação adicional",
|
||||||
|
"blocks.inputs.payment.settings.additionalInformation.name.label": "Nome:",
|
||||||
|
"blocks.inputs.payment.settings.additionalInformation.phone.label": "Número de telefone:",
|
||||||
|
"blocks.inputs.payment.settings.address.city.label": "Cidade:",
|
||||||
|
"blocks.inputs.payment.settings.address.country.label": "País:",
|
||||||
|
"blocks.inputs.payment.settings.address.label": "Endereço",
|
||||||
|
"blocks.inputs.payment.settings.address.line.label": "Linha {line}:",
|
||||||
|
"blocks.inputs.payment.settings.address.postalCode.label": "Código postal:",
|
||||||
|
"blocks.inputs.payment.settings.address.state.label": "Estado:",
|
||||||
|
"blocks.inputs.payment.settings.credentials.connectNew.label": "Nova conexão",
|
||||||
|
"blocks.inputs.payment.settings.credentials.removeCredentials.label": "Remover credenciais",
|
||||||
|
"blocks.inputs.payment.settings.currency.label": "Moeda:",
|
||||||
|
"blocks.inputs.payment.settings.priceAmount.label": "Valor do preço:",
|
||||||
|
"blocks.inputs.payment.settings.provider.label": "Provedor:",
|
||||||
|
"blocks.inputs.payment.settings.stripeConfig.accountName.label": "Nome da conta:",
|
||||||
|
"blocks.inputs.payment.settings.stripeConfig.findKeys.here.label": "aqui",
|
||||||
|
"blocks.inputs.payment.settings.stripeConfig.findKeys.label": "Você pode encontrar suas chaves",
|
||||||
|
"blocks.inputs.payment.settings.stripeConfig.liveKeys.label": "Chaves de produção:",
|
||||||
|
"blocks.inputs.payment.settings.stripeConfig.testKeys.infoText.label": "Será usada durante a visualização do bot.",
|
||||||
|
"blocks.inputs.payment.settings.stripeConfig.testKeys.label": "Chaves teste:",
|
||||||
|
"blocks.inputs.payment.settings.stripeConfig.title.label": "Conectar conta Stripe",
|
||||||
|
"blocks.inputs.payment.settings.successMessage.label": "Mensagem de sucesso:",
|
||||||
|
"blocks.inputs.phone.settings.defaultCountry.label": "País padrão:",
|
||||||
|
"blocks.inputs.phone.settings.international.placeholder.label": "Internacional",
|
||||||
|
"blocks.inputs.picture.itemSettings.image.change.label": "Alterar imagem",
|
||||||
|
"blocks.inputs.picture.itemSettings.image.label": "Imagem",
|
||||||
|
"blocks.inputs.picture.itemSettings.image.pick.label": "Escolha uma imagem",
|
||||||
|
"blocks.inputs.picture.itemSettings.title.label": "Título:",
|
||||||
|
"blocks.inputs.picture.settings.dynamicItems.descriptions.label": "Descrições:",
|
||||||
|
"blocks.inputs.picture.settings.dynamicItems.images.label": "Imagens:",
|
||||||
|
"blocks.inputs.picture.settings.dynamicItems.label": "Itens dinâmicos?",
|
||||||
|
"blocks.inputs.picture.settings.dynamicItems.titles.label": "Títulos:",
|
||||||
|
"blocks.inputs.picture.settings.dynamicVariables.display.label": "Exibir",
|
||||||
|
"blocks.inputs.picture.settings.dynamicVariables.pictures.label": "imagens",
|
||||||
|
"blocks.inputs.rating.from.label": "Avalie de",
|
||||||
|
"blocks.inputs.rating.settings.customIcon.label": "Customizar ícone?",
|
||||||
|
"blocks.inputs.rating.settings.extremelyLikely.placeholder.label": "Extremamente provável",
|
||||||
|
"blocks.inputs.rating.settings.iconSVG.label": "Ícone SVG:",
|
||||||
|
"blocks.inputs.rating.settings.maximum.label": "Máximo:",
|
||||||
|
"blocks.inputs.rating.settings.notLikely.placeholder.label": "Nada provável",
|
||||||
|
"blocks.inputs.rating.settings.oneClickSubmit.infoText.label": "Se habilitado, a resposta será enviada no momento em que o usuário clicar em uma avaliação ao invés de mostrar o botão de envio",
|
||||||
|
"blocks.inputs.rating.settings.oneClickSubmit.label": "Enviar em um clique",
|
||||||
|
"blocks.inputs.rating.settings.rateLabel.label": "Legenda {rate}",
|
||||||
|
"blocks.inputs.rating.settings.type.label": "Tipo:",
|
||||||
|
"blocks.inputs.rating.to.label": "a",
|
||||||
|
"blocks.inputs.settings.button.label": "Legenda do botão:",
|
||||||
|
"blocks.inputs.settings.buttonText.label": "Enviar",
|
||||||
|
"blocks.inputs.settings.description.label": "Descrição:",
|
||||||
|
"blocks.inputs.settings.displayCondition.label": "Condição de exibição",
|
||||||
|
"blocks.inputs.settings.input.filterOptions.label": "Filtre as opções...",
|
||||||
|
"blocks.inputs.settings.input.placeholder.label": "Placeholder do input:",
|
||||||
|
"blocks.inputs.settings.isSearchable.label": "É pesquisável?",
|
||||||
|
"blocks.inputs.settings.max.label": "Máx:",
|
||||||
|
"blocks.inputs.settings.min.label": "Mín:",
|
||||||
|
"blocks.inputs.settings.multipleChoice.label": "Múltipla escolha?",
|
||||||
|
"blocks.inputs.settings.placeholder.label": "Placeholder:",
|
||||||
|
"blocks.inputs.settings.retryMessage.label": "Mensagem de nova tentativa:",
|
||||||
|
"blocks.inputs.settings.saveAnswer.label": "Salve a resposta em uma variável:",
|
||||||
|
"blocks.inputs.settings.submitButton.label": "Legenda do botão de envio:",
|
||||||
|
"blocks.inputs.text.settings.longText.label": "Texto longo?",
|
||||||
"blocks.integrations.googleAnalytics.blockCard.tooltip": "Google Analytics",
|
"blocks.integrations.googleAnalytics.blockCard.tooltip": "Google Analytics",
|
||||||
"blocks.integrations.googleSheets.blockCard.tooltip": "Google Sheets",
|
"blocks.integrations.googleSheets.blockCard.tooltip": "Google Sheets",
|
||||||
"cancel": "Cancelar",
|
"cancel": "Cancelar",
|
||||||
@@ -124,13 +221,16 @@
|
|||||||
"colorPicker.colorValue.ariaLabel": "Valor da cor",
|
"colorPicker.colorValue.ariaLabel": "Valor da cor",
|
||||||
"colorPicker.pickColor.ariaLabel": "Escolha uma cor",
|
"colorPicker.pickColor.ariaLabel": "Escolha uma cor",
|
||||||
"confirmModal.defaultTitle": "Tem certeza?",
|
"confirmModal.defaultTitle": "Tem certeza?",
|
||||||
|
"connect": "Conectar",
|
||||||
"copied": "Copiado",
|
"copied": "Copiado",
|
||||||
"copy": "Copiar",
|
"copy": "Copiar",
|
||||||
|
"create": "Criar",
|
||||||
"dashboard.header.settingsButton.label": "Configurações & Membros",
|
"dashboard.header.settingsButton.label": "Configurações & Membros",
|
||||||
"dashboard.redirectionMessage": "Você está sendo redirecionado...",
|
"dashboard.redirectionMessage": "Você está sendo redirecionado...",
|
||||||
"dashboard.title": "Meus typebots",
|
"dashboard.title": "Meus typebots",
|
||||||
"delete": "Apagar",
|
"delete": "Apagar",
|
||||||
"downgrade": "Downgrade",
|
"downgrade": "Downgrade",
|
||||||
|
"duplicate": "Duplicar",
|
||||||
"editor.blockCard.logicBlock.tooltip.code.label": "Executar código Javascript",
|
"editor.blockCard.logicBlock.tooltip.code.label": "Executar código Javascript",
|
||||||
"editor.blockCard.logicBlock.tooltip.jump.label": "Encaminhar fluxo para outro grupo",
|
"editor.blockCard.logicBlock.tooltip.jump.label": "Encaminhar fluxo para outro grupo",
|
||||||
"editor.blockCard.logicBlock.tooltip.typebotLink.label": "Link e salte para outro typebot",
|
"editor.blockCard.logicBlock.tooltip.typebotLink.label": "Link e salte para outro typebot",
|
||||||
@@ -238,6 +338,7 @@
|
|||||||
"folders.typebotButton.live": "Live",
|
"folders.typebotButton.live": "Live",
|
||||||
"folders.typebotButton.showMoreOptions": "Mostrar mais opções",
|
"folders.typebotButton.showMoreOptions": "Mostrar mais opções",
|
||||||
"folders.typebotButton.unpublish": "Despublicar",
|
"folders.typebotButton.unpublish": "Despublicar",
|
||||||
|
"help": "Ajuda",
|
||||||
"pending": "Pendente",
|
"pending": "Pendente",
|
||||||
"preview.restartButton.label": "Reiniciar",
|
"preview.restartButton.label": "Reiniciar",
|
||||||
"publish.error.label": "Erro durante a publicação do typebot",
|
"publish.error.label": "Erro durante a publicação do typebot",
|
||||||
@@ -257,6 +358,7 @@
|
|||||||
"remove": "Remover",
|
"remove": "Remover",
|
||||||
"rename": "Renomear",
|
"rename": "Renomear",
|
||||||
"save": "Salvar",
|
"save": "Salvar",
|
||||||
|
"select": "Selecionar",
|
||||||
"share.button.label": "Compartilhar",
|
"share.button.label": "Compartilhar",
|
||||||
"share.button.popover.ariaLabel": "Abrir popover de compartilhamento",
|
"share.button.popover.ariaLabel": "Abrir popover de compartilhamento",
|
||||||
"share.button.popover.collaboratorsFetch.error.label": "Falha ao buscar os colaboradores",
|
"share.button.popover.collaboratorsFetch.error.label": "Falha ao buscar os colaboradores",
|
||||||
@@ -348,6 +450,11 @@
|
|||||||
"upgrade": "Upgrade",
|
"upgrade": "Upgrade",
|
||||||
"variables.button.searchInput.placeholder": "Procure por uma variável",
|
"variables.button.searchInput.placeholder": "Procure por uma variável",
|
||||||
"variables.button.tooltip": "Insira uma variável",
|
"variables.button.tooltip": "Insira uma variável",
|
||||||
|
"variables.remove": "Remova a variável",
|
||||||
|
"variables.rename": "Renomeie a variável",
|
||||||
|
"variables.search": "Pesquise uma variável",
|
||||||
|
"variables.select": "Selecione uma variável",
|
||||||
|
"variables.set": "Definir",
|
||||||
"video.aspectRatioInput.label": "Proporção",
|
"video.aspectRatioInput.label": "Proporção",
|
||||||
"video.aspectRatioInput.moreInfoTooltip": "Exemplo: \"16/9\" ou \"9/16\"",
|
"video.aspectRatioInput.moreInfoTooltip": "Exemplo: \"16/9\" ou \"9/16\"",
|
||||||
"video.maxWidthInput.label": "Largura máxima",
|
"video.maxWidthInput.label": "Largura máxima",
|
||||||
|
|||||||
Reference in New Issue
Block a user