2
0

refactor(♻️ Add defaults everywhere (+ settings page)):

This commit is contained in:
Baptiste Arnaud
2022-01-25 18:19:37 +01:00
parent 21448bcc8a
commit c5aaa323d1
115 changed files with 1436 additions and 720 deletions

View File

@ -8,10 +8,11 @@ import { ImageUploadContent } from 'components/shared/ImageUploadContent'
import { useTypebot } from 'contexts/TypebotContext'
import {
BubbleStep,
BubbleStepContent,
BubbleStepType,
ImageBubbleStep,
TextBubbleStep,
VideoBubbleContent,
VideoBubbleStep,
} from 'models'
import { useRef } from 'react'
import { VideoUploadContent } from './VideoUploadContent'
@ -39,14 +40,17 @@ export const ContentPopover = ({ step }: Props) => {
export const StepContent = ({ step }: Props) => {
const { updateStep } = useTypebot()
const handleContentChange = (content: BubbleStepContent) =>
updateStep(step.id, { content } as Partial<ImageBubbleStep>)
const handleContentChange = (url: string) =>
updateStep(step.id, { content: { url } } as Partial<ImageBubbleStep>)
const handleVideoContentChange = (content: VideoBubbleContent) =>
updateStep(step.id, { content } as Partial<VideoBubbleStep>)
switch (step.type) {
case BubbleStepType.IMAGE: {
return (
<ImageUploadContent
content={step.content}
url={step.content?.url}
onSubmit={handleContentChange}
/>
)
@ -55,7 +59,7 @@ export const StepContent = ({ step }: Props) => {
return (
<VideoUploadContent
content={step.content}
onSubmit={handleContentChange}
onSubmit={handleVideoContentChange}
/>
)
}

View File

@ -1,5 +1,5 @@
import { Stack, Text } from '@chakra-ui/react'
import { InputWithVariableButton } from 'components/shared/InputWithVariableButton'
import { InputWithVariableButton } from 'components/shared/TextboxWithVariableButton/InputWithVariableButton'
import { VideoBubbleContent, VideoBubbleContentType } from 'models'
import urlParser from 'js-video-url-parser/lib/base'
import 'js-video-url-parser/lib/provider/vimeo'

View File

@ -1,6 +1,6 @@
import { Stack } from '@chakra-ui/react'
import { DropdownList } from 'components/shared/DropdownList'
import { InputWithVariableButton } from 'components/shared/InputWithVariableButton'
import { InputWithVariableButton } from 'components/shared/TextboxWithVariableButton/InputWithVariableButton'
import { TableListItemProps } from 'components/shared/TableList'
import { VariableSearchInput } from 'components/shared/VariableSearchInput'
import { Comparison, Variable, ComparisonOperators } from 'models'

View File

@ -6,7 +6,7 @@ import { DateInputOptions, Variable } from 'models'
import React from 'react'
type DateInputSettingsBodyProps = {
options?: DateInputOptions
options: DateInputOptions
onOptionsChange: (options: DateInputOptions) => void
}
@ -32,23 +32,23 @@ export const DateInputSettingsBody = ({
<SwitchWithLabel
id="is-range"
label={'Is range?'}
initialValue={options?.isRange ?? false}
initialValue={options.isRange}
onCheckChange={handleIsRangeChange}
/>
<SwitchWithLabel
id="with-time"
label={'With time?'}
initialValue={options?.isRange ?? false}
initialValue={options.isRange}
onCheckChange={handleHasTimeChange}
/>
{options?.isRange && (
{options.isRange && (
<Stack>
<FormLabel mb="0" htmlFor="from">
From label:
</FormLabel>
<DebouncedInput
id="from"
initialValue={options?.labels?.from ?? 'From:'}
initialValue={options.labels.from}
delay={100}
onChange={handleFromChange}
/>
@ -61,7 +61,7 @@ export const DateInputSettingsBody = ({
</FormLabel>
<DebouncedInput
id="to"
initialValue={options?.labels?.to ?? 'To:'}
initialValue={options.labels.to}
delay={100}
onChange={handleToChange}
/>
@ -73,7 +73,7 @@ export const DateInputSettingsBody = ({
</FormLabel>
<DebouncedInput
id="button"
initialValue={options?.labels?.button ?? 'Send'}
initialValue={options.labels.button}
delay={100}
onChange={handleButtonLabelChange}
/>
@ -83,7 +83,7 @@ export const DateInputSettingsBody = ({
Save answer in a variable:
</FormLabel>
<VariableSearchInput
initialVariableId={options?.variableId}
initialVariableId={options.variableId}
onSelectVariable={handleVariableChange}
/>
</Stack>

View File

@ -5,7 +5,7 @@ import { EmailInputOptions, Variable } from 'models'
import React from 'react'
type EmailInputSettingsBodyProps = {
options?: EmailInputOptions
options: EmailInputOptions
onOptionsChange: (options: EmailInputOptions) => void
}
@ -14,9 +14,9 @@ export const EmailInputSettingsBody = ({
onOptionsChange,
}: EmailInputSettingsBodyProps) => {
const handlePlaceholderChange = (placeholder: string) =>
onOptionsChange({ ...options, labels: { ...options?.labels, placeholder } })
onOptionsChange({ ...options, labels: { ...options.labels, placeholder } })
const handleButtonLabelChange = (button: string) =>
onOptionsChange({ ...options, labels: { ...options?.labels, button } })
onOptionsChange({ ...options, labels: { ...options.labels, button } })
const handleVariableChange = (variable?: Variable) =>
onOptionsChange({ ...options, variableId: variable?.id })
@ -28,7 +28,7 @@ export const EmailInputSettingsBody = ({
</FormLabel>
<DebouncedInput
id="placeholder"
initialValue={options?.labels?.placeholder ?? 'Type your email...'}
initialValue={options.labels.placeholder}
delay={100}
onChange={handlePlaceholderChange}
/>
@ -39,7 +39,7 @@ export const EmailInputSettingsBody = ({
</FormLabel>
<DebouncedInput
id="button"
initialValue={options?.labels?.button ?? 'Send'}
initialValue={options.labels.button}
delay={100}
onChange={handleButtonLabelChange}
/>
@ -49,7 +49,7 @@ export const EmailInputSettingsBody = ({
Save answer in a variable:
</FormLabel>
<VariableSearchInput
initialVariableId={options?.variableId}
initialVariableId={options.variableId}
onSelectVariable={handleVariableChange}
/>
</Stack>

View File

@ -10,7 +10,7 @@ import {
Tag,
} from '@chakra-ui/react'
import { DebouncedInput } from 'components/shared/DebouncedInput'
import { InputWithVariableButton } from 'components/shared/InputWithVariableButton'
import { InputWithVariableButton } from 'components/shared/TextboxWithVariableButton/InputWithVariableButton'
import { GoogleAnalyticsOptions } from 'models'
import React from 'react'

View File

@ -1,6 +1,6 @@
import { Stack } from '@chakra-ui/react'
import { DropdownList } from 'components/shared/DropdownList'
import { InputWithVariableButton } from 'components/shared/InputWithVariableButton'
import { InputWithVariableButton } from 'components/shared/TextboxWithVariableButton/InputWithVariableButton'
import { TableListItemProps } from 'components/shared/TableList'
import { Cell } from 'models'

View File

@ -1,5 +1,5 @@
import { FormLabel, HStack, Stack } from '@chakra-ui/react'
import { SmartNumberInput } from 'components/settings/SmartNumberInput'
import { SmartNumberInput } from 'components/shared/SmartNumberInput'
import { DebouncedInput } from 'components/shared/DebouncedInput'
import { VariableSearchInput } from 'components/shared/VariableSearchInput'
import { NumberInputOptions, Variable } from 'models'
@ -7,7 +7,7 @@ import React from 'react'
import { removeUndefinedFields } from 'services/utils'
type NumberInputSettingsBodyProps = {
options?: NumberInputOptions
options: NumberInputOptions
onOptionsChange: (options: NumberInputOptions) => void
}
@ -16,9 +16,9 @@ export const NumberInputSettingsBody = ({
onOptionsChange,
}: NumberInputSettingsBodyProps) => {
const handlePlaceholderChange = (placeholder: string) =>
onOptionsChange({ ...options, labels: { ...options?.labels, placeholder } })
onOptionsChange({ ...options, labels: { ...options.labels, placeholder } })
const handleButtonLabelChange = (button: string) =>
onOptionsChange({ ...options, labels: { ...options?.labels, button } })
onOptionsChange({ ...options, labels: { ...options.labels, button } })
const handleMinChange = (min?: number) =>
onOptionsChange(removeUndefinedFields({ ...options, min }))
const handleMaxChange = (max?: number) =>
@ -36,7 +36,7 @@ export const NumberInputSettingsBody = ({
</FormLabel>
<DebouncedInput
id="placeholder"
initialValue={options?.labels?.placeholder ?? 'Type your answer...'}
initialValue={options.labels.placeholder}
delay={100}
onChange={handlePlaceholderChange}
/>
@ -58,7 +58,7 @@ export const NumberInputSettingsBody = ({
</FormLabel>
<SmartNumberInput
id="min"
initialValue={options?.min}
value={options.min}
onValueChange={handleMinChange}
/>
</HStack>
@ -68,7 +68,7 @@ export const NumberInputSettingsBody = ({
</FormLabel>
<SmartNumberInput
id="max"
initialValue={options?.max}
value={options.max}
onValueChange={handleMaxChange}
/>
</HStack>
@ -78,7 +78,7 @@ export const NumberInputSettingsBody = ({
</FormLabel>
<SmartNumberInput
id="step"
initialValue={options?.step}
value={options.step}
onValueChange={handleStepChange}
/>
</HStack>
@ -87,7 +87,7 @@ export const NumberInputSettingsBody = ({
Save answer in a variable:
</FormLabel>
<VariableSearchInput
initialVariableId={options?.variableId}
initialVariableId={options.variableId}
onSelectVariable={handleVariableChange}
/>
</Stack>

View File

@ -5,7 +5,7 @@ import { EmailInputOptions, Variable } from 'models'
import React from 'react'
type PhoneNumberSettingsBodyProps = {
options?: EmailInputOptions
options: EmailInputOptions
onOptionsChange: (options: EmailInputOptions) => void
}
@ -14,9 +14,9 @@ export const PhoneNumberSettingsBody = ({
onOptionsChange,
}: PhoneNumberSettingsBodyProps) => {
const handlePlaceholderChange = (placeholder: string) =>
onOptionsChange({ ...options, labels: { ...options?.labels, placeholder } })
onOptionsChange({ ...options, labels: { ...options.labels, placeholder } })
const handleButtonLabelChange = (button: string) =>
onOptionsChange({ ...options, labels: { ...options?.labels, button } })
onOptionsChange({ ...options, labels: { ...options.labels, button } })
const handleVariableChange = (variable?: Variable) =>
onOptionsChange({ ...options, variableId: variable?.id })
@ -28,7 +28,7 @@ export const PhoneNumberSettingsBody = ({
</FormLabel>
<DebouncedInput
id="placeholder"
initialValue={options?.labels?.placeholder ?? 'Your phone number...'}
initialValue={options.labels.placeholder}
delay={100}
onChange={handlePlaceholderChange}
/>
@ -39,7 +39,7 @@ export const PhoneNumberSettingsBody = ({
</FormLabel>
<DebouncedInput
id="button"
initialValue={options?.labels?.button ?? 'Send'}
initialValue={options.labels.button}
delay={100}
onChange={handleButtonLabelChange}
/>
@ -49,7 +49,7 @@ export const PhoneNumberSettingsBody = ({
Save answer in a variable:
</FormLabel>
<VariableSearchInput
initialVariableId={options?.variableId}
initialVariableId={options.variableId}
onSelectVariable={handleVariableChange}
/>
</Stack>

View File

@ -5,14 +5,14 @@ import { RedirectOptions } from 'models'
import React from 'react'
type Props = {
options?: RedirectOptions
options: RedirectOptions
onOptionsChange: (options: RedirectOptions) => void
}
export const RedirectSettings = ({ options, onOptionsChange }: Props) => {
const handleUrlChange = (url?: string) => onOptionsChange({ ...options, url })
const handleIsNewTabChange = (isNewTab?: boolean) =>
const handleIsNewTabChange = (isNewTab: boolean) =>
onOptionsChange({ ...options, isNewTab })
return (
@ -23,7 +23,7 @@ export const RedirectSettings = ({ options, onOptionsChange }: Props) => {
</FormLabel>
<DebouncedInput
id="tracking-id"
initialValue={options?.url ?? ''}
initialValue={options.url ?? ''}
placeholder="Type a URL..."
delay={100}
onChange={handleUrlChange}
@ -32,7 +32,7 @@ export const RedirectSettings = ({ options, onOptionsChange }: Props) => {
<SwitchWithLabel
id="new-tab"
label="Open in new tab?"
initialValue={options?.isNewTab ?? false}
initialValue={options.isNewTab}
onCheckChange={handleIsNewTabChange}
/>
</Stack>

View File

@ -5,7 +5,7 @@ import { SetVariableOptions, Variable } from 'models'
import React from 'react'
type Props = {
options?: SetVariableOptions
options: SetVariableOptions
onOptionsChange: (options: SetVariableOptions) => void
}
@ -26,7 +26,7 @@ export const SetVariableSettingsBody = ({
</FormLabel>
<VariableSearchInput
onSelectVariable={handleVariableChange}
initialVariableId={options?.variableId}
initialVariableId={options.variableId}
id="variable-search"
/>
</Stack>
@ -36,7 +36,7 @@ export const SetVariableSettingsBody = ({
</FormLabel>
<DebouncedTextarea
id="expression"
initialValue={options?.expressionToEvaluate ?? ''}
initialValue={options.expressionToEvaluate ?? ''}
delay={100}
onChange={handleExpressionChange}
/>

View File

@ -6,7 +6,7 @@ import { TextInputOptions, Variable } from 'models'
import React from 'react'
type TextInputSettingsBodyProps = {
options?: TextInputOptions
options: TextInputOptions
onOptionsChange: (options: TextInputOptions) => void
}
@ -15,9 +15,9 @@ export const TextInputSettingsBody = ({
onOptionsChange,
}: TextInputSettingsBodyProps) => {
const handlePlaceholderChange = (placeholder: string) =>
onOptionsChange({ ...options, labels: { ...options?.labels, placeholder } })
onOptionsChange({ ...options, labels: { ...options.labels, placeholder } })
const handleButtonLabelChange = (button: string) =>
onOptionsChange({ ...options, labels: { ...options?.labels, button } })
onOptionsChange({ ...options, labels: { ...options.labels, button } })
const handleLongChange = (isLong: boolean) =>
onOptionsChange({ ...options, isLong })
const handleVariableChange = (variable?: Variable) =>
@ -37,7 +37,7 @@ export const TextInputSettingsBody = ({
</FormLabel>
<DebouncedInput
id="placeholder"
initialValue={options?.labels?.placeholder ?? 'Type your answer...'}
initialValue={options.labels.placeholder}
delay={100}
onChange={handlePlaceholderChange}
/>
@ -48,7 +48,7 @@ export const TextInputSettingsBody = ({
</FormLabel>
<DebouncedInput
id="button"
initialValue={options?.labels?.button ?? 'Send'}
initialValue={options.labels.button}
delay={100}
onChange={handleButtonLabelChange}
/>
@ -58,7 +58,7 @@ export const TextInputSettingsBody = ({
Save answer in a variable:
</FormLabel>
<VariableSearchInput
initialVariableId={options?.variableId}
initialVariableId={options.variableId}
onSelectVariable={handleVariableChange}
/>
</Stack>

View File

@ -5,7 +5,7 @@ import { UrlInputOptions, Variable } from 'models'
import React from 'react'
type UrlInputSettingsBodyProps = {
options?: UrlInputOptions
options: UrlInputOptions
onOptionsChange: (options: UrlInputOptions) => void
}
@ -14,9 +14,9 @@ export const UrlInputSettingsBody = ({
onOptionsChange,
}: UrlInputSettingsBodyProps) => {
const handlePlaceholderChange = (placeholder: string) =>
onOptionsChange({ ...options, labels: { ...options?.labels, placeholder } })
onOptionsChange({ ...options, labels: { ...options.labels, placeholder } })
const handleButtonLabelChange = (button: string) =>
onOptionsChange({ ...options, labels: { ...options?.labels, button } })
onOptionsChange({ ...options, labels: { ...options.labels, button } })
const handleVariableChange = (variable?: Variable) =>
onOptionsChange({ ...options, variableId: variable?.id })
@ -28,7 +28,7 @@ export const UrlInputSettingsBody = ({
</FormLabel>
<DebouncedInput
id="placeholder"
initialValue={options?.labels?.placeholder ?? 'Type your URL...'}
initialValue={options.labels.placeholder}
delay={100}
onChange={handlePlaceholderChange}
/>
@ -39,7 +39,7 @@ export const UrlInputSettingsBody = ({
</FormLabel>
<DebouncedInput
id="button"
initialValue={options?.labels?.button ?? 'Send'}
initialValue={options.labels.button}
delay={100}
onChange={handleButtonLabelChange}
/>
@ -49,7 +49,7 @@ export const UrlInputSettingsBody = ({
Save answer in a variable:
</FormLabel>
<VariableSearchInput
initialVariableId={options?.variableId}
initialVariableId={options.variableId}
onSelectVariable={handleVariableChange}
/>
</Stack>

View File

@ -1,5 +1,5 @@
import { Stack, FormControl, FormLabel } from '@chakra-ui/react'
import { InputWithVariableButton } from 'components/shared/InputWithVariableButton'
import { InputWithVariableButton } from 'components/shared/TextboxWithVariableButton/InputWithVariableButton'
import { TableListItemProps } from 'components/shared/TableList'
import { KeyValue } from 'models'

View File

@ -10,7 +10,7 @@ import {
Stack,
useToast,
} from '@chakra-ui/react'
import { InputWithVariableButton } from 'components/shared/InputWithVariableButton'
import { InputWithVariableButton } from 'components/shared/TextboxWithVariableButton/InputWithVariableButton'
import { useTypebot } from 'contexts/TypebotContext'
import {
HttpMethod,

View File

@ -103,7 +103,7 @@ export const StepNodeContent = ({ step }: Props) => {
return <ConditionNodeContent step={step} />
}
case LogicStepType.REDIRECT: {
if (!step.options) return <Text color={'gray.500'}>Configure...</Text>
if (!step.options.url) return <Text color={'gray.500'}>Configure...</Text>
return <Text isTruncated>Redirect to {step.options?.url}</Text>
}
case IntegrationStepType.GOOGLE_SHEETS: {