Introducing The Forge (#1072)

The Forge allows anyone to easily create their own Typebot Block.

Closes #380
This commit is contained in:
Baptiste Arnaud
2023-12-13 10:22:02 +01:00
committed by GitHub
parent c373108b55
commit 5e019bbb22
184 changed files with 42659 additions and 37411 deletions

View File

@@ -43,13 +43,13 @@ test.describe.parallel('Buttons input block', () => {
await expect(page.getByTestId('guest-bubble')).toHaveText('Item 3')
await page.click('button[aria-label="Close"]')
await page.click('[data-testid="block2-icon"]')
await page.getByTestId('block block2').click({ position: { x: 0, y: 0 } })
await page.click('text=Multiple choice?')
await page.getByLabel('Button label:').fill('Go')
await page.getByPlaceholder('Select a variable').nth(1).click()
await page.getByText('var1').click()
await expect(page.getByText('Setvar1')).toBeVisible()
await page.click('[data-testid="block2-icon"]')
await page.getByTestId('block block2').click({ position: { x: 0, y: 0 } })
await page.locator('text=Item 1').hover()
await page.waitForTimeout(1000)
@@ -83,7 +83,7 @@ test('Variable buttons should work', async ({ page }) => {
await expect(page.locator('text=Ok great!')).toBeVisible()
await page.click('text="Item 1"')
await page.fill('input[value="Item 1"]', '{{Item 2}}')
await page.click('[data-testid="block1-icon"]')
await page.getByTestId('block block1').click({ position: { x: 0, y: 0 } })
await page.click('text=Multiple choice?')
await page.click('text="Restart"')
await page

View File

@@ -75,7 +75,7 @@ test.describe.parallel('Picture choice input block', () => {
page.locator('typebot-standard').getByText('Third image')
).toBeVisible()
await page.getByTestId('block2-icon').click()
await page.getByTestId('block block2').click({ position: { x: 0, y: 0 } })
await page.getByText('Multiple choice?').click()
await page.getByLabel('Submit button label:').fill('Go')
await page.getByRole('button', { name: 'Restart' }).click()
@@ -94,7 +94,7 @@ test.describe.parallel('Picture choice input block', () => {
page.locator('typebot-standard').getByText('First image, Second image')
).toBeVisible()
await page.getByTestId('block2-icon').click()
await page.getByTestId('block block2').click({ position: { x: 0, y: 0 } })
await page.getByText('Is searchable?').click()
await page.getByLabel('Input placeholder:').fill('Search...')
await page.getByRole('button', { name: 'Restart' }).click()

View File

@@ -26,7 +26,7 @@ import { SpreadsheetsDropdown } from './SpreadsheetDropdown'
import { CellWithValueStack } from './CellWithValueStack'
import { CellWithVariableIdStack } from './CellWithVariableIdStack'
import { GoogleSheetConnectModal } from './GoogleSheetsConnectModal'
import { TableListItemProps, TableList } from '@/components/TableList'
import { TableList } from '@/components/TableList'
import { CredentialsDropdown } from '@/features/credentials/components/CredentialsDropdown'
import { RowsFilterTableList } from './RowsFilterTableList'
import { useWorkspace } from '@/features/workspace/WorkspaceProvider'
@@ -177,33 +177,22 @@ const ActionOptions = ({
totalRowsToExtract,
} as GoogleSheetsBlock['options'])
const UpdatingCellItem = useMemo(
() =>
function Component(props: TableListItemProps<Cell>) {
return <CellWithValueStack {...props} columns={sheet?.columns ?? []} />
},
[sheet?.columns]
)
const ExtractingCellItem = useMemo(
() =>
function Component(props: TableListItemProps<ExtractingCell>) {
return (
<CellWithVariableIdStack {...props} columns={sheet?.columns ?? []} />
)
},
[sheet?.columns]
)
switch (options.action) {
case GoogleSheetsAction.INSERT_ROW:
return (
<TableList<Cell>
initialItems={options.cellsToInsert}
onItemsChange={handleInsertColumnsChange}
Item={UpdatingCellItem}
addLabel="Add a value"
/>
>
{({ item, onItemChange }) => (
<CellWithValueStack
item={item}
onItemChange={onItemChange}
columns={sheet?.columns ?? []}
/>
)}
</TableList>
)
case GoogleSheetsAction.UPDATE_ROW:
return (
@@ -236,9 +225,16 @@ const ActionOptions = ({
<TableList<Cell>
initialItems={options.cellsToUpsert}
onItemsChange={handleUpsertColumnsChange}
Item={UpdatingCellItem}
addLabel="Add a value"
/>
>
{({ item, onItemChange }) => (
<CellWithValueStack
item={item}
onItemChange={onItemChange}
columns={sheet?.columns ?? []}
/>
)}
</TableList>
</AccordionPanel>
</AccordionItem>
</Accordion>
@@ -286,10 +282,17 @@ const ActionOptions = ({
<TableList<ExtractingCell>
initialItems={options.cellsToExtract}
onItemsChange={handleExtractingCellsChange}
Item={ExtractingCellItem}
addLabel="Add a value"
hasDefaultItem
/>
>
{({ item, onItemChange }) => (
<CellWithVariableIdStack
item={item}
onItemChange={onItemChange}
columns={sheet?.columns ?? []}
/>
)}
</TableList>
</AccordionPanel>
</AccordionItem>
</Stack>

View File

@@ -1,11 +1,11 @@
import { DropdownList } from '@/components/DropdownList'
import { TableList, TableListItemProps } from '@/components/TableList'
import { TableList } from '@/components/TableList'
import { Flex } from '@chakra-ui/react'
import {
GoogleSheetsGetOptions,
RowsFilterComparison,
} from '@typebot.io/schemas'
import React, { useCallback } from 'react'
import React from 'react'
import { RowsFilterComparisonItem } from './RowsFilterComparisonItem'
import { LogicalOperator } from '@typebot.io/schemas/features/blocks/logic/condition/constants'
@@ -30,18 +30,10 @@ export const RowsFilterTableList = ({
const updateLogicalOperator = (logicalOperator: LogicalOperator) =>
filter && onFilterChange({ ...filter, logicalOperator })
const createRowsFilterComparisonItem = useCallback(
(props: TableListItemProps<RowsFilterComparison>) => (
<RowsFilterComparisonItem {...props} columns={columns} />
),
[columns]
)
return (
<TableList<RowsFilterComparison>
initialItems={filter?.comparisons ?? []}
onItemsChange={updateComparisons}
Item={createRowsFilterComparisonItem}
ComponentBetweenItems={() => (
<Flex justify="center">
<DropdownList
@@ -52,6 +44,8 @@ export const RowsFilterTableList = ({
</Flex>
)}
addLabel="Add filter rule"
/>
>
{(props) => <RowsFilterComparisonItem {...props} columns={columns} />}
</TableList>
)
}

View File

@@ -94,12 +94,13 @@ export const OpenAIChatCompletionSettings = ({
<AccordionPanel pt="4">
<TableList
initialItems={options.messages}
Item={ChatCompletionMessageItem}
onItemsChange={updateMessages}
isOrdered
hasDefaultItem
addLabel="Add message"
/>
>
{(props) => <ChatCompletionMessageItem {...props} />}
</TableList>
</AccordionPanel>
</AccordionItem>
<AccordionItem>
@@ -131,11 +132,12 @@ export const OpenAIChatCompletionSettings = ({
<AccordionPanel pt="4">
<TableList
initialItems={options.responseMapping}
Item={ChatCompletionResponseItem}
onItemsChange={updateResponseMapping}
newItemDefaultProps={{ valueToExtract: 'Message content' }}
hasDefaultItem
/>
>
{(props) => <ChatCompletionResponseItem {...props} />}
</TableList>
</AccordionPanel>
</AccordionItem>
</Accordion>

View File

@@ -1,6 +1,6 @@
import { DropdownList } from '@/components/DropdownList'
import { SwitchWithRelatedSettings } from '@/components/SwitchWithRelatedSettings'
import { TableList, TableListItemProps } from '@/components/TableList'
import { TableList } from '@/components/TableList'
import { TextLink } from '@/components/TextLink'
import { TextInput } from '@/components/inputs'
import { CodeEditor } from '@/components/inputs/CodeEditor'
@@ -14,7 +14,7 @@ import {
pixelEventTypes,
pixelObjectProperties,
} from '@typebot.io/schemas/features/blocks/integrations/pixel/constants'
import React, { useMemo } from 'react'
import React from 'react'
const pixelReferenceUrl =
'https://developers.facebook.com/docs/meta-pixel/reference#standard-events'
@@ -69,14 +69,6 @@ export const PixelSettings = ({ options, onOptionsChange }: Props) => {
})
}
const Item = useMemo(
() =>
function Component(props: TableListItemProps<Item>) {
return <ParamItem {...props} eventType={options?.eventType} />
},
[options?.eventType]
)
return (
<Stack spacing={4}>
<TextInput
@@ -123,10 +115,13 @@ export const PixelSettings = ({ options, onOptionsChange }: Props) => {
).length > 0) && (
<TableList
initialItems={options?.params ?? []}
Item={Item}
onItemsChange={updateParams}
addLabel="Add parameter"
/>
>
{(props) => (
<ParamItem {...props} eventType={options?.eventType} />
)}
</TableList>
)}
</SwitchWithRelatedSettings>
</Stack>

View File

@@ -154,9 +154,10 @@ export const WebhookAdvancedConfigForm = ({
<TableList<KeyValue>
initialItems={webhook?.queryParams}
onItemsChange={updateQueryParams}
Item={QueryParamsInputs}
addLabel="Add a param"
/>
>
{(props) => <QueryParamsInputs {...props} />}
</TableList>
</AccordionPanel>
</AccordionItem>
<AccordionItem>
@@ -168,9 +169,10 @@ export const WebhookAdvancedConfigForm = ({
<TableList<KeyValue>
initialItems={webhook?.headers}
onItemsChange={updateHeaders}
Item={HeadersInputs}
addLabel="Add a value"
/>
>
{(props) => <HeadersInputs {...props} />}
</TableList>
</AccordionPanel>
</AccordionItem>
<AccordionItem>
@@ -203,9 +205,10 @@ export const WebhookAdvancedConfigForm = ({
<TableList<VariableForTest>
initialItems={options?.variablesForTest}
onItemsChange={updateVariablesForTest}
Item={VariableForTestInputs}
addLabel="Add an entry"
/>
>
{(props) => <VariableForTestInputs {...props} />}
</TableList>
</AccordionPanel>
</AccordionItem>
</Accordion>
@@ -235,9 +238,10 @@ export const WebhookAdvancedConfigForm = ({
<TableList<ResponseVariableMapping>
initialItems={options?.responseVariableMapping}
onItemsChange={updateResponseVariableMapping}
Item={ResponseMappingInputs}
addLabel="Add an entry"
/>
>
{(props) => <ResponseMappingInputs {...props} />}
</TableList>
</AccordionPanel>
</AccordionItem>
</Accordion>

View File

@@ -171,10 +171,11 @@ export const ZemanticAiSettings = ({
<AccordionPanel pt="4">
<TableList
initialItems={options.responseMapping ?? []}
Item={SearchResponseItem}
onItemsChange={updateResponseMapping}
newItemDefaultProps={{ valueToExtract: 'Summary' }}
/>
>
{(props) => <SearchResponseItem {...props} />}
</TableList>
</AccordionPanel>
</AccordionItem>
</Accordion>

View File

@@ -24,7 +24,6 @@ export const ConditionForm = ({ condition, onConditionChange }: Props) => {
<TableList<Comparison>
initialItems={condition?.comparisons}
onItemsChange={handleComparisonsChange}
Item={ComparisonItem}
ComponentBetweenItems={() => (
<Flex justify="center">
<DropdownList
@@ -38,6 +37,8 @@ export const ConditionForm = ({ condition, onConditionChange }: Props) => {
</Flex>
)}
addLabel="Add a comparison"
/>
>
{(props) => <ComparisonItem {...props} />}
</TableList>
)
}