refactor(graph): ♻️ Add Edges table in Typebot
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
import { Block, Step, Table, Target } from 'models'
|
||||
import { Block, Source, Step, Table, Target } from 'models'
|
||||
import {
|
||||
createContext,
|
||||
Dispatch,
|
||||
@ -43,19 +43,10 @@ export type Node = Omit<Block, 'steps'> & {
|
||||
const graphPositionDefaultValue = { x: 400, y: 100, scale: 1 }
|
||||
|
||||
export type ConnectingIds = {
|
||||
source: ConnectingSourceIds
|
||||
source: Source
|
||||
target?: Target
|
||||
}
|
||||
|
||||
export type ConnectingSourceIds = {
|
||||
blockId: string
|
||||
stepId: string
|
||||
choiceItemId?: string
|
||||
conditionType?: 'true' | 'false'
|
||||
}
|
||||
|
||||
type PreviewingIdsProps = { sourceId?: string; targetId?: string }
|
||||
|
||||
type StepId = string
|
||||
type NodeId = string
|
||||
export type Endpoint = {
|
||||
@ -68,8 +59,8 @@ const graphContext = createContext<{
|
||||
setGraphPosition: Dispatch<SetStateAction<Position>>
|
||||
connectingIds: ConnectingIds | null
|
||||
setConnectingIds: Dispatch<SetStateAction<ConnectingIds | null>>
|
||||
previewingIds: PreviewingIdsProps
|
||||
setPreviewingIds: Dispatch<SetStateAction<PreviewingIdsProps>>
|
||||
previewingEdgeId?: string
|
||||
setPreviewingEdgeId: Dispatch<SetStateAction<string | undefined>>
|
||||
sourceEndpoints: Table<Endpoint>
|
||||
addSourceEndpoint: (endpoint: Endpoint) => void
|
||||
targetEndpoints: Table<Endpoint>
|
||||
@ -84,7 +75,7 @@ const graphContext = createContext<{
|
||||
export const GraphProvider = ({ children }: { children: ReactNode }) => {
|
||||
const [graphPosition, setGraphPosition] = useState(graphPositionDefaultValue)
|
||||
const [connectingIds, setConnectingIds] = useState<ConnectingIds | null>(null)
|
||||
const [previewingIds, setPreviewingIds] = useState<PreviewingIdsProps>({})
|
||||
const [previewingEdgeId, setPreviewingEdgeId] = useState<string>()
|
||||
const [sourceEndpoints, setSourceEndpoints] = useState<Table<Endpoint>>({
|
||||
byId: {},
|
||||
allIds: [],
|
||||
@ -115,8 +106,8 @@ export const GraphProvider = ({ children }: { children: ReactNode }) => {
|
||||
setGraphPosition,
|
||||
connectingIds,
|
||||
setConnectingIds,
|
||||
previewingIds,
|
||||
setPreviewingIds,
|
||||
previewingEdgeId,
|
||||
setPreviewingEdgeId,
|
||||
sourceEndpoints,
|
||||
targetEndpoints,
|
||||
addSourceEndpoint,
|
||||
|
@ -28,6 +28,7 @@ import { useImmer, Updater } from 'use-immer'
|
||||
import { stepsAction, StepsActions } from './actions/steps'
|
||||
import { choiceItemsAction, ChoiceItemsActions } from './actions/choiceItems'
|
||||
import { variablesAction, VariablesActions } from './actions/variables'
|
||||
import { edgesAction, EdgesActions } from './actions/edges'
|
||||
|
||||
type UpdateTypebotPayload = Partial<{
|
||||
theme: Theme
|
||||
@ -50,7 +51,8 @@ const typebotContext = createContext<
|
||||
} & BlocksActions &
|
||||
StepsActions &
|
||||
ChoiceItemsActions &
|
||||
VariablesActions
|
||||
VariablesActions &
|
||||
EdgesActions
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
>({})
|
||||
@ -211,6 +213,7 @@ export const TypebotContext = ({
|
||||
...stepsAction(setLocalTypebot as Updater<Typebot>),
|
||||
...choiceItemsAction(setLocalTypebot as Updater<Typebot>),
|
||||
...variablesAction(setLocalTypebot as Updater<Typebot>),
|
||||
...edgesAction(setLocalTypebot as Updater<Typebot>),
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
@ -3,6 +3,7 @@ import { WritableDraft } from 'immer/dist/internal'
|
||||
import { Block, DraggableStep, DraggableStepType, Typebot } from 'models'
|
||||
import { parseNewBlock } from 'services/typebots'
|
||||
import { Updater } from 'use-immer'
|
||||
import { deleteEdgeDraft } from './edges'
|
||||
import { createStepDraft, deleteStepDraft } from './steps'
|
||||
|
||||
export type BlocksActions = {
|
||||
@ -44,6 +45,7 @@ export const blocksActions = (setTypebot: Updater<Typebot>): BlocksActions => ({
|
||||
deleteBlock: (blockId: string) =>
|
||||
setTypebot((typebot) => {
|
||||
deleteStepsInsideBlock(typebot, blockId)
|
||||
deleteAssociatedEdges(typebot, blockId)
|
||||
deleteBlockDraft(typebot)(blockId)
|
||||
}),
|
||||
})
|
||||
@ -55,6 +57,16 @@ export const removeEmptyBlocks = (typebot: WritableDraft<Typebot>) => {
|
||||
emptyBlockIds.forEach(deleteBlockDraft(typebot))
|
||||
}
|
||||
|
||||
const deleteAssociatedEdges = (
|
||||
typebot: WritableDraft<Typebot>,
|
||||
blockId: string
|
||||
) => {
|
||||
typebot.edges.allIds.forEach((edgeId) => {
|
||||
if (typebot.edges.byId[edgeId].to.blockId === blockId)
|
||||
deleteEdgeDraft(typebot, edgeId)
|
||||
})
|
||||
}
|
||||
|
||||
const deleteStepsInsideBlock = (
|
||||
typebot: WritableDraft<Typebot>,
|
||||
blockId: string
|
||||
|
69
apps/builder/contexts/TypebotContext/actions/edges.ts
Normal file
69
apps/builder/contexts/TypebotContext/actions/edges.ts
Normal file
@ -0,0 +1,69 @@
|
||||
import { Typebot, Edge, ConditionStep } from 'models'
|
||||
import { Updater } from 'use-immer'
|
||||
import { WritableDraft } from 'immer/dist/types/types-external'
|
||||
import { generate } from 'short-uuid'
|
||||
|
||||
export type EdgesActions = {
|
||||
createEdge: (edge: Omit<Edge, 'id'>) => void
|
||||
updateEdge: (edgeId: string, updates: Partial<Omit<Edge, 'id'>>) => void
|
||||
deleteEdge: (edgeId: string) => void
|
||||
}
|
||||
|
||||
export const edgesAction = (setTypebot: Updater<Typebot>): EdgesActions => ({
|
||||
createEdge: (edge: Omit<Edge, 'id'>) => {
|
||||
setTypebot((typebot) => {
|
||||
const newEdge = {
|
||||
...edge,
|
||||
id: generate(),
|
||||
}
|
||||
if (edge.from.nodeId) {
|
||||
deleteEdgeDraft(
|
||||
typebot,
|
||||
typebot.choiceItems.byId[edge.from.nodeId].edgeId
|
||||
)
|
||||
typebot.choiceItems.byId[edge.from.nodeId].edgeId = newEdge.id
|
||||
} else if (edge.from.conditionType === 'true') {
|
||||
deleteEdgeDraft(
|
||||
typebot,
|
||||
(typebot.steps.byId[edge.from.stepId] as ConditionStep).trueEdgeId
|
||||
)
|
||||
;(typebot.steps.byId[edge.from.stepId] as ConditionStep).trueEdgeId =
|
||||
newEdge.id
|
||||
} else if (edge.from.conditionType === 'false') {
|
||||
deleteEdgeDraft(
|
||||
typebot,
|
||||
(typebot.steps.byId[edge.from.stepId] as ConditionStep).falseEdgeId
|
||||
)
|
||||
;(typebot.steps.byId[edge.from.stepId] as ConditionStep).falseEdgeId =
|
||||
newEdge.id
|
||||
} else {
|
||||
deleteEdgeDraft(typebot, typebot.steps.byId[edge.from.stepId].edgeId)
|
||||
typebot.steps.byId[edge.from.stepId].edgeId = newEdge.id
|
||||
}
|
||||
typebot.edges.byId[newEdge.id] = newEdge
|
||||
typebot.edges.allIds.push(newEdge.id)
|
||||
})
|
||||
},
|
||||
updateEdge: (edgeId: string, updates: Partial<Omit<Edge, 'id'>>) =>
|
||||
setTypebot((typebot) => {
|
||||
typebot.edges.byId[edgeId] = {
|
||||
...typebot.edges.byId[edgeId],
|
||||
...updates,
|
||||
}
|
||||
}),
|
||||
deleteEdge: (edgeId: string) => {
|
||||
setTypebot((typebot) => {
|
||||
deleteEdgeDraft(typebot, edgeId)
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
export const deleteEdgeDraft = (
|
||||
typebot: WritableDraft<Typebot>,
|
||||
edgeId?: string
|
||||
) => {
|
||||
if (!edgeId) return
|
||||
delete typebot.edges.byId[edgeId]
|
||||
const index = typebot.edges.allIds.indexOf(edgeId)
|
||||
if (index !== -1) typebot.edges.allIds.splice(index, 1)
|
||||
}
|
@ -11,6 +11,7 @@ import { removeEmptyBlocks } from './blocks'
|
||||
import { WritableDraft } from 'immer/dist/types/types-external'
|
||||
import { createChoiceItemDraft, deleteChoiceItemDraft } from './choiceItems'
|
||||
import { isChoiceInput } from 'utils'
|
||||
import { deleteEdgeDraft } from './edges'
|
||||
|
||||
export type StepsActions = {
|
||||
createStep: (
|
||||
@ -50,12 +51,23 @@ export const stepsAction = (setTypebot: Updater<Typebot>): StepsActions => ({
|
||||
setTypebot((typebot) => {
|
||||
const step = typebot.steps.byId[stepId]
|
||||
if (isChoiceInput(step)) deleteChoiceItemsInsideStep(typebot, step)
|
||||
deleteAssociatedEdges(typebot, stepId)
|
||||
removeStepIdFromBlock(typebot, stepId)
|
||||
deleteStepDraft(typebot, stepId)
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
const deleteAssociatedEdges = (
|
||||
typebot: WritableDraft<Typebot>,
|
||||
stepId: string
|
||||
) => {
|
||||
typebot.edges.allIds.forEach((edgeId) => {
|
||||
if (typebot.edges.byId[edgeId].from.stepId === stepId)
|
||||
deleteEdgeDraft(typebot, edgeId)
|
||||
})
|
||||
}
|
||||
|
||||
const removeStepIdFromBlock = (
|
||||
typebot: WritableDraft<Typebot>,
|
||||
stepId: string
|
||||
|
Reference in New Issue
Block a user