2
0

chore(viewer): 🛂 Dynamically parse the viewer api host

This commit is contained in:
Baptiste Arnaud
2022-02-10 14:31:44 +01:00
parent 0338acae82
commit cfbf3d4c0d
4 changed files with 61 additions and 45 deletions

View File

@ -31,7 +31,7 @@ export const ChatBlock = ({
onScroll, onScroll,
onBlockEnd, onBlockEnd,
}: ChatBlockProps) => { }: ChatBlockProps) => {
const { typebot, updateVariableValue, createEdge } = useTypebot() const { typebot, updateVariableValue, createEdge, apiHost } = useTypebot()
const [displayedSteps, setDisplayedSteps] = useState<PublicStep[]>([]) const [displayedSteps, setDisplayedSteps] = useState<PublicStep[]>([])
const currentStepIndex = displayedSteps.length - 1 const currentStepIndex = displayedSteps.length - 1
@ -60,13 +60,16 @@ export const ChatBlock = ({
nextEdgeId ? onBlockEnd(nextEdgeId) : displayNextStep() nextEdgeId ? onBlockEnd(nextEdgeId) : displayNextStep()
} }
if (isIntegrationStep(currentStep)) { if (isIntegrationStep(currentStep)) {
const nextEdgeId = await executeIntegration( const nextEdgeId = await executeIntegration({
typebot.typebotId, step: currentStep,
currentStep, context: {
typebot.variables, apiHost,
{ blockIndex, stepIndex: currentStepIndex }, typebotId: typebot.id,
updateVariableValue indices: { blockIndex, stepIndex: currentStepIndex },
) variables: typebot.variables,
updateVariableValue,
},
})
nextEdgeId ? onBlockEnd(nextEdgeId) : displayNextStep() nextEdgeId ? onBlockEnd(nextEdgeId) : displayNextStep()
} }
} }

View File

