2
0

🚸 (js) Display last input if send message errored

This commit is contained in:
Baptiste Arnaud
2023-04-03 18:14:32 +02:00
parent a5d3f83c7f
commit 9f8398b9ae
7 changed files with 38 additions and 18 deletions

View File

@ -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."))

View File

@ -12,6 +12,7 @@ type Props = Pick<ChatReply, 'messages' | 'input'> & {
inputIndex: number
context: BotContext
isLoadingBubbleDisplayed: boolean
hasError: boolean
onNewBubbleDisplayed: (blockId: string) => Promise<void>
onScrollToBottom: () => void
onSubmit: (input: string) => void
@ -90,6 +91,7 @@ export const ChatChunk = (props: Props) => {
isInputPrefillEnabled={
props.settings.general.isInputPrefillEnabled ?? true
}
hasError={props.hasError}
/>
)}
</div>

View File

@ -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<string>()
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}
/>
)}
</For>

View File

@ -5,6 +5,7 @@ export const ErrorMessage = (props: Props) => {
return (
<div class="h-full flex justify-center items-center flex-col">
<p class="text-2xl text-center">{props.error.message}</p>
<p class="text-center">{props.error.cause as string}</p>
</div>
)
}

View File

@ -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 (
<Switch>
<Match when={answer()} keyed>
{(answer) => (
<GuestBubble
message={answer}
showAvatar={props.guestAvatar?.isEnabled ?? false}
avatarSrc={props.guestAvatar?.url && props.guestAvatar.url}
/>
)}
<Match when={answer() && !props.hasError}>
<GuestBubble
message={answer() as string}
showAvatar={props.guestAvatar?.isEnabled ?? false}
avatarSrc={props.guestAvatar?.url && props.guestAvatar.url}
/>
</Match>
<Match when={isNotDefined(answer())}>
<Match when={isNotDefined(answer()) || props.hasError}>
<div
class="flex justify-end animate-fade-in"
data-blockid={props.block.id}

View File

@ -2,15 +2,12 @@ import { guessApiHost } from '@/utils/guessApiHost'
import type { ChatReply, SendMessageInput } from '@typebot.io/schemas'
import { isNotEmpty, sendRequest } from '@typebot.io/lib'
export async function sendMessageQuery({
export const sendMessageQuery = ({
apiHost,
...body
}: SendMessageInput & { apiHost?: string }) {
const response = await sendRequest<ChatReply>({
}: SendMessageInput & { apiHost?: string }) =>
sendRequest<ChatReply>({
method: 'POST',
url: `${isNotEmpty(apiHost) ? apiHost : guessApiHost()}/api/v1/sendMessage`,
body,
})
return response.data
}

View File

@ -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