2
0

🚸 (bot) Show a popup when the redirect is blocked by browser

Allows us to show a link button to redirect the user anyway
This commit is contained in:
Baptiste Arnaud
2023-02-20 08:36:48 +01:00
parent e6ec84b77b
commit b2d1235f1b
9 changed files with 148 additions and 34 deletions

View File

@ -6,6 +6,7 @@ import { BotContext, InitialChatReply } from '@/types'
import { isNotDefined } from 'utils'
import { executeClientSideAction } from '@/utils/executeClientSideActions'
import { LoadingChunk } from './LoadingChunk'
import { PopupBlockedToast } from './PopupBlockedToast'
const parseDynamicTheme = (
initialTheme: Theme,
@ -57,6 +58,7 @@ export const ConversationContainer = (props: Props) => {
>(props.initialChatReply.dynamicTheme)
const [theme, setTheme] = createSignal(props.initialChatReply.typebot.theme)
const [isSending, setIsSending] = createSignal(false)
const [blockedPopupUrl, setBlockedPopupUrl] = createSignal<string>()
createEffect(() => {
setTheme(
@ -112,7 +114,8 @@ export const ConversationContainer = (props: Props) => {
isNotDefined(action.lastBubbleBlockId)
)
for (const action of actionsToExecute) {
await executeClientSideAction(action)
const response = await executeClientSideAction(action)
if (response) setBlockedPopupUrl(response.blockedPopupUrl)
}
}
if (isNotDefined(lastChunk.input)) {
@ -128,7 +131,8 @@ export const ConversationContainer = (props: Props) => {
(action) => action.lastBubbleBlockId === blockId
)
for (const action of actionsToExecute) {
await executeClientSideAction(action)
const response = await executeClientSideAction(action)
if (response) setBlockedPopupUrl(response.blockedPopupUrl)
}
}
}
@ -161,6 +165,16 @@ export const ConversationContainer = (props: Props) => {
<Show when={isSending()}>
<LoadingChunk theme={theme()} />
</Show>
<Show when={blockedPopupUrl()} keyed>
{(blockedPopupUrl) => (
<div class="flex justify-end">
<PopupBlockedToast
url={blockedPopupUrl}
onLinkClick={() => setBlockedPopupUrl(undefined)}
/>
</div>
)}
</Show>
<BottomSpacer ref={bottomSpacer} />
</div>
)

View File

@ -0,0 +1,30 @@
type Props = {
url: string
onLinkClick: () => void
}
export const PopupBlockedToast = (props: Props) => {
return (
<div
class="w-full max-w-xs p-4 text-gray-500 bg-white rounded-lg shadow flex flex-col gap-2"
role="alert"
>
<span class="mb-1 text-sm font-semibold text-gray-900">
Popup blocked
</span>
<div class="mb-2 text-sm font-normal">
The bot wants to open a new tab but it was blocked by your broswer. It
needs a manual approval.
</div>
<a
href={props.url}
target="_blank"
class="py-1 px-4 justify-center text-sm font-semibold rounded-md text-white focus:outline-none flex items-center disabled:opacity-50 disabled:cursor-not-allowed disabled:brightness-100 transition-all filter hover:brightness-90 active:brightness-75 typebot-button"
rel="noreferrer"
onClick={() => props.onLinkClick()}
>
Continue in new tab
</a>
</div>
)
}

View File

@ -13,7 +13,7 @@ export const GuestBubble = (props: Props) => (
style={{ 'margin-left': '50px' }}
>
<span
class="px-4 py-2 rounded-lg mr-2 whitespace-pre-wrap max-w-full typebot-guest-bubble cursor-pointer"
class="px-4 py-2 rounded-lg mr-2 whitespace-pre-wrap max-w-full typebot-guest-bubble"
data-testid="guest-bubble"
>
{props.message}

View File

@ -1,6 +1,13 @@
import type { RedirectOptions } from 'models'
export const executeRedirect = ({ url, isNewTab }: RedirectOptions) => {
export const executeRedirect = ({
url,
isNewTab,
}: RedirectOptions): { blockedPopupUrl: string } | undefined => {
if (!url) return
window.open(url, isNewTab ? '_blank' : '_self')
const updatedWindow = window.open(url, isNewTab ? '_blank' : '_self')
if (!updatedWindow)
return {
blockedPopupUrl: url,
}
}

View File

@ -7,20 +7,20 @@ import type { ChatReply } from 'models'
export const executeClientSideAction = async (
clientSideAction: NonNullable<ChatReply['clientSideActions']>[0]
) => {
): Promise<{ blockedPopupUrl: string } | void> => {
if ('chatwoot' in clientSideAction) {
executeChatwoot(clientSideAction.chatwoot)
return executeChatwoot(clientSideAction.chatwoot)
}
if ('googleAnalytics' in clientSideAction) {
executeGoogleAnalyticsBlock(clientSideAction.googleAnalytics)
return executeGoogleAnalyticsBlock(clientSideAction.googleAnalytics)
}
if ('scriptToExecute' in clientSideAction) {
await executeScript(clientSideAction.scriptToExecute)
return executeScript(clientSideAction.scriptToExecute)
}
if ('redirect' in clientSideAction) {
executeRedirect(clientSideAction.redirect)
return executeRedirect(clientSideAction.redirect)
}
if ('wait' in clientSideAction) {
await executeWait(clientSideAction.wait)
return executeWait(clientSideAction.wait)
}
}