@ -14,12 +14,14 @@ import { Answer, BackgroundType, Edge, PublicTypebot } from 'models'
export type TypebotViewerProps = { export type TypebotViewerProps = {
typebot: PublicTypebot typebot: PublicTypebot
apiHost?: string
onNewBlockVisible?: (edge: Edge) => void onNewBlockVisible?: (edge: Edge) => void
onNewAnswer?: (answer: Answer) => void onNewAnswer?: (answer: Answer) => void
onCompleted?: () => void onCompleted?: () => void
} }
export const TypebotViewer = ({ export const TypebotViewer = ({
typebot, typebot,
apiHost = process.env.NEXT_PUBLIC_VIEWER_HOST,
onNewBlockVisible, onNewBlockVisible,
onNewAnswer, onNewAnswer,
onCompleted, onCompleted,
@ -41,6 +43,8 @@ export const TypebotViewer = ({
if (onCompleted) onCompleted() if (onCompleted) onCompleted()
} }
if (!apiHost)
return <p>process.env.NEXT_PUBLIC_VIEWER_HOST is missing in env</p>
return ( return (
<Frame <Frame
id="typebot-iframe" id="typebot-iframe"
@ -62,7 +66,7 @@ export const TypebotViewer = ({
}:wght@300;400;600&display=swap');`, }:wght@300;400;600&display=swap');`,
}} }}
/> />
<TypebotContext typebot={typebot}> <TypebotContext typebot={typebot} apiHost={apiHost}>
<AnswersContext> <AnswersContext>
<div <div
className="flex text-base overflow-hidden bg-cover h-screen w-screen flex-col items-center typebot-container" className="flex text-base overflow-hidden bg-cover h-screen w-screen flex-col items-center typebot-container"

View File

@ -3,6 +3,7 @@ import React, { createContext, ReactNode, useContext, useState } from 'react'
const typebotContext = createContext<{ const typebotContext = createContext<{
typebot: PublicTypebot typebot: PublicTypebot
apiHost: string
updateVariableValue: (variableId: string, value: string) => void updateVariableValue: (variableId: string, value: string) => void
createEdge: (edge: Edge) => void createEdge: (edge: Edge) => void
// eslint-disable-next-line @typescript-eslint/ban-ts-comment // eslint-disable-next-line @typescript-eslint/ban-ts-comment
@ -12,9 +13,11 @@ const typebotContext = createContext<{
export const TypebotContext = ({ export const TypebotContext = ({
children, children,
typebot, typebot,
apiHost,
}: { }: {
children: ReactNode children: ReactNode
typebot: PublicTypebot typebot: PublicTypebot
apiHost: string
}) => { }) => {
const [localTypebot, setLocalTypebot] = useState<PublicTypebot>(typebot) const [localTypebot, setLocalTypebot] = useState<PublicTypebot>(typebot)
@ -38,6 +41,7 @@ export const TypebotContext = ({
<typebotContext.Provider <typebotContext.Provider
value={{ value={{
typebot: localTypebot, typebot: localTypebot,
apiHost,
updateVariableValue, updateVariableValue,
createEdge, createEdge,
}} }}

View File

@ -20,34 +20,35 @@ import { parseVariables, parseVariablesInObject } from './variable'
const safeEval = eval const safeEval = eval
type Indices = { blockIndex: number; stepIndex: number } type Indices = { blockIndex: number; stepIndex: number }
export const executeIntegration = ( type IntegrationContext = {
typebotId: string, apiHost: string
step: IntegrationStep, typebotId: string
variables: Variable[], indices: Indices
indices: Indices, variables: Variable[]
updateVariableValue: (variableId: string, value: string) => void updateVariableValue: (variableId: string, value: string) => void
): Promise<string | undefined> => { }
export const executeIntegration = ({
step,
context,
}: {
step: IntegrationStep
context: IntegrationContext
}): Promise<string | undefined> => {
switch (step.type) { switch (step.type) {
case IntegrationStepType.GOOGLE_SHEETS: case IntegrationStepType.GOOGLE_SHEETS:
return executeGoogleSheetIntegration(step, variables, updateVariableValue) return executeGoogleSheetIntegration(step, context)
case IntegrationStepType.GOOGLE_ANALYTICS: case IntegrationStepType.GOOGLE_ANALYTICS:
return executeGoogleAnalyticsIntegration(step, variables) return executeGoogleAnalyticsIntegration(step, context)
case IntegrationStepType.WEBHOOK: case IntegrationStepType.WEBHOOK:
return executeWebhook( return executeWebhook(step, context)
typebotId,
step,
variables,
indices,
updateVariableValue
)
case IntegrationStepType.EMAIL: case IntegrationStepType.EMAIL:
return sendEmail(step, variables) return sendEmail(step, context)
} }
} }
export const executeGoogleAnalyticsIntegration = async ( export const executeGoogleAnalyticsIntegration = async (
step: GoogleAnalyticsStep, step: GoogleAnalyticsStep,
variables: Variable[] { variables }: IntegrationContext
) => { ) => {
if (!step.options?.trackingId) return step.outgoingEdgeId if (!step.options?.trackingId) return step.outgoingEdgeId
const { default: initGoogleAnalytics } = await import('../../lib/gtag') const { default: initGoogleAnalytics } = await import('../../lib/gtag')
@ -58,19 +59,18 @@ export const executeGoogleAnalyticsIntegration = async (
const executeGoogleSheetIntegration = async ( const executeGoogleSheetIntegration = async (
step: GoogleSheetsStep, step: GoogleSheetsStep,
variables: Variable[], context: IntegrationContext
updateVariableValue: (variableId: string, value: string) => void
) => { ) => {
if (!('action' in step.options)) return step.outgoingEdgeId if (!('action' in step.options)) return step.outgoingEdgeId
switch (step.options.action) { switch (step.options.action) {
case GoogleSheetsAction.INSERT_ROW: case GoogleSheetsAction.INSERT_ROW:
await insertRowInGoogleSheets(step.options, variables) await insertRowInGoogleSheets(step.options, context)
break break
case GoogleSheetsAction.UPDATE_ROW: case GoogleSheetsAction.UPDATE_ROW:
await updateRowInGoogleSheets(step.options, variables) await updateRowInGoogleSheets(step.options, context)
break break
case GoogleSheetsAction.GET: case GoogleSheetsAction.GET:
await getRowFromGoogleSheets(step.options, variables, updateVariableValue) await getRowFromGoogleSheets(step.options, context)
break break
} }
return step.outgoingEdgeId return step.outgoingEdgeId
@ -78,11 +78,11 @@ const executeGoogleSheetIntegration = async (
const insertRowInGoogleSheets = async ( const insertRowInGoogleSheets = async (
options: GoogleSheetsInsertRowOptions, options: GoogleSheetsInsertRowOptions,
variables: Variable[] { variables, apiHost }: IntegrationContext
) => { ) => {
if (!options.cellsToInsert) return if (!options.cellsToInsert) return
return sendRequest({ return sendRequest({
url: `http://localhost:3001/api/integrations/google-sheets/spreadsheets/${options.spreadsheetId}/sheets/${options.sheetId}`, url: `${apiHost}/api/integrations/google-sheets/spreadsheets/${options.spreadsheetId}/sheets/${options.sheetId}`,
method: 'POST', method: 'POST',
body: { body: {
credentialsId: options.credentialsId, credentialsId: options.credentialsId,
@ -93,11 +93,11 @@ const insertRowInGoogleSheets = async (
const updateRowInGoogleSheets = async ( const updateRowInGoogleSheets = async (
options: GoogleSheetsUpdateRowOptions, options: GoogleSheetsUpdateRowOptions,
variables: Variable[] { variables, apiHost }: IntegrationContext
) => { ) => {
if (!options.cellsToUpsert || !options.referenceCell) return if (!options.cellsToUpsert || !options.referenceCell) return
return sendRequest({ return sendRequest({
url: `http://localhost:3001/api/integrations/google-sheets/spreadsheets/${options.spreadsheetId}/sheets/${options.sheetId}`, url: `${apiHost}/api/integrations/google-sheets/spreadsheets/${options.spreadsheetId}/sheets/${options.sheetId}`,
method: 'PATCH', method: 'PATCH',
body: { body: {
credentialsId: options.credentialsId, credentialsId: options.credentialsId,
@ -112,8 +112,7 @@ const updateRowInGoogleSheets = async (
const getRowFromGoogleSheets = async ( const getRowFromGoogleSheets = async (
options: GoogleSheetsGetOptions, options: GoogleSheetsGetOptions,
variables: Variable[], { variables, updateVariableValue, apiHost }: IntegrationContext
updateVariableValue: (variableId: string, value: string) => void
) => { ) => {
if (!options.referenceCell || !options.cellsToExtract) return if (!options.referenceCell || !options.cellsToExtract) return
const queryParams = stringify( const queryParams = stringify(
@ -128,7 +127,7 @@ const getRowFromGoogleSheets = async (
{ indices: false } { indices: false }
) )
const { data } = await sendRequest<{ [key: string]: string }>({ const { data } = await sendRequest<{ [key: string]: string }>({
url: `http://localhost:3001/api/integrations/google-sheets/spreadsheets/${options.spreadsheetId}/sheets/${options.sheetId}?${queryParams}`, url: `${apiHost}/api/integrations/google-sheets/spreadsheets/${options.spreadsheetId}/sheets/${options.sheetId}?${queryParams}`,
method: 'GET', method: 'GET',
}) })
if (!data) return if (!data) return
@ -150,16 +149,19 @@ const parseCellValues = (
}, {}) }, {})
const executeWebhook = async ( const executeWebhook = async (
typebotId: string,
step: WebhookStep, step: WebhookStep,
variables: Variable[], {
indices: Indices, indices,
updateVariableValue: (variableId: string, value: string) => void variables,
updateVariableValue,
typebotId,
apiHost,
}: IntegrationContext
) => { ) => {
if (!step.webhook) return step.outgoingEdgeId if (!step.webhook) return step.outgoingEdgeId
const { blockIndex, stepIndex } = indices const { blockIndex, stepIndex } = indices
const { data, error } = await sendRequest({ const { data, error } = await sendRequest({
url: `http://localhost:3000/api/typebots/${typebotId}/blocks/${blockIndex}/steps/${stepIndex}/executeWebhook`, url: `${apiHost}/api/typebots/${typebotId}/blocks/${blockIndex}/steps/${stepIndex}/executeWebhook`,
method: 'POST', method: 'POST',
body: { body: {
variables, variables,
@ -173,10 +175,13 @@ const executeWebhook = async (
}) })
} }
const sendEmail = async (step: SendEmailStep, variables: Variable[]) => { const sendEmail = async (
step: SendEmailStep,
{ variables, apiHost }: IntegrationContext
) => {
const { options } = step const { options } = step
const { error } = await sendRequest({ const { error } = await sendRequest({
url: `http://localhost:3001/api/integrations/email`, url: `${apiHost}/api/integrations/email`,
method: 'POST', method: 'POST',
body: { body: {
credentialsId: options.credentialsId, credentialsId: options.credentialsId,