fix(editor): 🐛 Edge not properly connecting to step target
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { Coordinates, useGraph } from 'contexts/GraphContext'
|
import { Coordinates, useGraph } from 'contexts/GraphContext'
|
||||||
import React, { useMemo } from 'react'
|
import React, { useLayoutEffect, useMemo, useState } from 'react'
|
||||||
import {
|
import {
|
||||||
getAnchorsPosition,
|
getAnchorsPosition,
|
||||||
computeEdgePath,
|
computeEdgePath,
|
||||||
@@ -38,23 +38,22 @@ export const Edge = ({ edge }: { edge: EdgeProps }) => {
|
|||||||
getSourceEndpointId(edge)
|
getSourceEndpointId(edge)
|
||||||
),
|
),
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
[
|
[sourceBlockCoordinates?.y, edge, sourceEndpoints]
|
||||||
sourceBlockCoordinates?.x,
|
|
||||||
sourceBlockCoordinates?.y,
|
|
||||||
edge,
|
|
||||||
sourceEndpoints,
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
const targetTop = useMemo(
|
|
||||||
() => getEndpointTopOffset(targetEndpoints, graphOffsetY, edge?.to.stepId),
|
const [targetTop, setTargetTop] = useState(
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
getEndpointTopOffset(targetEndpoints, graphOffsetY, edge?.to.stepId)
|
||||||
[
|
|
||||||
targetBlockCoordinates?.x,
|
|
||||||
targetBlockCoordinates?.y,
|
|
||||||
edge?.to.stepId,
|
|
||||||
targetEndpoints,
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
setTargetTop(
|
||||||
|
getEndpointTopOffset(targetEndpoints, graphOffsetY, edge?.to.stepId)
|
||||||
|
)
|
||||||
|
}, [
|
||||||
|
targetBlockCoordinates?.y,
|
||||||
|
targetEndpoints,
|
||||||
|
graphOffsetY,
|
||||||
|
edge?.to.stepId,
|
||||||
|
])
|
||||||
|
|
||||||
const path = useMemo(() => {
|
const path = useMemo(() => {
|
||||||
if (!sourceBlockCoordinates || !targetBlockCoordinates || !sourceTop)
|
if (!sourceBlockCoordinates || !targetBlockCoordinates || !sourceTop)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { Block, DraggableStepType, PublicTypebot, Typebot } from 'models'
|
|||||||
import { generate } from 'short-uuid'
|
import { generate } from 'short-uuid'
|
||||||
import { AnswersCount } from 'services/analytics'
|
import { AnswersCount } from 'services/analytics'
|
||||||
import { useDebounce } from 'use-debounce'
|
import { useDebounce } from 'use-debounce'
|
||||||
|
import { DraggableCore, DraggableData, DraggableEvent } from 'react-draggable'
|
||||||
|
|
||||||
declare const window: { chrome: unknown | undefined }
|
declare const window: { chrome: unknown | undefined }
|
||||||
|
|
||||||
@@ -115,34 +116,46 @@ export const Graph = ({
|
|||||||
useEventListener('mouseup', handleMouseUp, graphContainerRef.current)
|
useEventListener('mouseup', handleMouseUp, graphContainerRef.current)
|
||||||
useEventListener('mouseup', handleGlobalMouseUp)
|
useEventListener('mouseup', handleGlobalMouseUp)
|
||||||
useEventListener('click', handleClick, editorContainerRef.current)
|
useEventListener('click', handleClick, editorContainerRef.current)
|
||||||
|
|
||||||
|
const onDrag = (event: DraggableEvent, draggableData: DraggableData) => {
|
||||||
|
const { deltaX, deltaY } = draggableData
|
||||||
|
setGraphPosition({
|
||||||
|
x: graphPosition.x + deltaX,
|
||||||
|
y: graphPosition.y + deltaY,
|
||||||
|
scale: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<DraggableCore onDrag={onDrag}>
|
||||||
ref={graphContainerRef}
|
|
||||||
onMouseDown={handleMouseDown}
|
|
||||||
onMouseMove={handleMouseMove}
|
|
||||||
position="relative"
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<Flex
|
<Flex
|
||||||
flex="1"
|
ref={graphContainerRef}
|
||||||
w="full"
|
onMouseDown={handleMouseDown}
|
||||||
h="full"
|
onMouseMove={handleMouseMove}
|
||||||
position="absolute"
|
position="relative"
|
||||||
style={{
|
{...props}
|
||||||
transform,
|
|
||||||
}}
|
|
||||||
willChange="transform"
|
|
||||||
transformOrigin="0px 0px 0px"
|
|
||||||
>
|
>
|
||||||
<Edges
|
<Flex
|
||||||
edges={typebot?.edges ?? []}
|
flex="1"
|
||||||
answersCounts={answersCounts}
|
w="full"
|
||||||
onUnlockProPlanClick={onUnlockProPlanClick}
|
h="full"
|
||||||
/>
|
position="absolute"
|
||||||
{typebot?.blocks.map((block, idx) => (
|
style={{
|
||||||
<BlockNode block={block as Block} blockIndex={idx} key={block.id} />
|
transform,
|
||||||
))}
|
}}
|
||||||
|
willChange="transform"
|
||||||
|
transformOrigin="0px 0px 0px"
|
||||||
|
>
|
||||||
|
<Edges
|
||||||
|
edges={typebot?.edges ?? []}
|
||||||
|
answersCounts={answersCounts}
|
||||||
|
onUnlockProPlanClick={onUnlockProPlanClick}
|
||||||
|
/>
|
||||||
|
{typebot?.blocks.map((block, idx) => (
|
||||||
|
<BlockNode block={block as Block} blockIndex={idx} key={block.id} />
|
||||||
|
))}
|
||||||
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</DraggableCore>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import {
|
|||||||
EditableInput,
|
EditableInput,
|
||||||
EditablePreview,
|
EditablePreview,
|
||||||
Stack,
|
Stack,
|
||||||
useEventListener,
|
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import React, { useEffect, useRef, useState } from 'react'
|
import React, { useEffect, useRef, useState } from 'react'
|
||||||
import { Block } from 'models'
|
import { Block } from 'models'
|
||||||
@@ -16,6 +15,7 @@ import { ContextMenu } from 'components/shared/ContextMenu'
|
|||||||
import { BlockNodeContextMenu } from './BlockNodeContextMenu'
|
import { BlockNodeContextMenu } from './BlockNodeContextMenu'
|
||||||
import { useDebounce } from 'use-debounce'
|
import { useDebounce } from 'use-debounce'
|
||||||
import { setMultipleRefs } from 'services/utils'
|
import { setMultipleRefs } from 'services/utils'
|
||||||
|
import { DraggableCore, DraggableData, DraggableEvent } from 'react-draggable'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
block: Block
|
block: Block
|
||||||
@@ -67,25 +67,7 @@ export const BlockNode = ({ block, blockIndex }: Props) => {
|
|||||||
|
|
||||||
const handleMouseDown = (e: React.MouseEvent) => {
|
const handleMouseDown = (e: React.MouseEvent) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
setIsMouseDown(true)
|
|
||||||
}
|
}
|
||||||
const handleMouseUp = () => {
|
|
||||||
setIsMouseDown(false)
|
|
||||||
}
|
|
||||||
useEventListener('mouseup', handleMouseUp)
|
|
||||||
|
|
||||||
const handleMouseMove = (event: MouseEvent) => {
|
|
||||||
if (!isMouseDown) return
|
|
||||||
const { movementX, movementY } = event
|
|
||||||
|
|
||||||
if (!blockCoordinates) return
|
|
||||||
updateBlockCoordinates(block.id, {
|
|
||||||
x: blockCoordinates.x + movementX,
|
|
||||||
y: blockCoordinates.y + movementY,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
useEventListener('mousemove', handleMouseMove)
|
|
||||||
|
|
||||||
const handleMouseEnter = () => {
|
const handleMouseEnter = () => {
|
||||||
if (isReadOnly) return
|
if (isReadOnly) return
|
||||||
@@ -101,61 +83,71 @@ export const BlockNode = ({ block, blockIndex }: Props) => {
|
|||||||
if (connectingIds) setConnectingIds({ ...connectingIds, target: undefined })
|
if (connectingIds) setConnectingIds({ ...connectingIds, target: undefined })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onDrag = (event: DraggableEvent, draggableData: DraggableData) => {
|
||||||
|
const { deltaX, deltaY } = draggableData
|
||||||
|
updateBlockCoordinates(block.id, {
|
||||||
|
x: blockCoordinates.x + deltaX,
|
||||||
|
y: blockCoordinates.y + deltaY,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContextMenu<HTMLDivElement>
|
<ContextMenu<HTMLDivElement>
|
||||||
renderMenu={() => <BlockNodeContextMenu blockIndex={blockIndex} />}
|
renderMenu={() => <BlockNodeContextMenu blockIndex={blockIndex} />}
|
||||||
isDisabled={isReadOnly}
|
isDisabled={isReadOnly}
|
||||||
>
|
>
|
||||||
{(ref, isOpened) => (
|
{(ref, isOpened) => (
|
||||||
<Stack
|
<DraggableCore onDrag={onDrag} onMouseDown={(e) => e.stopPropagation()}>
|
||||||
ref={setMultipleRefs([ref, blockRef])}
|
<Stack
|
||||||
data-testid="block"
|
ref={setMultipleRefs([ref, blockRef])}
|
||||||
p="4"
|
data-testid="block"
|
||||||
rounded="lg"
|
p="4"
|
||||||
bgColor="blue.50"
|
rounded="lg"
|
||||||
backgroundImage="linear-gradient(rgb(235, 239, 244), rgb(231, 234, 241))"
|
bgColor="blue.50"
|
||||||
borderWidth="2px"
|
backgroundImage="linear-gradient(rgb(235, 239, 244), rgb(231, 234, 241))"
|
||||||
borderColor={
|
borderWidth="2px"
|
||||||
isConnecting || isOpened || isPreviewing ? 'blue.400' : 'white'
|
borderColor={
|
||||||
}
|
isConnecting || isOpened || isPreviewing ? 'blue.400' : 'white'
|
||||||
w="300px"
|
}
|
||||||
transition="border 300ms, box-shadow 200ms"
|
w="300px"
|
||||||
pos="absolute"
|
transition="border 300ms, box-shadow 200ms"
|
||||||
style={{
|
pos="absolute"
|
||||||
transform: `translate(${blockCoordinates?.x ?? 0}px, ${
|
style={{
|
||||||
blockCoordinates?.y ?? 0
|
transform: `translate(${blockCoordinates?.x ?? 0}px, ${
|
||||||
}px)`,
|
blockCoordinates?.y ?? 0
|
||||||
}}
|
}px)`,
|
||||||
onMouseDown={handleMouseDown}
|
}}
|
||||||
onMouseEnter={handleMouseEnter}
|
onMouseDown={handleMouseDown}
|
||||||
onMouseLeave={handleMouseLeave}
|
onMouseEnter={handleMouseEnter}
|
||||||
cursor={isMouseDown ? 'grabbing' : 'pointer'}
|
onMouseLeave={handleMouseLeave}
|
||||||
boxShadow="0px 0px 0px 1px #e9edf3;"
|
cursor={isMouseDown ? 'grabbing' : 'pointer'}
|
||||||
_hover={{ shadow: 'lg' }}
|
boxShadow="0px 0px 0px 1px #e9edf3;"
|
||||||
>
|
_hover={{ shadow: 'lg' }}
|
||||||
<Editable
|
|
||||||
defaultValue={block.title}
|
|
||||||
onSubmit={handleTitleSubmit}
|
|
||||||
fontWeight="semibold"
|
|
||||||
pointerEvents={isReadOnly ? 'none' : 'auto'}
|
|
||||||
>
|
>
|
||||||
<EditablePreview
|
<Editable
|
||||||
_hover={{ bgColor: 'gray.300' }}
|
defaultValue={block.title}
|
||||||
px="1"
|
onSubmit={handleTitleSubmit}
|
||||||
userSelect={'none'}
|
fontWeight="semibold"
|
||||||
/>
|
pointerEvents={isReadOnly ? 'none' : 'auto'}
|
||||||
<EditableInput minW="0" px="1" />
|
>
|
||||||
</Editable>
|
<EditablePreview
|
||||||
{typebot && (
|
_hover={{ bgColor: 'gray.300' }}
|
||||||
<StepNodesList
|
px="1"
|
||||||
blockId={block.id}
|
userSelect={'none'}
|
||||||
steps={block.steps}
|
/>
|
||||||
blockIndex={blockIndex}
|
<EditableInput minW="0" px="1" />
|
||||||
blockRef={ref}
|
</Editable>
|
||||||
isStartBlock={isStartBlock}
|
{typebot && (
|
||||||
/>
|
<StepNodesList
|
||||||
)}
|
blockId={block.id}
|
||||||
</Stack>
|
steps={block.steps}
|
||||||
|
blockIndex={blockIndex}
|
||||||
|
blockRef={ref}
|
||||||
|
isStartBlock={isStartBlock}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
</DraggableCore>
|
||||||
)}
|
)}
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -66,6 +66,7 @@
|
|||||||
"qs": "^6.10.3",
|
"qs": "^6.10.3",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
|
"react-draggable": "^4.4.4",
|
||||||
"react-table": "^7.7.0",
|
"react-table": "^7.7.0",
|
||||||
"short-uuid": "^4.2.0",
|
"short-uuid": "^4.2.0",
|
||||||
"slate": "^0.72.8",
|
"slate": "^0.72.8",
|
||||||
|
|||||||
@@ -6,15 +6,6 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||||||
if (req.method === 'POST') {
|
if (req.method === 'POST') {
|
||||||
const { from, port, isTlsEnabled, username, password, host, to } =
|
const { from, port, isTlsEnabled, username, password, host, to } =
|
||||||
JSON.parse(req.body) as SmtpCredentialsData & { to: string }
|
JSON.parse(req.body) as SmtpCredentialsData & { to: string }
|
||||||
console.log({
|
|
||||||
host,
|
|
||||||
port,
|
|
||||||
secure: isTlsEnabled ?? undefined,
|
|
||||||
auth: {
|
|
||||||
user: username,
|
|
||||||
pass: password,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
const transporter = createTransport({
|
const transporter = createTransport({
|
||||||
host,
|
host,
|
||||||
port,
|
port,
|
||||||
|
|||||||
10
yarn.lock
10
yarn.lock
@@ -11547,7 +11547,7 @@ prompts@^2.4.1, prompts@^2.4.2:
|
|||||||
kleur "^3.0.3"
|
kleur "^3.0.3"
|
||||||
sisteransi "^1.0.5"
|
sisteransi "^1.0.5"
|
||||||
|
|
||||||
prop-types@^15.6.2, prop-types@^15.7.2:
|
prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2:
|
||||||
version "15.8.1"
|
version "15.8.1"
|
||||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
|
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
|
||||||
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
|
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
|
||||||
@@ -11817,6 +11817,14 @@ react-dom@17.0.2, react-dom@^17.0.2:
|
|||||||
object-assign "^4.1.1"
|
object-assign "^4.1.1"
|
||||||
scheduler "^0.20.2"
|
scheduler "^0.20.2"
|
||||||
|
|
||||||
|
react-draggable@^4.4.4:
|
||||||
|
version "4.4.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.4.4.tgz#5b26d9996be63d32d285a426f41055de87e59b2f"
|
||||||
|
integrity sha512-6e0WdcNLwpBx/YIDpoyd2Xb04PB0elrDrulKUgdrIlwuYvxh5Ok9M+F8cljm8kPXXs43PmMzek9RrB1b7mLMqA==
|
||||||
|
dependencies:
|
||||||
|
clsx "^1.1.1"
|
||||||
|
prop-types "^15.6.0"
|
||||||
|
|
||||||
react-error-overlay@^6.0.10:
|
react-error-overlay@^6.0.10:
|
||||||
version "6.0.10"
|
version "6.0.10"
|
||||||
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.10.tgz#0fe26db4fa85d9dbb8624729580e90e7159a59a6"
|
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.10.tgz#0fe26db4fa85d9dbb8624729580e90e7159a59a6"
|
||||||
|
|||||||
Reference in New Issue
Block a user