Skip to content

Commit

Permalink
refactor(graph): ♻️ Add Edges table in Typebot
Browse files Browse the repository at this point in the history
  • Loading branch information
baptisteArno committed Jan 19, 2022
1 parent ab34f95 commit 8bbd897
Show file tree
Hide file tree
Showing 59 changed files with 1,106 additions and 979 deletions.
28 changes: 16 additions & 12 deletions apps/builder/components/analytics/graph/Edges/Edge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,31 @@ import {
getAnchorsPosition,
computeEdgePath,
getEndpointTopOffset,
getSourceEndpointId,
} from 'services/graph'

type Props = { stepId: string }
type Props = { edgeId: string }

export const Edge = ({ stepId }: Props) => {
export const Edge = ({ edgeId }: Props) => {
const { typebot } = useAnalyticsGraph()
const step = typebot?.steps.byId[stepId]
const edge = typebot?.edges.byId[edgeId]
const { sourceEndpoints, targetEndpoints, graphPosition } = useGraph()
const [sourceTop, setSourceTop] = useState(
getEndpointTopOffset(graphPosition, sourceEndpoints, stepId)
getEndpointTopOffset(
graphPosition,
sourceEndpoints,
getSourceEndpointId(edge)
)
)
const [targetTop, setTargetTop] = useState(
getEndpointTopOffset(graphPosition, sourceEndpoints, step?.target?.stepId)
getEndpointTopOffset(graphPosition, sourceEndpoints, edge?.to.stepId)
)

useEffect(() => {
const newSourceTop = getEndpointTopOffset(
graphPosition,
sourceEndpoints,
stepId
getSourceEndpointId(edge)
)
const sensibilityThreshold = 10
const newSourceTopIsTooClose =
Expand All @@ -39,7 +44,7 @@ export const Edge = ({ stepId }: Props) => {
const newTargetTop = getEndpointTopOffset(
graphPosition,
targetEndpoints,
step?.target?.stepId
edge?.to.stepId
)
const sensibilityThreshold = 10
const newSourceTopIsTooClose =
Expand All @@ -51,15 +56,14 @@ export const Edge = ({ stepId }: Props) => {
}, [graphPosition])

const { sourceBlock, targetBlock } = useMemo(() => {
if (!typebot) return {}
if (!step?.target) return {}
const targetBlock = typebot.blocks.byId[step.target.blockId]
const sourceBlock = typebot.blocks.byId[step.blockId]
if (!typebot || !edge) return {}
const targetBlock = typebot.blocks.byId[edge.to.blockId]
const sourceBlock = typebot.blocks.byId[edge.from.blockId]
return {
sourceBlock,
targetBlock,
}
}, [step?.blockId, step?.target, typebot])
}, [edge, typebot])

const path = useMemo(() => {
if (!sourceBlock || !targetBlock) return ``
Expand Down
14 changes: 3 additions & 11 deletions apps/builder/components/analytics/graph/Edges/Edges.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { chakra } from '@chakra-ui/system'
import { useAnalyticsGraph } from 'contexts/AnalyticsGraphProvider'
import React, { useMemo } from 'react'
import React from 'react'
import { AnswersCount } from 'services/analytics'
import { isDefined } from 'utils'
import { DropOffBlock } from '../blocks/DropOffBlock'
import { DropOffEdge } from './DropOffEdge'
import { Edge } from './Edge'
Expand All @@ -12,13 +11,6 @@ type Props = { answersCounts?: AnswersCount[] }
export const Edges = ({ answersCounts }: Props) => {
const { typebot } = useAnalyticsGraph()

const stepIdsWithTarget: string[] = useMemo(() => {
if (!typebot) return []
return typebot.steps.allIds.filter((stepId) =>
isDefined(typebot.steps.byId[stepId].target)
)
}, [typebot])

return (
<>
<chakra.svg
Expand All @@ -29,8 +21,8 @@ export const Edges = ({ answersCounts }: Props) => {
left="0"
top="0"
>
{stepIdsWithTarget.map((stepId) => (
<Edge key={stepId} stepId={stepId} />
{typebot?.edges.allIds.map((edgeId) => (
<Edge key={edgeId} edgeId={edgeId} />
))}
<marker
id={'arrow'}
Expand Down
12 changes: 7 additions & 5 deletions apps/builder/components/analytics/graph/blocks/DropOffBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useAnalyticsGraph } from 'contexts/AnalyticsGraphProvider'
import React, { useMemo } from 'react'
import { AnswersCount } from 'services/analytics'
import { computeSourceCoordinates } from 'services/graph'
import { isDefined } from 'utils'

type Props = {
answersCounts: AnswersCount[]
Expand All @@ -20,11 +21,12 @@ export const DropOffBlock = ({ answersCounts, blockId }: Props) => {
const { totalDroppedUser, dropOffRate } = useMemo(() => {
if (!typebot || totalAnswers === undefined)
return { previousTotal: undefined, dropOffRate: undefined }
const previousBlockIds = typebot.blocks.allIds.filter(() =>
typebot.steps.allIds.find(
(sId) => typebot.steps.byId[sId].target?.blockId === blockId
)
)
const previousBlockIds = typebot.edges.allIds
.map((edgeId) => {
const edge = typebot.edges.byId[edgeId]
return edge.to.blockId === blockId ? edge.from.blockId : undefined
})
.filter((blockId) => isDefined(blockId))
const previousTotal = answersCounts
.filter((a) => previousBlockIds.includes(a.blockId))
.reduce((prev, acc) => acc.totalAnswers + prev, 0)
Expand Down
13 changes: 6 additions & 7 deletions apps/builder/components/board/graph/BlockNode/BlockNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,17 @@ type Props = {
}

export const BlockNode = ({ block }: Props) => {
const { connectingIds, setConnectingIds, previewingIds } = useGraph()
const { connectingIds, setConnectingIds, previewingEdgeId } = useGraph()
const { typebot, updateBlock } = useTypebot()
const { setMouseOverBlockId } = useDnd()
const { draggedStep, draggedStepType } = useDnd()
const [isMouseDown, setIsMouseDown] = useState(false)
const [isConnecting, setIsConnecting] = useState(false)
const isPreviewing = useMemo(
() =>
previewingIds.sourceId === block.id ||
previewingIds.targetId === block.id,
[block.id, previewingIds.sourceId, previewingIds.targetId]
)
const isPreviewing = useMemo(() => {
if (!previewingEdgeId) return
const edge = typebot?.edges.byId[previewingEdgeId]
return edge?.to.blockId === block.id || edge?.from.blockId === block.id
}, [block.id, previewingEdgeId, typebot?.edges.byId])

useEffect(() => {
setIsConnecting(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export const ChoiceItemNode = ({
source={{
blockId: typebot.steps.byId[item.stepId].blockId,
stepId: item.stepId,
choiceItemId: item.id,
nodeId: item.id,
}}
pos="absolute"
right="15px"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,7 @@ export const SettingsPopoverContent = ({ step, onExpandClick }: Props) => {
<PopoverContent onMouseDown={handleMouseDown} pos="relative">
<PopoverArrow />
<PopoverBody
px="6"
pb="6"
pt="4"
p="6"
overflowY="scroll"
maxH="400px"
ref={ref}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { Box, BoxProps, Flex } from '@chakra-ui/react'
import { ConnectingSourceIds, useGraph } from 'contexts/GraphContext'
import { useGraph } from 'contexts/GraphContext'
import { Source } from 'models'
import React, { MouseEvent, useEffect, useRef } from 'react'

export const SourceEndpoint = ({
source,
...props
}: BoxProps & {
source: ConnectingSourceIds
source: Source
}) => {
const { setConnectingIds, addSourceEndpoint: addEndpoint } = useGraph()
const ref = useRef<HTMLDivElement | null>(null)
Expand All @@ -18,8 +19,7 @@ export const SourceEndpoint = ({

useEffect(() => {
if (!ref.current) return
const id =
source.choiceItemId ?? source.stepId + (source.conditionType ?? '')
const id = source.nodeId ?? source.stepId + (source.conditionType ?? '')
addEndpoint({
id,
ref,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import {
Box,
Flex,
HStack,
Popover,
PopoverTrigger,
useDisclosure,
useEventListener,
} from '@chakra-ui/react'
import React, { useEffect, useMemo, useState } from 'react'
import { Block, DraggableStep, Step } from 'models'
import React, { useEffect, useState } from 'react'
import { DraggableStep, Step } from 'models'
import { useGraph } from 'contexts/GraphContext'
import { StepIcon } from 'components/board/StepTypesList/StepIcon'
import {
isDefined,
isInputStep,
isLogicStep,
isTextBubbleStep,
Expand Down Expand Up @@ -50,7 +48,7 @@ export const StepNode = ({
}) => {
const { query } = useRouter()
const { setConnectingIds, connectingIds } = useGraph()
const { moveStep, typebot } = useTypebot()
const { moveStep } = useTypebot()
const [isConnecting, setIsConnecting] = useState(false)
const [mouseDownEvent, setMouseDownEvent] =
useState<{ absolute: Coordinates; relative: Coordinates }>()
Expand Down Expand Up @@ -132,30 +130,6 @@ export const StepNode = ({
setIsEditing(false)
}

const connectedStubPosition: 'right' | 'left' | undefined = useMemo(() => {
if (!typebot) return
const currentBlock = typebot.blocks?.byId[step.blockId]
const isDragginConnectorFromCurrentBlock =
connectingIds?.source.blockId === currentBlock?.id &&
connectingIds?.target?.blockId
const targetBlockId = isDragginConnectorFromCurrentBlock
? connectingIds.target?.blockId
: step.target?.blockId
const targetedBlock = targetBlockId && typebot.blocks.byId[targetBlockId]
return targetedBlock
? targetedBlock.graphCoordinates.x <
(currentBlock as Block).graphCoordinates.x
? 'left'
: 'right'
: undefined
}, [
typebot,
step.blockId,
step.target?.blockId,
connectingIds?.source.blockId,
connectingIds?.target?.blockId,
])

return isEditing && isTextBubbleStep(step) ? (
<TextEditor
stepId={step.id}
Expand Down Expand Up @@ -184,16 +158,6 @@ export const StepNode = ({
data-testid={`step-${step.id}`}
w="full"
>
{connectedStubPosition === 'left' && (
<Box
h="2px"
pos="absolute"
left="-18px"
top="25px"
w="18px"
bgColor="blue.500"
/>
)}
<HStack
flex="1"
userSelect="none"
Expand Down Expand Up @@ -225,24 +189,6 @@ export const StepNode = ({
/>
)}
</HStack>

{isDefined(connectedStubPosition) &&
hasDefaultConnector(step) &&
isConnectable && (
<Box
h="2px"
pos="absolute"
right={
connectedStubPosition === 'left' ? undefined : '-18px'
}
left={
connectedStubPosition === 'left' ? '-18px' : undefined
}
top="25px"
w="18px"
bgColor="gray.500"
/>
)}
</Flex>
</PopoverTrigger>
{hasPopover(step) && (
Expand Down
26 changes: 6 additions & 20 deletions apps/builder/components/board/graph/Edges/DrawingEdge.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { useEventListener } from '@chakra-ui/hooks'
import assert from 'assert'
import { headerHeight } from 'components/shared/TypebotHeader/TypebotHeader'
import { useGraph, ConnectingIds } from 'contexts/GraphContext'
import { useTypebot } from 'contexts/TypebotContext/TypebotContext'
import { Step, Target } from 'models'
import { Target } from 'models'
import React, { useMemo, useState } from 'react'
import {
computeConnectingEdgePath,
Expand All @@ -18,7 +19,7 @@ export const DrawingEdge = () => {
sourceEndpoints,
targetEndpoints,
} = useGraph()
const { typebot, updateStep, updateChoiceItem } = useTypebot()
const { typebot, createEdge } = useTypebot()
const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 })

const sourceBlock = useMemo(
Expand All @@ -32,7 +33,7 @@ export const DrawingEdge = () => {
return getEndpointTopOffset(
graphPosition,
sourceEndpoints,
connectingIds.source.choiceItemId ??
connectingIds.source.nodeId ??
connectingIds.source.stepId + (connectingIds.source.conditionType ?? '')
)
// eslint-disable-next-line react-hooks/exhaustive-deps
Expand Down Expand Up @@ -79,23 +80,8 @@ export const DrawingEdge = () => {
})

const createNewEdge = (connectingIds: ConnectingIds) => {
if (connectingIds.source.choiceItemId) {
updateChoiceItem(connectingIds.source.choiceItemId, {
target: connectingIds.target,
})
} else if (connectingIds.source.conditionType === 'true') {
updateStep(connectingIds.source.stepId, {
trueTarget: connectingIds.target,
} as Step)
} else if (connectingIds.source.conditionType === 'false') {
updateStep(connectingIds.source.stepId, {
falseTarget: connectingIds.target,
} as Step)
} else {
updateStep(connectingIds.source.stepId, {
target: connectingIds.target,
})
}
assert(connectingIds.target)
createEdge({ from: connectingIds.source, to: connectingIds.target })
}

if ((mousePosition.x === 0 && mousePosition.y === 0) || !connectingIds)
Expand Down
Loading

0 comments on commit 8bbd897

Please sign in to comment.