Add OpenAI block

Also migrate credentials to tRPC

Closes #253
This commit is contained in:
Baptiste Arnaud
2023-03-09 08:46:36 +01:00
parent 97cfdfe79f
commit ff04edf139
86 changed files with 2583 additions and 1055 deletions

View File

@@ -52,7 +52,7 @@ test.describe.parallel('Buttons input block', () => {
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('Collectsvar1')).toBeVisible()
await expect(page.getByText('Setvar1')).toBeVisible()
await page.click('[data-testid="block2-icon"]')
await page.locator('text=Item 1').hover()

View File

@@ -1,15 +1,9 @@
import { BlockIndices, ChoiceInputBlock, Variable } from 'models'
import { BlockIndices, ChoiceInputBlock } from 'models'
import React from 'react'
import { ItemNodesList } from '@/features/graph/components/Nodes/ItemNode'
import {
HStack,
Stack,
Tag,
Text,
useColorModeValue,
Wrap,
} from '@chakra-ui/react'
import { Stack, Tag, Text, Wrap } from '@chakra-ui/react'
import { useTypebot } from '@/features/editor'
import { SetVariableLabel } from '@/components/SetVariableLabel'
type Props = {
block: ChoiceInputBlock
@@ -25,7 +19,7 @@ export const ButtonsBlockNode = ({ block, indices }: Props) => {
return (
<Stack w="full">
{block.options.variableId ? (
<CollectVariableLabel
<SetVariableLabel
variableId={block.options.variableId}
variables={typebot?.variables}
/>
@@ -44,28 +38,3 @@ export const ButtonsBlockNode = ({ block, indices }: Props) => {
</Stack>
)
}
const CollectVariableLabel = ({
variableId,
variables,
}: {
variableId: string
variables?: Variable[]
}) => {
const textColor = useColorModeValue('gray.600', 'gray.400')
const variableName = variables?.find(
(variable) => variable.id === variableId
)?.name
if (!variableName) return null
return (
<HStack fontStyle="italic" spacing={1}>
<Text fontSize="sm" color={textColor}>
Collects
</Text>
<Tag bg="orange.400" color="white" size="sm">
{variableName}
</Tag>
</HStack>
)
}

View File

@@ -11,12 +11,13 @@ import {
AccordionPanel,
} from '@chakra-ui/react'
import { DropdownList } from '@/components/DropdownList'
import { CredentialsType, PaymentInputOptions, PaymentProvider } from 'models'
import React, { ChangeEvent, useState } from 'react'
import { PaymentInputOptions, PaymentProvider } from 'models'
import React, { ChangeEvent } from 'react'
import { currencies } from './currencies'
import { StripeConfigModal } from './StripeConfigModal'
import { CredentialsDropdown } from '@/features/credentials'
import { TextInput } from '@/components/inputs'
import { useWorkspace } from '@/features/workspace/WorkspaceProvider'
type Props = {
options: PaymentInputOptions
@@ -24,8 +25,8 @@ type Props = {
}
export const PaymentSettings = ({ options, onOptionsChange }: Props) => {
const { workspace } = useWorkspace()
const { isOpen, onOpen, onClose } = useDisclosure()
const [refreshCredentialsKey, setRefreshCredentialsKey] = useState(0)
const handleProviderChange = (provider: PaymentProvider) => {
onOptionsChange({
@@ -35,7 +36,6 @@ export const PaymentSettings = ({ options, onOptionsChange }: Props) => {
}
const handleCredentialsSelect = (credentialsId?: string) => {
setRefreshCredentialsKey(refreshCredentialsKey + 1)
onOptionsChange({
...options,
credentialsId,
@@ -96,13 +96,15 @@ export const PaymentSettings = ({ options, onOptionsChange }: Props) => {
</Stack>
<Stack>
<Text>Account:</Text>
<CredentialsDropdown
type={CredentialsType.STRIPE}
currentCredentialsId={options.credentialsId}
onCredentialsSelect={handleCredentialsSelect}
onCreateNewClick={onOpen}
refreshDropdownKey={refreshCredentialsKey}
/>
{workspace && (
<CredentialsDropdown
type="stripe"
workspaceId={workspace.id}
currentCredentialsId={options.credentialsId}
onCredentialsSelect={handleCredentialsSelect}
onCreateNewClick={onOpen}
/>
)}
</Stack>
<HStack>
<TextInput

View File

@@ -14,15 +14,15 @@ import {
HStack,
} from '@chakra-ui/react'
import { useUser } from '@/features/account'
import { CredentialsType, StripeCredentialsData } from 'models'
import React, { useState } from 'react'
import { useWorkspace } from '@/features/workspace'
import { omit } from 'utils'
import { useToast } from '@/hooks/useToast'
import { TextInput } from '@/components/inputs'
import { MoreInfoTooltip } from '@/components/MoreInfoTooltip'
import { TextLink } from '@/components/TextLink'
import { createCredentialsQuery } from '@/features/credentials'
import { StripeCredentials } from 'models'
import { trpc } from '@/lib/trpc'
import { isNotEmpty } from 'utils'
type Props = {
isOpen: boolean
@@ -40,12 +40,32 @@ export const StripeConfigModal = ({
const [isCreating, setIsCreating] = useState(false)
const { showToast } = useToast()
const [stripeConfig, setStripeConfig] = useState<
StripeCredentialsData & { name: string }
StripeCredentials['data'] & { name: string }
>({
name: '',
live: { publicKey: '', secretKey: '' },
test: { publicKey: '', secretKey: '' },
})
const {
credentials: {
listCredentials: { refetch: refetchCredentials },
},
} = trpc.useContext()
const { mutate } = trpc.credentials.createCredentials.useMutation({
onMutate: () => setIsCreating(true),
onSettled: () => setIsCreating(false),
onError: (err) => {
showToast({
description: err.message,
status: 'error',
})
},
onSuccess: (data) => {
refetchCredentials()
onNewCredentials(data.credentialsId)
onClose()
},
})
const handleNameChange = (name: string) =>
setStripeConfig({
@@ -77,22 +97,26 @@ export const StripeConfigModal = ({
test: { ...stripeConfig.test, secretKey },
})
const handleCreateClick = async () => {
const createCredentials = async () => {
if (!user?.email || !workspace?.id) return
setIsCreating(true)
const { data, error } = await createCredentialsQuery({
data: omit(stripeConfig, 'name'),
name: stripeConfig.name,
type: CredentialsType.STRIPE,
workspaceId: workspace.id,
mutate({
credentials: {
data: {
live: stripeConfig.live,
test: {
publicKey: isNotEmpty(stripeConfig.test.publicKey)
? stripeConfig.test.publicKey
: undefined,
secretKey: isNotEmpty(stripeConfig.test.secretKey)
? stripeConfig.test.secretKey
: undefined,
},
},
name: stripeConfig.name,
type: 'stripe',
workspaceId: workspace.id,
},
})
setIsCreating(false)
if (error)
return showToast({ title: error.name, description: error.message })
if (!data?.credentials)
return showToast({ description: "Credentials wasn't created" })
onNewCredentials(data.credentials.id)
onClose()
}
return (
<Modal isOpen={isOpen} onClose={onClose}>
@@ -108,6 +132,7 @@ export const StripeConfigModal = ({
onChange={handleNameChange}
placeholder="Typebot"
withVariableButton={false}
debounceTimeout={0}
/>
<Stack>
<FormLabel>
@@ -121,11 +146,13 @@ export const StripeConfigModal = ({
onChange={handleTestPublicKeyChange}
placeholder="pk_test_..."
withVariableButton={false}
debounceTimeout={0}
/>
<TextInput
onChange={handleTestSecretKeyChange}
placeholder="sk_test_..."
withVariableButton={false}
debounceTimeout={0}
/>
</HStack>
</Stack>
@@ -137,6 +164,7 @@ export const StripeConfigModal = ({
onChange={handlePublicKeyChange}
placeholder="pk_live_..."
withVariableButton={false}
debounceTimeout={0}
/>
</FormControl>
<FormControl>
@@ -144,6 +172,7 @@ export const StripeConfigModal = ({
onChange={handleSecretKeyChange}
placeholder="sk_live_..."
withVariableButton={false}
debounceTimeout={0}
/>
</FormControl>
</HStack>
@@ -162,7 +191,7 @@ export const StripeConfigModal = ({
<ModalFooter>
<Button
colorScheme="blue"
onClick={handleCreateClick}
onClick={createCredentials}
isDisabled={
stripeConfig.live.publicKey === '' ||
stripeConfig.name === '' ||

View File

@@ -64,7 +64,7 @@ export const RatingInputSettings = ({
</FormLabel>
<DropdownList
onItemSelect={handleTypeChange}
items={['Icons', 'Numbers']}
items={['Icons', 'Numbers'] as const}
currentItem={options.buttonType}
/>
</Stack>