2
0

refactor: ♻️ Rename step to block

This commit is contained in:
Baptiste Arnaud
2022-06-11 07:27:38 +02:00
parent 8751766d0e
commit 2df8338505
297 changed files with 4292 additions and 3989 deletions

View File

@ -0,0 +1,156 @@
import { Text } from '@chakra-ui/react'
import {
Block,
StartBlock,
BubbleBlockType,
InputBlockType,
LogicBlockType,
IntegrationBlockType,
BlockIndices,
} from 'models'
import { isChoiceInput, isInputBlock } from 'utils'
import { ItemNodesList } from '../../ItemNode'
import {
EmbedBubbleContent,
SetVariableContent,
TextBubbleContent,
VideoBubbleContent,
WebhookContent,
WithVariableContent,
} from './contents'
import { ConfigureContent } from './contents/ConfigureContent'
import { ImageBubbleContent } from './contents/ImageBubbleContent'
import { PaymentInputContent } from './contents/PaymentInputContent'
import { PlaceholderContent } from './contents/PlaceholderContent'
import { RatingInputContent } from './contents/RatingInputContent'
import { SendEmailContent } from './contents/SendEmailContent'
import { TypebotLinkContent } from './contents/TypebotLinkContent'
import { ProviderWebhookContent } from './contents/ZapierContent'
type Props = {
block: Block | StartBlock
indices: BlockIndices
}
export const BlockNodeContent = ({ block, indices }: Props): JSX.Element => {
if (
isInputBlock(block) &&
!isChoiceInput(block) &&
block.options.variableId
) {
return <WithVariableContent block={block} />
}
switch (block.type) {
case BubbleBlockType.TEXT: {
return <TextBubbleContent block={block} />
}
case BubbleBlockType.IMAGE: {
return <ImageBubbleContent block={block} />
}
case BubbleBlockType.VIDEO: {
return <VideoBubbleContent block={block} />
}
case BubbleBlockType.EMBED: {
return <EmbedBubbleContent block={block} />
}
case InputBlockType.TEXT: {
return (
<PlaceholderContent
placeholder={block.options.labels.placeholder}
isLong={block.options.isLong}
/>
)
}
case InputBlockType.NUMBER:
case InputBlockType.EMAIL:
case InputBlockType.URL:
case InputBlockType.PHONE: {
return (
<PlaceholderContent placeholder={block.options.labels.placeholder} />
)
}
case InputBlockType.DATE: {
return <Text color={'gray.500'}>Pick a date...</Text>
}
case InputBlockType.CHOICE: {
return <ItemNodesList block={block} indices={indices} />
}
case InputBlockType.PAYMENT: {
return <PaymentInputContent block={block} />
}
case InputBlockType.RATING: {
return <RatingInputContent block={block} />
}
case LogicBlockType.SET_VARIABLE: {
return <SetVariableContent block={block} />
}
case LogicBlockType.CONDITION: {
return <ItemNodesList block={block} indices={indices} isReadOnly />
}
case LogicBlockType.REDIRECT: {
return (
<ConfigureContent
label={
block.options?.url ? `Redirect to ${block.options?.url}` : undefined
}
/>
)
}
case LogicBlockType.CODE: {
return (
<ConfigureContent
label={
block.options?.content ? `Run ${block.options?.name}` : undefined
}
/>
)
}
case LogicBlockType.TYPEBOT_LINK:
return <TypebotLinkContent block={block} />
case IntegrationBlockType.GOOGLE_SHEETS: {
return (
<ConfigureContent
label={
block.options && 'action' in block.options
? block.options.action
: undefined
}
/>
)
}
case IntegrationBlockType.GOOGLE_ANALYTICS: {
return (
<ConfigureContent
label={
block.options?.action
? `Track "${block.options?.action}" `
: undefined
}
/>
)
}
case IntegrationBlockType.WEBHOOK: {
return <WebhookContent block={block} />
}
case IntegrationBlockType.ZAPIER: {
return (
<ProviderWebhookContent block={block} configuredLabel="Trigger zap" />
)
}
case IntegrationBlockType.PABBLY_CONNECT:
case IntegrationBlockType.MAKE_COM: {
return (
<ProviderWebhookContent
block={block}
configuredLabel="Trigger scenario"
/>
)
}
case IntegrationBlockType.EMAIL: {
return <SendEmailContent block={block} />
}
case 'start': {
return <Text>Start</Text>
}
}
}

View File

@ -0,0 +1,10 @@
import React from 'react'
import { Text } from '@chakra-ui/react'
type Props = { label?: string }
export const ConfigureContent = ({ label }: Props) => (
<Text color={label ? 'currentcolor' : 'gray.500'} noOfLines={0}>
{label ?? 'Configure...'}
</Text>
)

View File

