+ keyValues: KeyValue[] | undefined,
+ variables: Variable[]
) => {
if (!keyValues) return
- return keyValues.allIds.reduce((object, id) => {
- const item = keyValues.byId[id]
+ return keyValues.reduce((object, item) => {
if (!item.key) return {}
return {
...object,
diff --git a/apps/builder/pages/api/typebots/[typebotId]/results/answers/count.ts b/apps/builder/pages/api/typebots/[typebotId]/results/answers/count.ts
index 93784d3f4..ada2e72f3 100644
--- a/apps/builder/pages/api/typebots/[typebotId]/results/answers/count.ts
+++ b/apps/builder/pages/api/typebots/[typebotId]/results/answers/count.ts
@@ -24,14 +24,14 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const answersCounts: { blockId: string; totalAnswers: number }[] =
await Promise.all(
- (
- typebot.publishedTypebot as unknown as PublicTypebot
- ).blocks.allIds.map(async (blockId) => {
- const totalAnswers = await prisma.answer.count({
- where: { blockId },
- })
- return { blockId, totalAnswers }
- })
+ (typebot.publishedTypebot as unknown as PublicTypebot).blocks.map(
+ async (block) => {
+ const totalAnswers = await prisma.answer.count({
+ where: { blockId: block.id },
+ })
+ return { blockId: block.id, totalAnswers }
+ }
+ )
)
return res.status(200).send({ answersCounts })
}
diff --git a/apps/builder/playwright.config.ts b/apps/builder/playwright.config.ts
index c038a910e..9b3126666 100644
--- a/apps/builder/playwright.config.ts
+++ b/apps/builder/playwright.config.ts
@@ -8,8 +8,8 @@ const config: PlaywrightTestConfig = {
expect: {
timeout: 5000,
},
- retries: 2,
- workers: process.env.CI ? 1 : undefined,
+ retries: process.env.NO_RETRIES ? 0 : 2,
+ workers: process.env.CI ? 1 : 3,
reporter: 'html',
maxFailures: process.env.CI ? 10 : undefined,
use: {
diff --git a/apps/builder/playwright/fixtures/typebots/editor/buttonsDnd.json b/apps/builder/playwright/fixtures/typebots/editor/buttonsDnd.json
new file mode 100644
index 000000000..c793c8a9d
--- /dev/null
+++ b/apps/builder/playwright/fixtures/typebots/editor/buttonsDnd.json
@@ -0,0 +1,185 @@
+{
+ "id": "ckz84wbbj2095no1ali9kzfz4",
+ "createdAt": "2022-02-04T08:16:59.215Z",
+ "updatedAt": "2022-02-04T08:16:59.215Z",
+ "name": "My typebot",
+ "ownerId": "ckz6t9iep0006k31a22j05fwq",
+ "publishedTypebotId": null,
+ "folderId": null,
+ "blocks": [
+ {
+ "id": "de8iZbvNxMxyhvLrnPBpt8",
+ "steps": [
+ {
+ "id": "hqgG9FuPDWrkrdHXFnSy9G",
+ "type": "start",
+ "label": "Start",
+ "blockId": "de8iZbvNxMxyhvLrnPBpt8",
+ "outgoingEdgeId": "41aa19ih9WQQQEurwdjmVJ"
+ }
+ ],
+ "title": "Start",
+ "graphCoordinates": { "x": 0, "y": 0 }
+ },
+ {
+ "id": "vmDTsAC7aLeqanVVtJ9yQx",
+ "graphCoordinates": { "x": 85, "y": 220 },
+ "title": "Block #1",
+ "steps": [
+ {
+ "id": "sqUp2x8SXx8JBC8a9XuKGL9",
+ "blockId": "vmDTsAC7aLeqanVVtJ9yQx",
+ "type": "text",
+ "content": {
+ "html": "Hello!
",
+ "richText": [{ "type": "p", "children": [{ "text": "Hello!" }] }],
+ "plainText": "Hello!"
+ }
+ },
+ {
+ "id": "suRXuWyuJ7kpsdLUYKA6VqM",
+ "blockId": "vmDTsAC7aLeqanVVtJ9yQx",
+ "type": "text",
+ "content": {
+ "html": "How are you?
",
+ "richText": [
+ { "type": "p", "children": [{ "text": "How are you?" }] }
+ ],
+ "plainText": "How are you?"
+ }
+ },
+ {
+ "id": "ssxDdzVUkgZYPPoPnQK4dCo",
+ "blockId": "vmDTsAC7aLeqanVVtJ9yQx",
+ "type": "choice input",
+ "options": { "buttonLabel": "Send", "isMultipleChoice": false },
+ "items": [
+ {
+ "id": "e7dy3bH2py8fFcak2jUJjr",
+ "stepId": "ssxDdzVUkgZYPPoPnQK4dCo",
+ "type": 0,
+ "content": "Item 1",
+ "outgoingEdgeId": "8Ty7noiTJAP3jtaWXLsNwy"
+ },
+ {
+ "stepId": "ssxDdzVUkgZYPPoPnQK4dCo",
+ "type": 0,
+ "id": "mBJkTavGHAygmPTjiLMQyC",
+ "content": "Item 2"
+ },
+ {
+ "stepId": "ssxDdzVUkgZYPPoPnQK4dCo",
+ "type": 0,
+ "id": "vVfToFyNLyGgRYyB8jYLkn",
+ "content": "Item 3",
+ "outgoingEdgeId": "tprSzPvt6A5kTFf7iUNaeR"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id": "hB4p8rwA1dUSq9A5ctTLqh",
+ "graphCoordinates": { "x": 513, "y": 152 },
+ "title": "Block #2",
+ "steps": [
+ {
+ "id": "suHw7fjcMD9KjDRpbB413jn",
+ "blockId": "hB4p8rwA1dUSq9A5ctTLqh",
+ "type": "Condition",
+ "items": [
+ {
+ "id": "jvGN6sfftqJgfYYVRUYMuJ",
+ "stepId": "suHw7fjcMD9KjDRpbB413jn",
+ "type": 1,
+ "content": { "comparisons": [], "logicalOperator": "AND" }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id": "t7g44CwVvCg6mN16KHVAWv",
+ "graphCoordinates": { "x": 509, "y": 489 },
+ "title": "Block #3",
+ "steps": [
+ {
+ "id": "suHztCMVss4kTAtgShANxjU",
+ "blockId": "t7g44CwVvCg6mN16KHVAWv",
+ "type": "choice input",
+ "options": { "buttonLabel": "Send", "isMultipleChoice": false },
+ "items": [
+ {
+ "id": "buQjAL2M3cBUVK2ofnxKW3",
+ "stepId": "suHztCMVss4kTAtgShANxjU",
+ "type": 0,
+ "content": "Item 2-1"
+ },
+ {
+ "stepId": "suHztCMVss4kTAtgShANxjU",
+ "type": 0,
+ "id": "4gQe9XK1vyQUHXVzFErW4t",
+ "content": "Item 2-2"
+ },
+ {
+ "stepId": "suHztCMVss4kTAtgShANxjU",
+ "type": 0,
+ "id": "uttagH8w5XWzibkKsW23oi",
+ "content": "Item 2-3"
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "variables": [],
+ "edges": [
+ {
+ "from": {
+ "blockId": "de8iZbvNxMxyhvLrnPBpt8",
+ "stepId": "hqgG9FuPDWrkrdHXFnSy9G"
+ },
+ "to": { "blockId": "vmDTsAC7aLeqanVVtJ9yQx" },
+ "id": "41aa19ih9WQQQEurwdjmVJ"
+ },
+ {
+ "from": {
+ "blockId": "vmDTsAC7aLeqanVVtJ9yQx",
+ "stepId": "ssxDdzVUkgZYPPoPnQK4dCo",
+ "itemId": "e7dy3bH2py8fFcak2jUJjr"
+ },
+ "to": { "blockId": "hB4p8rwA1dUSq9A5ctTLqh" },
+ "id": "8Ty7noiTJAP3jtaWXLsNwy"
+ },
+ {
+ "from": {
+ "blockId": "vmDTsAC7aLeqanVVtJ9yQx",
+ "stepId": "ssxDdzVUkgZYPPoPnQK4dCo",
+ "itemId": "vVfToFyNLyGgRYyB8jYLkn"
+ },
+ "to": { "blockId": "t7g44CwVvCg6mN16KHVAWv" },
+ "id": "tprSzPvt6A5kTFf7iUNaeR"
+ }
+ ],
+ "theme": {
+ "chat": {
+ "inputs": {
+ "color": "#303235",
+ "backgroundColor": "#FFFFFF",
+ "placeholderColor": "#9095A0"
+ },
+ "buttons": { "color": "#FFFFFF", "backgroundColor": "#0042DA" },
+ "hostBubbles": { "color": "#303235", "backgroundColor": "#F7F8FF" },
+ "guestBubbles": { "color": "#FFFFFF", "backgroundColor": "#FF8E21" }
+ },
+ "general": { "font": "Open Sans", "background": { "type": "None" } }
+ },
+ "settings": {
+ "general": { "isBrandingEnabled": true },
+ "metadata": {
+ "description": "Build beautiful conversational forms and embed them directly in your applications without a line of code. Triple your response rate and collect answers that has more value compared to a traditional form."
+ },
+ "typingEmulation": { "speed": 300, "enabled": true, "maxDelay": 1.5 }
+ },
+ "publicId": null
+}
diff --git a/apps/builder/playwright/fixtures/typebots/integrations/googleSheets.json b/apps/builder/playwright/fixtures/typebots/integrations/googleSheets.json
index ee6a36063..4c8989e23 100644
--- a/apps/builder/playwright/fixtures/typebots/integrations/googleSheets.json
+++ b/apps/builder/playwright/fixtures/typebots/integrations/googleSheets.json
@@ -1,98 +1,76 @@
{
- "id": "ckylszb9z0354z31a623dg7ji",
- "createdAt": "2022-01-19T17:12:27.863Z",
- "updatedAt": "2022-01-19T17:12:27.863Z",
+ "id": "ckz8gg4n39573no1aa5rsfyp1",
+ "createdAt": "2022-02-04T13:40:19.455Z",
+ "updatedAt": "2022-02-04T13:40:19.455Z",
"name": "My typebot",
- "ownerId": "ckylsz8yy0335z31amvq0jwtt",
+ "ownerId": "ckz6t9iep0006k31a22j05fwq",
"publishedTypebotId": null,
"folderId": null,
- "webhooks": { "byId": {}, "allIds": [] },
- "blocks": {
- "byId": {
- "j24wz82YG3rjXMgrmCiTLy": {
- "id": "j24wz82YG3rjXMgrmCiTLy",
- "title": "Start",
- "stepIds": ["1NdXPCiRicqDA8k4JfnXfi"],
- "graphCoordinates": { "x": 0, "y": 0 }
- },
- "bmaKTUXkT2cc3wtKfK7ra71": {
- "id": "bmaKTUXkT2cc3wtKfK7ra71",
- "title": "Block #2",
- "graphCoordinates": { "x": 175, "y": 197 },
- "stepIds": ["spHxPWbSqkVZW9gqH86ovC5"]
- },
- "bnt8fM5Wgc8gBg2iSmUcfJu": {
- "id": "bnt8fM5Wgc8gBg2iSmUcfJu",
- "title": "Block #3",
- "graphCoordinates": { "x": 504, "y": 347 },
- "stepIds": ["siPoEE9H27hVHqykth3a7Kj"]
- }
+ "blocks": [
+ {
+ "id": "bSHn2HQZ1sKji5pd9Nmejf",
+ "steps": [
+ {
+ "id": "qYmbSFBxCvGCgTvQTg9HeH",
+ "type": "start",
+ "label": "Start",
+ "blockId": "bSHn2HQZ1sKji5pd9Nmejf",
+ "outgoingEdgeId": "jdQnqJK4b559rTJzHHhjcz"
+ }
+ ],
+ "title": "Start",
+ "graphCoordinates": { "x": 0, "y": 0 }
},
- "allIds": [
- "j24wz82YG3rjXMgrmCiTLy",
- "bmaKTUXkT2cc3wtKfK7ra71",
- "bnt8fM5Wgc8gBg2iSmUcfJu"
- ]
- },
- "steps": {
- "byId": {
- "1NdXPCiRicqDA8k4JfnXfi": {
- "id": "1NdXPCiRicqDA8k4JfnXfi",
- "type": "start",
- "label": "Start",
- "blockId": "j24wz82YG3rjXMgrmCiTLy",
- "edgeId": "benDCcLMUWNvi6Fg6CXE9H"
- },
- "spHxPWbSqkVZW9gqH86ovC5": {
- "id": "spHxPWbSqkVZW9gqH86ovC5",
- "blockId": "bmaKTUXkT2cc3wtKfK7ra71",
- "type": "email input",
- "options": { "variableId": "oexLr4sJQNVdSnYCGgGRB3" },
- "edgeId": "6Tax9rw7L8kmRn9JRD2Mrg"
- },
- "siPoEE9H27hVHqykth3a7Kj": {
- "id": "siPoEE9H27hVHqykth3a7Kj",
- "blockId": "bnt8fM5Wgc8gBg2iSmUcfJu",
- "type": "Google Sheets"
- }
+ {
+ "id": "mSvUFogQH16bQDN1iGWF66",
+ "graphCoordinates": { "x": 324, "y": 209 },
+ "title": "Block #1",
+ "steps": [
+ {
+ "id": "spDLmDCZfNJu4DrZ1MUg84c",
+ "blockId": "mSvUFogQH16bQDN1iGWF66",
+ "type": "email input",
+ "options": {
+ "labels": { "button": "Send", "placeholder": "Type your email..." },
+ "variableId": "qyLW6xD1AyLeedso2tHmhw"
+ },
+ "outgoingEdgeId": "4yg9V76fdDntpDEw6H3tvU"
+ }
+ ]
},
- "allIds": [
- "1NdXPCiRicqDA8k4JfnXfi",
- "spHxPWbSqkVZW9gqH86ovC5",
- "siPoEE9H27hVHqykth3a7Kj"
- ]
- },
- "choiceItems": { "byId": {}, "allIds": [] },
- "variables": {
- "byId": {
- "oexLr4sJQNVdSnYCGgGRB3": {
- "id": "oexLr4sJQNVdSnYCGgGRB3",
- "name": "Email"
- }
- },
- "allIds": ["oexLr4sJQNVdSnYCGgGRB3"]
- },
- "edges": {
- "byId": {
- "benDCcLMUWNvi6Fg6CXE9H": {
- "from": {
- "blockId": "j24wz82YG3rjXMgrmCiTLy",
- "stepId": "1NdXPCiRicqDA8k4JfnXfi"
- },
- "to": { "blockId": "bmaKTUXkT2cc3wtKfK7ra71" },
- "id": "benDCcLMUWNvi6Fg6CXE9H"
+ {
+ "id": "jd4S6BQsUQ2RuKieHXYKs9",
+ "graphCoordinates": { "x": 655, "y": 363 },
+ "title": "Block #2",
+ "steps": [
+ {
+ "id": "s1ZvUqWxV6b8UgFGYWh39pV",
+ "blockId": "jd4S6BQsUQ2RuKieHXYKs9",
+ "type": "Google Sheets",
+ "options": {}
+ }
+ ]
+ }
+ ],
+ "variables": [{ "id": "qyLW6xD1AyLeedso2tHmhw", "name": "Email" }],
+ "edges": [
+ {
+ "from": {
+ "blockId": "bSHn2HQZ1sKji5pd9Nmejf",
+ "stepId": "qYmbSFBxCvGCgTvQTg9HeH"
},
- "6Tax9rw7L8kmRn9JRD2Mrg": {
- "from": {
- "blockId": "bmaKTUXkT2cc3wtKfK7ra71",
- "stepId": "spHxPWbSqkVZW9gqH86ovC5"
- },
- "to": { "blockId": "bnt8fM5Wgc8gBg2iSmUcfJu" },
- "id": "6Tax9rw7L8kmRn9JRD2Mrg"
- }
+ "to": { "blockId": "mSvUFogQH16bQDN1iGWF66" },
+ "id": "jdQnqJK4b559rTJzHHhjcz"
},
- "allIds": ["benDCcLMUWNvi6Fg6CXE9H", "6Tax9rw7L8kmRn9JRD2Mrg"]
- },
+ {
+ "from": {
+ "blockId": "mSvUFogQH16bQDN1iGWF66",
+ "stepId": "spDLmDCZfNJu4DrZ1MUg84c"
+ },
+ "to": { "blockId": "jd4S6BQsUQ2RuKieHXYKs9" },
+ "id": "4yg9V76fdDntpDEw6H3tvU"
+ }
+ ],
"theme": {
"chat": {
"inputs": {
diff --git a/apps/builder/playwright/fixtures/typebots/integrations/googleSheetsGet.json b/apps/builder/playwright/fixtures/typebots/integrations/googleSheetsGet.json
index c0fc51813..6f395df6a 100644
--- a/apps/builder/playwright/fixtures/typebots/integrations/googleSheetsGet.json
+++ b/apps/builder/playwright/fixtures/typebots/integrations/googleSheetsGet.json
@@ -1,136 +1,109 @@
{
- "id": "ckyltevlb0559z31an8cmkyrp",
- "createdAt": "2022-01-19T17:24:34.031Z",
- "updatedAt": "2022-01-19T17:24:34.031Z",
+ "id": "ckz8gg4n39573no1aa5rsfyp1",
+ "createdAt": "2022-02-04T13:40:19.455Z",
+ "updatedAt": "2022-02-04T13:40:19.455Z",
"name": "My typebot",
- "ownerId": "ckyltekzq0533z31ad8opmacz",
+ "ownerId": "ckz6t9iep0006k31a22j05fwq",
"publishedTypebotId": null,
"folderId": null,
- "webhooks": { "byId": {}, "allIds": [] },
- "blocks": {
- "byId": {
- "kPupUcEn7TcBGKHUpgK2Q5": {
- "id": "kPupUcEn7TcBGKHUpgK2Q5",
- "title": "Start",
- "stepIds": ["nP5oWm7PxigMupyWpPLq24"],
- "graphCoordinates": { "x": 0, "y": 0 }
- },
- "bi4J5fv9DFn1zPSqGf8eRht": {
- "id": "bi4J5fv9DFn1zPSqGf8eRht",
- "title": "Block #2",
- "graphCoordinates": { "x": 104, "y": 201 },
- "stepIds": ["scH9qdXwFfAScoavj6UzQNT"]
- },
- "bwqGhUsa2SKaxXSrKtapVc8": {
- "id": "bwqGhUsa2SKaxXSrKtapVc8",
- "title": "Block #3",
- "graphCoordinates": { "x": 458, "y": 292 },
- "stepIds": ["shZdc8Qw48domEbS7vLW5eN"]
- },
- "bqmgS9hLUu2RA2oxVv7hMka": {
- "id": "bqmgS9hLUu2RA2oxVv7hMka",
- "title": "Block #4",
- "graphCoordinates": { "x": 102, "y": 432 },
- "stepIds": ["s4z6G3MGAyhXChU9jakQWer"]
- }
- },
- "allIds": [
- "kPupUcEn7TcBGKHUpgK2Q5",
- "bi4J5fv9DFn1zPSqGf8eRht",
- "bwqGhUsa2SKaxXSrKtapVc8",
- "bqmgS9hLUu2RA2oxVv7hMka"
- ]
- },
- "steps": {
- "byId": {
- "nP5oWm7PxigMupyWpPLq24": {
- "id": "nP5oWm7PxigMupyWpPLq24",
- "type": "start",
- "label": "Start",
- "blockId": "kPupUcEn7TcBGKHUpgK2Q5",
- "edgeId": "kCLXGLpiM2F6pn4wFYc1f5"
- },
- "scH9qdXwFfAScoavj6UzQNT": {
- "id": "scH9qdXwFfAScoavj6UzQNT",
- "blockId": "bi4J5fv9DFn1zPSqGf8eRht",
- "type": "email input",
- "options": { "variableId": "ifXp66N1meAtoUDcbqWxuD" },
- "edgeId": "7Czn5hJFUfpkRGtwGnKxtt"
- },
- "shZdc8Qw48domEbS7vLW5eN": {
- "id": "shZdc8Qw48domEbS7vLW5eN",
- "blockId": "bwqGhUsa2SKaxXSrKtapVc8",
- "type": "Google Sheets",
- "edgeId": "eMhGokwHMDRDrynSvpiRje"
- },
- "s4z6G3MGAyhXChU9jakQWer": {
- "id": "s4z6G3MGAyhXChU9jakQWer",
- "blockId": "bqmgS9hLUu2RA2oxVv7hMka",
- "type": "text",
- "content": {
- "html": "Your name is: {{First name}} {{Last name}}
",
- "richText": [
- {
- "type": "p",
- "children": [
- { "text": "Your name is: {{First name}} {{Last name}}" }
- ]
- }
- ],
- "plainText": "Your name is: {{First name}} {{Last name}}"
+ "blocks": [
+ {
+ "id": "bSHn2HQZ1sKji5pd9Nmejf",
+ "steps": [
+ {
+ "id": "qYmbSFBxCvGCgTvQTg9HeH",
+ "type": "start",
+ "label": "Start",
+ "blockId": "bSHn2HQZ1sKji5pd9Nmejf",
+ "outgoingEdgeId": "jdQnqJK4b559rTJzHHhjcz"
}
- }
+ ],
+ "title": "Start",
+ "graphCoordinates": { "x": 0, "y": 0 }
},
- "allIds": [
- "nP5oWm7PxigMupyWpPLq24",
- "scH9qdXwFfAScoavj6UzQNT",
- "shZdc8Qw48domEbS7vLW5eN",
- "s4z6G3MGAyhXChU9jakQWer"
- ]
- },
- "choiceItems": { "byId": {}, "allIds": [] },
- "variables": {
- "byId": {
- "ifXp66N1meAtoUDcbqWxuD": {
- "id": "ifXp66N1meAtoUDcbqWxuD",
- "name": "Email"
- }
+ {
+ "id": "mSvUFogQH16bQDN1iGWF66",
+ "graphCoordinates": { "x": 324, "y": 209 },
+ "title": "Block #1",
+ "steps": [
+ {
+ "id": "spDLmDCZfNJu4DrZ1MUg84c",
+ "blockId": "mSvUFogQH16bQDN1iGWF66",
+ "type": "email input",
+ "options": {
+ "labels": { "button": "Send", "placeholder": "Type your email..." },
+ "variableId": "qyLW6xD1AyLeedso2tHmhw"
+ },
+ "outgoingEdgeId": "4yg9V76fdDntpDEw6H3tvU"
+ }
+ ]
},
- "allIds": ["ifXp66N1meAtoUDcbqWxuD"]
- },
- "edges": {
- "byId": {
- "kCLXGLpiM2F6pn4wFYc1f5": {
- "from": {
- "blockId": "kPupUcEn7TcBGKHUpgK2Q5",
- "stepId": "nP5oWm7PxigMupyWpPLq24"
- },
- "to": { "blockId": "bi4J5fv9DFn1zPSqGf8eRht" },
- "id": "kCLXGLpiM2F6pn4wFYc1f5"
+ {
+ "id": "jd4S6BQsUQ2RuKieHXYKs9",
+ "graphCoordinates": { "x": 655, "y": 363 },
+ "title": "Block #2",
+ "steps": [
+ {
+ "id": "s1ZvUqWxV6b8UgFGYWh39pV",
+ "blockId": "jd4S6BQsUQ2RuKieHXYKs9",
+ "type": "Google Sheets",
+ "options": {},
+ "outgoingEdgeId": "tBsPNYzMW1mMSvFMHZpmx8"
+ }
+ ]
+ },
+ {
+ "id": "pd3PECJqHB9xHMfc52SbrZ",
+ "graphCoordinates": { "x": 292, "y": 509 },
+ "title": "Block #3",
+ "steps": [
+ {
+ "id": "sdECvSYszxBaZHH5TuWm11h",
+ "blockId": "pd3PECJqHB9xHMfc52SbrZ",
+ "type": "text",
+ "content": {
+ "html": "Your name is: {{First name}} {{Last name}}
",
+ "richText": [
+ {
+ "type": "p",
+ "children": [
+ { "text": "Your name is: {{First name}} {{Last name}}" }
+ ]
+ }
+ ],
+ "plainText": "Your name is: {{First name}} {{Last name}}"
+ }
+ }
+ ]
+ }
+ ],
+ "variables": [{ "id": "qyLW6xD1AyLeedso2tHmhw", "name": "Email" }],
+ "edges": [
+ {
+ "from": {
+ "blockId": "bSHn2HQZ1sKji5pd9Nmejf",
+ "stepId": "qYmbSFBxCvGCgTvQTg9HeH"
},
- "7Czn5hJFUfpkRGtwGnKxtt": {
- "from": {
- "blockId": "bi4J5fv9DFn1zPSqGf8eRht",
- "stepId": "scH9qdXwFfAScoavj6UzQNT"
- },
- "to": { "blockId": "bwqGhUsa2SKaxXSrKtapVc8" },
- "id": "7Czn5hJFUfpkRGtwGnKxtt"
- },
- "eMhGokwHMDRDrynSvpiRje": {
- "from": {
- "blockId": "bwqGhUsa2SKaxXSrKtapVc8",
- "stepId": "shZdc8Qw48domEbS7vLW5eN"
- },
- "to": { "blockId": "bqmgS9hLUu2RA2oxVv7hMka" },
- "id": "eMhGokwHMDRDrynSvpiRje"
- }
+ "to": { "blockId": "mSvUFogQH16bQDN1iGWF66" },
+ "id": "jdQnqJK4b559rTJzHHhjcz"
},
- "allIds": [
- "kCLXGLpiM2F6pn4wFYc1f5",
- "7Czn5hJFUfpkRGtwGnKxtt",
- "eMhGokwHMDRDrynSvpiRje"
- ]
- },
+ {
+ "from": {
+ "blockId": "mSvUFogQH16bQDN1iGWF66",
+ "stepId": "spDLmDCZfNJu4DrZ1MUg84c"
+ },
+ "to": { "blockId": "jd4S6BQsUQ2RuKieHXYKs9" },
+ "id": "4yg9V76fdDntpDEw6H3tvU"
+ },
+ {
+ "from": {
+ "blockId": "jd4S6BQsUQ2RuKieHXYKs9",
+ "stepId": "s1ZvUqWxV6b8UgFGYWh39pV"
+ },
+ "to": { "blockId": "pd3PECJqHB9xHMfc52SbrZ" },
+ "id": "tBsPNYzMW1mMSvFMHZpmx8"
+ }
+ ],
"theme": {
"chat": {
"inputs": {
diff --git a/apps/builder/playwright/fixtures/typebots/integrations/webhook.json b/apps/builder/playwright/fixtures/typebots/integrations/webhook.json
index 4c5606360..12b7facf2 100644
--- a/apps/builder/playwright/fixtures/typebots/integrations/webhook.json
+++ b/apps/builder/playwright/fixtures/typebots/integrations/webhook.json
@@ -1,155 +1,103 @@
{
- "id": "ckz478ggv1144eo1a5euf9twl",
- "createdAt": "2022-02-01T14:11:20.287Z",
- "updatedAt": "2022-02-01T14:11:20.286Z",
- "name": "Webhook",
- "ownerId": "ckz478eaj1091eo1amyo1me1z",
+ "id": "ckz8gli9e9842no1afuppdn0z",
+ "createdAt": "2022-02-04T13:44:30.386Z",
+ "updatedAt": "2022-02-04T13:44:30.386Z",
+ "name": "My typebot",
+ "ownerId": "ckz6t9iep0006k31a22j05fwq",
"publishedTypebotId": null,
"folderId": null,
- "blocks": {
- "byId": {
- "q7gjzJu7wBFycca5dNvZek": {
- "id": "q7gjzJu7wBFycca5dNvZek",
- "title": "Start",
- "stepIds": ["da1KErxMzczHwaM25vQtFP"],
- "graphCoordinates": { "x": 0, "y": 0 }
- },
- "bUUqjxyAFZkKzjByqEaEzV": {
- "id": "bUUqjxyAFZkKzjByqEaEzV",
- "graphCoordinates": { "x": 248, "y": 247 },
- "title": "Block 1",
- "stepIds": ["siAj9x5LZ8W5cviqznX82T3", "s5GToHCtqZhwpygDuTb3tu4"]
- },
- "ifpYvoBnYU2X3B3RgwfeNJ": {
- "id": "ifpYvoBnYU2X3B3RgwfeNJ",
- "graphCoordinates": { "x": 690, "y": 504 },
- "title": "Block 2",
- "stepIds": ["sjDhaBWVLd2Ep7N3WryJGQJ"]
- }
- },
- "allIds": [
- "q7gjzJu7wBFycca5dNvZek",
- "bUUqjxyAFZkKzjByqEaEzV",
- "ifpYvoBnYU2X3B3RgwfeNJ"
- ]
- },
- "steps": {
- "byId": {
- "da1KErxMzczHwaM25vQtFP": {
- "id": "da1KErxMzczHwaM25vQtFP",
- "type": "start",
- "label": "Start",
- "blockId": "q7gjzJu7wBFycca5dNvZek",
- "edgeId": "mcxdssnDkbvJBZ6d51XDey"
- },
- "s5GToHCtqZhwpygDuTb3tu4": {
- "id": "s5GToHCtqZhwpygDuTb3tu4",
- "blockId": "bUUqjxyAFZkKzjByqEaEzV",
- "type": "choice input",
- "options": {
- "buttonLabel": "Send",
- "isMultipleChoice": false,
- "itemIds": ["ddSjZkft27gQnZAEeXtQny"]
+ "blocks": [
+ {
+ "id": "p6GeeRXHgwiJeoJRBkKaMJ",
+ "steps": [
+ {
+ "id": "iDS7jFemUsQ7Sp3eu3xg3w",
+ "type": "start",
+ "label": "Start",
+ "blockId": "p6GeeRXHgwiJeoJRBkKaMJ",
+ "outgoingEdgeId": "cyEJPaLU7AchnBSaeWoyiS"
}
- },
- "siAj9x5LZ8W5cviqznX82T3": {
- "id": "siAj9x5LZ8W5cviqznX82T3",
- "blockId": "bUUqjxyAFZkKzjByqEaEzV",
- "type": "text",
- "content": {
- "html": "Ready?
",
- "richText": [{ "type": "p", "children": [{ "text": "Ready?" }] }],
- "plainText": "Ready?"
- }
- },
- "sjDhaBWVLd2Ep7N3WryJGQJ": {
- "id": "sjDhaBWVLd2Ep7N3WryJGQJ",
- "blockId": "ifpYvoBnYU2X3B3RgwfeNJ",
- "type": "Webhook",
- "options": {
- "responseVariableMapping": { "byId": {}, "allIds": [] },
- "variablesForTest": { "byId": {}, "allIds": [] },
- "webhookId": "3nxQGoMMXpA6K5iuhGFW5S"
- }
- }
+ ],
+ "title": "Start",
+ "graphCoordinates": { "x": 0, "y": 0 }
},
- "allIds": [
- "da1KErxMzczHwaM25vQtFP",
- "s5GToHCtqZhwpygDuTb3tu4",
- "siAj9x5LZ8W5cviqznX82T3",
- "sjDhaBWVLd2Ep7N3WryJGQJ"
- ]
- },
- "choiceItems": {
- "byId": {
- "ddSjZkft27gQnZAEeXtQny": {
- "id": "ddSjZkft27gQnZAEeXtQny",
- "stepId": "s5GToHCtqZhwpygDuTb3tu4",
- "content": "Go",
- "edgeId": "x6cbRGrLAVYy4ymAg5tfp9"
- }
- },
- "allIds": ["ddSjZkft27gQnZAEeXtQny"]
- },
- "variables": {
- "byId": {
- "oASkBtoLqkYNqeakcjZH4L": {
- "id": "oASkBtoLqkYNqeakcjZH4L",
- "name": "secret 1"
- },
- "4tvkRmf32wiTsXrYoqyhfr": {
- "id": "4tvkRmf32wiTsXrYoqyhfr",
- "name": "secret 2"
- },
- "jEg1FvkCU5S5owNAxXFsHL": {
- "id": "jEg1FvkCU5S5owNAxXFsHL",
- "name": "secret 3"
- },
- "rEoE1ehHzgx8X3d3UPGDHg": {
- "id": "rEoE1ehHzgx8X3d3UPGDHg",
- "name": "secret 4"
- }
- },
- "allIds": [
- "oASkBtoLqkYNqeakcjZH4L",
- "4tvkRmf32wiTsXrYoqyhfr",
- "jEg1FvkCU5S5owNAxXFsHL",
- "rEoE1ehHzgx8X3d3UPGDHg"
- ]
- },
- "webhooks": {
- "byId": {
- "3nxQGoMMXpA6K5iuhGFW5S": {
- "id": "3nxQGoMMXpA6K5iuhGFW5S",
- "method": "GET",
- "headers": { "byId": {}, "allIds": [] },
- "queryParams": { "byId": {}, "allIds": [] }
- }
- },
- "allIds": ["3nxQGoMMXpA6K5iuhGFW5S"]
- },
- "edges": {
- "byId": {
- "mcxdssnDkbvJBZ6d51XDey": {
- "from": {
- "blockId": "q7gjzJu7wBFycca5dNvZek",
- "stepId": "da1KErxMzczHwaM25vQtFP"
+ {
+ "id": "kBneEpKdMYrF65XxUQ5GS7",
+ "graphCoordinates": { "x": 260, "y": 186 },
+ "title": "Block #1",
+ "steps": [
+ {
+ "id": "skSkZ4PNP7m1gYvu9Ew6ngM",
+ "blockId": "kBneEpKdMYrF65XxUQ5GS7",
+ "type": "text",
+ "content": {
+ "html": "Ready?
",
+ "richText": [{ "type": "p", "children": [{ "text": "Ready?" }] }],
+ "plainText": "Ready?"
+ }
},
- "to": { "blockId": "bUUqjxyAFZkKzjByqEaEzV" },
- "id": "mcxdssnDkbvJBZ6d51XDey"
- },
- "x6cbRGrLAVYy4ymAg5tfp9": {
- "from": {
- "blockId": "bUUqjxyAFZkKzjByqEaEzV",
- "stepId": "s5GToHCtqZhwpygDuTb3tu4",
- "buttonId": "ddSjZkft27gQnZAEeXtQny"
- },
- "to": { "blockId": "ifpYvoBnYU2X3B3RgwfeNJ" },
- "id": "x6cbRGrLAVYy4ymAg5tfp9"
- }
+ {
+ "id": "sh6ZVRA3o72y6BEiNKVcoma",
+ "blockId": "kBneEpKdMYrF65XxUQ5GS7",
+ "type": "choice input",
+ "options": { "buttonLabel": "Send", "isMultipleChoice": false },
+ "items": [
+ {
+ "id": "rr5mKKBPq73ZrfXZ3uuupz",
+ "stepId": "sh6ZVRA3o72y6BEiNKVcoma",
+ "type": 0,
+ "content": "Go",
+ "outgoingEdgeId": "1sLicz8gq2QxytFTwBd8ac"
+ }
+ ]
+ }
+ ]
},
- "allIds": ["mcxdssnDkbvJBZ6d51XDey", "x6cbRGrLAVYy4ymAg5tfp9"]
- },
+ {
+ "id": "8XnDM1QsqPms4LQHh8q3Jo",
+ "graphCoordinates": { "x": 646, "y": 511 },
+ "title": "Block #2",
+ "steps": [
+ {
+ "id": "soSmiE7zyb3WF77GxFxAjYX",
+ "blockId": "8XnDM1QsqPms4LQHh8q3Jo",
+ "type": "Webhook",
+ "options": { "responseVariableMapping": [], "variablesForTest": [] },
+ "webhook": {
+ "id": "2L9mPYsLAXdXwcnGVK6pv9",
+ "method": "GET",
+ "headers": [],
+ "queryParams": []
+ }
+ }
+ ]
+ }
+ ],
+ "variables": [
+ { "id": "var1", "name": "secret 1" },
+ { "id": "var2", "name": "secret 2" },
+ { "id": "var3", "name": "secret 3" },
+ { "id": "var4", "name": "secret 4" }
+ ],
+ "edges": [
+ {
+ "from": {
+ "blockId": "p6GeeRXHgwiJeoJRBkKaMJ",
+ "stepId": "iDS7jFemUsQ7Sp3eu3xg3w"
+ },
+ "to": { "blockId": "kBneEpKdMYrF65XxUQ5GS7" },
+ "id": "cyEJPaLU7AchnBSaeWoyiS"
+ },
+ {
+ "from": {
+ "blockId": "kBneEpKdMYrF65XxUQ5GS7",
+ "stepId": "sh6ZVRA3o72y6BEiNKVcoma",
+ "itemId": "rr5mKKBPq73ZrfXZ3uuupz"
+ },
+ "to": { "blockId": "8XnDM1QsqPms4LQHh8q3Jo" },
+ "id": "1sLicz8gq2QxytFTwBd8ac"
+ }
+ ],
"theme": {
"chat": {
"inputs": {
diff --git a/apps/builder/playwright/fixtures/typebots/integrations/webhook.png b/apps/builder/playwright/fixtures/typebots/integrations/webhook.png
new file mode 100644
index 000000000..4077ad2a6
Binary files /dev/null and b/apps/builder/playwright/fixtures/typebots/integrations/webhook.png differ
diff --git a/apps/builder/playwright/fixtures/typebots/integrations/webhookPreview.json b/apps/builder/playwright/fixtures/typebots/integrations/webhookPreview.json
deleted file mode 100644
index 70ab65ed8..000000000
--- a/apps/builder/playwright/fixtures/typebots/integrations/webhookPreview.json
+++ /dev/null
@@ -1,275 +0,0 @@
-{
- "id": "bdFW2HHjMoEFmqHtFre9Xi8",
- "createdAt": "2022-01-21T07:55:14.727Z",
- "updatedAt": "2022-01-21T07:55:14.727Z",
- "name": "My typebot",
- "ownerId": "user2",
- "publishedTypebotId": null,
- "folderId": null,
- "blocks": {
- "byId": {
- "3kH2sUjVThQDWmqdoKnGk5": {
- "id": "3kH2sUjVThQDWmqdoKnGk5",
- "title": "Start",
- "stepIds": ["oxTsU2C1RX5QHuyY8qjHAM"],
- "graphCoordinates": { "x": 42, "y": 13 }
- },
- "b9mSgu7RKmK4xuiTVQP5Me8": {
- "id": "b9mSgu7RKmK4xuiTVQP5Me8",
- "title": "Block #3",
- "stepIds": ["ssLd2wjExS9qWRur4tZDU1Z"],
- "graphCoordinates": { "x": 300, "y": 550 }
- },
- "bdFW2HHjMoEFmqHtFre9Xi8": {
- "id": "bdFW2HHjMoEFmqHtFre9Xi8",
- "title": "Block #2",
- "stepIds": ["sgkADMK25y9P9V3vjwjBaac", "ssEiEECKSFkA44dGDceHxKw"],
- "graphCoordinates": { "x": 121, "y": 227 }
- },
- "bmz4rc8r19H2C6b7soxzby4": {
- "id": "bmz4rc8r19H2C6b7soxzby4",
- "title": "Block #4",
- "graphCoordinates": { "x": 632, "y": 279 },
- "stepIds": ["sgTWsRM1qF2YoYLuGo3Z3pU"]
- }
- },
- "allIds": [
- "3kH2sUjVThQDWmqdoKnGk5",
- "bdFW2HHjMoEFmqHtFre9Xi8",
- "b9mSgu7RKmK4xuiTVQP5Me8",
- "bmz4rc8r19H2C6b7soxzby4"
- ]
- },
- "steps": {
- "byId": {
- "oxTsU2C1RX5QHuyY8qjHAM": {
- "id": "oxTsU2C1RX5QHuyY8qjHAM",
- "type": "start",
- "label": "Start",
- "edgeId": "25yX9DnQgdafpdAjfAu5Fp",
- "blockId": "3kH2sUjVThQDWmqdoKnGk5"
- },
- "sgkADMK25y9P9V3vjwjBaac": {
- "id": "sgkADMK25y9P9V3vjwjBaac",
- "type": "text",
- "blockId": "bdFW2HHjMoEFmqHtFre9Xi8",
- "content": {
- "html": "Ready?
",
- "richText": [{ "type": "p", "children": [{ "text": "Ready?" }] }],
- "plainText": "Ready?"
- }
- },
- "ssEiEECKSFkA44dGDceHxKw": {
- "id": "ssEiEECKSFkA44dGDceHxKw",
- "type": "choice input",
- "edgeId": "oxEEtym3NfDf34NCipzjRQ",
- "blockId": "bdFW2HHjMoEFmqHtFre9Xi8",
- "options": { "itemIds": ["q69Ex7LacPrH9QUMeosRnB"] }
- },
- "ssLd2wjExS9qWRur4tZDU1Z": {
- "id": "ssLd2wjExS9qWRur4tZDU1Z",
- "type": "Webhook",
- "blockId": "b9mSgu7RKmK4xuiTVQP5Me8",
- "options": {
- "webhookId": "4h4Kk3Q1qGy7gFzpZtWVpU",
- "variablesForTest": {
- "byId": {
- "6pMn1xm1y3xWVSdJetMAJH": {
- "id": "6pMn1xm1y3xWVSdJetMAJH",
- "variableId": "oASkBtoLqkYNqeakcjZH4L",
- "value": "secret1"
- },
- "ettAiB75uoFWnJyPS7gn5k": {
- "id": "ettAiB75uoFWnJyPS7gn5k",
- "variableId": "4tvkRmf32wiTsXrYoqyhfr",
- "value": "secret2"
- },
- "kKpD3Q4YvFQ7CGWiZxJF4s": {
- "id": "kKpD3Q4YvFQ7CGWiZxJF4s",
- "variableId": "jEg1FvkCU5S5owNAxXFsHL",
- "value": "secret3"
- },
- "xjUC5Q3msXCw9fwqpNdoSx": {
- "id": "xjUC5Q3msXCw9fwqpNdoSx",
- "variableId": "rEoE1ehHzgx8X3d3UPGDHg",
- "value": "secret4"
- }
- },
- "allIds": [
- "6pMn1xm1y3xWVSdJetMAJH",
- "ettAiB75uoFWnJyPS7gn5k",
- "kKpD3Q4YvFQ7CGWiZxJF4s",
- "xjUC5Q3msXCw9fwqpNdoSx"
- ]
- },
- "responseVariableMapping": {
- "byId": {
- "o53h6M1sgHJfDTY5C3YEaT": {
- "id": "o53h6M1sgHJfDTY5C3YEaT",
- "bodyPath": "data[0].name",
- "variableId": "4kVx5uf8W1XP6WsfJEvt8v"
- }
- },
- "allIds": ["o53h6M1sgHJfDTY5C3YEaT"]
- }
- },
- "edgeId": "81SjKnxuUgrPmXvvJJihHM"
- },
- "sgTWsRM1qF2YoYLuGo3Z3pU": {
- "id": "sgTWsRM1qF2YoYLuGo3Z3pU",
- "blockId": "bmz4rc8r19H2C6b7soxzby4",
- "type": "text",
- "content": {
- "html": "His name is {{Name}}
",
- "richText": [
- { "type": "p", "children": [{ "text": "His name is {{Name}}" }] }
- ],
- "plainText": "His name is {{Name}}"
- }
- }
- },
- "allIds": [
- "oxTsU2C1RX5QHuyY8qjHAM",
- "sgkADMK25y9P9V3vjwjBaac",
- "ssEiEECKSFkA44dGDceHxKw",
- "ssLd2wjExS9qWRur4tZDU1Z",
- "sgTWsRM1qF2YoYLuGo3Z3pU"
- ]
- },
- "choiceItems": {
- "byId": {
- "q69Ex7LacPrH9QUMeosRnB": {
- "id": "q69Ex7LacPrH9QUMeosRnB",
- "stepId": "ssEiEECKSFkA44dGDceHxKw",
- "content": "Go"
- }
- },
- "allIds": ["q69Ex7LacPrH9QUMeosRnB"]
- },
- "webhooks": { "byId": {}, "allIds": [] },
- "variables": {
- "byId": {
- "4tvkRmf32wiTsXrYoqyhfr": {
- "id": "4tvkRmf32wiTsXrYoqyhfr",
- "name": "secret 2",
- "value": "secret2"
- },
- "jEg1FvkCU5S5owNAxXFsHL": {
- "id": "jEg1FvkCU5S5owNAxXFsHL",
- "name": "secret 3",
- "value": "secret3"
- },
- "oASkBtoLqkYNqeakcjZH4L": {
- "id": "oASkBtoLqkYNqeakcjZH4L",
- "name": "secret 1",
- "value": "secret1"
- },
- "rEoE1ehHzgx8X3d3UPGDHg": {
- "id": "rEoE1ehHzgx8X3d3UPGDHg",
- "name": "secret 4",
- "value": "secret4"
- },
- "4kVx5uf8W1XP6WsfJEvt8v": {
- "id": "4kVx5uf8W1XP6WsfJEvt8v",
- "name": "Name"
- }
- },
- "allIds": [
- "oASkBtoLqkYNqeakcjZH4L",
- "4tvkRmf32wiTsXrYoqyhfr",
- "jEg1FvkCU5S5owNAxXFsHL",
- "rEoE1ehHzgx8X3d3UPGDHg",
- "4kVx5uf8W1XP6WsfJEvt8v"
- ]
- },
- "webhooks": {
- "byId": {
- "4h4Kk3Q1qGy7gFzpZtWVpU": {
- "id": "4h4Kk3Q1qGy7gFzpZtWVpU",
- "url": "http://localhost:3000/api/mock/webhook",
- "queryParams": {
- "byId": {
- "hwGB11cA7RaYnaqH7gYyuQ": {
- "id": "hwGB11cA7RaYnaqH7gYyuQ",
- "key": "firstParam",
- "value": "{{secret 1}}"
- },
- "6ux2FZjhNc4vfqNUDuCkxn": {
- "id": "6ux2FZjhNc4vfqNUDuCkxn",
- "key": "secondParam",
- "value": "{{secret 2}}"
- }
- },
- "allIds": ["hwGB11cA7RaYnaqH7gYyuQ", "6ux2FZjhNc4vfqNUDuCkxn"]
- },
- "headers": {
- "byId": {
- "ayTB2cFRKMo6oH9t9KS8SA": {
- "id": "ayTB2cFRKMo6oH9t9KS8SA",
- "key": "Custom-Typebot",
- "value": "{{secret 3}}"
- }
- },
- "allIds": ["ayTB2cFRKMo6oH9t9KS8SA"]
- },
- "method": "POST",
- "body": "{ \"customField\": \"{{secret 4}}\" }"
- }
- },
- "allIds": ["4h4Kk3Q1qGy7gFzpZtWVpU"]
- },
- "edges": {
- "byId": {
- "25yX9DnQgdafpdAjfAu5Fp": {
- "id": "25yX9DnQgdafpdAjfAu5Fp",
- "to": { "blockId": "bdFW2HHjMoEFmqHtFre9Xi8" },
- "from": {
- "stepId": "oxTsU2C1RX5QHuyY8qjHAM",
- "blockId": "3kH2sUjVThQDWmqdoKnGk5"
- }
- },
- "oxEEtym3NfDf34NCipzjRQ": {
- "id": "oxEEtym3NfDf34NCipzjRQ",
- "to": { "blockId": "b9mSgu7RKmK4xuiTVQP5Me8" },
- "from": {
- "stepId": "ssEiEECKSFkA44dGDceHxKw",
- "blockId": "bdFW2HHjMoEFmqHtFre9Xi8"
- }
- },
- "81SjKnxuUgrPmXvvJJihHM": {
- "from": {
- "blockId": "b9mSgu7RKmK4xuiTVQP5Me8",
- "stepId": "ssLd2wjExS9qWRur4tZDU1Z"
- },
- "to": { "blockId": "bmz4rc8r19H2C6b7soxzby4" },
- "id": "81SjKnxuUgrPmXvvJJihHM"
- }
- },
- "allIds": [
- "25yX9DnQgdafpdAjfAu5Fp",
- "oxEEtym3NfDf34NCipzjRQ",
- "81SjKnxuUgrPmXvvJJihHM"
- ]
- },
- "theme": {
- "chat": {
- "inputs": {
- "color": "#303235",
- "backgroundColor": "#FFFFFF",
- "placeholderColor": "#9095A0"
- },
- "buttons": { "color": "#FFFFFF", "backgroundColor": "#0042DA" },
- "hostBubbles": { "color": "#303235", "backgroundColor": "#F7F8FF" },
- "guestBubbles": { "color": "#FFFFFF", "backgroundColor": "#FF8E21" }
- },
- "general": { "font": "Open Sans", "background": { "type": "None" } }
- },
- "settings": {
- "general": { "isBrandingEnabled": true },
- "metadata": {
- "description": "Build beautiful conversational forms and embed them directly in your applications without a line of code. Triple your response rate and collect answers that has more value compared to a traditional form."
- },
- "typingEmulation": { "speed": 300, "enabled": true, "maxDelay": 1.5 }
- },
- "publicId": null
-}
diff --git a/apps/builder/playwright/fixtures/typebots/integrations/webhookPreview.png b/apps/builder/playwright/fixtures/typebots/integrations/webhookPreview.png
deleted file mode 100644
index 8b98e2c9e..000000000
Binary files a/apps/builder/playwright/fixtures/typebots/integrations/webhookPreview.png and /dev/null differ
diff --git a/apps/builder/playwright/fixtures/typebots/logic/condition.json b/apps/builder/playwright/fixtures/typebots/logic/condition.json
index 8fbfe4265..9bd7c9ff5 100644
--- a/apps/builder/playwright/fixtures/typebots/logic/condition.json
+++ b/apps/builder/playwright/fixtures/typebots/logic/condition.json
@@ -1,228 +1,217 @@
{
- "id": "ckylsd52p0114z31aobllswmu",
- "createdAt": "2022-01-19T16:55:13.393Z",
- "updatedAt": "2022-01-19T16:55:13.393Z",
+ "id": "ckz8gpmgr10008no1a1mq4q1l2",
+ "createdAt": "2022-02-04T13:47:42.459Z",
+ "updatedAt": "2022-02-04T13:47:42.459Z",
"name": "My typebot",
- "ownerId": "ckylsbdf60088z31ayqytest6",
+ "ownerId": "ckz6t9iep0006k31a22j05fwq",
"publishedTypebotId": null,
"folderId": null,
- "webhooks": { "byId": {}, "allIds": [] },
- "blocks": {
- "byId": {
- "2x83WHtEBkiv7pk7KgqJwZ": {
- "id": "2x83WHtEBkiv7pk7KgqJwZ",
- "title": "Start",
- "stepIds": ["1A76iZBgXG7hvkG2koCxe4"],
- "graphCoordinates": { "x": 0, "y": 0 }
- },
- "bwga7RwqQWbowdHph27DM1N": {
- "id": "bwga7RwqQWbowdHph27DM1N",
- "title": "Block #2",
- "graphCoordinates": { "x": 78, "y": 224 },
- "stepIds": ["srwUKaUFFmehppJ2ZDqp4xG", "sxvzuo48GHi3AcAfmiFyYC1"]
- },
- "bu8whx817bJBG37FQrtD5dD": {
- "id": "bu8whx817bJBG37FQrtD5dD",
- "title": "Block #3",
- "graphCoordinates": { "x": 430, "y": 287 },
- "stepIds": ["ituVWW1AvQeVdFHTwsiVao", "5SLc4whZooZVUfr1bmTNSC"]
- },
- "b59jwmEdwZUvJszV394x44u": {
- "id": "b59jwmEdwZUvJszV394x44u",
- "title": "Block #4",
- "graphCoordinates": { "x": 844, "y": 185 },
- "stepIds": ["sm1YcKTL9cQMCGywzo1wyBB"]
- },
- "baVF9HqhuSnLDZqY9eRPpcp": {
- "id": "baVF9HqhuSnLDZqY9eRPpcp",
- "title": "Block #5",
- "graphCoordinates": { "x": 841, "y": 356 },
- "stepIds": ["sb3o6J8Fybg6u8KuayKviJq"]
- },
- "b9aEH46RHuZWTdQwZJ6KBWR": {
- "id": "b9aEH46RHuZWTdQwZJ6KBWR",
- "title": "Block #6",
- "graphCoordinates": { "x": 839, "y": 523 },
- "stepIds": ["scKogEJSTq4kPeHRhwTTjit"]
- }
- },
- "allIds": [
- "2x83WHtEBkiv7pk7KgqJwZ",
- "bwga7RwqQWbowdHph27DM1N",
- "bu8whx817bJBG37FQrtD5dD",
- "b59jwmEdwZUvJszV394x44u",
- "baVF9HqhuSnLDZqY9eRPpcp",
- "b9aEH46RHuZWTdQwZJ6KBWR"
- ]
- },
- "steps": {
- "byId": {
- "1A76iZBgXG7hvkG2koCxe4": {
- "id": "1A76iZBgXG7hvkG2koCxe4",
- "type": "start",
- "label": "Start",
- "blockId": "2x83WHtEBkiv7pk7KgqJwZ",
- "edgeId": "jjNy2hYgrQgPS9EBMKA7MH"
- },
- "srwUKaUFFmehppJ2ZDqp4xG": {
- "id": "srwUKaUFFmehppJ2ZDqp4xG",
- "blockId": "bwga7RwqQWbowdHph27DM1N",
- "type": "text",
- "content": {
- "html": "How old are you?
",
- "richText": [
- { "type": "p", "children": [{ "text": "How old are you?" }] }
- ],
- "plainText": "How old are you?"
+ "blocks": [
+ {
+ "id": "cN46uqNAR3ohjrS8jHJ6xT",
+ "steps": [
+ {
+ "id": "nzijwLtLTAZfNNCN7kEpn5",
+ "type": "start",
+ "label": "Start",
+ "blockId": "cN46uqNAR3ohjrS8jHJ6xT",
+ "outgoingEdgeId": "7wxB76VK81JsXMX9jU9dbQ"
}
- },
- "sxvzuo48GHi3AcAfmiFyYC1": {
- "id": "sxvzuo48GHi3AcAfmiFyYC1",
- "blockId": "bwga7RwqQWbowdHph27DM1N",
- "type": "number input",
- "options": { "variableId": "dEz689uVm8AxUM8TrbQd2t" },
- "edgeId": "7mcWaWohM9zGtLX8ZSnqFy"
- },
- "ituVWW1AvQeVdFHTwsiVao": {
- "id": "ituVWW1AvQeVdFHTwsiVao",
- "blockId": "bu8whx817bJBG37FQrtD5dD",
- "type": "Condition",
- "options": {
- "comparisons": {
- "byId": {},
- "allIds": []
+ ],
+ "title": "Start",
+ "graphCoordinates": { "x": 0, "y": 0 }
+ },
+ {
+ "id": "eh2ohNATnGg6RTdjG9h5kb",
+ "steps": [
+ {
+ "id": "sb6xdkJRr6P6BxtTM3ku5JD",
+ "type": "text",
+ "blockId": "eh2ohNATnGg6RTdjG9h5kb",
+ "content": {
+ "html": "How old are you?
",
+ "richText": [
+ { "type": "p", "children": [{ "text": "How old are you?" }] }
+ ],
+ "plainText": "How old are you?"
+ }
+ },
+ {
+ "id": "ssyBKZve7bihSxUASYTruZA",
+ "type": "number input",
+ "blockId": "eh2ohNATnGg6RTdjG9h5kb",
+ "options": {
+ "labels": { "button": "Send", "placeholder": "Type a number..." },
+ "variableId": "iDJzzyzAY2jrapm3NwhGMz"
},
- "logicalOperator": "AND"
- },
- "trueEdgeId": "iBPsFyBsPv6Rbdfo2QdJyi"
- },
- "5SLc4whZooZVUfr1bmTNSC": {
- "id": "5SLc4whZooZVUfr1bmTNSC",
- "blockId": "bu8whx817bJBG37FQrtD5dD",
- "type": "Condition",
- "options": {
- "comparisons": {
- "byId": {},
- "allIds": []
- },
- "logicalOperator": "AND"
- },
- "trueEdgeId": "354PJ2jD5U3J2APqLsPJrp",
- "falseEdgeId": "94bmeCLigEUUpWYw2xsAVB"
- },
- "sm1YcKTL9cQMCGywzo1wyBB": {
- "id": "sm1YcKTL9cQMCGywzo1wyBB",
- "blockId": "b59jwmEdwZUvJszV394x44u",
- "type": "text",
- "content": {
- "html": "You are older than 80
",
- "richText": [
- { "type": "p", "children": [{ "text": "You are older than 80" }] }
- ],
- "plainText": "You are older than 80"
+ "outgoingEdgeId": "r8LX7iuEXxjF5SW5dbS6qT"
}
- },
- "sb3o6J8Fybg6u8KuayKviJq": {
- "id": "sb3o6J8Fybg6u8KuayKviJq",
- "blockId": "baVF9HqhuSnLDZqY9eRPpcp",
- "type": "text",
- "content": {
- "html": "You are older than 20
",
- "richText": [
- { "type": "p", "children": [{ "text": "You are older than 20" }] }
+ ],
+ "title": "Block #1",
+ "graphCoordinates": { "x": 159, "y": 224 }
+ },
+ {
+ "id": "eMk84KvFM53sBxchTeackR",
+ "steps": [
+ {
+ "id": "s5hz7HQki66cwELvk2738MJ",
+ "blockId": "eMk84KvFM53sBxchTeackR",
+ "type": "Condition",
+ "items": [
+ {
+ "id": "56s4R9THRKeoJtBdKzEGLn",
+ "stepId": "s5hz7HQki66cwELvk2738MJ",
+ "type": 1,
+ "content": {
+ "comparisons": [
+ {
+ "id": "wxWqL7JuZhy9uwCZNPDJjM"
+ }
+ ],
+ "logicalOperator": "AND"
+ },
+ "outgoingEdgeId": "nDjMjM11xPQF7c9Be6ukdY"
+ }
+ ]
+ },
+ {
+ "id": "sv8uvEXgYWQNMfZWcdbfyCs",
+ "type": "Condition",
+ "items": [
+ {
+ "id": "ijYfW38tGhCMRrCtmR3bcr",
+ "type": 1,
+ "stepId": "sv8uvEXgYWQNMfZWcdbfyCs",
+ "content": {
+ "comparisons": [
+ {
+ "id": "3di6P3ypWf3XusgBLLHYBE"
+ }
+ ],
+ "logicalOperator": "AND"
+ },
+ "outgoingEdgeId": "s1uVbzP1zMMJjsCguAfhGV"
+ }
],
- "plainText": "You are older than 20"
+ "blockId": "eMk84KvFM53sBxchTeackR",
+ "outgoingEdgeId": "hVScFHNzToiEsMfYVv5AWZ"
}
- },
- "scKogEJSTq4kPeHRhwTTjit": {
- "id": "scKogEJSTq4kPeHRhwTTjit",
- "blockId": "b9aEH46RHuZWTdQwZJ6KBWR",
- "type": "text",
- "content": {
- "html": "You are younger than 20
",
- "richText": [
- { "type": "p", "children": [{ "text": "You are younger than 20" }] }
- ],
- "plainText": "You are younger than 20"
+ ],
+ "title": "Block #2",
+ "graphCoordinates": { "x": 561, "y": 295 }
+ },
+ {
+ "id": "fGrzjahWecA8hoNMRrLSwn",
+ "steps": [
+ {
+ "id": "soZqPdPUjYAht9nHmVpba1Q",
+ "type": "text",
+ "blockId": "fGrzjahWecA8hoNMRrLSwn",
+ "content": {
+ "html": "You are older than 80
",
+ "richText": [
+ {
+ "type": "p",
+ "children": [{ "text": "You are older than 80" }]
+ }
+ ],
+ "plainText": "You are older than 80"
+ }
}
- }
+ ],
+ "title": "Block #3",
+ "graphCoordinates": { "x": 936, "y": 63 }
},
- "allIds": [
- "1A76iZBgXG7hvkG2koCxe4",
- "srwUKaUFFmehppJ2ZDqp4xG",
- "sxvzuo48GHi3AcAfmiFyYC1",
- "ituVWW1AvQeVdFHTwsiVao",
- "5SLc4whZooZVUfr1bmTNSC",
- "sxvzuo48GHi3AcAfmiFyYC1",
- "sm1YcKTL9cQMCGywzo1wyBB",
- "sb3o6J8Fybg6u8KuayKviJq",
- "scKogEJSTq4kPeHRhwTTjit"
- ]
- },
- "choiceItems": { "byId": {}, "allIds": [] },
- "variables": {
- "byId": {
- "dEz689uVm8AxUM8TrbQd2t": {
- "id": "dEz689uVm8AxUM8TrbQd2t",
- "name": "Age"
- }
+ {
+ "id": "49Jv45UJi9R3U4FuWS8R2c",
+ "steps": [
+ {
+ "id": "svipUacs1sDk9KDxzaGhnsG",
+ "type": "text",
+ "blockId": "49Jv45UJi9R3U4FuWS8R2c",
+ "content": {
+ "html": "You are older than 20
",
+ "richText": [
+ {
+ "type": "p",
+ "children": [{ "text": "You are older than 20" }]
+ }
+ ],
+ "plainText": "You are older than 20"
+ }
+ }
+ ],
+ "title": "Block #4",
+ "graphCoordinates": { "x": 950, "y": 298 }
},
- "allIds": ["dEz689uVm8AxUM8TrbQd2t"]
- },
- "edges": {
- "byId": {
- "jjNy2hYgrQgPS9EBMKA7MH": {
- "from": {
- "blockId": "2x83WHtEBkiv7pk7KgqJwZ",
- "stepId": "1A76iZBgXG7hvkG2koCxe4"
- },
- "to": { "blockId": "bwga7RwqQWbowdHph27DM1N" },
- "id": "jjNy2hYgrQgPS9EBMKA7MH"
+ {
+ "id": "fD28kefdySKK7XA7SyTozC",
+ "steps": [
+ {
+ "id": "spHJ7v9bDdVrFfuF2zg3YNR",
+ "type": "text",
+ "blockId": "fD28kefdySKK7XA7SyTozC",
+ "content": {
+ "html": "You are younger than 20
",
+ "richText": [
+ {
+ "type": "p",
+ "children": [{ "text": "You are younger than 20" }]
+ }
+ ],
+ "plainText": "You are younger than 20"
+ }
+ }
+ ],
+ "title": "Block #5",
+ "graphCoordinates": { "x": 985, "y": 537 }
+ }
+ ],
+ "variables": [{ "id": "iDJzzyzAY2jrapm3NwhGMz", "name": "Age" }],
+ "edges": [
+ {
+ "from": {
+ "blockId": "eMk84KvFM53sBxchTeackR",
+ "stepId": "s5hz7HQki66cwELvk2738MJ",
+ "itemId": "56s4R9THRKeoJtBdKzEGLn"
},
- "iBPsFyBsPv6Rbdfo2QdJyi": {
- "from": {
- "blockId": "bu8whx817bJBG37FQrtD5dD",
- "stepId": "ituVWW1AvQeVdFHTwsiVao",
- "conditionType": "true"
- },
- "to": { "blockId": "b59jwmEdwZUvJszV394x44u" },
- "id": "iBPsFyBsPv6Rbdfo2QdJyi"
- },
- "354PJ2jD5U3J2APqLsPJrp": {
- "from": {
- "blockId": "bu8whx817bJBG37FQrtD5dD",
- "stepId": "5SLc4whZooZVUfr1bmTNSC",
- "conditionType": "true"
- },
- "to": { "blockId": "baVF9HqhuSnLDZqY9eRPpcp" },
- "id": "354PJ2jD5U3J2APqLsPJrp"
- },
- "94bmeCLigEUUpWYw2xsAVB": {
- "from": {
- "blockId": "bu8whx817bJBG37FQrtD5dD",
- "stepId": "5SLc4whZooZVUfr1bmTNSC",
- "conditionType": "false"
- },
- "to": { "blockId": "b9aEH46RHuZWTdQwZJ6KBWR" },
- "id": "94bmeCLigEUUpWYw2xsAVB"
- },
- "7mcWaWohM9zGtLX8ZSnqFy": {
- "from": {
- "blockId": "bwga7RwqQWbowdHph27DM1N",
- "stepId": "sxvzuo48GHi3AcAfmiFyYC1"
- },
- "to": { "blockId": "bu8whx817bJBG37FQrtD5dD" },
- "id": "7mcWaWohM9zGtLX8ZSnqFy"
- }
+ "to": { "blockId": "fGrzjahWecA8hoNMRrLSwn" },
+ "id": "nDjMjM11xPQF7c9Be6ukdY"
},
- "allIds": [
- "jjNy2hYgrQgPS9EBMKA7MH",
- "iBPsFyBsPv6Rbdfo2QdJyi",
- "354PJ2jD5U3J2APqLsPJrp",
- "94bmeCLigEUUpWYw2xsAVB",
- "7mcWaWohM9zGtLX8ZSnqFy"
- ]
- },
+ {
+ "from": {
+ "blockId": "eMk84KvFM53sBxchTeackR",
+ "stepId": "sv8uvEXgYWQNMfZWcdbfyCs",
+ "itemId": "ijYfW38tGhCMRrCtmR3bcr"
+ },
+ "to": { "blockId": "49Jv45UJi9R3U4FuWS8R2c" },
+ "id": "s1uVbzP1zMMJjsCguAfhGV"
+ },
+ {
+ "from": {
+ "blockId": "eMk84KvFM53sBxchTeackR",
+ "stepId": "sv8uvEXgYWQNMfZWcdbfyCs"
+ },
+ "to": { "blockId": "fD28kefdySKK7XA7SyTozC" },
+ "id": "hVScFHNzToiEsMfYVv5AWZ"
+ },
+ {
+ "from": {
+ "blockId": "eh2ohNATnGg6RTdjG9h5kb",
+ "stepId": "ssyBKZve7bihSxUASYTruZA"
+ },
+ "to": { "blockId": "eMk84KvFM53sBxchTeackR" },
+ "id": "r8LX7iuEXxjF5SW5dbS6qT"
+ },
+ {
+ "from": {
+ "blockId": "cN46uqNAR3ohjrS8jHJ6xT",
+ "stepId": "nzijwLtLTAZfNNCN7kEpn5"
+ },
+ "to": { "blockId": "eh2ohNATnGg6RTdjG9h5kb" },
+ "id": "7wxB76VK81JsXMX9jU9dbQ"
+ }
+ ],
"theme": {
"chat": {
"inputs": {
diff --git a/apps/builder/playwright/fixtures/typebots/logic/condition.png b/apps/builder/playwright/fixtures/typebots/logic/condition.png
index 22fe2da91..d668cbfde 100644
Binary files a/apps/builder/playwright/fixtures/typebots/logic/condition.png and b/apps/builder/playwright/fixtures/typebots/logic/condition.png differ
diff --git a/apps/builder/playwright/fixtures/typebots/logic/redirect.json b/apps/builder/playwright/fixtures/typebots/logic/redirect.json
index 3ec1cb2e9..d48cdd006 100644
--- a/apps/builder/playwright/fixtures/typebots/logic/redirect.json
+++ b/apps/builder/playwright/fixtures/typebots/logic/redirect.json
@@ -1,101 +1,82 @@
{
- "id": "ckymkfh1e00562z1a3fjoua3e",
- "createdAt": "2022-01-20T06:00:51.458Z",
- "updatedAt": "2022-01-20T06:00:51.458Z",
+ "id": "ckz8hnw7m10833no1ar12eov20",
+ "createdAt": "2022-02-04T14:14:21.394Z",
+ "updatedAt": "2022-02-04T14:14:21.394Z",
"name": "My typebot",
- "ownerId": "ckymkff1100362z1a85juyoa8",
+ "ownerId": "ckz6t9iep0006k31a22j05fwq",
"publishedTypebotId": null,
"folderId": null,
- "webhooks": { "byId": {}, "allIds": [] },
- "blocks": {
- "byId": {
- "bsVJfEW7EZrUnAi9s5ev17": {
- "id": "bsVJfEW7EZrUnAi9s5ev17",
- "title": "Start",
- "stepIds": ["9Ck2yveNjZNHhjyc4HCJAL"],
- "graphCoordinates": { "x": 0, "y": 0 }
- },
- "bmdnpyvzopZ8YVfqsJY7Q8K": {
- "id": "bmdnpyvzopZ8YVfqsJY7Q8K",
- "title": "Block #2",
- "graphCoordinates": { "x": 68, "y": 229 },
- "stepIds": ["sas16Qqf4TmZEXSexmYpmSd"]
- },
- "bnsxmer7DD2R9DogoXTsvHJ": {
- "id": "bnsxmer7DD2R9DogoXTsvHJ",
- "title": "Block #3",
- "graphCoordinates": { "x": 491, "y": 239 },
- "stepIds": ["sqNGop2aYkXRvJqb9nGtFbD"]
- }
+ "blocks": [
+ {
+ "id": "tdN9VXcdBWpuh6Gpaz3w4u",
+ "steps": [
+ {
+ "id": "cVRL5EuVruTK31SAaVCvNE",
+ "type": "start",
+ "label": "Start",
+ "blockId": "tdN9VXcdBWpuh6Gpaz3w4u",
+ "outgoingEdgeId": "jqZYCYGxaL8svJbM2h1QAn"
+ }
+ ],
+ "title": "Start",
+ "graphCoordinates": { "x": 0, "y": 0 }
},
- "allIds": [
- "bsVJfEW7EZrUnAi9s5ev17",
- "bmdnpyvzopZ8YVfqsJY7Q8K",
- "bnsxmer7DD2R9DogoXTsvHJ"
- ]
- },
- "steps": {
- "byId": {
- "9Ck2yveNjZNHhjyc4HCJAL": {
- "id": "9Ck2yveNjZNHhjyc4HCJAL",
- "type": "start",
- "label": "Start",
- "blockId": "bsVJfEW7EZrUnAi9s5ev17",
- "edgeId": "totLsWG6AQfcFT39CsZwDy"
- },
- "sas16Qqf4TmZEXSexmYpmSd": {
- "id": "sas16Qqf4TmZEXSexmYpmSd",
- "blockId": "bmdnpyvzopZ8YVfqsJY7Q8K",
- "type": "choice input",
- "options": { "itemIds": ["mAgynXh3zmkmWzNyPGVAcf"] }
- },
- "sqNGop2aYkXRvJqb9nGtFbD": {
- "id": "sqNGop2aYkXRvJqb9nGtFbD",
- "blockId": "bnsxmer7DD2R9DogoXTsvHJ",
- "type": "Redirect",
- "options": { "isNewTab": false }
- }
+ {
+ "id": "vymPUjL9AcWpkg9PkUXovk",
+ "graphCoordinates": { "x": 685, "y": 194 },
+ "title": "Block #1",
+ "steps": [
+ {
+ "id": "sa8WhnrMyMjYCBMeozfYRoi",
+ "blockId": "vymPUjL9AcWpkg9PkUXovk",
+ "type": "Redirect",
+ "options": { "isNewTab": false }
+ }
+ ]
},
- "allIds": [
- "9Ck2yveNjZNHhjyc4HCJAL",
- "sas16Qqf4TmZEXSexmYpmSd",
- "sqNGop2aYkXRvJqb9nGtFbD"
- ]
- },
- "choiceItems": {
- "byId": {
- "mAgynXh3zmkmWzNyPGVAcf": {
- "id": "mAgynXh3zmkmWzNyPGVAcf",
- "stepId": "sas16Qqf4TmZEXSexmYpmSd",
- "content": "Go to URL",
- "edgeId": "7KgqWB88ufzhDwzvwHuEbN"
- }
- },
- "allIds": ["mAgynXh3zmkmWzNyPGVAcf"]
- },
- "variables": { "byId": {}, "allIds": [] },
- "edges": {
- "byId": {
- "totLsWG6AQfcFT39CsZwDy": {
- "from": {
- "blockId": "bsVJfEW7EZrUnAi9s5ev17",
- "stepId": "9Ck2yveNjZNHhjyc4HCJAL"
- },
- "to": { "blockId": "bmdnpyvzopZ8YVfqsJY7Q8K" },
- "id": "totLsWG6AQfcFT39CsZwDy"
+ {
+ "id": "rEJ3PhFQc7diJ23jdoF6w7",
+ "graphCoordinates": { "x": 294, "y": 201 },
+ "title": "Block #2",
+ "steps": [
+ {
+ "id": "s7QRApVZmVFZgS53CNruBRz",
+ "blockId": "rEJ3PhFQc7diJ23jdoF6w7",
+ "type": "choice input",
+ "options": { "buttonLabel": "Send", "isMultipleChoice": false },
+ "items": [
+ {
+ "id": "5rWR3enRg6jZyFhtmgbPYo",
+ "stepId": "s7QRApVZmVFZgS53CNruBRz",
+ "type": 0,
+ "content": "Go to URL",
+ "outgoingEdgeId": "6aVDkPMEsadze2vf4mLiYt"
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "variables": [],
+ "edges": [
+ {
+ "from": {
+ "blockId": "tdN9VXcdBWpuh6Gpaz3w4u",
+ "stepId": "cVRL5EuVruTK31SAaVCvNE"
},
- "7KgqWB88ufzhDwzvwHuEbN": {
- "from": {
- "blockId": "bmdnpyvzopZ8YVfqsJY7Q8K",
- "stepId": "sas16Qqf4TmZEXSexmYpmSd",
- "nodeId": "mAgynXh3zmkmWzNyPGVAcf"
- },
- "to": { "blockId": "bnsxmer7DD2R9DogoXTsvHJ" },
- "id": "7KgqWB88ufzhDwzvwHuEbN"
- }
+ "to": { "blockId": "rEJ3PhFQc7diJ23jdoF6w7" },
+ "id": "jqZYCYGxaL8svJbM2h1QAn"
},
- "allIds": ["totLsWG6AQfcFT39CsZwDy", "7KgqWB88ufzhDwzvwHuEbN"]
- },
+ {
+ "from": {
+ "blockId": "rEJ3PhFQc7diJ23jdoF6w7",
+ "stepId": "s7QRApVZmVFZgS53CNruBRz",
+ "itemId": "5rWR3enRg6jZyFhtmgbPYo"
+ },
+ "to": { "blockId": "vymPUjL9AcWpkg9PkUXovk" },
+ "id": "6aVDkPMEsadze2vf4mLiYt"
+ }
+ ],
"theme": {
"chat": {
"inputs": {
diff --git a/apps/builder/playwright/fixtures/typebots/logic/setVariable.json b/apps/builder/playwright/fixtures/typebots/logic/setVariable.json
index 9574ffb98..a63607894 100644
--- a/apps/builder/playwright/fixtures/typebots/logic/setVariable.json
+++ b/apps/builder/playwright/fixtures/typebots/logic/setVariable.json
@@ -1,152 +1,125 @@
{
- "id": "ckylrr3qh0030fn1a3nszzxiu",
- "createdAt": "2022-01-19T16:38:05.225Z",
- "updatedAt": "2022-01-19T16:38:05.225Z",
+ "id": "ckz8hovd511021no1apuuyjv7b",
+ "createdAt": "2022-02-04T14:15:06.953Z",
+ "updatedAt": "2022-02-04T14:15:06.953Z",
"name": "My typebot",
- "ownerId": "ckylrpsmt0006fn1ah956d0z1",
+ "ownerId": "ckz6t9iep0006k31a22j05fwq",
"publishedTypebotId": null,
"folderId": null,
- "webhooks": { "byId": {}, "allIds": [] },
- "blocks": {
- "byId": {
- "kmUzhRFzSKjkaipYNcku9S": {
- "id": "kmUzhRFzSKjkaipYNcku9S",
- "title": "Start",
- "stepIds": ["6XgP3JoCh7Y4M8GCX9DKym"],
- "graphCoordinates": { "x": 0, "y": 0 }
- },
- "bwWRAaX5m6NZyZ9jjpXmWSb": {
- "id": "bwWRAaX5m6NZyZ9jjpXmWSb",
- "title": "Block #2",
- "graphCoordinates": { "x": -21, "y": 221 },
- "stepIds": ["sqMVMXeRYp4inLcRqej2Wac", "s8n3nJajsBaYqrFeRYVvcf6"]
- },
- "baUyUnNBxZzPe1z5PqE4NkD": {
- "id": "baUyUnNBxZzPe1z5PqE4NkD",
- "title": "Block #3",
- "graphCoordinates": { "x": 375, "y": 280 },
- "stepIds": ["shfL5ueQDuj2RPcJPWZGArT", "sugJ6xN3jFys1CjWfsxGhiJ"]
- },
- "bwkKNpJmAFCCLbZSnPnnLnR": {
- "id": "bwkKNpJmAFCCLbZSnPnnLnR",
- "title": "Block #4",
- "graphCoordinates": { "x": 421, "y": 42 },
- "stepIds": ["shR7ae3iNEvB6arCSu7wVFF"]
- }
+ "blocks": [
+ {
+ "id": "jvbBpKifJ3ssvKQxPqhBiD",
+ "steps": [
+ {
+ "id": "rqecLJCZT7gP2JgBhRpb3a",
+ "type": "start",
+ "label": "Start",
+ "blockId": "jvbBpKifJ3ssvKQxPqhBiD",
+ "outgoingEdgeId": "qnD38SqA7sYEh7efPZgDoR"
+ }
+ ],
+ "title": "Start",
+ "graphCoordinates": { "x": 0, "y": 0 }
},
- "allIds": [
- "kmUzhRFzSKjkaipYNcku9S",
- "bwWRAaX5m6NZyZ9jjpXmWSb",
- "baUyUnNBxZzPe1z5PqE4NkD",
- "bwkKNpJmAFCCLbZSnPnnLnR"
- ]
- },
- "steps": {
- "byId": {
- "6XgP3JoCh7Y4M8GCX9DKym": {
- "id": "6XgP3JoCh7Y4M8GCX9DKym",
- "type": "start",
- "label": "Start",
- "blockId": "kmUzhRFzSKjkaipYNcku9S",
- "edgeId": "ahfJ4fUuvxX2dcBMk876tf"
- },
- "s8n3nJajsBaYqrFeRYVvcf6": {
- "id": "s8n3nJajsBaYqrFeRYVvcf6",
- "blockId": "bwWRAaX5m6NZyZ9jjpXmWSb",
- "type": "number input",
- "edgeId": "dcJedLC7qsLtsmm1wbiFFc",
- "options": {
- "labels": {
- "placeholder": "Type a number..."
+ {
+ "id": "roD9feCwx6jTDuVCThgzM2",
+ "graphCoordinates": { "x": 200, "y": 171 },
+ "title": "Block #1",
+ "steps": [
+ {
+ "id": "souEkLukHsYU9jrN2rAP7YT",
+ "blockId": "roD9feCwx6jTDuVCThgzM2",
+ "type": "text",
+ "content": {
+ "html": "How old are you?
",
+ "richText": [
+ { "type": "p", "children": [{ "text": "How old are you?" }] }
+ ],
+ "plainText": "How old are you?"
+ }
+ },
+ {
+ "id": "skfn5McXVrTNpi2e62RtEEY",
+ "blockId": "roD9feCwx6jTDuVCThgzM2",
+ "type": "number input",
+ "options": {
+ "labels": { "button": "Send", "placeholder": "Type a number..." }
+ },
+ "outgoingEdgeId": "5ZYDLyR1CUF6B8ESHrFXwK"
+ }
+ ]
+ },
+ {
+ "id": "tFFeBrrWxY4tvr11C8rjTw",
+ "graphCoordinates": { "x": 526, "y": 283 },
+ "title": "Block #2",
+ "steps": [
+ {
+ "id": "spgqbyvunY91Ct5kVgeLLkz",
+ "blockId": "tFFeBrrWxY4tvr11C8rjTw",
+ "type": "Set variable",
+ "options": {}
+ },
+ {
+ "id": "skeKC71L8C8wpfeuV4TTLCD",
+ "blockId": "tFFeBrrWxY4tvr11C8rjTw",
+ "type": "Set variable",
+ "options": {},
+ "outgoingEdgeId": "7A4BD2vJT87grt3xFw86bn"
+ }
+ ]
+ },
+ {
+ "id": "k6jFuKuSwy29LVwKxMWasv",
+ "graphCoordinates": { "x": 691, "y": 35 },
+ "title": "Block #3",
+ "steps": [
+ {
+ "id": "svpmd4uNoAXpoKyfYuuXTQe",
+ "blockId": "k6jFuKuSwy29LVwKxMWasv",
+ "type": "text",
+ "content": {
+ "html": "Total: {{Total}}
Custom var: {{Custom var}}
",
+ "richText": [
+ { "type": "p", "children": [{ "text": "Total: {{Total}}" }] },
+ {
+ "type": "p",
+ "children": [{ "text": "Custom var: {{Custom var}}" }]
+ }
+ ],
+ "plainText": "Total: {{Total}}Custom var: {{Custom var}}"
}
}
+ ]
+ }
+ ],
+ "variables": [],
+ "edges": [
+ {
+ "from": {
+ "blockId": "jvbBpKifJ3ssvKQxPqhBiD",
+ "stepId": "rqecLJCZT7gP2JgBhRpb3a"
},
- "sqMVMXeRYp4inLcRqej2Wac": {
- "id": "sqMVMXeRYp4inLcRqej2Wac",
- "blockId": "bwWRAaX5m6NZyZ9jjpXmWSb",
- "type": "text",
- "content": {
- "html": "How old are you?
",
- "richText": [
- { "type": "p", "children": [{ "text": "How old are you?" }] }
- ],
- "plainText": "How old are you?"
- }
- },
- "shfL5ueQDuj2RPcJPWZGArT": {
- "id": "shfL5ueQDuj2RPcJPWZGArT",
- "blockId": "baUyUnNBxZzPe1z5PqE4NkD",
- "type": "Set variable",
- "options": {}
- },
- "sugJ6xN3jFys1CjWfsxGhiJ": {
- "id": "sugJ6xN3jFys1CjWfsxGhiJ",
- "blockId": "baUyUnNBxZzPe1z5PqE4NkD",
- "type": "Set variable",
- "edgeId": "sA5gvCVVBVYdGsdeSGF5ei",
- "options": {}
- },
- "shR7ae3iNEvB6arCSu7wVFF": {
- "id": "shR7ae3iNEvB6arCSu7wVFF",
- "blockId": "bwkKNpJmAFCCLbZSnPnnLnR",
- "type": "text",
- "content": {
- "html": "Total: {{Total}}
Custom var: {{Custom var}}
",
- "richText": [
- { "type": "p", "children": [{ "text": "Total: {{Total}}" }] },
- {
- "type": "p",
- "children": [{ "text": "Custom var: {{Custom var}}" }]
- }
- ],
- "plainText": "Total: {{Total}}Custom var: {{Custom var}}"
- }
- }
+ "to": { "blockId": "roD9feCwx6jTDuVCThgzM2" },
+ "id": "qnD38SqA7sYEh7efPZgDoR"
},
- "allIds": [
- "6XgP3JoCh7Y4M8GCX9DKym",
- "s8n3nJajsBaYqrFeRYVvcf6",
- "sqMVMXeRYp4inLcRqej2Wac",
- "shfL5ueQDuj2RPcJPWZGArT",
- "sugJ6xN3jFys1CjWfsxGhiJ",
- "shR7ae3iNEvB6arCSu7wVFF"
- ]
- },
- "choiceItems": { "byId": {}, "allIds": [] },
- "variables": { "byId": {}, "allIds": [] },
- "edges": {
- "byId": {
- "ahfJ4fUuvxX2dcBMk876tf": {
- "from": {
- "blockId": "kmUzhRFzSKjkaipYNcku9S",
- "stepId": "6XgP3JoCh7Y4M8GCX9DKym"
- },
- "to": { "blockId": "bwWRAaX5m6NZyZ9jjpXmWSb" },
- "id": "ahfJ4fUuvxX2dcBMk876tf"
+ {
+ "from": {
+ "blockId": "roD9feCwx6jTDuVCThgzM2",
+ "stepId": "skfn5McXVrTNpi2e62RtEEY"
},
- "dcJedLC7qsLtsmm1wbiFFc": {
- "from": {
- "blockId": "bwWRAaX5m6NZyZ9jjpXmWSb",
- "stepId": "s8n3nJajsBaYqrFeRYVvcf6"
- },
- "to": { "blockId": "baUyUnNBxZzPe1z5PqE4NkD" },
- "id": "dcJedLC7qsLtsmm1wbiFFc"
- },
- "sA5gvCVVBVYdGsdeSGF5ei": {
- "from": {
- "blockId": "baUyUnNBxZzPe1z5PqE4NkD",
- "stepId": "sugJ6xN3jFys1CjWfsxGhiJ"
- },
- "to": { "blockId": "bwkKNpJmAFCCLbZSnPnnLnR" },
- "id": "sA5gvCVVBVYdGsdeSGF5ei"
- }
+ "to": { "blockId": "tFFeBrrWxY4tvr11C8rjTw" },
+ "id": "5ZYDLyR1CUF6B8ESHrFXwK"
},
- "allIds": [
- "ahfJ4fUuvxX2dcBMk876tf",
- "dcJedLC7qsLtsmm1wbiFFc",
- "sA5gvCVVBVYdGsdeSGF5ei"
- ]
- },
+ {
+ "from": {
+ "blockId": "tFFeBrrWxY4tvr11C8rjTw",
+ "stepId": "skeKC71L8C8wpfeuV4TTLCD"
+ },
+ "to": { "blockId": "k6jFuKuSwy29LVwKxMWasv" },
+ "id": "7A4BD2vJT87grt3xFw86bn"
+ }
+ ],
"theme": {
"chat": {
"inputs": {
diff --git a/apps/builder/playwright/fixtures/typebots/singleChoiceTarget.json b/apps/builder/playwright/fixtures/typebots/singleChoiceTarget.json
index 53753b8a2..aac9f1067 100644
--- a/apps/builder/playwright/fixtures/typebots/singleChoiceTarget.json
+++ b/apps/builder/playwright/fixtures/typebots/singleChoiceTarget.json
@@ -1,158 +1,126 @@
{
- "id": "ckylsr69q0240z31afjhedyxo",
- "createdAt": "2022-01-19T17:06:08.126Z",
- "updatedAt": "2022-01-19T17:06:08.126Z",
+ "id": "ckz8hrq1i11165no1artywpjvb",
+ "createdAt": "2022-02-04T14:17:20.022Z",
+ "updatedAt": "2022-02-04T14:17:20.022Z",
"name": "My typebot",
- "ownerId": "ckylsr4fi0220z31apbinpy9d",
+ "ownerId": "ckz6t9iep0006k31a22j05fwq",
"publishedTypebotId": null,
"folderId": null,
- "webhooks": { "byId": {}, "allIds": [] },
- "blocks": {
- "byId": {
- "weeBMMXxNKwEonMfDX8Z5k": {
- "id": "weeBMMXxNKwEonMfDX8Z5k",
- "title": "Start",
- "stepIds": ["nEXiHesKXRQJhQbaWfbDVH"],
- "graphCoordinates": { "x": 0, "y": 0 }
- },
- "bg2MBdkf6y7g6WsbqAP3eAT": {
- "id": "bg2MBdkf6y7g6WsbqAP3eAT",
- "title": "Block #2",
- "graphCoordinates": { "x": 120, "y": 221 },
- "stepIds": ["sqzMjp1Ba4jTL3A6iJehC6C"]
- },
- "bj5BE1yKPzFFhvRk6cMnmsQ": {
- "id": "bj5BE1yKPzFFhvRk6cMnmsQ",
- "title": "Block #3",
- "graphCoordinates": { "x": 529, "y": 130 },
- "stepIds": ["s8zPdEj96z8EoJG2zBqgoE8"]
- },
- "bdET8zLFQbwpTaAmi4wmezE": {
- "id": "bdET8zLFQbwpTaAmi4wmezE",
- "title": "Block #4",
- "graphCoordinates": { "x": 538, "y": 386 },
- "stepIds": ["sjZ28izS5e3VjNynFKT2F7E"]
- }
+ "blocks": [
+ {
+ "id": "3EgW9xiicKuiCNycEY2huP",
+ "steps": [
+ {
+ "id": "bHS7nGbziYUwD27tKANQY6",
+ "type": "start",
+ "label": "Start",
+ "blockId": "3EgW9xiicKuiCNycEY2huP",
+ "outgoingEdgeId": "9LViRZxY8G6iswJrE4YLsq"
+ }
+ ],
+ "title": "Start",
+ "graphCoordinates": { "x": 0, "y": 0 }
},
- "allIds": [
- "weeBMMXxNKwEonMfDX8Z5k",
- "bg2MBdkf6y7g6WsbqAP3eAT",
- "bj5BE1yKPzFFhvRk6cMnmsQ",
- "bdET8zLFQbwpTaAmi4wmezE"
- ]
- },
- "steps": {
- "byId": {
- "nEXiHesKXRQJhQbaWfbDVH": {
- "id": "nEXiHesKXRQJhQbaWfbDVH",
- "type": "start",
- "label": "Start",
- "blockId": "weeBMMXxNKwEonMfDX8Z5k",
- "edgeId": "uh95dDpiiZdYxpPFsUqZEg"
- },
- "sqzMjp1Ba4jTL3A6iJehC6C": {
- "id": "sqzMjp1Ba4jTL3A6iJehC6C",
- "blockId": "bg2MBdkf6y7g6WsbqAP3eAT",
- "type": "choice input",
- "options": {
- "itemIds": [
- "bWrsg18ucP9cdtFKhzgHbF",
- "p7Z57shv7p79KiwAtdi8Y3",
- "wjMRa2GBBnME9bEiNi6XgP"
- ]
- },
- "edgeId": "asT5shwJqDQ67qPuydR4gy"
- },
- "s8zPdEj96z8EoJG2zBqgoE8": {
- "id": "s8zPdEj96z8EoJG2zBqgoE8",
- "blockId": "bj5BE1yKPzFFhvRk6cMnmsQ",
- "type": "text",
- "content": {
- "html": "I love burgers!
",
- "richText": [
- { "type": "p", "children": [{ "text": "I love burgers!" }] }
+ {
+ "id": "bs9JCJfixRTv8W2imPAoyX",
+ "graphCoordinates": { "x": 392, "y": 180 },
+ "title": "Block #1",
+ "steps": [
+ {
+ "id": "sqcez9cUVbPvaFL4rQsUwUk",
+ "blockId": "bs9JCJfixRTv8W2imPAoyX",
+ "type": "choice input",
+ "options": { "buttonLabel": "Send", "isMultipleChoice": false },
+ "items": [
+ {
+ "id": "2jCerpszvvbmhUS8FXkKG9",
+ "stepId": "sqcez9cUVbPvaFL4rQsUwUk",
+ "type": 0,
+ "content": "Burgers",
+ "outgoingEdgeId": "aTS7nwxhRdFN8NwAXE2oSq"
+ },
+ {
+ "stepId": "sqcez9cUVbPvaFL4rQsUwUk",
+ "type": 0,
+ "id": "vP4HWCYkeRL6egk3yjCCmg",
+ "content": "Hot dogs"
+ },
+ {
+ "stepId": "sqcez9cUVbPvaFL4rQsUwUk",
+ "type": 0,
+ "id": "hhveB5JSxJ8X9N66LFaUfe",
+ "content": "Carpaccio"
+ }
],
- "plainText": "I love burgers!"
+ "outgoingEdgeId": "8FaF38WfM7PiLJLS5z6vQe"
}
- },
- "sjZ28izS5e3VjNynFKT2F7E": {
- "id": "sjZ28izS5e3VjNynFKT2F7E",
- "blockId": "bdET8zLFQbwpTaAmi4wmezE",
- "type": "text",
- "content": {
- "html": "Cool!
",
- "richText": [{ "type": "p", "children": [{ "text": "Cool!" }] }],
- "plainText": "Cool!"
+ ]
+ },
+ {
+ "id": "ih574JsgYCSSt3t77DH9gp",
+ "graphCoordinates": { "x": 770, "y": 105 },
+ "title": "Block #2",
+ "steps": [
+ {
+ "id": "s9hdG689cjRzmTdb5hMN83q",
+ "blockId": "ih574JsgYCSSt3t77DH9gp",
+ "type": "text",
+ "content": {
+ "html": "I love burgers!
",
+ "richText": [
+ { "type": "p", "children": [{ "text": "I love burgers!" }] }
+ ],
+ "plainText": "I love burgers!"
+ }
}
- }
+ ]
},
- "allIds": [
- "nEXiHesKXRQJhQbaWfbDVH",
- "sqzMjp1Ba4jTL3A6iJehC6C",
- "s8zPdEj96z8EoJG2zBqgoE8",
- "sjZ28izS5e3VjNynFKT2F7E"
- ]
- },
- "choiceItems": {
- "byId": {
- "bWrsg18ucP9cdtFKhzgHbF": {
- "id": "bWrsg18ucP9cdtFKhzgHbF",
- "stepId": "sqzMjp1Ba4jTL3A6iJehC6C",
- "content": "Burgers",
- "edgeId": "jfR6AUWt9b4dhjnUHXB179"
+ {
+ "id": "5bMwu6Wv79avgdz3TKjVXr",
+ "graphCoordinates": { "x": 766, "y": 311 },
+ "title": "Block #3",
+ "steps": [
+ {
+ "id": "s3Zwr8m3Nm2BwGxNNCu4n7N",
+ "blockId": "5bMwu6Wv79avgdz3TKjVXr",
+ "type": "text",
+ "content": {
+ "html": "Cool!
",
+ "richText": [{ "type": "p", "children": [{ "text": "Cool!" }] }],
+ "plainText": "Cool!"
+ }
+ }
+ ]
+ }
+ ],
+ "variables": [],
+ "edges": [
+ {
+ "from": {
+ "blockId": "3EgW9xiicKuiCNycEY2huP",
+ "stepId": "bHS7nGbziYUwD27tKANQY6"
},
- "p7Z57shv7p79KiwAtdi8Y3": {
- "id": "p7Z57shv7p79KiwAtdi8Y3",
- "stepId": "sqzMjp1Ba4jTL3A6iJehC6C",
- "content": "Hot dogs"
- },
- "wjMRa2GBBnME9bEiNi6XgP": {
- "id": "wjMRa2GBBnME9bEiNi6XgP",
- "stepId": "sqzMjp1Ba4jTL3A6iJehC6C",
- "content": "Carpaccio"
- }
+ "to": { "blockId": "bs9JCJfixRTv8W2imPAoyX" },
+ "id": "9LViRZxY8G6iswJrE4YLsq"
},
- "allIds": [
- "bWrsg18ucP9cdtFKhzgHbF",
- "p7Z57shv7p79KiwAtdi8Y3",
- "wjMRa2GBBnME9bEiNi6XgP"
- ]
- },
- "variables": { "byId": {}, "allIds": [] },
- "edges": {
- "byId": {
- "uh95dDpiiZdYxpPFsUqZEg": {
- "from": {
- "blockId": "weeBMMXxNKwEonMfDX8Z5k",
- "stepId": "nEXiHesKXRQJhQbaWfbDVH"
- },
- "to": { "blockId": "bg2MBdkf6y7g6WsbqAP3eAT" },
- "id": "uh95dDpiiZdYxpPFsUqZEg"
+ {
+ "from": {
+ "blockId": "bs9JCJfixRTv8W2imPAoyX",
+ "stepId": "sqcez9cUVbPvaFL4rQsUwUk",
+ "itemId": "2jCerpszvvbmhUS8FXkKG9"
},
- "jfR6AUWt9b4dhjnUHXB179": {
- "from": {
- "blockId": "bg2MBdkf6y7g6WsbqAP3eAT",
- "stepId": "sqzMjp1Ba4jTL3A6iJehC6C",
- "nodeId": "bWrsg18ucP9cdtFKhzgHbF"
- },
- "to": { "blockId": "bj5BE1yKPzFFhvRk6cMnmsQ" },
- "id": "jfR6AUWt9b4dhjnUHXB179"
- },
- "asT5shwJqDQ67qPuydR4gy": {
- "from": {
- "blockId": "bg2MBdkf6y7g6WsbqAP3eAT",
- "stepId": "sqzMjp1Ba4jTL3A6iJehC6C"
- },
- "to": { "blockId": "bdET8zLFQbwpTaAmi4wmezE" },
- "id": "asT5shwJqDQ67qPuydR4gy"
- }
+ "to": { "blockId": "ih574JsgYCSSt3t77DH9gp" },
+ "id": "aTS7nwxhRdFN8NwAXE2oSq"
},
- "allIds": [
- "uh95dDpiiZdYxpPFsUqZEg",
- "jfR6AUWt9b4dhjnUHXB179",
- "asT5shwJqDQ67qPuydR4gy"
- ]
- },
+ {
+ "from": {
+ "blockId": "bs9JCJfixRTv8W2imPAoyX",
+ "stepId": "sqcez9cUVbPvaFL4rQsUwUk"
+ },
+ "to": { "blockId": "5bMwu6Wv79avgdz3TKjVXr" },
+ "id": "8FaF38WfM7PiLJLS5z6vQe"
+ }
+ ],
"theme": {
"chat": {
"inputs": {
diff --git a/apps/builder/playwright/fixtures/typebots/theme.json b/apps/builder/playwright/fixtures/typebots/theme.json
index 56b0a3e72..c4782702d 100644
--- a/apps/builder/playwright/fixtures/typebots/theme.json
+++ b/apps/builder/playwright/fixtures/typebots/theme.json
@@ -1,140 +1,94 @@
{
- "id": "bdFW2HHjMoEFmqHtFre9Xi8",
- "createdAt": "2022-01-21T07:55:14.727Z",
- "updatedAt": "2022-01-21T07:55:14.727Z",
+ "id": "ckz8huhvo11297no1a7b4zf3ce",
+ "createdAt": "2022-02-04T14:19:29.412Z",
+ "updatedAt": "2022-02-04T14:19:29.412Z",
"name": "My typebot",
- "ownerId": "user2",
+ "ownerId": "ckz6t9iep0006k31a22j05fwq",
"publishedTypebotId": null,
"folderId": null,
- "blocks": {
- "byId": {
- "3kH2sUjVThQDWmqdoKnGk5": {
- "id": "3kH2sUjVThQDWmqdoKnGk5",
- "title": "Start",
- "stepIds": ["oxTsU2C1RX5QHuyY8qjHAM"],
- "graphCoordinates": { "x": 42, "y": 13 }
- },
- "bdFW2HHjMoEFmqHtFre9Xi8": {
- "id": "bdFW2HHjMoEFmqHtFre9Xi8",
- "title": "Block #2",
- "stepIds": ["sgkADMK25y9P9V3vjwjBaac", "ssEiEECKSFkA44dGDceHxKw"],
- "graphCoordinates": { "x": 121, "y": 227 }
- },
- "bhKHKi1SQb5woZEy1y4fNsJ": {
- "id": "bhKHKi1SQb5woZEy1y4fNsJ",
- "title": "Block #3",
- "graphCoordinates": { "x": 605, "y": 454 },
- "stepIds": ["sseUQEWCMdiZquk8EbxHYtk"]
- }
- },
- "allIds": [
- "3kH2sUjVThQDWmqdoKnGk5",
- "bdFW2HHjMoEFmqHtFre9Xi8",
- "bhKHKi1SQb5woZEy1y4fNsJ"
- ]
- },
- "steps": {
- "byId": {
- "oxTsU2C1RX5QHuyY8qjHAM": {
- "id": "oxTsU2C1RX5QHuyY8qjHAM",
- "type": "start",
- "label": "Start",
- "edgeId": "25yX9DnQgdafpdAjfAu5Fp",
- "blockId": "3kH2sUjVThQDWmqdoKnGk5"
- },
- "sgkADMK25y9P9V3vjwjBaac": {
- "id": "sgkADMK25y9P9V3vjwjBaac",
- "type": "text",
- "blockId": "bdFW2HHjMoEFmqHtFre9Xi8",
- "content": {
- "html": "Ready?
",
- "richText": [{ "type": "p", "children": [{ "text": "Ready?" }] }],
- "plainText": "Ready?"
+ "blocks": [
+ {
+ "id": "teepNancm8TLj1qYhaTYAf",
+ "steps": [
+ {
+ "id": "8fG3wDsExSSkq5ekUMzWVY",
+ "type": "start",
+ "label": "Start",
+ "blockId": "teepNancm8TLj1qYhaTYAf",
+ "outgoingEdgeId": "pj6fgTAjarwBq2jVgMgYoK"
}
- },
- "ssEiEECKSFkA44dGDceHxKw": {
- "id": "ssEiEECKSFkA44dGDceHxKw",
- "type": "choice input",
- "edgeId": "6e4Sbp8pGTvBQYtCk2qXbN",
- "blockId": "bdFW2HHjMoEFmqHtFre9Xi8",
- "options": { "itemIds": ["q69Ex7LacPrH9QUMeosRnB"] }
- },
- "sseUQEWCMdiZquk8EbxHYtk": {
- "id": "sseUQEWCMdiZquk8EbxHYtk",
- "blockId": "bhKHKi1SQb5woZEy1y4fNsJ",
- "type": "text input"
- }
+ ],
+ "title": "Start",
+ "graphCoordinates": { "x": 0, "y": 0 }
},
- "allIds": [
- "oxTsU2C1RX5QHuyY8qjHAM",
- "sgkADMK25y9P9V3vjwjBaac",
- "ssEiEECKSFkA44dGDceHxKw",
- "sseUQEWCMdiZquk8EbxHYtk"
- ]
- },
- "choiceItems": {
- "byId": {
- "q69Ex7LacPrH9QUMeosRnB": {
- "id": "q69Ex7LacPrH9QUMeosRnB",
- "stepId": "ssEiEECKSFkA44dGDceHxKw",
- "content": "Go"
- }
- },
- "allIds": ["q69Ex7LacPrH9QUMeosRnB"]
- },
- "variables": {
- "byId": {
- "4tvkRmf32wiTsXrYoqyhfr": {
- "id": "4tvkRmf32wiTsXrYoqyhfr",
- "name": "secret 2"
- },
- "jEg1FvkCU5S5owNAxXFsHL": {
- "id": "jEg1FvkCU5S5owNAxXFsHL",
- "name": "secret 3"
- },
- "oASkBtoLqkYNqeakcjZH4L": {
- "id": "oASkBtoLqkYNqeakcjZH4L",
- "name": "secret 1"
- },
- "rEoE1ehHzgx8X3d3UPGDHg": {
- "id": "rEoE1ehHzgx8X3d3UPGDHg",
- "name": "secret 4"
- }
- },
- "allIds": [
- "oASkBtoLqkYNqeakcjZH4L",
- "4tvkRmf32wiTsXrYoqyhfr",
- "jEg1FvkCU5S5owNAxXFsHL",
- "rEoE1ehHzgx8X3d3UPGDHg"
- ]
- },
- "webhooks": {
- "byId": {
- "4h4Kk3Q1qGy7gFzpZtWVpU": { "id": "4h4Kk3Q1qGy7gFzpZtWVpU", "url": "" }
- },
- "allIds": ["4h4Kk3Q1qGy7gFzpZtWVpU"]
- },
- "edges": {
- "byId": {
- "25yX9DnQgdafpdAjfAu5Fp": {
- "id": "25yX9DnQgdafpdAjfAu5Fp",
- "to": { "blockId": "bdFW2HHjMoEFmqHtFre9Xi8" },
- "from": {
- "stepId": "oxTsU2C1RX5QHuyY8qjHAM",
- "blockId": "3kH2sUjVThQDWmqdoKnGk5"
- }
- },
- "6e4Sbp8pGTvBQYtCk2qXbN": {
- "from": {
- "blockId": "bdFW2HHjMoEFmqHtFre9Xi8",
- "stepId": "ssEiEECKSFkA44dGDceHxKw"
+ {
+ "id": "6Dj1i7LeM3qXg5SKMhMyo1",
+ "graphCoordinates": { "x": 315, "y": 137 },
+ "title": "Block #1",
+ "steps": [
+ {
+ "id": "swUB2pSmvcv3NC7ySzskRpL",
+ "blockId": "6Dj1i7LeM3qXg5SKMhMyo1",
+ "type": "text",
+ "content": {
+ "html": "Ready?
",
+ "richText": [{ "type": "p", "children": [{ "text": "Ready?" }] }],
+ "plainText": "Ready?"
+ }
},
- "to": { "blockId": "bhKHKi1SQb5woZEy1y4fNsJ" },
- "id": "6e4Sbp8pGTvBQYtCk2qXbN"
- }
+ {
+ "id": "sc7ZYFtHVegJUA8c5K3gghi",
+ "blockId": "6Dj1i7LeM3qXg5SKMhMyo1",
+ "type": "choice input",
+ "options": { "buttonLabel": "Send", "isMultipleChoice": false },
+ "items": [
+ {
+ "id": "nTjur4kxyL473XTbAb4Fak",
+ "stepId": "sc7ZYFtHVegJUA8c5K3gghi",
+ "type": 0,
+ "content": "Go"
+ }
+ ],
+ "outgoingEdgeId": "uAsACqSmud99zmyCABWDwr"
+ }
+ ]
},
- "allIds": ["25yX9DnQgdafpdAjfAu5Fp", "6e4Sbp8pGTvBQYtCk2qXbN"]
- },
+ {
+ "id": "2TR5xAQobKAg8hbArfh5br",
+ "graphCoordinates": { "x": 760, "y": 299 },
+ "title": "Block #2",
+ "steps": [
+ {
+ "id": "s4xokHybra1jmZsWGVmza1K",
+ "blockId": "2TR5xAQobKAg8hbArfh5br",
+ "type": "text input",
+ "options": {
+ "isLong": false,
+ "labels": { "button": "Send", "placeholder": "Type your answer..." }
+ }
+ }
+ ]
+ }
+ ],
+ "variables": [],
+ "edges": [
+ {
+ "from": {
+ "blockId": "teepNancm8TLj1qYhaTYAf",
+ "stepId": "8fG3wDsExSSkq5ekUMzWVY"
+ },
+ "to": { "blockId": "6Dj1i7LeM3qXg5SKMhMyo1" },
+ "id": "pj6fgTAjarwBq2jVgMgYoK"
+ },
+ {
+ "from": {
+ "blockId": "6Dj1i7LeM3qXg5SKMhMyo1",
+ "stepId": "sc7ZYFtHVegJUA8c5K3gghi"
+ },
+ "to": { "blockId": "2TR5xAQobKAg8hbArfh5br" },
+ "id": "uAsACqSmud99zmyCABWDwr"
+ }
+ ],
"theme": {
"chat": {
"inputs": {
diff --git a/apps/builder/playwright/global-setup.ts b/apps/builder/playwright/global-setup.ts
index 8f6673bdf..e8c4ee34b 100644
--- a/apps/builder/playwright/global-setup.ts
+++ b/apps/builder/playwright/global-setup.ts
@@ -1,6 +1,10 @@
import { chromium, FullConfig, Page } from '@playwright/test'
import { existsSync } from 'fs'
-import { setupDatabase, teardownDatabase } from './services/database'
+import {
+ getSignedInUser,
+ setupDatabase,
+ teardownDatabase,
+} from './services/database'
// eslint-disable-next-line @typescript-eslint/no-var-requires
require('dotenv').config({ path: '.env' })
@@ -8,10 +12,15 @@ require('dotenv').config({ path: '.env' })
async function globalSetup(config: FullConfig) {
const { baseURL } = config.projects[0].use
if (!baseURL) throw new Error('baseURL is missing')
+ if (!process.env.GITHUB_EMAIL || !process.env.GITHUB_PASSWORD)
+ throw new Error(
+ 'GITHUB_EMAIL or GITHUB_PASSWORD are missing in the environment. They are required to log in.'
+ )
await teardownDatabase()
- if (!existsSync('./playwright/authenticatedState.json')) {
+ const signedInUser = await getSignedInUser(process.env.GITHUB_EMAIL as string)
+ if (!signedInUser || !existsSync('./playwright/authenticatedState.json')) {
const browser = await chromium.launch()
const page = await browser.newPage()
await signIn(page)
@@ -24,14 +33,13 @@ async function globalSetup(config: FullConfig) {
}
const signIn = async (page: Page) => {
- if (!process.env.GITHUB_EMAIL || !process.env.GITHUB_PASSWORD)
- throw new Error(
- 'GITHUB_EMAIL or GITHUB_PASSWORD are missing in the environment. They are required to log in.'
- )
await page.goto(`${process.env.PLAYWRIGHT_BUILDER_TEST_BASE_URL}/signin`)
await page.click('text=Continue with GitHub')
- await page.fill('input[name="login"]', process.env.GITHUB_EMAIL)
- await page.fill('input[name="password"]', process.env.GITHUB_PASSWORD)
+ await page.fill('input[name="login"]', process.env.GITHUB_EMAIL as string)
+ await page.fill(
+ 'input[name="password"]',
+ process.env.GITHUB_PASSWORD as string
+ )
await page.press('input[name="password"]', 'Enter')
try {
await page.locator('text=Authorize baptisteArno').click({ timeout: 3000 })
diff --git a/apps/builder/playwright/services/database.ts b/apps/builder/playwright/services/database.ts
index 797483861..92f89e886 100644
--- a/apps/builder/playwright/services/database.ts
+++ b/apps/builder/playwright/services/database.ts
@@ -1,6 +1,8 @@
import {
+ Block,
defaultSettings,
defaultTheme,
+ PublicBlock,
PublicTypebot,
Step,
Typebot,
@@ -23,7 +25,7 @@ export const setupDatabase = async (userEmail: string) => {
return createCredentials()
}
-const getSignedInUser = (email: string) =>
+export const getSignedInUser = (email: string) =>
prisma.user.findFirst({ where: { email } })
export const createTypebots = async (partialTypebots: Partial[]) => {
@@ -108,18 +110,24 @@ const parseTypebotToPublicTypebot = (
typebot: Typebot
): PublicTypebot => ({
id,
- blocks: typebot.blocks,
- steps: typebot.steps,
name: typebot.name,
+ blocks: parseBlocksToPublicBlocks(typebot.blocks),
typebotId: typebot.id,
theme: typebot.theme,
settings: typebot.settings,
publicId: typebot.publicId,
- choiceItems: typebot.choiceItems,
variables: typebot.variables,
edges: typebot.edges,
})
+const parseBlocksToPublicBlocks = (blocks: Block[]): PublicBlock[] =>
+ blocks.map((b) => ({
+ ...b,
+ steps: b.steps.map((s) =>
+ 'webhook' in s ? { ...s, webhook: s.webhook.id } : s
+ ),
+ }))
+
const parseTestTypebot = (partialTypebot: Partial): Typebot => ({
id: partialTypebot.id ?? 'typebot',
folderId: null,
@@ -128,82 +136,54 @@ const parseTestTypebot = (partialTypebot: Partial): Typebot => ({
theme: defaultTheme,
settings: defaultSettings,
createdAt: new Date(),
- choiceItems: partialTypebot.choiceItems ?? {
- byId: {
- choice1: {
- id: 'choice1',
- stepId: 'step1',
- },
- },
- allIds: ['choice1'],
- },
publicId: null,
publishedTypebotId: null,
updatedAt: new Date(),
- variables: { byId: {}, allIds: [] },
- webhooks: { byId: {}, allIds: [] },
- edges: {
- byId: {
- edge1: {
- id: 'edge1',
- from: { blockId: 'block0', stepId: 'step0' },
- to: { blockId: 'block1' },
- },
- },
- allIds: ['edge1'],
- },
+ variables: [],
...partialTypebot,
- blocks: {
- byId: {
- block0: {
- id: 'block0',
- title: 'Block #0',
- stepIds: ['step0'],
- graphCoordinates: { x: 0, y: 0 },
- },
- ...partialTypebot.blocks?.byId,
+ edges: [
+ {
+ id: 'edge1',
+ from: { blockId: 'block0', stepId: 'step0' },
+ to: { blockId: 'block1' },
},
- allIds: ['block0', ...(partialTypebot.blocks?.allIds ?? [])],
- },
- steps: {
- byId: {
- step0: {
- id: 'step0',
- type: 'start',
- blockId: 'block0',
- label: 'Start',
- edgeId: 'edge1',
- },
- ...partialTypebot.steps?.byId,
+ ],
+ blocks: [
+ {
+ id: 'block0',
+ title: 'Block #0',
+ steps: [
+ {
+ id: 'step0',
+ type: 'start',
+ blockId: 'block0',
+ label: 'Start',
+ outgoingEdgeId: 'edge1',
+ },
+ ],
+ graphCoordinates: { x: 0, y: 0 },
},
- allIds: ['step0', ...(partialTypebot.steps?.allIds ?? [])],
- },
+ ...(partialTypebot.blocks ?? []),
+ ],
})
export const parseDefaultBlockWithStep = (
step: Partial
-): Pick => ({
- blocks: {
- byId: {
- block1: {
- graphCoordinates: { x: 200, y: 200 },
- id: 'block1',
- stepIds: ['step1'],
- title: 'Block #1',
- },
+): Pick => ({
+ blocks: [
+ {
+ graphCoordinates: { x: 200, y: 200 },
+ id: 'block1',
+ steps: [
+ {
+ id: 'step1',
+ blockId: 'block1',
+ ...step,
+ } as Step,
+ ],
+ title: 'Block #1',
},
- allIds: ['block1'],
- },
- steps: {
- byId: {
- step1: {
- id: 'step1',
- blockId: 'block1',
- ...step,
- } as Step,
- },
- allIds: ['step1'],
- },
+ ],
})
export const importTypebotInDatabase = (
diff --git a/apps/builder/playwright/tests/account.spec.ts b/apps/builder/playwright/tests/account.spec.ts
index 760221051..55424a7c2 100644
--- a/apps/builder/playwright/tests/account.spec.ts
+++ b/apps/builder/playwright/tests/account.spec.ts
@@ -6,7 +6,11 @@ import { updateUser } from '../services/database'
test.describe('Account page', () => {
test('should edit user info properly', async ({ page }) => {
- await updateUser({ name: 'Default Name' })
+ await updateUser({
+ name: 'Default Name',
+ image:
+ 'https://images.unsplash.com/photo-1521119989659-a83eee488004?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1323&q=80',
+ })
await page.goto('/account')
const saveButton = page.locator('button:has-text("Save")')
await expect(saveButton).toBeHidden()
diff --git a/apps/builder/playwright/tests/bubbles/text.spec.ts b/apps/builder/playwright/tests/bubbles/text.spec.ts
index bd5a11da7..4f530afb9 100644
--- a/apps/builder/playwright/tests/bubbles/text.spec.ts
+++ b/apps/builder/playwright/tests/bubbles/text.spec.ts
@@ -24,22 +24,22 @@ test.describe('Text bubble step', () => {
await page.click('[data-testid="bold-button"]')
await page.type('div[role="textbox"]', 'Bold text')
- await page.press('div[role="textbox"]', 'Enter')
+ await page.press('div[role="textbox"]', 'Shift+Enter')
await page.click('[data-testid="bold-button"]')
await page.click('[data-testid="italic-button"]')
await page.type('div[role="textbox"]', 'Italic text')
- await page.press('div[role="textbox"]', 'Enter')
+ await page.press('div[role="textbox"]', 'Shift+Enter')
await page.click('[data-testid="underline-button"]')
await page.click('[data-testid="italic-button"]')
await page.type('div[role="textbox"]', 'Underlined text')
- await page.press('div[role="textbox"]', 'Enter')
+ await page.press('div[role="textbox"]', 'Shift+Enter')
await page.click('[data-testid="bold-button"]')
await page.click('[data-testid="italic-button"]')
await page.type('div[role="textbox"]', 'Everything text')
- await page.press('div[role="textbox"]', 'Enter')
+ await page.press('div[role="textbox"]', 'Shift+Enter')
await page.click('text=Preview')
await expect(
diff --git a/apps/builder/playwright/tests/editor.spec.ts b/apps/builder/playwright/tests/editor.spec.ts
index b1b552877..2c1752a67 100644
--- a/apps/builder/playwright/tests/editor.spec.ts
+++ b/apps/builder/playwright/tests/editor.spec.ts
@@ -1,9 +1,97 @@
-import test, { expect } from '@playwright/test'
-import { createTypebots, parseDefaultBlockWithStep } from '../services/database'
+import test, { expect, Page } from '@playwright/test'
+import {
+ createTypebots,
+ importTypebotInDatabase,
+ parseDefaultBlockWithStep,
+} from '../services/database'
import { defaultTextInputOptions, InputStepType } from 'models'
import { generate } from 'short-uuid'
+import path from 'path'
-test.describe('Editor', () => {
+test.describe.parallel('Editor', () => {
+ test('Edges connection should work', async ({ page }) => {
+ const typebotId = generate()
+ await createTypebots([
+ {
+ id: typebotId,
+ },
+ ])
+ await page.goto(`/typebots/${typebotId}/edit`)
+ await page.dragAndDrop('text=Button', '#editor-container', {
+ targetPosition: { x: 800, y: 400 },
+ })
+ await page.dragAndDrop(
+ 'text=Text >> nth=0',
+ '[data-testid="block"] >> nth=1',
+ {
+ targetPosition: { x: 100, y: 50 },
+ }
+ )
+ await page.dragAndDrop(
+ '[data-testid="endpoint"]',
+ '[data-testid="block"] >> nth=1',
+ { targetPosition: { x: 100, y: 10 } }
+ )
+ await expect(page.locator('[data-testid="edge"]')).toBeVisible()
+ await page.dragAndDrop(
+ '[data-testid="endpoint"]',
+ '[data-testid="step"] >> nth=1'
+ )
+ await expect(page.locator('[data-testid="edge"]')).toBeVisible()
+ await page.dragAndDrop('text=Date', '#editor-container', {
+ targetPosition: { x: 1000, y: 800 },
+ })
+ await page.dragAndDrop(
+ '[data-testid="endpoint"] >> nth=2',
+ '[data-testid="block"] >> nth=2',
+ {
+ targetPosition: { x: 100, y: 10 },
+ }
+ )
+ await expect(page.locator('[data-testid="edge"] >> nth=0')).toBeVisible()
+ await expect(page.locator('[data-testid="edge"] >> nth=1')).toBeVisible()
+ })
+ test('Drag and drop steps and items should work', async ({ page }) => {
+ const typebotId = generate()
+ await importTypebotInDatabase(
+ path.join(__dirname, '../fixtures/typebots/editor/buttonsDnd.json'),
+ {
+ id: typebotId,
+ }
+ )
+
+ // Steps dnd
+ await page.goto(`/typebots/${typebotId}/edit`)
+ await expect(page.locator('[data-testid="step"] >> nth=1')).toHaveText(
+ 'Hello!'
+ )
+ await page.dragAndDrop('text=Hello', 'text=Item 1')
+ await expect(page.locator('[data-testid="step"] >> nth=2')).toHaveText(
+ 'Hello!'
+ )
+ await page.dragAndDrop('text=Hello', '[data-testid="step"] >> text=Start')
+ await expect(page.locator('text=Block #4')).toBeVisible()
+ await page.dragAndDrop('text=Hello', 'text=Block #2')
+ await expect(page.locator('[data-testid="step"] >> nth=3')).toHaveText(
+ 'Hello!'
+ )
+
+ // Items dnd
+ await expect(page.locator('[data-testid="item"] >> nth=0')).toHaveText(
+ 'Item 1'
+ )
+ await page.dragAndDrop('text=Item 1', 'text=Item 3')
+ await expect(page.locator('[data-testid="item"] >> nth=2')).toHaveText(
+ 'Item 1'
+ )
+ await expect(page.locator('[data-testid="item"] >> nth=1')).toHaveText(
+ 'Item 3'
+ )
+ await page.dragAndDrop('text=Item 3', 'text=Item 2-3')
+ await expect(page.locator('[data-testid="item"] >> nth=6')).toHaveText(
+ 'Item 3'
+ )
+ })
test('Undo / Redo buttons should work', async ({ page }) => {
const typebotId = generate()
await createTypebots([
diff --git a/apps/builder/playwright/tests/inputs/buttons.spec.ts b/apps/builder/playwright/tests/inputs/buttons.spec.ts
index 4f3e97ffb..df95ed19d 100644
--- a/apps/builder/playwright/tests/inputs/buttons.spec.ts
+++ b/apps/builder/playwright/tests/inputs/buttons.spec.ts
@@ -3,7 +3,7 @@ import {
createTypebots,
parseDefaultBlockWithStep,
} from '../../services/database'
-import { defaultChoiceInputOptions, InputStepType } from 'models'
+import { defaultChoiceInputOptions, InputStepType, ItemType } from 'models'
import { typebotViewer } from '../../services/selectorUtils'
import { generate } from 'short-uuid'
@@ -15,7 +15,14 @@ test.describe.parallel('Buttons input step', () => {
id: typebotId,
...parseDefaultBlockWithStep({
type: InputStepType.CHOICE,
- options: { ...defaultChoiceInputOptions, itemIds: ['choice1'] },
+ items: [
+ {
+ id: 'choice1',
+ stepId: 'step1',
+ type: ItemType.BUTTON,
+ },
+ ],
+ options: { ...defaultChoiceInputOptions },
}),
},
])
@@ -23,14 +30,11 @@ test.describe.parallel('Buttons input step', () => {
await page.goto(`/typebots/${typebotId}/edit`)
await page.fill('input[value="Click to edit"]', 'Item 1')
await page.press('input[value="Item 1"]', 'Enter')
- await page.locator('text=Item 1').hover()
- await page.click('[aria-label="Add item"]')
await page.fill('input[value="Click to edit"]', 'Item 2')
await page.press('input[value="Item 2"]', 'Enter')
- await page.locator('text=Item 2').hover()
- await page.click('[aria-label="Add item"]')
await page.fill('input[value="Click to edit"]', 'Item 3')
await page.press('input[value="Item 3"]', 'Enter')
+ await page.press('input[value="Click to edit"]', 'Escape')
await page.click('text=Item 2', { button: 'right' })
await page.click('text=Delete')
await expect(page.locator('text=Item 2')).toBeHidden()
diff --git a/apps/builder/playwright/tests/integrations/googleSheets.spec.ts b/apps/builder/playwright/tests/integrations/googleSheets.spec.ts
index d103806c1..b3cb9f178 100644
--- a/apps/builder/playwright/tests/integrations/googleSheets.spec.ts
+++ b/apps/builder/playwright/tests/integrations/googleSheets.spec.ts
@@ -145,7 +145,7 @@ test.describe.parallel('Google sheets integration', () => {
.press('Enter')
await expect(
typebotViewer(page).locator('text=Your name is: John Smith')
- ).toBeVisible()
+ ).toBeVisible({ timeout: 30000 })
})
})
diff --git a/apps/builder/playwright/tests/logic/condition.spec.ts b/apps/builder/playwright/tests/logic/condition.spec.ts
index 2968c1e19..be3172f27 100644
--- a/apps/builder/playwright/tests/logic/condition.spec.ts
+++ b/apps/builder/playwright/tests/logic/condition.spec.ts
@@ -16,8 +16,7 @@ test.describe('Condition step', () => {
)
await page.goto(`/typebots/${typebotId}/edit`)
- await page.click('text=Configure...')
- await page.click('button:has-text("Add a comparison")')
+ await page.click('text=Configure... >> nth=0', { force: true })
await page.fill(
'input[placeholder="Search for a variable"] >> nth=-1',
'Age'
@@ -41,8 +40,7 @@ test.describe('Condition step', () => {
'100'
)
- await page.click('text=Configure...')
- await page.click('button:has-text("Add a comparison")')
+ await page.click('text=Configure...', { force: true })
await page.fill(
'input[placeholder="Search for a variable"] >> nth=-1',
'Age'
@@ -54,7 +52,7 @@ test.describe('Condition step', () => {
await page.click('text=Preview')
await typebotViewer(page)
- .locator('input[placeholder="Type your answer..."]')
+ .locator('input[placeholder="Type a number..."]')
.fill('15')
await typebotViewer(page).locator('text=Send').click()
await expect(
@@ -63,7 +61,7 @@ test.describe('Condition step', () => {
await page.click('text=Restart')
await typebotViewer(page)
- .locator('input[placeholder="Type your answer..."]')
+ .locator('input[placeholder="Type a number..."]')
.fill('45')
await typebotViewer(page).locator('text=Send').click()
await expect(
@@ -72,7 +70,7 @@ test.describe('Condition step', () => {
await page.click('text=Restart')
await typebotViewer(page)
- .locator('input[placeholder="Type your answer..."]')
+ .locator('input[placeholder="Type a number..."]')
.fill('90')
await typebotViewer(page).locator('text=Send').click()
await expect(
diff --git a/apps/builder/playwright/tests/theme.spec.ts b/apps/builder/playwright/tests/theme.spec.ts
index 7be72baa2..6c48e65e5 100644
--- a/apps/builder/playwright/tests/theme.spec.ts
+++ b/apps/builder/playwright/tests/theme.spec.ts
@@ -31,7 +31,7 @@ test.describe.parallel('Theme page', () => {
)
await page.click('text=Color')
await page.click('[aria-label="Pick a color"]')
- await page.fill('[aria-label="Color value"]', '#2a9d8f')
+ await page.fill('[aria-label="Color value"] >> nth=-1', '#2a9d8f')
await expect(chatContainer).toHaveCSS(
'background-color',
'rgb(42, 157, 143)'
@@ -56,10 +56,14 @@ test.describe.parallel('Theme page', () => {
await page.waitForTimeout(300)
// Host bubbles
- await page.click(':nth-match([aria-label="Pick a color"], 1)')
- await page.fill('[aria-label="Color value"]', '#2a9d8f')
- await page.click(':nth-match([aria-label="Pick a color"], 2)')
- await page.fill('[aria-label="Color value"]', '#ffffff')
+ await page.click(
+ '[data-testid="host-bubbles-theme"] >> [aria-label="Pick a color"] >> nth=0'
+ )
+ await page.fill('input[value="#F7F8FF"]', '#2a9d8f')
+ await page.click(
+ '[data-testid="host-bubbles-theme"] >> [aria-label="Pick a color"] >> nth=1'
+ )
+ await page.fill('input[value="#303235"]', '#ffffff')
const hostBubble = typebotViewer(page).locator(
'[data-testid="host-bubble"]'
)
@@ -70,19 +74,27 @@ test.describe.parallel('Theme page', () => {
await expect(hostBubble).toHaveCSS('color', 'rgb(255, 255, 255)')
// Buttons
- await page.click(':nth-match([aria-label="Pick a color"], 5)')
- await page.fill('[aria-label="Color value"]', '#7209b7')
- await page.click(':nth-match([aria-label="Pick a color"], 6)')
- await page.fill('[aria-label="Color value"]', '#e9c46a')
+ await page.click(
+ '[data-testid="buttons-theme"] >> [aria-label="Pick a color"] >> nth=0'
+ )
+ await page.fill('input[value="#0042DA"]', '#7209b7')
+ await page.click(
+ '[data-testid="buttons-theme"] >> [aria-label="Pick a color"] >> nth=1'
+ )
+ await page.fill('input[value="#FFFFFF"]', '#e9c46a')
const button = typebotViewer(page).locator('[data-testid="button"]')
await expect(button).toHaveCSS('background-color', 'rgb(114, 9, 183)')
await expect(button).toHaveCSS('color', 'rgb(233, 196, 106)')
// Guest bubbles
- await page.click(':nth-match([aria-label="Pick a color"], 3)')
- await page.fill('[aria-label="Color value"]', '#d8f3dc')
- await page.click(':nth-match([aria-label="Pick a color"], 4)')
- await page.fill('[aria-label="Color value"]', '#264653')
+ await page.click(
+ '[data-testid="guest-bubbles-theme"] >> [aria-label="Pick a color"] >> nth=0'
+ )
+ await page.fill('input[value="#FF8E21"]', '#d8f3dc')
+ await page.click(
+ '[data-testid="guest-bubbles-theme"] >> [aria-label="Pick a color"] >> nth=1'
+ )
+ await page.fill('input[value="#FFFFFF"]', '#264653')
await typebotViewer(page).locator('text=Go').click()
const guestBubble = typebotViewer(page).locator(
'[data-testid="guest-bubble"]'
@@ -94,10 +106,14 @@ test.describe.parallel('Theme page', () => {
await expect(guestBubble).toHaveCSS('color', 'rgb(38, 70, 83)')
// Input
- await page.click(':nth-match([aria-label="Pick a color"], 7)')
- await page.fill('[aria-label="Color value"]', '#ffe8d6')
- await page.click(':nth-match([aria-label="Pick a color"], 8)')
- await page.fill('[aria-label="Color value"]', '#023e8a')
+ await page.click(
+ '[data-testid="inputs-theme"] >> [aria-label="Pick a color"] >> nth=0'
+ )
+ await page.fill('input[value="#FFFFFF"]', '#ffe8d6')
+ await page.click(
+ '[data-testid="inputs-theme"] >> [aria-label="Pick a color"] >> nth=1'
+ )
+ await page.fill('input[value="#303235"]', '#023e8a')
await typebotViewer(page).locator('text=Go').click()
const input = typebotViewer(page).locator('.typebot-input')
await expect(input).toHaveCSS('background-color', 'rgb(255, 232, 214)')
diff --git a/apps/builder/services/graph.ts b/apps/builder/services/graph.ts
index 1016730b8..c2b9afd52 100644
--- a/apps/builder/services/graph.ts
+++ b/apps/builder/services/graph.ts
@@ -1,13 +1,11 @@
-import { Edge, Table, Target } from 'models'
+import { Edge, IdMap } from 'models'
import { AnchorsPositionProps } from 'components/shared/Graph/Edges/Edge'
import {
stubLength,
blockWidth,
blockAnchorsOffset,
- ConnectingIds,
Endpoint,
Coordinates,
- BlocksCoordinates,
} from 'contexts/GraphContext'
import { roundCorners } from 'svg-round-corners'
import { headerHeight } from 'components/shared/TypebotHeader'
@@ -230,20 +228,11 @@ export const computeEdgePath = ({
}
export const computeConnectingEdgePath = ({
- connectingIds,
+ sourceBlockCoordinates,
+ targetBlockCoordinates,
sourceTop,
targetTop,
- blocksCoordinates,
-}: {
- connectingIds: Omit & { target: Target }
- sourceTop: number
- targetTop?: number
- blocksCoordinates: BlocksCoordinates
-}) => {
- const sourceBlockCoordinates =
- blocksCoordinates.byId[connectingIds.source.blockId]
- const targetBlockCoordinates =
- blocksCoordinates.byId[connectingIds.target.blockId]
+}: GetAnchorsPositionParams) => {
const anchorsPosition = getAnchorsPosition({
sourceBlockCoordinates,
targetBlockCoordinates,
@@ -254,23 +243,25 @@ export const computeConnectingEdgePath = ({
}
export const computeEdgePathToMouse = ({
- blockPosition,
+ sourceBlockCoordinates,
mousePosition,
sourceTop,
}: {
- blockPosition: Coordinates
+ sourceBlockCoordinates: Coordinates
mousePosition: Coordinates
sourceTop: number
}): string => {
const sourcePosition = {
x:
- mousePosition.x - blockPosition.x > blockWidth / 2
- ? blockPosition.x + blockWidth - 40
- : blockPosition.x + 40,
+ mousePosition.x - sourceBlockCoordinates.x > blockWidth / 2
+ ? sourceBlockCoordinates.x + blockWidth - 40
+ : sourceBlockCoordinates.x + 40,
y: sourceTop,
}
const sourceType =
- mousePosition.x - blockPosition.x > blockWidth / 2 ? 'right' : 'left'
+ mousePosition.x - sourceBlockCoordinates.x > blockWidth / 2
+ ? 'right'
+ : 'left'
const segments = computeThreeSegments(
sourcePosition,
mousePosition,
@@ -284,11 +275,11 @@ export const computeEdgePathToMouse = ({
export const getEndpointTopOffset = (
graphPosition: Coordinates,
- endpoints: Table,
+ endpoints: IdMap,
endpointId?: string
): number | undefined => {
if (!endpointId) return
- const endpointRef = endpoints.byId[endpointId]?.ref
+ const endpointRef = endpoints[endpointId]?.ref
if (!endpointRef) return
return (
8 +
@@ -299,4 +290,4 @@ export const getEndpointTopOffset = (
}
export const getSourceEndpointId = (edge?: Edge) =>
- edge?.from.buttonId ?? edge?.from.stepId + `${edge?.from.conditionType ?? ''}`
+ edge?.from.itemId ?? edge?.from.stepId
diff --git a/apps/builder/services/integrations.ts b/apps/builder/services/integrations.ts
index 6028e58f0..20fbb5f22 100644
--- a/apps/builder/services/integrations.ts
+++ b/apps/builder/services/integrations.ts
@@ -2,7 +2,7 @@ import { sendRequest } from 'utils'
import { stringify } from 'qs'
import useSWR from 'swr'
import { fetcher } from './utils'
-import { Table, Variable, VariableForTest, WebhookResponse } from 'models'
+import { StepIndices, Variable, VariableForTest, WebhookResponse } from 'models'
export const getGoogleSheetsConsentScreenUrl = (
redirectUrl: string,
@@ -69,10 +69,11 @@ export const useSheets = ({
export const executeWebhook = (
typebotId: string,
webhookId: string,
- variables: Table
+ variables: Variable[],
+ { blockIndex, stepIndex }: StepIndices
) =>
sendRequest({
- url: `/api/typebots/${typebotId}/webhooks/${webhookId}/execute`,
+ url: `/api/typebots/${typebotId}/blocks/${blockIndex}/steps/${stepIndex}/executeWebhook`,
method: 'POST',
body: {
variables,
@@ -80,28 +81,21 @@ export const executeWebhook = (
})
export const convertVariableForTestToVariables = (
- variablesForTest: Table | undefined,
- variables: Table
-): Table => {
- if (!variablesForTest) return { byId: {}, allIds: [] }
- return {
- byId: {
- ...variables.byId,
- ...variablesForTest.allIds.reduce((obj, id) => {
- const variableForTest = variablesForTest.byId[id]
- if (!variableForTest.variableId) return {}
- const variable = variables.byId[variableForTest.variableId ?? '']
- return {
- ...obj,
- [variableForTest.variableId]: {
- ...variable,
- value: variableForTest.value,
- },
- }
+ variablesForTest: VariableForTest[],
+ variables: Variable[]
+): Variable[] => {
+ if (!variablesForTest) return []
+ return [
+ ...variables,
+ ...variablesForTest
+ .filter((v) => v.variableId)
+ .map((variableForTest) => {
+ const variable = variables.find(
+ (v) => v.id === variableForTest.variableId
+ ) as Variable
+ return { ...variable, value: variableForTest.value }
}, {}),
- },
- allIds: variables.allIds,
- }
+ ]
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
diff --git a/apps/builder/services/publicTypebot.tsx b/apps/builder/services/publicTypebot.tsx
index 0f1b434aa..5faf1473d 100644
--- a/apps/builder/services/publicTypebot.tsx
+++ b/apps/builder/services/publicTypebot.tsx
@@ -1,26 +1,39 @@
-import { PublicTypebot, Typebot } from 'models'
+import {
+ Block,
+ InputStep,
+ PublicBlock,
+ PublicStep,
+ PublicTypebot,
+ Step,
+ Typebot,
+} from 'models'
import shortId from 'short-uuid'
import { HStack, Text } from '@chakra-ui/react'
import { CalendarIcon } from 'assets/icons'
import { StepIcon } from 'components/editor/StepsSideBar/StepIcon'
import { isInputStep, sendRequest } from 'utils'
+import { isDefined } from '@udecode/plate-common'
export const parseTypebotToPublicTypebot = (
typebot: Typebot
): PublicTypebot => ({
+ ...typebot,
id: shortId.generate(),
- blocks: typebot.blocks,
- steps: typebot.steps,
- name: typebot.name,
typebotId: typebot.id,
- theme: typebot.theme,
- settings: typebot.settings,
- publicId: typebot.publicId,
- choiceItems: typebot.choiceItems,
- variables: typebot.variables,
- edges: typebot.edges,
+ blocks: parseBlocksToPublicBlocks(typebot.blocks),
})
+const parseBlocksToPublicBlocks = (blocks: Block[]): PublicBlock[] =>
+ blocks.map((b) => ({
+ ...b,
+ steps: b.steps.map(
+ (s) =>
+ ('webhook' in s && isDefined(s.webhook)
+ ? { ...s, webhook: s.webhook.id }
+ : s) as PublicStep
+ ),
+ }))
+
export const createPublishedTypebot = async (
typebot: Omit
) =>
@@ -41,12 +54,11 @@ export const updatePublishedTypebot = async (
})
export const parseSubmissionsColumns = (
- typebot?: PublicTypebot
+ typebot: PublicTypebot
): {
Header: JSX.Element
accessor: string
}[] => {
- if (!typebot) return []
return [
{
Header: (
@@ -57,14 +69,14 @@ export const parseSubmissionsColumns = (
),
accessor: 'createdAt',
},
- ...typebot.blocks.allIds
- .filter((blockId) => typebot && blockContainsInput(typebot, blockId))
- .map((blockId) => {
- const block = typebot.blocks.byId[blockId]
- const inputStepId = block.stepIds.find((stepId) =>
- isInputStep(typebot.steps.byId[stepId])
- )
- const inputStep = typebot.steps.byId[inputStepId as string]
+ ...typebot.blocks
+ .filter(
+ (block) => typebot && block.steps.some((step) => isInputStep(step))
+ )
+ .map((block) => {
+ const inputStep = block.steps.find((step) =>
+ isInputStep(step)
+ ) as InputStep
return {
Header: (
@@ -72,16 +84,8 @@ export const parseSubmissionsColumns = (
{block.title}
),
- accessor: blockId,
+ accessor: block.id,
}
}),
]
}
-
-const blockContainsInput = (
- typebot: PublicTypebot | Typebot,
- blockId: string
-) =>
- typebot.blocks.byId[blockId].stepIds.some((stepId) =>
- isInputStep(typebot.steps.byId[stepId])
- )
diff --git a/apps/builder/services/typebots.ts b/apps/builder/services/typebots.ts
index b376265b3..a3903d242 100644
--- a/apps/builder/services/typebots.ts
+++ b/apps/builder/services/typebots.ts
@@ -24,18 +24,27 @@ import {
defaultUrlInputOptions,
defaultChoiceInputOptions,
defaultSetVariablesOptions,
- defaultConditionOptions,
defaultRedirectOptions,
defaultGoogleSheetsOptions,
defaultGoogleAnalyticsOptions,
defaultWebhookOptions,
StepWithOptionsType,
+ defaultWebhookAttributes,
+ Webhook,
+ Item,
+ ItemType,
+ defaultConditionContent,
} from 'models'
import shortId, { generate } from 'short-uuid'
import { Typebot } from 'models'
import useSWR from 'swr'
import { fetcher, toKebabCase } from './utils'
-import { isBubbleStepType, stepTypeHasOption } from 'utils'
+import {
+ isBubbleStepType,
+ stepTypeHasItems,
+ stepTypeHasOption,
+ stepTypeHasWebhook,
+} from 'utils'
import { deepEqual } from 'fast-equals'
import { stringify } from 'qs'
import { isChoiceInput, isConditionStep, sendRequest } from 'utils'
@@ -125,9 +134,35 @@ export const parseNewStep = (
options: stepTypeHasOption(type)
? parseDefaultStepOptions(type)
: undefined,
+ webhook: stepTypeHasWebhook(type) ? parseDefaultWebhook() : undefined,
+ items: stepTypeHasItems(type) ? parseDefaultItems(type, id) : undefined,
} as DraggableStep
}
+const parseDefaultWebhook = (): Webhook => ({
+ id: generate(),
+ ...defaultWebhookAttributes,
+})
+
+const parseDefaultItems = (
+ type: LogicStepType.CONDITION | InputStepType.CHOICE,
+ stepId: string
+): Item[] => {
+ switch (type) {
+ case InputStepType.CHOICE:
+ return [{ id: generate(), stepId, type: ItemType.BUTTON }]
+ case LogicStepType.CONDITION:
+ return [
+ {
+ id: generate(),
+ stepId,
+ type: ItemType.CONDITION,
+ content: defaultConditionContent,
+ },
+ ]
+ }
+}
+
const parseDefaultContent = (type: BubbleStepType): BubbleStepContent => {
switch (type) {
case BubbleStepType.TEXT:
@@ -154,11 +189,9 @@ const parseDefaultStepOptions = (type: StepWithOptionsType): StepOptions => {
case InputStepType.URL:
return defaultUrlInputOptions
case InputStepType.CHOICE:
- return { ...defaultChoiceInputOptions, itemIds: [generate()] }
+ return defaultChoiceInputOptions
case LogicStepType.SET_VARIABLE:
return defaultSetVariablesOptions
- case LogicStepType.CONDITION:
- return defaultConditionOptions
case LogicStepType.REDIRECT:
return defaultRedirectOptions
case IntegrationStepType.GOOGLE_SHEETS:
@@ -166,7 +199,7 @@ const parseDefaultStepOptions = (type: StepWithOptionsType): StepOptions => {
case IntegrationStepType.GOOGLE_ANALYTICS:
return defaultGoogleAnalyticsOptions
case IntegrationStepType.WEBHOOK:
- return { ...defaultWebhookOptions, webhookId: generate() }
+ return defaultWebhookOptions
}
}
@@ -181,7 +214,6 @@ export const checkIfPublished = (
publicTypebot: PublicTypebot
) =>
deepEqual(typebot.blocks, publicTypebot.blocks) &&
- deepEqual(typebot.steps, publicTypebot.steps) &&
typebot.name === publicTypebot.name &&
typebot.publicId === publicTypebot.publicId &&
deepEqual(typebot.settings, publicTypebot.settings) &&
@@ -214,18 +246,15 @@ export const parseNewTypebot = ({
id: startBlockId,
title: 'Start',
graphCoordinates: { x: 0, y: 0 },
- stepIds: [startStepId],
+ steps: [startStep],
}
return {
folderId,
name,
ownerId,
- blocks: { byId: { [startBlockId]: startBlock }, allIds: [startBlockId] },
- steps: { byId: { [startStepId]: startStep }, allIds: [startStepId] },
- choiceItems: { byId: {}, allIds: [] },
- variables: { byId: {}, allIds: [] },
- edges: { byId: {}, allIds: [] },
- webhooks: { byId: {}, allIds: [] },
+ blocks: [startBlock],
+ edges: [],
+ variables: [],
theme: defaultTheme,
settings: defaultSettings,
}
diff --git a/apps/builder/services/utils/utils.ts b/apps/builder/services/utils/utils.ts
index de8ae90cc..947573d54 100644
--- a/apps/builder/services/utils/utils.ts
+++ b/apps/builder/services/utils/utils.ts
@@ -100,11 +100,8 @@ export const removeUndefinedFields = (obj: T): T =>
export const stepHasOptions = (step: Step) => 'options' in step
-export const parseVariableHighlight = (content: string, typebot?: Typebot) => {
- if (!typebot) return content
- const varNames = typebot.variables.allIds.map(
- (varId) => typebot.variables.byId[varId].name
- )
+export const parseVariableHighlight = (content: string, typebot: Typebot) => {
+ const varNames = typebot.variables.map((v) => v.name)
return content.replace(/\{\{(.*?)\}\}/g, (fullMatch, foundVar) => {
if (varNames.some((val) => foundVar.includes(val))) {
return `${fullMatch.replace(
@@ -115,3 +112,8 @@ export const parseVariableHighlight = (content: string, typebot?: Typebot) => {
return fullMatch
})
}
+
+export const setMultipleRefs =
+ (refs: React.MutableRefObject[]) =>
+ (elem: HTMLDivElement) =>
+ refs.forEach((ref) => (ref.current = elem))
diff --git a/apps/viewer/layouts/TypebotPage.tsx b/apps/viewer/layouts/TypebotPage.tsx
index e62a7f98b..052a6afba 100644
--- a/apps/viewer/layouts/TypebotPage.tsx
+++ b/apps/viewer/layouts/TypebotPage.tsx
@@ -5,7 +5,6 @@ import { upsertAnswer } from 'services/answer'
import { SEO } from '../components/Seo'
import { createResult, updateResult } from '../services/result'
import { ErrorPage } from './ErrorPage'
-import { NotFoundPage } from './NotFoundPage'
export type TypebotPageProps = {
typebot?: PublicTypebot
@@ -15,7 +14,11 @@ export type TypebotPageProps = {
const sessionStorageKey = 'resultId'
-export const TypebotPage = ({ typebot, isIE, url }: TypebotPageProps) => {
+export const TypebotPage = ({
+ typebot,
+ isIE,
+ url,
+}: TypebotPageProps & { typebot: PublicTypebot }) => {
const [error, setError] = useState(
isIE ? new Error('Internet explorer is not supported') : undefined
)
@@ -27,7 +30,6 @@ export const TypebotPage = ({ typebot, isIE, url }: TypebotPageProps) => {
}, [])
const initializeResult = async () => {
- if (!typebot) return
const resultIdFromSession = sessionStorage.getItem(sessionStorageKey)
if (resultIdFromSession) setResultId(resultIdFromSession)
else {
@@ -52,9 +54,6 @@ export const TypebotPage = ({ typebot, isIE, url }: TypebotPageProps) => {
if (error) setError(error)
}
- if (!typebot) {
- return
- }
if (error) {
return
}
diff --git a/apps/viewer/pages/[publicId].tsx b/apps/viewer/pages/[publicId].tsx
index 24a5ff3b8..9991ade9c 100644
--- a/apps/viewer/pages/[publicId].tsx
+++ b/apps/viewer/pages/[publicId].tsx
@@ -1,3 +1,4 @@
+import { NotFoundPage } from 'layouts/NotFoundPage'
import { PublicTypebot } from 'models'
import { GetServerSideProps, GetServerSidePropsContext } from 'next'
import { TypebotPage, TypebotPageProps } from '../layouts/TypebotPage'
@@ -12,7 +13,6 @@ export const getServerSideProps: GetServerSideProps = async (
try {
if (!context.req.headers.host) return { props: {} }
typebot = await getTypebotFromPublicId(context.query.publicId?.toString())
- if (!typebot) return { props: {} }
return {
props: {
typebot,
@@ -41,5 +41,7 @@ const getTypebotFromPublicId = async (
return (typebot as unknown as PublicTypebot | undefined) ?? undefined
}
-const App = (props: TypebotPageProps) =>
+const App = ({ typebot, ...props }: TypebotPageProps) =>
+ typebot ? :
+
export default App
diff --git a/apps/viewer/pages/index.tsx b/apps/viewer/pages/index.tsx
index f643b1e3d..02f1d68fd 100644
--- a/apps/viewer/pages/index.tsx
+++ b/apps/viewer/pages/index.tsx
@@ -1,3 +1,4 @@
+import { NotFoundPage } from 'layouts/NotFoundPage'
import { PublicTypebot } from 'models'
import { GetServerSideProps, GetServerSidePropsContext } from 'next'
import { TypebotPage, TypebotPageProps } from '../layouts/TypebotPage'
@@ -12,7 +13,6 @@ export const getServerSideProps: GetServerSideProps = async (
try {
if (!context.req.headers.host) return { props: {} }
typebot = await getTypebotFromUrl(context.req.headers.host)
- if (!typebot) return { props: {} }
return {
props: {
typebot,
@@ -42,5 +42,6 @@ const getTypebotFromUrl = async (
return (typebot as unknown as PublicTypebot | undefined) ?? undefined
}
-const App = (props: TypebotPageProps) =>
+const App = ({ typebot, ...props }: TypebotPageProps) =>
+ typebot ? :
export default App
diff --git a/packages/bot-engine/src/components/ChatBlock/ChatBlock.tsx b/packages/bot-engine/src/components/ChatBlock/ChatBlock.tsx
index b774c382f..ee02de073 100644
--- a/packages/bot-engine/src/components/ChatBlock/ChatBlock.tsx
+++ b/packages/bot-engine/src/components/ChatBlock/ChatBlock.tsx
@@ -4,7 +4,7 @@ import { TransitionGroup, CSSTransition } from 'react-transition-group'
import { ChatStep } from './ChatStep'
import { AvatarSideContainer } from './AvatarSideContainer'
import { HostAvatarsContext } from '../../contexts/HostAvatarsContext'
-import { Step } from 'models'
+import { PublicStep } from 'models'
import { useTypebot } from '../../contexts/TypebotContext'
import {
isBubbleStep,
@@ -14,26 +14,28 @@ import {
isLogicStep,
} from 'utils'
import { executeLogic } from 'services/logic'
-import { getSingleChoiceTargetId } from 'services/inputs'
import { executeIntegration } from 'services/integration'
type ChatBlockProps = {
- stepIds: string[]
- startStepId?: string
+ steps: PublicStep[]
+ startStepIndex: number
+ blockIndex: number
onBlockEnd: (edgeId?: string) => void
}
export const ChatBlock = ({
- stepIds,
- startStepId,
+ steps,
+ startStepIndex,
+ blockIndex,
onBlockEnd,
}: ChatBlockProps) => {
const { typebot, updateVariableValue } = useTypebot()
- const [displayedSteps, setDisplayedSteps] = useState([])
+ const [displayedSteps, setDisplayedSteps] = useState([])
+
+ const currentStepIndex = displayedSteps.length - 1
useEffect(() => {
- const nextStep =
- typebot.steps.byId[startStepId ?? stepIds[displayedSteps.length]]
+ const nextStep = steps[startStepIndex]
if (nextStep) setDisplayedSteps([...displayedSteps, nextStep])
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
@@ -60,6 +62,7 @@ export const ChatBlock = ({
typebot.typebotId,
currentStep,
typebot.variables,
+ { blockIndex, stepIndex: currentStepIndex },
updateVariableValue
)
nextEdgeId ? onBlockEnd(nextEdgeId) : displayNextStep()
@@ -85,18 +88,17 @@ export const ChatBlock = ({
}
const isSingleChoiceStep =
isChoiceInput(currentStep) && !currentStep.options.isMultipleChoice
- if (isSingleChoiceStep)
- return onBlockEnd(
- getSingleChoiceTargetId(
- currentStep,
- typebot.choiceItems,
- answerContent
- )
+ if (isSingleChoiceStep) {
+ onBlockEnd(
+ currentStep.items.find((i) => i.content === answerContent)
+ ?.outgoingEdgeId
)
- if (currentStep?.edgeId || displayedSteps.length === stepIds.length)
- return onBlockEnd(currentStep.edgeId)
+ }
+
+ if (currentStep?.outgoingEdgeId || displayedSteps.length === steps.length)
+ return onBlockEnd(currentStep.outgoingEdgeId)
}
- const nextStep = typebot.steps.byId[stepIds[displayedSteps.length]]
+ const nextStep = steps[displayedSteps.length]
if (nextStep) setDisplayedSteps([...displayedSteps, nextStep])
}
diff --git a/packages/bot-engine/src/components/ChatBlock/ChatStep/ChatStep.tsx b/packages/bot-engine/src/components/ChatBlock/ChatStep/ChatStep.tsx
index a018e4bd0..cf20a1e3c 100644
--- a/packages/bot-engine/src/components/ChatBlock/ChatStep/ChatStep.tsx
+++ b/packages/bot-engine/src/components/ChatBlock/ChatStep/ChatStep.tsx
@@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react'
import { useAnswers } from '../../../contexts/AnswersContext'
import { useHostAvatars } from '../../../contexts/HostAvatarsContext'
-import { InputStep, InputStepType, Step } from 'models'
+import { InputStep, InputStepType, PublicStep, Step } from 'models'
import { GuestBubble } from './bubbles/GuestBubble'
import { TextForm } from './inputs/TextForm'
import { isBubbleStep, isInputStep } from 'utils'
@@ -13,7 +13,7 @@ export const ChatStep = ({
step,
onTransitionEnd,
}: {
- step: Step
+ step: PublicStep
onTransitionEnd: (answerContent?: string) => void
}) => {
const { addAnswer } = useAnswers()
@@ -63,6 +63,6 @@ const InputChatStep = ({
case InputStepType.DATE:
return
case InputStepType.CHOICE:
- return
+ return
}
}
diff --git a/packages/bot-engine/src/components/ChatBlock/ChatStep/bubbles/VideoBubble.tsx b/packages/bot-engine/src/components/ChatBlock/ChatStep/bubbles/VideoBubble.tsx
index fef80fe04..63a8727fa 100644
--- a/packages/bot-engine/src/components/ChatBlock/ChatStep/bubbles/VideoBubble.tsx
+++ b/packages/bot-engine/src/components/ChatBlock/ChatStep/bubbles/VideoBubble.tsx
@@ -2,7 +2,6 @@ import React, { useEffect, useMemo, useRef, useState } from 'react'
import { useHostAvatars } from 'contexts/HostAvatarsContext'
import { useTypebot } from 'contexts/TypebotContext'
import {
- Table,
Variable,
VideoBubbleContent,
VideoBubbleContentType,
@@ -83,7 +82,7 @@ const VideoContent = ({
}: {
content?: VideoBubbleContent
isTyping: boolean
- variables: Table
+ variables: Variable[]
}) => {
const url = useMemo(
() => parseVariables({ text: content?.url, variables: variables }),
diff --git a/packages/bot-engine/src/components/ChatBlock/ChatStep/inputs/ChoiceForm.tsx b/packages/bot-engine/src/components/ChatBlock/ChatStep/inputs/ChoiceForm.tsx
index 8959d48f4..438f15eb5 100644
--- a/packages/bot-engine/src/components/ChatBlock/ChatStep/inputs/ChoiceForm.tsx
+++ b/packages/bot-engine/src/components/ChatBlock/ChatStep/inputs/ChoiceForm.tsx
@@ -1,65 +1,61 @@
-import { ChoiceInputOptions } from 'models'
-import React, { useMemo, useState } from 'react'
-import { filterTable } from 'utils'
-import { useTypebot } from '../../../../contexts/TypebotContext'
+import { ChoiceInputStep } from 'models'
+import React, { useState } from 'react'
import { SendButton } from './SendButton'
type ChoiceFormProps = {
- options?: ChoiceInputOptions
+ step: ChoiceInputStep
onSubmit: (value: string) => void
}
-export const ChoiceForm = ({ options, onSubmit }: ChoiceFormProps) => {
- const { typebot } = useTypebot()
- const items = useMemo(
- () => filterTable(options?.itemIds ?? [], typebot.choiceItems),
- // eslint-disable-next-line react-hooks/exhaustive-deps
- []
- )
- const [selectedIds, setSelectedIds] = useState([])
+export const ChoiceForm = ({ step, onSubmit }: ChoiceFormProps) => {
+ const [selectedIndices, setSelectedIndices] = useState([])
- const handleClick = (itemId: string) => (e: React.MouseEvent) => {
+ const handleClick = (itemIndex: number) => (e: React.MouseEvent) => {
e.preventDefault()
- if (options?.isMultipleChoice) toggleSelectedItemId(itemId)
- else onSubmit(items.byId[itemId].content ?? '')
+ if (step.options?.isMultipleChoice) toggleSelectedItemIndex(itemIndex)
+ else onSubmit(step.items[itemIndex].content ?? '')
}
- const toggleSelectedItemId = (itemId: string) => {
- const existingIndex = selectedIds.indexOf(itemId)
+ const toggleSelectedItemIndex = (itemIndex: number) => {
+ const existingIndex = selectedIndices.indexOf(itemIndex)
if (existingIndex !== -1) {
- selectedIds.splice(existingIndex, 1)
- setSelectedIds([...selectedIds])
+ selectedIndices.splice(existingIndex, 1)
+ setSelectedIndices([...selectedIndices])
} else {
- setSelectedIds([...selectedIds, itemId])
+ setSelectedIndices([...selectedIndices, itemIndex])
}
}
const handleSubmit = () =>
- onSubmit(selectedIds.map((itemId) => items.byId[itemId].content).join(', '))
+ onSubmit(
+ selectedIndices
+ .map((itemIndex) => step.items[itemIndex].content)
+ .join(', ')
+ )
return (
diff --git a/packages/bot-engine/src/components/ConversationContainer.tsx b/packages/bot-engine/src/components/ConversationContainer.tsx
index 4f58e5a0a..823c6a1c3 100644
--- a/packages/bot-engine/src/components/ConversationContainer.tsx
+++ b/packages/bot-engine/src/components/ConversationContainer.tsx
@@ -5,11 +5,12 @@ import { useFrame } from 'react-frame-component'
import { setCssVariablesValue } from '../services/theme'
import { useAnswers } from '../contexts/AnswersContext'
import { deepEqual } from 'fast-equals'
-import { Answer, Block, PublicTypebot } from 'models'
+import { Answer, Edge, PublicBlock, PublicTypebot } from 'models'
+import { byId } from 'utils'
type Props = {
typebot: PublicTypebot
- onNewBlockVisible: (edgeId: string) => void
+ onNewBlockVisible: (edge: Edge) => void
onNewAnswer: (answer: Answer) => void
onCompleted: () => void
}
@@ -21,30 +22,29 @@ export const ConversationContainer = ({
}: Props) => {
const { document: frameDocument } = useFrame()
const [displayedBlocks, setDisplayedBlocks] = useState<
- { block: Block; startStepId?: string }[]
+ { block: PublicBlock; startStepIndex: number }[]
>([])
const [localAnswer, setLocalAnswer] = useState()
const { answers } = useAnswers()
const bottomAnchor = useRef(null)
const displayNextBlock = (edgeId?: string) => {
- const edge = typebot.edges.byId[edgeId ?? '']
- if (!edge) return onCompleted()
- const nextBlock = {
- block: typebot.blocks.byId[edge.to.blockId],
- startStepId: edge.to.stepId,
- }
+ const nextEdge = typebot.edges.find(byId(edgeId))
+ if (!nextEdge) return onCompleted()
+ const nextBlock = typebot.blocks.find(byId(nextEdge.to.blockId))
if (!nextBlock) return onCompleted()
- onNewBlockVisible(edge.id)
- setDisplayedBlocks([...displayedBlocks, nextBlock])
+ const startStepIndex = nextEdge.to.stepId
+ ? nextBlock.steps.findIndex(byId(nextEdge.to.stepId))
+ : 0
+ onNewBlockVisible(nextEdge)
+ setDisplayedBlocks([
+ ...displayedBlocks,
+ { block: nextBlock, startStepIndex },
+ ])
}
useEffect(() => {
- const blocks = typebot.blocks
- const firstEdgeId =
- typebot.steps.byId[blocks.byId[blocks.allIds[0]].stepIds[0]].edgeId
- if (!firstEdgeId) return
- displayNextBlock(firstEdgeId)
+ displayNextBlock(typebot.blocks[0].steps[0].outgoingEdgeId)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
@@ -68,8 +68,9 @@ export const ConversationContainer = ({
{displayedBlocks.map((displayedBlock, idx) => (
))}
diff --git a/packages/bot-engine/src/components/TypebotViewer.tsx b/packages/bot-engine/src/components/TypebotViewer.tsx
index 9a4535a21..afffc1405 100644
--- a/packages/bot-engine/src/components/TypebotViewer.tsx
+++ b/packages/bot-engine/src/components/TypebotViewer.tsx
@@ -10,11 +10,11 @@ import phoneNumberInputStyle from 'react-phone-number-input/style.css'
import phoneSyle from '../assets/phone.css'
import { ConversationContainer } from './ConversationContainer'
import { AnswersContext } from '../contexts/AnswersContext'
-import { Answer, BackgroundType, PublicTypebot } from 'models'
+import { Answer, BackgroundType, Edge, PublicTypebot } from 'models'
export type TypebotViewerProps = {
typebot: PublicTypebot
- onNewBlockVisible?: (edgeId: string) => void
+ onNewBlockVisible?: (edge: Edge) => void
onNewAnswer?: (answer: Answer) => void
onCompleted?: () => void
}
@@ -31,8 +31,8 @@ export const TypebotViewer = ({
: 'transparent',
[typebot?.theme?.general?.background]
)
- const handleNewBlockVisible = (blockId: string) => {
- if (onNewBlockVisible) onNewBlockVisible(blockId)
+ const handleNewBlockVisible = (edge: Edge) => {
+ if (onNewBlockVisible) onNewBlockVisible(edge)
}
const handleNewAnswer = (answer: Answer) => {
if (onNewAnswer) onNewAnswer(answer)
diff --git a/packages/bot-engine/src/contexts/TypebotContext.tsx b/packages/bot-engine/src/contexts/TypebotContext.tsx
index ee4d4e03e..e9961feb6 100644
--- a/packages/bot-engine/src/contexts/TypebotContext.tsx
+++ b/packages/bot-engine/src/contexts/TypebotContext.tsx
@@ -20,13 +20,9 @@ export const TypebotContext = ({
const updateVariableValue = (variableId: string, value: string) => {
setLocalTypebot((typebot) => ({
...typebot,
- variables: {
- ...typebot.variables,
- byId: {
- ...typebot.variables.byId,
- [variableId]: { ...typebot.variables.byId[variableId], value },
- },
- },
+ variables: typebot.variables.map((v) =>
+ v.id === variableId ? { ...v, value } : v
+ ),
}))
}
return (
diff --git a/packages/bot-engine/src/services/inputs.ts b/packages/bot-engine/src/services/inputs.ts
deleted file mode 100644
index 828857d88..000000000
--- a/packages/bot-engine/src/services/inputs.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { ChoiceInputStep, ChoiceItem, Table } from 'models'
-
-export const getSingleChoiceTargetId = (
- currentStep: ChoiceInputStep,
- choiceItems: Table,
- answerContent?: string
-): string | undefined => {
- const itemId = currentStep.options.itemIds.find(
- (itemId) => choiceItems.byId[itemId].content === answerContent
- )
- if (!itemId) throw new Error('itemId should exist')
- return choiceItems.byId[itemId].edgeId ?? currentStep.edgeId
-}
diff --git a/packages/bot-engine/src/services/integration.ts b/packages/bot-engine/src/services/integration.ts
index 2413503a3..da1152f57 100644
--- a/packages/bot-engine/src/services/integration.ts
+++ b/packages/bot-engine/src/services/integration.ts
@@ -5,7 +5,6 @@ import {
GoogleSheetsAction,
GoogleSheetsInsertRowOptions,
Variable,
- Table,
GoogleSheetsUpdateRowOptions,
Cell,
GoogleSheetsGetOptions,
@@ -19,10 +18,12 @@ import { parseVariables, parseVariablesInObject } from './variable'
const safeEval = eval
+type Indices = { blockIndex: number; stepIndex: number }
export const executeIntegration = (
typebotId: string,
step: IntegrationStep,
- variables: Table,
+ variables: Variable[],
+ indices: Indices,
updateVariableValue: (variableId: string, value: string) => void
) => {
switch (step.type) {
@@ -31,13 +32,19 @@ export const executeIntegration = (
case IntegrationStepType.GOOGLE_ANALYTICS:
return executeGoogleAnalyticsIntegration(step, variables)
case IntegrationStepType.WEBHOOK:
- return executeWebhook(typebotId, step, variables, updateVariableValue)
+ return executeWebhook(
+ typebotId,
+ step,
+ variables,
+ indices,
+ updateVariableValue
+ )
}
}
export const executeGoogleAnalyticsIntegration = async (
step: GoogleAnalyticsStep,
- variables: Table
+ variables: Variable[]
) => {
if (!step.options?.trackingId) return
const { default: initGoogleAnalytics } = await import('../../lib/gtag')
@@ -47,10 +54,10 @@ export const executeGoogleAnalyticsIntegration = async (
const executeGoogleSheetIntegration = async (
step: GoogleSheetsStep,
- variables: Table,
+ variables: Variable[],
updateVariableValue: (variableId: string, value: string) => void
) => {
- if (!('action' in step.options)) return step.edgeId
+ if (!('action' in step.options)) return step.outgoingEdgeId
switch (step.options.action) {
case GoogleSheetsAction.INSERT_ROW:
await insertRowInGoogleSheets(step.options, variables)
@@ -62,12 +69,12 @@ const executeGoogleSheetIntegration = async (
await getRowFromGoogleSheets(step.options, variables, updateVariableValue)
break
}
- return step.edgeId
+ return step.outgoingEdgeId
}
const insertRowInGoogleSheets = async (
options: GoogleSheetsInsertRowOptions,
- variables: Table
+ variables: Variable[]
) => {
if (!options.cellsToInsert) return
return sendRequest({
@@ -82,7 +89,7 @@ const insertRowInGoogleSheets = async (
const updateRowInGoogleSheets = async (
options: GoogleSheetsUpdateRowOptions,
- variables: Table
+ variables: Variable[]
) => {
if (!options.cellsToUpsert || !options.referenceCell) return
return sendRequest({
@@ -104,7 +111,7 @@ const updateRowInGoogleSheets = async (
const getRowFromGoogleSheets = async (
options: GoogleSheetsGetOptions,
- variables: Table,
+ variables: Variable[],
updateVariableValue: (variableId: string, value: string) => void
) => {
if (!options.referenceCell || !options.cellsToExtract) return
@@ -118,9 +125,7 @@ const getRowFromGoogleSheets = async (
variables,
}),
},
- columns: options.cellsToExtract.allIds.map(
- (id) => options.cellsToExtract?.byId[id].column
- ),
+ columns: options.cellsToExtract.map((cell) => cell.column),
},
{ indices: false }
)
@@ -129,18 +134,15 @@ const getRowFromGoogleSheets = async (
method: 'GET',
})
if (!data) return
- options.cellsToExtract.allIds.forEach((cellId) => {
- const cell = options.cellsToExtract?.byId[cellId]
- if (!cell) return
+ options.cellsToExtract.forEach((cell) =>
updateVariableValue(cell.variableId ?? '', data[cell.column ?? ''])
- })
+ )
}
const parseCellValues = (
- cells: Table,
- variables: Table
+ cells: Cell[],
+ variables: Variable[]
): { [key: string]: string } =>
- cells.allIds.reduce((row, id) => {
- const cell = cells.byId[id]
+ cells.reduce((row, cell) => {
return !cell.column || !cell.value
? row
: {
@@ -152,20 +154,21 @@ const parseCellValues = (
const executeWebhook = async (
typebotId: string,
step: WebhookStep,
- variables: Table,
+ variables: Variable[],
+ indices: Indices,
updateVariableValue: (variableId: string, value: string) => void
) => {
- if (!step.options?.webhookId) return step.edgeId
+ if (!step.webhook) return step.outgoingEdgeId
+ const { blockIndex, stepIndex } = indices
const { data, error } = await sendRequest({
- url: `http://localhost:3000/api/typebots/${typebotId}/webhooks/${step.options?.webhookId}/execute`,
+ url: `http://localhost:3000/api/typebots/${typebotId}/blocks/${blockIndex}/steps/${stepIndex}/executeWebhook`,
method: 'POST',
body: {
variables,
},
})
console.error(error)
- step.options.responseVariableMapping?.allIds.forEach((varMappingId) => {
- const varMapping = step.options?.responseVariableMapping?.byId[varMappingId]
+ step.options.responseVariableMapping.forEach((varMapping) => {
if (!varMapping?.bodyPath || !varMapping.variableId) return
const value = safeEval(`(${JSON.stringify(data)}).${varMapping?.bodyPath}`)
updateVariableValue(varMapping.variableId, value)
diff --git a/packages/bot-engine/src/services/logic.ts b/packages/bot-engine/src/services/logic.ts
index 175deb30a..869ff3257 100644
--- a/packages/bot-engine/src/services/logic.ts
+++ b/packages/bot-engine/src/services/logic.ts
@@ -3,20 +3,21 @@ import {
LogicStepType,
LogicalOperator,
ConditionStep,
- Table,
Variable,
ComparisonOperators,
SetVariableStep,
RedirectStep,
+ Comparison,
} from 'models'
import { isDefined, isNotDefined } from 'utils'
import { sanitizeUrl } from './utils'
import { isMathFormula, evaluateExpression, parseVariables } from './variable'
type EdgeId = string
+
export const executeLogic = (
step: LogicStep,
- variables: Table,
+ variables: Variable[],
updateVariableValue: (variableId: string, expression: string) => void
): EdgeId | undefined => {
switch (step.type) {
@@ -31,40 +32,36 @@ export const executeLogic = (
const executeSetVariable = (
step: SetVariableStep,
- variables: Table,
+ variables: Variable[],
updateVariableValue: (variableId: string, expression: string) => void
): EdgeId | undefined => {
if (!step.options?.variableId || !step.options.expressionToEvaluate)
- return step.edgeId
+ return step.outgoingEdgeId
const expression = step.options.expressionToEvaluate
const evaluatedExpression = isMathFormula(expression)
? evaluateExpression(parseVariables({ text: expression, variables }))
: expression
updateVariableValue(step.options.variableId, evaluatedExpression)
- return step.edgeId
+ return step.outgoingEdgeId
}
const executeCondition = (
step: ConditionStep,
- variables: Table
+ variables: Variable[]
): EdgeId | undefined => {
+ const { content } = step.items[0]
const isConditionPassed =
- step.options?.logicalOperator === LogicalOperator.AND
- ? step.options?.comparisons.allIds.every(
- executeComparison(step, variables)
- )
- : step.options?.comparisons.allIds.some(
- executeComparison(step, variables)
- )
- return isConditionPassed ? step.trueEdgeId : step.falseEdgeId
+ content.logicalOperator === LogicalOperator.AND
+ ? content.comparisons.every(executeComparison(variables))
+ : content.comparisons.some(executeComparison(variables))
+ return isConditionPassed ? step.items[0].outgoingEdgeId : step.outgoingEdgeId
}
const executeComparison =
- (step: ConditionStep, variables: Table) =>
- (comparisonId: string) => {
- const comparison = step.options?.comparisons.byId[comparisonId]
+ (variables: Variable[]) => (comparison: Comparison) => {
if (!comparison?.variableId) return false
- const inputValue = variables.byId[comparison.variableId].value ?? ''
+ const inputValue =
+ variables.find((v) => v.id === comparison.variableId)?.value ?? ''
const { value } = comparison
if (isNotDefined(value)) return false
switch (comparison.comparisonOperator) {
@@ -91,12 +88,12 @@ const executeComparison =
const executeRedirect = (
step: RedirectStep,
- variables: Table
+ variables: Variable[]
): EdgeId | undefined => {
- if (!step.options?.url) return step.edgeId
+ if (!step.options?.url) return step.outgoingEdgeId
window.open(
sanitizeUrl(parseVariables({ text: step.options?.url, variables })),
step.options.isNewTab ? '_blank' : '_self'
)
- return step.edgeId
+ return step.outgoingEdgeId
}
diff --git a/packages/bot-engine/src/services/variable.ts b/packages/bot-engine/src/services/variable.ts
index b7f6e11eb..0f2b9a79e 100644
--- a/packages/bot-engine/src/services/variable.ts
+++ b/packages/bot-engine/src/services/variable.ts
@@ -1,4 +1,4 @@
-import { Table, Variable } from 'models'
+import { Variable } from 'models'
import { isDefined } from 'utils'
const safeEval = eval
@@ -11,16 +11,16 @@ export const parseVariables = ({
variables,
}: {
text?: string
- variables: Table
+ variables: Variable[]
}): string => {
if (!text || text === '') return ''
return text.replace(/\{\{(.*?)\}\}/g, (_, fullVariableString) => {
const matchedVarName = fullVariableString.replace(/{{|}}/g, '')
- const matchedVariableId = variables.allIds.find((variableId) => {
- const variable = variables.byId[variableId]
- return matchedVarName === variable.name && isDefined(variable.value)
- })
- return variables.byId[matchedVariableId ?? '']?.value ?? ''
+ return (
+ variables.find((v) => {
+ return matchedVarName === v.name && isDefined(v.value)
+ })?.value ?? ''
+ )
})
}
@@ -50,7 +50,7 @@ const countDecimals = (value: number) => {
export const parseVariablesInObject = (
object: { [key: string]: string | number },
- variables: Table
+ variables: Variable[]
) =>
Object.keys(object).reduce((newObj, key) => {
const currentValue = object[key]
diff --git a/packages/bot-engine/tsconfig.json b/packages/bot-engine/tsconfig.json
index 2292756c5..a8a746894 100644
--- a/packages/bot-engine/tsconfig.json
+++ b/packages/bot-engine/tsconfig.json
@@ -14,6 +14,7 @@
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"emitDeclarationOnly": true,
- "baseUrl": "./src"
+ "baseUrl": "./src",
+ "downlevelIteration": true
}
}
diff --git a/packages/db/prisma/schema.prisma b/packages/db/prisma/schema.prisma
index 166e285f9..bc589d385 100644
--- a/packages/db/prisma/schema.prisma
+++ b/packages/db/prisma/schema.prisma
@@ -106,30 +106,25 @@ model Typebot {
results Result[]
folderId String?
folder DashboardFolder? @relation(fields: [folderId], references: [id])
- blocks Json
- steps Json
- choiceItems Json
- variables Json
- webhooks Json
- edges Json
+ blocks Json[]
+ variables Json[]
+ edges Json[]
theme Json
settings Json
publicId String? @unique
}
model PublicTypebot {
- id String @id @default(cuid())
- typebotId String @unique
- typebot Typebot @relation(fields: [typebotId], references: [id], onDelete: Cascade)
- name String
- blocks Json
- steps Json
- choiceItems Json
- variables Json
- edges Json
- theme Json
- settings Json
- publicId String? @unique
+ id String @id @default(cuid())
+ typebotId String @unique
+ typebot Typebot @relation(fields: [typebotId], references: [id], onDelete: Cascade)
+ name String
+ blocks Json[]
+ variables Json[]
+ edges Json[]
+ theme Json
+ settings Json
+ publicId String? @unique
}
model Result {
diff --git a/packages/models/src/publicTypebot.ts b/packages/models/src/publicTypebot.ts
index 41ab43eb0..913892d72 100644
--- a/packages/models/src/publicTypebot.ts
+++ b/packages/models/src/publicTypebot.ts
@@ -1,23 +1,16 @@
+import { Block, Edge, Settings, Step, Theme, Variable } from './typebot'
import { PublicTypebot as PublicTypebotFromPrisma } from 'db'
-import { Block, ChoiceItem, Edge, Settings, Step, Theme } from './typebot'
-import { Variable } from './typebot/variable'
-import { Table } from './utils'
export type PublicTypebot = Omit<
PublicTypebotFromPrisma,
- | 'blocks'
- | 'startBlock'
- | 'theme'
- | 'settings'
- | 'steps'
- | 'choiceItems'
- | 'variables'
+ 'blocks' | 'theme' | 'settings' | 'variables' | 'edges'
> & {
- blocks: Table
- steps: Table
- choiceItems: Table |