2
0

(chatwoot) Add result URL custom attribute

This commit is contained in:
Baptiste Arnaud
2023-04-25 08:15:53 +02:00
parent 3529da210c
commit c09a84034e
5 changed files with 66 additions and 29 deletions

View File

@@ -1,12 +1,14 @@
import { Stack } from '@chakra-ui/react' import { Stack } from '@chakra-ui/react'
import React, { useState } from 'react' import React, { useEffect, useState } from 'react'
import { LogsModal } from './LogsModal' import { LogsModal } from './LogsModal'
import { useTypebot } from '@/features/editor/providers/TypebotProvider' import { useTypebot } from '@/features/editor/providers/TypebotProvider'
import { useResults } from '../ResultsProvider' import { useResults } from '../ResultsProvider'
import { ResultModal } from './ResultModal' import { ResultModal } from './ResultModal'
import { ResultsTable } from './table/ResultsTable' import { ResultsTable } from './table/ResultsTable'
import { useRouter } from 'next/router'
export const ResultsTableContainer = () => { export const ResultsTableContainer = () => {
const { query } = useRouter()
const { const {
flatResults: results, flatResults: results,
fetchNextPage, fetchNextPage,
@@ -34,6 +36,10 @@ export const ResultsTableContainer = () => {
setExpandedResultId(results[index].id) setExpandedResultId(results[index].id)
} }
useEffect(() => {
if (query.id) setExpandedResultId(query.id as string)
}, [query.id])
return ( return (
<Stack pb="28" px={['4', '0']} spacing="4" maxW="1600px" w="full"> <Stack pb="28" px={['4', '0']} spacing="4" maxW="1600px" w="full">
{publishedTypebot && ( {publishedTypebot && (

View File

@@ -31,3 +31,16 @@ To find your website token, head over to Chatwoot in your Inbox settings:
You can prefill user information by adding collected variables to the "Set user details" inputs. You can prefill user information by adding collected variables to the "Set user details" inputs.
For example, if you set the "Email" input to "john@gmail.com" then Chatwoot will automatically associate this email to the current user. For example, if you set the "Email" input to "john@gmail.com" then Chatwoot will automatically associate this email to the current user.
## Custom attributes
You can add these custom attributes that Typebot will automatically fill in for you:
### Result URL
You can link the current result URL to the Chatwoot conversation by creating this custom attribute:
<img
src="/img/blocks/integrations/chatwoot/custom-attribute.png"
alt="Chatwoot custom attribute"
/>

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

View File

@@ -2,32 +2,47 @@ import { ExecuteIntegrationResponse } from '@/features/chat/types'
import { extractVariablesFromText } from '@/features/variables/extractVariablesFromText' import { extractVariablesFromText } from '@/features/variables/extractVariablesFromText'
import { parseGuessedValueType } from '@/features/variables/parseGuessedValueType' import { parseGuessedValueType } from '@/features/variables/parseGuessedValueType'
import { parseVariables } from '@/features/variables/parseVariables' import { parseVariables } from '@/features/variables/parseVariables'
import { isDefined } from '@typebot.io/lib'
import { import {
ChatwootBlock, ChatwootBlock,
ChatwootOptions, ChatwootOptions,
SessionState, SessionState,
} from '@typebot.io/schemas' } from '@typebot.io/schemas'
const parseSetUserCode = (user: ChatwootOptions['user']) => ` const parseSetUserCode = (user: ChatwootOptions['user'], resultId: string) =>
window.$chatwoot.setUser("${user?.id ?? ''}", { user?.email || user?.id
email: ${user?.email ? `"${user.email}"` : 'undefined'}, ? `
name: ${user?.name ? `"${user.name}"` : 'undefined'}, window.$chatwoot.setUser(${user?.id ?? `"${resultId}"`}, {
avatar_url: ${user?.avatarUrl ? `"${user.avatarUrl}"` : 'undefined'}, email: ${user?.email ? user.email : 'undefined'},
phone_number: ${user?.phoneNumber ? `"${user.phoneNumber}"` : 'undefined'}, name: ${user?.name ? user.name : 'undefined'},
}); avatar_url: ${user?.avatarUrl ? user.avatarUrl : 'undefined'},
phone_number: ${user?.phoneNumber ? user.phoneNumber : 'undefined'},
});`
: ''
`
const parseChatwootOpenCode = ({ const parseChatwootOpenCode = ({
baseUrl, baseUrl,
websiteToken, websiteToken,
user, user,
}: ChatwootOptions) => ` resultId,
if (window.$chatwoot) { typebotId,
if(${Boolean(user)}) { }: ChatwootOptions & { typebotId: string; resultId: string }) => {
${parseSetUserCode(user)} const openChatwoot = `${parseSetUserCode(user, resultId)}
} window.$chatwoot.setCustomAttributes({
typebot_result_url: "${
process.env.NEXTAUTH_URL
}/typebots/${typebotId}/results?id=${resultId}",
});
window.$chatwoot.toggle("open"); window.$chatwoot.toggle("open");
} else { `
return `
window.addEventListener("chatwoot:error", function (error) {
console.log(error);
});
if (window.$chatwoot) {${openChatwoot}}
else {
(function (d, t) { (function (d, t) {
var BASE_URL = "${baseUrl}"; var BASE_URL = "${baseUrl}";
var g = d.createElement(t), var g = d.createElement(t),
@@ -41,15 +56,11 @@ if (window.$chatwoot) {
websiteToken: "${websiteToken}", websiteToken: "${websiteToken}",
baseUrl: BASE_URL, baseUrl: BASE_URL,
}); });
window.addEventListener("chatwoot:ready", function () { window.addEventListener("chatwoot:ready", function () {${openChatwoot}});
if(${Boolean(user?.id || user?.email)}) {
${parseSetUserCode(user)}
}
window.$chatwoot.toggle("open");
});
}; };
})(document, "script"); })(document, "script");
}` }`
}
const chatwootCloseCode = ` const chatwootCloseCode = `
if (window.$chatwoot) { if (window.$chatwoot) {
@@ -59,17 +70,20 @@ if (window.$chatwoot) {
` `
export const executeChatwootBlock = ( export const executeChatwootBlock = (
{ typebot: { variables }, result }: SessionState, { typebot, result }: SessionState,
block: ChatwootBlock, block: ChatwootBlock,
lastBubbleBlockId?: string lastBubbleBlockId?: string
): ExecuteIntegrationResponse => { ): ExecuteIntegrationResponse => {
const isPreview = !result.id
const chatwootCode = const chatwootCode =
block.options.task === 'Close widget' block.options.task === 'Close widget'
? chatwootCloseCode ? chatwootCloseCode
: isPreview : isDefined(result.id)
? '' ? parseChatwootOpenCode({
: parseChatwootOpenCode(block.options) ...block.options,
typebotId: typebot.id,
resultId: result.id,
})
: ''
return { return {
outgoingEdgeId: block.outgoingEdgeId, outgoingEdgeId: block.outgoingEdgeId,
clientSideActions: [ clientSideActions: [
@@ -77,10 +91,10 @@ export const executeChatwootBlock = (
lastBubbleBlockId, lastBubbleBlockId,
chatwoot: { chatwoot: {
scriptToExecute: { scriptToExecute: {
content: parseVariables(variables, { fieldToParse: 'id' })( content: parseVariables(typebot.variables, { fieldToParse: 'id' })(
chatwootCode chatwootCode
), ),
args: extractVariablesFromText(variables)(chatwootCode).map( args: extractVariablesFromText(typebot.variables)(chatwootCode).map(
(variable) => ({ (variable) => ({
id: variable.id, id: variable.id,
value: parseGuessedValueType(variable.value), value: parseGuessedValueType(variable.value),

View File

@@ -9,7 +9,11 @@ export const extractVariablesFromText =
const variable = variables.find( const variable = variables.find(
(variable) => variable.name === variableName (variable) => variable.name === variableName
) )
if (!variable) return acc if (
!variable ||
acc.find((accVariable) => accVariable.id === variable.id)
)
return acc
return [...acc, variable] return [...acc, variable]
}, []) }, [])
} }