@ -0,0 +1,20 @@
import { Box, Text } from '@chakra-ui/react'
import { EmbedBubbleBlock } from 'models'
export const EmbedBubbleContent = ({ block }: { block: EmbedBubbleBlock }) => {
if (!block.content?.url) return <Text color="gray.500">Click to edit...</Text>
return (
<Box w="full" h="120px" pos="relative">
<iframe
id="embed-bubble-content"
src={block.content.url}
style={{
width: '100%',
height: '100%',
pointerEvents: 'none',
borderRadius: '5px',
}}
/>
</Box>
)
}

View File

@ -0,0 +1,21 @@
import { Box, Text, Image } from '@chakra-ui/react'
import { ImageBubbleBlock } from 'models'
export const ImageBubbleContent = ({ block }: { block: ImageBubbleBlock }) => {
const containsVariables =
block.content?.url?.includes('{{') && block.content.url.includes('}}')
return !block.content?.url ? (
<Text color={'gray.500'}>Click to edit...</Text>
) : (
<Box w="full">
<Image
src={
containsVariables ? '/images/dynamic-image.png' : block.content?.url
}
alt="Group image"
rounded="md"
objectFit="cover"
/>
</Box>
)
}

View File

@ -0,0 +1,20 @@
import { Text } from '@chakra-ui/react'
import { PaymentInputBlock } from 'models'
type Props = {
block: PaymentInputBlock
}
export const PaymentInputContent = ({ block }: Props) => {
if (
!block.options.amount ||
!block.options.credentialsId ||
!block.options.currency
)
return <Text color="gray.500">Configure...</Text>
return (
<Text noOfLines={0} pr="6">
Collect {block.options.amount} {block.options.currency}
</Text>
)
}

View File

@ -0,0 +1,10 @@
import React from 'react'
import { Text } from '@chakra-ui/react'
type Props = { placeholder: string; isLong?: boolean }
export const PlaceholderContent = ({ placeholder, isLong }: Props) => (
<Text color={'gray.500'} h={isLong ? '100px' : 'auto'}>
{placeholder}
</Text>
)

View File

@ -0,0 +1,12 @@
import { Text } from '@chakra-ui/react'
import { RatingInputBlock } from 'models'
type Props = {
block: RatingInputBlock
}
export const RatingInputContent = ({ block }: Props) => (
<Text noOfLines={0} pr="6">
Rate from 1 to {block.options.length}
</Text>
)

View File

@ -0,0 +1,23 @@
import { Tag, Text, Wrap, WrapItem } from '@chakra-ui/react'
import { SendEmailBlock } from 'models'
type Props = {
block: SendEmailBlock
}
export const SendEmailContent = ({ block }: Props) => {
if (block.options.recipients.length === 0)
return <Text color="gray.500">Configure...</Text>
return (
<Wrap noOfLines={2} pr="6">
<WrapItem>
<Text>Send email to</Text>
</WrapItem>
{block.options.recipients.map((to) => (
<WrapItem key={to}>
<Tag>{to}</Tag>
</WrapItem>
))}
</Wrap>
)
}

View File

@ -0,0 +1,18 @@
import { Text } from '@chakra-ui/react'
import { useTypebot } from 'contexts/TypebotContext'
import { SetVariableBlock } from 'models'
import { byId } from 'utils'
export const SetVariableContent = ({ block }: { block: SetVariableBlock }) => {
const { typebot } = useTypebot()
const variableName =
typebot?.variables.find(byId(block.options.variableId))?.name ?? ''
const expression = block.options.expressionToEvaluate ?? ''
return (
<Text color={'gray.500'} noOfLines={2}>
{variableName === '' && expression === ''
? 'Click to edit...'
: `${variableName} ${expression ? `= ${expression}` : ``}`}
</Text>
)
}

View File

@ -0,0 +1,28 @@
import { Flex } from '@chakra-ui/react'
import { useTypebot } from 'contexts/TypebotContext'
import { TextBubbleBlock } from 'models'
import React from 'react'
import { parseVariableHighlight } from 'services/utils'
type Props = {
block: TextBubbleBlock
}
export const TextBubbleContent = ({ block }: Props) => {
const { typebot } = useTypebot()
if (!typebot) return <></>
return (
<Flex
w="90%"
flexDir={'column'}
opacity={block.content.html === '' ? '0.5' : '1'}
className="slate-html-container"
dangerouslySetInnerHTML={{
__html:
block.content.html === ''
? `<p>Click to edit...</p>`
: parseVariableHighlight(block.content.html, typebot),
}}
/>
)
}

View File

