♻️ (bot) Change to features-centric folder structure
This commit is contained in:
committed by
Baptiste Arnaud
parent
a5c8a8a95c
commit
972094425a
83
packages/bot-engine/src/providers/AnswersProvider.tsx
Normal file
83
packages/bot-engine/src/providers/AnswersProvider.tsx
Normal file
@ -0,0 +1,83 @@
|
||||
import { safeStringify } from '@/features/variables'
|
||||
import {
|
||||
Answer,
|
||||
ResultValues,
|
||||
VariableWithUnknowValue,
|
||||
VariableWithValue,
|
||||
} from 'models'
|
||||
import React, { createContext, ReactNode, useContext, useState } from 'react'
|
||||
|
||||
const answersContext = createContext<{
|
||||
resultId?: string
|
||||
resultValues: ResultValues
|
||||
addAnswer: (
|
||||
answer: Answer & { uploadedFiles: boolean }
|
||||
) => Promise<void> | undefined
|
||||
updateVariables: (variables: VariableWithUnknowValue[]) => void
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
}>({})
|
||||
|
||||
export const AnswersProvider = ({
|
||||
children,
|
||||
resultId,
|
||||
onNewAnswer,
|
||||
onVariablesUpdated,
|
||||
}: {
|
||||
resultId?: string
|
||||
onNewAnswer: (
|
||||
answer: Answer & { uploadedFiles: boolean }
|
||||
) => Promise<void> | undefined
|
||||
onVariablesUpdated?: (variables: VariableWithValue[]) => void
|
||||
children: ReactNode
|
||||
}) => {
|
||||
const [resultValues, setResultValues] = useState<ResultValues>({
|
||||
answers: [],
|
||||
variables: [],
|
||||
createdAt: new Date().toISOString(),
|
||||
})
|
||||
|
||||
const addAnswer = (answer: Answer & { uploadedFiles: boolean }) => {
|
||||
setResultValues((resultValues) => ({
|
||||
...resultValues,
|
||||
answers: [...resultValues.answers, answer],
|
||||
}))
|
||||
return onNewAnswer && onNewAnswer(answer)
|
||||
}
|
||||
|
||||
const updateVariables = (newVariables: VariableWithUnknowValue[]) => {
|
||||
const serializedNewVariables = newVariables.map((variable) => ({
|
||||
...variable,
|
||||
value: safeStringify(variable.value),
|
||||
})) as VariableWithValue[]
|
||||
|
||||
setResultValues((resultValues) => {
|
||||
const updatedVariables = [
|
||||
...resultValues.variables.filter((v) =>
|
||||
serializedNewVariables.every((variable) => variable.id !== v.id)
|
||||
),
|
||||
...serializedNewVariables,
|
||||
]
|
||||
if (onVariablesUpdated) onVariablesUpdated(updatedVariables)
|
||||
return {
|
||||
...resultValues,
|
||||
variables: updatedVariables,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<answersContext.Provider
|
||||
value={{
|
||||
resultId,
|
||||
resultValues,
|
||||
addAnswer,
|
||||
updateVariables,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</answersContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export const useAnswers = () => useContext(answersContext)
|
28
packages/bot-engine/src/providers/ChatProvider.tsx
Normal file
28
packages/bot-engine/src/providers/ChatProvider.tsx
Normal file
@ -0,0 +1,28 @@
|
||||
import React, { createContext, ReactNode, useContext } from 'react'
|
||||
|
||||
const chatContext = createContext<{
|
||||
scroll: () => void
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
}>({})
|
||||
|
||||
export const ChatProvider = ({
|
||||
children,
|
||||
onScroll,
|
||||
}: {
|
||||
children: ReactNode
|
||||
onScroll: () => void
|
||||
}) => {
|
||||
const scroll = onScroll
|
||||
return (
|
||||
<chatContext.Provider
|
||||
value={{
|
||||
scroll,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</chatContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export const useChat = () => useContext(chatContext)
|
155
packages/bot-engine/src/providers/TypebotProvider.tsx
Normal file
155
packages/bot-engine/src/providers/TypebotProvider.tsx
Normal file
@ -0,0 +1,155 @@
|
||||
import { TypebotViewerProps } from '@/components/TypebotViewer'
|
||||
import { safeStringify } from '@/features/variables'
|
||||
import { sendEventToParent } from '@/utils/chat'
|
||||
import { Log } from 'db'
|
||||
import { Edge, PublicTypebot, Typebot } from 'models'
|
||||
import React, {
|
||||
createContext,
|
||||
ReactNode,
|
||||
useContext,
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react'
|
||||
|
||||
export type LinkedTypebot = Pick<
|
||||
PublicTypebot | Typebot,
|
||||
'id' | 'groups' | 'variables' | 'edges'
|
||||
>
|
||||
|
||||
export type LinkedTypebotQueue = {
|
||||
typebotId: string
|
||||
edgeId: string
|
||||
}[]
|
||||
|
||||
const typebotContext = createContext<{
|
||||
currentTypebotId: string
|
||||
typebot: TypebotViewerProps['typebot']
|
||||
linkedTypebots: LinkedTypebot[]
|
||||
apiHost: string
|
||||
isPreview: boolean
|
||||
linkedBotQueue: LinkedTypebotQueue
|
||||
isLoading: boolean
|
||||
setCurrentTypebotId: (id: string) => void
|
||||
updateVariableValue: (variableId: string, value: unknown) => void
|
||||
createEdge: (edge: Edge) => void
|
||||
injectLinkedTypebot: (typebot: Typebot | PublicTypebot) => LinkedTypebot
|
||||
popEdgeIdFromLinkedTypebotQueue: () => void
|
||||
pushEdgeIdInLinkedTypebotQueue: (bot: {
|
||||
typebotId: string
|
||||
edgeId: string
|
||||
}) => void
|
||||
onNewLog: (log: Omit<Log, 'id' | 'createdAt' | 'resultId'>) => void
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
}>({})
|
||||
|
||||
export const TypebotProvider = ({
|
||||
children,
|
||||
typebot,
|
||||
apiHost,
|
||||
isPreview,
|
||||
isLoading,
|
||||
onNewLog,
|
||||
}: {
|
||||
children: ReactNode
|
||||
typebot: TypebotViewerProps['typebot']
|
||||
apiHost: string
|
||||
isLoading: boolean
|
||||
isPreview: boolean
|
||||
onNewLog: (log: Omit<Log, 'id' | 'createdAt' | 'resultId'>) => void
|
||||
}) => {
|
||||
const [localTypebot, setLocalTypebot] =
|
||||
useState<TypebotViewerProps['typebot']>(typebot)
|
||||
const [linkedTypebots, setLinkedTypebots] = useState<LinkedTypebot[]>([])
|
||||
const [currentTypebotId, setCurrentTypebotId] = useState(typebot.typebotId)
|
||||
const [linkedBotQueue, setLinkedBotQueue] = useState<LinkedTypebotQueue>([])
|
||||
|
||||
useEffect(() => {
|
||||
setLocalTypebot((localTypebot) => ({
|
||||
...localTypebot,
|
||||
theme: typebot.theme,
|
||||
settings: typebot.settings,
|
||||
}))
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [typebot.theme, typebot.settings])
|
||||
|
||||
const updateVariableValue = (variableId: string, value: unknown) => {
|
||||
const formattedValue = safeStringify(value)
|
||||
|
||||
sendEventToParent({
|
||||
newVariableValue: {
|
||||
name:
|
||||
typebot.variables.find((variable) => variable.id === variableId)
|
||||
?.name ?? '',
|
||||
value: formattedValue ?? '',
|
||||
},
|
||||
})
|
||||
|
||||
setLocalTypebot((typebot) => ({
|
||||
...typebot,
|
||||
variables: typebot.variables.map((v) =>
|
||||
v.id === variableId ? { ...v, value: formattedValue } : v
|
||||
),
|
||||
}))
|
||||
}
|
||||
|
||||
const createEdge = (edge: Edge) => {
|
||||
setLocalTypebot((typebot) => ({
|
||||
...typebot,
|
||||
edges: [...typebot.edges, edge],
|
||||
}))
|
||||
}
|
||||
|
||||
const injectLinkedTypebot = (typebot: Typebot | PublicTypebot) => {
|
||||
const typebotToInject = {
|
||||
id: 'typebotId' in typebot ? typebot.typebotId : typebot.id,
|
||||
groups: typebot.groups,
|
||||
edges: typebot.edges,
|
||||
variables: typebot.variables,
|
||||
}
|
||||
setLinkedTypebots((typebots) => [...typebots, typebotToInject])
|
||||
const updatedTypebot = {
|
||||
...localTypebot,
|
||||
groups: [...localTypebot.groups, ...typebotToInject.groups],
|
||||
variables: [...localTypebot.variables, ...typebotToInject.variables],
|
||||
edges: [...localTypebot.edges, ...typebotToInject.edges],
|
||||
}
|
||||
setLocalTypebot(updatedTypebot)
|
||||
return typebotToInject
|
||||
}
|
||||
|
||||
const pushEdgeIdInLinkedTypebotQueue = (bot: {
|
||||
typebotId: string
|
||||
edgeId: string
|
||||
}) => setLinkedBotQueue((queue) => [...queue, bot])
|
||||
|
||||
const popEdgeIdFromLinkedTypebotQueue = () => {
|
||||
setLinkedBotQueue((queue) => queue.slice(1))
|
||||
setCurrentTypebotId(linkedBotQueue[0].typebotId)
|
||||
}
|
||||
|
||||
return (
|
||||
<typebotContext.Provider
|
||||
value={{
|
||||
typebot: localTypebot,
|
||||
linkedTypebots,
|
||||
apiHost,
|
||||
isPreview,
|
||||
updateVariableValue,
|
||||
createEdge,
|
||||
injectLinkedTypebot,
|
||||
onNewLog,
|
||||
linkedBotQueue,
|
||||
isLoading,
|
||||
pushEdgeIdInLinkedTypebotQueue,
|
||||
popEdgeIdFromLinkedTypebotQueue,
|
||||
currentTypebotId,
|
||||
setCurrentTypebotId,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</typebotContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export const useTypebot = () => useContext(typebotContext)
|
Reference in New Issue
Block a user