2
0

🚸 (sendEmail) Make custom sender name optional

This commit is contained in:
Baptiste Arnaud
2022-11-14 11:02:30 +01:00
parent d01549fee6
commit 3686465a85
17 changed files with 75 additions and 105 deletions

View File

@ -73,14 +73,12 @@ export const GeneralSettingsForm = ({
/> />
</Flex> </Flex>
<SwitchWithLabel <SwitchWithLabel
id="prefill"
label="Prefill input" label="Prefill input"
initialValue={generalSettings.isInputPrefillEnabled ?? true} initialValue={generalSettings.isInputPrefillEnabled ?? true}
onCheckChange={handleInputPrefillChange} onCheckChange={handleInputPrefillChange}
moreInfoContent="Inputs are automatically pre-filled whenever their associated variable has a value" moreInfoContent="Inputs are automatically pre-filled whenever their associated variable has a value"
/> />
<SwitchWithLabel <SwitchWithLabel
id="new-result"
label="Remember session" label="Remember session"
initialValue={ initialValue={
isDefined(generalSettings.isNewResultOnRefreshEnabled) isDefined(generalSettings.isNewResultOnRefreshEnabled)
@ -91,7 +89,6 @@ export const GeneralSettingsForm = ({
moreInfoContent="If the user refreshes the page, its existing results will be overwritten. Disable this if you want to create a new results every time the user refreshes the page." moreInfoContent="If the user refreshes the page, its existing results will be overwritten. Disable this if you want to create a new results every time the user refreshes the page."
/> />
<SwitchWithLabel <SwitchWithLabel
id="query-params"
label="Hide query params on bot start" label="Hide query params on bot start"
initialValue={generalSettings.isHideQueryParamsEnabled ?? true} initialValue={generalSettings.isHideQueryParamsEnabled ?? true}
onCheckChange={handleHideQueryParamsChange} onCheckChange={handleHideQueryParamsChange}

View File

@ -24,8 +24,7 @@ export const ChoiceInputSettingsBody = ({
return ( return (
<Stack spacing={4}> <Stack spacing={4}>
<SwitchWithLabel <SwitchWithLabel
id={'is-multiple'} label="Multiple choice?"
label={'Multiple choice?'}
initialValue={options?.isMultipleChoice ?? false} initialValue={options?.isMultipleChoice ?? false}
onCheckChange={handleIsMultipleChange} onCheckChange={handleIsMultipleChange}
/> />

View File

@ -33,7 +33,6 @@ export const CodeSettings = ({ options, onOptionsChange }: Props) => {
/> />
</Stack> </Stack>
<SwitchWithLabel <SwitchWithLabel
id="shouldExecuteInParentContext"
label="Execute in parent window" label="Execute in parent window"
moreInfoContent="Execute the code in the parent window context (when the bot is embedded). If it isn't detected, the code will be executed in the current window context." moreInfoContent="Execute the code in the parent window context (when the bot is embedded). If it isn't detected, the code will be executed in the current window context."
initialValue={options.shouldExecuteInParentContext ?? false} initialValue={options.shouldExecuteInParentContext ?? false}

View File

@ -30,14 +30,12 @@ export const DateInputSettingsBody = ({
return ( return (
<Stack spacing={4}> <Stack spacing={4}>
<SwitchWithLabel <SwitchWithLabel
id="is-range" label="Is range?"
label={'Is range?'}
initialValue={options.isRange} initialValue={options.isRange}
onCheckChange={handleIsRangeChange} onCheckChange={handleIsRangeChange}
/> />
<SwitchWithLabel <SwitchWithLabel
id="with-time" label="With time?"
label={'With time?'}
initialValue={options.isRange} initialValue={options.isRange}
onCheckChange={handleHasTimeChange} onCheckChange={handleHasTimeChange}
/> />

View File

@ -28,13 +28,11 @@ export const FileInputSettings = ({ options, onOptionsChange }: Props) => {
return ( return (
<Stack spacing={4}> <Stack spacing={4}>
<SwitchWithLabel <SwitchWithLabel
id="required"
label="Required?" label="Required?"
initialValue={options.isRequired ?? true} initialValue={options.isRequired ?? true}
onCheckChange={handleRequiredChange} onCheckChange={handleRequiredChange}
/> />
<SwitchWithLabel <SwitchWithLabel
id="switch"
label="Allow multiple files?" label="Allow multiple files?"
initialValue={options.isMultipleAllowed} initialValue={options.isMultipleAllowed}
onCheckChange={handleMultipleFilesChange} onCheckChange={handleMultipleFilesChange}

View File

@ -68,7 +68,6 @@ export const RatingInputSettings = ({
{options.buttonType === 'Icons' && ( {options.buttonType === 'Icons' && (
<SwitchWithLabel <SwitchWithLabel
id="switch"
label="Custom icon?" label="Custom icon?"
initialValue={options.customIcon.isEnabled} initialValue={options.customIcon.isEnabled}
onCheckChange={handleCustomIconCheck} onCheckChange={handleCustomIconCheck}

View File

@ -29,7 +29,6 @@ export const RedirectSettings = ({ options, onOptionsChange }: Props) => {
/> />
</Stack> </Stack>
<SwitchWithLabel <SwitchWithLabel
id="new-tab"
label="Open in new tab?" label="Open in new tab?"
initialValue={options.isNewTab} initialValue={options.isNewTab}
onCheckChange={handleIsNewTabChange} onCheckChange={handleIsNewTabChange}

View File

@ -154,7 +154,6 @@ export const SendEmailSettings = ({ options, onOptionsChange }: Props) => {
/> />
</Stack> </Stack>
<SwitchWithLabel <SwitchWithLabel
id={'custom-body'}
label={'Custom content?'} label={'Custom content?'}
initialValue={options.isCustomBody ?? false} initialValue={options.isCustomBody ?? false}
onCheckChange={handleIsCustomBodyChange} onCheckChange={handleIsCustomBodyChange}

View File

@ -28,60 +28,53 @@ export const SmtpConfigForm = ({ config, onConfigChange }: Props) => {
return ( return (
<Stack as="form" spacing={4}> <Stack as="form" spacing={4}>
<FormControl isRequired> <Input
<FormLabel>From email:</FormLabel> isRequired
<Input label="From email"
defaultValue={config.from.email ?? ''} defaultValue={config.from.email ?? ''}
onChange={handleFromEmailChange} onChange={handleFromEmailChange}
placeholder="notifications@provider.com" placeholder="notifications@provider.com"
withVariableButton={false} withVariableButton={false}
/> />
</FormControl> <Input
<FormControl isRequired> label="From name"
<FormLabel>From name:</FormLabel> defaultValue={config.from.name ?? ''}
<Input onChange={handleFromNameChange}
defaultValue={config.from.name ?? ''} placeholder="John Smith"
onChange={handleFromNameChange} withVariableButton={false}
placeholder="John Smith" />
withVariableButton={false} <Input
/> isRequired
</FormControl> label="Host"
<FormControl isRequired> defaultValue={config.host ?? ''}
<FormLabel>Host:</FormLabel> onChange={handleHostChange}
<Input placeholder="mail.provider.com"
defaultValue={config.host ?? ''} withVariableButton={false}
onChange={handleHostChange} />
placeholder="mail.provider.com" <Input
withVariableButton={false} isRequired
/> label="Username / Email"
</FormControl> type="email"
<FormControl isRequired> defaultValue={config.username ?? ''}
<FormLabel>Username / Email:</FormLabel> onChange={handleUsernameChange}
<Input placeholder="user@provider.com"
type="email" withVariableButton={false}
defaultValue={config.username ?? ''} />
onChange={handleUsernameChange} <Input
placeholder="user@provider.com" isRequired
withVariableButton={false} label="Password"
/> type="password"
</FormControl> defaultValue={config.password ?? ''}
<FormControl isRequired> onChange={handlePasswordChange}
<FormLabel>Password:</FormLabel> withVariableButton={false}
<Input />
type="password"
defaultValue={config.password ?? ''}
onChange={handlePasswordChange}
withVariableButton={false}
/>
</FormControl>
<SwitchWithLabel <SwitchWithLabel
id="Tls" label="Secure?"
label={'Secure?'}
initialValue={config.isTlsEnabled ?? false} initialValue={config.isTlsEnabled ?? false}
onCheckChange={handleTlsCheck} onCheckChange={handleTlsCheck}
moreInfoContent="If enabled, the connection will use TLS when connecting to server. If disabled then TLS is used if server supports the STARTTLS extension. In most cases enable it if you are connecting to port 465. For port 587 or 25 keep it disabled." moreInfoContent="If enabled, the connection will use TLS when connecting to server. If disabled then TLS is used if server supports the STARTTLS extension. In most cases enable it if you are connecting to port 465. For port 587 or 25 keep it disabled."
/> />
<FormControl as={HStack} justifyContent="space-between"> <FormControl as={HStack} justifyContent="space-between" isRequired>
<FormLabel mb="0">Port number:</FormLabel> <FormLabel mb="0">Port number:</FormLabel>
<SmartNumberInput <SmartNumberInput
placeholder="25" placeholder="25"

View File

@ -83,10 +83,10 @@ export const SmtpConfigModal = ({
onClick={handleCreateClick} onClick={handleCreateClick}
isDisabled={ isDisabled={
isNotDefined(smtpConfig.from.email) || isNotDefined(smtpConfig.from.email) ||
isNotDefined(smtpConfig.from.name) ||
isNotDefined(smtpConfig.host) || isNotDefined(smtpConfig.host) ||
isNotDefined(smtpConfig.username) || isNotDefined(smtpConfig.username) ||
isNotDefined(smtpConfig.password) isNotDefined(smtpConfig.password) ||
isNotDefined(smtpConfig.port)
} }
isLoading={isCreating} isLoading={isCreating}
> >

View File

@ -26,7 +26,6 @@ export const TextInputSettingsBody = ({
return ( return (
<Stack spacing={4}> <Stack spacing={4}>
<SwitchWithLabel <SwitchWithLabel
id="switch"
label="Long text?" label="Long text?"
initialValue={options?.isLong ?? false} initialValue={options?.isLong ?? false}
onCheckChange={handleLongChange} onCheckChange={handleLongChange}

View File

@ -172,7 +172,6 @@ export const WebhookSettings = ({
withVariableButton={!provider} withVariableButton={!provider}
/> />
<SwitchWithLabel <SwitchWithLabel
id={'easy-config'}
label="Advanced configuration" label="Advanced configuration"
initialValue={options.isAdvancedConfig ?? true} initialValue={options.isAdvancedConfig ?? true}
onCheckChange={handleAdvancedConfigChange} onCheckChange={handleAdvancedConfigChange}
@ -225,7 +224,6 @@ export const WebhookSettings = ({
</AccordionButton> </AccordionButton>
<AccordionPanel pb={4} as={Stack} spacing="6"> <AccordionPanel pb={4} as={Stack} spacing="6">
<SwitchWithLabel <SwitchWithLabel
id={'custom-body'}
label="Custom body" label="Custom body"
initialValue={options.isCustomBody ?? true} initialValue={options.isCustomBody ?? true}
onCheckChange={handleBodyFormStateChange} onCheckChange={handleBodyFormStateChange}

View File

@ -1,9 +1,14 @@
import { FormLabel, HStack, Switch, SwitchProps } from '@chakra-ui/react' import {
FormControl,
FormLabel,
HStack,
Switch,
SwitchProps,
} from '@chakra-ui/react'
import React, { useState } from 'react' import React, { useState } from 'react'
import { MoreInfoTooltip } from './MoreInfoTooltip' import { MoreInfoTooltip } from './MoreInfoTooltip'
type SwitchWithLabelProps = { type SwitchWithLabelProps = {
id: string
label: string label: string
initialValue: boolean initialValue: boolean
moreInfoContent?: string moreInfoContent?: string
@ -11,12 +16,11 @@ type SwitchWithLabelProps = {
} & SwitchProps } & SwitchProps
export const SwitchWithLabel = ({ export const SwitchWithLabel = ({
id,
label, label,
initialValue, initialValue,
moreInfoContent, moreInfoContent,
onCheckChange, onCheckChange,
...props ...switchProps
}: SwitchWithLabelProps) => { }: SwitchWithLabelProps) => {
const [isChecked, setIsChecked] = useState(initialValue) const [isChecked, setIsChecked] = useState(initialValue)
@ -25,21 +29,16 @@ export const SwitchWithLabel = ({
onCheckChange(!isChecked) onCheckChange(!isChecked)
} }
return ( return (
<HStack justifyContent="space-between"> <FormControl as={HStack} justifyContent="space-between">
<HStack> <FormLabel mb="0">
<FormLabel htmlFor={id} mb="0" mr="0"> {label}
{label}
</FormLabel>
{moreInfoContent && ( {moreInfoContent && (
<MoreInfoTooltip>{moreInfoContent}</MoreInfoTooltip> <>
&nbsp;<MoreInfoTooltip>{moreInfoContent}</MoreInfoTooltip>
</>
)} )}
</HStack> </FormLabel>
<Switch <Switch isChecked={isChecked} onChange={handleChange} {...switchProps} />
isChecked={isChecked} </FormControl>
onChange={handleChange}
id={id}
{...props}
/>
</HStack>
) )
} }

View File

@ -3,7 +3,6 @@ import { createTypebots } from 'utils/playwright/databaseActions'
import { parseDefaultGroupWithBlock } from 'utils/playwright/databaseHelpers' import { parseDefaultGroupWithBlock } from 'utils/playwright/databaseHelpers'
import cuid from 'cuid' import cuid from 'cuid'
import { defaultChatwootOptions, IntegrationBlockType } from 'models' import { defaultChatwootOptions, IntegrationBlockType } from 'models'
import { typebotViewer } from 'utils/playwright/testHelpers'
const typebotId = cuid() const typebotId = cuid()

View File

@ -21,6 +21,7 @@ test('should be configurable', async ({ page }) => {
await page.click('input[placeholder="Select a typebot"]') await page.click('input[placeholder="Select a typebot"]')
await page.click('text=My link typebot 2') await page.click('text=My link typebot 2')
await expect(page.locator('input[value="My link typebot 2"]')).toBeVisible() await expect(page.locator('input[value="My link typebot 2"]')).toBeVisible()
await expect(page.getByText('Jump in My link typebot 2')).toBeVisible()
await page.click('[aria-label="Navigate to typebot"]') await page.click('[aria-label="Navigate to typebot"]')
await expect(page).toHaveURL( await expect(page).toHaveURL(
`/typebots/${linkedTypebotId}/edit?parentId=${typebotId}` `/typebots/${linkedTypebotId}/edit?parentId=${typebotId}`

View File

@ -6,19 +6,16 @@ import { importTypebotInDatabase } from 'utils/playwright/databaseActions'
import { freeWorkspaceId } from 'utils/playwright/databaseSetup' import { freeWorkspaceId } from 'utils/playwright/databaseSetup'
import { typebotViewer } from 'utils/playwright/testHelpers' import { typebotViewer } from 'utils/playwright/testHelpers'
const typebotId = cuid()
test.describe.parallel('Settings page', () => { test.describe.parallel('Settings page', () => {
test.beforeAll(async () => {
await importTypebotInDatabase(
path.join(__dirname, '../fixtures/typebots/settings.json'),
{
id: typebotId,
}
)
})
test.describe('General', () => { test.describe('General', () => {
test('should reflect change in real-time', async ({ page }) => { test('should reflect change in real-time', async ({ page }) => {
const typebotId = cuid()
await importTypebotInDatabase(
path.join(__dirname, '../fixtures/typebots/settings.json'),
{
id: typebotId,
}
)
await page.goto(`/typebots/${typebotId}/settings`) await page.goto(`/typebots/${typebotId}/settings`)
await expect( await expect(
typebotViewer(page).locator('a:has-text("Made with Typebot")') typebotViewer(page).locator('a:has-text("Made with Typebot")')
@ -72,7 +69,7 @@ test.describe.parallel('Settings page', () => {
test('should be fillable', async ({ page }) => { test('should be fillable', async ({ page }) => {
const favIconUrl = 'https://www.baptistearno.com/favicon.png' const favIconUrl = 'https://www.baptistearno.com/favicon.png'
const imageUrl = 'https://www.baptistearno.com/images/site-preview.png' const imageUrl = 'https://www.baptistearno.com/images/site-preview.png'
const typebotId = 'metadata-typebot' const typebotId = cuid()
await importTypebotInDatabase( await importTypebotInDatabase(
path.join(__dirname, '../fixtures/typebots/settings.json'), path.join(__dirname, '../fixtures/typebots/settings.json'),
{ {
@ -124,7 +121,7 @@ test.describe.parallel('Settings page', () => {
test.describe('Free workspace', () => { test.describe('Free workspace', () => {
test("can't remove branding", async ({ page }) => { test("can't remove branding", async ({ page }) => {
const typebotId = 'free-branding-typebot' const typebotId = cuid()
await importTypebotInDatabase( await importTypebotInDatabase(
path.join(__dirname, '../fixtures/typebots/settings.json'), path.join(__dirname, '../fixtures/typebots/settings.json'),
{ {

View File

@ -66,11 +66,7 @@ test('can create and delete a new workspace', async ({ page }) => {
) )
).toBeVisible() ).toBeVisible()
await page.click('text="Delete"') await page.click('text="Delete"')
await expect(page.locator('text=Free workspace')).toBeVisible() await expect(page.locator('text="John Doe\'s workspace"')).toBeHidden()
await page.click('text=Free workspace')
await expect(
page.locator('text="John Doe\'s workspace" >> nth=1')
).toBeHidden()
}) })
test('can update workspace info', async ({ page }) => { test('can update workspace info', async ({ page }) => {