@ -0,0 +1,44 @@
import { TypebotLinkBlock } from 'models'
import React from 'react'
import { Tag, Text } from '@chakra-ui/react'
import { useTypebot } from 'contexts/TypebotContext'
import { byId } from 'utils'
type Props = {
block: TypebotLinkBlock
}
export const TypebotLinkContent = ({ block }: Props) => {
const { linkedTypebots, typebot } = useTypebot()
const isCurrentTypebot =
typebot &&
(block.options.typebotId === typebot.id ||
block.options.typebotId === 'current')
const linkedTypebot = isCurrentTypebot
? typebot
: linkedTypebots?.find(byId(block.options.typebotId))
const blockTitle = linkedTypebot?.groups.find(
byId(block.options.groupId)
)?.title
if (!block.options.typebotId)
return <Text color="gray.500">Configure...</Text>
return (
<Text>
Jump{' '}
{blockTitle ? (
<>
to <Tag>{blockTitle}</Tag>
</>
) : (
<></>
)}{' '}
{!isCurrentTypebot ? (
<>
in <Tag colorScheme="blue">{linkedTypebot?.name}</Tag>
</>
) : (
<></>
)}
</Text>
)
}

View File

@ -0,0 +1,52 @@
import { Box, Text } from '@chakra-ui/react'
import { VideoBubbleBlock, VideoBubbleContentType } from 'models'
export const VideoBubbleContent = ({ block }: { block: VideoBubbleBlock }) => {
if (!block.content?.url || !block.content.type)
return <Text color="gray.500">Click to edit...</Text>
switch (block.content.type) {
case VideoBubbleContentType.URL:
return (
<Box w="full" h="120px" pos="relative">
<video
key={block.content.url}
controls
style={{
width: '100%',
height: '100%',
position: 'absolute',
left: '0',
top: '0',
borderRadius: '10px',
}}
>
<source src={block.content.url} />
</video>
</Box>
)
case VideoBubbleContentType.VIMEO:
case VideoBubbleContentType.YOUTUBE: {
const baseUrl =
block.content.type === VideoBubbleContentType.VIMEO
? 'https://player.vimeo.com/video'
: 'https://www.youtube.com/embed'
return (
<Box w="full" h="120px" pos="relative">
<iframe
src={`${baseUrl}/${block.content.id}`}
allowFullScreen
style={{
width: '100%',
height: '100%',
position: 'absolute',
left: '0',
top: '0',
borderRadius: '10px',
pointerEvents: 'none',
}}
/>
</Box>
)
}
}
}

View File

@ -0,0 +1,20 @@
import { Text } from '@chakra-ui/react'
import { useTypebot } from 'contexts/TypebotContext'
import { WebhookBlock } from 'models'
import { byId } from 'utils'
type Props = {
block: WebhookBlock
}
export const WebhookContent = ({ block: { webhookId } }: Props) => {
const { webhooks } = useTypebot()
const webhook = webhooks.find(byId(webhookId))
if (!webhook?.url) return <Text color="gray.500">Configure...</Text>
return (
<Text noOfLines={2} pr="6">
{webhook.method} {webhook.url}
</Text>
)
}

View File

@ -0,0 +1,31 @@
import { InputBlock } from 'models'
import { chakra, Text } from '@chakra-ui/react'
import React from 'react'
import { useTypebot } from 'contexts/TypebotContext'
import { byId } from 'utils'
type Props = {
block: InputBlock
}
export const WithVariableContent = ({ block }: Props) => {
const { typebot } = useTypebot()
const variableName = typebot?.variables.find(
byId(block.options.variableId)
)?.name
return (
<Text>
Collect{' '}
<chakra.span
bgColor="orange.400"
color="white"
rounded="md"
py="0.5"
px="1"
>
{variableName}
</chakra.span>
</Text>
)
}

View File

@ -0,0 +1,43 @@
import { Text } from '@chakra-ui/react'
import { useTypebot } from 'contexts/TypebotContext'
import {
defaultWebhookAttributes,
MakeComBlock,
PabblyConnectBlock,
Webhook,
ZapierBlock,
} from 'models'
import { useEffect } from 'react'
import { byId, isNotDefined } from 'utils'
type Props = {
block: ZapierBlock | MakeComBlock | PabblyConnectBlock
configuredLabel: string
}
export const ProviderWebhookContent = ({ block, configuredLabel }: Props) => {
const { webhooks, typebot, updateWebhook } = useTypebot()
const webhook = webhooks.find(byId(block.webhookId))
useEffect(() => {
if (!typebot) return
if (!webhook) {
const { webhookId } = block
const newWebhook = {
id: webhookId,
...defaultWebhookAttributes,
typebotId: typebot.id,
} as Webhook
updateWebhook(webhookId, newWebhook)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
if (isNotDefined(webhook?.body))
return <Text color="gray.500">Configure...</Text>
return (
<Text noOfLines={0} pr="6">
{webhook?.url ? configuredLabel : 'Disabled'}
</Text>
)
}

View File

@ -0,0 +1,6 @@
export * from './SetVariableContent'
export * from './WithVariableContent'
export * from './VideoBubbleContent'
export * from './WebhookContent'
export * from './TextBubbleContent'
export * from './EmbedBubbleContent'

View File

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