diff --git a/packages/embeds/js/src/components/Bot.tsx b/packages/embeds/js/src/components/Bot.tsx index a6a1a0ce4..0ca06ed85 100644 --- a/packages/embeds/js/src/components/Bot.tsx +++ b/packages/embeds/js/src/components/Bot.tsx @@ -60,11 +60,17 @@ export const Bot = (props: BotProps & { class?: string }) => { }, }) if (error && 'code' in error && typeof error.code === 'string') { + if (typeof props.typebot !== 'string' || (props.isPreview ?? false)) { + setError( + new Error('An error occurred while loading the bot.', { + cause: error.message, + }) + ) + } if (['BAD_REQUEST', 'FORBIDDEN'].includes(error.code)) setError(new Error('This bot is now closed.')) if (error.code === 'NOT_FOUND') setError(new Error("The bot you're looking for doesn't exist.")) - return } if (!data) return setError(new Error("Error! Couldn't initiate the chat.")) diff --git a/packages/embeds/js/src/components/ConversationContainer/ChatChunk.tsx b/packages/embeds/js/src/components/ConversationContainer/ChatChunk.tsx index ddf71d5d1..0096bd3d4 100644 --- a/packages/embeds/js/src/components/ConversationContainer/ChatChunk.tsx +++ b/packages/embeds/js/src/components/ConversationContainer/ChatChunk.tsx @@ -12,6 +12,7 @@ type Props = Pick & { inputIndex: number context: BotContext isLoadingBubbleDisplayed: boolean + hasError: boolean onNewBubbleDisplayed: (blockId: string) => Promise onScrollToBottom: () => void onSubmit: (input: string) => void @@ -90,6 +91,7 @@ export const ChatChunk = (props: Props) => { isInputPrefillEnabled={ props.settings.general.isInputPrefillEnabled ?? true } + hasError={props.hasError} /> )} diff --git a/packages/embeds/js/src/components/ConversationContainer/ConversationContainer.tsx b/packages/embeds/js/src/components/ConversationContainer/ConversationContainer.tsx index aa341feaa..43851e984 100644 --- a/packages/embeds/js/src/components/ConversationContainer/ConversationContainer.tsx +++ b/packages/embeds/js/src/components/ConversationContainer/ConversationContainer.tsx @@ -59,6 +59,7 @@ export const ConversationContainer = (props: Props) => { const [theme, setTheme] = createSignal(props.initialChatReply.typebot.theme) const [isSending, setIsSending] = createSignal(false) const [blockedPopupUrl, setBlockedPopupUrl] = createSignal() + const [hasError, setHasError] = createSignal(false) onMount(() => { ;(async () => { @@ -82,19 +83,30 @@ export const ConversationContainer = (props: Props) => { }) const sendMessage = async (message: string | undefined) => { + setHasError(false) const currentBlockId = [...chatChunks()].pop()?.input?.id if (currentBlockId && props.onAnswer && message) props.onAnswer({ message, blockId: currentBlockId }) const longRequest = setTimeout(() => { setIsSending(true) }, 1000) - const data = await sendMessageQuery({ + const { data, error } = await sendMessageQuery({ apiHost: props.context.apiHost, sessionId: props.initialChatReply.sessionId, message, }) clearTimeout(longRequest) setIsSending(false) + if (error) { + setHasError(true) + props.onNewLogs?.([ + { + description: 'Error while sending message', + details: error, + status: 'error', + }, + ]) + } if (!data) return if (data.logs) props.onNewLogs?.(data.logs) if (data.dynamicTheme) setDynamicTheme(data.dynamicTheme) @@ -174,6 +186,7 @@ export const ConversationContainer = (props: Props) => { onScrollToBottom={autoScrollToBottom} onSkip={handleSkip} context={props.context} + hasError={hasError() && index() === chatChunks().length - 1} /> )} diff --git a/packages/embeds/js/src/components/ErrorMessage.tsx b/packages/embeds/js/src/components/ErrorMessage.tsx index 5b9235442..6399bbc54 100644 --- a/packages/embeds/js/src/components/ErrorMessage.tsx +++ b/packages/embeds/js/src/components/ErrorMessage.tsx @@ -5,6 +5,7 @@ export const ErrorMessage = (props: Props) => { return (

{props.error.message}

+

{props.error.cause as string}

) } diff --git a/packages/embeds/js/src/components/InputChatBlock.tsx b/packages/embeds/js/src/components/InputChatBlock.tsx index 50b1eb9c4..72e5ff11d 100644 --- a/packages/embeds/js/src/components/InputChatBlock.tsx +++ b/packages/embeds/js/src/components/InputChatBlock.tsx @@ -37,6 +37,7 @@ type Props = { inputIndex: number context: BotContext isInputPrefillEnabled: boolean + hasError: boolean onSubmit: (answer: string) => void onSkip: () => void } @@ -56,16 +57,14 @@ export const InputChatBlock = (props: Props) => { return ( - - {(answer) => ( - - )} + + - +
({ +}: SendMessageInput & { apiHost?: string }) => + sendRequest({ method: 'POST', url: `${isNotEmpty(apiHost) ? apiHost : guessApiHost()}/api/v1/sendMessage`, body, }) - - return response.data -} diff --git a/packages/embeds/js/src/utils/guessApiHost.ts b/packages/embeds/js/src/utils/guessApiHost.ts index 930ab5b1f..df3a8a7d8 100644 --- a/packages/embeds/js/src/utils/guessApiHost.ts +++ b/packages/embeds/js/src/utils/guessApiHost.ts @@ -3,4 +3,6 @@ import { env } from '@typebot.io/lib' const cloudViewerUrl = 'https://viewer.typebot.io' export const guessApiHost = () => - env('VIEWER_URL')?.split(',')[0] ?? cloudViewerUrl + env('VIEWER_INTERNAL_URL') ?? + env('VIEWER_URL')?.split(',')[0] ?? + cloudViewerUrl