2
0

feat(bubbles): Add image bubble

This commit is contained in:
Baptiste Arnaud
2022-01-20 16:14:47 +01:00
parent c43fd1d386
commit 2d178978ef
33 changed files with 848 additions and 142 deletions

View File

@ -9,6 +9,7 @@ import {
FilterIcon,
FlagIcon,
GlobeIcon,
ImageIcon,
NumberIcon,
PhoneIcon,
TextIcon,
@ -29,6 +30,8 @@ export const StepIcon = ({ type, ...props }: StepIconProps) => {
switch (type) {
case BubbleStepType.TEXT:
return <ChatIcon {...props} />
case BubbleStepType.IMAGE:
return <ImageIcon {...props} />
case InputStepType.TEXT:
return <TextIcon {...props} />
case InputStepType.NUMBER:

View File

@ -16,6 +16,8 @@ export const StepTypeLabel = ({ type }: Props) => {
case InputStepType.TEXT: {
return <Text>Text</Text>
}
case BubbleStepType.IMAGE:
return <Text>Image</Text>
case InputStepType.NUMBER: {
return <Text>Number</Text>
}

View File

@ -43,7 +43,6 @@ export const StepTypesList = () => {
const x = e.clientX - rect.left
const y = e.clientY - rect.top
setRelativeCoordinates({ x, y })
console.log({ x: rect.left, y: rect.top })
setDraggedStepType(type)
}

View File

@ -0,0 +1,54 @@
import {
Portal,
PopoverContent,
PopoverArrow,
PopoverBody,
} from '@chakra-ui/react'
import { ImagePopoverContent } from 'components/shared/ImageUploadContent'
import { useTypebot } from 'contexts/TypebotContext'
import {
BubbleStep,
BubbleStepType,
ImageBubbleContent,
ImageBubbleStep,
TextBubbleStep,
} from 'models'
import { useRef } from 'react'
type Props = {
step: Exclude<BubbleStep, TextBubbleStep>
}
export const ContentPopover = ({ step }: Props) => {
const ref = useRef<HTMLDivElement | null>(null)
const handleMouseDown = (e: React.MouseEvent) => e.stopPropagation()
return (
<Portal>
<PopoverContent onMouseDown={handleMouseDown} w="500px">
<PopoverArrow />
<PopoverBody ref={ref} shadow="lg">
<StepContent step={step} />
</PopoverBody>
</PopoverContent>
</Portal>
)
}
export const StepContent = ({ step }: Props) => {
const { updateStep } = useTypebot()
const handleContentChange = (content: ImageBubbleContent) =>
updateStep(step.id, { content } as Partial<ImageBubbleStep>)
const handleNewImageSubmit = (url: string) => handleContentChange({ url })
switch (step.type) {
case BubbleStepType.IMAGE: {
return (
<ImagePopoverContent
url={step.content?.url}
onSubmit={handleNewImageSubmit}
/>
)
}
}
}

View File

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

View File

@ -15,6 +15,7 @@ import {
LogicStepType,
Step,
StepOptions,
TextBubbleStep,
} from 'models'
import { useRef } from 'react'
import {
@ -33,7 +34,7 @@ import { RedirectSettings } from './bodies/RedirectSettings'
import { SetVariableSettingsBody } from './bodies/SetVariableSettingsBody'
type Props = {
step: Step
step: Exclude<Step, TextBubbleStep>
onExpandClick: () => void
}

View File

@ -7,15 +7,10 @@ import {
useEventListener,
} from '@chakra-ui/react'
import React, { useEffect, useState } from 'react'
import { DraggableStep, Step } from 'models'
import { BubbleStep, DraggableStep, Step, TextBubbleStep } from 'models'
import { useGraph } from 'contexts/GraphContext'
import { StepIcon } from 'components/board/StepTypesList/StepIcon'
import {
isInputStep,
isLogicStep,
isTextBubbleStep,
isIntegrationStep,
} from 'utils'
import { isBubbleStep, isTextBubbleStep } from 'utils'
import { Coordinates } from '@dnd-kit/core/dist/types'
import { TextEditor } from './TextEditor/TextEditor'
import { StepNodeContent } from './StepNodeContent'
@ -29,6 +24,7 @@ import { TargetEndpoint } from './TargetEndpoint'
import { useRouter } from 'next/router'
import { SettingsModal } from './SettingsPopoverContent/SettingsModal'
import { StepSettings } from './SettingsPopoverContent/SettingsPopoverContent'
import { ContentPopover } from './ContentPopover'
export const StepNode = ({
step,
@ -185,15 +181,16 @@ export const StepNode = ({
}}
pos="absolute"
right="15px"
top="18px"
bottom="18px"
/>
)}
</HStack>
</Flex>
</PopoverTrigger>
{hasPopover(step) && (
{hasSettingsPopover(step) && (
<SettingsPopoverContent step={step} onExpandClick={onModalOpen} />
)}
{hasContentPopover(step) && <ContentPopover step={step} />}
<SettingsModal isOpen={isModalOpen} onClose={onModalClose}>
<StepSettings step={step} />
</SettingsModal>
@ -203,5 +200,10 @@ export const StepNode = ({
)
}
const hasPopover = (step: Step) =>
isInputStep(step) || isLogicStep(step) || isIntegrationStep(step)
const hasSettingsPopover = (step: Step): step is Exclude<Step, BubbleStep> =>
!isBubbleStep(step)
const hasContentPopover = (
step: Step
): step is Exclude<BubbleStep, TextBubbleStep> =>
isBubbleStep(step) && !isTextBubbleStep(step)

View File

@ -1,4 +1,4 @@
import { Flex, HStack, Stack, Tag, Text } from '@chakra-ui/react'
import { Box, Flex, HStack, Image, Stack, Tag, Text } from '@chakra-ui/react'
import { useTypebot } from 'contexts/TypebotContext'
import {
Step,
@ -34,6 +34,20 @@ export const StepNodeContent = ({ step }: Props) => {
/>
)
}
case BubbleStepType.IMAGE: {
return !step.content?.url ? (
<Text color={'gray.500'}>Click to edit...</Text>
) : (
<Box w="full">
<Image
src={step.content?.url}
alt="Step image"
rounded="md"
objectFit="cover"
/>
</Box>
)
}
case InputStepType.TEXT: {
return (
<Text color={'gray.500'}>

View File

@ -12,7 +12,7 @@ import { useTypebot } from 'contexts/TypebotContext/TypebotContext'
import { BaseSelection, createEditor, Transforms } from 'slate'
import { ToolBar } from './ToolBar'
import { parseHtmlStringToPlainText } from 'services/utils'
import { TextStep, Variable } from 'models'
import { TextBubbleStep, Variable } from 'models'
import { VariableSearchInput } from 'components/shared/VariableSearchInput'
import { ReactEditor } from 'slate-react'
@ -87,7 +87,7 @@ export const TextEditor = ({
richText: value,
plainText: parseHtmlStringToPlainText(html),
},
} as TextStep)
} as TextBubbleStep)
}
const handleMouseDown = (e: React.MouseEvent) => {