@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "clf6ov7hg00001ao6q02sb8re",
|
"id": "clf6ov7hg00001ao6q02sb8re",
|
||||||
"version": "3",
|
"version": "4",
|
||||||
"createdAt": "2023-03-13T10:35:44.933Z",
|
"createdAt": "2023-03-13T10:35:44.933Z",
|
||||||
"updatedAt": "2023-03-13T14:53:00.817Z",
|
"updatedAt": "2023-03-13T14:53:00.817Z",
|
||||||
"icon": "🤖",
|
"icon": "🤖",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "qcueq3ttys1ddagic7jsimp4",
|
"id": "qcueq3ttys1ddagic7jsimp4",
|
||||||
"version": "3",
|
"version": "4",
|
||||||
"createdAt": "2023-03-30T15:45:12.464Z",
|
"createdAt": "2023-03-30T15:45:12.464Z",
|
||||||
"updatedAt": "2023-03-30T15:45:12.464Z",
|
"updatedAt": "2023-03-30T15:45:12.464Z",
|
||||||
"icon": "🎭",
|
"icon": "🎭",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "cl16la7p900990b1a72qjqbb3",
|
"id": "cl16la7p900990b1a72qjqbb3",
|
||||||
|
"version": "4",
|
||||||
"createdAt": "2022-03-25T15:39:33.885Z",
|
"createdAt": "2022-03-25T15:39:33.885Z",
|
||||||
"updatedAt": "2022-03-25T15:42:12.544Z",
|
"updatedAt": "2022-03-25T15:42:12.544Z",
|
||||||
"name": "Customer Support",
|
"name": "Customer Support",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "cl3u43chu40824z1acel3iw1c",
|
"id": "cl3u43chu40824z1acel3iw1c",
|
||||||
|
"version": "4",
|
||||||
"createdAt": "2022-05-31T12:04:12.930Z",
|
"createdAt": "2022-05-31T12:04:12.930Z",
|
||||||
"updatedAt": "2022-05-31T12:31:12.867Z",
|
"updatedAt": "2022-05-31T12:31:12.867Z",
|
||||||
"icon": "🖼️",
|
"icon": "🖼️",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "clh9fzu4b00031aotzr1ik4ba",
|
"id": "clh9fzu4b00031aotzr1ik4ba",
|
||||||
"version": "3",
|
"version": "4",
|
||||||
"createdAt": "2023-05-04T18:10:07.548Z",
|
"createdAt": "2023-05-04T18:10:07.548Z",
|
||||||
"updatedAt": "2023-05-04T19:13:45.356Z",
|
"updatedAt": "2023-05-04T19:13:45.356Z",
|
||||||
"icon": "🐶",
|
"icon": "🐶",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "cl96ns7zc000dky099ku4bmav",
|
"id": "cl96ns7zc000dky099ku4bmav",
|
||||||
|
"version": "4",
|
||||||
"createdAt": "2022-10-13T06:07:11.976Z",
|
"createdAt": "2022-10-13T06:07:11.976Z",
|
||||||
"updatedAt": "2022-10-13T06:27:31.951Z",
|
"updatedAt": "2022-10-13T06:27:31.951Z",
|
||||||
"icon": "💬",
|
"icon": "💬",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "pjkxzxkujkbk2oml3d35w6zz",
|
"id": "pjkxzxkujkbk2oml3d35w6zz",
|
||||||
"version": "3",
|
"version": "4",
|
||||||
"createdAt": "2023-04-20T12:29:18.633Z",
|
"createdAt": "2023-04-20T12:29:18.633Z",
|
||||||
"updatedAt": "2023-04-20T12:50:12.385Z",
|
"updatedAt": "2023-04-20T12:50:12.385Z",
|
||||||
"icon": "🦾",
|
"icon": "🦾",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "qgMiLSr4W1ftXocFncin1G",
|
"id": "qgMiLSr4W1ftXocFncin1G",
|
||||||
|
"version": "4",
|
||||||
"createdAt": "2022-02-05T06:21:16.522Z",
|
"createdAt": "2022-02-05T06:21:16.522Z",
|
||||||
"updatedAt": "2022-02-05T06:21:16.522Z",
|
"updatedAt": "2022-02-05T06:21:16.522Z",
|
||||||
"name": "Lead Generation",
|
"name": "Lead Generation",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "clg69gafk00011ar14aryt8ej",
|
"id": "clg69gafk00011ar14aryt8ej",
|
||||||
"version": "3",
|
"version": "4",
|
||||||
"createdAt": "2023-04-07T08:03:57.008Z",
|
"createdAt": "2023-04-07T08:03:57.008Z",
|
||||||
"updatedAt": "2023-04-07T08:22:10.285Z",
|
"updatedAt": "2023-04-07T08:22:10.285Z",
|
||||||
"icon": "🧲",
|
"icon": "🧲",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "cl1seoz582103xk1at12y4ucb",
|
"id": "cl1seoz582103xk1at12y4ucb",
|
||||||
|
"version": "4",
|
||||||
"createdAt": "2022-04-09T22:06:01.196Z",
|
"createdAt": "2022-04-09T22:06:01.196Z",
|
||||||
"updatedAt": "2022-04-09T22:35:22.449Z",
|
"updatedAt": "2022-04-09T22:35:22.449Z",
|
||||||
"icon": "🏆",
|
"icon": "🏆",
|
||||||
|
|||||||
@@ -1,41 +1,41 @@
|
|||||||
{
|
{
|
||||||
"id": "clf17krhw00011am023muokc1",
|
"id": "d8z3y5ats5r0lyptw938re79",
|
||||||
"version": "3",
|
"version": "4",
|
||||||
"createdAt": "2023-03-09T14:32:53.301Z",
|
"createdAt": "2023-08-06T05:56:35.727Z",
|
||||||
"updatedAt": "2023-03-09T16:26:36.916Z",
|
"updatedAt": "2023-08-06T06:39:16.019Z",
|
||||||
"icon": "🍿",
|
"icon": "🍿",
|
||||||
"name": "Movie recommendation",
|
"name": "Movie recommendation",
|
||||||
"folderId": null,
|
"folderId": null,
|
||||||
"groups": [
|
"groups": [
|
||||||
{
|
{
|
||||||
"id": "kto4a8zwoqvagp14sjol0mqq",
|
"id": "u6lpjibfjhyoqij5wjf9kvnl",
|
||||||
"title": "Start",
|
"title": "Start",
|
||||||
"blocks": [
|
"blocks": [
|
||||||
{
|
{
|
||||||
"id": "dn2vorjxq275ulqwd97sgfjp",
|
"id": "rha69fygov33vym1hf6z837p",
|
||||||
"type": "start",
|
"type": "start",
|
||||||
"label": "Start",
|
"label": "Start",
|
||||||
"groupId": "kto4a8zwoqvagp14sjol0mqq",
|
"groupId": "u6lpjibfjhyoqij5wjf9kvnl",
|
||||||
"outgoingEdgeId": "ozfvttdxg70dy931m762ssc0"
|
"outgoingEdgeId": "wfec8f4e1jtden2wqna6nrso"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"graphCoordinates": { "x": 0, "y": 0 }
|
"graphCoordinates": { "x": 0, "y": 0 }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "vpsi7kfd4hiu38fd0txt3ndn",
|
"id": "mjnkukpkpvf4ha2g4n5m804v",
|
||||||
"title": "Menu",
|
"title": "Menu",
|
||||||
"blocks": [
|
"blocks": [
|
||||||
{
|
{
|
||||||
"id": "tmm2xkt5wqt5zmxzkyg2kx1q",
|
"id": "kjlf184vxf0uorniwje28iqb",
|
||||||
"type": "Set variable",
|
"type": "Set variable",
|
||||||
"groupId": "vpsi7kfd4hiu38fd0txt3ndn",
|
"groupId": "mjnkukpkpvf4ha2g4n5m804v",
|
||||||
"options": {
|
"options": {
|
||||||
"variableId": "vh5bxx07kl3016wr1undh2yb3",
|
"variableId": "vh5bxx07kl3016wr1undh2yb3",
|
||||||
"expressionToEvaluate": "2f584d1ffe2b7fb082dd4e05038e9bd7"
|
"expressionToEvaluate": "2f584d1ffe2b7fb082dd4e05038e9bd7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "pd22jxxptmw66xhwddj8toos",
|
"id": "f5rr5wi9zldun13tw79u9z2n",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"content": {
|
"content": {
|
||||||
"richText": [
|
"richText": [
|
||||||
@@ -47,18 +47,18 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"groupId": "vpsi7kfd4hiu38fd0txt3ndn"
|
"groupId": "mjnkukpkpvf4ha2g4n5m804v"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "vwfnjnfnqnlvgraai2k4kl9e",
|
"id": "c7swi84rmdvrul0wz5kxtplm",
|
||||||
"type": "image",
|
"type": "image",
|
||||||
"content": {
|
"content": {
|
||||||
"url": "https://media3.giphy.com/media/BElb9DVpHezcZufOhl/giphy-downsized.gif?cid=fe3852a3uwhsp1sc3j6avr625v5e94h1v8o3wfb1ii3xwswk&rid=giphy-downsized.gif&ct=g"
|
"url": "https://media3.giphy.com/media/BElb9DVpHezcZufOhl/giphy-downsized.gif?cid=fe3852a3uwhsp1sc3j6avr625v5e94h1v8o3wfb1ii3xwswk&rid=giphy-downsized.gif&ct=g"
|
||||||
},
|
},
|
||||||
"groupId": "vpsi7kfd4hiu38fd0txt3ndn"
|
"groupId": "mjnkukpkpvf4ha2g4n5m804v"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "gr8qlv926y817febq85zl0y0",
|
"id": "nlihfc4ptxnxoktqblh6mcql",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"content": {
|
"content": {
|
||||||
"richText": [
|
"richText": [
|
||||||
@@ -68,28 +68,28 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"groupId": "vpsi7kfd4hiu38fd0txt3ndn"
|
"groupId": "mjnkukpkpvf4ha2g4n5m804v"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "fm1894ok09bdyjpqhqth1p7q",
|
"id": "vr73urm54d9mq2oqg7ey1xh8",
|
||||||
"type": "image",
|
"type": "image",
|
||||||
"content": {
|
"content": {
|
||||||
"url": "https://www.themoviedb.org/assets/2/v4/logos/v2/blue_square_1-5bdc75aaebeb75dc7ae79426ddd9be3b2be1e342510f8202baf6bffa71d7f5c4.svg"
|
"url": "https://www.themoviedb.org/assets/2/v4/logos/v2/blue_square_1-5bdc75aaebeb75dc7ae79426ddd9be3b2be1e342510f8202baf6bffa71d7f5c4.svg"
|
||||||
},
|
},
|
||||||
"groupId": "vpsi7kfd4hiu38fd0txt3ndn"
|
"groupId": "mjnkukpkpvf4ha2g4n5m804v"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "qllnzuo1zxr5ef8bq9kjdjel",
|
"id": "g5yyuh9g75x7xa7fgqhhi1zz",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"content": {
|
"content": {
|
||||||
"richText": [
|
"richText": [
|
||||||
{ "type": "p", "children": [{ "text": "How can I we help?" }] }
|
{ "type": "p", "children": [{ "text": "How can I we help?" }] }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"groupId": "vpsi7kfd4hiu38fd0txt3ndn"
|
"groupId": "mjnkukpkpvf4ha2g4n5m804v"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "sodsq9mcigwvogmwx0t4jvil",
|
"id": "tzf45bvd8iquoxz7qgta8v94",
|
||||||
"type": "choice input",
|
"type": "choice input",
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
@@ -97,39 +97,52 @@
|
|||||||
"type": 0,
|
"type": 0,
|
||||||
"blockId": "sodsq9mcigwvogmwx0t4jvil",
|
"blockId": "sodsq9mcigwvogmwx0t4jvil",
|
||||||
"content": "Select a genre 💅",
|
"content": "Select a genre 💅",
|
||||||
"outgoingEdgeId": "o8n3df42rx0og3vlkzhskp7r"
|
"outgoingEdgeId": "t8qyjpigrz7cdl8gxl1wxlwj"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "i8ls2f8inq2ovuijj6l7rbcq",
|
"id": "i8ls2f8inq2ovuijj6l7rbcq",
|
||||||
"type": 0,
|
"type": 0,
|
||||||
"blockId": "sodsq9mcigwvogmwx0t4jvil",
|
"blockId": "sodsq9mcigwvogmwx0t4jvil",
|
||||||
"content": "See what's trending 🔝",
|
"content": "See what's trending 🔝",
|
||||||
"outgoingEdgeId": "cfwctrcqoucw6djnn0j2zsv0"
|
"outgoingEdgeId": "tjn2ljosqyd4aj9dk8mnifsu"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"groupId": "vpsi7kfd4hiu38fd0txt3ndn",
|
"groupId": "mjnkukpkpvf4ha2g4n5m804v",
|
||||||
"options": { "buttonLabel": "Send", "isMultipleChoice": false }
|
"options": { "buttonLabel": "Send", "isMultipleChoice": false }
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"graphCoordinates": { "x": 255.24609375, "y": 173.00390625 }
|
"graphCoordinates": { "x": 255.25, "y": 172.89 }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "xjwiuplgl79ezx460xfuplgr",
|
"id": "kq1g5z6pz4buot7sawqdrr3s",
|
||||||
"title": "Genre",
|
"title": "Genre",
|
||||||
"blocks": [
|
"blocks": [
|
||||||
{
|
{
|
||||||
"id": "vqrsszjis5qtbalo8d0fwb1j",
|
"id": "ecwz96cghzp4ji3lyx7taxt1",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"content": {
|
"content": {
|
||||||
"richText": [{ "type": "p", "children": [{ "text": "Sure!" }] }]
|
"richText": [{ "type": "p", "children": [{ "text": "Sure!" }] }]
|
||||||
},
|
},
|
||||||
"groupId": "xjwiuplgl79ezx460xfuplgr"
|
"groupId": "kq1g5z6pz4buot7sawqdrr3s"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "lmoqmlovcsg2l0uzkm9sohor",
|
"id": "gd4lt2pcljer6zaf7v9hkr1k",
|
||||||
"type": "Webhook",
|
"type": "Webhook",
|
||||||
"groupId": "xjwiuplgl79ezx460xfuplgr",
|
"groupId": "kq1g5z6pz4buot7sawqdrr3s",
|
||||||
"options": {
|
"options": {
|
||||||
|
"webhook": {
|
||||||
|
"id": "t4pht3ndfc8tu9geovi7czqm",
|
||||||
|
"url": "https://api.themoviedb.org/3/genre/movie/list",
|
||||||
|
"method": "GET",
|
||||||
|
"headers": [],
|
||||||
|
"queryParams": [
|
||||||
|
{
|
||||||
|
"id": "gq6m7x2k20qzrj752qi2zpmu",
|
||||||
|
"key": "api_key",
|
||||||
|
"value": "{{API Key}}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"isCustomBody": false,
|
"isCustomBody": false,
|
||||||
"isAdvancedConfig": true,
|
"isAdvancedConfig": true,
|
||||||
"variablesForTest": [
|
"variablesForTest": [
|
||||||
@@ -151,11 +164,10 @@
|
|||||||
"variableId": "vwc00rydyp035vtb0nlaqyzwr"
|
"variableId": "vwc00rydyp035vtb0nlaqyzwr"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
}
|
||||||
"webhookId": "kbd4kqs5lk58nyeggctha9hc"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "v2516de17eigf6mbccy2t6dr",
|
"id": "qeyvu7uq5tkvo7uo8iaj87z5",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"content": {
|
"content": {
|
||||||
"richText": [
|
"richText": [
|
||||||
@@ -165,10 +177,10 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"groupId": "xjwiuplgl79ezx460xfuplgr"
|
"groupId": "kq1g5z6pz4buot7sawqdrr3s"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "eqm19tzeh7kullwld8auoqy4",
|
"id": "nwuk2clo78hmnh4d0g31u9xg",
|
||||||
"type": "choice input",
|
"type": "choice input",
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
@@ -178,7 +190,7 @@
|
|||||||
"content": "Click to edit"
|
"content": "Click to edit"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"groupId": "xjwiuplgl79ezx460xfuplgr",
|
"groupId": "kq1g5z6pz4buot7sawqdrr3s",
|
||||||
"options": {
|
"options": {
|
||||||
"variableId": "vkmbb3rb2hcfd2io1fhf7rz5x",
|
"variableId": "vkmbb3rb2hcfd2io1fhf7rz5x",
|
||||||
"buttonLabel": "Send",
|
"buttonLabel": "Send",
|
||||||
@@ -187,36 +199,55 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "s27x4vixvakw62rwlsx61vw6",
|
"id": "j7pm34um4piuyabwlobjc356",
|
||||||
"type": "Set variable",
|
"type": "Set variable",
|
||||||
"groupId": "xjwiuplgl79ezx460xfuplgr",
|
"groupId": "kq1g5z6pz4buot7sawqdrr3s",
|
||||||
"options": {
|
"options": {
|
||||||
|
"type": "Map item with same index",
|
||||||
"isCode": true,
|
"isCode": true,
|
||||||
"variableId": "vwewa4yugqch2sswdpneszk3i",
|
"variableId": "vwewa4yugqch2sswdpneszk3i",
|
||||||
|
"mapListItemParams": {
|
||||||
|
"baseItemVariableId": "vkmbb3rb2hcfd2io1fhf7rz5x",
|
||||||
|
"baseListVariableId": "vx0bbqzug4vk3zpc31ly8k7al",
|
||||||
|
"targetListVariableId": "vwc00rydyp035vtb0nlaqyzwr"
|
||||||
|
},
|
||||||
"expressionToEvaluate": "{{Genre IDs}}.at({{Genres}}.indexOf({{Selected genre}}))"
|
"expressionToEvaluate": "{{Genre IDs}}.at({{Genres}}.indexOf({{Selected genre}}))"
|
||||||
},
|
},
|
||||||
"outgoingEdgeId": "vcuv47fbcqrtuelfy4i6ctqz"
|
"outgoingEdgeId": "tfuuwjnpn7mftd5s65mbhytd"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"graphCoordinates": { "x": 630.84765625, "y": 333.68359375 }
|
"graphCoordinates": { "x": 630.85, "y": 333.68 }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "dewz832l9kse7xx1vhkihbk6",
|
"id": "d6v9lh83c7zuwrhf2mmo6nxo",
|
||||||
"title": "Trending",
|
"title": "Trending",
|
||||||
"blocks": [
|
"blocks": [
|
||||||
{
|
{
|
||||||
"id": "yqci070mkxfjjdok5yztj1nx",
|
"id": "edokvbp15ubqeuydw9n7wf4w",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"content": {
|
"content": {
|
||||||
"richText": [{ "type": "p", "children": [{ "text": "Sure!" }] }]
|
"richText": [{ "type": "p", "children": [{ "text": "Sure!" }] }]
|
||||||
},
|
},
|
||||||
"groupId": "dewz832l9kse7xx1vhkihbk6"
|
"groupId": "d6v9lh83c7zuwrhf2mmo6nxo"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "xkd9bmjx1xf6uglewaeds8d8",
|
"id": "pwxb57b8nc2bp764vcdstois",
|
||||||
"type": "Webhook",
|
"type": "Webhook",
|
||||||
"groupId": "dewz832l9kse7xx1vhkihbk6",
|
"groupId": "d6v9lh83c7zuwrhf2mmo6nxo",
|
||||||
"options": {
|
"options": {
|
||||||
|
"webhook": {
|
||||||
|
"id": "a5oaijpqxo5a0mqrnjqg3tyt",
|
||||||
|
"url": "https://api.themoviedb.org/3/trending/movie/week",
|
||||||
|
"method": "GET",
|
||||||
|
"headers": [],
|
||||||
|
"queryParams": [
|
||||||
|
{
|
||||||
|
"id": "x9nxr63itm2lvbe8dmi53mi7",
|
||||||
|
"key": "api_key",
|
||||||
|
"value": "{{API Key}}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"isCustomBody": false,
|
"isCustomBody": false,
|
||||||
"isAdvancedConfig": true,
|
"isAdvancedConfig": true,
|
||||||
"variablesForTest": [
|
"variablesForTest": [
|
||||||
@@ -238,11 +269,10 @@
|
|||||||
"variableId": "vcmybxcoaytd2geo5sqx7v8hw"
|
"variableId": "vcmybxcoaytd2geo5sqx7v8hw"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
}
|
||||||
"webhookId": "ohc5k58i0bs4i2vc5ymjxqbx"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "u6q1nvxowaszfdu4g42nqz38",
|
"id": "ruhgtbpv18cy2g5ujavljkku",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"content": {
|
"content": {
|
||||||
"richText": [
|
"richText": [
|
||||||
@@ -252,10 +282,10 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"groupId": "dewz832l9kse7xx1vhkihbk6"
|
"groupId": "d6v9lh83c7zuwrhf2mmo6nxo"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "stlcncbupmsjxjipi86s45hy",
|
"id": "krcvvncnqtn99v0qe1dzudrk",
|
||||||
"type": "choice input",
|
"type": "choice input",
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
@@ -265,7 +295,7 @@
|
|||||||
"content": "Click to edit"
|
"content": "Click to edit"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"groupId": "dewz832l9kse7xx1vhkihbk6",
|
"groupId": "d6v9lh83c7zuwrhf2mmo6nxo",
|
||||||
"options": {
|
"options": {
|
||||||
"variableId": "vulnb1om2fk8mvkcesl8s15cr",
|
"variableId": "vulnb1om2fk8mvkcesl8s15cr",
|
||||||
"buttonLabel": "Send",
|
"buttonLabel": "Send",
|
||||||
@@ -274,25 +304,31 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "h0mbyxa1o6kyhpv2gwbweunu",
|
"id": "mgn6uuw2yebmengsukjramjx",
|
||||||
"type": "Set variable",
|
"type": "Set variable",
|
||||||
"groupId": "dewz832l9kse7xx1vhkihbk6",
|
"groupId": "d6v9lh83c7zuwrhf2mmo6nxo",
|
||||||
"options": {
|
"options": {
|
||||||
|
"type": "Map item with same index",
|
||||||
"isCode": true,
|
"isCode": true,
|
||||||
"variableId": "vzslfw8oyo1f08uo5rpkegn0x",
|
"variableId": "vzslfw8oyo1f08uo5rpkegn0x",
|
||||||
|
"mapListItemParams": {
|
||||||
|
"baseItemVariableId": "vulnb1om2fk8mvkcesl8s15cr",
|
||||||
|
"baseListVariableId": "vkzk96oh1pmdjv2bt5ps60qc0",
|
||||||
|
"targetListVariableId": "vcmybxcoaytd2geo5sqx7v8hw"
|
||||||
|
},
|
||||||
"expressionToEvaluate": "{{Trending IDs}}.at({{Trending Movies}}.indexOf({{Selected Trending Movie}}))"
|
"expressionToEvaluate": "{{Trending IDs}}.at({{Trending Movies}}.indexOf({{Selected Trending Movie}}))"
|
||||||
},
|
},
|
||||||
"outgoingEdgeId": "ctxcurho3eq3dkna3emyvpwr"
|
"outgoingEdgeId": "ual6xszx6tfcxqrnihc6zrvx"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"graphCoordinates": { "x": 621.875, "y": 933.359375 }
|
"graphCoordinates": { "x": 628.03, "y": 965.53 }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "a1c99wep8eqambqjw8g8yeo8",
|
"id": "v35sky44jzz9fkwwul2qxufl",
|
||||||
"title": "Movies by genre",
|
"title": "Movies by genre",
|
||||||
"blocks": [
|
"blocks": [
|
||||||
{
|
{
|
||||||
"id": "dbp1cdzqy7txabinmm5osi1a",
|
"id": "g2pgwx5yr1ou9vkoy6gdwuor",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"content": {
|
"content": {
|
||||||
"richText": [
|
"richText": [
|
||||||
@@ -306,13 +342,31 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"groupId": "a1c99wep8eqambqjw8g8yeo8"
|
"groupId": "v35sky44jzz9fkwwul2qxufl"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ym35vqr6euzhmtj8i03yzilz",
|
"id": "a2datk3pv8o6xgitwjsq61m2",
|
||||||
"type": "Webhook",
|
"type": "Webhook",
|
||||||
"groupId": "a1c99wep8eqambqjw8g8yeo8",
|
"groupId": "v35sky44jzz9fkwwul2qxufl",
|
||||||
"options": {
|
"options": {
|
||||||
|
"webhook": {
|
||||||
|
"id": "em7huyvp98pd6hr25md0l6hb",
|
||||||
|
"url": "https://api.themoviedb.org/3/discover/movie",
|
||||||
|
"method": "GET",
|
||||||
|
"headers": [],
|
||||||
|
"queryParams": [
|
||||||
|
{
|
||||||
|
"id": "mgwlp399a056o9jo93tjqp02",
|
||||||
|
"key": "api_key",
|
||||||
|
"value": "{{API Key}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "dv4wioynywqo57jq8lakq3yr",
|
||||||
|
"key": "with_genres",
|
||||||
|
"value": "{{Selected genre ID}}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"isCustomBody": false,
|
"isCustomBody": false,
|
||||||
"isAdvancedConfig": true,
|
"isAdvancedConfig": true,
|
||||||
"variablesForTest": [
|
"variablesForTest": [
|
||||||
@@ -339,11 +393,10 @@
|
|||||||
"variableId": "vhc2pc1sv4xc778r9od2ctooz"
|
"variableId": "vhc2pc1sv4xc778r9od2ctooz"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
}
|
||||||
"webhookId": "brjx15qipztmljhh31bsxj4u"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "dxp0gakw90f3ckahjuphx5ir",
|
"id": "tr5y76tx9ca336f8ob9odfa6",
|
||||||
"type": "choice input",
|
"type": "choice input",
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
@@ -353,7 +406,7 @@
|
|||||||
"content": "Click to edit"
|
"content": "Click to edit"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"groupId": "a1c99wep8eqambqjw8g8yeo8",
|
"groupId": "v35sky44jzz9fkwwul2qxufl",
|
||||||
"options": {
|
"options": {
|
||||||
"variableId": "vyyr3j2pu76uzvf88laai8snl",
|
"variableId": "vyyr3j2pu76uzvf88laai8snl",
|
||||||
"buttonLabel": "Send",
|
"buttonLabel": "Send",
|
||||||
@@ -362,38 +415,57 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "hufag2k15sttgg2v2y1mipxz",
|
"id": "vudr8jrv2k3x0ubemt39tv7a",
|
||||||
"type": "Set variable",
|
"type": "Set variable",
|
||||||
"groupId": "a1c99wep8eqambqjw8g8yeo8",
|
"groupId": "v35sky44jzz9fkwwul2qxufl",
|
||||||
"options": {
|
"options": {
|
||||||
|
"type": "Map item with same index",
|
||||||
"isCode": true,
|
"isCode": true,
|
||||||
"variableId": "vzslfw8oyo1f08uo5rpkegn0x",
|
"variableId": "vzslfw8oyo1f08uo5rpkegn0x",
|
||||||
|
"mapListItemParams": {
|
||||||
|
"baseItemVariableId": "vyyr3j2pu76uzvf88laai8snl",
|
||||||
|
"baseListVariableId": "vad8vq3jfyybxo4la57hfd529",
|
||||||
|
"targetListVariableId": "vhc2pc1sv4xc778r9od2ctooz"
|
||||||
|
},
|
||||||
"expressionToEvaluate": "const movieIndex = {{Movies}}.indexOf({{Selected Movie}})\n\nreturn {{Movie IDs}}.at(movieIndex)"
|
"expressionToEvaluate": "const movieIndex = {{Movies}}.indexOf({{Selected Movie}})\n\nreturn {{Movie IDs}}.at(movieIndex)"
|
||||||
},
|
},
|
||||||
"outgoingEdgeId": "wv1qglc5fmexvpaei0xbhtzm"
|
"outgoingEdgeId": "r4wyd2185zhen98r5pmx53g9"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"graphCoordinates": { "x": 977.484375, "y": 330.8515625 }
|
"graphCoordinates": { "x": 977.48, "y": 330.85 }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "xutzzlxo0f5hs9q8ga1e8tl9",
|
"id": "uozlg88loeb8xegu6y4le6k8",
|
||||||
"title": "Movie details",
|
"title": "Movie details",
|
||||||
"blocks": [
|
"blocks": [
|
||||||
{
|
{
|
||||||
"id": "tsferop3f80u2jq9p8ip964h",
|
"id": "ve9m7fromxw4tbm8558n8520",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"content": {
|
"content": {
|
||||||
"richText": [
|
"richText": [
|
||||||
{ "type": "p", "children": [{ "text": "Excellent choice 🔥" }] }
|
{ "type": "p", "children": [{ "text": "Excellent choice 🔥" }] }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"groupId": "xutzzlxo0f5hs9q8ga1e8tl9"
|
"groupId": "uozlg88loeb8xegu6y4le6k8"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "sssp7cez39ndix4owjl8x09t",
|
"id": "xag9d5i5td40kdt3poyq5g4b",
|
||||||
"type": "Webhook",
|
"type": "Webhook",
|
||||||
"groupId": "xutzzlxo0f5hs9q8ga1e8tl9",
|
"groupId": "uozlg88loeb8xegu6y4le6k8",
|
||||||
"options": {
|
"options": {
|
||||||
|
"webhook": {
|
||||||
|
"id": "ewrjdmbrm2yksvjrbp0z9duy",
|
||||||
|
"url": "https://api.themoviedb.org/3/movie/{{Selected Movie ID}}",
|
||||||
|
"method": "GET",
|
||||||
|
"headers": [],
|
||||||
|
"queryParams": [
|
||||||
|
{
|
||||||
|
"id": "f33u3unbezibfdv54kbkien3",
|
||||||
|
"key": "api_key",
|
||||||
|
"value": "{{API Key}}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"isCustomBody": false,
|
"isCustomBody": false,
|
||||||
"isAdvancedConfig": true,
|
"isAdvancedConfig": true,
|
||||||
"variablesForTest": [
|
"variablesForTest": [
|
||||||
@@ -425,13 +497,12 @@
|
|||||||
"variableId": "vzf5ryexokpr4dihiur2spm8z"
|
"variableId": "vzf5ryexokpr4dihiur2spm8z"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
}
|
||||||
"webhookId": "d0x75v11voy19hnrrqnjlwpv"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "e4h6b2vb409zkwa0jrpyjpt0",
|
"id": "d0rsus9shxj8iowczbcaw53i",
|
||||||
"type": "Set variable",
|
"type": "Set variable",
|
||||||
"groupId": "xutzzlxo0f5hs9q8ga1e8tl9",
|
"groupId": "uozlg88loeb8xegu6y4le6k8",
|
||||||
"options": {
|
"options": {
|
||||||
"isCode": false,
|
"isCode": false,
|
||||||
"variableId": "vwitf3um5uweynypc0hxxwm14",
|
"variableId": "vwitf3um5uweynypc0hxxwm14",
|
||||||
@@ -439,23 +510,23 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ze726gr9fs7elsdqekbijckv",
|
"id": "nqnry4c1z3wwcni8rwpduuhe",
|
||||||
"type": "image",
|
"type": "image",
|
||||||
"content": { "url": "{{Poster URL}}" },
|
"content": { "url": "{{Poster URL}}" },
|
||||||
"groupId": "xutzzlxo0f5hs9q8ga1e8tl9"
|
"groupId": "uozlg88loeb8xegu6y4le6k8"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "t21xt4nr48hyu2qk2ij0d2oe",
|
"id": "lhljw54rdykyqtjiuh6jsl5c",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"content": {
|
"content": {
|
||||||
"richText": [
|
"richText": [
|
||||||
{ "type": "p", "children": [{ "text": "{{Movie Overview}}" }] }
|
{ "type": "p", "children": [{ "text": "{{Movie Overview}}" }] }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"groupId": "xutzzlxo0f5hs9q8ga1e8tl9"
|
"groupId": "uozlg88loeb8xegu6y4le6k8"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "nahhsfc6hsok5sufxcknopxr",
|
"id": "yifjhiamifo1y4ay7vols0mm",
|
||||||
"type": "choice input",
|
"type": "choice input",
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
@@ -463,7 +534,7 @@
|
|||||||
"type": 0,
|
"type": 0,
|
||||||
"blockId": "nahhsfc6hsok5sufxcknopxr",
|
"blockId": "nahhsfc6hsok5sufxcknopxr",
|
||||||
"content": "Watch the movie",
|
"content": "Watch the movie",
|
||||||
"outgoingEdgeId": "v2qrjwz43nej3nxbkbcq3kyd"
|
"outgoingEdgeId": "fteu5frsbj8wejfhhwzuv8t1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "j9d1pf2tndax0itezys7t73c",
|
"id": "j9d1pf2tndax0itezys7t73c",
|
||||||
@@ -472,44 +543,44 @@
|
|||||||
"content": "Find something else"
|
"content": "Find something else"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"groupId": "xutzzlxo0f5hs9q8ga1e8tl9",
|
"groupId": "uozlg88loeb8xegu6y4le6k8",
|
||||||
"options": { "buttonLabel": "Send", "isMultipleChoice": false },
|
"options": { "buttonLabel": "Send", "isMultipleChoice": false },
|
||||||
"outgoingEdgeId": "rddv20ku82g2yyagatt95t3r"
|
"outgoingEdgeId": "ntef5v9bt7vn4wg8s3dfm8yl"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"graphCoordinates": { "x": 1198.4140625, "y": 846.53515625 }
|
"graphCoordinates": { "x": 1151.05, "y": 913.34 }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "vgulvp3bw1bi9em7yq6jfdrv",
|
"id": "x4d8cdsyzoqz6vzsurnb8twc",
|
||||||
"title": "Redirect to IMDB",
|
"title": "Redirect to IMDB",
|
||||||
"blocks": [
|
"blocks": [
|
||||||
{
|
{
|
||||||
"id": "y7z3nkawu4dwh1otgcwbenyz",
|
"id": "mw0e0bzwiokhndkkncp9niu2",
|
||||||
"type": "Redirect",
|
"type": "Redirect",
|
||||||
"groupId": "vgulvp3bw1bi9em7yq6jfdrv",
|
"groupId": "x4d8cdsyzoqz6vzsurnb8twc",
|
||||||
"options": {
|
"options": {
|
||||||
"url": "https://m.imdb.com/title/{{IMDB ID}}",
|
"url": "https://m.imdb.com/title/{{IMDB ID}}",
|
||||||
"isNewTab": false
|
"isNewTab": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"graphCoordinates": { "x": 1693.453125, "y": 1324.9921875 }
|
"graphCoordinates": { "x": 1616.55, "y": 1411.44 }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "trfx6m1qiu7awvwjfnhfd712",
|
"id": "x9610wtdv125hg56wicm2qmv",
|
||||||
"title": "Return to menu",
|
"title": "Return to menu",
|
||||||
"blocks": [
|
"blocks": [
|
||||||
{
|
{
|
||||||
"id": "jumese0l44liwke0l5glv0fs",
|
"id": "efto9jivvcvomj3kltf57hbb",
|
||||||
"type": "Jump",
|
"type": "Jump",
|
||||||
"groupId": "trfx6m1qiu7awvwjfnhfd712",
|
"groupId": "x9610wtdv125hg56wicm2qmv",
|
||||||
"options": {
|
"options": {
|
||||||
"blockId": "sodsq9mcigwvogmwx0t4jvil",
|
"blockId": "sodsq9mcigwvogmwx0t4jvil",
|
||||||
"groupId": "vpsi7kfd4hiu38fd0txt3ndn"
|
"groupId": "mjnkukpkpvf4ha2g4n5m804v"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"graphCoordinates": { "x": 1690.52734375, "y": 1501.76953125 }
|
"graphCoordinates": { "x": 1619.34, "y": 1586.5 }
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"variables": [
|
"variables": [
|
||||||
@@ -532,70 +603,70 @@
|
|||||||
],
|
],
|
||||||
"edges": [
|
"edges": [
|
||||||
{
|
{
|
||||||
"id": "ozfvttdxg70dy931m762ssc0",
|
"id": "wfec8f4e1jtden2wqna6nrso",
|
||||||
"to": { "groupId": "vpsi7kfd4hiu38fd0txt3ndn" },
|
"to": { "groupId": "mjnkukpkpvf4ha2g4n5m804v" },
|
||||||
"from": {
|
"from": {
|
||||||
"blockId": "dn2vorjxq275ulqwd97sgfjp",
|
"blockId": "rha69fygov33vym1hf6z837p",
|
||||||
"groupId": "kto4a8zwoqvagp14sjol0mqq"
|
"groupId": "u6lpjibfjhyoqij5wjf9kvnl"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "o8n3df42rx0og3vlkzhskp7r",
|
"id": "t8qyjpigrz7cdl8gxl1wxlwj",
|
||||||
"to": { "groupId": "xjwiuplgl79ezx460xfuplgr" },
|
"to": { "groupId": "kq1g5z6pz4buot7sawqdrr3s" },
|
||||||
"from": {
|
"from": {
|
||||||
"itemId": "kaimvzg9igdtktgou5m3s1bw",
|
"itemId": "kaimvzg9igdtktgou5m3s1bw",
|
||||||
"blockId": "sodsq9mcigwvogmwx0t4jvil",
|
"blockId": "tzf45bvd8iquoxz7qgta8v94",
|
||||||
"groupId": "vpsi7kfd4hiu38fd0txt3ndn"
|
"groupId": "mjnkukpkpvf4ha2g4n5m804v"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "vcuv47fbcqrtuelfy4i6ctqz",
|
"id": "tfuuwjnpn7mftd5s65mbhytd",
|
||||||
"to": { "groupId": "a1c99wep8eqambqjw8g8yeo8" },
|
"to": { "groupId": "v35sky44jzz9fkwwul2qxufl" },
|
||||||
"from": {
|
"from": {
|
||||||
"blockId": "s27x4vixvakw62rwlsx61vw6",
|
"blockId": "j7pm34um4piuyabwlobjc356",
|
||||||
"groupId": "xjwiuplgl79ezx460xfuplgr"
|
"groupId": "kq1g5z6pz4buot7sawqdrr3s"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "wv1qglc5fmexvpaei0xbhtzm",
|
"id": "r4wyd2185zhen98r5pmx53g9",
|
||||||
"to": { "groupId": "xutzzlxo0f5hs9q8ga1e8tl9" },
|
"to": { "groupId": "uozlg88loeb8xegu6y4le6k8" },
|
||||||
"from": {
|
"from": {
|
||||||
"blockId": "hufag2k15sttgg2v2y1mipxz",
|
"blockId": "vudr8jrv2k3x0ubemt39tv7a",
|
||||||
"groupId": "a1c99wep8eqambqjw8g8yeo8"
|
"groupId": "v35sky44jzz9fkwwul2qxufl"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "v2qrjwz43nej3nxbkbcq3kyd",
|
"id": "fteu5frsbj8wejfhhwzuv8t1",
|
||||||
"to": { "groupId": "vgulvp3bw1bi9em7yq6jfdrv" },
|
"to": { "groupId": "x4d8cdsyzoqz6vzsurnb8twc" },
|
||||||
"from": {
|
"from": {
|
||||||
"itemId": "n4818dnrb4arw1xh5v0ot8vz",
|
"itemId": "n4818dnrb4arw1xh5v0ot8vz",
|
||||||
"blockId": "nahhsfc6hsok5sufxcknopxr",
|
"blockId": "yifjhiamifo1y4ay7vols0mm",
|
||||||
"groupId": "xutzzlxo0f5hs9q8ga1e8tl9"
|
"groupId": "uozlg88loeb8xegu6y4le6k8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "cfwctrcqoucw6djnn0j2zsv0",
|
"id": "tjn2ljosqyd4aj9dk8mnifsu",
|
||||||
"to": { "groupId": "dewz832l9kse7xx1vhkihbk6" },
|
"to": { "groupId": "d6v9lh83c7zuwrhf2mmo6nxo" },
|
||||||
"from": {
|
"from": {
|
||||||
"itemId": "i8ls2f8inq2ovuijj6l7rbcq",
|
"itemId": "i8ls2f8inq2ovuijj6l7rbcq",
|
||||||
"blockId": "sodsq9mcigwvogmwx0t4jvil",
|
"blockId": "tzf45bvd8iquoxz7qgta8v94",
|
||||||
"groupId": "vpsi7kfd4hiu38fd0txt3ndn"
|
"groupId": "mjnkukpkpvf4ha2g4n5m804v"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "rddv20ku82g2yyagatt95t3r",
|
"id": "ntef5v9bt7vn4wg8s3dfm8yl",
|
||||||
"to": { "groupId": "trfx6m1qiu7awvwjfnhfd712" },
|
"to": { "groupId": "x9610wtdv125hg56wicm2qmv" },
|
||||||
"from": {
|
"from": {
|
||||||
"blockId": "nahhsfc6hsok5sufxcknopxr",
|
"blockId": "yifjhiamifo1y4ay7vols0mm",
|
||||||
"groupId": "xutzzlxo0f5hs9q8ga1e8tl9"
|
"groupId": "uozlg88loeb8xegu6y4le6k8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ctxcurho3eq3dkna3emyvpwr",
|
"id": "ual6xszx6tfcxqrnihc6zrvx",
|
||||||
"to": { "groupId": "xutzzlxo0f5hs9q8ga1e8tl9" },
|
"to": { "groupId": "uozlg88loeb8xegu6y4le6k8" },
|
||||||
"from": {
|
"from": {
|
||||||
"blockId": "h0mbyxa1o6kyhpv2gwbweunu",
|
"blockId": "mgn6uuw2yebmengsukjramjx",
|
||||||
"groupId": "dewz832l9kse7xx1vhkihbk6"
|
"groupId": "d6v9lh83c7zuwrhf2mmo6nxo"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -632,7 +703,6 @@
|
|||||||
},
|
},
|
||||||
"publicId": null,
|
"publicId": null,
|
||||||
"customDomain": null,
|
"customDomain": null,
|
||||||
"workspaceId": "freeWorkspace",
|
|
||||||
"resultsTablePreferences": null,
|
"resultsTablePreferences": null,
|
||||||
"isArchived": false,
|
"isArchived": false,
|
||||||
"isClosed": false
|
"isClosed": false
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "clesntjqu00011a4xkgffc3p0",
|
"id": "clesntjqu00011a4xkgffc3p0",
|
||||||
"version": "3",
|
"version": "4",
|
||||||
"createdAt": "2023-03-03T14:57:41.430Z",
|
"createdAt": "2023-03-03T14:57:41.430Z",
|
||||||
"updatedAt": "2023-03-03T16:14:29.268Z",
|
"updatedAt": "2023-03-03T16:14:29.268Z",
|
||||||
"icon": "⭐",
|
"icon": "⭐",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "qkvenb8ur2y0ahlbckmx7law",
|
"id": "qkvenb8ur2y0ahlbckmx7law",
|
||||||
"version": "3",
|
"version": "4",
|
||||||
"createdAt": "2023-02-22T14:26:28.592Z",
|
"createdAt": "2023-02-22T14:26:28.592Z",
|
||||||
"updatedAt": "2023-02-22T14:28:05.063Z",
|
"updatedAt": "2023-02-22T14:28:05.063Z",
|
||||||
"icon": null,
|
"icon": null,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "mdbjvgqhqypbsdd0airkzcwu",
|
"id": "mdbjvgqhqypbsdd0airkzcwu",
|
||||||
"version": "3",
|
"version": "4",
|
||||||
"createdAt": "2023-06-05T15:40:37.278Z",
|
"createdAt": "2023-06-05T15:40:37.278Z",
|
||||||
"updatedAt": "2023-06-05T15:45:43.049Z",
|
"updatedAt": "2023-06-05T15:45:43.049Z",
|
||||||
"icon": "🍫",
|
"icon": "🍫",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"id": "cl1qz4luj04007w1ai7rk1j5q",
|
"id": "cl1qz4luj04007w1ai7rk1j5q",
|
||||||
|
"version": "4",
|
||||||
"createdAt": "2022-04-08T22:02:30.427Z",
|
"createdAt": "2022-04-08T22:02:30.427Z",
|
||||||
"updatedAt": "2022-04-08T23:03:34.726Z",
|
"updatedAt": "2022-04-08T23:03:34.726Z",
|
||||||
"icon": "🕹️",
|
"icon": "🕹️",
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ type Props = {
|
|||||||
|
|
||||||
export const MakeComContent = ({ block }: Props) => {
|
export const MakeComContent = ({ block }: Props) => {
|
||||||
const { webhooks } = useTypebot()
|
const { webhooks } = useTypebot()
|
||||||
const webhook = webhooks.find(byId(block.webhookId))
|
const webhook = block.options.webhook ?? webhooks.find(byId(block.webhookId))
|
||||||
|
|
||||||
if (isNotDefined(webhook?.body))
|
if (isNotDefined(webhook?.body))
|
||||||
return <Text color="gray.500">Configure...</Text>
|
return <Text color="gray.500">Configure...</Text>
|
||||||
|
|||||||
@@ -22,10 +22,17 @@ export const MakeComSettings = ({
|
|||||||
|
|
||||||
const setLocalWebhook = useCallback(
|
const setLocalWebhook = useCallback(
|
||||||
async (newLocalWebhook: Webhook) => {
|
async (newLocalWebhook: Webhook) => {
|
||||||
|
if (options.webhook) {
|
||||||
|
onOptionsChange({
|
||||||
|
...options,
|
||||||
|
webhook: newLocalWebhook,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
_setLocalWebhook(newLocalWebhook)
|
_setLocalWebhook(newLocalWebhook)
|
||||||
await updateWebhook(newLocalWebhook.id, newLocalWebhook)
|
await updateWebhook(newLocalWebhook.id, newLocalWebhook)
|
||||||
},
|
},
|
||||||
[updateWebhook]
|
[onOptionsChange, options, updateWebhook]
|
||||||
)
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -33,20 +40,23 @@ export const MakeComSettings = ({
|
|||||||
!localWebhook ||
|
!localWebhook ||
|
||||||
localWebhook.url ||
|
localWebhook.url ||
|
||||||
!webhook?.url ||
|
!webhook?.url ||
|
||||||
webhook.url === localWebhook.url
|
webhook.url === localWebhook.url ||
|
||||||
|
options.webhook
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
setLocalWebhook({
|
setLocalWebhook({
|
||||||
...localWebhook,
|
...localWebhook,
|
||||||
url: webhook?.url,
|
url: webhook?.url,
|
||||||
})
|
})
|
||||||
}, [webhook, localWebhook, setLocalWebhook])
|
}, [webhook, localWebhook, setLocalWebhook, options.webhook])
|
||||||
|
|
||||||
|
const url = options.webhook?.url ?? localWebhook?.url
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack spacing={4}>
|
<Stack spacing={4}>
|
||||||
<Alert status={localWebhook?.url ? 'success' : 'info'} rounded="md">
|
<Alert status={url ? 'success' : 'info'} rounded="md">
|
||||||
<AlertIcon />
|
<AlertIcon />
|
||||||
{localWebhook?.url ? (
|
{url ? (
|
||||||
<>Your scenario is correctly configured 🚀</>
|
<>Your scenario is correctly configured 🚀</>
|
||||||
) : (
|
) : (
|
||||||
<Stack>
|
<Stack>
|
||||||
@@ -62,10 +72,10 @@ export const MakeComSettings = ({
|
|||||||
</Stack>
|
</Stack>
|
||||||
)}
|
)}
|
||||||
</Alert>
|
</Alert>
|
||||||
{localWebhook && (
|
{(localWebhook || options.webhook) && (
|
||||||
<WebhookAdvancedConfigForm
|
<WebhookAdvancedConfigForm
|
||||||
blockId={blockId}
|
blockId={blockId}
|
||||||
webhook={localWebhook}
|
webhook={(options.webhook ?? localWebhook) as Webhook}
|
||||||
options={options}
|
options={options}
|
||||||
onWebhookChange={setLocalWebhook}
|
onWebhookChange={setLocalWebhook}
|
||||||
onOptionsChange={onOptionsChange}
|
onOptionsChange={onOptionsChange}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ type Props = {
|
|||||||
|
|
||||||
export const PabblyConnectContent = ({ block }: Props) => {
|
export const PabblyConnectContent = ({ block }: Props) => {
|
||||||
const { webhooks } = useTypebot()
|
const { webhooks } = useTypebot()
|
||||||
const webhook = webhooks.find(byId(block.webhookId))
|
const webhook = block.options.webhook ?? webhooks.find(byId(block.webhookId))
|
||||||
|
|
||||||
if (isNotDefined(webhook?.body))
|
if (isNotDefined(webhook?.body))
|
||||||
return <Text color="gray.500">Configure...</Text>
|
return <Text color="gray.500">Configure...</Text>
|
||||||
|
|||||||
@@ -27,6 +27,13 @@ export const PabblyConnectSettings = ({
|
|||||||
)
|
)
|
||||||
|
|
||||||
const setLocalWebhook = async (newLocalWebhook: Webhook) => {
|
const setLocalWebhook = async (newLocalWebhook: Webhook) => {
|
||||||
|
if (options.webhook) {
|
||||||
|
onOptionsChange({
|
||||||
|
...options,
|
||||||
|
webhook: newLocalWebhook,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
_setLocalWebhook(newLocalWebhook)
|
_setLocalWebhook(newLocalWebhook)
|
||||||
await updateWebhook(newLocalWebhook.id, newLocalWebhook)
|
await updateWebhook(newLocalWebhook.id, newLocalWebhook)
|
||||||
}
|
}
|
||||||
@@ -38,11 +45,13 @@ export const PabblyConnectSettings = ({
|
|||||||
url,
|
url,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const url = options.webhook?.url ?? localWebhook?.url
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack spacing={4}>
|
<Stack spacing={4}>
|
||||||
<Alert status={localWebhook?.url ? 'success' : 'info'} rounded="md">
|
<Alert status={url ? 'success' : 'info'} rounded="md">
|
||||||
<AlertIcon />
|
<AlertIcon />
|
||||||
{localWebhook?.url ? (
|
{url ? (
|
||||||
<>Your scenario is correctly configured 🚀</>
|
<>Your scenario is correctly configured 🚀</>
|
||||||
) : (
|
) : (
|
||||||
<Stack>
|
<Stack>
|
||||||
@@ -60,15 +69,15 @@ export const PabblyConnectSettings = ({
|
|||||||
</Alert>
|
</Alert>
|
||||||
<TextInput
|
<TextInput
|
||||||
placeholder="Paste webhook URL..."
|
placeholder="Paste webhook URL..."
|
||||||
defaultValue={localWebhook?.url ?? ''}
|
defaultValue={url ?? ''}
|
||||||
onChange={handleUrlChange}
|
onChange={handleUrlChange}
|
||||||
withVariableButton={false}
|
withVariableButton={false}
|
||||||
debounceTimeout={0}
|
debounceTimeout={0}
|
||||||
/>
|
/>
|
||||||
{localWebhook && (
|
{(localWebhook || options.webhook) && (
|
||||||
<WebhookAdvancedConfigForm
|
<WebhookAdvancedConfigForm
|
||||||
blockId={blockId}
|
blockId={blockId}
|
||||||
webhook={localWebhook}
|
webhook={(options.webhook ?? localWebhook) as Webhook}
|
||||||
options={options}
|
options={options}
|
||||||
onWebhookChange={setLocalWebhook}
|
onWebhookChange={setLocalWebhook}
|
||||||
onOptionsChange={onOptionsChange}
|
onOptionsChange={onOptionsChange}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import prisma from '@/lib/prisma'
|
|||||||
import { canReadTypebots } from '@/helpers/databaseRules'
|
import { canReadTypebots } from '@/helpers/databaseRules'
|
||||||
import { authenticatedProcedure } from '@/helpers/server/trpc'
|
import { authenticatedProcedure } from '@/helpers/server/trpc'
|
||||||
import { TRPCError } from '@trpc/server'
|
import { TRPCError } from '@trpc/server'
|
||||||
import { Typebot, Webhook } from '@typebot.io/schemas'
|
import { Typebot } from '@typebot.io/schemas'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { fetchLinkedTypebots } from '@/features/blocks/logic/typebotLink/helpers/fetchLinkedTypebots'
|
import { fetchLinkedTypebots } from '@/features/blocks/logic/typebotLink/helpers/fetchLinkedTypebots'
|
||||||
import { parseResultExample } from '../helpers/parseResultExample'
|
import { parseResultExample } from '../helpers/parseResultExample'
|
||||||
@@ -45,20 +45,15 @@ export const getResultExample = authenticatedProcedure
|
|||||||
groups: true,
|
groups: true,
|
||||||
edges: true,
|
edges: true,
|
||||||
variables: true,
|
variables: true,
|
||||||
webhooks: true,
|
|
||||||
},
|
},
|
||||||
})) as
|
})) as Pick<Typebot, 'groups' | 'edges' | 'variables'> | null
|
||||||
| (Pick<Typebot, 'groups' | 'edges' | 'variables'> & {
|
|
||||||
webhooks: Webhook[]
|
|
||||||
})
|
|
||||||
| null
|
|
||||||
|
|
||||||
if (!typebot)
|
if (!typebot)
|
||||||
throw new TRPCError({ code: 'NOT_FOUND', message: 'Typebot not found' })
|
throw new TRPCError({ code: 'NOT_FOUND', message: 'Typebot not found' })
|
||||||
|
|
||||||
const block = typebot.groups
|
const block = typebot.groups
|
||||||
.flatMap((g) => g.blocks)
|
.flatMap((group) => group.blocks)
|
||||||
.find((s) => s.id === blockId)
|
.find((block) => block.id === blockId)
|
||||||
|
|
||||||
if (!block)
|
if (!block)
|
||||||
throw new TRPCError({ code: 'NOT_FOUND', message: 'Block not found' })
|
throw new TRPCError({ code: 'NOT_FOUND', message: 'Block not found' })
|
||||||
|
|||||||
@@ -2,9 +2,10 @@ import prisma from '@/lib/prisma'
|
|||||||
import { canReadTypebots } from '@/helpers/databaseRules'
|
import { canReadTypebots } from '@/helpers/databaseRules'
|
||||||
import { authenticatedProcedure } from '@/helpers/server/trpc'
|
import { authenticatedProcedure } from '@/helpers/server/trpc'
|
||||||
import { TRPCError } from '@trpc/server'
|
import { TRPCError } from '@trpc/server'
|
||||||
import { Group, Typebot, Webhook, WebhookBlock } from '@typebot.io/schemas'
|
import { Group, IntegrationBlockType, Typebot } from '@typebot.io/schemas'
|
||||||
import { byId, isWebhookBlock, parseGroupTitle } from '@typebot.io/lib'
|
import { byId, isWebhookBlock, parseGroupTitle } from '@typebot.io/lib'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
import { Webhook } from '@typebot.io/prisma'
|
||||||
|
|
||||||
export const listWebhookBlocks = authenticatedProcedure
|
export const listWebhookBlocks = authenticatedProcedure
|
||||||
.meta({
|
.meta({
|
||||||
@@ -28,6 +29,12 @@ export const listWebhookBlocks = authenticatedProcedure
|
|||||||
webhookBlocks: z.array(
|
webhookBlocks: z.array(
|
||||||
z.object({
|
z.object({
|
||||||
id: z.string(),
|
id: z.string(),
|
||||||
|
type: z.enum([
|
||||||
|
IntegrationBlockType.WEBHOOK,
|
||||||
|
IntegrationBlockType.ZAPIER,
|
||||||
|
IntegrationBlockType.MAKE_COM,
|
||||||
|
IntegrationBlockType.PABBLY_CONNECT,
|
||||||
|
]),
|
||||||
label: z.string(),
|
label: z.string(),
|
||||||
url: z.string().optional(),
|
url: z.string().optional(),
|
||||||
})
|
})
|
||||||
@@ -46,17 +53,27 @@ export const listWebhookBlocks = authenticatedProcedure
|
|||||||
throw new TRPCError({ code: 'NOT_FOUND', message: 'Typebot not found' })
|
throw new TRPCError({ code: 'NOT_FOUND', message: 'Typebot not found' })
|
||||||
|
|
||||||
const webhookBlocks = (typebot?.groups as Group[]).reduce<
|
const webhookBlocks = (typebot?.groups as Group[]).reduce<
|
||||||
{ id: string; label: string; url: string | undefined }[]
|
{
|
||||||
|
id: string
|
||||||
|
label: string
|
||||||
|
url: string | undefined
|
||||||
|
type:
|
||||||
|
| IntegrationBlockType.WEBHOOK
|
||||||
|
| IntegrationBlockType.ZAPIER
|
||||||
|
| IntegrationBlockType.MAKE_COM
|
||||||
|
| IntegrationBlockType.PABBLY_CONNECT
|
||||||
|
}[]
|
||||||
>((webhookBlocks, group) => {
|
>((webhookBlocks, group) => {
|
||||||
const blocks = group.blocks.filter((block) =>
|
const blocks = group.blocks.filter(isWebhookBlock)
|
||||||
isWebhookBlock(block)
|
|
||||||
) as WebhookBlock[]
|
|
||||||
return [
|
return [
|
||||||
...webhookBlocks,
|
...webhookBlocks,
|
||||||
...blocks.map((b) => ({
|
...blocks.map((block) => ({
|
||||||
id: b.id,
|
id: block.id,
|
||||||
label: `${parseGroupTitle(group.title)} > ${b.id}`,
|
type: block.type,
|
||||||
url: typebot?.webhooks.find(byId(b.webhookId))?.url ?? undefined,
|
label: `${parseGroupTitle(group.title)} > ${block.id}`,
|
||||||
|
url: block.options.webhook
|
||||||
|
? block.options.webhook.url
|
||||||
|
: typebot?.webhooks.find(byId(block.webhookId))?.url ?? undefined,
|
||||||
})),
|
})),
|
||||||
]
|
]
|
||||||
}, [])
|
}, [])
|
||||||
|
|||||||
@@ -2,9 +2,10 @@ import prisma from '@/lib/prisma'
|
|||||||
import { canWriteTypebots } from '@/helpers/databaseRules'
|
import { canWriteTypebots } from '@/helpers/databaseRules'
|
||||||
import { authenticatedProcedure } from '@/helpers/server/trpc'
|
import { authenticatedProcedure } from '@/helpers/server/trpc'
|
||||||
import { TRPCError } from '@trpc/server'
|
import { TRPCError } from '@trpc/server'
|
||||||
import { Typebot, Webhook, WebhookBlock } from '@typebot.io/schemas'
|
import { Typebot, WebhookBlock } from '@typebot.io/schemas'
|
||||||
import { byId, isWebhookBlock } from '@typebot.io/lib'
|
import { byId, isWebhookBlock } from '@typebot.io/lib'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
import { HttpMethod } from '@typebot.io/schemas/features/blocks/integrations/webhook/enums'
|
||||||
|
|
||||||
export const subscribeWebhook = authenticatedProcedure
|
export const subscribeWebhook = authenticatedProcedure
|
||||||
.meta({
|
.meta({
|
||||||
@@ -34,9 +35,8 @@ export const subscribeWebhook = authenticatedProcedure
|
|||||||
where: canWriteTypebots(typebotId, user),
|
where: canWriteTypebots(typebotId, user),
|
||||||
select: {
|
select: {
|
||||||
groups: true,
|
groups: true,
|
||||||
webhooks: true,
|
|
||||||
},
|
},
|
||||||
})) as (Pick<Typebot, 'groups'> & { webhooks: Webhook[] }) | null
|
})) as Pick<Typebot, 'groups'> | null
|
||||||
|
|
||||||
if (!typebot)
|
if (!typebot)
|
||||||
throw new TRPCError({ code: 'NOT_FOUND', message: 'Typebot not found' })
|
throw new TRPCError({ code: 'NOT_FOUND', message: 'Typebot not found' })
|
||||||
@@ -51,18 +51,50 @@ export const subscribeWebhook = authenticatedProcedure
|
|||||||
message: 'Webhook block not found',
|
message: 'Webhook block not found',
|
||||||
})
|
})
|
||||||
|
|
||||||
await prisma.webhook.upsert({
|
const newWebhook = {
|
||||||
where: { id: webhookBlock.webhookId },
|
id: webhookBlock.webhookId ?? webhookBlock.id,
|
||||||
update: { url, body: '{{state}}', method: 'POST' },
|
|
||||||
create: {
|
|
||||||
url,
|
url,
|
||||||
body: '{{state}}',
|
body: '{{state}}',
|
||||||
method: 'POST',
|
method: HttpMethod.POST,
|
||||||
typebotId,
|
|
||||||
headers: [],
|
headers: [],
|
||||||
queryParams: [],
|
queryParams: [],
|
||||||
|
}
|
||||||
|
|
||||||
|
if (webhookBlock.webhookId)
|
||||||
|
await prisma.webhook.upsert({
|
||||||
|
where: { id: webhookBlock.webhookId },
|
||||||
|
update: { url, body: newWebhook.body, method: newWebhook.method },
|
||||||
|
create: {
|
||||||
|
typebotId,
|
||||||
|
...newWebhook,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
else {
|
||||||
|
const updatedGroups = typebot.groups.map((group) =>
|
||||||
|
group.id !== webhookBlock.groupId
|
||||||
|
? group
|
||||||
|
: {
|
||||||
|
...group,
|
||||||
|
blocks: group.blocks.map((block) =>
|
||||||
|
block.id !== webhookBlock.id
|
||||||
|
? block
|
||||||
|
: {
|
||||||
|
...block,
|
||||||
|
options: {
|
||||||
|
...webhookBlock.options,
|
||||||
|
webhook: newWebhook,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
await prisma.typebot.updateMany({
|
||||||
|
where: { id: typebotId },
|
||||||
|
data: {
|
||||||
|
groups: updatedGroups,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: blockId,
|
id: blockId,
|
||||||
|
|||||||
@@ -50,10 +50,45 @@ export const unsubscribeWebhook = authenticatedProcedure
|
|||||||
message: 'Webhook block not found',
|
message: 'Webhook block not found',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (webhookBlock.webhookId)
|
||||||
await prisma.webhook.update({
|
await prisma.webhook.update({
|
||||||
where: { id: webhookBlock.webhookId },
|
where: { id: webhookBlock.webhookId },
|
||||||
data: { url: null },
|
data: { url: null },
|
||||||
})
|
})
|
||||||
|
else {
|
||||||
|
if (!webhookBlock.options.webhook)
|
||||||
|
throw new TRPCError({
|
||||||
|
code: 'NOT_FOUND',
|
||||||
|
message: 'Webhook block not found',
|
||||||
|
})
|
||||||
|
const updatedGroups = typebot.groups.map((group) =>
|
||||||
|
group.id !== webhookBlock.groupId
|
||||||
|
? group
|
||||||
|
: {
|
||||||
|
...group,
|
||||||
|
blocks: group.blocks.map((block) =>
|
||||||
|
block.id !== webhookBlock.id
|
||||||
|
? block
|
||||||
|
: {
|
||||||
|
...block,
|
||||||
|
options: {
|
||||||
|
...webhookBlock.options,
|
||||||
|
webhook: {
|
||||||
|
...webhookBlock.options.webhook,
|
||||||
|
url: undefined,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
await prisma.typebot.updateMany({
|
||||||
|
where: { id: typebotId },
|
||||||
|
data: {
|
||||||
|
groups: updatedGroups,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: blockId,
|
id: blockId,
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import {
|
|||||||
Text,
|
Text,
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
import {
|
import {
|
||||||
HttpMethod,
|
|
||||||
KeyValue,
|
KeyValue,
|
||||||
VariableForTest,
|
VariableForTest,
|
||||||
ResponseVariableMapping,
|
ResponseVariableMapping,
|
||||||
@@ -31,6 +30,7 @@ import { QueryParamsInputs, HeadersInputs } from './KeyValueInputs'
|
|||||||
import { DataVariableInputs } from './ResponseMappingInputs'
|
import { DataVariableInputs } from './ResponseMappingInputs'
|
||||||
import { VariableForTestInputs } from './VariableForTestInputs'
|
import { VariableForTestInputs } from './VariableForTestInputs'
|
||||||
import { SwitchWithRelatedSettings } from '@/components/SwitchWithRelatedSettings'
|
import { SwitchWithRelatedSettings } from '@/components/SwitchWithRelatedSettings'
|
||||||
|
import { HttpMethod } from '@typebot.io/schemas/features/blocks/integrations/webhook/enums'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
blockId: string
|
blockId: string
|
||||||
@@ -78,9 +78,11 @@ export const WebhookAdvancedConfigForm = ({
|
|||||||
onOptionsChange({ ...options, isCustomBody })
|
onOptionsChange({ ...options, isCustomBody })
|
||||||
|
|
||||||
const executeTestRequest = async () => {
|
const executeTestRequest = async () => {
|
||||||
if (!typebot || !webhook) return
|
if (!typebot) return
|
||||||
setIsTestResponseLoading(true)
|
setIsTestResponseLoading(true)
|
||||||
|
if (!options.webhook)
|
||||||
await Promise.all([updateWebhook(webhook.id, webhook), save()])
|
await Promise.all([updateWebhook(webhook.id, webhook), save()])
|
||||||
|
else await save()
|
||||||
const { data, error } = await executeWebhook(
|
const { data, error } = await executeWebhook(
|
||||||
typebot.id,
|
typebot.id,
|
||||||
convertVariablesForTestToVariables(
|
convertVariablesForTestToVariables(
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ type Props = {
|
|||||||
block: WebhookBlock
|
block: WebhookBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
export const WebhookContent = ({ block: { webhookId, options } }: Props) => {
|
export const WebhookContent = ({ block: { options, webhookId } }: Props) => {
|
||||||
const { typebot } = useTypebot()
|
const { typebot } = useTypebot()
|
||||||
const { webhooks } = useTypebot()
|
const { webhooks } = useTypebot()
|
||||||
const webhook = webhooks.find(byId(webhookId))
|
const webhook = options.webhook ?? webhooks.find(byId(webhookId))
|
||||||
|
|
||||||
if (!webhook?.url) return <Text color="gray.500">Configure...</Text>
|
if (!webhook?.url) return <Text color="gray.500">Configure...</Text>
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -21,25 +21,33 @@ export const WebhookSettings = ({
|
|||||||
)
|
)
|
||||||
|
|
||||||
const setLocalWebhook = async (newLocalWebhook: Webhook) => {
|
const setLocalWebhook = async (newLocalWebhook: Webhook) => {
|
||||||
|
if (options.webhook) {
|
||||||
|
onOptionsChange({ ...options, webhook: newLocalWebhook })
|
||||||
|
return
|
||||||
|
}
|
||||||
_setLocalWebhook(newLocalWebhook)
|
_setLocalWebhook(newLocalWebhook)
|
||||||
await updateWebhook(newLocalWebhook.id, newLocalWebhook)
|
await updateWebhook(newLocalWebhook.id, newLocalWebhook)
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateUrl = (url?: string) =>
|
const updateUrl = (url: string) => {
|
||||||
localWebhook && setLocalWebhook({ ...localWebhook, url: url ?? null })
|
if (options.webhook)
|
||||||
|
onOptionsChange({ ...options, webhook: { ...options.webhook, url } })
|
||||||
|
else if (localWebhook)
|
||||||
|
setLocalWebhook({ ...localWebhook, url: url ?? undefined })
|
||||||
|
}
|
||||||
|
|
||||||
if (!localWebhook) return <Spinner />
|
if (!localWebhook && !options.webhook) return <Spinner />
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack spacing={4}>
|
<Stack spacing={4}>
|
||||||
<TextInput
|
<TextInput
|
||||||
placeholder="Paste webhook URL..."
|
placeholder="Paste webhook URL..."
|
||||||
defaultValue={localWebhook.url ?? ''}
|
defaultValue={options.webhook?.url ?? localWebhook?.url ?? ''}
|
||||||
onChange={updateUrl}
|
onChange={updateUrl}
|
||||||
/>
|
/>
|
||||||
<WebhookAdvancedConfigForm
|
<WebhookAdvancedConfigForm
|
||||||
blockId={blockId}
|
blockId={blockId}
|
||||||
webhook={localWebhook}
|
webhook={(options.webhook ?? localWebhook) as Webhook}
|
||||||
options={options}
|
options={options}
|
||||||
onWebhookChange={setLocalWebhook}
|
onWebhookChange={setLocalWebhook}
|
||||||
onOptionsChange={onOptionsChange}
|
onOptionsChange={onOptionsChange}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {
|
|||||||
createWebhook,
|
createWebhook,
|
||||||
importTypebotInDatabase,
|
importTypebotInDatabase,
|
||||||
} from '@typebot.io/lib/playwright/databaseActions'
|
} from '@typebot.io/lib/playwright/databaseActions'
|
||||||
import { HttpMethod } from '@typebot.io/schemas'
|
import { HttpMethod } from '@typebot.io/schemas/features/blocks/integrations/webhook/enums'
|
||||||
import { createId } from '@paralleldrive/cuid2'
|
import { createId } from '@paralleldrive/cuid2'
|
||||||
import { getTestAsset } from '@/test/utils/playwright'
|
import { getTestAsset } from '@/test/utils/playwright'
|
||||||
import { apiToken } from '@typebot.io/lib/playwright/databaseSetup'
|
import { apiToken } from '@typebot.io/lib/playwright/databaseSetup'
|
||||||
@@ -26,7 +26,8 @@ test.describe('Builder', () => {
|
|||||||
)
|
)
|
||||||
await page.click('text=Test the request')
|
await page.click('text=Test the request')
|
||||||
await expect(page.locator('div[role="textbox"] >> nth=-1')).toContainText(
|
await expect(page.locator('div[role="textbox"] >> nth=-1')).toContainText(
|
||||||
`"Group #1": "answer value", "Group #2": "20", "Group #2 (1)": "Yes"`, {timeout: 10000}
|
`"Group #1": "answer value", "Group #2": "20", "Group #2 (1)": "Yes"`,
|
||||||
|
{ timeout: 10000 }
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -126,6 +127,7 @@ test.describe('API', () => {
|
|||||||
expect(webhookBlocks[0]).toEqual({
|
expect(webhookBlocks[0]).toEqual({
|
||||||
id: 'webhookBlock',
|
id: 'webhookBlock',
|
||||||
label: 'Webhook > webhookBlock',
|
label: 'Webhook > webhookBlock',
|
||||||
|
type: 'Webhook',
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ type Props = {
|
|||||||
|
|
||||||
export const ZapierContent = ({ block }: Props) => {
|
export const ZapierContent = ({ block }: Props) => {
|
||||||
const { webhooks } = useTypebot()
|
const { webhooks } = useTypebot()
|
||||||
const webhook = webhooks.find(byId(block.webhookId))
|
const webhook = block.options.webhook ?? webhooks.find(byId(block.webhookId))
|
||||||
|
|
||||||
if (isNotDefined(webhook?.body))
|
if (isNotDefined(webhook?.body))
|
||||||
return <Text color="gray.500">Configure...</Text>
|
return <Text color="gray.500">Configure...</Text>
|
||||||
|
|||||||
@@ -22,10 +22,17 @@ export const ZapierSettings = ({
|
|||||||
|
|
||||||
const setLocalWebhook = useCallback(
|
const setLocalWebhook = useCallback(
|
||||||
async (newLocalWebhook: Webhook) => {
|
async (newLocalWebhook: Webhook) => {
|
||||||
|
if (options.webhook) {
|
||||||
|
onOptionsChange({
|
||||||
|
...options,
|
||||||
|
webhook: newLocalWebhook,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
_setLocalWebhook(newLocalWebhook)
|
_setLocalWebhook(newLocalWebhook)
|
||||||
await updateWebhook(newLocalWebhook.id, newLocalWebhook)
|
await updateWebhook(newLocalWebhook.id, newLocalWebhook)
|
||||||
},
|
},
|
||||||
[updateWebhook]
|
[onOptionsChange, options, updateWebhook]
|
||||||
)
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -33,20 +40,23 @@ export const ZapierSettings = ({
|
|||||||
!localWebhook ||
|
!localWebhook ||
|
||||||
localWebhook.url ||
|
localWebhook.url ||
|
||||||
!webhook?.url ||
|
!webhook?.url ||
|
||||||
webhook.url === localWebhook.url
|
webhook.url === localWebhook.url ||
|
||||||
|
options.webhook
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
setLocalWebhook({
|
setLocalWebhook({
|
||||||
...localWebhook,
|
...localWebhook,
|
||||||
url: webhook?.url,
|
url: webhook?.url,
|
||||||
})
|
})
|
||||||
}, [webhook, localWebhook, setLocalWebhook])
|
}, [webhook, localWebhook, setLocalWebhook, options.webhook])
|
||||||
|
|
||||||
|
const url = options.webhook?.url ?? localWebhook?.url
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack spacing={4}>
|
<Stack spacing={4}>
|
||||||
<Alert status={localWebhook?.url ? 'success' : 'info'} rounded="md">
|
<Alert status={url ? 'success' : 'info'} rounded="md">
|
||||||
<AlertIcon />
|
<AlertIcon />
|
||||||
{localWebhook?.url ? (
|
{url ? (
|
||||||
<>Your zap is correctly configured 🚀</>
|
<>Your zap is correctly configured 🚀</>
|
||||||
) : (
|
) : (
|
||||||
<Stack>
|
<Stack>
|
||||||
@@ -62,10 +72,10 @@ export const ZapierSettings = ({
|
|||||||
</Stack>
|
</Stack>
|
||||||
)}
|
)}
|
||||||
</Alert>
|
</Alert>
|
||||||
{localWebhook && (
|
{(localWebhook || options.webhook) && (
|
||||||
<WebhookAdvancedConfigForm
|
<WebhookAdvancedConfigForm
|
||||||
blockId={blockId}
|
blockId={blockId}
|
||||||
webhook={localWebhook}
|
webhook={(options.webhook ?? localWebhook) as Webhook}
|
||||||
options={options}
|
options={options}
|
||||||
onWebhookChange={setLocalWebhook}
|
onWebhookChange={setLocalWebhook}
|
||||||
onOptionsChange={onOptionsChange}
|
onOptionsChange={onOptionsChange}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ test.describe('Condition block', () => {
|
|||||||
await page.click('button:has-text("Age")')
|
await page.click('button:has-text("Age")')
|
||||||
await page.click('button:has-text("Select an operator")')
|
await page.click('button:has-text("Select an operator")')
|
||||||
await page.click('button:has-text("Greater than")', { force: true })
|
await page.click('button:has-text("Greater than")', { force: true })
|
||||||
await page.fill('input[placeholder="Type a value..."]', '80')
|
await page.fill('input[placeholder="Type a number..."]', '80')
|
||||||
|
|
||||||
await page.click('button:has-text("Add a comparison")')
|
await page.click('button:has-text("Add a comparison")')
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ test.describe('Condition block', () => {
|
|||||||
await page.click('button:has-text("Select an operator")')
|
await page.click('button:has-text("Select an operator")')
|
||||||
await page.click('button:has-text("Less than")', { force: true })
|
await page.click('button:has-text("Less than")', { force: true })
|
||||||
await page.fill(
|
await page.fill(
|
||||||
':nth-match(input[placeholder="Type a value..."], 2)',
|
':nth-match(input[placeholder="Type a number..."], 2)',
|
||||||
'100'
|
'100'
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ test.describe('Condition block', () => {
|
|||||||
await page.click('button:has-text("Age")')
|
await page.click('button:has-text("Age")')
|
||||||
await page.click('button:has-text("Select an operator")')
|
await page.click('button:has-text("Select an operator")')
|
||||||
await page.click('button:has-text("Greater than")', { force: true })
|
await page.click('button:has-text("Greater than")', { force: true })
|
||||||
await page.fill('input[placeholder="Type a value..."]', '20')
|
await page.fill('input[placeholder="Type a number..."]', '20')
|
||||||
|
|
||||||
await page.click('text=Preview')
|
await page.click('text=Preview')
|
||||||
await page
|
await page
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ export const parseNewTypebot = ({
|
|||||||
return {
|
return {
|
||||||
folderId,
|
folderId,
|
||||||
name,
|
name,
|
||||||
version: '3',
|
version: '4',
|
||||||
workspaceId,
|
workspaceId,
|
||||||
groups: [startGroup],
|
groups: [startGroup],
|
||||||
edges: [],
|
edges: [],
|
||||||
|
|||||||
@@ -29,13 +29,19 @@ export const importTypebotQuery = async (typebot: Typebot, userPlan: Plan) => {
|
|||||||
const webhookBlocks = typebot.groups
|
const webhookBlocks = typebot.groups
|
||||||
.flatMap((b) => b.blocks)
|
.flatMap((b) => b.blocks)
|
||||||
.filter(isWebhookBlock)
|
.filter(isWebhookBlock)
|
||||||
|
.filter((block) => block.webhookId)
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
webhookBlocks.map((s) =>
|
webhookBlocks.map((webhookBlock) =>
|
||||||
duplicateWebhookQuery({
|
duplicateWebhookQuery({
|
||||||
existingIds: { typebotId: typebot.id, webhookId: s.webhookId },
|
existingIds: {
|
||||||
|
typebotId: typebot.id,
|
||||||
|
webhookId: webhookBlock.webhookId as string,
|
||||||
|
},
|
||||||
newIds: {
|
newIds: {
|
||||||
typebotId: newTypebot.id,
|
typebotId: newTypebot.id,
|
||||||
webhookId: webhookIdsMapping.get(s.webhookId) as string,
|
webhookId: webhookIdsMapping.get(
|
||||||
|
webhookBlock.webhookId as string
|
||||||
|
) as string,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
@@ -51,84 +57,98 @@ const duplicateTypebot = (
|
|||||||
webhookIdsMapping: Map<string, string>
|
webhookIdsMapping: Map<string, string>
|
||||||
} => {
|
} => {
|
||||||
const groupIdsMapping = generateOldNewIdsMapping(typebot.groups)
|
const groupIdsMapping = generateOldNewIdsMapping(typebot.groups)
|
||||||
|
const blockIdsMapping = generateOldNewIdsMapping(
|
||||||
|
typebot.groups.flatMap((group) => group.blocks)
|
||||||
|
)
|
||||||
const edgeIdsMapping = generateOldNewIdsMapping(typebot.edges)
|
const edgeIdsMapping = generateOldNewIdsMapping(typebot.edges)
|
||||||
const webhookIdsMapping = generateOldNewIdsMapping(
|
const webhookIdsMapping = generateOldNewIdsMapping(
|
||||||
typebot.groups
|
typebot.groups
|
||||||
.flatMap((b) => b.blocks)
|
.flatMap((group) => group.blocks)
|
||||||
.filter(isWebhookBlock)
|
.filter(isWebhookBlock)
|
||||||
.map((s) => ({ id: s.webhookId }))
|
.map((block) => ({
|
||||||
|
id: block.webhookId as string,
|
||||||
|
}))
|
||||||
)
|
)
|
||||||
const id = createId()
|
const id = createId()
|
||||||
return {
|
return {
|
||||||
typebot: {
|
typebot: {
|
||||||
...typebot,
|
...typebot,
|
||||||
version: '3',
|
|
||||||
id,
|
id,
|
||||||
name: `${typebot.name} copy`,
|
name: `${typebot.name} copy`,
|
||||||
publicId: null,
|
publicId: null,
|
||||||
customDomain: null,
|
customDomain: null,
|
||||||
groups: typebot.groups.map((b) => ({
|
groups: typebot.groups.map((group) => ({
|
||||||
...b,
|
...group,
|
||||||
id: groupIdsMapping.get(b.id) as string,
|
id: groupIdsMapping.get(group.id) as string,
|
||||||
blocks: b.blocks.map((s) => {
|
blocks: group.blocks.map((block) => {
|
||||||
const newIds = {
|
const newIds = {
|
||||||
groupId: groupIdsMapping.get(s.groupId) as string,
|
id: blockIdsMapping.get(block.id) as string,
|
||||||
outgoingEdgeId: s.outgoingEdgeId
|
groupId: groupIdsMapping.get(block.groupId) as string,
|
||||||
? edgeIdsMapping.get(s.outgoingEdgeId)
|
outgoingEdgeId: block.outgoingEdgeId
|
||||||
|
? edgeIdsMapping.get(block.outgoingEdgeId)
|
||||||
: undefined,
|
: undefined,
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
s.type === LogicBlockType.TYPEBOT_LINK &&
|
block.type === LogicBlockType.TYPEBOT_LINK &&
|
||||||
s.options.typebotId === 'current' &&
|
block.options.typebotId === 'current' &&
|
||||||
isDefined(s.options.groupId)
|
isDefined(block.options.groupId)
|
||||||
)
|
)
|
||||||
return {
|
return {
|
||||||
...s,
|
...block,
|
||||||
|
...newIds,
|
||||||
options: {
|
options: {
|
||||||
...s.options,
|
...block.options,
|
||||||
groupId: groupIdsMapping.get(s.options.groupId as string),
|
groupId: groupIdsMapping.get(block.options.groupId as string),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if (s.type === LogicBlockType.JUMP)
|
if (block.type === LogicBlockType.JUMP)
|
||||||
return {
|
return {
|
||||||
...s,
|
...block,
|
||||||
|
...newIds,
|
||||||
options: {
|
options: {
|
||||||
...s.options,
|
...block.options,
|
||||||
groupId: groupIdsMapping.get(s.options.groupId as string),
|
groupId: groupIdsMapping.get(block.options.groupId as string),
|
||||||
} satisfies JumpBlock['options'],
|
} satisfies JumpBlock['options'],
|
||||||
}
|
}
|
||||||
if (blockHasItems(s))
|
if (blockHasItems(block))
|
||||||
return {
|
return {
|
||||||
...s,
|
...block,
|
||||||
items: s.items.map((item) => ({
|
...newIds,
|
||||||
|
items: block.items.map((item) => ({
|
||||||
...item,
|
...item,
|
||||||
outgoingEdgeId: item.outgoingEdgeId
|
outgoingEdgeId: item.outgoingEdgeId
|
||||||
? (edgeIdsMapping.get(item.outgoingEdgeId) as string)
|
? (edgeIdsMapping.get(item.outgoingEdgeId) as string)
|
||||||
: undefined,
|
: undefined,
|
||||||
})),
|
})),
|
||||||
...newIds,
|
|
||||||
} as ChoiceInputBlock | ConditionBlock
|
} as ChoiceInputBlock | ConditionBlock
|
||||||
if (isWebhookBlock(s)) {
|
if (isWebhookBlock(block) && block.webhookId) {
|
||||||
return {
|
return {
|
||||||
...s,
|
...block,
|
||||||
webhookId: webhookIdsMapping.get(s.webhookId) as string,
|
|
||||||
...newIds,
|
...newIds,
|
||||||
|
webhookId: webhookIdsMapping.get(block.webhookId) as string,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
...s,
|
...block,
|
||||||
...newIds,
|
...newIds,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
})),
|
})),
|
||||||
edges: typebot.edges.map((e) => ({
|
edges: typebot.edges.map((edge) => ({
|
||||||
...e,
|
...edge,
|
||||||
id: edgeIdsMapping.get(e.id) as string,
|
id: edgeIdsMapping.get(edge.id) as string,
|
||||||
from: {
|
from: {
|
||||||
...e.from,
|
...edge.from,
|
||||||
groupId: groupIdsMapping.get(e.from.groupId) as string,
|
blockId: blockIdsMapping.get(edge.from.blockId) as string,
|
||||||
|
groupId: groupIdsMapping.get(edge.from.groupId) as string,
|
||||||
|
},
|
||||||
|
to: {
|
||||||
|
...edge.to,
|
||||||
|
blockId: edge.to.blockId
|
||||||
|
? (blockIdsMapping.get(edge.to.blockId) as string)
|
||||||
|
: undefined,
|
||||||
|
groupId: groupIdsMapping.get(edge.to.groupId) as string,
|
||||||
},
|
},
|
||||||
to: { ...e.to, groupId: groupIdsMapping.get(e.to.groupId) as string },
|
|
||||||
})),
|
})),
|
||||||
settings:
|
settings:
|
||||||
typebot.settings.general.isBrandingEnabled === false &&
|
typebot.settings.general.isBrandingEnabled === false &&
|
||||||
|
|||||||
@@ -189,6 +189,7 @@ export const duplicateBlockDraft =
|
|||||||
} as Block
|
} as Block
|
||||||
if (isWebhookBlock(block)) {
|
if (isWebhookBlock(block)) {
|
||||||
const newWebhookId = createId()
|
const newWebhookId = createId()
|
||||||
|
if (block.webhookId)
|
||||||
onWebhookBlockDuplicated(block.webhookId, newWebhookId)
|
onWebhookBlockDuplicated(block.webhookId, newWebhookId)
|
||||||
return {
|
return {
|
||||||
...block,
|
...block,
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { createId } from '@paralleldrive/cuid2'
|
|||||||
import {
|
import {
|
||||||
isBubbleBlockType,
|
isBubbleBlockType,
|
||||||
blockTypeHasOption,
|
blockTypeHasOption,
|
||||||
blockTypeHasWebhook,
|
|
||||||
blockTypeHasItems,
|
blockTypeHasItems,
|
||||||
} from '@typebot.io/lib'
|
} from '@typebot.io/lib'
|
||||||
import {
|
import {
|
||||||
@@ -134,7 +133,7 @@ const parseDefaultBlockOptions = (type: BlockWithOptionsType): BlockOptions => {
|
|||||||
case IntegrationBlockType.PABBLY_CONNECT:
|
case IntegrationBlockType.PABBLY_CONNECT:
|
||||||
case IntegrationBlockType.MAKE_COM:
|
case IntegrationBlockType.MAKE_COM:
|
||||||
case IntegrationBlockType.WEBHOOK:
|
case IntegrationBlockType.WEBHOOK:
|
||||||
return defaultWebhookOptions
|
return defaultWebhookOptions(createId())
|
||||||
case IntegrationBlockType.EMAIL:
|
case IntegrationBlockType.EMAIL:
|
||||||
return defaultSendEmailOptions
|
return defaultSendEmailOptions
|
||||||
case IntegrationBlockType.CHATWOOT:
|
case IntegrationBlockType.CHATWOOT:
|
||||||
@@ -159,7 +158,6 @@ export const parseNewBlock = (
|
|||||||
options: blockTypeHasOption(type)
|
options: blockTypeHasOption(type)
|
||||||
? parseDefaultBlockOptions(type)
|
? parseDefaultBlockOptions(type)
|
||||||
: undefined,
|
: undefined,
|
||||||
webhookId: blockTypeHasWebhook(type) ? createId() : undefined,
|
|
||||||
items: blockTypeHasItems(type) ? parseDefaultItems(type, id) : undefined,
|
items: blockTypeHasItems(type) ? parseDefaultItems(type, id) : undefined,
|
||||||
} as DraggableBlock
|
} as DraggableBlock
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { isReadTypebotForbidden } from '@/features/typebot/helpers/isReadTypebot
|
|||||||
import { removeTypebotOldProperties } from '@/features/typebot/helpers/removeTypebotOldProperties'
|
import { removeTypebotOldProperties } from '@/features/typebot/helpers/removeTypebotOldProperties'
|
||||||
import { roundGroupsCoordinate } from '@/features/typebot/helpers/roundGroupsCoordinate'
|
import { roundGroupsCoordinate } from '@/features/typebot/helpers/roundGroupsCoordinate'
|
||||||
import { archiveResults } from '@typebot.io/lib/api/helpers/archiveResults'
|
import { archiveResults } from '@typebot.io/lib/api/helpers/archiveResults'
|
||||||
|
import { migrateTypebotFromV3ToV4 } from '@typebot.io/lib/migrations/migrateTypebotFromV3ToV4'
|
||||||
|
|
||||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
const user = await getAuthenticatedUser(req, res)
|
const user = await getAuthenticatedUser(req, res)
|
||||||
@@ -37,9 +38,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||||||
collaborators.find((c) => c.userId === user.id)?.type ===
|
collaborators.find((c) => c.userId === user.id)?.type ===
|
||||||
CollaborationType.READ
|
CollaborationType.READ
|
||||||
return res.send({
|
return res.send({
|
||||||
typebot: roundGroupsCoordinate(
|
typebot: await migrateTypebot(typebot as Typebot),
|
||||||
removeTypebotOldProperties(typebot) as Typebot
|
|
||||||
),
|
|
||||||
publishedTypebot,
|
publishedTypebot,
|
||||||
isReadOnly,
|
isReadOnly,
|
||||||
webhooks,
|
webhooks,
|
||||||
@@ -95,7 +94,6 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||||||
|
|
||||||
const updates = {
|
const updates = {
|
||||||
...omit(data, 'id', 'createdAt', 'updatedAt'),
|
...omit(data, 'id', 'createdAt', 'updatedAt'),
|
||||||
version: '3',
|
|
||||||
theme: data.theme ?? undefined,
|
theme: data.theme ?? undefined,
|
||||||
settings: data.settings ?? undefined,
|
settings: data.settings ?? undefined,
|
||||||
resultsTablePreferences: data.resultsTablePreferences ?? undefined,
|
resultsTablePreferences: data.resultsTablePreferences ?? undefined,
|
||||||
@@ -142,4 +140,12 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||||||
return methodNotAllowed(res)
|
return methodNotAllowed(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const migrateTypebot = async (typebot: Typebot): Promise<Typebot> => {
|
||||||
|
if (typebot.version === '4') return typebot
|
||||||
|
const updatedTypebot = roundGroupsCoordinate(
|
||||||
|
removeTypebotOldProperties(typebot) as Typebot
|
||||||
|
)
|
||||||
|
return migrateTypebotFromV3ToV4(prisma)(updatedTypebot)
|
||||||
|
}
|
||||||
|
|
||||||
export default handler
|
export default handler
|
||||||
|
|||||||
@@ -2797,6 +2797,83 @@
|
|||||||
},
|
},
|
||||||
"isExecutedOnClient": {
|
"isExecutedOnClient": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"webhook": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"queryParams": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"key": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"headers": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"key": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"method": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"POST",
|
||||||
|
"GET",
|
||||||
|
"PUT",
|
||||||
|
"DELETE",
|
||||||
|
"PATCH",
|
||||||
|
"HEAD",
|
||||||
|
"CONNECT",
|
||||||
|
"OPTIONS",
|
||||||
|
"TRACE"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"queryParams",
|
||||||
|
"headers",
|
||||||
|
"method"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
@@ -2806,15 +2883,15 @@
|
|||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
"webhookId": {
|
"webhookId": {
|
||||||
"type": "string"
|
"type": "string",
|
||||||
|
"description": "Deprecated, use webhook.id instead"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"id",
|
"id",
|
||||||
"groupId",
|
"groupId",
|
||||||
"type",
|
"type",
|
||||||
"options",
|
"options"
|
||||||
"webhookId"
|
|
||||||
],
|
],
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
@@ -3135,6 +3212,83 @@
|
|||||||
},
|
},
|
||||||
"isExecutedOnClient": {
|
"isExecutedOnClient": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"webhook": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"queryParams": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"key": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"headers": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"key": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"method": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"POST",
|
||||||
|
"GET",
|
||||||
|
"PUT",
|
||||||
|
"DELETE",
|
||||||
|
"PATCH",
|
||||||
|
"HEAD",
|
||||||
|
"CONNECT",
|
||||||
|
"OPTIONS",
|
||||||
|
"TRACE"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"queryParams",
|
||||||
|
"headers",
|
||||||
|
"method"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
@@ -3144,15 +3298,15 @@
|
|||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
"webhookId": {
|
"webhookId": {
|
||||||
"type": "string"
|
"type": "string",
|
||||||
|
"description": "Deprecated, use webhook.id instead"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"id",
|
"id",
|
||||||
"groupId",
|
"groupId",
|
||||||
"type",
|
"type",
|
||||||
"options",
|
"options"
|
||||||
"webhookId"
|
|
||||||
],
|
],
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
@@ -3303,6 +3457,83 @@
|
|||||||
},
|
},
|
||||||
"isExecutedOnClient": {
|
"isExecutedOnClient": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"webhook": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"queryParams": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"key": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"headers": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"key": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"method": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"POST",
|
||||||
|
"GET",
|
||||||
|
"PUT",
|
||||||
|
"DELETE",
|
||||||
|
"PATCH",
|
||||||
|
"HEAD",
|
||||||
|
"CONNECT",
|
||||||
|
"OPTIONS",
|
||||||
|
"TRACE"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"queryParams",
|
||||||
|
"headers",
|
||||||
|
"method"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
@@ -3312,15 +3543,15 @@
|
|||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
"webhookId": {
|
"webhookId": {
|
||||||
"type": "string"
|
"type": "string",
|
||||||
|
"description": "Deprecated, now integrated in webhook block options"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"id",
|
"id",
|
||||||
"groupId",
|
"groupId",
|
||||||
"type",
|
"type",
|
||||||
"options",
|
"options"
|
||||||
"webhookId"
|
|
||||||
],
|
],
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
@@ -3395,6 +3626,83 @@
|
|||||||
},
|
},
|
||||||
"isExecutedOnClient": {
|
"isExecutedOnClient": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"webhook": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"queryParams": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"key": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"headers": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"key": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"method": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"POST",
|
||||||
|
"GET",
|
||||||
|
"PUT",
|
||||||
|
"DELETE",
|
||||||
|
"PATCH",
|
||||||
|
"HEAD",
|
||||||
|
"CONNECT",
|
||||||
|
"OPTIONS",
|
||||||
|
"TRACE"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"queryParams",
|
||||||
|
"headers",
|
||||||
|
"method"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
@@ -3404,15 +3712,15 @@
|
|||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
"webhookId": {
|
"webhookId": {
|
||||||
"type": "string"
|
"type": "string",
|
||||||
|
"description": "Deprecated, use webhook.id instead"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"id",
|
"id",
|
||||||
"groupId",
|
"groupId",
|
||||||
"type",
|
"type",
|
||||||
"options",
|
"options"
|
||||||
"webhookId"
|
|
||||||
],
|
],
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
@@ -4528,6 +4836,15 @@
|
|||||||
"id": {
|
"id": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Webhook",
|
||||||
|
"Zapier",
|
||||||
|
"Make.com",
|
||||||
|
"Pabbly"
|
||||||
|
]
|
||||||
|
},
|
||||||
"label": {
|
"label": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
@@ -4537,6 +4854,7 @@
|
|||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"id",
|
"id",
|
||||||
|
"type",
|
||||||
"label"
|
"label"
|
||||||
],
|
],
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
|
|||||||
@@ -2365,6 +2365,83 @@
|
|||||||
},
|
},
|
||||||
"isExecutedOnClient": {
|
"isExecutedOnClient": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"webhook": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"queryParams": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"key": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"headers": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"key": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"method": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"POST",
|
||||||
|
"GET",
|
||||||
|
"PUT",
|
||||||
|
"DELETE",
|
||||||
|
"PATCH",
|
||||||
|
"HEAD",
|
||||||
|
"CONNECT",
|
||||||
|
"OPTIONS",
|
||||||
|
"TRACE"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"queryParams",
|
||||||
|
"headers",
|
||||||
|
"method"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
@@ -2374,15 +2451,15 @@
|
|||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
"webhookId": {
|
"webhookId": {
|
||||||
"type": "string"
|
"type": "string",
|
||||||
|
"description": "Deprecated, use webhook.id instead"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"id",
|
"id",
|
||||||
"groupId",
|
"groupId",
|
||||||
"type",
|
"type",
|
||||||
"options",
|
"options"
|
||||||
"webhookId"
|
|
||||||
],
|
],
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
@@ -2703,6 +2780,83 @@
|
|||||||
},
|
},
|
||||||
"isExecutedOnClient": {
|
"isExecutedOnClient": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"webhook": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"queryParams": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"key": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"headers": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"key": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"method": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"POST",
|
||||||
|
"GET",
|
||||||
|
"PUT",
|
||||||
|
"DELETE",
|
||||||
|
"PATCH",
|
||||||
|
"HEAD",
|
||||||
|
"CONNECT",
|
||||||
|
"OPTIONS",
|
||||||
|
"TRACE"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"queryParams",
|
||||||
|
"headers",
|
||||||
|
"method"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
@@ -2712,15 +2866,15 @@
|
|||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
"webhookId": {
|
"webhookId": {
|
||||||
"type": "string"
|
"type": "string",
|
||||||
|
"description": "Deprecated, use webhook.id instead"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"id",
|
"id",
|
||||||
"groupId",
|
"groupId",
|
||||||
"type",
|
"type",
|
||||||
"options",
|
"options"
|
||||||
"webhookId"
|
|
||||||
],
|
],
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
@@ -2871,6 +3025,83 @@
|
|||||||
},
|
},
|
||||||
"isExecutedOnClient": {
|
"isExecutedOnClient": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"webhook": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"queryParams": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"key": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"headers": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"key": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"method": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"POST",
|
||||||
|
"GET",
|
||||||
|
"PUT",
|
||||||
|
"DELETE",
|
||||||
|
"PATCH",
|
||||||
|
"HEAD",
|
||||||
|
"CONNECT",
|
||||||
|
"OPTIONS",
|
||||||
|
"TRACE"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"queryParams",
|
||||||
|
"headers",
|
||||||
|
"method"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
@@ -2880,15 +3111,15 @@
|
|||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
"webhookId": {
|
"webhookId": {
|
||||||
"type": "string"
|
"type": "string",
|
||||||
|
"description": "Deprecated, now integrated in webhook block options"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"id",
|
"id",
|
||||||
"groupId",
|
"groupId",
|
||||||
"type",
|
"type",
|
||||||
"options",
|
"options"
|
||||||
"webhookId"
|
|
||||||
],
|
],
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
@@ -2963,6 +3194,83 @@
|
|||||||
},
|
},
|
||||||
"isExecutedOnClient": {
|
"isExecutedOnClient": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"webhook": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"queryParams": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"key": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"headers": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"key": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"method": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"POST",
|
||||||
|
"GET",
|
||||||
|
"PUT",
|
||||||
|
"DELETE",
|
||||||
|
"PATCH",
|
||||||
|
"HEAD",
|
||||||
|
"CONNECT",
|
||||||
|
"OPTIONS",
|
||||||
|
"TRACE"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"queryParams",
|
||||||
|
"headers",
|
||||||
|
"method"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
@@ -2972,15 +3280,15 @@
|
|||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
"webhookId": {
|
"webhookId": {
|
||||||
"type": "string"
|
"type": "string",
|
||||||
|
"description": "Deprecated, use webhook.id instead"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"id",
|
"id",
|
||||||
"groupId",
|
"groupId",
|
||||||
"type",
|
"type",
|
||||||
"options",
|
"options"
|
||||||
"webhookId"
|
|
||||||
],
|
],
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
@@ -3524,7 +3832,7 @@
|
|||||||
},
|
},
|
||||||
"isPreview": {
|
"isPreview": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "If set to `true`, it will start a Preview session with the unpublished bot and it won't be saved in the Results tab. You need to be authenticated for this to work."
|
"description": "If set to `true`, it will start a Preview session with the unpublished bot and it won't be saved in the Results tab. You need to be authenticated with a bearer token for this to work."
|
||||||
},
|
},
|
||||||
"resultId": {
|
"resultId": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -5808,7 +6116,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/session/{sessionId}/updateTypebot": {
|
"/sessions/{sessionId}/updateTypebot": {
|
||||||
"post": {
|
"post": {
|
||||||
"operationId": "updateTypebotInSession",
|
"operationId": "updateTypebotInSession",
|
||||||
"summary": "Update typebot in session",
|
"summary": "Update typebot in session",
|
||||||
|
|||||||
@@ -76,11 +76,40 @@ const nextConfig = {
|
|||||||
}))
|
}))
|
||||||
)
|
)
|
||||||
: []
|
: []
|
||||||
).concat({
|
).concat([
|
||||||
|
{
|
||||||
source: '/api/typebots/:typebotId/blocks/:blockId/storage/upload-url',
|
source: '/api/typebots/:typebotId/blocks/:blockId/storage/upload-url',
|
||||||
destination:
|
destination:
|
||||||
'/api/v1/typebots/:typebotId/blocks/:blockId/storage/upload-url',
|
'/api/v1/typebots/:typebotId/blocks/:blockId/storage/upload-url',
|
||||||
}),
|
},
|
||||||
|
{
|
||||||
|
source:
|
||||||
|
'/api/typebots/:typebotId/blocks/:blockId/steps/:stepId/sampleResult',
|
||||||
|
destination: `${process.env.NEXTAUTH_URL}/api/v1/typebots/:typebotId/webhookBlocks/:blockId/getResultExample`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: '/api/typebots/:typebotId/blocks/:blockId/sampleResult',
|
||||||
|
destination: `${process.env.NEXTAUTH_URL}/api/v1/typebots/:typebotId/webhookBlocks/:blockId/getResultExample`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source:
|
||||||
|
'/api/typebots/:typebotId/blocks/:blockId/steps/:stepId/unsubscribeWebhook',
|
||||||
|
destination: `${process.env.NEXTAUTH_URL}/api/v1/typebots/:typebotId/webhookBlocks/:blockId/unsubscribe`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: '/api/typebots/:typebotId/blocks/:blockId/unsubscribeWebhook',
|
||||||
|
destination: `${process.env.NEXTAUTH_URL}/api/v1/typebots/:typebotId/webhookBlocks/:blockId/unsubscribe`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source:
|
||||||
|
'/api/typebots/:typebotId/blocks/:blockId/steps/:stepId/subscribeWebhook',
|
||||||
|
destination: `${process.env.NEXTAUTH_URL}/api/v1/typebots/:typebotId/webhookBlocks/:blockId/subscribe`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: '/api/typebots/:typebotId/blocks/:blockId/subscribeWebhook',
|
||||||
|
destination: `${process.env.NEXTAUTH_URL}/api/v1/typebots/:typebotId/webhookBlocks/:blockId/subscribe`,
|
||||||
|
},
|
||||||
|
]),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import {
|
|||||||
WebhookResponse,
|
WebhookResponse,
|
||||||
WebhookOptions,
|
WebhookOptions,
|
||||||
defaultWebhookAttributes,
|
defaultWebhookAttributes,
|
||||||
HttpMethod,
|
|
||||||
PublicTypebot,
|
PublicTypebot,
|
||||||
KeyValue,
|
KeyValue,
|
||||||
ReplyLog,
|
ReplyLog,
|
||||||
@@ -26,6 +25,7 @@ import { parseSampleResult } from './parseSampleResult'
|
|||||||
import { ExecuteIntegrationResponse } from '@/features/chat/types'
|
import { ExecuteIntegrationResponse } from '@/features/chat/types'
|
||||||
import { parseVariables } from '@/features/variables/parseVariables'
|
import { parseVariables } from '@/features/variables/parseVariables'
|
||||||
import { resumeWebhookExecution } from './resumeWebhookExecution'
|
import { resumeWebhookExecution } from './resumeWebhookExecution'
|
||||||
|
import { HttpMethod } from '@typebot.io/schemas/features/blocks/integrations/webhook/enums'
|
||||||
|
|
||||||
type ParsedWebhook = ExecutableWebhook & {
|
type ParsedWebhook = ExecutableWebhook & {
|
||||||
basicAuth: { username?: string; password?: string }
|
basicAuth: { username?: string; password?: string }
|
||||||
@@ -38,9 +38,11 @@ export const executeWebhookBlock = async (
|
|||||||
): Promise<ExecuteIntegrationResponse> => {
|
): Promise<ExecuteIntegrationResponse> => {
|
||||||
const { typebot, result } = state
|
const { typebot, result } = state
|
||||||
const logs: ReplyLog[] = []
|
const logs: ReplyLog[] = []
|
||||||
const webhook = (await prisma.webhook.findUnique({
|
const webhook =
|
||||||
|
block.options.webhook ??
|
||||||
|
((await prisma.webhook.findUnique({
|
||||||
where: { id: block.webhookId },
|
where: { id: block.webhookId },
|
||||||
})) as Webhook | null
|
})) as Webhook | null)
|
||||||
if (!webhook) {
|
if (!webhook) {
|
||||||
logs.push({
|
logs.push({
|
||||||
status: 'error',
|
status: 'error',
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import test, { expect } from '@playwright/test'
|
import test, { expect } from '@playwright/test'
|
||||||
import { createId } from '@paralleldrive/cuid2'
|
import { createId } from '@paralleldrive/cuid2'
|
||||||
import { HttpMethod } from '@typebot.io/schemas'
|
import { HttpMethod } from '@typebot.io/schemas/features/blocks/integrations/webhook/enums'
|
||||||
import {
|
import {
|
||||||
createWebhook,
|
createWebhook,
|
||||||
importTypebotInDatabase,
|
importTypebotInDatabase,
|
||||||
|
|||||||
@@ -2,13 +2,14 @@ import { getTestAsset } from '@/test/utils/playwright'
|
|||||||
import test, { expect } from '@playwright/test'
|
import test, { expect } from '@playwright/test'
|
||||||
import { createId } from '@paralleldrive/cuid2'
|
import { createId } from '@paralleldrive/cuid2'
|
||||||
import prisma from '@/lib/prisma'
|
import prisma from '@/lib/prisma'
|
||||||
import { HttpMethod, SendMessageInput } from '@typebot.io/schemas'
|
import { SendMessageInput } from '@typebot.io/schemas'
|
||||||
import {
|
import {
|
||||||
createWebhook,
|
createWebhook,
|
||||||
deleteTypebots,
|
deleteTypebots,
|
||||||
deleteWebhooks,
|
deleteWebhooks,
|
||||||
importTypebotInDatabase,
|
importTypebotInDatabase,
|
||||||
} from '@typebot.io/lib/playwright/databaseActions'
|
} from '@typebot.io/lib/playwright/databaseActions'
|
||||||
|
import { HttpMethod } from '@typebot.io/schemas/features/blocks/integrations/webhook/enums'
|
||||||
|
|
||||||
test.afterEach(async () => {
|
test.afterEach(async () => {
|
||||||
await deleteWebhooks(['chat-webhook-id'])
|
await deleteWebhooks(['chat-webhook-id'])
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ const App = ({
|
|||||||
return <NotFoundPage />
|
return <NotFoundPage />
|
||||||
if (publishedTypebot.typebot.isClosed)
|
if (publishedTypebot.typebot.isClosed)
|
||||||
return <ErrorPage error={new Error('This bot is now closed')} />
|
return <ErrorPage error={new Error('This bot is now closed')} />
|
||||||
return publishedTypebot.version === '3' ? (
|
return publishedTypebot.version ? (
|
||||||
<TypebotPageV3
|
<TypebotPageV3
|
||||||
url={props.url}
|
url={props.url}
|
||||||
typebot={{
|
typebot={{
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import {
|
|||||||
WebhookOptions,
|
WebhookOptions,
|
||||||
WebhookResponse,
|
WebhookResponse,
|
||||||
WebhookBlock,
|
WebhookBlock,
|
||||||
HttpMethod,
|
|
||||||
} from '@typebot.io/schemas'
|
} from '@typebot.io/schemas'
|
||||||
import { NextApiRequest, NextApiResponse } from 'next'
|
import { NextApiRequest, NextApiResponse } from 'next'
|
||||||
import got, { Method, Headers, HTTPError } from 'got'
|
import got, { Method, Headers, HTTPError } from 'got'
|
||||||
@@ -25,6 +24,7 @@ import { fetchLinkedTypebots } from '@/features/blocks/logic/typebotLink/fetchLi
|
|||||||
import { getPreviouslyLinkedTypebots } from '@/features/blocks/logic/typebotLink/getPreviouslyLinkedTypebots'
|
import { getPreviouslyLinkedTypebots } from '@/features/blocks/logic/typebotLink/getPreviouslyLinkedTypebots'
|
||||||
import { saveErrorLog } from '@/features/logs/saveErrorLog'
|
import { saveErrorLog } from '@/features/logs/saveErrorLog'
|
||||||
import { saveSuccessLog } from '@/features/logs/saveSuccessLog'
|
import { saveSuccessLog } from '@/features/logs/saveSuccessLog'
|
||||||
|
import { HttpMethod } from '@typebot.io/schemas/features/blocks/integrations/webhook/enums'
|
||||||
|
|
||||||
const cors = initMiddleware(Cors())
|
const cors = initMiddleware(Cors())
|
||||||
|
|
||||||
@@ -49,7 +49,8 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||||||
const block = typebot.groups
|
const block = typebot.groups
|
||||||
.flatMap((g) => g.blocks)
|
.flatMap((g) => g.blocks)
|
||||||
.find(byId(blockId)) as WebhookBlock
|
.find(byId(blockId)) as WebhookBlock
|
||||||
const webhook = typebot.webhooks.find(byId(block.webhookId))
|
const webhook =
|
||||||
|
block.options.webhook ?? typebot.webhooks.find(byId(block.webhookId))
|
||||||
if (!webhook)
|
if (!webhook)
|
||||||
return res
|
return res
|
||||||
.status(404)
|
.status(404)
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
import { authenticateUser } from '@/helpers/authenticateUser'
|
|
||||||
import prisma from '@/lib/prisma'
|
|
||||||
import { Typebot } from '@typebot.io/schemas'
|
|
||||||
import { NextApiRequest, NextApiResponse } from 'next'
|
|
||||||
import { methodNotAllowed } from '@typebot.io/lib/api'
|
|
||||||
import { getPreviouslyLinkedTypebots } from '@/features/blocks/logic/typebotLink/getPreviouslyLinkedTypebots'
|
|
||||||
import { parseSampleResult } from '@/features/blocks/integrations/webhook/parseSampleResult'
|
|
||||||
|
|
||||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|
||||||
const user = await authenticateUser(req)
|
|
||||||
if (!user) return res.status(401).json({ message: 'Not authenticated' })
|
|
||||||
if (req.method === 'GET') {
|
|
||||||
const typebotId = req.query.typebotId as string
|
|
||||||
const blockId = req.query.blockId as string
|
|
||||||
const typebot = (await prisma.typebot.findFirst({
|
|
||||||
where: {
|
|
||||||
id: typebotId,
|
|
||||||
workspace: { members: { some: { userId: user.id } } },
|
|
||||||
},
|
|
||||||
})) as unknown as Typebot | undefined
|
|
||||||
if (!typebot) return res.status(400).send({ message: 'Typebot not found' })
|
|
||||||
const block = typebot.groups
|
|
||||||
.flatMap((g) => g.blocks)
|
|
||||||
.find((s) => s.id === blockId)
|
|
||||||
if (!block) return res.status(404).send({ message: 'Group not found' })
|
|
||||||
const linkedTypebots = await getPreviouslyLinkedTypebots({
|
|
||||||
isPreview: true,
|
|
||||||
typebots: [typebot],
|
|
||||||
user,
|
|
||||||
})([])
|
|
||||||
return res.send(
|
|
||||||
await parseSampleResult(typebot, linkedTypebots)(block.groupId, [])
|
|
||||||
)
|
|
||||||
}
|
|
||||||
methodNotAllowed(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default handler
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
import prisma from '@/lib/prisma'
|
|
||||||
import {
|
|
||||||
defaultWebhookAttributes,
|
|
||||||
ResultValues,
|
|
||||||
Typebot,
|
|
||||||
Variable,
|
|
||||||
Webhook,
|
|
||||||
WebhookOptions,
|
|
||||||
WebhookBlock,
|
|
||||||
} from '@typebot.io/schemas'
|
|
||||||
import { NextApiRequest, NextApiResponse } from 'next'
|
|
||||||
import { initMiddleware, methodNotAllowed, notFound } from '@typebot.io/lib/api'
|
|
||||||
import { byId } from '@typebot.io/lib'
|
|
||||||
import Cors from 'cors'
|
|
||||||
import { executeWebhook } from '../../executeWebhook'
|
|
||||||
|
|
||||||
const cors = initMiddleware(Cors())
|
|
||||||
|
|
||||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|
||||||
await cors(req, res)
|
|
||||||
if (req.method === 'POST') {
|
|
||||||
const typebotId = req.query.typebotId as string
|
|
||||||
const groupId = req.query.groupId as string
|
|
||||||
const blockId = req.query.blockId as string
|
|
||||||
const resultId = req.query.resultId as string | undefined
|
|
||||||
const { resultValues, variables, parentTypebotIds } = (
|
|
||||||
typeof req.body === 'string' ? JSON.parse(req.body) : req.body
|
|
||||||
) as {
|
|
||||||
resultValues: ResultValues
|
|
||||||
variables: Variable[]
|
|
||||||
parentTypebotIds: string[]
|
|
||||||
}
|
|
||||||
const typebot = (await prisma.typebot.findUnique({
|
|
||||||
where: { id: typebotId },
|
|
||||||
include: { webhooks: true },
|
|
||||||
})) as unknown as (Typebot & { webhooks: Webhook[] }) | null
|
|
||||||
if (!typebot) return notFound(res)
|
|
||||||
const block = typebot.groups
|
|
||||||
.find(byId(groupId))
|
|
||||||
?.blocks.find(byId(blockId)) as WebhookBlock
|
|
||||||
const webhook = typebot.webhooks.find(byId(block.webhookId))
|
|
||||||
if (!webhook)
|
|
||||||
return res
|
|
||||||
.status(404)
|
|
||||||
.send({ statusCode: 404, data: { message: `Couldn't find webhook` } })
|
|
||||||
const preparedWebhook = prepareWebhookAttributes(webhook, block.options)
|
|
||||||
const result = await executeWebhook(typebot)({
|
|
||||||
webhook: preparedWebhook,
|
|
||||||
variables,
|
|
||||||
groupId,
|
|
||||||
resultValues,
|
|
||||||
resultId,
|
|
||||||
parentTypebotIds,
|
|
||||||
})
|
|
||||||
return res.status(200).send(result)
|
|
||||||
}
|
|
||||||
return methodNotAllowed(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
const prepareWebhookAttributes = (
|
|
||||||
webhook: Webhook,
|
|
||||||
options: WebhookOptions
|
|
||||||
): Webhook => {
|
|
||||||
if (options.isAdvancedConfig === false) {
|
|
||||||
return { ...webhook, body: '{{state}}', ...defaultWebhookAttributes }
|
|
||||||
} else if (options.isCustomBody === false) {
|
|
||||||
return { ...webhook, body: '{{state}}' }
|
|
||||||
}
|
|
||||||
return webhook
|
|
||||||
}
|
|
||||||
|
|
||||||
export default handler
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
import prisma from '@/lib/prisma'
|
|
||||||
import { Typebot } from '@typebot.io/schemas'
|
|
||||||
import { NextApiRequest, NextApiResponse } from 'next'
|
|
||||||
import { methodNotAllowed } from '@typebot.io/lib/api'
|
|
||||||
import { parseSampleResult } from '@/features/blocks/integrations/webhook/parseSampleResult'
|
|
||||||
import { getPreviouslyLinkedTypebots } from '@/features/blocks/logic/typebotLink/getPreviouslyLinkedTypebots'
|
|
||||||
import { authenticateUser } from '@/helpers/authenticateUser'
|
|
||||||
|
|
||||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|
||||||
const user = await authenticateUser(req)
|
|
||||||
if (!user) return res.status(401).json({ message: 'Not authenticated' })
|
|
||||||
if (req.method === 'GET') {
|
|
||||||
const typebotId = req.query.typebotId as string
|
|
||||||
const groupId = req.query.groupId as string
|
|
||||||
const typebot = (await prisma.typebot.findFirst({
|
|
||||||
where: {
|
|
||||||
id: typebotId,
|
|
||||||
workspace: { members: { some: { userId: user.id } } },
|
|
||||||
},
|
|
||||||
})) as unknown as Typebot | undefined
|
|
||||||
if (!typebot) return res.status(400).send({ message: 'Typebot not found' })
|
|
||||||
const linkedTypebots = await getPreviouslyLinkedTypebots({
|
|
||||||
isPreview: true,
|
|
||||||
typebots: [typebot],
|
|
||||||
user,
|
|
||||||
})([])
|
|
||||||
return res.send(
|
|
||||||
await parseSampleResult(typebot, linkedTypebots)(groupId, [])
|
|
||||||
)
|
|
||||||
}
|
|
||||||
methodNotAllowed(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default handler
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
import { Typebot, WebhookBlock } from '@typebot.io/schemas'
|
|
||||||
import { NextApiRequest, NextApiResponse } from 'next'
|
|
||||||
import { methodNotAllowed } from '@typebot.io/lib/api'
|
|
||||||
import { byId } from '@typebot.io/lib'
|
|
||||||
import prisma from '@/lib/prisma'
|
|
||||||
import { authenticateUser } from '@/helpers/authenticateUser'
|
|
||||||
|
|
||||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|
||||||
const user = await authenticateUser(req)
|
|
||||||
if (!user) return res.status(401).json({ message: 'Not authenticated' })
|
|
||||||
if (req.method === 'POST') {
|
|
||||||
const body = req.body as Record<string, string>
|
|
||||||
if (!('url' in body))
|
|
||||||
return res.status(403).send({ message: 'url is missing in body' })
|
|
||||||
const { url } = body
|
|
||||||
const typebotId = req.query.typebotId as string
|
|
||||||
const groupId = req.query.groupId as string
|
|
||||||
const blockId = req.query.blockId as string
|
|
||||||
const typebot = (await prisma.typebot.findFirst({
|
|
||||||
where: {
|
|
||||||
id: typebotId,
|
|
||||||
workspace: { members: { some: { userId: user.id } } },
|
|
||||||
},
|
|
||||||
})) as unknown as Typebot | undefined
|
|
||||||
if (!typebot) return res.status(400).send({ message: 'Typebot not found' })
|
|
||||||
try {
|
|
||||||
const { webhookId } = typebot.groups
|
|
||||||
.find(byId(groupId))
|
|
||||||
?.blocks.find(byId(blockId)) as WebhookBlock
|
|
||||||
await prisma.webhook.upsert({
|
|
||||||
where: { id: webhookId },
|
|
||||||
update: { url, body: '{{state}}', method: 'POST' },
|
|
||||||
create: {
|
|
||||||
url,
|
|
||||||
body: '{{state}}',
|
|
||||||
method: 'POST',
|
|
||||||
typebotId,
|
|
||||||
headers: [],
|
|
||||||
queryParams: [],
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
return res.send({ message: 'success' })
|
|
||||||
} catch (err) {
|
|
||||||
return res
|
|
||||||
.status(400)
|
|
||||||
.send({ message: "blockId doesn't point to a Webhook block" })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return methodNotAllowed(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default handler
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
import { Typebot, WebhookBlock } from '@typebot.io/schemas'
|
|
||||||
import { NextApiRequest, NextApiResponse } from 'next'
|
|
||||||
import { methodNotAllowed } from '@typebot.io/lib/api'
|
|
||||||
import { byId } from '@typebot.io/lib'
|
|
||||||
import { authenticateUser } from '@/helpers/authenticateUser'
|
|
||||||
import prisma from '@/lib/prisma'
|
|
||||||
|
|
||||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|
||||||
const user = await authenticateUser(req)
|
|
||||||
if (!user) return res.status(401).json({ message: 'Not authenticated' })
|
|
||||||
if (req.method === 'POST') {
|
|
||||||
const typebotId = req.query.typebotId as string
|
|
||||||
const groupId = req.query.groupId as string
|
|
||||||
const blockId = req.query.blockId as string
|
|
||||||
const typebot = (await prisma.typebot.findFirst({
|
|
||||||
where: {
|
|
||||||
id: typebotId,
|
|
||||||
workspace: { members: { some: { userId: user.id } } },
|
|
||||||
},
|
|
||||||
})) as unknown as Typebot | undefined
|
|
||||||
if (!typebot) return res.status(400).send({ message: 'Typebot not found' })
|
|
||||||
try {
|
|
||||||
const { webhookId } = typebot.groups
|
|
||||||
.find(byId(groupId))
|
|
||||||
?.blocks.find(byId(blockId)) as WebhookBlock
|
|
||||||
await prisma.webhook.updateMany({
|
|
||||||
where: { id: webhookId },
|
|
||||||
data: { url: null },
|
|
||||||
})
|
|
||||||
|
|
||||||
return res.send({ message: 'success' })
|
|
||||||
} catch (err) {
|
|
||||||
return res
|
|
||||||
.status(400)
|
|
||||||
.send({ message: "blockId doesn't point to a Webhook block" })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return methodNotAllowed(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default handler
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
import { authenticateUser } from '@/helpers/authenticateUser'
|
|
||||||
import prisma from '@/lib/prisma'
|
|
||||||
import { Typebot, WebhookBlock } from '@typebot.io/schemas'
|
|
||||||
import { NextApiRequest, NextApiResponse } from 'next'
|
|
||||||
import { byId } from '@typebot.io/lib'
|
|
||||||
import { methodNotAllowed } from '@typebot.io/lib/api'
|
|
||||||
|
|
||||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|
||||||
const user = await authenticateUser(req)
|
|
||||||
if (!user) return res.status(401).json({ message: 'Not authenticated' })
|
|
||||||
if (req.method === 'POST') {
|
|
||||||
const body = req.body as Record<string, string>
|
|
||||||
if (!('url' in body))
|
|
||||||
return res.status(403).send({ message: 'url is missing in body' })
|
|
||||||
const { url } = body
|
|
||||||
const typebotId = req.query.typebotId as string
|
|
||||||
const blockId = req.query.blockId as string
|
|
||||||
const typebot = (await prisma.typebot.findFirst({
|
|
||||||
where: {
|
|
||||||
id: typebotId,
|
|
||||||
workspace: { members: { some: { userId: user.id } } },
|
|
||||||
},
|
|
||||||
})) as unknown as Typebot | undefined
|
|
||||||
if (!typebot) return res.status(400).send({ message: 'Typebot not found' })
|
|
||||||
try {
|
|
||||||
const { webhookId } = typebot.groups
|
|
||||||
.flatMap((g) => g.blocks)
|
|
||||||
.find(byId(blockId)) as WebhookBlock
|
|
||||||
await prisma.webhook.upsert({
|
|
||||||
where: { id: webhookId },
|
|
||||||
update: { url, body: '{{state}}', method: 'POST' },
|
|
||||||
create: {
|
|
||||||
url,
|
|
||||||
body: '{{state}}',
|
|
||||||
method: 'POST',
|
|
||||||
typebotId,
|
|
||||||
headers: [],
|
|
||||||
queryParams: [],
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
return res.send({ message: 'success' })
|
|
||||||
} catch (err) {
|
|
||||||
return res
|
|
||||||
.status(400)
|
|
||||||
.send({ message: "groupId doesn't point to a Webhook block" })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return methodNotAllowed(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default handler
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
import { authenticateUser } from '@/helpers/authenticateUser'
|
|
||||||
import prisma from '@/lib/prisma'
|
|
||||||
import { Typebot, WebhookBlock } from '@typebot.io/schemas'
|
|
||||||
import { NextApiRequest, NextApiResponse } from 'next'
|
|
||||||
import { byId } from '@typebot.io/lib'
|
|
||||||
import { methodNotAllowed } from '@typebot.io/lib/api'
|
|
||||||
|
|
||||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|
||||||
const user = await authenticateUser(req)
|
|
||||||
if (!user) return res.status(401).json({ message: 'Not authenticated' })
|
|
||||||
if (req.method === 'POST') {
|
|
||||||
const typebotId = req.query.typebotId as string
|
|
||||||
const blockId = req.query.blockId as string
|
|
||||||
const typebot = (await prisma.typebot.findFirst({
|
|
||||||
where: {
|
|
||||||
id: typebotId,
|
|
||||||
workspace: { members: { some: { userId: user.id } } },
|
|
||||||
},
|
|
||||||
})) as unknown as Typebot | undefined
|
|
||||||
if (!typebot) return res.status(400).send({ message: 'Typebot not found' })
|
|
||||||
try {
|
|
||||||
const { webhookId } = typebot.groups
|
|
||||||
.flatMap((g) => g.blocks)
|
|
||||||
.find(byId(blockId)) as WebhookBlock
|
|
||||||
await prisma.webhook.updateMany({
|
|
||||||
where: { id: webhookId },
|
|
||||||
data: { url: null },
|
|
||||||
})
|
|
||||||
|
|
||||||
return res.send({ message: 'success' })
|
|
||||||
} catch (err) {
|
|
||||||
return res
|
|
||||||
.status(400)
|
|
||||||
.send({ message: "groupId doesn't point to a Webhook block" })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return methodNotAllowed(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default handler
|
|
||||||
@@ -105,7 +105,6 @@ export const ConversationContainer = (props: Props) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const streamMessage = (content: string) => {
|
const streamMessage = (content: string) => {
|
||||||
console.log('STREAM', content)
|
|
||||||
setIsSending(false)
|
setIsSending(false)
|
||||||
const lastChunk = [...chatChunks()].pop()
|
const lastChunk = [...chatChunks()].pop()
|
||||||
if (!lastChunk) return
|
if (!lastChunk) return
|
||||||
|
|||||||
63
packages/lib/migrations/migrateTypebotFromV3ToV4.ts
Normal file
63
packages/lib/migrations/migrateTypebotFromV3ToV4.ts
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import { PrismaClient, Webhook as WebhookFromDb } from '@typebot.io/prisma'
|
||||||
|
import {
|
||||||
|
Block,
|
||||||
|
Typebot,
|
||||||
|
Webhook,
|
||||||
|
defaultWebhookAttributes,
|
||||||
|
} from '@typebot.io/schemas'
|
||||||
|
import { isWebhookBlock } from '../utils'
|
||||||
|
import { HttpMethod } from '@typebot.io/schemas/features/blocks/integrations/webhook/enums'
|
||||||
|
|
||||||
|
export const migrateTypebotFromV3ToV4 =
|
||||||
|
(prisma: PrismaClient) =>
|
||||||
|
async (
|
||||||
|
typebot: Typebot
|
||||||
|
): Promise<Omit<Typebot, 'version'> & { version: '4' }> => {
|
||||||
|
if (typebot.version === '4')
|
||||||
|
return typebot as Omit<Typebot, 'version'> & { version: '4' }
|
||||||
|
const webhookBlocks = typebot.groups
|
||||||
|
.flatMap((group) => group.blocks)
|
||||||
|
.filter(isWebhookBlock)
|
||||||
|
const webhooks = await prisma.webhook.findMany({
|
||||||
|
where: {
|
||||||
|
id: {
|
||||||
|
in: webhookBlocks.map((block) => block.webhookId as string),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
...typebot,
|
||||||
|
version: '4',
|
||||||
|
groups: typebot.groups.map((group) => ({
|
||||||
|
...group,
|
||||||
|
blocks: group.blocks.map(migrateWebhookBlock(webhooks)),
|
||||||
|
})),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const migrateWebhookBlock =
|
||||||
|
(webhooks: WebhookFromDb[]) =>
|
||||||
|
(block: Block): Block => {
|
||||||
|
if (!isWebhookBlock(block)) return block
|
||||||
|
const webhook = webhooks.find((webhook) => webhook.id === block.webhookId)
|
||||||
|
return {
|
||||||
|
...block,
|
||||||
|
webhookId: undefined,
|
||||||
|
options: {
|
||||||
|
...block.options,
|
||||||
|
webhook: webhook
|
||||||
|
? {
|
||||||
|
id: webhook.id,
|
||||||
|
url: webhook.url ?? undefined,
|
||||||
|
method: (webhook.method as Webhook['method']) ?? HttpMethod.POST,
|
||||||
|
headers: (webhook.headers as Webhook['headers']) ?? [],
|
||||||
|
queryParams: (webhook.queryParams as Webhook['headers']) ?? [],
|
||||||
|
body: webhook.body ?? undefined,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
...defaultWebhookAttributes,
|
||||||
|
id: block.webhookId ?? '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -125,16 +125,6 @@ export const blockTypeHasOption = (
|
|||||||
.concat(Object.values(IntegrationBlockType))
|
.concat(Object.values(IntegrationBlockType))
|
||||||
.includes(type)
|
.includes(type)
|
||||||
|
|
||||||
export const blockTypeHasWebhook = (
|
|
||||||
type: BlockType
|
|
||||||
): type is IntegrationBlockType.WEBHOOK =>
|
|
||||||
Object.values([
|
|
||||||
IntegrationBlockType.WEBHOOK,
|
|
||||||
IntegrationBlockType.ZAPIER,
|
|
||||||
IntegrationBlockType.MAKE_COM,
|
|
||||||
IntegrationBlockType.PABBLY_CONNECT,
|
|
||||||
] as string[]).includes(type)
|
|
||||||
|
|
||||||
export const blockTypeHasItems = (
|
export const blockTypeHasItems = (
|
||||||
type: BlockType
|
type: BlockType
|
||||||
): type is
|
): type is
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ export * from './googleSheets'
|
|||||||
export * from './makeCom'
|
export * from './makeCom'
|
||||||
export * from './pabblyConnect'
|
export * from './pabblyConnect'
|
||||||
export * from './sendEmail'
|
export * from './sendEmail'
|
||||||
export * from './webhook'
|
export * from './webhook/schemas'
|
||||||
export * from './zapier'
|
export * from './zapier'
|
||||||
export * from './pixel/schemas'
|
export * from './pixel/schemas'
|
||||||
export * from './pixel/constants'
|
export * from './pixel/constants'
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { blockBaseSchema } from '../baseSchemas'
|
import { blockBaseSchema } from '../baseSchemas'
|
||||||
import { IntegrationBlockType } from './enums'
|
import { IntegrationBlockType } from './enums'
|
||||||
import { webhookOptionsSchema } from './webhook'
|
import { webhookOptionsSchema } from './webhook/schemas'
|
||||||
|
|
||||||
export const makeComBlockSchema = blockBaseSchema.merge(
|
export const makeComBlockSchema = blockBaseSchema.merge(
|
||||||
z.object({
|
z.object({
|
||||||
type: z.enum([IntegrationBlockType.MAKE_COM]),
|
type: z.enum([IntegrationBlockType.MAKE_COM]),
|
||||||
options: webhookOptionsSchema,
|
options: webhookOptionsSchema,
|
||||||
webhookId: z.string(),
|
webhookId: z
|
||||||
|
.string()
|
||||||
|
.describe('Deprecated, use webhook.id instead')
|
||||||
|
.optional(),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { blockBaseSchema } from '../baseSchemas'
|
import { blockBaseSchema } from '../baseSchemas'
|
||||||
import { IntegrationBlockType } from './enums'
|
import { IntegrationBlockType } from './enums'
|
||||||
import { webhookOptionsSchema } from './webhook'
|
import { webhookOptionsSchema } from './webhook/schemas'
|
||||||
|
|
||||||
export const pabblyConnectBlockSchema = blockBaseSchema.merge(
|
export const pabblyConnectBlockSchema = blockBaseSchema.merge(
|
||||||
z.object({
|
z.object({
|
||||||
type: z.enum([IntegrationBlockType.PABBLY_CONNECT]),
|
type: z.enum([IntegrationBlockType.PABBLY_CONNECT]),
|
||||||
options: webhookOptionsSchema,
|
options: webhookOptionsSchema,
|
||||||
webhookId: z.string(),
|
webhookId: z
|
||||||
|
.string()
|
||||||
|
.describe('Deprecated, use webhook.id instead')
|
||||||
|
.optional(),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,45 +0,0 @@
|
|||||||
import { z } from 'zod'
|
|
||||||
import { blockBaseSchema } from '../baseSchemas'
|
|
||||||
import { IntegrationBlockType } from './enums'
|
|
||||||
|
|
||||||
const variableForTestSchema = z.object({
|
|
||||||
id: z.string(),
|
|
||||||
variableId: z.string().optional(),
|
|
||||||
value: z.string().optional(),
|
|
||||||
})
|
|
||||||
|
|
||||||
const responseVariableMappingSchema = z.object({
|
|
||||||
id: z.string(),
|
|
||||||
variableId: z.string().optional(),
|
|
||||||
bodyPath: z.string().optional(),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const webhookOptionsSchema = z.object({
|
|
||||||
variablesForTest: z.array(variableForTestSchema),
|
|
||||||
responseVariableMapping: z.array(responseVariableMappingSchema),
|
|
||||||
isAdvancedConfig: z.boolean().optional(),
|
|
||||||
isCustomBody: z.boolean().optional(),
|
|
||||||
isExecutedOnClient: z.boolean().optional(),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const webhookBlockSchema = blockBaseSchema.merge(
|
|
||||||
z.object({
|
|
||||||
type: z.enum([IntegrationBlockType.WEBHOOK]),
|
|
||||||
options: webhookOptionsSchema,
|
|
||||||
webhookId: z.string(),
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
export const defaultWebhookOptions: Omit<WebhookOptions, 'webhookId'> = {
|
|
||||||
responseVariableMapping: [],
|
|
||||||
variablesForTest: [],
|
|
||||||
isAdvancedConfig: false,
|
|
||||||
isCustomBody: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
export type WebhookBlock = z.infer<typeof webhookBlockSchema>
|
|
||||||
export type WebhookOptions = z.infer<typeof webhookOptionsSchema>
|
|
||||||
export type ResponseVariableMapping = z.infer<
|
|
||||||
typeof responseVariableMappingSchema
|
|
||||||
>
|
|
||||||
export type VariableForTest = z.infer<typeof variableForTestSchema>
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
export enum HttpMethod {
|
||||||
|
POST = 'POST',
|
||||||
|
GET = 'GET',
|
||||||
|
PUT = 'PUT',
|
||||||
|
DELETE = 'DELETE',
|
||||||
|
PATCH = 'PATCH',
|
||||||
|
HEAD = 'HEAD',
|
||||||
|
CONNECT = 'CONNECT',
|
||||||
|
OPTIONS = 'OPTIONS',
|
||||||
|
TRACE = 'TRACE',
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
export * from './enums'
|
||||||
|
export * from './schemas'
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
import { z } from 'zod'
|
||||||
|
import { blockBaseSchema } from '../../baseSchemas'
|
||||||
|
import { IntegrationBlockType } from '../enums'
|
||||||
|
import { HttpMethod } from './enums'
|
||||||
|
|
||||||
|
const variableForTestSchema = z.object({
|
||||||
|
id: z.string(),
|
||||||
|
variableId: z.string().optional(),
|
||||||
|
value: z.string().optional(),
|
||||||
|
})
|
||||||
|
|
||||||
|
const responseVariableMappingSchema = z.object({
|
||||||
|
id: z.string(),
|
||||||
|
variableId: z.string().optional(),
|
||||||
|
bodyPath: z.string().optional(),
|
||||||
|
})
|
||||||
|
|
||||||
|
const keyValueSchema = z.object({
|
||||||
|
id: z.string(),
|
||||||
|
key: z.string().optional(),
|
||||||
|
value: z.string().optional(),
|
||||||
|
})
|
||||||
|
|
||||||
|
export const webhookSchema = z.object({
|
||||||
|
id: z.string(),
|
||||||
|
queryParams: keyValueSchema.array(),
|
||||||
|
headers: keyValueSchema.array(),
|
||||||
|
method: z.nativeEnum(HttpMethod),
|
||||||
|
url: z.string().optional(),
|
||||||
|
body: z.string().optional(),
|
||||||
|
})
|
||||||
|
|
||||||
|
export const webhookOptionsSchema = z.object({
|
||||||
|
variablesForTest: z.array(variableForTestSchema),
|
||||||
|
responseVariableMapping: z.array(responseVariableMappingSchema),
|
||||||
|
isAdvancedConfig: z.boolean().optional(),
|
||||||
|
isCustomBody: z.boolean().optional(),
|
||||||
|
isExecutedOnClient: z.boolean().optional(),
|
||||||
|
webhook: webhookSchema.optional(),
|
||||||
|
})
|
||||||
|
|
||||||
|
export const webhookBlockSchema = blockBaseSchema.merge(
|
||||||
|
z.object({
|
||||||
|
type: z.enum([IntegrationBlockType.WEBHOOK]),
|
||||||
|
options: webhookOptionsSchema,
|
||||||
|
webhookId: z
|
||||||
|
.string()
|
||||||
|
.describe('Deprecated, now integrated in webhook block options')
|
||||||
|
.optional(),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
export const defaultWebhookAttributes: Omit<
|
||||||
|
Webhook,
|
||||||
|
'id' | 'body' | 'url' | 'typebotId' | 'createdAt' | 'updatedAt'
|
||||||
|
> = {
|
||||||
|
method: HttpMethod.POST,
|
||||||
|
headers: [],
|
||||||
|
queryParams: [],
|
||||||
|
}
|
||||||
|
|
||||||
|
export const defaultWebhookOptions = (webhookId: string): WebhookOptions => ({
|
||||||
|
responseVariableMapping: [],
|
||||||
|
variablesForTest: [],
|
||||||
|
isAdvancedConfig: false,
|
||||||
|
isCustomBody: false,
|
||||||
|
webhook: {
|
||||||
|
id: webhookId,
|
||||||
|
...defaultWebhookAttributes,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export const executableWebhookSchema = z.object({
|
||||||
|
url: z.string(),
|
||||||
|
headers: z.record(z.string()).optional(),
|
||||||
|
body: z.unknown().optional(),
|
||||||
|
method: z.nativeEnum(HttpMethod).optional(),
|
||||||
|
})
|
||||||
|
|
||||||
|
export type KeyValue = { id: string; key?: string; value?: string }
|
||||||
|
|
||||||
|
export type WebhookResponse = {
|
||||||
|
statusCode: number
|
||||||
|
data?: unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ExecutableWebhook = z.infer<typeof executableWebhookSchema>
|
||||||
|
|
||||||
|
export type Webhook = z.infer<typeof webhookSchema>
|
||||||
|
export type WebhookBlock = z.infer<typeof webhookBlockSchema>
|
||||||
|
export type WebhookOptions = z.infer<typeof webhookOptionsSchema>
|
||||||
|
export type ResponseVariableMapping = z.infer<
|
||||||
|
typeof responseVariableMappingSchema
|
||||||
|
>
|
||||||
|
export type VariableForTest = z.infer<typeof variableForTestSchema>
|
||||||
@@ -1,13 +1,16 @@
|
|||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { blockBaseSchema } from '../baseSchemas'
|
import { blockBaseSchema } from '../baseSchemas'
|
||||||
import { IntegrationBlockType } from './enums'
|
import { IntegrationBlockType } from './enums'
|
||||||
import { webhookOptionsSchema } from './webhook'
|
import { webhookOptionsSchema } from './webhook/schemas'
|
||||||
|
|
||||||
export const zapierBlockSchema = blockBaseSchema.merge(
|
export const zapierBlockSchema = blockBaseSchema.merge(
|
||||||
z.object({
|
z.object({
|
||||||
type: z.enum([IntegrationBlockType.ZAPIER]),
|
type: z.enum([IntegrationBlockType.ZAPIER]),
|
||||||
options: webhookOptionsSchema,
|
options: webhookOptionsSchema,
|
||||||
webhookId: z.string(),
|
webhookId: z
|
||||||
|
.string()
|
||||||
|
.describe('Deprecated, use webhook.id instead')
|
||||||
|
.optional(),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import {
|
import {
|
||||||
|
executableWebhookSchema,
|
||||||
googleAnalyticsOptionsSchema,
|
googleAnalyticsOptionsSchema,
|
||||||
paymentInputRuntimeOptionsSchema,
|
paymentInputRuntimeOptionsSchema,
|
||||||
pixelOptionsSchema,
|
pixelOptionsSchema,
|
||||||
@@ -19,7 +20,6 @@ import { answerSchema } from './answer'
|
|||||||
import { BubbleBlockType } from './blocks/bubbles/enums'
|
import { BubbleBlockType } from './blocks/bubbles/enums'
|
||||||
import { inputBlockSchemas } from './blocks/schemas'
|
import { inputBlockSchemas } from './blocks/schemas'
|
||||||
import { chatCompletionMessageSchema } from './blocks/integrations/openai'
|
import { chatCompletionMessageSchema } from './blocks/integrations/openai'
|
||||||
import { executableWebhookSchema } from './webhooks'
|
|
||||||
|
|
||||||
const typebotInSessionStateSchema = publicTypebotSchema.pick({
|
const typebotInSessionStateSchema = publicTypebotSchema.pick({
|
||||||
id: true,
|
id: true,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { z } from 'zod'
|
|||||||
|
|
||||||
export const publicTypebotSchema = z.object({
|
export const publicTypebotSchema = z.object({
|
||||||
id: z.string(),
|
id: z.string(),
|
||||||
version: z.enum(['3']).nullable(),
|
version: z.enum(['3', '4']).nullable(),
|
||||||
createdAt: z.date(),
|
createdAt: z.date(),
|
||||||
updatedAt: z.date(),
|
updatedAt: z.date(),
|
||||||
typebotId: z.string(),
|
typebotId: z.string(),
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ const resultsTablePreferencesSchema = z.object({
|
|||||||
})
|
})
|
||||||
|
|
||||||
export const typebotSchema = z.object({
|
export const typebotSchema = z.object({
|
||||||
version: z.enum(['3']).nullable(),
|
version: z.enum(['3', '4']).nullable(),
|
||||||
id: z.string(),
|
id: z.string(),
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
groups: z.array(groupSchema),
|
groups: z.array(groupSchema),
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
import { Webhook as WebhookFromPrisma } from '@typebot.io/prisma'
|
|
||||||
import { z } from 'zod'
|
|
||||||
|
|
||||||
export enum HttpMethod {
|
|
||||||
POST = 'POST',
|
|
||||||
GET = 'GET',
|
|
||||||
PUT = 'PUT',
|
|
||||||
DELETE = 'DELETE',
|
|
||||||
PATCH = 'PATCH',
|
|
||||||
HEAD = 'HEAD',
|
|
||||||
CONNECT = 'CONNECT',
|
|
||||||
OPTIONS = 'OPTIONS',
|
|
||||||
TRACE = 'TRACE',
|
|
||||||
}
|
|
||||||
|
|
||||||
export type KeyValue = { id: string; key?: string; value?: string }
|
|
||||||
|
|
||||||
export type Webhook = Omit<
|
|
||||||
WebhookFromPrisma,
|
|
||||||
'queryParams' | 'headers' | 'method' | 'createdAt' | 'updatedAt'
|
|
||||||
> & {
|
|
||||||
queryParams: KeyValue[]
|
|
||||||
headers: KeyValue[]
|
|
||||||
method: HttpMethod
|
|
||||||
}
|
|
||||||
|
|
||||||
export type WebhookResponse = {
|
|
||||||
statusCode: number
|
|
||||||
data?: unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
export const defaultWebhookAttributes: Omit<
|
|
||||||
Webhook,
|
|
||||||
'id' | 'body' | 'url' | 'typebotId' | 'createdAt' | 'updatedAt'
|
|
||||||
> = {
|
|
||||||
method: HttpMethod.POST,
|
|
||||||
headers: [],
|
|
||||||
queryParams: [],
|
|
||||||
}
|
|
||||||
|
|
||||||
export const executableWebhookSchema = z.object({
|
|
||||||
url: z.string(),
|
|
||||||
headers: z.record(z.string()).optional(),
|
|
||||||
body: z.unknown().optional(),
|
|
||||||
method: z.nativeEnum(HttpMethod).optional(),
|
|
||||||
})
|
|
||||||
|
|
||||||
export type ExecutableWebhook = z.infer<typeof executableWebhookSchema>
|
|
||||||
@@ -5,7 +5,6 @@ export * from './features/result'
|
|||||||
export * from './features/answer'
|
export * from './features/answer'
|
||||||
export * from './features/utils'
|
export * from './features/utils'
|
||||||
export * from './features/credentials'
|
export * from './features/credentials'
|
||||||
export * from './features/webhooks'
|
|
||||||
export * from './features/chat'
|
export * from './features/chat'
|
||||||
export * from './features/workspace'
|
export * from './features/workspace'
|
||||||
export * from './features/items'
|
export * from './features/items'
|
||||||
|
|||||||
Reference in New Issue
Block a user