@ -99,7 +99,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@chakra-ui/styled-system": "2.9.1",
|
||||
"@playwright/test": "1.41.2",
|
||||
"@playwright/test": "1.43.1",
|
||||
"@typebot.io/billing": "workspace:*",
|
||||
"@typebot.io/forge": "workspace:*",
|
||||
"@typebot.io/forge-repository": "workspace:*",
|
||||
@ -123,12 +123,13 @@
|
||||
"@types/qs": "6.9.7",
|
||||
"@types/react": "18.2.15",
|
||||
"@types/tinycolor2": "1.4.3",
|
||||
"dotenv-cli": "7.2.1",
|
||||
"dotenv-cli": "7.4.1",
|
||||
"eslint": "8.44.0",
|
||||
"eslint-config-custom": "workspace:*",
|
||||
"next-runtime-env": "1.6.2",
|
||||
"superjson": "1.12.4",
|
||||
"typescript": "5.4.5",
|
||||
"zod": "3.22.4"
|
||||
"zod": "3.22.4",
|
||||
"dotenv": "16.4.5"
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,8 @@
|
||||
import { defineConfig, devices } from '@playwright/test'
|
||||
import { resolve } from 'path'
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
require('dotenv').config({ path: resolve(__dirname, '../../.env') })
|
||||
|
||||
export default defineConfig({
|
||||
timeout: process.env.CI ? 50 * 1000 : 40 * 1000,
|
||||
|
@ -6,8 +6,9 @@ import {
|
||||
Switch,
|
||||
SwitchProps,
|
||||
} from '@chakra-ui/react'
|
||||
import React, { useState } from 'react'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { MoreInfoTooltip } from '../MoreInfoTooltip'
|
||||
import { isDefined } from '@typebot.io/lib'
|
||||
|
||||
export type SwitchWithLabelProps = {
|
||||
label: string
|
||||
@ -32,6 +33,11 @@ export const SwitchWithLabel = ({
|
||||
if (onCheckChange) onCheckChange(!isChecked)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (isChecked === undefined && isDefined(initialValue))
|
||||
setIsChecked(initialValue)
|
||||
}, [initialValue, isChecked])
|
||||
|
||||
return (
|
||||
<FormControl as={HStack} justifyContent={justifyContent}>
|
||||
<FormLabel mb="0">
|
||||
|
@ -123,7 +123,7 @@ export const VariableSearchInput = ({
|
||||
if (!inputValue || inputValue === '') return
|
||||
const id = 'v' + createId()
|
||||
onSelectVariable({ id, name: inputValue })
|
||||
createVariable({ id, name: inputValue })
|
||||
createVariable({ id, name: inputValue, isSessionVariable: true })
|
||||
inputRef.current?.blur()
|
||||
onClose()
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ test.describe('Date input block', () => {
|
||||
'date'
|
||||
)
|
||||
await page.locator('[data-testid="from-date"]').fill('2021-01-01')
|
||||
await page.getByRole('button', { name: 'Send' }).click()
|
||||
await page.locator('form').getByRole('button').click()
|
||||
await expect(page.locator('text="01/01/2021"')).toBeVisible()
|
||||
|
||||
await page.click(`text=Pick a date`)
|
||||
|
@ -32,7 +32,7 @@ test('options should work', async ({ page }) => {
|
||||
|
||||
await page.click('text=Test')
|
||||
await expect(page.locator(`text=Send`)).toBeHidden()
|
||||
await page.getByRole('button', { name: '8' }).click()
|
||||
await page.getByRole('checkbox', { name: '8' }).click()
|
||||
await page.locator(`text=Send`).click()
|
||||
await expect(page.getByTestId('guest-bubble')).toHaveText('8')
|
||||
await page.click('text=Rate from 0 to 10')
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { Alert, AlertIcon, FormLabel, Stack, Tag, Text } from '@chakra-ui/react'
|
||||
import { CodeEditor } from '@/components/inputs/CodeEditor'
|
||||
import { SetVariableBlock, Variable } from '@typebot.io/schemas'
|
||||
import React from 'react'
|
||||
import { VariableSearchInput } from '@/components/inputs/VariableSearchInput'
|
||||
import { SwitchWithLabel } from '@/components/inputs/SwitchWithLabel'
|
||||
import { Select } from '@/components/inputs/Select'
|
||||
@ -13,6 +12,7 @@ import {
|
||||
} from '@typebot.io/schemas/features/blocks/logic/setVariable/constants'
|
||||
import { TextInput } from '@/components/inputs'
|
||||
import { isDefined } from '@typebot.io/lib'
|
||||
import { useTypebot } from '@/features/editor/providers/TypebotProvider'
|
||||
|
||||
type Props = {
|
||||
options: SetVariableBlock['options']
|
||||
@ -24,7 +24,12 @@ const setVarTypes = valueTypes.filter(
|
||||
)
|
||||
|
||||
export const SetVariableSettings = ({ options, onOptionsChange }: Props) => {
|
||||
const updateVariableId = (variable?: Variable) =>
|
||||
const { typebot, updateVariable } = useTypebot()
|
||||
const selectedVariable = typebot?.variables.find(
|
||||
(variable) => variable.id === options?.variableId
|
||||
)
|
||||
|
||||
const updateVariableId = (variable?: Pick<Variable, 'id'>) =>
|
||||
onOptionsChange({
|
||||
...options,
|
||||
variableId: variable?.id,
|
||||
@ -36,6 +41,13 @@ export const SetVariableSettings = ({ options, onOptionsChange }: Props) => {
|
||||
type: type as NonNullable<SetVariableBlock['options']>['type'],
|
||||
})
|
||||
|
||||
const updateIsSessionVariable = (isSavingInResults: boolean) => {
|
||||
if (!selectedVariable?.id) return
|
||||
updateVariable(selectedVariable.id, {
|
||||
isSessionVariable: !isSavingInResults,
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack spacing={4}>
|
||||
<Stack>
|
||||
@ -49,22 +61,34 @@ export const SetVariableSettings = ({ options, onOptionsChange }: Props) => {
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
<Stack>
|
||||
<Text mb="0" fontWeight="medium">
|
||||
Value:
|
||||
</Text>
|
||||
<Select
|
||||
selectedItem={options?.type ?? defaultSetVariableOptions.type}
|
||||
items={setVarTypes.map((type) => ({
|
||||
label: type,
|
||||
value: type,
|
||||
icon:
|
||||
type === 'Contact name' || type === 'Phone number' ? (
|
||||
<WhatsAppLogo />
|
||||
) : undefined,
|
||||
}))}
|
||||
onSelect={updateValueType}
|
||||
/>
|
||||
<Stack spacing="4">
|
||||
<Stack>
|
||||
<Text mb="0" fontWeight="medium">
|
||||
Value:
|
||||
</Text>
|
||||
<Select
|
||||
selectedItem={options?.type ?? defaultSetVariableOptions.type}
|
||||
items={setVarTypes.map((type) => ({
|
||||
label: type,
|
||||
value: type,
|
||||
icon:
|
||||
type === 'Contact name' || type === 'Phone number' ? (
|
||||
<WhatsAppLogo />
|
||||
) : undefined,
|
||||
}))}
|
||||
onSelect={updateValueType}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
{selectedVariable && (
|
||||
<SwitchWithLabel
|
||||
key={selectedVariable.id}
|
||||
label="Save in results?"
|
||||
moreInfoContent="By default, the variable is saved only for the user chat session. Check this option if you want to also store the variable in the typebot Results table."
|
||||
initialValue={!selectedVariable.isSessionVariable}
|
||||
onCheckChange={updateIsSessionVariable}
|
||||
/>
|
||||
)}
|
||||
<SetVariableValue options={options} onOptionsChange={onOptionsChange} />
|
||||
</Stack>
|
||||
</Stack>
|
||||
@ -91,7 +115,7 @@ const SetVariableValue = ({
|
||||
isExecutedOnClient,
|
||||
})
|
||||
|
||||
const updateItemVariableId = (variable?: Variable) => {
|
||||
const updateItemVariableId = (variable?: Pick<Variable, 'id'>) => {
|
||||
if (!options || options.type !== 'Map item with same index') return
|
||||
onOptionsChange({
|
||||
...options,
|
||||
@ -102,7 +126,7 @@ const SetVariableValue = ({
|
||||
})
|
||||
}
|
||||
|
||||
const updateBaseListVariableId = (variable?: Variable) => {
|
||||
const updateBaseListVariableId = (variable?: Pick<Variable, 'id'>) => {
|
||||
if (!options || options.type !== 'Map item with same index') return
|
||||
onOptionsChange({
|
||||
...options,
|
||||
@ -113,7 +137,7 @@ const SetVariableValue = ({
|
||||
})
|
||||
}
|
||||
|
||||
const updateTargetListVariableId = (variable?: Variable) => {
|
||||
const updateTargetListVariableId = (variable?: Pick<Variable, 'id'>) => {
|
||||
if (!options || options.type !== 'Map item with same index') return
|
||||
onOptionsChange({
|
||||
...options,
|
||||
|
@ -28,11 +28,16 @@ test.describe('Set variable block', () => {
|
||||
.fill('1000 * {{Num}}')
|
||||
|
||||
await page.click('text=Click to edit...', { force: true })
|
||||
await expect(page.getByText('Save in results?')).toBeHidden()
|
||||
await page.fill(
|
||||
'input[placeholder="Select a variable"] >> nth=-1',
|
||||
'Custom var'
|
||||
)
|
||||
await page.getByRole('menuitem', { name: 'Create Custom var' }).click()
|
||||
await expect(page.getByText('Save in results?')).toBeVisible()
|
||||
await expect(
|
||||
page.getByRole('group').nth(1).locator('.chakra-switch')
|
||||
).not.toHaveAttribute('data-checked')
|
||||
await page
|
||||
.getByTestId('code-editor')
|
||||
.getByRole('textbox')
|
||||
|
@ -33,6 +33,7 @@ test('table features should work', async ({ page }) => {
|
||||
await expect(page.locator('text=Additional information')).toBeVisible()
|
||||
await expect(page.locator('text=utm_source')).toBeVisible()
|
||||
await expect(page.locator('text=utm_userid')).toBeVisible()
|
||||
await expect(page.locator('text=utm_session')).toBeHidden()
|
||||
})
|
||||
|
||||
await test.step('Resize columns', async () => {
|
||||
|
@ -177,7 +177,7 @@ test("can't add new members when limit is reached", async ({ page }) => {
|
||||
await page.click('button >> text="Invite"')
|
||||
await expect(
|
||||
page.locator(
|
||||
'text="Upgrade your plan to work with more team members, and unlock awesome power features 🚀"'
|
||||
'text="Upgrade your plan to work with more team members, and unlock awesome power features"'
|
||||
)
|
||||
).toBeVisible()
|
||||
await expect(page.locator('button >> text="Invite"')).toBeDisabled()
|
||||
|
@ -258,8 +258,21 @@
|
||||
}
|
||||
],
|
||||
"variables": [
|
||||
{ "id": "giiLFGw5xXBCHzvp1qAbdX", "name": "Name" },
|
||||
{ "id": "3VFChNVSCXQ2rXv4DrJ8Ah", "name": "Email" },
|
||||
{
|
||||
"id": "giiLFGw5xXBCHzvp1qAbdX",
|
||||
"name": "Name",
|
||||
"isSessionVariable": true
|
||||
},
|
||||
{
|
||||
"id": "3VFChNVSCXQ2rXv4DrJ8Ah",
|
||||
"name": "Email",
|
||||
"isSessionVariable": true
|
||||
},
|
||||
{
|
||||
"id": "8Q8t9YCc3ieAEXSYkmnCxH",
|
||||
"name": "utm_session",
|
||||
"isSessionVariable": true
|
||||
},
|
||||
{ "id": "8Q8t9YCc3ieAEXSYkmnCxH", "name": "utm_source" },
|
||||
{ "id": "ds54chWAyWC4zjkdWAm3Vc", "name": "utm_userid" }
|
||||
],
|
||||
|
Reference in New Issue
Block a user