2
0

feat(editor): Add send email integration

This commit is contained in:
Baptiste Arnaud
2022-02-07 18:06:37 +01:00
parent f4336b83cc
commit d6238b3474
48 changed files with 2119 additions and 2606 deletions

View File

@ -3,9 +3,9 @@ import { CredentialsDropdown } from 'components/shared/CredentialsDropdown'
import { DropdownList } from 'components/shared/DropdownList'
import { TableList, TableListItemProps } from 'components/shared/TableList'
import { useTypebot } from 'contexts/TypebotContext'
import { CredentialsType } from 'db'
import {
Cell,
CredentialsType,
ExtractingCell,
GoogleSheetsAction,
GoogleSheetsGetOptions,

View File

@ -0,0 +1,92 @@
import { Stack, useDisclosure, Text } from '@chakra-ui/react'
import { CredentialsDropdown } from 'components/shared/CredentialsDropdown'
import {
InputWithVariableButton,
TextareaWithVariableButton,
} from 'components/shared/TextboxWithVariableButton'
import { CredentialsType, SendEmailOptions } from 'models'
import React from 'react'
import { SmtpConfigModal } from './SmtpConfigModal'
type Props = {
options: SendEmailOptions
onOptionsChange: (options: SendEmailOptions) => void
}
export const SendEmailSettings = ({ options, onOptionsChange }: Props) => {
const { isOpen, onOpen, onClose } = useDisclosure()
const handleCredentialsSelect = (credentialsId: string) =>
onOptionsChange({
...options,
credentialsId,
})
const handleToChange = (recipientsStr: string) => {
const recipients: string[] = recipientsStr
.split(',')
.map((str) => str.trim())
onOptionsChange({
...options,
recipients,
})
}
const handleSubjectChange = (subject: string) =>
onOptionsChange({
...options,
subject,
})
const handleBodyChange = (body: string) =>
onOptionsChange({
...options,
body,
})
return (
<Stack spacing={4}>
<Stack>
<Text>From: </Text>
<CredentialsDropdown
type={CredentialsType.SMTP}
currentCredentialsId={options.credentialsId}
onCredentialsSelect={handleCredentialsSelect}
onCreateNewClick={onOpen}
defaultCredentialLabel={
process.env.NEXT_PUBLIC_EMAIL_NOTIFICATIONS_FROM_EMAIL
}
/>
</Stack>
<Stack>
<Text>To: </Text>
<InputWithVariableButton
onChange={handleToChange}
initialValue={options.recipients.join(', ')}
placeholder="email1@gmail.com, email2@gmail.com"
/>
</Stack>
<Stack>
<Text>Subject: </Text>
<InputWithVariableButton
data-testid="subject-input"
onChange={handleSubjectChange}
initialValue={options.subject ?? ''}
/>
</Stack>
<Stack>
<Text>Body: </Text>
<TextareaWithVariableButton
data-testid="body-input"
minH="300px"
onChange={handleBodyChange}
initialValue={options.body ?? ''}
/>
</Stack>
<SmtpConfigModal
isOpen={isOpen}
onClose={onClose}
onNewCredentials={handleCredentialsSelect}
/>
</Stack>
)
}

View File

@ -0,0 +1,88 @@
import { FormControl, FormLabel, HStack, Stack } from '@chakra-ui/react'
import { isDefined } from '@udecode/plate-common'
import { DebouncedInput } from 'components/shared/DebouncedInput'
import { SmartNumberInput } from 'components/shared/SmartNumberInput'
import { SwitchWithLabel } from 'components/shared/SwitchWithLabel'
import { SmtpCredentialsData } from 'models'
import React from 'react'
type Props = {
config: SmtpCredentialsData
onConfigChange: (config: SmtpCredentialsData) => void
}
export const SmtpConfigForm = ({ config, onConfigChange }: Props) => {
const handleFromEmailChange = (email: string) =>
onConfigChange({ ...config, from: { ...config.from, email } })
const handleFromNameChange = (name: string) =>
onConfigChange({ ...config, from: { ...config.from, name } })
const handleHostChange = (host: string) => onConfigChange({ ...config, host })
const handleUsernameChange = (username: string) =>
onConfigChange({ ...config, username })
const handlePasswordChange = (password: string) =>
onConfigChange({ ...config, password })
const handleTlsCheck = (isTlsEnabled: boolean) =>
onConfigChange({ ...config, isTlsEnabled })
const handlePortNumberChange = (port?: number) =>
isDefined(port) && onConfigChange({ ...config, port })
return (
<Stack as="form" spacing={4}>
<FormControl isRequired>
<FormLabel>From email:</FormLabel>
<DebouncedInput
initialValue={config.from.email ?? ''}
onChange={handleFromEmailChange}
placeholder="notifications@provider.com"
/>
</FormControl>
<FormControl isRequired>
<FormLabel>From name:</FormLabel>
<DebouncedInput
initialValue={config.from.name ?? ''}
onChange={handleFromNameChange}
placeholder="John Smith"
/>
</FormControl>
<FormControl isRequired>
<FormLabel>Host:</FormLabel>
<DebouncedInput
initialValue={config.host ?? ''}
onChange={handleHostChange}
placeholder="mail.provider.com"
/>
</FormControl>
<FormControl isRequired>
<FormLabel>Username / Email:</FormLabel>
<DebouncedInput
type="email"
initialValue={config.username ?? ''}
onChange={handleUsernameChange}
placeholder="user@provider.com"
/>
</FormControl>
<FormControl isRequired>
<FormLabel>Password:</FormLabel>
<DebouncedInput
type="password"
initialValue={config.password ?? ''}
onChange={handlePasswordChange}
/>
</FormControl>
<SwitchWithLabel
id="Tls"
label={'Use TLS?'}
initialValue={config.isTlsEnabled ?? false}
onCheckChange={handleTlsCheck}
/>
<FormControl as={HStack} justifyContent="space-between">
<FormLabel mb="0">Port number:</FormLabel>
<SmartNumberInput
placeholder="25"
value={config.port}
onValueChange={handlePortNumberChange}
/>
</FormControl>
</Stack>
)
}

View File

@ -0,0 +1,88 @@
import {
Modal,
ModalOverlay,
ModalContent,
ModalHeader,
ModalCloseButton,
ModalBody,
ModalFooter,
Button,
useToast,
} from '@chakra-ui/react'
import { useUser } from 'contexts/UserContext'
import { CredentialsType, SmtpCredentialsData } from 'models'
import React, { useState } from 'react'
import { createCredentials } from 'services/credentials'
import { isNotDefined } from 'utils'
import { SmtpConfigForm } from './SmtpConfigForm'
type Props = {
isOpen: boolean
onClose: () => void
onNewCredentials: (id: string) => void
}
export const SmtpConfigModal = ({
isOpen,
onNewCredentials,
onClose,
}: Props) => {
const { user, mutateCredentials } = useUser()
const [isCreating, setIsCreating] = useState(false)
const toast = useToast({
position: 'top-right',
status: 'error',
})
const [smtpConfig, setSmtpConfig] = useState<SmtpCredentialsData>({
from: {},
port: 25,
})
const handleCreateClick = async () => {
if (!user) return
setIsCreating(true)
const { data, error } = await createCredentials(user.id, {
data: smtpConfig,
name: smtpConfig.from.email as string,
type: CredentialsType.SMTP,
})
await mutateCredentials()
setIsCreating(false)
if (error) return toast({ title: error.name, description: error.message })
if (!data?.credentials)
return toast({ description: "Credentials wasn't created" })
onNewCredentials(data.credentials.id)
onClose()
}
return (
<Modal isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Create SMTP config</ModalHeader>
<ModalCloseButton />
<ModalBody>
<SmtpConfigForm config={smtpConfig} onConfigChange={setSmtpConfig} />
</ModalBody>
<ModalFooter>
<Button
colorScheme="blue"
mr={3}
onClick={handleCreateClick}
isDisabled={
isNotDefined(smtpConfig.from.email) ||
isNotDefined(smtpConfig.from.name) ||
isNotDefined(smtpConfig.host) ||
isNotDefined(smtpConfig.username) ||
isNotDefined(smtpConfig.password)
}
isLoading={isCreating}
>
Create
</Button>
<Button variant="ghost">Close</Button>
</ModalFooter>
</ModalContent>
</Modal>
)
}

View File

@ -0,0 +1 @@
export { SendEmailSettings } from './SendEmailSettings'