Skip to content

Commit

Permalink
feat(editor): ⚡️ Optimize graph navigation
Browse files Browse the repository at this point in the history
  • Loading branch information
baptisteArno committed Jun 26, 2022
1 parent d7b9bda commit fc4db57
Show file tree
Hide file tree
Showing 17 changed files with 485 additions and 299 deletions.
22 changes: 17 additions & 5 deletions apps/builder/components/shared/Graph/Edges/DrawingEdge.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { useEventListener } from '@chakra-ui/hooks'
import assert from 'assert'
import { useGraph, ConnectingIds } from 'contexts/GraphContext'
import {
useGraph,
ConnectingIds,
Coordinates,
useGroupsCoordinates,
} from 'contexts/GraphContext'
import { useTypebot } from 'contexts/TypebotContext/TypebotContext'
import { colors } from 'libs/theme'
import React, { useMemo, useState } from 'react'
Expand All @@ -17,10 +22,10 @@ export const DrawingEdge = () => {
connectingIds,
sourceEndpoints,
targetEndpoints,
groupsCoordinates,
} = useGraph()
const { groupsCoordinates } = useGroupsCoordinates()
const { createEdge } = useTypebot()
const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 })
const [mousePosition, setMousePosition] = useState<Coordinates | null>(null)

const sourceGroupCoordinates =
groupsCoordinates && groupsCoordinates[connectingIds?.source.groupId ?? '']
Expand Down Expand Up @@ -50,7 +55,7 @@ export const DrawingEdge = () => {
}, [connectingIds, targetEndpoints])

