refactor: ♻️ Rename step to block
This commit is contained in:
@@ -17,14 +17,17 @@ export const getServerSideProps: GetServerSideProps = async (
|
||||
try {
|
||||
if (!host) return { props: {} }
|
||||
const viewerUrls = (process.env.NEXT_PUBLIC_VIEWER_URL ?? '').split(',')
|
||||
const isMatchingViewerUrl = viewerUrls.some(
|
||||
(url) =>
|
||||
host.split(':')[0].includes(url.split('//')[1].split(':')[0]) ||
|
||||
(forwardedHost &&
|
||||
forwardedHost
|
||||
.split(':')[0]
|
||||
.includes(url.split('//')[1].split(':')[0]))
|
||||
)
|
||||
const isMatchingViewerUrl =
|
||||
process.env.NEXT_PUBLIC_E2E_TEST === 'enabled'
|
||||
? true
|
||||
: viewerUrls.some(
|
||||
(url) =>
|
||||
host.split(':')[0].includes(url.split('//')[1].split(':')[0]) ||
|
||||
(forwardedHost &&
|
||||
forwardedHost
|
||||
.split(':')[0]
|
||||
.includes(url.split('//')[1].split(':')[0]))
|
||||
)
|
||||
const customDomain = `${forwardedHost ?? host}${
|
||||
pathname === '/' ? '' : pathname
|
||||
}`
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
Webhook,
|
||||
WebhookOptions,
|
||||
WebhookResponse,
|
||||
WebhookStep,
|
||||
WebhookBlock,
|
||||
} from 'models'
|
||||
import { parseVariables } from 'bot-engine'
|
||||
import { NextApiRequest, NextApiResponse } from 'next'
|
||||
@@ -38,7 +38,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
await cors(req, res)
|
||||
if (req.method === 'POST') {
|
||||
const typebotId = req.query.typebotId.toString()
|
||||
const stepId = req.query.blockId.toString()
|
||||
const blockId = req.query.blockId.toString()
|
||||
const resultId = req.query.resultId as string | undefined
|
||||
const { resultValues, variables } = (
|
||||
typeof req.body === 'string' ? JSON.parse(req.body) : req.body
|
||||
@@ -51,19 +51,19 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
include: { webhooks: true },
|
||||
})) as unknown as (Typebot & { webhooks: Webhook[] }) | null
|
||||
if (!typebot) return notFound(res)
|
||||
const step = typebot.blocks
|
||||
.flatMap((b) => b.steps)
|
||||
.find(byId(stepId)) as WebhookStep
|
||||
const webhook = typebot.webhooks.find(byId(step.webhookId))
|
||||
const block = typebot.groups
|
||||
.flatMap((g) => g.blocks)
|
||||
.find(byId(blockId)) as WebhookBlock
|
||||
const webhook = typebot.webhooks.find(byId(block.webhookId))
|
||||
if (!webhook)
|
||||
return res
|
||||
.status(404)
|
||||
.send({ statusCode: 404, data: { message: `Couldn't find webhook` } })
|
||||
const preparedWebhook = prepareWebhookAttributes(webhook, step.options)
|
||||
const preparedWebhook = prepareWebhookAttributes(webhook, block.options)
|
||||
const result = await executeWebhook(typebot)(
|
||||
preparedWebhook,
|
||||
variables,
|
||||
step.blockId,
|
||||
block.groupId,
|
||||
resultValues,
|
||||
resultId
|
||||
)
|
||||
@@ -89,7 +89,7 @@ export const executeWebhook =
|
||||
async (
|
||||
webhook: Webhook,
|
||||
variables: Variable[],
|
||||
blockId: string,
|
||||
groupId: string,
|
||||
resultValues?: ResultValues,
|
||||
resultId?: string
|
||||
): Promise<WebhookResponse> => {
|
||||
@@ -130,7 +130,7 @@ export const executeWebhook =
|
||||
)({
|
||||
body: webhook.body,
|
||||
resultValues,
|
||||
blockId,
|
||||
groupId,
|
||||
})
|
||||
: undefined
|
||||
const request = {
|
||||
@@ -191,33 +191,33 @@ export const executeWebhook =
|
||||
|
||||
const getBodyContent =
|
||||
(
|
||||
typebot: Pick<Typebot | PublicTypebot, 'blocks' | 'variables' | 'edges'>,
|
||||
typebot: Pick<Typebot | PublicTypebot, 'groups' | 'variables' | 'edges'>,
|
||||
linkedTypebots: (Typebot | PublicTypebot)[]
|
||||
) =>
|
||||
async ({
|
||||
body,
|
||||
resultValues,
|
||||
blockId,
|
||||
groupId,
|
||||
}: {
|
||||
body?: string | null
|
||||
resultValues?: ResultValues
|
||||
blockId: string
|
||||
groupId: string
|
||||
}): Promise<string | undefined> => {
|
||||
if (!body) return
|
||||
return body === '{{state}}'
|
||||
? JSON.stringify(
|
||||
resultValues
|
||||
? parseAnswers({
|
||||
blocks: [
|
||||
...typebot.blocks,
|
||||
...linkedTypebots.flatMap((t) => t.blocks),
|
||||
groups: [
|
||||
...typebot.groups,
|
||||
...linkedTypebots.flatMap((t) => t.groups),
|
||||
],
|
||||
variables: [
|
||||
...typebot.variables,
|
||||
...linkedTypebots.flatMap((t) => t.variables),
|
||||
],
|
||||
})(resultValues)
|
||||
: await parseSampleResult(typebot, linkedTypebots)(blockId)
|
||||
: await parseSampleResult(typebot, linkedTypebots)(groupId)
|
||||
)
|
||||
: body
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
if (!user) return res.status(401).json({ message: 'Not authenticated' })
|
||||
if (req.method === 'GET') {
|
||||
const typebotId = req.query.typebotId.toString()
|
||||
const stepId = req.query.blockId.toString()
|
||||
const blockId = req.query.blockId.toString()
|
||||
const typebot = (await prisma.typebot.findFirst({
|
||||
where: {
|
||||
id: typebotId,
|
||||
@@ -18,13 +18,13 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
},
|
||||
})) as unknown as Typebot | undefined
|
||||
if (!typebot) return res.status(400).send({ message: 'Typebot not found' })
|
||||
const step = typebot.blocks
|
||||
.flatMap((b) => b.steps)
|
||||
.find((s) => s.id === stepId)
|
||||
if (!step) return res.status(404).send({ message: 'Block not found' })
|
||||
const block = typebot.groups
|
||||
.flatMap((g) => g.blocks)
|
||||
.find((s) => s.id === blockId)
|
||||
if (!block) return res.status(404).send({ message: 'Group not found' })
|
||||
const linkedTypebots = await getLinkedTypebots(typebot, user)
|
||||
return res.send(
|
||||
await parseSampleResult(typebot, linkedTypebots)(step.blockId)
|
||||
await parseSampleResult(typebot, linkedTypebots)(block.groupId)
|
||||
)
|
||||
}
|
||||
methodNotAllowed(res)
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
Variable,
|
||||
Webhook,
|
||||
WebhookOptions,
|
||||
WebhookStep,
|
||||
WebhookBlock,
|
||||
} from 'models'
|
||||
import { NextApiRequest, NextApiResponse } from 'next'
|
||||
import { byId, initMiddleware, methodNotAllowed, notFound } from 'utils'
|
||||
@@ -19,8 +19,8 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
await cors(req, res)
|
||||
if (req.method === 'POST') {
|
||||
const typebotId = req.query.typebotId.toString()
|
||||
const groupId = req.query.groupId.toString()
|
||||
const blockId = req.query.blockId.toString()
|
||||
const stepId = req.query.stepId.toString()
|
||||
const resultId = req.query.resultId as string | undefined
|
||||
const { resultValues, variables } = (
|
||||
typeof req.body === 'string' ? JSON.parse(req.body) : req.body
|
||||
@@ -33,19 +33,19 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
include: { webhooks: true },
|
||||
})) as unknown as (Typebot & { webhooks: Webhook[] }) | null
|
||||
if (!typebot) return notFound(res)
|
||||
const step = typebot.blocks
|
||||
.find(byId(blockId))
|
||||
?.steps.find(byId(stepId)) as WebhookStep
|
||||
const webhook = typebot.webhooks.find(byId(step.webhookId))
|
||||
const block = typebot.groups
|
||||
.find(byId(groupId))
|
||||
?.blocks.find(byId(blockId)) as WebhookBlock
|
||||
const webhook = typebot.webhooks.find(byId(block.webhookId))
|
||||
if (!webhook)
|
||||
return res
|
||||
.status(404)
|
||||
.send({ statusCode: 404, data: { message: `Couldn't find webhook` } })
|
||||
const preparedWebhook = prepareWebhookAttributes(webhook, step.options)
|
||||
const preparedWebhook = prepareWebhookAttributes(webhook, block.options)
|
||||
const result = await executeWebhook(typebot)(
|
||||
preparedWebhook,
|
||||
variables,
|
||||
blockId,
|
||||
groupId,
|
||||
resultValues,
|
||||
resultId
|
||||
)
|
||||
|
||||
@@ -10,7 +10,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
if (!user) return res.status(401).json({ message: 'Not authenticated' })
|
||||
if (req.method === 'GET') {
|
||||
const typebotId = req.query.typebotId.toString()
|
||||
const blockId = req.query.blockId.toString()
|
||||
const groupId = req.query.groupId.toString()
|
||||
const typebot = (await prisma.typebot.findFirst({
|
||||
where: {
|
||||
id: typebotId,
|
||||
@@ -19,7 +19,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
})) as unknown as Typebot | undefined
|
||||
if (!typebot) return res.status(400).send({ message: 'Typebot not found' })
|
||||
const linkedTypebots = await getLinkedTypebots(typebot, user)
|
||||
return res.send(await parseSampleResult(typebot, linkedTypebots)(blockId))
|
||||
return res.send(await parseSampleResult(typebot, linkedTypebots)(groupId))
|
||||
}
|
||||
methodNotAllowed(res)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { withSentry } from '@sentry/nextjs'
|
||||
import prisma from 'libs/prisma'
|
||||
import { Typebot, WebhookStep } from 'models'
|
||||
import { Typebot, WebhookBlock } from 'models'
|
||||
import { NextApiRequest, NextApiResponse } from 'next'
|
||||
import { authenticateUser } from 'services/api/utils'
|
||||
import { byId, methodNotAllowed } from 'utils'
|
||||
@@ -14,8 +14,8 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
return res.status(403).send({ message: 'url is missing in body' })
|
||||
const { url } = body
|
||||
const typebotId = req.query.typebotId.toString()
|
||||
const groupId = req.query.groupId.toString()
|
||||
const blockId = req.query.blockId.toString()
|
||||
const stepId = req.query.stepId.toString()
|
||||
const typebot = (await prisma.typebot.findFirst({
|
||||
where: {
|
||||
id: typebotId,
|
||||
@@ -24,9 +24,9 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
})) as unknown as Typebot | undefined
|
||||
if (!typebot) return res.status(400).send({ message: 'Typebot not found' })
|
||||
try {
|
||||
const { webhookId } = typebot.blocks
|
||||
.find(byId(blockId))
|
||||
?.steps.find(byId(stepId)) as WebhookStep
|
||||
const { webhookId } = typebot.groups
|
||||
.find(byId(groupId))
|
||||
?.blocks.find(byId(blockId)) as WebhookBlock
|
||||
await prisma.webhook.upsert({
|
||||
where: { id: webhookId },
|
||||
update: { url, body: '{{state}}', method: 'POST' },
|
||||
@@ -37,7 +37,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
} catch (err) {
|
||||
return res
|
||||
.status(400)
|
||||
.send({ message: "stepId doesn't point to a Webhook step" })
|
||||
.send({ message: "blockId doesn't point to a Webhook block" })
|
||||
}
|
||||
}
|
||||
return methodNotAllowed(res)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { withSentry } from '@sentry/nextjs'
|
||||
import prisma from 'libs/prisma'
|
||||
import { Typebot, WebhookStep } from 'models'
|
||||
import { Typebot, WebhookBlock } from 'models'
|
||||
import { NextApiRequest, NextApiResponse } from 'next'
|
||||
import { authenticateUser } from 'services/api/utils'
|
||||
import { byId, methodNotAllowed } from 'utils'
|
||||
@@ -10,8 +10,8 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
if (!user) return res.status(401).json({ message: 'Not authenticated' })
|
||||
if (req.method === 'POST') {
|
||||
const typebotId = req.query.typebotId.toString()
|
||||
const groupId = req.query.groupId.toString()
|
||||
const blockId = req.query.blockId.toString()
|
||||
const stepId = req.query.stepId.toString()
|
||||
const typebot = (await prisma.typebot.findFirst({
|
||||
where: {
|
||||
id: typebotId,
|
||||
@@ -20,9 +20,9 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
})) as unknown as Typebot | undefined
|
||||
if (!typebot) return res.status(400).send({ message: 'Typebot not found' })
|
||||
try {
|
||||
const { webhookId } = typebot.blocks
|
||||
.find(byId(blockId))
|
||||
?.steps.find(byId(stepId)) as WebhookStep
|
||||
const { webhookId } = typebot.groups
|
||||
.find(byId(groupId))
|
||||
?.blocks.find(byId(blockId)) as WebhookBlock
|
||||
await prisma.webhook.update({
|
||||
where: { id: webhookId },
|
||||
data: { url: null },
|
||||
@@ -32,7 +32,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
} catch (err) {
|
||||
return res
|
||||
.status(400)
|
||||
.send({ message: "stepId doesn't point to a Webhook step" })
|
||||
.send({ message: "blockId doesn't point to a Webhook block" })
|
||||
}
|
||||
}
|
||||
return methodNotAllowed(res)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { withSentry } from '@sentry/nextjs'
|
||||
import prisma from 'libs/prisma'
|
||||
import { Typebot, WebhookStep } from 'models'
|
||||
import { Typebot, WebhookBlock } from 'models'
|
||||
import { NextApiRequest, NextApiResponse } from 'next'
|
||||
import { authenticateUser } from 'services/api/utils'
|
||||
import { byId, methodNotAllowed } from 'utils'
|
||||
@@ -14,7 +14,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
return res.status(403).send({ message: 'url is missing in body' })
|
||||
const { url } = body
|
||||
const typebotId = req.query.typebotId.toString()
|
||||
const stepId = req.query.blockId.toString()
|
||||
const blockId = req.query.blockId.toString()
|
||||
const typebot = (await prisma.typebot.findFirst({
|
||||
where: {
|
||||
id: typebotId,
|
||||
@@ -23,9 +23,9 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
})) as unknown as Typebot | undefined
|
||||
if (!typebot) return res.status(400).send({ message: 'Typebot not found' })
|
||||
try {
|
||||
const { webhookId } = typebot.blocks
|
||||
.flatMap((b) => b.steps)
|
||||
.find(byId(stepId)) as WebhookStep
|
||||
const { webhookId } = typebot.groups
|
||||
.flatMap((g) => g.blocks)
|
||||
.find(byId(blockId)) as WebhookBlock
|
||||
await prisma.webhook.upsert({
|
||||
where: { id: webhookId },
|
||||
update: { url, body: '{{state}}', method: 'POST' },
|
||||
@@ -36,7 +36,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
} catch (err) {
|
||||
return res
|
||||
.status(400)
|
||||
.send({ message: "blockId doesn't point to a Webhook step" })
|
||||
.send({ message: "groupId doesn't point to a Webhook block" })
|
||||
}
|
||||
}
|
||||
return methodNotAllowed(res)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { withSentry } from '@sentry/nextjs'
|
||||
import prisma from 'libs/prisma'
|
||||
import { Typebot, WebhookStep } from 'models'
|
||||
import { Typebot, WebhookBlock } from 'models'
|
||||
import { NextApiRequest, NextApiResponse } from 'next'
|
||||
import { authenticateUser } from 'services/api/utils'
|
||||
import { byId, methodNotAllowed } from 'utils'
|
||||
@@ -10,7 +10,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
if (!user) return res.status(401).json({ message: 'Not authenticated' })
|
||||
if (req.method === 'POST') {
|
||||
const typebotId = req.query.typebotId.toString()
|
||||
const stepId = req.query.blockId.toString()
|
||||
const blockId = req.query.blockId.toString()
|
||||
const typebot = (await prisma.typebot.findFirst({
|
||||
where: {
|
||||
id: typebotId,
|
||||
@@ -19,9 +19,9 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
})) as unknown as Typebot | undefined
|
||||
if (!typebot) return res.status(400).send({ message: 'Typebot not found' })
|
||||
try {
|
||||
const { webhookId } = typebot.blocks
|
||||
.flatMap((b) => b.steps)
|
||||
.find(byId(stepId)) as WebhookStep
|
||||
const { webhookId } = typebot.groups
|
||||
.flatMap((g) => g.blocks)
|
||||
.find(byId(blockId)) as WebhookBlock
|
||||
await prisma.webhook.update({
|
||||
where: { id: webhookId },
|
||||
data: { url: null },
|
||||
@@ -31,7 +31,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
} catch (err) {
|
||||
return res
|
||||
.status(400)
|
||||
.send({ message: "blockId doesn't point to a Webhook step" })
|
||||
.send({ message: "groupId doesn't point to a Webhook block" })
|
||||
}
|
||||
}
|
||||
return methodNotAllowed(res)
|
||||
|
||||
@@ -11,10 +11,10 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
) as Answer
|
||||
const result = await prisma.answer.upsert({
|
||||
where: {
|
||||
resultId_blockId_stepId: {
|
||||
resultId_blockId_groupId: {
|
||||
resultId: answer.resultId,
|
||||
groupId: answer.groupId,
|
||||
blockId: answer.blockId,
|
||||
stepId: answer.stepId,
|
||||
},
|
||||
},
|
||||
create: answer,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { withSentry } from '@sentry/nextjs'
|
||||
import prisma from 'libs/prisma'
|
||||
import { Block, WebhookStep } from 'models'
|
||||
import { Group, WebhookBlock } from 'models'
|
||||
import { NextApiRequest, NextApiResponse } from 'next'
|
||||
import { authenticateUser } from 'services/api/utils'
|
||||
import { byId, isWebhookStep, methodNotAllowed } from 'utils'
|
||||
import { byId, isWebhookBlock, methodNotAllowed } from 'utils'
|
||||
|
||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
if (req.method === 'GET') {
|
||||
@@ -15,24 +15,25 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
id: typebotId,
|
||||
workspace: { members: { some: { userId: user.id } } },
|
||||
},
|
||||
select: { blocks: true, webhooks: true },
|
||||
select: { groups: true, webhooks: true },
|
||||
})
|
||||
const emptyWebhookSteps = (typebot?.blocks as Block[]).reduce<
|
||||
const emptyWebhookBlocks = (typebot?.groups as Group[]).reduce<
|
||||
{ blockId: string; name: string; url: string | undefined }[]
|
||||
>((emptyWebhookSteps, block) => {
|
||||
const steps = block.steps.filter((step) =>
|
||||
isWebhookStep(step)
|
||||
) as WebhookStep[]
|
||||
>((emptyWebhookBlocks, group) => {
|
||||
const blocks = group.blocks.filter((block) =>
|
||||
isWebhookBlock(block)
|
||||
) as WebhookBlock[]
|
||||
return [
|
||||
...emptyWebhookSteps,
|
||||
...steps.map((s) => ({
|
||||
blockId: s.id,
|
||||
name: `${block.title} > ${s.id}`,
|
||||
url: typebot?.webhooks.find(byId(s.webhookId))?.url ?? undefined,
|
||||
...emptyWebhookBlocks,
|
||||
...blocks.map((b) => ({
|
||||
blockId: b.id,
|
||||
name: `${group.title} > ${b.id}`,
|
||||
url: typebot?.webhooks.find(byId(b.webhookId))?.url ?? undefined,
|
||||
})),
|
||||
]
|
||||
}, [])
|
||||
return res.send({ blocks: emptyWebhookSteps })
|
||||
console.log({ blocks: emptyWebhookBlocks })
|
||||
return res.send({ blocks: emptyWebhookBlocks })
|
||||
}
|
||||
return methodNotAllowed(res)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { withSentry } from '@sentry/nextjs'
|
||||
import prisma from 'libs/prisma'
|
||||
import { Block } from 'models'
|
||||
import { Group, WebhookBlock } from 'models'
|
||||
import { NextApiRequest, NextApiResponse } from 'next'
|
||||
import { authenticateUser } from 'services/api/utils'
|
||||
import { byId, isNotDefined, isWebhookStep, methodNotAllowed } from 'utils'
|
||||
import { byId, isNotDefined, isWebhookBlock, methodNotAllowed } from 'utils'
|
||||
|
||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
if (req.method === 'GET') {
|
||||
@@ -15,26 +15,28 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
id: typebotId,
|
||||
workspace: { members: { some: { userId: user.id } } },
|
||||
},
|
||||
select: { blocks: true, webhooks: true },
|
||||
select: { groups: true, webhooks: true },
|
||||
})
|
||||
const emptyWebhookSteps = (typebot?.blocks as Block[]).reduce<
|
||||
{ blockId: string; id: string; name: string }[]
|
||||
>((emptyWebhookSteps, block) => {
|
||||
const steps = block.steps.filter(
|
||||
(step) =>
|
||||
isWebhookStep(step) &&
|
||||
isNotDefined(typebot?.webhooks.find(byId(step.webhookId))?.url)
|
||||
const emptyWebhookBlocks = (typebot?.groups as Group[]).reduce<
|
||||
{ groupId: string; id: string; name: string }[]
|
||||
>((emptyWebhookBlocks, group) => {
|
||||
const blocks = group.blocks.filter(
|
||||
(block) =>
|
||||
isWebhookBlock(block) &&
|
||||
isNotDefined(
|
||||
typebot?.webhooks.find(byId((block as WebhookBlock).webhookId))?.url
|
||||
)
|
||||
)
|
||||
return [
|
||||
...emptyWebhookSteps,
|
||||
...steps.map((s) => ({
|
||||
...emptyWebhookBlocks,
|
||||
...blocks.map((s) => ({
|
||||
id: s.id,
|
||||
blockId: s.blockId,
|
||||
name: `${block.title} > ${s.id}`,
|
||||
groupId: s.groupId,
|
||||
name: `${group.title} > ${s.id}`,
|
||||
})),
|
||||
]
|
||||
}, [])
|
||||
return res.send({ steps: emptyWebhookSteps })
|
||||
return res.send({ blocks: emptyWebhookBlocks })
|
||||
}
|
||||
return methodNotAllowed(res)
|
||||
}
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
"name": "My typebot",
|
||||
"publishedTypebotId": null,
|
||||
"folderId": null,
|
||||
"blocks": [
|
||||
"groups": [
|
||||
{
|
||||
"id": "k6kY6gwRE6noPoYQNGzgUq",
|
||||
"steps": [
|
||||
"blocks": [
|
||||
{
|
||||
"id": "22HP69iipkLjJDTUcc1AWW",
|
||||
"type": "start",
|
||||
"label": "Start",
|
||||
"blockId": "k6kY6gwRE6noPoYQNGzgUq",
|
||||
"groupId": "k6kY6gwRE6noPoYQNGzgUq",
|
||||
"outgoingEdgeId": "oNvqaqNExdSH2kKEhKZHuE"
|
||||
}
|
||||
],
|
||||
@@ -22,11 +22,11 @@
|
||||
},
|
||||
{
|
||||
"id": "kinRXxYop2X4d7F9qt8WNB",
|
||||
"steps": [
|
||||
"blocks": [
|
||||
{
|
||||
"id": "sc1y8VwDabNJgiVTBi4qtif",
|
||||
"type": "text",
|
||||
"blockId": "kinRXxYop2X4d7F9qt8WNB",
|
||||
"groupId": "kinRXxYop2X4d7F9qt8WNB",
|
||||
"content": {
|
||||
"html": "<div>Welcome to <span class=\"slate-bold\">AA</span> (Awesome Agency)</div>",
|
||||
"richText": [
|
||||
@@ -45,7 +45,7 @@
|
||||
{
|
||||
"id": "s7YqZTBeyCa4Hp3wN2j922c",
|
||||
"type": "image",
|
||||
"blockId": "kinRXxYop2X4d7F9qt8WNB",
|
||||
"groupId": "kinRXxYop2X4d7F9qt8WNB",
|
||||
"content": {
|
||||
"url": "https://media2.giphy.com/media/XD9o33QG9BoMis7iM4/giphy.gif?cid=fe3852a3ihg8rvipzzky5lybmdyq38fhke2tkrnshwk52c7d&rid=giphy.gif&ct=g"
|
||||
}
|
||||
@@ -57,11 +57,11 @@
|
||||
{
|
||||
"id": "hQw2zbp7FDX7XYK9cFpbgC",
|
||||
"type": 0,
|
||||
"stepId": "sbjZWLJGVkHAkDqS4JQeGow",
|
||||
"blockId": "sbjZWLJGVkHAkDqS4JQeGow",
|
||||
"content": "Hi!"
|
||||
}
|
||||
],
|
||||
"blockId": "kinRXxYop2X4d7F9qt8WNB",
|
||||
"groupId": "kinRXxYop2X4d7F9qt8WNB",
|
||||
"options": { "buttonLabel": "Send", "isMultipleChoice": false },
|
||||
"outgoingEdgeId": "i51YhHpk1dtSyduFNf5Wim"
|
||||
}
|
||||
@@ -71,11 +71,11 @@
|
||||
},
|
||||
{
|
||||
"id": "o4SH1UtKANnW5N5D67oZUz",
|
||||
"steps": [
|
||||
"blocks": [
|
||||
{
|
||||
"id": "sxeYubYN6XzhAfG7m9Fivhc",
|
||||
"type": "text",
|
||||
"blockId": "o4SH1UtKANnW5N5D67oZUz",
|
||||
"groupId": "o4SH1UtKANnW5N5D67oZUz",
|
||||
"content": {
|
||||
"html": "<div>Great! Nice to meet you {{Name}}</div>",
|
||||
"richText": [
|
||||
@@ -90,7 +90,7 @@
|
||||
{
|
||||
"id": "scQ5kduafAtfP9T8SHUJnGi",
|
||||
"type": "text",
|
||||
"blockId": "o4SH1UtKANnW5N5D67oZUz",
|
||||
"groupId": "o4SH1UtKANnW5N5D67oZUz",
|
||||
"content": {
|
||||
"html": "<div>What's the best email we can reach you at?</div>",
|
||||
"richText": [
|
||||
@@ -107,7 +107,7 @@
|
||||
{
|
||||
"id": "snbsad18Bgry8yZ8DZCfdFD",
|
||||
"type": "email input",
|
||||
"blockId": "o4SH1UtKANnW5N5D67oZUz",
|
||||
"groupId": "o4SH1UtKANnW5N5D67oZUz",
|
||||
"options": {
|
||||
"labels": { "button": "Send", "placeholder": "Type your email..." },
|
||||
"variableId": "3VFChNVSCXQ2rXv4DrJ8Ah"
|
||||
@@ -120,11 +120,11 @@
|
||||
},
|
||||
{
|
||||
"id": "q5dAhqSTCaNdiGSJm9B9Rw",
|
||||
"steps": [
|
||||
"blocks": [
|
||||
{
|
||||
"id": "sgtE2Sy7cKykac9B223Kq9R",
|
||||
"type": "text",
|
||||
"blockId": "q5dAhqSTCaNdiGSJm9B9Rw",
|
||||
"groupId": "q5dAhqSTCaNdiGSJm9B9Rw",
|
||||
"content": {
|
||||
"html": "<div>What's your name?</div>",
|
||||
"richText": [
|
||||
@@ -136,7 +136,7 @@
|
||||
{
|
||||
"id": "sqEsMo747LTDnY9FjQcEwUv",
|
||||
"type": "text input",
|
||||
"blockId": "q5dAhqSTCaNdiGSJm9B9Rw",
|
||||
"groupId": "q5dAhqSTCaNdiGSJm9B9Rw",
|
||||
"options": {
|
||||
"isLong": false,
|
||||
"labels": {
|
||||
@@ -153,11 +153,11 @@
|
||||
},
|
||||
{
|
||||
"id": "fKqRz7iswk7ULaj5PJocZL",
|
||||
"steps": [
|
||||
"blocks": [
|
||||
{
|
||||
"id": "su7HceVXWyTCzi2vv3m4QbK",
|
||||
"type": "text",
|
||||
"blockId": "fKqRz7iswk7ULaj5PJocZL",
|
||||
"groupId": "fKqRz7iswk7ULaj5PJocZL",
|
||||
"content": {
|
||||
"html": "<div>What services are you interested in?</div>",
|
||||
"richText": [
|
||||
@@ -176,29 +176,29 @@
|
||||
{
|
||||
"id": "fnLCBF4NdraSwcubnBhk8H",
|
||||
"type": 0,
|
||||
"stepId": "s5VQGsVF4hQgziQsXVdwPDW",
|
||||
"blockId": "s5VQGsVF4hQgziQsXVdwPDW",
|
||||
"content": "Website dev"
|
||||
},
|
||||
{
|
||||
"id": "a782h8ynMouY84QjH7XSnR",
|
||||
"type": 0,
|
||||
"stepId": "s5VQGsVF4hQgziQsXVdwPDW",
|
||||
"blockId": "s5VQGsVF4hQgziQsXVdwPDW",
|
||||
"content": "Content Marketing"
|
||||
},
|
||||
{
|
||||
"id": "jGvh94zBByvVFpSS3w97zY",
|
||||
"type": 0,
|
||||
"stepId": "s5VQGsVF4hQgziQsXVdwPDW",
|
||||
"blockId": "s5VQGsVF4hQgziQsXVdwPDW",
|
||||
"content": "Social Media"
|
||||
},
|
||||
{
|
||||
"id": "6PRLbKUezuFmwWtLVbvAQ7",
|
||||
"type": 0,
|
||||
"stepId": "s5VQGsVF4hQgziQsXVdwPDW",
|
||||
"blockId": "s5VQGsVF4hQgziQsXVdwPDW",
|
||||
"content": "UI / UX Design"
|
||||
}
|
||||
],
|
||||
"blockId": "fKqRz7iswk7ULaj5PJocZL",
|
||||
"groupId": "fKqRz7iswk7ULaj5PJocZL",
|
||||
"options": { "buttonLabel": "Send", "isMultipleChoice": true },
|
||||
"outgoingEdgeId": "ohTRakmcYJ7GdFWRZrWRjk"
|
||||
}
|
||||
@@ -208,11 +208,11 @@
|
||||
},
|
||||
{
|
||||
"id": "7qHBEyCMvKEJryBHzPmHjV",
|
||||
"steps": [
|
||||
"blocks": [
|
||||
{
|
||||
"id": "sqR8Sz9gW21aUYKtUikq7qZ",
|
||||
"type": "text",
|
||||
"blockId": "7qHBEyCMvKEJryBHzPmHjV",
|
||||
"groupId": "7qHBEyCMvKEJryBHzPmHjV",
|
||||
"content": {
|
||||
"html": "<div>Can you tell me a bit more about your needs?</div>",
|
||||
"richText": [
|
||||
@@ -229,7 +229,7 @@
|
||||
{
|
||||
"id": "sqFy2G3C1mh9p6s3QBdSS5x",
|
||||
"type": "text input",
|
||||
"blockId": "7qHBEyCMvKEJryBHzPmHjV",
|
||||
"groupId": "7qHBEyCMvKEJryBHzPmHjV",
|
||||
"options": {
|
||||
"isLong": true,
|
||||
"labels": { "button": "Send", "placeholder": "Type your answer..." }
|
||||
@@ -242,11 +242,11 @@
|
||||
},
|
||||
{
|
||||
"id": "vF7AD7zSAj7SNvN3gr9N94",
|
||||
"steps": [
|
||||
"blocks": [
|
||||
{
|
||||
"id": "seLegenCgUwMopRFeAefqZ7",
|
||||
"type": "text",
|
||||
"blockId": "vF7AD7zSAj7SNvN3gr9N94",
|
||||
"groupId": "vF7AD7zSAj7SNvN3gr9N94",
|
||||
"content": {
|
||||
"html": "<div>Perfect!</div>",
|
||||
"richText": [{ "type": "p", "children": [{ "text": "Perfect!" }] }],
|
||||
@@ -256,7 +256,7 @@
|
||||
{
|
||||
"id": "s779Q1y51aVaDUJVrFb16vv",
|
||||
"type": "text",
|
||||
"blockId": "vF7AD7zSAj7SNvN3gr9N94",
|
||||
"groupId": "vF7AD7zSAj7SNvN3gr9N94",
|
||||
"content": {
|
||||
"html": "<div>We'll get back to you at {{Email}}</div>",
|
||||
"richText": [
|
||||
@@ -274,13 +274,13 @@
|
||||
"graphCoordinates": { "x": 1668, "y": 143 }
|
||||
},
|
||||
{
|
||||
"id": "webhookBlock",
|
||||
"id": "webhookGroup",
|
||||
"graphCoordinates": { "x": 1996, "y": 134 },
|
||||
"title": "Webhook",
|
||||
"steps": [
|
||||
"blocks": [
|
||||
{
|
||||
"id": "webhookStep",
|
||||
"blockId": "webhookBlock",
|
||||
"id": "webhookBlock",
|
||||
"groupId": "webhookGroup",
|
||||
"type": "Webhook",
|
||||
"options": { "responseVariableMapping": [], "variablesForTest": [] },
|
||||
"webhookId": "webhook1"
|
||||
@@ -295,58 +295,58 @@
|
||||
"edges": [
|
||||
{
|
||||
"id": "oNvqaqNExdSH2kKEhKZHuE",
|
||||
"to": { "blockId": "kinRXxYop2X4d7F9qt8WNB" },
|
||||
"to": { "groupId": "kinRXxYop2X4d7F9qt8WNB" },
|
||||
"from": {
|
||||
"stepId": "22HP69iipkLjJDTUcc1AWW",
|
||||
"blockId": "k6kY6gwRE6noPoYQNGzgUq"
|
||||
"blockId": "22HP69iipkLjJDTUcc1AWW",
|
||||
"groupId": "k6kY6gwRE6noPoYQNGzgUq"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "i51YhHpk1dtSyduFNf5Wim",
|
||||
"to": { "blockId": "q5dAhqSTCaNdiGSJm9B9Rw" },
|
||||
"to": { "groupId": "q5dAhqSTCaNdiGSJm9B9Rw" },
|
||||
"from": {
|
||||
"stepId": "sbjZWLJGVkHAkDqS4JQeGow",
|
||||
"blockId": "kinRXxYop2X4d7F9qt8WNB"
|
||||
"blockId": "sbjZWLJGVkHAkDqS4JQeGow",
|
||||
"groupId": "kinRXxYop2X4d7F9qt8WNB"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "4tYbERpi5Po4goVgt6rWXg",
|
||||
"to": { "blockId": "o4SH1UtKANnW5N5D67oZUz" },
|
||||
"to": { "groupId": "o4SH1UtKANnW5N5D67oZUz" },
|
||||
"from": {
|
||||
"stepId": "sqEsMo747LTDnY9FjQcEwUv",
|
||||
"blockId": "q5dAhqSTCaNdiGSJm9B9Rw"
|
||||
"blockId": "sqEsMo747LTDnY9FjQcEwUv",
|
||||
"groupId": "q5dAhqSTCaNdiGSJm9B9Rw"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "w3MiN1Ct38jT5NykVsgmb5",
|
||||
"to": { "blockId": "fKqRz7iswk7ULaj5PJocZL" },
|
||||
"to": { "groupId": "fKqRz7iswk7ULaj5PJocZL" },
|
||||
"from": {
|
||||
"stepId": "snbsad18Bgry8yZ8DZCfdFD",
|
||||
"blockId": "o4SH1UtKANnW5N5D67oZUz"
|
||||
"blockId": "snbsad18Bgry8yZ8DZCfdFD",
|
||||
"groupId": "o4SH1UtKANnW5N5D67oZUz"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "ohTRakmcYJ7GdFWRZrWRjk",
|
||||
"to": { "blockId": "7qHBEyCMvKEJryBHzPmHjV" },
|
||||
"to": { "groupId": "7qHBEyCMvKEJryBHzPmHjV" },
|
||||
"from": {
|
||||
"stepId": "s5VQGsVF4hQgziQsXVdwPDW",
|
||||
"blockId": "fKqRz7iswk7ULaj5PJocZL"
|
||||
"blockId": "s5VQGsVF4hQgziQsXVdwPDW",
|
||||
"groupId": "fKqRz7iswk7ULaj5PJocZL"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "sH5nUssG2XQbm6ZidGv9BY",
|
||||
"to": { "blockId": "vF7AD7zSAj7SNvN3gr9N94" },
|
||||
"to": { "groupId": "vF7AD7zSAj7SNvN3gr9N94" },
|
||||
"from": {
|
||||
"stepId": "sqFy2G3C1mh9p6s3QBdSS5x",
|
||||
"blockId": "7qHBEyCMvKEJryBHzPmHjV"
|
||||
"blockId": "sqFy2G3C1mh9p6s3QBdSS5x",
|
||||
"groupId": "7qHBEyCMvKEJryBHzPmHjV"
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": {
|
||||
"blockId": "vF7AD7zSAj7SNvN3gr9N94",
|
||||
"stepId": "s779Q1y51aVaDUJVrFb16vv"
|
||||
"groupId": "vF7AD7zSAj7SNvN3gr9N94",
|
||||
"blockId": "s779Q1y51aVaDUJVrFb16vv"
|
||||
},
|
||||
"to": { "blockId": "webhookBlock" },
|
||||
"to": { "groupId": "webhookGroup" },
|
||||
"id": "fTVo43AG97eKcaTrZf9KyV"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
"name": "My typebot",
|
||||
"publishedTypebotId": "dm12bh6hmEQemywn86osJD",
|
||||
"folderId": null,
|
||||
"blocks": [
|
||||
"groups": [
|
||||
{
|
||||
"id": "dqork4dJJZk3RgKYavBpRE",
|
||||
"steps": [
|
||||
"blocks": [
|
||||
{
|
||||
"id": "u7Px8eD9MWXNJEBwxQwJCF",
|
||||
"type": "start",
|
||||
"label": "Start",
|
||||
"blockId": "dqork4dJJZk3RgKYavBpRE",
|
||||
"groupId": "dqork4dJJZk3RgKYavBpRE",
|
||||
"outgoingEdgeId": "b3XsreaqtWt4CrZZmCKDpa"
|
||||
}
|
||||
],
|
||||
@@ -22,11 +22,11 @@
|
||||
},
|
||||
{
|
||||
"id": "2Vrpgk5VP9BUo3vKtM5kws",
|
||||
"steps": [
|
||||
"blocks": [
|
||||
{
|
||||
"id": "s6GezsfD612D1naKwvhDFgA",
|
||||
"type": "text",
|
||||
"blockId": "2Vrpgk5VP9BUo3vKtM5kws",
|
||||
"groupId": "2Vrpgk5VP9BUo3vKtM5kws",
|
||||
"content": {
|
||||
"html": "<div>Hi what's your name?</div>",
|
||||
"richText": [
|
||||
@@ -38,7 +38,7 @@
|
||||
{
|
||||
"id": "sq3mPXUrugs5t6FoME3T4t4",
|
||||
"type": "text input",
|
||||
"blockId": "2Vrpgk5VP9BUo3vKtM5kws",
|
||||
"groupId": "2Vrpgk5VP9BUo3vKtM5kws",
|
||||
"options": {
|
||||
"isLong": false,
|
||||
"labels": {
|
||||
@@ -51,7 +51,7 @@
|
||||
{
|
||||
"id": "s57hbzfpG2sVvXefznVhbVB",
|
||||
"type": "text",
|
||||
"blockId": "2Vrpgk5VP9BUo3vKtM5kws",
|
||||
"groupId": "2Vrpgk5VP9BUo3vKtM5kws",
|
||||
"content": {
|
||||
"html": "<div>How old are you?</div>",
|
||||
"richText": [
|
||||
@@ -63,7 +63,7 @@
|
||||
{
|
||||
"id": "s4fFn3s7nouQk88iJ3oLgx6",
|
||||
"type": "number input",
|
||||
"blockId": "2Vrpgk5VP9BUo3vKtM5kws",
|
||||
"groupId": "2Vrpgk5VP9BUo3vKtM5kws",
|
||||
"options": {
|
||||
"labels": { "button": "Send", "placeholder": "Type a number..." }
|
||||
}
|
||||
@@ -71,7 +71,7 @@
|
||||
{
|
||||
"id": "scR6MewJwkPNJzABYG8NEA4",
|
||||
"type": "text",
|
||||
"blockId": "2Vrpgk5VP9BUo3vKtM5kws",
|
||||
"groupId": "2Vrpgk5VP9BUo3vKtM5kws",
|
||||
"content": {
|
||||
"html": "<div>Cool!</div>",
|
||||
"richText": [{ "type": "p", "children": [{ "text": "Cool!" }] }],
|
||||
@@ -81,7 +81,7 @@
|
||||
{
|
||||
"id": "s5fo1s8UTyHQ7CfqC6MRxyW",
|
||||
"type": "text",
|
||||
"blockId": "2Vrpgk5VP9BUo3vKtM5kws",
|
||||
"groupId": "2Vrpgk5VP9BUo3vKtM5kws",
|
||||
"content": {
|
||||
"html": "<div>Do you eat pizza?</div>",
|
||||
"richText": [
|
||||
@@ -97,21 +97,21 @@
|
||||
{
|
||||
"id": "wGKXMr4mfySw1HNThND2Xd",
|
||||
"type": 0,
|
||||
"stepId": "sxn8UjQ2MjEMuRjhkh7LWws",
|
||||
"blockId": "sxn8UjQ2MjEMuRjhkh7LWws",
|
||||
"content": "Yes"
|
||||
},
|
||||
{
|
||||
"id": "qzqzVqMeo6TDUdMYckLZmf",
|
||||
"type": 0,
|
||||
"stepId": "sxn8UjQ2MjEMuRjhkh7LWws",
|
||||
"blockId": "sxn8UjQ2MjEMuRjhkh7LWws",
|
||||
"content": "No"
|
||||
}
|
||||
],
|
||||
"blockId": "2Vrpgk5VP9BUo3vKtM5kws",
|
||||
"groupId": "2Vrpgk5VP9BUo3vKtM5kws",
|
||||
"options": { "buttonLabel": "Send", "isMultipleChoice": false }
|
||||
}
|
||||
],
|
||||
"title": "Block #1",
|
||||
"title": "Group #1",
|
||||
"graphCoordinates": { "x": 386, "y": 108 }
|
||||
}
|
||||
],
|
||||
@@ -119,10 +119,10 @@
|
||||
"edges": [
|
||||
{
|
||||
"id": "b3XsreaqtWt4CrZZmCKDpa",
|
||||
"to": { "blockId": "2Vrpgk5VP9BUo3vKtM5kws" },
|
||||
"to": { "groupId": "2Vrpgk5VP9BUo3vKtM5kws" },
|
||||
"from": {
|
||||
"stepId": "u7Px8eD9MWXNJEBwxQwJCF",
|
||||
"blockId": "dqork4dJJZk3RgKYavBpRE"
|
||||
"blockId": "u7Px8eD9MWXNJEBwxQwJCF",
|
||||
"groupId": "dqork4dJJZk3RgKYavBpRE"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -5,15 +5,15 @@
|
||||
"name": "My typebot",
|
||||
"publishedTypebotId": null,
|
||||
"folderId": null,
|
||||
"blocks": [
|
||||
"groups": [
|
||||
{
|
||||
"id": "1qQrnsLzRim1LqCrhbj1MW",
|
||||
"steps": [
|
||||
"blocks": [
|
||||
{
|
||||
"id": "8srsGhdBJK8v88Xo1RRS4C",
|
||||
"type": "start",
|
||||
"label": "Start",
|
||||
"blockId": "1qQrnsLzRim1LqCrhbj1MW",
|
||||
"groupId": "1qQrnsLzRim1LqCrhbj1MW",
|
||||
"outgoingEdgeId": "ovUHhwr6THMhqtn8QbkjtA"
|
||||
}
|
||||
],
|
||||
@@ -22,15 +22,15 @@
|
||||
},
|
||||
{
|
||||
"id": "wSR4VCcDNDTTsD9Szi2xH8",
|
||||
"steps": [
|
||||
"blocks": [
|
||||
{
|
||||
"id": "sw6nHJfkMsM4pxZxMBB6QqW",
|
||||
"type": "Typebot link",
|
||||
"blockId": "wSR4VCcDNDTTsD9Szi2xH8",
|
||||
"groupId": "wSR4VCcDNDTTsD9Szi2xH8",
|
||||
"options": { "typebotId": "cl0ibhv8d0130n21aw8doxhj5" }
|
||||
}
|
||||
],
|
||||
"title": "Block #1",
|
||||
"title": "Group #1",
|
||||
"graphCoordinates": { "x": 363, "y": 199 }
|
||||
}
|
||||
],
|
||||
@@ -38,10 +38,10 @@
|
||||
"edges": [
|
||||
{
|
||||
"id": "ovUHhwr6THMhqtn8QbkjtA",
|
||||
"to": { "blockId": "wSR4VCcDNDTTsD9Szi2xH8" },
|
||||
"to": { "groupId": "wSR4VCcDNDTTsD9Szi2xH8" },
|
||||
"from": {
|
||||
"stepId": "8srsGhdBJK8v88Xo1RRS4C",
|
||||
"blockId": "1qQrnsLzRim1LqCrhbj1MW"
|
||||
"blockId": "8srsGhdBJK8v88Xo1RRS4C",
|
||||
"groupId": "1qQrnsLzRim1LqCrhbj1MW"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
"name": "Another typebot",
|
||||
"publishedTypebotId": null,
|
||||
"folderId": null,
|
||||
"blocks": [
|
||||
"groups": [
|
||||
{
|
||||
"id": "p4ByLVoKiDRyRoPHKmcTfw",
|
||||
"steps": [
|
||||
"blocks": [
|
||||
{
|
||||
"id": "rw6smEWEJzHKbiVKLUKFvZ",
|
||||
"type": "start",
|
||||
"label": "Start",
|
||||
"blockId": "p4ByLVoKiDRyRoPHKmcTfw",
|
||||
"groupId": "p4ByLVoKiDRyRoPHKmcTfw",
|
||||
"outgoingEdgeId": "1z3pfiatTUHbraD2uSoA3E"
|
||||
}
|
||||
],
|
||||
@@ -23,11 +23,11 @@
|
||||
{
|
||||
"id": "bg4QEJseUsTP496H27j5k2",
|
||||
"graphCoordinates": { "x": 366, "y": 191 },
|
||||
"title": "Block #1",
|
||||
"steps": [
|
||||
"title": "Group #1",
|
||||
"blocks": [
|
||||
{
|
||||
"id": "s8ZeBL9p5za77eBmdKECLYq",
|
||||
"blockId": "bg4QEJseUsTP496H27j5k2",
|
||||
"groupId": "bg4QEJseUsTP496H27j5k2",
|
||||
"type": "text input",
|
||||
"options": {
|
||||
"isLong": false,
|
||||
@@ -41,10 +41,10 @@
|
||||
"edges": [
|
||||
{
|
||||
"from": {
|
||||
"blockId": "p4ByLVoKiDRyRoPHKmcTfw",
|
||||
"stepId": "rw6smEWEJzHKbiVKLUKFvZ"
|
||||
"groupId": "p4ByLVoKiDRyRoPHKmcTfw",
|
||||
"blockId": "rw6smEWEJzHKbiVKLUKFvZ"
|
||||
},
|
||||
"to": { "blockId": "bg4QEJseUsTP496H27j5k2" },
|
||||
"to": { "groupId": "bg4QEJseUsTP496H27j5k2" },
|
||||
"id": "1z3pfiatTUHbraD2uSoA3E"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
"name": "My typebot",
|
||||
"publishedTypebotId": null,
|
||||
"folderId": null,
|
||||
"blocks": [
|
||||
"groups": [
|
||||
{
|
||||
"id": "cl13bgvlk0000t71a4wabccvw",
|
||||
"steps": [
|
||||
"blocks": [
|
||||
{
|
||||
"id": "cl13bgvlk0001t71a3pilbj53",
|
||||
"type": "start",
|
||||
"label": "Start",
|
||||
"blockId": "cl13bgvlk0000t71a4wabccvw",
|
||||
"groupId": "cl13bgvlk0000t71a4wabccvw",
|
||||
"outgoingEdgeId": "cl13bgz4800062e6dv7ejcchb"
|
||||
}
|
||||
],
|
||||
@@ -23,11 +23,11 @@
|
||||
{
|
||||
"id": "cl13bgy1s00042e6dao1wyobm",
|
||||
"graphCoordinates": { "x": 329, "y": 65 },
|
||||
"title": "Block #1",
|
||||
"steps": [
|
||||
"title": "Group #1",
|
||||
"blocks": [
|
||||
{
|
||||
"id": "cl13bgy1w00052e6d5x57wt7o",
|
||||
"blockId": "cl13bgy1s00042e6dao1wyobm",
|
||||
"groupId": "cl13bgy1s00042e6dao1wyobm",
|
||||
"type": "text",
|
||||
"content": {
|
||||
"html": "<div>Hey I know you!</div>",
|
||||
@@ -39,7 +39,7 @@
|
||||
},
|
||||
{
|
||||
"id": "cl13bh6jd00072e6dftdirwy4",
|
||||
"blockId": "cl13bgy1s00042e6dao1wyobm",
|
||||
"groupId": "cl13bgy1s00042e6dao1wyobm",
|
||||
"type": "text",
|
||||
"content": {
|
||||
"html": "<div>Your name is {{Name}}</div>",
|
||||
@@ -51,7 +51,7 @@
|
||||
},
|
||||
{
|
||||
"id": "cl13bhfxd00092e6dydvcqlhm",
|
||||
"blockId": "cl13bgy1s00042e6dao1wyobm",
|
||||
"groupId": "cl13bgy1s00042e6dao1wyobm",
|
||||
"type": "text",
|
||||
"content": {
|
||||
"html": "<div>What's your email?</div>",
|
||||
@@ -63,7 +63,7 @@
|
||||
},
|
||||
{
|
||||
"id": "cl13bhnay000a2e6dxa630dh3",
|
||||
"blockId": "cl13bgy1s00042e6dao1wyobm",
|
||||
"groupId": "cl13bgy1s00042e6dao1wyobm",
|
||||
"type": "email input",
|
||||
"options": {
|
||||
"labels": { "button": "Send", "placeholder": "Type your email..." },
|
||||
@@ -81,10 +81,10 @@
|
||||
"edges": [
|
||||
{
|
||||
"from": {
|
||||
"blockId": "cl13bgvlk0000t71a4wabccvw",
|
||||
"stepId": "cl13bgvlk0001t71a3pilbj53"
|
||||
"groupId": "cl13bgvlk0000t71a4wabccvw",
|
||||
"blockId": "cl13bgvlk0001t71a3pilbj53"
|
||||
},
|
||||
"to": { "blockId": "cl13bgy1s00042e6dao1wyobm" },
|
||||
"to": { "groupId": "cl13bgy1s00042e6dao1wyobm" },
|
||||
"id": "cl13bgz4800062e6dv7ejcchb"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -6,15 +6,15 @@
|
||||
"name": "My typebot",
|
||||
"publishedTypebotId": null,
|
||||
"folderId": null,
|
||||
"blocks": [
|
||||
"groups": [
|
||||
{
|
||||
"id": "cl1rxxg6k000009lhd0mgfy5i",
|
||||
"steps": [
|
||||
"blocks": [
|
||||
{
|
||||
"id": "cl1rxxg6k000109lh2is0gfua",
|
||||
"type": "start",
|
||||
"label": "Start",
|
||||
"blockId": "cl1rxxg6k000009lhd0mgfy5i",
|
||||
"groupId": "cl1rxxg6k000009lhd0mgfy5i",
|
||||
"outgoingEdgeId": "cl1w8rhzs000f2e694836a1k3"
|
||||
}
|
||||
],
|
||||
@@ -25,16 +25,16 @@
|
||||
"id": "cl1w8repd000b2e69fwiqsd00",
|
||||
"graphCoordinates": { "x": 364, "y": -2 },
|
||||
"title": "Group #1",
|
||||
"steps": [
|
||||
"blocks": [
|
||||
{
|
||||
"id": "cl1w8repg000c2e699jqwrepg",
|
||||
"blockId": "cl1w8repd000b2e69fwiqsd00",
|
||||
"groupId": "cl1w8repd000b2e69fwiqsd00",
|
||||
"type": "choice input",
|
||||
"options": { "buttonLabel": "Send", "isMultipleChoice": false },
|
||||
"items": [
|
||||
{
|
||||
"id": "cl1w8repg000d2e69d8xnkqeq",
|
||||
"stepId": "cl1w8repg000c2e699jqwrepg",
|
||||
"blockId": "cl1w8repg000c2e699jqwrepg",
|
||||
"type": 0,
|
||||
"content": "Send email",
|
||||
"outgoingEdgeId": "cl1w8rkoo000i2e69hs60pk0q"
|
||||
@@ -47,10 +47,10 @@
|
||||
"id": "cl1w8rjaf000g2e69cqd2bwvk",
|
||||
"graphCoordinates": { "x": 715, "y": -10 },
|
||||
"title": "Group #2",
|
||||
"steps": [
|
||||
"blocks": [
|
||||
{
|
||||
"id": "cl1w8rjai000h2e695uvoimq7",
|
||||
"blockId": "cl1w8rjaf000g2e69cqd2bwvk",
|
||||
"groupId": "cl1w8rjaf000g2e69cqd2bwvk",
|
||||
"type": "Email",
|
||||
"options": {
|
||||
"credentialsId": "send-email-credentials",
|
||||
@@ -72,19 +72,19 @@
|
||||
"edges": [
|
||||
{
|
||||
"from": {
|
||||
"blockId": "cl1rxxg6k000009lhd0mgfy5i",
|
||||
"stepId": "cl1rxxg6k000109lh2is0gfua"
|
||||
"groupId": "cl1rxxg6k000009lhd0mgfy5i",
|
||||
"blockId": "cl1rxxg6k000109lh2is0gfua"
|
||||
},
|
||||
"to": { "blockId": "cl1w8repd000b2e69fwiqsd00" },
|
||||
"to": { "groupId": "cl1w8repd000b2e69fwiqsd00" },
|
||||
"id": "cl1w8rhzs000f2e694836a1k3"
|
||||
},
|
||||
{
|
||||
"from": {
|
||||
"blockId": "cl1w8repd000b2e69fwiqsd00",
|
||||
"stepId": "cl1w8repg000c2e699jqwrepg",
|
||||
"groupId": "cl1w8repd000b2e69fwiqsd00",
|
||||
"blockId": "cl1w8repg000c2e699jqwrepg",
|
||||
"itemId": "cl1w8repg000d2e69d8xnkqeq"
|
||||
},
|
||||
"to": { "blockId": "cl1w8rjaf000g2e69cqd2bwvk" },
|
||||
"to": { "groupId": "cl1w8rjaf000g2e69cqd2bwvk" },
|
||||
"id": "cl1w8rkoo000i2e69hs60pk0q"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -6,15 +6,15 @@
|
||||
"name": "My typebot",
|
||||
"publishedTypebotId": null,
|
||||
"folderId": null,
|
||||
"blocks": [
|
||||
"groups": [
|
||||
{
|
||||
"id": "cl26li8fj0000iez05x7razkg",
|
||||
"steps": [
|
||||
"blocks": [
|
||||
{
|
||||
"id": "cl26li8fj0001iez0bqfraw9h",
|
||||
"type": "start",
|
||||
"label": "Start",
|
||||
"blockId": "cl26li8fj0000iez05x7razkg",
|
||||
"groupId": "cl26li8fj0000iez05x7razkg",
|
||||
"outgoingEdgeId": "cl26liqj6000g2e6ed2cwkvse"
|
||||
}
|
||||
],
|
||||
@@ -23,7 +23,7 @@
|
||||
},
|
||||
{
|
||||
"id": "cl26lidjz000a2e6etf4v03hv",
|
||||
"steps": [
|
||||
"blocks": [
|
||||
{
|
||||
"id": "cl26lidk4000b2e6es2fos0nl",
|
||||
"type": "choice input",
|
||||
@@ -31,17 +31,17 @@
|
||||
{
|
||||
"id": "cl26lidk5000c2e6e39wyc7wq",
|
||||
"type": 0,
|
||||
"stepId": "cl26lidk4000b2e6es2fos0nl",
|
||||
"blockId": "cl26lidk4000b2e6es2fos0nl",
|
||||
"content": "Send success webhook"
|
||||
}
|
||||
],
|
||||
"blockId": "cl26lidjz000a2e6etf4v03hv",
|
||||
"groupId": "cl26lidjz000a2e6etf4v03hv",
|
||||
"options": { "buttonLabel": "Send", "isMultipleChoice": false }
|
||||
},
|
||||
{
|
||||
"id": "cl26lip76000e2e6ebmph843a",
|
||||
"type": "Webhook",
|
||||
"blockId": "cl26lidjz000a2e6etf4v03hv",
|
||||
"groupId": "cl26lidjz000a2e6etf4v03hv",
|
||||
"options": {
|
||||
"isCustomBody": false,
|
||||
"isAdvancedConfig": false,
|
||||
@@ -52,13 +52,13 @@
|
||||
},
|
||||
{
|
||||
"id": "cl26m0pdz00042e6ebjdoclaa",
|
||||
"blockId": "cl26lidjz000a2e6etf4v03hv",
|
||||
"groupId": "cl26lidjz000a2e6etf4v03hv",
|
||||
"type": "choice input",
|
||||
"options": { "buttonLabel": "Send", "isMultipleChoice": false },
|
||||
"items": [
|
||||
{
|
||||
"id": "cl26m0pdz00052e6ecmxwfz44",
|
||||
"stepId": "cl26m0pdz00042e6ebjdoclaa",
|
||||
"blockId": "cl26m0pdz00042e6ebjdoclaa",
|
||||
"type": 0,
|
||||
"content": "Send failed webhook"
|
||||
}
|
||||
@@ -66,7 +66,7 @@
|
||||
},
|
||||
{
|
||||
"id": "cl26m0w9b00072e6eld1ei291",
|
||||
"blockId": "cl26lidjz000a2e6etf4v03hv",
|
||||
"groupId": "cl26lidjz000a2e6etf4v03hv",
|
||||
"type": "Webhook",
|
||||
"options": {
|
||||
"responseVariableMapping": [],
|
||||
@@ -89,10 +89,10 @@
|
||||
"edges": [
|
||||
{
|
||||
"id": "cl26liqj6000g2e6ed2cwkvse",
|
||||
"to": { "blockId": "cl26lidjz000a2e6etf4v03hv" },
|
||||
"to": { "groupId": "cl26lidjz000a2e6etf4v03hv" },
|
||||
"from": {
|
||||
"stepId": "cl26li8fj0001iez0bqfraw9h",
|
||||
"blockId": "cl26li8fj0000iez05x7razkg"
|
||||
"blockId": "cl26li8fj0001iez0bqfraw9h",
|
||||
"groupId": "cl26li8fj0000iez05x7razkg"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
defaultTheme,
|
||||
PublicTypebot,
|
||||
SmtpCredentialsData,
|
||||
Step,
|
||||
Block,
|
||||
Typebot,
|
||||
Webhook,
|
||||
} from 'models'
|
||||
@@ -92,7 +92,7 @@ const parseTypebotToPublicTypebot = (
|
||||
typebot: Typebot
|
||||
): PublicTypebot => ({
|
||||
id,
|
||||
blocks: typebot.blocks,
|
||||
groups: typebot.groups,
|
||||
typebotId: typebot.id,
|
||||
theme: typebot.theme,
|
||||
settings: typebot.settings,
|
||||
@@ -120,44 +120,44 @@ const parseTestTypebot = (partialTypebot: Partial<Typebot>): Typebot => ({
|
||||
edges: [
|
||||
{
|
||||
id: 'edge1',
|
||||
from: { blockId: 'block0', stepId: 'step0' },
|
||||
to: { blockId: 'block1' },
|
||||
from: { groupId: 'group0', blockId: 'block0' },
|
||||
to: { groupId: 'group1' },
|
||||
},
|
||||
],
|
||||
blocks: [
|
||||
groups: [
|
||||
{
|
||||
id: 'block0',
|
||||
title: 'Block #0',
|
||||
steps: [
|
||||
id: 'group0',
|
||||
title: 'Group #0',
|
||||
blocks: [
|
||||
{
|
||||
id: 'step0',
|
||||
id: 'block0',
|
||||
type: 'start',
|
||||
blockId: 'block0',
|
||||
groupId: 'group0',
|
||||
label: 'Start',
|
||||
outgoingEdgeId: 'edge1',
|
||||
},
|
||||
],
|
||||
graphCoordinates: { x: 0, y: 0 },
|
||||
},
|
||||
...(partialTypebot.blocks ?? []),
|
||||
...(partialTypebot.groups ?? []),
|
||||
],
|
||||
})
|
||||
|
||||
export const parseDefaultBlockWithStep = (
|
||||
step: Partial<Step>
|
||||
): Pick<Typebot, 'blocks'> => ({
|
||||
blocks: [
|
||||
export const parseDefaultGroupWithBlock = (
|
||||
block: Partial<Block>
|
||||
): Pick<Typebot, 'groups'> => ({
|
||||
groups: [
|
||||
{
|
||||
graphCoordinates: { x: 200, y: 200 },
|
||||
id: 'block1',
|
||||
steps: [
|
||||
id: 'group1',
|
||||
blocks: [
|
||||
{
|
||||
id: 'step1',
|
||||
blockId: 'block1',
|
||||
...step,
|
||||
} as Step,
|
||||
id: 'block1',
|
||||
groupId: 'group1',
|
||||
...block,
|
||||
} as Block,
|
||||
],
|
||||
title: 'Block #1',
|
||||
title: 'Group #1',
|
||||
},
|
||||
],
|
||||
})
|
||||
@@ -209,8 +209,8 @@ const createAnswers = () => {
|
||||
...Array.from(Array(200)).map((_, idx) => ({
|
||||
resultId: `result${idx}`,
|
||||
content: `content${idx}`,
|
||||
stepId: 'step1',
|
||||
blockId: 'block1',
|
||||
groupId: 'group1',
|
||||
})),
|
||||
],
|
||||
})
|
||||
|
||||
@@ -34,7 +34,7 @@ test('can list typebots', async ({ request }) => {
|
||||
})
|
||||
})
|
||||
|
||||
test('can get webhook steps', async ({ request }) => {
|
||||
test('can get webhook blocks', async ({ request }) => {
|
||||
expect(
|
||||
(await request.get(`/api/typebots/${typebotId}/webhookBlocks`)).status()
|
||||
).toBe(401)
|
||||
@@ -47,8 +47,8 @@ test('can get webhook steps', async ({ request }) => {
|
||||
const { blocks } = await response.json()
|
||||
expect(blocks).toHaveLength(1)
|
||||
expect(blocks[0]).toEqual({
|
||||
blockId: 'webhookStep',
|
||||
name: 'Webhook > webhookStep',
|
||||
blockId: 'webhookBlock',
|
||||
name: 'Webhook > webhookBlock',
|
||||
})
|
||||
})
|
||||
|
||||
@@ -56,13 +56,13 @@ test('can subscribe webhook', async ({ request }) => {
|
||||
expect(
|
||||
(
|
||||
await request.post(
|
||||
`/api/typebots/${typebotId}/blocks/webhookStep/subscribeWebhook`,
|
||||
`/api/typebots/${typebotId}/blocks/webhookBlock/subscribeWebhook`,
|
||||
{ data: { url: 'https://test.com' } }
|
||||
)
|
||||
).status()
|
||||
).toBe(401)
|
||||
const response = await request.post(
|
||||
`/api/typebots/${typebotId}/blocks/webhookStep/subscribeWebhook`,
|
||||
`/api/typebots/${typebotId}/blocks/webhookBlock/subscribeWebhook`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: 'Bearer userToken',
|
||||
@@ -80,12 +80,12 @@ test('can unsubscribe webhook', async ({ request }) => {
|
||||
expect(
|
||||
(
|
||||
await request.post(
|
||||
`/api/typebots/${typebotId}/blocks/webhookStep/unsubscribeWebhook`
|
||||
`/api/typebots/${typebotId}/blocks/webhookBlock/unsubscribeWebhook`
|
||||
)
|
||||
).status()
|
||||
).toBe(401)
|
||||
const response = await request.post(
|
||||
`/api/typebots/${typebotId}/blocks/webhookStep/unsubscribeWebhook`,
|
||||
`/api/typebots/${typebotId}/blocks/webhookBlock/unsubscribeWebhook`,
|
||||
{
|
||||
headers: { Authorization: 'Bearer userToken' },
|
||||
}
|
||||
@@ -100,12 +100,12 @@ test('can get a sample result', async ({ request }) => {
|
||||
expect(
|
||||
(
|
||||
await request.get(
|
||||
`/api/typebots/${typebotId}/blocks/webhookStep/sampleResult`
|
||||
`/api/typebots/${typebotId}/blocks/webhookBlock/sampleResult`
|
||||
)
|
||||
).status()
|
||||
).toBe(401)
|
||||
const response = await request.get(
|
||||
`/api/typebots/${typebotId}/blocks/webhookStep/sampleResult`,
|
||||
`/api/typebots/${typebotId}/blocks/webhookBlock/sampleResult`,
|
||||
{
|
||||
headers: { Authorization: 'Bearer userToken' },
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import cuid from 'cuid'
|
||||
test('should work as expected', async ({ page }) => {
|
||||
const typebotId = cuid()
|
||||
await importTypebotInDatabase(
|
||||
path.join(__dirname, '../fixtures/typebots/hugeBlock.json'),
|
||||
path.join(__dirname, '../fixtures/typebots/hugeGroup.json'),
|
||||
{ id: typebotId, publicId: `${typebotId}-public` }
|
||||
)
|
||||
await page.goto(`/${typebotId}-public`)
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import test, { expect } from '@playwright/test'
|
||||
import { createTypebots, parseDefaultBlockWithStep } from '../services/database'
|
||||
import {
|
||||
createTypebots,
|
||||
parseDefaultGroupWithBlock,
|
||||
} from '../services/database'
|
||||
import {
|
||||
defaultSettings,
|
||||
defaultTextInputOptions,
|
||||
InputStepType,
|
||||
InputBlockType,
|
||||
Metadata,
|
||||
} from 'models'
|
||||
import { typebotViewer } from '../services/selectorUtils'
|
||||
@@ -24,8 +27,8 @@ test('Should correctly parse metadata', async ({ page }) => {
|
||||
...defaultSettings,
|
||||
metadata: customMetadata,
|
||||
},
|
||||
...parseDefaultBlockWithStep({
|
||||
type: InputStepType.TEXT,
|
||||
...parseDefaultGroupWithBlock({
|
||||
type: InputBlockType.TEXT,
|
||||
options: defaultTextInputOptions,
|
||||
}),
|
||||
},
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
import test, { expect } from '@playwright/test'
|
||||
import {
|
||||
createTypebots,
|
||||
parseDefaultBlockWithStep,
|
||||
parseDefaultGroupWithBlock,
|
||||
updateTypebot,
|
||||
} from '../services/database'
|
||||
import cuid from 'cuid'
|
||||
import { defaultSettings, defaultTextInputOptions, InputStepType } from 'models'
|
||||
import {
|
||||
defaultSettings,
|
||||
defaultTextInputOptions,
|
||||
InputBlockType,
|
||||
} from 'models'
|
||||
|
||||
test('Result should be in storage by default', async ({ page }) => {
|
||||
const typebotId = cuid()
|
||||
await createTypebots([
|
||||
{
|
||||
id: typebotId,
|
||||
...parseDefaultBlockWithStep({
|
||||
type: InputStepType.TEXT,
|
||||
...parseDefaultGroupWithBlock({
|
||||
type: InputBlockType.TEXT,
|
||||
options: defaultTextInputOptions,
|
||||
}),
|
||||
},
|
||||
@@ -45,8 +49,8 @@ test.describe('Create result on page refresh enabled', () => {
|
||||
isNewResultOnRefreshEnabled: true,
|
||||
},
|
||||
},
|
||||
...parseDefaultBlockWithStep({
|
||||
type: InputStepType.TEXT,
|
||||
...parseDefaultGroupWithBlock({
|
||||
type: InputBlockType.TEXT,
|
||||
options: defaultTextInputOptions,
|
||||
}),
|
||||
},
|
||||
@@ -81,8 +85,8 @@ test('Hide query params', async ({ page }) => {
|
||||
await createTypebots([
|
||||
{
|
||||
id: typebotId,
|
||||
...parseDefaultBlockWithStep({
|
||||
type: InputStepType.TEXT,
|
||||
...parseDefaultGroupWithBlock({
|
||||
type: InputBlockType.TEXT,
|
||||
options: defaultTextInputOptions,
|
||||
}),
|
||||
},
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import { User } from 'db'
|
||||
import prisma from 'libs/prisma'
|
||||
import { LogicStepType, Typebot, TypebotLinkStep, PublicTypebot } from 'models'
|
||||
import {
|
||||
LogicBlockType,
|
||||
Typebot,
|
||||
TypebotLinkBlock,
|
||||
PublicTypebot,
|
||||
} from 'models'
|
||||
import { NextApiRequest } from 'next'
|
||||
import { isDefined } from 'utils'
|
||||
import { canReadTypebots } from './dbRules'
|
||||
@@ -63,13 +68,13 @@ export const getLinkedTypebots = async (
|
||||
user?: User
|
||||
): Promise<(Typebot | PublicTypebot)[]> => {
|
||||
const linkedTypebotIds = (
|
||||
typebot.blocks
|
||||
.flatMap((b) => b.steps)
|
||||
typebot.groups
|
||||
.flatMap((g) => g.blocks)
|
||||
.filter(
|
||||
(s) =>
|
||||
s.type === LogicStepType.TYPEBOT_LINK &&
|
||||
s.type === LogicBlockType.TYPEBOT_LINK &&
|
||||
isDefined(s.options.typebotId)
|
||||
) as TypebotLinkStep[]
|
||||
) as TypebotLinkBlock[]
|
||||
).map((s) => s.options.typebotId as string)
|
||||
if (linkedTypebotIds.length === 0) return []
|
||||
const typebots = (await ('typebotId' in typebot
|
||||
|
||||
@@ -1,71 +1,71 @@
|
||||
import {
|
||||
InputStep,
|
||||
InputStepType,
|
||||
LogicStepType,
|
||||
InputBlock,
|
||||
InputBlockType,
|
||||
LogicBlockType,
|
||||
PublicTypebot,
|
||||
ResultHeaderCell,
|
||||
Step,
|
||||
Block,
|
||||
Typebot,
|
||||
TypebotLinkStep,
|
||||
TypebotLinkBlock,
|
||||
} from 'models'
|
||||
import { isInputStep, byId, parseResultHeader, isNotDefined } from 'utils'
|
||||
import { isInputBlock, byId, parseResultHeader, isNotDefined } from 'utils'
|
||||
|
||||
export const parseSampleResult =
|
||||
(
|
||||
typebot: Pick<Typebot | PublicTypebot, 'blocks' | 'variables' | 'edges'>,
|
||||
typebot: Pick<Typebot | PublicTypebot, 'groups' | 'variables' | 'edges'>,
|
||||
linkedTypebots: (Typebot | PublicTypebot)[]
|
||||
) =>
|
||||
async (
|
||||
currentBlockId: string
|
||||
currentGroupId: string
|
||||
): Promise<Record<string, string | boolean | undefined>> => {
|
||||
const header = parseResultHeader({
|
||||
blocks: [...typebot.blocks, ...linkedTypebots.flatMap((t) => t.blocks)],
|
||||
groups: [...typebot.groups, ...linkedTypebots.flatMap((t) => t.groups)],
|
||||
variables: [
|
||||
...typebot.variables,
|
||||
...linkedTypebots.flatMap((t) => t.variables),
|
||||
],
|
||||
})
|
||||
const linkedInputSteps = await extractLinkedInputSteps(
|
||||
const linkedInputBlocks = await extractLinkedInputBlocks(
|
||||
typebot,
|
||||
linkedTypebots
|
||||
)(currentBlockId)
|
||||
)(currentGroupId)
|
||||
|
||||
return {
|
||||
message: 'This is a sample result, it has been generated ⬇️',
|
||||
'Submitted at': new Date().toISOString(),
|
||||
...parseBlocksResultSample(linkedInputSteps, header),
|
||||
...parseGroupsResultSample(linkedInputBlocks, header),
|
||||
}
|
||||
}
|
||||
|
||||
const extractLinkedInputSteps =
|
||||
const extractLinkedInputBlocks =
|
||||
(
|
||||
typebot: Pick<Typebot | PublicTypebot, 'blocks' | 'variables' | 'edges'>,
|
||||
typebot: Pick<Typebot | PublicTypebot, 'groups' | 'variables' | 'edges'>,
|
||||
linkedTypebots: (Typebot | PublicTypebot)[]
|
||||
) =>
|
||||
async (
|
||||
currentBlockId?: string,
|
||||
currentGroupId?: string,
|
||||
direction: 'backward' | 'forward' = 'backward'
|
||||
): Promise<InputStep[]> => {
|
||||
const previousLinkedTypebotSteps = walkEdgesAndExtract(
|
||||
): Promise<InputBlock[]> => {
|
||||
const previousLinkedTypebotBlocks = walkEdgesAndExtract(
|
||||
'linkedBot',
|
||||
direction,
|
||||
typebot
|
||||
)({
|
||||
blockId: currentBlockId,
|
||||
}) as TypebotLinkStep[]
|
||||
groupId: currentGroupId,
|
||||
}) as TypebotLinkBlock[]
|
||||
|
||||
const linkedBotInputs =
|
||||
previousLinkedTypebotSteps.length > 0
|
||||
previousLinkedTypebotBlocks.length > 0
|
||||
? await Promise.all(
|
||||
previousLinkedTypebotSteps.map((linkedBot) =>
|
||||
extractLinkedInputSteps(
|
||||
previousLinkedTypebotBlocks.map((linkedBot) =>
|
||||
extractLinkedInputBlocks(
|
||||
linkedTypebots.find((t) =>
|
||||
'typebotId' in t
|
||||
? t.typebotId === linkedBot.options.typebotId
|
||||
: t.id === linkedBot.options.typebotId
|
||||
) as Typebot | PublicTypebot,
|
||||
linkedTypebots
|
||||
)(linkedBot.options.blockId, 'forward')
|
||||
)(linkedBot.options.groupId, 'forward')
|
||||
)
|
||||
)
|
||||
: []
|
||||
@@ -76,49 +76,52 @@ const extractLinkedInputSteps =
|
||||
direction,
|
||||
typebot
|
||||
)({
|
||||
blockId: currentBlockId,
|
||||
}) as InputStep[]
|
||||
groupId: currentGroupId,
|
||||
}) as InputBlock[]
|
||||
).concat(linkedBotInputs.flatMap((l) => l))
|
||||
}
|
||||
|
||||
const parseBlocksResultSample = (
|
||||
inputSteps: InputStep[],
|
||||
const parseGroupsResultSample = (
|
||||
inputBlocks: InputBlock[],
|
||||
header: ResultHeaderCell[]
|
||||
) =>
|
||||
header.reduce<Record<string, string | boolean | undefined>>((steps, cell) => {
|
||||
const inputStep = inputSteps.find((step) => step.id === cell.stepId)
|
||||
if (isNotDefined(inputStep)) {
|
||||
if (cell.variableId)
|
||||
return {
|
||||
...steps,
|
||||
[cell.label]: 'content',
|
||||
}
|
||||
return steps
|
||||
}
|
||||
const value = getSampleValue(inputStep)
|
||||
return {
|
||||
...steps,
|
||||
[cell.label]: value,
|
||||
}
|
||||
}, {})
|
||||
header.reduce<Record<string, string | boolean | undefined>>(
|
||||
(blocks, cell) => {
|
||||
const inputBlock = inputBlocks.find((block) => block.id === cell.blockId)
|
||||
if (isNotDefined(inputBlock)) {
|
||||
if (cell.variableId)
|
||||
return {
|
||||
...blocks,
|
||||
[cell.label]: 'content',
|
||||
}
|
||||
return blocks
|
||||
}
|
||||
const value = getSampleValue(inputBlock)
|
||||
return {
|
||||
...blocks,
|
||||
[cell.label]: value,
|
||||
}
|
||||
},
|
||||
{}
|
||||
)
|
||||
|
||||
const getSampleValue = (step: InputStep) => {
|
||||
switch (step.type) {
|
||||
case InputStepType.CHOICE:
|
||||
return step.options.isMultipleChoice
|
||||
? step.items.map((i) => i.content).join(', ')
|
||||
: step.items[0]?.content ?? 'Item'
|
||||
case InputStepType.DATE:
|
||||
const getSampleValue = (block: InputBlock) => {
|
||||
switch (block.type) {
|
||||
case InputBlockType.CHOICE:
|
||||
return block.options.isMultipleChoice
|
||||
? block.items.map((i) => i.content).join(', ')
|
||||
: block.items[0]?.content ?? 'Item'
|
||||
case InputBlockType.DATE:
|
||||
return new Date().toUTCString()
|
||||
case InputStepType.EMAIL:
|
||||
case InputBlockType.EMAIL:
|
||||
return 'test@email.com'
|
||||
case InputStepType.NUMBER:
|
||||
case InputBlockType.NUMBER:
|
||||
return '20'
|
||||
case InputStepType.PHONE:
|
||||
case InputBlockType.PHONE:
|
||||
return '+33665566773'
|
||||
case InputStepType.TEXT:
|
||||
case InputBlockType.TEXT:
|
||||
return 'answer value'
|
||||
case InputStepType.URL:
|
||||
case InputBlockType.URL:
|
||||
return 'https://test.com'
|
||||
}
|
||||
}
|
||||
@@ -127,67 +130,67 @@ const walkEdgesAndExtract =
|
||||
(
|
||||
type: 'input' | 'linkedBot',
|
||||
direction: 'backward' | 'forward',
|
||||
typebot: Pick<Typebot | PublicTypebot, 'blocks' | 'variables' | 'edges'>
|
||||
typebot: Pick<Typebot | PublicTypebot, 'groups' | 'variables' | 'edges'>
|
||||
) =>
|
||||
({ blockId }: { blockId?: string }): Step[] => {
|
||||
const currentBlockId =
|
||||
blockId ??
|
||||
(typebot.blocks.find((b) => b.steps[0].type === 'start')?.id as string)
|
||||
const stepsInBlock = extractStepsInBlock(
|
||||
({ groupId }: { groupId?: string }): Block[] => {
|
||||
const currentGroupId =
|
||||
groupId ??
|
||||
(typebot.groups.find((b) => b.blocks[0].type === 'start')?.id as string)
|
||||
const blocksInGroup = extractBlocksInGroup(
|
||||
type,
|
||||
typebot
|
||||
)({
|
||||
blockId: currentBlockId,
|
||||
groupId: currentGroupId,
|
||||
})
|
||||
const otherBlockIds = getBlockIds(typebot, direction)(currentBlockId)
|
||||
const otherGroupIds = getGroupIds(typebot, direction)(currentGroupId)
|
||||
return [
|
||||
...stepsInBlock,
|
||||
...otherBlockIds.flatMap((blockId) =>
|
||||
extractStepsInBlock(type, typebot)({ blockId })
|
||||
...blocksInGroup,
|
||||
...otherGroupIds.flatMap((groupId) =>
|
||||
extractBlocksInGroup(type, typebot)({ groupId })
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
const getBlockIds =
|
||||
const getGroupIds =
|
||||
(
|
||||
typebot: Pick<Typebot | PublicTypebot, 'blocks' | 'variables' | 'edges'>,
|
||||
typebot: Pick<Typebot | PublicTypebot, 'groups' | 'variables' | 'edges'>,
|
||||
direction: 'backward' | 'forward',
|
||||
existingBlockIds?: string[]
|
||||
existingGroupIds?: string[]
|
||||
) =>
|
||||
(blockId: string): string[] => {
|
||||
const blocks = typebot.edges.reduce<string[]>((blockIds, edge) => {
|
||||
(groupId: string): string[] => {
|
||||
const groups = typebot.edges.reduce<string[]>((groupIds, edge) => {
|
||||
if (direction === 'forward')
|
||||
return (!existingBlockIds ||
|
||||
!existingBlockIds?.includes(edge.to.blockId)) &&
|
||||
edge.from.blockId === blockId
|
||||
? [...blockIds, edge.to.blockId]
|
||||
: blockIds
|
||||
return (!existingBlockIds ||
|
||||
!existingBlockIds.includes(edge.from.blockId)) &&
|
||||
edge.to.blockId === blockId
|
||||
? [...blockIds, edge.from.blockId]
|
||||
: blockIds
|
||||
return (!existingGroupIds ||
|
||||
!existingGroupIds?.includes(edge.to.groupId)) &&
|
||||
edge.from.groupId === groupId
|
||||
? [...groupIds, edge.to.groupId]
|
||||
: groupIds
|
||||
return (!existingGroupIds ||
|
||||
!existingGroupIds.includes(edge.from.groupId)) &&
|
||||
edge.to.groupId === groupId
|
||||
? [...groupIds, edge.from.groupId]
|
||||
: groupIds
|
||||
}, [])
|
||||
const newBlocks = [...(existingBlockIds ?? []), ...blocks]
|
||||
return blocks.concat(
|
||||
blocks.flatMap(getBlockIds(typebot, direction, newBlocks))
|
||||
const newGroups = [...(existingGroupIds ?? []), ...groups]
|
||||
return groups.concat(
|
||||
groups.flatMap(getGroupIds(typebot, direction, newGroups))
|
||||
)
|
||||
}
|
||||
|
||||
const extractStepsInBlock =
|
||||
const extractBlocksInGroup =
|
||||
(
|
||||
type: 'input' | 'linkedBot',
|
||||
typebot: Pick<Typebot | PublicTypebot, 'blocks' | 'variables' | 'edges'>
|
||||
typebot: Pick<Typebot | PublicTypebot, 'groups' | 'variables' | 'edges'>
|
||||
) =>
|
||||
({ blockId, stepId }: { blockId: string; stepId?: string }) => {
|
||||
const currentBlock = typebot.blocks.find(byId(blockId))
|
||||
if (!currentBlock) return []
|
||||
const steps: Step[] = []
|
||||
for (const step of currentBlock.steps) {
|
||||
if (step.id === stepId) break
|
||||
if (type === 'input' && isInputStep(step)) steps.push(step)
|
||||
if (type === 'linkedBot' && step.type === LogicStepType.TYPEBOT_LINK)
|
||||
steps.push(step)
|
||||
({ groupId, blockId }: { groupId: string; blockId?: string }) => {
|
||||
const currentGroup = typebot.groups.find(byId(groupId))
|
||||
if (!currentGroup) return []
|
||||
const blocks: Block[] = []
|
||||
for (const block of currentGroup.blocks) {
|
||||
if (block.id === blockId) break
|
||||
if (type === 'input' && isInputBlock(block)) blocks.push(block)
|
||||
if (type === 'linkedBot' && block.type === LogicBlockType.TYPEBOT_LINK)
|
||||
blocks.push(block)
|
||||
}
|
||||
return steps
|
||||
return blocks
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user