@@ -29,7 +29,7 @@ export default defineConfig({
|
||||
use: {
|
||||
trace: 'on-first-retry',
|
||||
locale: 'en-US',
|
||||
baseURL: process.env.NEXT_PUBLIC_VIEWER_URL,
|
||||
baseURL: process.env.NEXT_PUBLIC_VIEWER_URL?.split(',')[0],
|
||||
},
|
||||
projects: [
|
||||
{
|
||||
|
||||
@@ -60,6 +60,7 @@ export const sendMessageV1 = publicProcedure
|
||||
clientSideActions,
|
||||
newSessionState,
|
||||
visitedEdges,
|
||||
setVariableHistory,
|
||||
} = await startSession({
|
||||
version: 1,
|
||||
startParams:
|
||||
@@ -136,6 +137,7 @@ export const sendMessageV1 = publicProcedure
|
||||
hasCustomEmbedBubble: messages.some(
|
||||
(message) => message.type === 'custom-embed'
|
||||
),
|
||||
setVariableHistory,
|
||||
})
|
||||
|
||||
return {
|
||||
@@ -176,6 +178,7 @@ export const sendMessageV1 = publicProcedure
|
||||
logs,
|
||||
lastMessageNewFormat,
|
||||
visitedEdges,
|
||||
setVariableHistory,
|
||||
} = await continueBotFlow(message, { version: 1, state: session.state })
|
||||
|
||||
const allLogs = clientLogs ? [...(logs ?? []), ...clientLogs] : logs
|
||||
@@ -193,6 +196,7 @@ export const sendMessageV1 = publicProcedure
|
||||
hasCustomEmbedBubble: messages.some(
|
||||
(message) => message.type === 'custom-embed'
|
||||
),
|
||||
setVariableHistory,
|
||||
})
|
||||
|
||||
return {
|
||||
|
||||
@@ -60,6 +60,7 @@ export const sendMessageV2 = publicProcedure
|
||||
clientSideActions,
|
||||
newSessionState,
|
||||
visitedEdges,
|
||||
setVariableHistory,
|
||||
} = await startSession({
|
||||
version: 2,
|
||||
startParams:
|
||||
@@ -136,6 +137,7 @@ export const sendMessageV2 = publicProcedure
|
||||
hasCustomEmbedBubble: messages.some(
|
||||
(message) => message.type === 'custom-embed'
|
||||
),
|
||||
setVariableHistory,
|
||||
})
|
||||
|
||||
return {
|
||||
@@ -175,6 +177,7 @@ export const sendMessageV2 = publicProcedure
|
||||
logs,
|
||||
lastMessageNewFormat,
|
||||
visitedEdges,
|
||||
setVariableHistory,
|
||||
} = await continueBotFlow(message, { version: 2, state: session.state })
|
||||
|
||||
const allLogs = clientLogs ? [...(logs ?? []), ...clientLogs] : logs
|
||||
@@ -192,6 +195,7 @@ export const sendMessageV2 = publicProcedure
|
||||
hasCustomEmbedBubble: messages.some(
|
||||
(message) => message.type === 'custom-embed'
|
||||
),
|
||||
setVariableHistory,
|
||||
})
|
||||
|
||||
return {
|
||||
|
||||
@@ -27,6 +27,7 @@ export const startChatPreview = publicProcedure
|
||||
typebotId,
|
||||
typebot: startTypebot,
|
||||
prefilledVariables,
|
||||
sessionId,
|
||||
},
|
||||
ctx: { user },
|
||||
}) =>
|
||||
@@ -39,5 +40,6 @@ export const startChatPreview = publicProcedure
|
||||
typebot: startTypebot,
|
||||
userId: user?.id,
|
||||
prefilledVariables,
|
||||
sessionId,
|
||||
})
|
||||
)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import {
|
||||
ResultValues,
|
||||
Typebot,
|
||||
@@ -36,7 +37,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const { resultValues, variables, parentTypebotIds } = (
|
||||
typeof req.body === 'string' ? JSON.parse(req.body) : req.body
|
||||
) as {
|
||||
resultValues: ResultValues | undefined
|
||||
resultValues: ResultValues
|
||||
variables: Variable[]
|
||||
parentTypebotIds: string[]
|
||||
}
|
||||
@@ -76,7 +77,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const linkedTypebots = [...linkedTypebotsParents, ...linkedTypebotsChildren]
|
||||
|
||||
const answers = resultValues
|
||||
? resultValues.answers.map((answer) => ({
|
||||
? resultValues.answers.map((answer: any) => ({
|
||||
key:
|
||||
(answer.variableId
|
||||
? typebot.variables.find(
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import {
|
||||
PublicTypebot,
|
||||
ResultValues,
|
||||
@@ -203,7 +204,7 @@ const getEmailBody = async ({
|
||||
})) as unknown as PublicTypebot
|
||||
if (!typebot) return
|
||||
const answers = parseAnswers({
|
||||
answers: resultValues.answers.map((answer) => ({
|
||||
answers: (resultValues as any).answers.map((answer: any) => ({
|
||||
key:
|
||||
(answer.variableId
|
||||
? typebot.variables.find(
|
||||
|
||||
@@ -1,38 +1,16 @@
|
||||
import prisma from '@typebot.io/lib/prisma'
|
||||
import { Answer } from '@typebot.io/prisma'
|
||||
import { got } from 'got'
|
||||
import { NextApiRequest, NextApiResponse } from 'next'
|
||||
import { isNotDefined } from '@typebot.io/lib'
|
||||
import { methodNotAllowed } from '@typebot.io/lib/api'
|
||||
|
||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
if (req.method === 'PUT') {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const { uploadedFiles, ...answer } = (
|
||||
typeof req.body === 'string' ? JSON.parse(req.body) : req.body
|
||||
) as Answer & { uploadedFiles?: boolean }
|
||||
let storageUsed = 0
|
||||
if (uploadedFiles && answer.content.includes('http')) {
|
||||
const fileUrls = answer.content.split(', ')
|
||||
const hasReachedStorageLimit = fileUrls[0] === null
|
||||
if (!hasReachedStorageLimit) {
|
||||
for (const url of fileUrls) {
|
||||
const { headers } = await got(url)
|
||||
const size = headers['content-length']
|
||||
if (isNotDefined(size)) return
|
||||
storageUsed += parseInt(size, 10)
|
||||
}
|
||||
}
|
||||
}
|
||||
const result = await prisma.answer.upsert({
|
||||
where: {
|
||||
resultId_blockId_groupId: {
|
||||
resultId: answer.resultId,
|
||||
groupId: answer.groupId,
|
||||
blockId: answer.blockId,
|
||||
},
|
||||
},
|
||||
create: { ...answer, storageUsed: storageUsed > 0 ? storageUsed : null },
|
||||
update: { ...answer, storageUsed: storageUsed > 0 ? storageUsed : null },
|
||||
) as Answer & { uploadedFiles: string[] }
|
||||
const result = await prisma.answer.createMany({
|
||||
data: [{ ...answer }],
|
||||
})
|
||||
return res.send(result)
|
||||
}
|
||||
|
||||
180
apps/viewer/src/test/assets/typebots/transcript.json
Normal file
180
apps/viewer/src/test/assets/typebots/transcript.json
Normal file
@@ -0,0 +1,180 @@
|
||||
{
|
||||
"version": "6",
|
||||
"id": "clvxf9ent0001tjmcr3e4bypk",
|
||||
"name": "My typebot",
|
||||
"events": [
|
||||
{
|
||||
"id": "d8r5fbpb2eqsq8egwydygiu2",
|
||||
"outgoingEdgeId": "eblhvxj5u2tmwr1459lwxrjh",
|
||||
"graphCoordinates": { "x": 0, "y": 0 },
|
||||
"type": "start"
|
||||
}
|
||||
],
|
||||
"groups": [
|
||||
{
|
||||
"id": "tfsvlygr7lay21s5w475syd8",
|
||||
"title": "Answer",
|
||||
"graphCoordinates": { "x": 579.3, "y": -31.43 },
|
||||
"blocks": [
|
||||
{
|
||||
"id": "pkadqaxm0ow0qvt4d6k9eznd",
|
||||
"type": "text",
|
||||
"content": {
|
||||
"richText": [
|
||||
{
|
||||
"type": "p",
|
||||
"children": [{ "text": "How are you? You said {{Answer}}" }]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "n8b3zi7wd6eory602o006e2a",
|
||||
"type": "text input",
|
||||
"options": { "variableId": "vzbq6pomlaf5bhav64ef5wx3d" }
|
||||
},
|
||||
{
|
||||
"id": "byrr3jxa2qh3imilup7yu1bz",
|
||||
"outgoingEdgeId": "yyc69sbg26ygd7oofetqrmj3",
|
||||
"type": "Set variable",
|
||||
"options": {
|
||||
"variableId": "ve15gxz2fsq004tcqbub0d4m4",
|
||||
"expressionToEvaluate": "{{Answers count}} + 1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "sw6habablg7wmyxzcat99wia",
|
||||
"title": "Condition",
|
||||
"graphCoordinates": { "x": 950.69, "y": -30.46 },
|
||||
"blocks": [
|
||||
{
|
||||
"id": "k7hs4zsybbbece1b0080d2pj",
|
||||
"type": "Condition",
|
||||
"items": [
|
||||
{
|
||||
"id": "ukawer7gc6qdpr4eh0fw2pnv",
|
||||
"content": {
|
||||
"comparisons": [
|
||||
{
|
||||
"id": "jgb06bu8qz0va8vtnarqxivd",
|
||||
"variableId": "ve15gxz2fsq004tcqbub0d4m4",
|
||||
"comparisonOperator": "Equal to",
|
||||
"value": "3"
|
||||
}
|
||||
]
|
||||
},
|
||||
"outgoingEdgeId": "hyel5nw6btuiudmt83b25dvu"
|
||||
}
|
||||
],
|
||||
"outgoingEdgeId": "cz2ayuq8nsoqosxlzu8pyebd"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "kpmjs3nqbbq88f63us13yqyy",
|
||||
"title": "Init",
|
||||
"graphCoordinates": { "x": 235.16, "y": -17.47 },
|
||||
"blocks": [
|
||||
{
|
||||
"id": "w487kr9s9wg3mar7ilfr3tep",
|
||||
"outgoingEdgeId": "mdcj3y9t8kh4uy8lhoh4avdj",
|
||||
"type": "Set variable",
|
||||
"options": {
|
||||
"variableId": "ve15gxz2fsq004tcqbub0d4m4",
|
||||
"expressionToEvaluate": "0"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "wno2kz74jmhzgbi05z4ftjoj",
|
||||
"title": "Transcript",
|
||||
"graphCoordinates": { "x": 1308.8, "y": -41 },
|
||||
"blocks": [
|
||||
{
|
||||
"id": "ejy8vk6gnzegn5copktmw74q",
|
||||
"type": "Set variable",
|
||||
"options": {
|
||||
"variableId": "vs2p20vizsf45xcpgwq5ab3rw",
|
||||
"type": "Transcript"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "qoa74xt647j42sk5b0yyvz9k",
|
||||
"type": "text",
|
||||
"content": {
|
||||
"richText": [
|
||||
{ "type": "p", "children": [{ "text": "{{Transcript}}" }] }
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "eblhvxj5u2tmwr1459lwxrjh",
|
||||
"from": { "eventId": "d8r5fbpb2eqsq8egwydygiu2" },
|
||||
"to": { "groupId": "kpmjs3nqbbq88f63us13yqyy" }
|
||||
},
|
||||
{
|
||||
"id": "mdcj3y9t8kh4uy8lhoh4avdj",
|
||||
"from": { "blockId": "w487kr9s9wg3mar7ilfr3tep" },
|
||||
"to": { "groupId": "tfsvlygr7lay21s5w475syd8" }
|
||||
},
|
||||
{
|
||||
"id": "yyc69sbg26ygd7oofetqrmj3",
|
||||
"from": { "blockId": "byrr3jxa2qh3imilup7yu1bz" },
|
||||
"to": { "groupId": "sw6habablg7wmyxzcat99wia" }
|
||||
},
|
||||
{
|
||||
"from": {
|
||||
"blockId": "k7hs4zsybbbece1b0080d2pj",
|
||||
"itemId": "ukawer7gc6qdpr4eh0fw2pnv"
|
||||
},
|
||||
"to": { "groupId": "wno2kz74jmhzgbi05z4ftjoj" },
|
||||
"id": "hyel5nw6btuiudmt83b25dvu"
|
||||
},
|
||||
{
|
||||
"from": { "blockId": "k7hs4zsybbbece1b0080d2pj" },
|
||||
"to": { "groupId": "tfsvlygr7lay21s5w475syd8" },
|
||||
"id": "cz2ayuq8nsoqosxlzu8pyebd"
|
||||
}
|
||||
],
|
||||
"variables": [
|
||||
{
|
||||
"id": "ve15gxz2fsq004tcqbub0d4m4",
|
||||
"name": "Answers count",
|
||||
"isSessionVariable": true
|
||||
},
|
||||
{
|
||||
"id": "vs2p20vizsf45xcpgwq5ab3rw",
|
||||
"name": "Transcript",
|
||||
"isSessionVariable": true
|
||||
},
|
||||
{
|
||||
"id": "vzbq6pomlaf5bhav64ef5wx3d",
|
||||
"name": "Answer",
|
||||
"isSessionVariable": true
|
||||
}
|
||||
],
|
||||
"theme": {},
|
||||
"selectedThemeTemplateId": null,
|
||||
"settings": {
|
||||
"typingEmulation": { "enabled": false }
|
||||
},
|
||||
"createdAt": "2024-05-08T06:11:55.385Z",
|
||||
"updatedAt": "2024-05-08T06:28:18.313Z",
|
||||
"icon": null,
|
||||
"folderId": null,
|
||||
"publicId": null,
|
||||
"customDomain": null,
|
||||
"workspaceId": "proWorkspace",
|
||||
"resultsTablePreferences": null,
|
||||
"isArchived": false,
|
||||
"isClosed": false,
|
||||
"whatsAppCredentialsId": null,
|
||||
"riskLevel": null
|
||||
}
|
||||
34
apps/viewer/src/test/transcript.spec.ts
Normal file
34
apps/viewer/src/test/transcript.spec.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import test, { expect } from '@playwright/test'
|
||||
import { createId } from '@paralleldrive/cuid2'
|
||||
import { importTypebotInDatabase } from '@typebot.io/playwright/databaseActions'
|
||||
import { getTestAsset } from './utils/playwright'
|
||||
|
||||
test('Transcript set variable should be correctly computed', async ({
|
||||
page,
|
||||
}) => {
|
||||
const typebotId = createId()
|
||||
await importTypebotInDatabase(getTestAsset('typebots/transcript.json'), {
|
||||
id: typebotId,
|
||||
publicId: `${typebotId}-public`,
|
||||
})
|
||||
|
||||
await page.goto(`/${typebotId}-public`)
|
||||
await page.getByPlaceholder('Type your answer...').fill('hey')
|
||||
await page.getByRole('button').click()
|
||||
await page.getByPlaceholder('Type your answer...').fill('hey 2')
|
||||
await page.getByRole('button').click()
|
||||
await page.getByPlaceholder('Type your answer...').fill('hey 3')
|
||||
await page.getByRole('button').click()
|
||||
await expect(
|
||||
page.getByText('Assistant: "How are you? You said "')
|
||||
).toBeVisible()
|
||||
await expect(
|
||||
page.getByText('Assistant: "How are you? You said hey"')
|
||||
).toBeVisible()
|
||||
await expect(
|
||||
page.getByText('Assistant: "How are you? You said hey 3"')
|
||||
).toBeVisible()
|
||||
await expect(page.getByText('User: "hey"')).toBeVisible()
|
||||
await expect(page.getByText('User: "hey 2"')).toBeVisible()
|
||||
await expect(page.getByText('User: "hey 3"')).toBeVisible()
|
||||
})
|
||||
Reference in New Issue
Block a user