const path = useMemo(() => {
if (!sourceTop || !sourceGroupCoordinates) return ``
if (!sourceTop || !sourceGroupCoordinates || !mousePosition) return ``

return targetGroupCoordinates
? computeConnectingEdgePath({
Expand All @@ -75,6 +80,10 @@ export const DrawingEdge = () => {
])

const handleMouseMove = (e: MouseEvent) => {
if (!connectingIds) {
if (mousePosition) setMousePosition(null)
return
}
const coordinates = {
x: (e.clientX - graphPosition.x) / graphPosition.scale,
y: (e.clientY - graphPosition.y) / graphPosition.scale,
Expand All @@ -92,7 +101,10 @@ export const DrawingEdge = () => {
createEdge({ from: connectingIds.source, to: connectingIds.target })
}

if ((mousePosition.x === 0 && mousePosition.y === 0) || !connectingIds)
if (
(mousePosition && mousePosition.x === 0 && mousePosition.y === 0) ||
!connectingIds
)
return <></>
return (
<path
Expand Down
5 changes: 3 additions & 2 deletions apps/builder/components/shared/Graph/Edges/DropOffEdge.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { VStack, Tag, Text, Tooltip } from '@chakra-ui/react'
import { useGraph } from 'contexts/GraphContext'
import { useGraph, useGroupsCoordinates } from 'contexts/GraphContext'
import { useTypebot } from 'contexts/TypebotContext'
import { useWorkspace } from 'contexts/WorkspaceContext'
import React, { useMemo } from 'react'
Expand All @@ -24,7 +24,8 @@ export const DropOffEdge = ({
onUnlockProPlanClick,
}: Props) => {
const { workspace } = useWorkspace()
const { sourceEndpoints, groupsCoordinates, graphPosition } = useGraph()
const { groupsCoordinates } = useGroupsCoordinates()
const { sourceEndpoints, graphPosition } = useGraph()
const { publishedTypebot } = useTypebot()

const isUserOnFreePlan = isFreePlan(workspace)
Expand Down
13 changes: 10 additions & 3 deletions apps/builder/components/shared/Graph/Edges/Edge.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { Coordinates, useGraph } from 'contexts/GraphContext'
import {
Coordinates,
useGraph,
useGroupsCoordinates,
} from 'contexts/GraphContext'
import React, { useEffect, useLayoutEffect, useMemo, useState } from 'react'
import {
getAnchorsPosition,
Expand All @@ -19,17 +23,20 @@ export type AnchorsPositionProps = {
totalSegments: number
}

export const Edge = ({ edge }: { edge: EdgeProps }) => {
type Props = {
edge: EdgeProps
}
export const Edge = ({ edge }: Props) => {
const { deleteEdge } = useTypebot()
const {
previewingEdge,
sourceEndpoints,
targetEndpoints,
groupsCoordinates,
graphPosition,
isReadOnly,
setPreviewingEdge,
} = useGraph()
const { groupsCoordinates } = useGroupsCoordinates()
const [isMouseOver, setIsMouseOver] = useState(false)
const { isOpen, onOpen, onClose } = useDisclosure()
const [edgeMenuPosition, setEdgeMenuPosition] = useState({ x: 0, y: 0 })
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BoxProps, Flex } from '@chakra-ui/react'
import { useGraph } from 'contexts/GraphContext'
import { useGraph, useGroupsCoordinates } from 'contexts/GraphContext'
import { Source } from 'models'
import React, { MouseEvent, useEffect, useRef, useState } from 'react'

Expand All @@ -10,12 +10,9 @@ export const SourceEndpoint = ({
source: Source
}) => {
const [ranOnce, setRanOnce] = useState(false)
const {
setConnectingIds,
addSourceEndpoint,
groupsCoordinates,
previewingEdge,
} = useGraph()
const { setConnectingIds, addSourceEndpoint, previewingEdge } = useGraph()

const { groupsCoordinates } = useGroupsCoordinates()
const ref = useRef<HTMLDivElement | null>(null)

const handleMouseDown = (e: MouseEvent<HTMLDivElement>) => {
Expand Down
24 changes: 15 additions & 9 deletions apps/builder/components/shared/Graph/Graph.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { Flex, FlexProps, useEventListener } from '@chakra-ui/react'
import React, { useRef, useMemo, useEffect, useState } from 'react'
import React, { useRef, useMemo, useEffect, useState, useCallback } from 'react'
import {
blockWidth,
Coordinates,
graphPositionDefaultValue,
useGraph,
useGroupsCoordinates,
} from 'contexts/GraphContext'
import { useBlockDnd } from 'contexts/GraphDndContext'
import { useTypebot } from 'contexts/TypebotContext/TypebotContext'
import { DraggableBlockType, PublicTypebot, Typebot } from 'models'
import { AnswersCount } from 'services/analytics'
import { useDebounce } from 'use-debounce'
import { DraggableCore, DraggableData, DraggableEvent } from 'react-draggable'
import GraphContent from './GraphContent'
import GraphElements from './GraphElements'
import cuid from 'cuid'
import { headerHeight } from '../TypebotHeader'
import { useUser } from 'contexts/UserContext'
Expand All @@ -29,7 +30,7 @@ export const Graph = ({
onUnlockProPlanClick,
...props
}: {
typebot?: Typebot | PublicTypebot
typebot: Typebot | PublicTypebot
answersCounts?: AnswersCount[]
onUnlockProPlanClick?: () => void
} & FlexProps) => {
Expand All @@ -47,10 +48,10 @@ export const Graph = ({
const {
setGraphPosition: setGlobalGraphPosition,
setOpenedBlockId,
updateGroupCoordinates,
setPreviewingEdge,
connectingIds,
} = useGraph()
const { updateGroupCoordinates } = useGroupsCoordinates()
const [graphPosition, setGraphPosition] = useState(graphPositionDefaultValue)
const [debouncedGraphPosition] = useDebounce(graphPosition, 200)
const transform = useMemo(
Expand Down Expand Up @@ -177,13 +178,16 @@ export const Graph = ({
useEventListener('mouseup', handleMouseUp, graphContainerRef.current)
useEventListener('click', handleClick, editorContainerRef.current)
useEventListener('mousemove', handleMouseMove)

// eslint-disable-next-line react-hooks/exhaustive-deps
const zoomIn = useCallback(() => zoom(zoomButtonsScaleBlock), [])
// eslint-disable-next-line react-hooks/exhaustive-deps
const zoomOut = useCallback(() => zoom(-zoomButtonsScaleBlock), [])

return (
<DraggableCore onDrag={onDrag} enableUserSelectHack={false}>
<Flex ref={graphContainerRef} position="relative" {...props}>
<ZoomButtons
onZoomIn={() => zoom(zoomButtonsScaleBlock)}
onZoomOut={() => zoom(-zoomButtonsScaleBlock)}
/>
<ZoomButtons onZoomIn={zoomIn} onZoomOut={zoomOut} />
<Flex
flex="1"
w="full"
Expand All @@ -195,7 +199,9 @@ export const Graph = ({
willChange="transform"
transformOrigin="0px 0px 0px"
>
<GraphContent
<GraphElements
edges={typebot.edges}
groups={typebot.groups}
answersCounts={answersCounts}
onUnlockProPlanClick={onUnlockProPlanClick}
/>
Expand Down
31 changes: 0 additions & 31 deletions apps/builder/components/shared/Graph/GraphContent.tsx

This file was deleted.

33 changes: 33 additions & 0 deletions apps/builder/components/shared/Graph/GraphElements.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Edge, Group } from 'models'
import React, { memo } from 'react'
import { AnswersCount } from 'services/analytics'
import { Edges } from './Edges'
import { GroupNode } from './Nodes/GroupNode'

type Props = {
edges: Edge[]
groups: Group[]
answersCounts?: AnswersCount[]
onUnlockProPlanClick?: () => void
}
const GroupNodes = ({
edges,
groups,
answersCounts,
onUnlockProPlanClick,
}: Props) => {
return (
<>
<Edges
edges={edges}
answersCounts={answersCounts}
onUnlockProPlanClick={onUnlockProPlanClick}
/>
{groups.map((group, idx) => (
<GroupNode group={group} groupIndex={idx} key={group.id} />
))}
</>
)
}

export default memo(GroupNodes)
Loading

5 comments on commit fc4db57

@vercel
Copy link

@vercel vercel bot commented on fc4db57 Jun 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on fc4db57 Jun 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

builder-v2 – ./apps/builder

app.typebot.io
builder-v2-typebot-io.vercel.app
builder-v2-git-main-typebot-io.vercel.app

@vercel
Copy link

@vercel vercel bot commented on fc4db57 Jun 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

docs – ./apps/docs

docs.typebot.io
docs-typebot-io.vercel.app
docs-git-main-typebot-io.vercel.app

@vercel
Copy link

@vercel vercel bot commented on fc4db57 Jun 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on fc4db57 Jun 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

viewer-v2-alpha – ./apps/viewer

ar.nigerias.io
apo.nigerias.io
vhpage.cr8.ai
bot.aws.bj
sat.cr8.ai
an.nigerias.io
bt.id8rs.com
am.nigerias.io
apr.nigerias.io
aso.nigerias.io
chat.sureb4.com
games.klujo.com
eventhub.com.au
bot.piccinato.co
bot.upfunnel.art
stan.vselise.com
feedback.ofx.one
faqs.nigerias.io
sakuranembro.it
clo.closeer.work
voicehelp.cr8.ai
app.chatforms.net
gentleman-shop.fr
ov1.wpwakanda.com
zap.techadviser.in
ov3.wpwakanda.com
goalsettingbot.com
ov2.wpwakanda.com
this-is-a-test.com
bot.eventhub.com.au
bot.cotemeuplano.com
typebot.stillio.com
forms.webisharp.com
bot.ansuraniphone.my
bot.incusservices.com
bbutton.wpwakanda.com
chat.hayurihijab.com
abutton.wpwakanda.com
get.freebotoffer.xyz
bot.meuesocial.com.br
sbutton.wpwakanda.com
cdd.searchcube.com.sg
apply.ansuraniphone.my
chat.missarkansas.org
gcase.barrettamario.it
bbutton.wpwwakanda.com
felipewelington.com.br
info.clickasuransi.com
c23111azqw.nigerias.io
form.searchcube.com.sg
83242573.actualizar.xyz
view.onlinebotdemo.xyz
mainmenu.diddancing.com
kodawariab736.skeep.it
subfooter.wpwakanda.com
hunterbot.saleshunter.ai
91181264.your-access.one
form.sergiolimajr.com.br
type.opaulovieira.com.br
aibot.angrybranding.co.uk
bot.cabinrentalagency.com
boyfriend-breakup.riku.ai
piazzatorre.barrettamario.it
designguide.techyscouts.com
type.talitasouzamarques.com.br
type.dericsoncalari.com.br
onboarding.libertydreamcare.ie
bot.comercializadoraomicron.com
agendamento.sergiolimajr.com.br
bookings.littlepartymonkeys.com
personal-trainer.barrettamario.it
preagendamento.sergiolimajr.com.br
viewer-v2-alpha-git-main-typebot-io.vercel.app
viewer-v2-alpha-typebot-io.vercel.app
studiotecnicoimmobiliaremerelli.it

Please sign in to comment.