@nyaruka/temba-components 0.131.1 → 0.131.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (427) hide show
  1. package/.github/workflows/publish.yml +4 -1
  2. package/CHANGELOG.md +61 -1
  3. package/demo/data/flows/food-order.json +2 -2
  4. package/demo/data/flows/sample-flow.json +74 -125
  5. package/dist/static/svg/index.svg +1 -1
  6. package/dist/temba-components.js +1155 -618
  7. package/dist/temba-components.js.map +1 -1
  8. package/out-tsc/src/Icons.js +4 -1
  9. package/out-tsc/src/Icons.js.map +1 -1
  10. package/out-tsc/src/events.js.map +1 -1
  11. package/out-tsc/src/flow/CanvasMenu.js +200 -0
  12. package/out-tsc/src/flow/CanvasMenu.js.map +1 -0
  13. package/out-tsc/src/flow/CanvasNode.js +327 -19
  14. package/out-tsc/src/flow/CanvasNode.js.map +1 -1
  15. package/out-tsc/src/flow/Editor.js +562 -66
  16. package/out-tsc/src/flow/Editor.js.map +1 -1
  17. package/out-tsc/src/flow/NodeEditor.js +240 -93
  18. package/out-tsc/src/flow/NodeEditor.js.map +1 -1
  19. package/out-tsc/src/flow/NodeTypeSelector.js +499 -0
  20. package/out-tsc/src/flow/NodeTypeSelector.js.map +1 -0
  21. package/out-tsc/src/flow/actions/add_contact_groups.js +3 -3
  22. package/out-tsc/src/flow/actions/add_contact_groups.js.map +1 -1
  23. package/out-tsc/src/flow/actions/add_contact_urn.js +62 -4
  24. package/out-tsc/src/flow/actions/add_contact_urn.js.map +1 -1
  25. package/out-tsc/src/flow/actions/add_input_labels.js +3 -3
  26. package/out-tsc/src/flow/actions/add_input_labels.js.map +1 -1
  27. package/out-tsc/src/flow/actions/play_audio.js +2 -2
  28. package/out-tsc/src/flow/actions/play_audio.js.map +1 -1
  29. package/out-tsc/src/flow/actions/remove_contact_groups.js +6 -5
  30. package/out-tsc/src/flow/actions/remove_contact_groups.js.map +1 -1
  31. package/out-tsc/src/flow/actions/request_optin.js +2 -2
  32. package/out-tsc/src/flow/actions/request_optin.js.map +1 -1
  33. package/out-tsc/src/flow/actions/say_msg.js +2 -2
  34. package/out-tsc/src/flow/actions/say_msg.js.map +1 -1
  35. package/out-tsc/src/flow/actions/send_broadcast.js +76 -23
  36. package/out-tsc/src/flow/actions/send_broadcast.js.map +1 -1
  37. package/out-tsc/src/flow/actions/send_email.js +4 -5
  38. package/out-tsc/src/flow/actions/send_email.js.map +1 -1
  39. package/out-tsc/src/flow/actions/send_msg.js +9 -19
  40. package/out-tsc/src/flow/actions/send_msg.js.map +1 -1
  41. package/out-tsc/src/flow/actions/set_contact_channel.js +5 -9
  42. package/out-tsc/src/flow/actions/set_contact_channel.js.map +1 -1
  43. package/out-tsc/src/flow/actions/set_contact_field.js +19 -20
  44. package/out-tsc/src/flow/actions/set_contact_field.js.map +1 -1
  45. package/out-tsc/src/flow/actions/set_contact_language.js +2 -2
  46. package/out-tsc/src/flow/actions/set_contact_language.js.map +1 -1
  47. package/out-tsc/src/flow/actions/set_contact_name.js +2 -12
  48. package/out-tsc/src/flow/actions/set_contact_name.js.map +1 -1
  49. package/out-tsc/src/flow/actions/set_contact_status.js +2 -2
  50. package/out-tsc/src/flow/actions/set_contact_status.js.map +1 -1
  51. package/out-tsc/src/flow/actions/set_run_result.js +3 -3
  52. package/out-tsc/src/flow/actions/set_run_result.js.map +1 -1
  53. package/out-tsc/src/flow/actions/start_session.js +180 -6
  54. package/out-tsc/src/flow/actions/start_session.js.map +1 -1
  55. package/out-tsc/src/flow/config.js +11 -15
  56. package/out-tsc/src/flow/config.js.map +1 -1
  57. package/out-tsc/src/flow/currencies.js +45 -0
  58. package/out-tsc/src/flow/currencies.js.map +1 -0
  59. package/out-tsc/src/flow/nodes/shared-rules.js +257 -0
  60. package/out-tsc/src/flow/nodes/shared-rules.js.map +1 -0
  61. package/out-tsc/src/flow/nodes/shared.js +17 -0
  62. package/out-tsc/src/flow/nodes/shared.js.map +1 -0
  63. package/out-tsc/src/flow/nodes/split_by_airtime.js +205 -5
  64. package/out-tsc/src/flow/nodes/split_by_airtime.js.map +1 -1
  65. package/out-tsc/src/flow/nodes/split_by_contact_field.js +147 -3
  66. package/out-tsc/src/flow/nodes/split_by_contact_field.js.map +1 -1
  67. package/out-tsc/src/flow/nodes/split_by_expression.js +68 -2
  68. package/out-tsc/src/flow/nodes/split_by_expression.js.map +1 -1
  69. package/out-tsc/src/flow/nodes/split_by_groups.js +12 -9
  70. package/out-tsc/src/flow/nodes/split_by_groups.js.map +1 -1
  71. package/out-tsc/src/flow/nodes/split_by_intent.js +7 -0
  72. package/out-tsc/src/flow/nodes/split_by_intent.js.map +1 -0
  73. package/out-tsc/src/flow/nodes/split_by_llm.js +3 -2
  74. package/out-tsc/src/flow/nodes/split_by_llm.js.map +1 -1
  75. package/out-tsc/src/flow/nodes/split_by_llm_categorize.js +2 -2
  76. package/out-tsc/src/flow/nodes/split_by_llm_categorize.js.map +1 -1
  77. package/out-tsc/src/flow/nodes/split_by_random.js +3 -3
  78. package/out-tsc/src/flow/nodes/split_by_random.js.map +1 -1
  79. package/out-tsc/src/flow/nodes/split_by_resthook.js +108 -0
  80. package/out-tsc/src/flow/nodes/split_by_resthook.js.map +1 -0
  81. package/out-tsc/src/flow/nodes/split_by_run_result.js +206 -3
  82. package/out-tsc/src/flow/nodes/split_by_run_result.js.map +1 -1
  83. package/out-tsc/src/flow/nodes/split_by_scheme.js +153 -2
  84. package/out-tsc/src/flow/nodes/split_by_scheme.js.map +1 -1
  85. package/out-tsc/src/flow/nodes/split_by_subflow.js +6 -4
  86. package/out-tsc/src/flow/nodes/split_by_subflow.js.map +1 -1
  87. package/out-tsc/src/flow/nodes/split_by_ticket.js +3 -2
  88. package/out-tsc/src/flow/nodes/split_by_ticket.js.map +1 -1
  89. package/out-tsc/src/flow/nodes/split_by_webhook.js +3 -2
  90. package/out-tsc/src/flow/nodes/split_by_webhook.js.map +1 -1
  91. package/out-tsc/src/flow/nodes/wait_for_audio.js +2 -2
  92. package/out-tsc/src/flow/nodes/wait_for_audio.js.map +1 -1
  93. package/out-tsc/src/flow/nodes/wait_for_digits.js +2 -2
  94. package/out-tsc/src/flow/nodes/wait_for_digits.js.map +1 -1
  95. package/out-tsc/src/flow/nodes/wait_for_image.js +2 -2
  96. package/out-tsc/src/flow/nodes/wait_for_image.js.map +1 -1
  97. package/out-tsc/src/flow/nodes/wait_for_location.js +2 -2
  98. package/out-tsc/src/flow/nodes/wait_for_location.js.map +1 -1
  99. package/out-tsc/src/flow/nodes/wait_for_menu.js +2 -2
  100. package/out-tsc/src/flow/nodes/wait_for_menu.js.map +1 -1
  101. package/out-tsc/src/flow/nodes/wait_for_response.js +32 -567
  102. package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -1
  103. package/out-tsc/src/flow/nodes/wait_for_video.js +2 -2
  104. package/out-tsc/src/flow/nodes/wait_for_video.js.map +1 -1
  105. package/out-tsc/src/flow/types.js +71 -12
  106. package/out-tsc/src/flow/types.js.map +1 -1
  107. package/out-tsc/src/flow/utils.js +101 -14
  108. package/out-tsc/src/flow/utils.js.map +1 -1
  109. package/out-tsc/src/form/FieldRenderer.js +2 -4
  110. package/out-tsc/src/form/FieldRenderer.js.map +1 -1
  111. package/out-tsc/src/interfaces.js +3 -0
  112. package/out-tsc/src/interfaces.js.map +1 -1
  113. package/out-tsc/src/list/SortableList.js +98 -33
  114. package/out-tsc/src/list/SortableList.js.map +1 -1
  115. package/out-tsc/src/live/ContactChat.js +15 -18
  116. package/out-tsc/src/live/ContactChat.js.map +1 -1
  117. package/out-tsc/src/store/AppState.js +53 -0
  118. package/out-tsc/src/store/AppState.js.map +1 -1
  119. package/out-tsc/src/utils.js +254 -13
  120. package/out-tsc/src/utils.js.map +1 -1
  121. package/out-tsc/temba-modules.js +4 -0
  122. package/out-tsc/temba-modules.js.map +1 -1
  123. package/out-tsc/test/ActionHelper.js +3 -3
  124. package/out-tsc/test/ActionHelper.js.map +1 -1
  125. package/out-tsc/test/NodeHelper.js +6 -3
  126. package/out-tsc/test/NodeHelper.js.map +1 -1
  127. package/out-tsc/test/actions/add_contact_urn.test.js +202 -0
  128. package/out-tsc/test/actions/add_contact_urn.test.js.map +1 -0
  129. package/out-tsc/test/actions/send_broadcast.test.js +148 -0
  130. package/out-tsc/test/actions/send_broadcast.test.js.map +1 -0
  131. package/out-tsc/test/actions/send_email.test.js +17 -23
  132. package/out-tsc/test/actions/send_email.test.js.map +1 -1
  133. package/out-tsc/test/actions/send_msg.test.js +33 -15
  134. package/out-tsc/test/actions/send_msg.test.js.map +1 -1
  135. package/out-tsc/test/actions/start_session.test.js +116 -0
  136. package/out-tsc/test/actions/start_session.test.js.map +1 -0
  137. package/out-tsc/test/nodes/split_by_airtime.test.js +604 -0
  138. package/out-tsc/test/nodes/split_by_airtime.test.js.map +1 -0
  139. package/out-tsc/test/nodes/split_by_contact_field.test.js +387 -0
  140. package/out-tsc/test/nodes/split_by_contact_field.test.js.map +1 -0
  141. package/out-tsc/test/nodes/split_by_expression.test.js +614 -0
  142. package/out-tsc/test/nodes/split_by_expression.test.js.map +1 -0
  143. package/out-tsc/test/nodes/split_by_random.test.js +3 -3
  144. package/out-tsc/test/nodes/split_by_random.test.js.map +1 -1
  145. package/out-tsc/test/nodes/split_by_resthook.test.js +337 -0
  146. package/out-tsc/test/nodes/split_by_resthook.test.js.map +1 -0
  147. package/out-tsc/test/nodes/split_by_run_result.test.js +920 -0
  148. package/out-tsc/test/nodes/split_by_run_result.test.js.map +1 -0
  149. package/out-tsc/test/nodes/split_by_scheme.test.js +399 -0
  150. package/out-tsc/test/nodes/split_by_scheme.test.js.map +1 -0
  151. package/out-tsc/test/nodes/split_by_subflow.test.js +333 -0
  152. package/out-tsc/test/nodes/split_by_subflow.test.js.map +1 -0
  153. package/out-tsc/test/nodes/wait_for_digits.test.js +2 -2
  154. package/out-tsc/test/nodes/wait_for_digits.test.js.map +1 -1
  155. package/out-tsc/test/nodes/wait_for_response.test.js +2 -1
  156. package/out-tsc/test/nodes/wait_for_response.test.js.map +1 -1
  157. package/out-tsc/test/temba-action-drag-between-nodes.test.js +252 -0
  158. package/out-tsc/test/temba-action-drag-between-nodes.test.js.map +1 -0
  159. package/out-tsc/test/temba-canvas-menu.test.js +122 -0
  160. package/out-tsc/test/temba-canvas-menu.test.js.map +1 -0
  161. package/out-tsc/test/temba-flow-editor-node.test.js +85 -2
  162. package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
  163. package/out-tsc/test/temba-flow-editor.test.js +7 -8
  164. package/out-tsc/test/temba-flow-editor.test.js.map +1 -1
  165. package/out-tsc/test/temba-node-editor.test.js +3 -1
  166. package/out-tsc/test/temba-node-editor.test.js.map +1 -1
  167. package/out-tsc/test/temba-node-type-selector.test.js +115 -0
  168. package/out-tsc/test/temba-node-type-selector.test.js.map +1 -0
  169. package/out-tsc/test/temba-omnibox.test.js +2 -1
  170. package/out-tsc/test/temba-omnibox.test.js.map +1 -1
  171. package/out-tsc/test/temba-sortable-list.test.js +51 -0
  172. package/out-tsc/test/temba-sortable-list.test.js.map +1 -1
  173. package/out-tsc/test/temba-utils-index.test.js +1 -27
  174. package/out-tsc/test/temba-utils-index.test.js.map +1 -1
  175. package/out-tsc/test/utils.test.js +2 -0
  176. package/out-tsc/test/utils.test.js.map +1 -1
  177. package/package.json +2 -1
  178. package/screenshots/truth/actions/add_contact_groups/editor/descriptive-group-names.png +0 -0
  179. package/screenshots/truth/actions/add_contact_groups/editor/long-group-names.png +0 -0
  180. package/screenshots/truth/actions/add_contact_groups/editor/many-groups.png +0 -0
  181. package/screenshots/truth/actions/add_contact_groups/editor/multiple-groups.png +0 -0
  182. package/screenshots/truth/actions/add_contact_groups/editor/single-group.png +0 -0
  183. package/screenshots/truth/actions/add_contact_groups/render/descriptive-group-names.png +0 -0
  184. package/screenshots/truth/actions/add_contact_groups/render/long-group-names.png +0 -0
  185. package/screenshots/truth/actions/add_contact_groups/render/many-groups.png +0 -0
  186. package/screenshots/truth/actions/add_contact_groups/render/multiple-groups.png +0 -0
  187. package/screenshots/truth/actions/add_contact_groups/render/single-group.png +0 -0
  188. package/screenshots/truth/actions/add_contact_urn/editor/expression-facebook.png +0 -0
  189. package/screenshots/truth/actions/add_contact_urn/editor/expression-phone.png +0 -0
  190. package/screenshots/truth/actions/add_contact_urn/editor/facebook-id.png +0 -0
  191. package/screenshots/truth/actions/add_contact_urn/editor/instagram-handle.png +0 -0
  192. package/screenshots/truth/actions/add_contact_urn/editor/line-id.png +0 -0
  193. package/screenshots/truth/actions/add_contact_urn/editor/phone-number.png +0 -0
  194. package/screenshots/truth/actions/add_contact_urn/editor/telegram-id.png +0 -0
  195. package/screenshots/truth/actions/add_contact_urn/editor/viber-id.png +0 -0
  196. package/screenshots/truth/actions/add_contact_urn/editor/wechat-id.png +0 -0
  197. package/screenshots/truth/actions/add_contact_urn/editor/whatsapp.png +0 -0
  198. package/screenshots/truth/actions/add_contact_urn/render/expression-facebook.png +0 -0
  199. package/screenshots/truth/actions/add_contact_urn/render/expression-phone.png +0 -0
  200. package/screenshots/truth/actions/add_contact_urn/render/facebook-id.png +0 -0
  201. package/screenshots/truth/actions/add_contact_urn/render/instagram-handle.png +0 -0
  202. package/screenshots/truth/actions/add_contact_urn/render/line-id.png +0 -0
  203. package/screenshots/truth/actions/add_contact_urn/render/phone-number.png +0 -0
  204. package/screenshots/truth/actions/add_contact_urn/render/telegram-id.png +0 -0
  205. package/screenshots/truth/actions/add_contact_urn/render/viber-id.png +0 -0
  206. package/screenshots/truth/actions/add_contact_urn/render/wechat-id.png +0 -0
  207. package/screenshots/truth/actions/add_contact_urn/render/whatsapp.png +0 -0
  208. package/screenshots/truth/actions/remove_contact_groups/editor/cleanup-groups.png +0 -0
  209. package/screenshots/truth/actions/remove_contact_groups/editor/long-descriptive-group-names.png +0 -0
  210. package/screenshots/truth/actions/remove_contact_groups/editor/many-groups.png +0 -0
  211. package/screenshots/truth/actions/remove_contact_groups/editor/multiple-groups.png +0 -0
  212. package/screenshots/truth/actions/remove_contact_groups/editor/remove-from-all-groups.png +0 -0
  213. package/screenshots/truth/actions/remove_contact_groups/editor/single-group.png +0 -0
  214. package/screenshots/truth/actions/remove_contact_groups/render/cleanup-groups.png +0 -0
  215. package/screenshots/truth/actions/remove_contact_groups/render/long-descriptive-group-names.png +0 -0
  216. package/screenshots/truth/actions/remove_contact_groups/render/many-groups.png +0 -0
  217. package/screenshots/truth/actions/remove_contact_groups/render/multiple-groups.png +0 -0
  218. package/screenshots/truth/actions/remove_contact_groups/render/remove-from-all-groups.png +0 -0
  219. package/screenshots/truth/actions/remove_contact_groups/render/single-group.png +0 -0
  220. package/screenshots/truth/actions/send_broadcast/editor/contacts-only.png +0 -0
  221. package/screenshots/truth/actions/send_broadcast/editor/groups-and-contacts.png +0 -0
  222. package/screenshots/truth/actions/send_broadcast/editor/groups-only.png +0 -0
  223. package/screenshots/truth/actions/send_broadcast/editor/many-groups.png +0 -0
  224. package/screenshots/truth/actions/send_broadcast/editor/multiline-text.png +0 -0
  225. package/screenshots/truth/actions/send_broadcast/editor/with-attachments.png +0 -0
  226. package/screenshots/truth/actions/send_broadcast/render/contacts-only.png +0 -0
  227. package/screenshots/truth/actions/send_broadcast/render/groups-and-contacts.png +0 -0
  228. package/screenshots/truth/actions/send_broadcast/render/groups-only.png +0 -0
  229. package/screenshots/truth/actions/send_broadcast/render/many-groups.png +0 -0
  230. package/screenshots/truth/actions/send_broadcast/render/multiline-text.png +0 -0
  231. package/screenshots/truth/actions/send_broadcast/render/with-attachments.png +0 -0
  232. package/screenshots/truth/actions/send_email/editor/complex-business-email.png +0 -0
  233. package/screenshots/truth/actions/send_email/editor/empty-body.png +0 -0
  234. package/screenshots/truth/actions/send_email/editor/empty-subject.png +0 -0
  235. package/screenshots/truth/actions/send_email/editor/long-subject.png +0 -0
  236. package/screenshots/truth/actions/send_email/editor/multiline-body.png +0 -0
  237. package/screenshots/truth/actions/send_email/editor/multiple-recipients.png +0 -0
  238. package/screenshots/truth/actions/send_email/editor/simple-email.png +0 -0
  239. package/screenshots/truth/actions/send_email/editor/with-expressions.png +0 -0
  240. package/screenshots/truth/actions/send_email/render/complex-business-email.png +0 -0
  241. package/screenshots/truth/actions/send_email/render/empty-body.png +0 -0
  242. package/screenshots/truth/actions/send_email/render/empty-subject.png +0 -0
  243. package/screenshots/truth/actions/send_email/render/long-subject.png +0 -0
  244. package/screenshots/truth/actions/send_email/render/multiline-body.png +0 -0
  245. package/screenshots/truth/actions/send_email/render/multiple-recipients.png +0 -0
  246. package/screenshots/truth/actions/send_email/render/simple-email.png +0 -0
  247. package/screenshots/truth/actions/send_email/render/with-expressions.png +0 -0
  248. package/screenshots/truth/actions/send_msg/editor/long-quick-replies.png +0 -0
  249. package/screenshots/truth/actions/send_msg/editor/multiline-text-with-replies.png +0 -0
  250. package/screenshots/truth/actions/send_msg/editor/simple-text.png +0 -0
  251. package/screenshots/truth/actions/send_msg/editor/text-with-linebreaks.png +0 -0
  252. package/screenshots/truth/actions/send_msg/editor/text-with-many-quick-replies.png +0 -0
  253. package/screenshots/truth/actions/send_msg/editor/text-with-quick-replies.png +0 -0
  254. package/screenshots/truth/actions/send_msg/editor/text-without-quick-replies.png +0 -0
  255. package/screenshots/truth/actions/send_msg/render/long-quick-replies.png +0 -0
  256. package/screenshots/truth/actions/send_msg/render/multiline-text-with-replies.png +0 -0
  257. package/screenshots/truth/actions/send_msg/render/simple-text.png +0 -0
  258. package/screenshots/truth/actions/send_msg/render/text-with-linebreaks.png +0 -0
  259. package/screenshots/truth/actions/send_msg/render/text-with-many-quick-replies.png +0 -0
  260. package/screenshots/truth/actions/send_msg/render/text-with-quick-replies.png +0 -0
  261. package/screenshots/truth/actions/send_msg/render/text-without-quick-replies.png +0 -0
  262. package/screenshots/truth/actions/start_session/editor/contact-query.png +0 -0
  263. package/screenshots/truth/actions/start_session/editor/contacts-only.png +0 -0
  264. package/screenshots/truth/actions/start_session/editor/create-contact.png +0 -0
  265. package/screenshots/truth/actions/start_session/editor/groups-and-contacts.png +0 -0
  266. package/screenshots/truth/actions/start_session/editor/groups-only.png +0 -0
  267. package/screenshots/truth/actions/start_session/editor/many-recipients.png +0 -0
  268. package/screenshots/truth/actions/start_session/render/contact-query.png +0 -0
  269. package/screenshots/truth/actions/start_session/render/contacts-only.png +0 -0
  270. package/screenshots/truth/actions/start_session/render/create-contact.png +0 -0
  271. package/screenshots/truth/actions/start_session/render/groups-and-contacts.png +0 -0
  272. package/screenshots/truth/actions/start_session/render/groups-only.png +0 -0
  273. package/screenshots/truth/actions/start_session/render/many-recipients.png +0 -0
  274. package/screenshots/truth/canvas-menu/open.png +0 -0
  275. package/screenshots/truth/editor/router.png +0 -0
  276. package/screenshots/truth/editor/wait.png +0 -0
  277. package/screenshots/truth/list/fields-dragging.png +0 -0
  278. package/screenshots/truth/list/sortable-dragging.png +0 -0
  279. package/screenshots/truth/node-type-selector/action-mode.png +0 -0
  280. package/screenshots/truth/node-type-selector/split-mode.png +0 -0
  281. package/screenshots/truth/nodes/split_by_llm/editor/information-extraction.png +0 -0
  282. package/screenshots/truth/nodes/split_by_llm/editor/sentiment-analysis.png +0 -0
  283. package/screenshots/truth/nodes/split_by_llm/editor/summarization.png +0 -0
  284. package/screenshots/truth/nodes/split_by_llm/editor/translation-task.png +0 -0
  285. package/screenshots/truth/nodes/split_by_llm/render/information-extraction.png +0 -0
  286. package/screenshots/truth/nodes/split_by_llm/render/sentiment-analysis.png +0 -0
  287. package/screenshots/truth/nodes/split_by_llm/render/summarization.png +0 -0
  288. package/screenshots/truth/nodes/split_by_llm/render/translation-task.png +0 -0
  289. package/screenshots/truth/nodes/split_by_llm_categorize/editor/basic-categorization.png +0 -0
  290. package/screenshots/truth/nodes/split_by_llm_categorize/editor/custom-input-and-result-name.png +0 -0
  291. package/screenshots/truth/nodes/split_by_llm_categorize/editor/feedback-categorization.png +0 -0
  292. package/screenshots/truth/nodes/split_by_llm_categorize/editor/many-categories.png +0 -0
  293. package/screenshots/truth/nodes/split_by_llm_categorize/editor/minimal-categories.png +0 -0
  294. package/screenshots/truth/nodes/split_by_llm_categorize/render/basic-categorization.png +0 -0
  295. package/screenshots/truth/nodes/split_by_llm_categorize/render/custom-input-and-result-name.png +0 -0
  296. package/screenshots/truth/nodes/split_by_llm_categorize/render/feedback-categorization.png +0 -0
  297. package/screenshots/truth/nodes/split_by_llm_categorize/render/many-categories.png +0 -0
  298. package/screenshots/truth/nodes/split_by_llm_categorize/render/minimal-categories.png +0 -0
  299. package/screenshots/truth/nodes/split_by_random/editor/ab-test-multiple-variants.png +0 -0
  300. package/screenshots/truth/nodes/split_by_random/editor/sampling-split.png +0 -0
  301. package/screenshots/truth/nodes/split_by_random/editor/three-way-split.png +0 -0
  302. package/screenshots/truth/nodes/split_by_random/editor/two-bucket-split.png +0 -0
  303. package/screenshots/truth/nodes/split_by_random/render/ab-test-multiple-variants.png +0 -0
  304. package/screenshots/truth/nodes/split_by_random/render/sampling-split.png +0 -0
  305. package/screenshots/truth/nodes/split_by_random/render/three-way-split.png +0 -0
  306. package/screenshots/truth/nodes/split_by_random/render/two-bucket-split.png +0 -0
  307. package/screenshots/truth/nodes/wait_for_digits/editor/basic-digits-wait.png +0 -0
  308. package/screenshots/truth/nodes/wait_for_digits/editor/phone-number-collection.png +0 -0
  309. package/screenshots/truth/nodes/wait_for_digits/editor/single-digit-with-timeout.png +0 -0
  310. package/screenshots/truth/nodes/wait_for_digits/editor/verification-code.png +0 -0
  311. package/screenshots/truth/nodes/wait_for_digits/render/basic-digits-wait.png +0 -0
  312. package/screenshots/truth/nodes/wait_for_digits/render/phone-number-collection.png +0 -0
  313. package/screenshots/truth/nodes/wait_for_digits/render/single-digit-with-timeout.png +0 -0
  314. package/screenshots/truth/nodes/wait_for_digits/render/verification-code.png +0 -0
  315. package/screenshots/truth/nodes/wait_for_response/editor/basic-wait.png +0 -0
  316. package/screenshots/truth/nodes/wait_for_response/editor/custom-result-name.png +0 -0
  317. package/screenshots/truth/nodes/wait_for_response/editor/no-timeout.png +0 -0
  318. package/screenshots/truth/nodes/wait_for_response/editor/short-timeout.png +0 -0
  319. package/screenshots/truth/nodes/wait_for_response/render/basic-wait.png +0 -0
  320. package/screenshots/truth/nodes/wait_for_response/render/custom-result-name.png +0 -0
  321. package/screenshots/truth/nodes/wait_for_response/render/no-timeout.png +0 -0
  322. package/screenshots/truth/nodes/wait_for_response/render/short-timeout.png +0 -0
  323. package/src/Icons.ts +4 -1
  324. package/src/events.ts +2 -6
  325. package/src/flow/CanvasMenu.ts +217 -0
  326. package/src/flow/CanvasNode.ts +408 -10
  327. package/src/flow/Editor.ts +683 -44
  328. package/src/flow/NodeEditor.ts +304 -125
  329. package/src/flow/NodeTypeSelector.ts +592 -0
  330. package/src/flow/actions/add_contact_groups.ts +4 -4
  331. package/src/flow/actions/add_contact_urn.ts +76 -4
  332. package/src/flow/actions/add_input_labels.ts +4 -4
  333. package/src/flow/actions/play_audio.ts +2 -2
  334. package/src/flow/actions/remove_contact_groups.ts +14 -6
  335. package/src/flow/actions/request_optin.ts +2 -2
  336. package/src/flow/actions/say_msg.ts +2 -2
  337. package/src/flow/actions/send_broadcast.ts +85 -23
  338. package/src/flow/actions/send_email.ts +10 -6
  339. package/src/flow/actions/send_msg.ts +22 -32
  340. package/src/flow/actions/set_contact_channel.ts +5 -11
  341. package/src/flow/actions/set_contact_field.ts +20 -25
  342. package/src/flow/actions/set_contact_language.ts +9 -4
  343. package/src/flow/actions/set_contact_name.ts +3 -15
  344. package/src/flow/actions/set_contact_status.ts +3 -3
  345. package/src/flow/actions/set_run_result.ts +4 -4
  346. package/src/flow/actions/start_session.ts +208 -6
  347. package/src/flow/config.ts +13 -15
  348. package/src/flow/currencies.ts +51 -0
  349. package/src/flow/nodes/shared-rules.ts +301 -0
  350. package/src/flow/nodes/shared.ts +18 -0
  351. package/src/flow/nodes/split_by_airtime.ts +238 -5
  352. package/src/flow/nodes/split_by_contact_field.ts +185 -3
  353. package/src/flow/nodes/split_by_expression.ts +94 -2
  354. package/src/flow/nodes/split_by_groups.ts +15 -10
  355. package/src/flow/nodes/split_by_intent.ts +7 -0
  356. package/src/flow/nodes/split_by_llm.ts +4 -3
  357. package/src/flow/nodes/split_by_llm_categorize.ts +4 -4
  358. package/src/flow/nodes/split_by_random.ts +5 -5
  359. package/src/flow/nodes/split_by_resthook.ts +130 -0
  360. package/src/flow/nodes/split_by_run_result.ts +249 -3
  361. package/src/flow/nodes/split_by_scheme.ts +192 -2
  362. package/src/flow/nodes/split_by_subflow.ts +6 -4
  363. package/src/flow/nodes/split_by_ticket.ts +4 -3
  364. package/src/flow/nodes/split_by_webhook.ts +6 -5
  365. package/src/flow/nodes/wait_for_audio.ts +2 -2
  366. package/src/flow/nodes/wait_for_digits.ts +2 -2
  367. package/src/flow/nodes/wait_for_image.ts +2 -2
  368. package/src/flow/nodes/wait_for_location.ts +2 -2
  369. package/src/flow/nodes/wait_for_menu.ts +2 -2
  370. package/src/flow/nodes/wait_for_response.ts +48 -679
  371. package/src/flow/nodes/wait_for_video.ts +2 -2
  372. package/src/flow/types.ts +109 -23
  373. package/src/flow/utils.ts +108 -14
  374. package/src/form/FieldRenderer.ts +2 -4
  375. package/src/interfaces.ts +3 -0
  376. package/src/list/SortableList.ts +109 -34
  377. package/src/live/ContactChat.ts +15 -18
  378. package/src/store/AppState.ts +69 -0
  379. package/src/store/flow-definition.d.ts +2 -5
  380. package/src/utils.ts +332 -12
  381. package/static/api/channels.json +46 -0
  382. package/static/api/resthooks.json +31 -0
  383. package/static/svg/index.svg +1 -1
  384. package/static/svg/work/traced/lightning-02.svg +1 -0
  385. package/static/svg/work/used/lightning-02.svg +3 -0
  386. package/temba-modules.ts +4 -0
  387. package/test/ActionHelper.ts +3 -3
  388. package/test/NodeHelper.ts +6 -3
  389. package/test/actions/add_contact_urn.test.ts +287 -0
  390. package/test/actions/send_broadcast.test.ts +190 -0
  391. package/test/actions/send_email.test.ts +17 -23
  392. package/test/actions/send_msg.test.ts +39 -15
  393. package/test/actions/start_session.test.ts +151 -0
  394. package/test/nodes/split_by_airtime.test.ts +673 -0
  395. package/test/nodes/split_by_contact_field.test.ts +451 -0
  396. package/test/nodes/split_by_expression.test.ts +751 -0
  397. package/test/nodes/split_by_random.test.ts +3 -3
  398. package/test/nodes/split_by_resthook.test.ts +398 -0
  399. package/test/nodes/split_by_run_result.test.ts +1109 -0
  400. package/test/nodes/split_by_scheme.test.ts +486 -0
  401. package/test/nodes/split_by_subflow.test.ts +381 -0
  402. package/test/nodes/wait_for_digits.test.ts +2 -2
  403. package/test/nodes/wait_for_response.test.ts +2 -1
  404. package/test/temba-action-drag-between-nodes.test.ts +301 -0
  405. package/test/temba-canvas-menu.test.ts +156 -0
  406. package/test/temba-flow-editor-node.test.ts +102 -2
  407. package/test/temba-flow-editor.test.ts +7 -8
  408. package/test/temba-node-editor.test.ts +3 -1
  409. package/test/temba-node-type-selector.test.ts +152 -0
  410. package/test/temba-omnibox.test.ts +2 -1
  411. package/test/temba-sortable-list.test.ts +69 -0
  412. package/test/temba-utils-index.test.ts +0 -35
  413. package/test/utils.test.ts +2 -0
  414. package/test-assets/contacts/history.json +14 -20
  415. package/web-dev-server.config.mjs +3 -1
  416. package/out-tsc/src/flow/actions/call_classifier.js +0 -11
  417. package/out-tsc/src/flow/actions/call_classifier.js.map +0 -1
  418. package/out-tsc/src/flow/actions/call_resthook.js +0 -11
  419. package/out-tsc/src/flow/actions/call_resthook.js.map +0 -1
  420. package/out-tsc/src/flow/actions/split_by_expression_example.js +0 -77
  421. package/out-tsc/src/flow/actions/split_by_expression_example.js.map +0 -1
  422. package/out-tsc/src/flow/actions/transfer_airtime.js +0 -11
  423. package/out-tsc/src/flow/actions/transfer_airtime.js.map +0 -1
  424. package/src/flow/actions/call_classifier.ts +0 -12
  425. package/src/flow/actions/call_resthook.ts +0 -12
  426. package/src/flow/actions/split_by_expression_example.ts +0 -88
  427. package/src/flow/actions/transfer_airtime.ts +0 -12
@@ -0,0 +1,108 @@
1
+ import { ACTION_GROUPS } from '../types';
2
+ import { generateUUID, createSuccessFailureRouter } from '../../utils';
3
+ import { html } from 'lit';
4
+ import { resultNameField } from './shared';
5
+ export const split_by_resthook = {
6
+ type: 'split_by_resthook',
7
+ name: 'Call Resthook',
8
+ group: ACTION_GROUPS.services,
9
+ showAsAction: true,
10
+ form: {
11
+ resthook: {
12
+ type: 'select',
13
+ label: 'Resthook',
14
+ required: true,
15
+ searchable: true,
16
+ clearable: false,
17
+ placeholder: 'Select a resthook...',
18
+ endpoint: '/api/v2/resthooks.json',
19
+ valueKey: 'resthook',
20
+ nameKey: 'resthook',
21
+ helpText: 'Select the resthook to call'
22
+ },
23
+ result_name: resultNameField
24
+ },
25
+ layout: ['resthook', 'result_name'],
26
+ validate: (formData) => {
27
+ const errors = {};
28
+ // validate resthook is provided
29
+ if (!formData.resthook || formData.resthook.length === 0) {
30
+ errors.resthook = 'A resthook is required';
31
+ }
32
+ return {
33
+ valid: Object.keys(errors).length === 0,
34
+ errors
35
+ };
36
+ },
37
+ render: (node) => {
38
+ var _a;
39
+ const callResthookAction = (_a = node.actions) === null || _a === void 0 ? void 0 : _a.find((action) => action.type === 'call_resthook');
40
+ return html `
41
+ <div
42
+ class="body"
43
+ style="word-wrap: break-word; overflow-wrap: break-word; hyphens: auto;"
44
+ >
45
+ ${(callResthookAction === null || callResthookAction === void 0 ? void 0 : callResthookAction.resthook) || 'Configure resthook'}
46
+ </div>
47
+ `;
48
+ },
49
+ toFormData: (node) => {
50
+ var _a, _b;
51
+ // extract data from the existing node structure
52
+ const callResthookAction = (_a = node.actions) === null || _a === void 0 ? void 0 : _a.find((action) => action.type === 'call_resthook');
53
+ return {
54
+ uuid: node.uuid,
55
+ resthook: (callResthookAction === null || callResthookAction === void 0 ? void 0 : callResthookAction.resthook)
56
+ ? [
57
+ {
58
+ resthook: callResthookAction.resthook
59
+ }
60
+ ]
61
+ : [],
62
+ result_name: ((_b = node.router) === null || _b === void 0 ? void 0 : _b.result_name) || ''
63
+ };
64
+ },
65
+ fromFormData: (formData, originalNode) => {
66
+ var _a, _b, _c;
67
+ // get resthook selection
68
+ const resthookSelection = Array.isArray(formData.resthook) && formData.resthook.length > 0
69
+ ? formData.resthook[0]
70
+ : null;
71
+ if (!resthookSelection) {
72
+ return originalNode;
73
+ }
74
+ // find existing call_resthook action to preserve its UUID
75
+ const existingCallResthookAction = (_a = originalNode.actions) === null || _a === void 0 ? void 0 : _a.find((action) => action.type === 'call_resthook');
76
+ const callResthookUuid = (existingCallResthookAction === null || existingCallResthookAction === void 0 ? void 0 : existingCallResthookAction.uuid) || generateUUID();
77
+ // create call_resthook action
78
+ const callResthookAction = {
79
+ type: 'call_resthook',
80
+ uuid: callResthookUuid,
81
+ resthook: resthookSelection.resthook
82
+ };
83
+ // create categories and exits for Success and Failure
84
+ const existingCategories = ((_b = originalNode.router) === null || _b === void 0 ? void 0 : _b.categories) || [];
85
+ const existingExits = originalNode.exits || [];
86
+ const existingCases = ((_c = originalNode.router) === null || _c === void 0 ? void 0 : _c.cases) || [];
87
+ const { router, exits } = createSuccessFailureRouter('@webhook.json.status', {
88
+ type: 'has_text',
89
+ arguments: []
90
+ }, existingCategories, existingExits, existingCases);
91
+ // Build final router with result_name
92
+ const finalRouter = {
93
+ ...router
94
+ };
95
+ // Only set result_name if provided
96
+ if (formData.result_name && formData.result_name.trim() !== '') {
97
+ finalRouter.result_name = formData.result_name.trim();
98
+ }
99
+ // return the complete node
100
+ return {
101
+ uuid: originalNode.uuid,
102
+ actions: [callResthookAction],
103
+ router: finalRouter,
104
+ exits: exits
105
+ };
106
+ }
107
+ };
108
+ //# sourceMappingURL=split_by_resthook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"split_by_resthook.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_resthook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAwB,MAAM,UAAU,CAAC;AAE/D,OAAO,EAAE,YAAY,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAC3B,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C,MAAM,CAAC,MAAM,iBAAiB,GAAe;IAC3C,IAAI,EAAE,mBAAmB;IACzB,IAAI,EAAE,eAAe;IACrB,KAAK,EAAE,aAAa,CAAC,QAAQ;IAC7B,YAAY,EAAE,IAAI;IAClB,IAAI,EAAE;QACJ,QAAQ,EAAE;YACR,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,UAAU;YACjB,QAAQ,EAAE,IAAI;YACd,UAAU,EAAE,IAAI;YAChB,SAAS,EAAE,KAAK;YAChB,WAAW,EAAE,sBAAsB;YACnC,QAAQ,EAAE,wBAAwB;YAClC,QAAQ,EAAE,UAAU;YACpB,OAAO,EAAE,UAAU;YACnB,QAAQ,EAAE,6BAA6B;SACxC;QACD,WAAW,EAAE,eAAe;KAC7B;IACD,MAAM,EAAE,CAAC,UAAU,EAAE,aAAa,CAAC;IACnC,QAAQ,EAAE,CAAC,QAAkB,EAAE,EAAE;QAC/B,MAAM,MAAM,GAA8B,EAAE,CAAC;QAE7C,gCAAgC;QAChC,IAAI,CAAC,QAAQ,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzD,MAAM,CAAC,QAAQ,GAAG,wBAAwB,CAAC;QAC7C,CAAC;QAED,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC;YACvC,MAAM;SACP,CAAC;IACJ,CAAC;IACD,MAAM,EAAE,CAAC,IAAU,EAAE,EAAE;;QACrB,MAAM,kBAAkB,GAAG,MAAA,IAAI,CAAC,OAAO,0CAAE,IAAI,CAC3C,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,eAAe,CAC5B,CAAC;QAClB,OAAO,IAAI,CAAA;;;;;UAKL,CAAA,kBAAkB,aAAlB,kBAAkB,uBAAlB,kBAAkB,CAAE,QAAQ,KAAI,oBAAoB;;KAEzD,CAAC;IACJ,CAAC;IACD,UAAU,EAAE,CAAC,IAAU,EAAE,EAAE;;QACzB,gDAAgD;QAChD,MAAM,kBAAkB,GAAG,MAAA,IAAI,CAAC,OAAO,0CAAE,IAAI,CAC3C,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,eAAe,CAC5B,CAAC;QAElB,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,QAAQ,EAAE,CAAA,kBAAkB,aAAlB,kBAAkB,uBAAlB,kBAAkB,CAAE,QAAQ;gBACpC,CAAC,CAAC;oBACE;wBACE,QAAQ,EAAE,kBAAkB,CAAC,QAAQ;qBACtC;iBACF;gBACH,CAAC,CAAC,EAAE;YACN,WAAW,EAAE,CAAA,MAAA,IAAI,CAAC,MAAM,0CAAE,WAAW,KAAI,EAAE;SAC5C,CAAC;IACJ,CAAC;IACD,YAAY,EAAE,CAAC,QAAkB,EAAE,YAAkB,EAAQ,EAAE;;QAC7D,yBAAyB;QACzB,MAAM,iBAAiB,GACrB,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;YAC9D,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;YACtB,CAAC,CAAC,IAAI,CAAC;QAEX,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvB,OAAO,YAAY,CAAC;QACtB,CAAC;QAED,0DAA0D;QAC1D,MAAM,0BAA0B,GAAG,MAAA,YAAY,CAAC,OAAO,0CAAE,IAAI,CAC3D,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,eAAe,CAC5C,CAAC;QACF,MAAM,gBAAgB,GAAG,CAAA,0BAA0B,aAA1B,0BAA0B,uBAA1B,0BAA0B,CAAE,IAAI,KAAI,YAAY,EAAE,CAAC;QAE5E,8BAA8B;QAC9B,MAAM,kBAAkB,GAAiB;YACvC,IAAI,EAAE,eAAe;YACrB,IAAI,EAAE,gBAAgB;YACtB,QAAQ,EAAE,iBAAiB,CAAC,QAAQ;SACrC,CAAC;QAEF,sDAAsD;QACtD,MAAM,kBAAkB,GAAG,CAAA,MAAA,YAAY,CAAC,MAAM,0CAAE,UAAU,KAAI,EAAE,CAAC;QACjE,MAAM,aAAa,GAAG,YAAY,CAAC,KAAK,IAAI,EAAE,CAAC;QAC/C,MAAM,aAAa,GAAG,CAAA,MAAA,YAAY,CAAC,MAAM,0CAAE,KAAK,KAAI,EAAE,CAAC;QAEvD,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,0BAA0B,CAClD,sBAAsB,EACtB;YACE,IAAI,EAAE,UAAU;YAChB,SAAS,EAAE,EAAE;SACd,EACD,kBAAkB,EAClB,aAAa,EACb,aAAa,CACd,CAAC;QAEF,sCAAsC;QACtC,MAAM,WAAW,GAAQ;YACvB,GAAG,MAAM;SACV,CAAC;QAEF,mCAAmC;QACnC,IAAI,QAAQ,CAAC,WAAW,IAAI,QAAQ,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAC/D,WAAW,CAAC,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;QACxD,CAAC;QAED,2BAA2B;QAC3B,OAAO;YACL,IAAI,EAAE,YAAY,CAAC,IAAI;YACvB,OAAO,EAAE,CAAC,kBAAkB,CAAC;YAC7B,MAAM,EAAE,WAAW;YACnB,KAAK,EAAE,KAAK;SACb,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import { ACTION_GROUPS, FormData, NodeConfig } from '../types';\nimport { CallResthook, Node } from '../../store/flow-definition';\nimport { generateUUID, createSuccessFailureRouter } from '../../utils';\nimport { html } from 'lit';\nimport { resultNameField } from './shared';\n\nexport const split_by_resthook: NodeConfig = {\n type: 'split_by_resthook',\n name: 'Call Resthook',\n group: ACTION_GROUPS.services,\n showAsAction: true,\n form: {\n resthook: {\n type: 'select',\n label: 'Resthook',\n required: true,\n searchable: true,\n clearable: false,\n placeholder: 'Select a resthook...',\n endpoint: '/api/v2/resthooks.json',\n valueKey: 'resthook',\n nameKey: 'resthook',\n helpText: 'Select the resthook to call'\n },\n result_name: resultNameField\n },\n layout: ['resthook', 'result_name'],\n validate: (formData: FormData) => {\n const errors: { [key: string]: string } = {};\n\n // validate resthook is provided\n if (!formData.resthook || formData.resthook.length === 0) {\n errors.resthook = 'A resthook is required';\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n render: (node: Node) => {\n const callResthookAction = node.actions?.find(\n (action) => action.type === 'call_resthook'\n ) as CallResthook;\n return html`\n <div\n class=\"body\"\n style=\"word-wrap: break-word; overflow-wrap: break-word; hyphens: auto;\"\n >\n ${callResthookAction?.resthook || 'Configure resthook'}\n </div>\n `;\n },\n toFormData: (node: Node) => {\n // extract data from the existing node structure\n const callResthookAction = node.actions?.find(\n (action) => action.type === 'call_resthook'\n ) as CallResthook;\n\n return {\n uuid: node.uuid,\n resthook: callResthookAction?.resthook\n ? [\n {\n resthook: callResthookAction.resthook\n }\n ]\n : [],\n result_name: node.router?.result_name || ''\n };\n },\n fromFormData: (formData: FormData, originalNode: Node): Node => {\n // get resthook selection\n const resthookSelection =\n Array.isArray(formData.resthook) && formData.resthook.length > 0\n ? formData.resthook[0]\n : null;\n\n if (!resthookSelection) {\n return originalNode;\n }\n\n // find existing call_resthook action to preserve its UUID\n const existingCallResthookAction = originalNode.actions?.find(\n (action) => action.type === 'call_resthook'\n );\n const callResthookUuid = existingCallResthookAction?.uuid || generateUUID();\n\n // create call_resthook action\n const callResthookAction: CallResthook = {\n type: 'call_resthook',\n uuid: callResthookUuid,\n resthook: resthookSelection.resthook\n };\n\n // create categories and exits for Success and Failure\n const existingCategories = originalNode.router?.categories || [];\n const existingExits = originalNode.exits || [];\n const existingCases = originalNode.router?.cases || [];\n\n const { router, exits } = createSuccessFailureRouter(\n '@webhook.json.status',\n {\n type: 'has_text',\n arguments: []\n },\n existingCategories,\n existingExits,\n existingCases\n );\n\n // Build final router with result_name\n const finalRouter: any = {\n ...router\n };\n\n // Only set result_name if provided\n if (formData.result_name && formData.result_name.trim() !== '') {\n finalRouter.result_name = formData.result_name.trim();\n }\n\n // return the complete node\n return {\n uuid: originalNode.uuid,\n actions: [callResthookAction],\n router: finalRouter,\n exits: exits\n };\n }\n};\n"]}
@@ -1,7 +1,210 @@
1
- import { COLORS } from '../types';
1
+ import { SPLIT_GROUPS } from '../types';
2
+ import { createRulesRouter } from '../../utils';
3
+ import { getWaitForResponseOperators, operatorsToSelectOptions, getOperatorConfig } from '../operators';
4
+ import { resultNameField } from './shared';
5
+ import { createRulesArrayConfig, extractUserRules, casesToFormRules } from './shared-rules';
6
+ import { getStore } from '../../store/Store';
7
+ // delimit index options (first through 20th)
8
+ const DELIMIT_INDEX_OPTIONS = [
9
+ { value: '0', name: 'first result' },
10
+ { value: '1', name: 'second result' },
11
+ { value: '2', name: 'third result' },
12
+ { value: '3', name: 'fourth result' },
13
+ { value: '4', name: 'fifth result' },
14
+ { value: '5', name: 'sixth result' },
15
+ { value: '6', name: 'seventh result' },
16
+ { value: '7', name: 'eighth result' },
17
+ { value: '8', name: 'ninth result' },
18
+ { value: '9', name: 'tenth result' },
19
+ { value: '10', name: '11th result' },
20
+ { value: '11', name: '12th result' },
21
+ { value: '12', name: '13th result' },
22
+ { value: '13', name: '14th result' },
23
+ { value: '14', name: '15th result' },
24
+ { value: '15', name: '16th result' },
25
+ { value: '16', name: '17th result' },
26
+ { value: '17', name: '18th result' },
27
+ { value: '18', name: '19th result' },
28
+ { value: '19', name: '20th result' }
29
+ ];
30
+ // delimit by options - includes "don't delimit" and delimiter characters
31
+ const DELIMIT_BY_OPTIONS = [
32
+ { value: '', name: "Don't delimit result" },
33
+ { value: ' ', name: 'Delimited by spaces' },
34
+ { value: '.', name: 'Delimited by periods' },
35
+ { value: '+', name: 'Delimited by plusses' }
36
+ ];
2
37
  export const split_by_run_result = {
3
38
  type: 'split_by_run_result',
4
- name: 'Split by Flow Result',
5
- color: COLORS.split
39
+ name: 'Split by Result',
40
+ group: SPLIT_GROUPS.split,
41
+ dialogSize: 'large',
42
+ form: {
43
+ result: {
44
+ type: 'select',
45
+ required: true,
46
+ searchable: false,
47
+ clearable: false,
48
+ placeholder: 'Select a result...',
49
+ getDynamicOptions: () => {
50
+ const store = getStore();
51
+ return store
52
+ ? store
53
+ .getState()
54
+ .getFlowResults()
55
+ .map((r) => ({ value: r.key, name: r.name }))
56
+ : [];
57
+ },
58
+ valueKey: 'value',
59
+ nameKey: 'name'
60
+ },
61
+ delimit_by: {
62
+ type: 'select',
63
+ required: false,
64
+ searchable: false,
65
+ clearable: false,
66
+ options: DELIMIT_BY_OPTIONS,
67
+ valueKey: 'value',
68
+ nameKey: 'name',
69
+ maxWidth: '180px'
70
+ },
71
+ delimit_index: {
72
+ type: 'select',
73
+ required: false,
74
+ searchable: false,
75
+ clearable: false,
76
+ options: DELIMIT_INDEX_OPTIONS,
77
+ valueKey: 'value',
78
+ nameKey: 'name',
79
+ maxWidth: '140px',
80
+ conditions: {
81
+ visible: (formData) => {
82
+ var _a, _b;
83
+ const delimitBy = (_b = (_a = formData.delimit_by) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.value;
84
+ return delimitBy !== undefined && delimitBy !== '';
85
+ }
86
+ }
87
+ },
88
+ rules: createRulesArrayConfig(operatorsToSelectOptions(getWaitForResponseOperators()), 'Define rules to categorize the result'),
89
+ result_name: resultNameField
90
+ },
91
+ layout: [
92
+ {
93
+ type: 'row',
94
+ label: 'Flow Result',
95
+ helpText: 'Select a flow result and optionally delimit it to split on a specific part',
96
+ items: ['result', 'delimit_by', 'delimit_index']
97
+ },
98
+ 'rules',
99
+ 'result_name'
100
+ ],
101
+ validate: (formData) => {
102
+ const errors = {};
103
+ // Validate result is provided
104
+ if (!formData.result || formData.result.length === 0) {
105
+ errors.result = 'A flow result is required';
106
+ }
107
+ return {
108
+ valid: Object.keys(errors).length === 0,
109
+ errors
110
+ };
111
+ },
112
+ toFormData: (node, nodeUI) => {
113
+ var _a, _b, _c;
114
+ // Get the result from the UI config operand (source of truth)
115
+ const result = (_a = nodeUI === null || nodeUI === void 0 ? void 0 : nodeUI.config) === null || _a === void 0 ? void 0 : _a.operand;
116
+ // Extract rules from router cases using shared function
117
+ const rules = casesToFormRules(node);
118
+ // Extract delimiter configuration by checking the actual operand string
119
+ // If operand contains field() function, we have a delimiter
120
+ const operand = ((_b = node.router) === null || _b === void 0 ? void 0 : _b.operand) || '';
121
+ const fieldFunctionMatch = operand.match(/field\(results\.[\w]+,\s*(\d+),\s*"(.+?)"\)/);
122
+ const hasDelimiter = fieldFunctionMatch !== null;
123
+ const delimitIndex = hasDelimiter
124
+ ? parseInt(fieldFunctionMatch[1], 10)
125
+ : 0;
126
+ const delimiter = hasDelimiter ? fieldFunctionMatch[2] : '';
127
+ return {
128
+ uuid: node.uuid,
129
+ result: result ? [result] : [],
130
+ delimit_by: hasDelimiter
131
+ ? [DELIMIT_BY_OPTIONS.find((opt) => opt.value === delimiter)]
132
+ : [DELIMIT_BY_OPTIONS[0]],
133
+ delimit_index: hasDelimiter
134
+ ? [
135
+ DELIMIT_INDEX_OPTIONS.find((opt) => opt.value === String(delimitIndex))
136
+ ]
137
+ : [DELIMIT_INDEX_OPTIONS[0]],
138
+ rules: rules,
139
+ result_name: ((_c = node.router) === null || _c === void 0 ? void 0 : _c.result_name) || ''
140
+ };
141
+ },
142
+ fromFormData: (formData, originalNode) => {
143
+ var _a, _b, _c, _d, _e, _f, _g, _h;
144
+ // Get selected result (it's an array from the select component)
145
+ const selectedResult = (_a = formData.result) === null || _a === void 0 ? void 0 : _a[0];
146
+ if (!selectedResult) {
147
+ return originalNode;
148
+ }
149
+ // Build operand based on whether delimiter is selected
150
+ let operand;
151
+ const delimitBy = (_c = (_b = formData.delimit_by) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.value;
152
+ const hasDelimiter = delimitBy !== undefined && delimitBy !== '';
153
+ if (hasDelimiter) {
154
+ // Get delimiter configuration
155
+ const delimitIndex = (_f = (_e = (_d = formData.delimit_index) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.value) !== null && _f !== void 0 ? _f : '0';
156
+ // Build operand with field() function
157
+ operand = `@(field(results.${selectedResult.value}, ${delimitIndex}, "${delimitBy}"))`;
158
+ }
159
+ else {
160
+ // Standard operand without delimiter
161
+ operand = `@results.${selectedResult.value}`;
162
+ }
163
+ // Get user rules using shared extraction function
164
+ const userRules = extractUserRules(formData);
165
+ // Get existing router data for preservation
166
+ const existingCategories = ((_g = originalNode.router) === null || _g === void 0 ? void 0 : _g.categories) || [];
167
+ const existingExits = originalNode.exits || [];
168
+ const existingCases = ((_h = originalNode.router) === null || _h === void 0 ? void 0 : _h.cases) || [];
169
+ // Create router and exits using existing data when possible
170
+ const { router, exits } = createRulesRouter(operand, userRules, getOperatorConfig, existingCategories, existingExits, existingCases);
171
+ // Build final router with result_name
172
+ const finalRouter = {
173
+ ...router
174
+ };
175
+ // Only set result_name if provided
176
+ if (formData.result_name && formData.result_name.trim() !== '') {
177
+ finalRouter.result_name = formData.result_name.trim();
178
+ }
179
+ return {
180
+ ...originalNode,
181
+ router: finalRouter,
182
+ exits: exits
183
+ };
184
+ },
185
+ toUIConfig: (formData) => {
186
+ var _a, _b, _c, _d, _e, _f;
187
+ // Get selected result (it's an array from the select component)
188
+ const selectedResult = (_a = formData.result) === null || _a === void 0 ? void 0 : _a[0];
189
+ if (!selectedResult) {
190
+ return {};
191
+ }
192
+ // Build UI config with operand information
193
+ const config = {
194
+ operand: {
195
+ id: selectedResult.value,
196
+ name: selectedResult.name,
197
+ type: 'result'
198
+ }
199
+ };
200
+ // Add delimiter configuration if selected
201
+ const delimitBy = (_c = (_b = formData.delimit_by) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.value;
202
+ const hasDelimiter = delimitBy !== undefined && delimitBy !== '';
203
+ if (hasDelimiter) {
204
+ config.index = parseInt((_f = (_e = (_d = formData.delimit_index) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.value) !== null && _f !== void 0 ? _f : '0', 10);
205
+ config.delimiter = delimitBy;
206
+ }
207
+ return config;
208
+ }
6
209
  };
7
210
  //# sourceMappingURL=split_by_run_result.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"split_by_run_result.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_run_result.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAc,MAAM,UAAU,CAAC;AAE9C,MAAM,CAAC,MAAM,mBAAmB,GAAe;IAC7C,IAAI,EAAE,qBAAqB;IAC3B,IAAI,EAAE,sBAAsB;IAC5B,KAAK,EAAE,MAAM,CAAC,KAAK;CACpB,CAAC","sourcesContent":["import { COLORS, NodeConfig } from '../types';\n\nexport const split_by_run_result: NodeConfig = {\n type: 'split_by_run_result',\n name: 'Split by Flow Result',\n color: COLORS.split\n};\n"]}
1
+ {"version":3,"file":"split_by_run_result.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_run_result.ts"],"names":[],"mappings":"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","sourcesContent":["import { SPLIT_GROUPS, FormData, NodeConfig } from '../types';\nimport { Node } from '../../store/flow-definition';\nimport { createRulesRouter } from '../../utils';\nimport {\n getWaitForResponseOperators,\n operatorsToSelectOptions,\n getOperatorConfig\n} from '../operators';\nimport { resultNameField } from './shared';\nimport {\n createRulesArrayConfig,\n extractUserRules,\n casesToFormRules\n} from './shared-rules';\nimport { getStore } from '../../store/Store';\n\n// delimit index options (first through 20th)\nconst DELIMIT_INDEX_OPTIONS = [\n { value: '0', name: 'first result' },\n { value: '1', name: 'second result' },\n { value: '2', name: 'third result' },\n { value: '3', name: 'fourth result' },\n { value: '4', name: 'fifth result' },\n { value: '5', name: 'sixth result' },\n { value: '6', name: 'seventh result' },\n { value: '7', name: 'eighth result' },\n { value: '8', name: 'ninth result' },\n { value: '9', name: 'tenth result' },\n { value: '10', name: '11th result' },\n { value: '11', name: '12th result' },\n { value: '12', name: '13th result' },\n { value: '13', name: '14th result' },\n { value: '14', name: '15th result' },\n { value: '15', name: '16th result' },\n { value: '16', name: '17th result' },\n { value: '17', name: '18th result' },\n { value: '18', name: '19th result' },\n { value: '19', name: '20th result' }\n];\n\n// delimit by options - includes \"don't delimit\" and delimiter characters\nconst DELIMIT_BY_OPTIONS = [\n { value: '', name: \"Don't delimit result\" },\n { value: ' ', name: 'Delimited by spaces' },\n { value: '.', name: 'Delimited by periods' },\n { value: '+', name: 'Delimited by plusses' }\n];\n\nexport const split_by_run_result: NodeConfig = {\n type: 'split_by_run_result',\n name: 'Split by Result',\n group: SPLIT_GROUPS.split,\n dialogSize: 'large',\n form: {\n result: {\n type: 'select',\n\n required: true,\n searchable: false,\n clearable: false,\n placeholder: 'Select a result...',\n getDynamicOptions: () => {\n const store = getStore();\n return store\n ? store\n .getState()\n .getFlowResults()\n .map((r) => ({ value: r.key, name: r.name }))\n : [];\n },\n valueKey: 'value',\n nameKey: 'name'\n },\n delimit_by: {\n type: 'select',\n required: false,\n searchable: false,\n clearable: false,\n options: DELIMIT_BY_OPTIONS,\n valueKey: 'value',\n nameKey: 'name',\n maxWidth: '180px'\n },\n delimit_index: {\n type: 'select',\n required: false,\n searchable: false,\n clearable: false,\n options: DELIMIT_INDEX_OPTIONS,\n valueKey: 'value',\n nameKey: 'name',\n maxWidth: '140px',\n conditions: {\n visible: (formData: FormData) => {\n const delimitBy = formData.delimit_by?.[0]?.value;\n return delimitBy !== undefined && delimitBy !== '';\n }\n }\n },\n rules: createRulesArrayConfig(\n operatorsToSelectOptions(getWaitForResponseOperators()),\n 'Define rules to categorize the result'\n ),\n result_name: resultNameField\n },\n layout: [\n {\n type: 'row',\n label: 'Flow Result',\n helpText:\n 'Select a flow result and optionally delimit it to split on a specific part',\n items: ['result', 'delimit_by', 'delimit_index']\n },\n 'rules',\n 'result_name'\n ],\n validate: (formData: FormData) => {\n const errors: { [key: string]: string } = {};\n\n // Validate result is provided\n if (!formData.result || formData.result.length === 0) {\n errors.result = 'A flow result is required';\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n toFormData: (node: Node, nodeUI?: any) => {\n // Get the result from the UI config operand (source of truth)\n const result = nodeUI?.config?.operand;\n\n // Extract rules from router cases using shared function\n const rules = casesToFormRules(node);\n\n // Extract delimiter configuration by checking the actual operand string\n // If operand contains field() function, we have a delimiter\n const operand = node.router?.operand || '';\n const fieldFunctionMatch = operand.match(\n /field\\(results\\.[\\w]+,\\s*(\\d+),\\s*\"(.+?)\"\\)/\n );\n\n const hasDelimiter = fieldFunctionMatch !== null;\n const delimitIndex = hasDelimiter\n ? parseInt(fieldFunctionMatch![1], 10)\n : 0;\n const delimiter = hasDelimiter ? fieldFunctionMatch![2] : '';\n\n return {\n uuid: node.uuid,\n result: result ? [result] : [],\n delimit_by: hasDelimiter\n ? [DELIMIT_BY_OPTIONS.find((opt) => opt.value === delimiter)]\n : [DELIMIT_BY_OPTIONS[0]],\n delimit_index: hasDelimiter\n ? [\n DELIMIT_INDEX_OPTIONS.find(\n (opt) => opt.value === String(delimitIndex)\n )\n ]\n : [DELIMIT_INDEX_OPTIONS[0]],\n rules: rules,\n result_name: node.router?.result_name || ''\n };\n },\n fromFormData: (formData: FormData, originalNode: Node): Node => {\n // Get selected result (it's an array from the select component)\n const selectedResult = formData.result?.[0];\n\n if (!selectedResult) {\n return originalNode;\n }\n\n // Build operand based on whether delimiter is selected\n let operand: string;\n const delimitBy = formData.delimit_by?.[0]?.value;\n const hasDelimiter = delimitBy !== undefined && delimitBy !== '';\n\n if (hasDelimiter) {\n // Get delimiter configuration\n const delimitIndex = formData.delimit_index?.[0]?.value ?? '0';\n\n // Build operand with field() function\n operand = `@(field(results.${selectedResult.value}, ${delimitIndex}, \"${delimitBy}\"))`;\n } else {\n // Standard operand without delimiter\n operand = `@results.${selectedResult.value}`;\n }\n\n // Get user rules using shared extraction function\n const userRules = extractUserRules(formData);\n\n // Get existing router data for preservation\n const existingCategories = originalNode.router?.categories || [];\n const existingExits = originalNode.exits || [];\n const existingCases = originalNode.router?.cases || [];\n\n // Create router and exits using existing data when possible\n const { router, exits } = createRulesRouter(\n operand,\n userRules,\n getOperatorConfig,\n existingCategories,\n existingExits,\n existingCases\n );\n\n // Build final router with result_name\n const finalRouter: any = {\n ...router\n };\n\n // Only set result_name if provided\n if (formData.result_name && formData.result_name.trim() !== '') {\n finalRouter.result_name = formData.result_name.trim();\n }\n\n return {\n ...originalNode,\n router: finalRouter,\n exits: exits\n };\n },\n toUIConfig: (formData: FormData) => {\n // Get selected result (it's an array from the select component)\n const selectedResult = formData.result?.[0];\n\n if (!selectedResult) {\n return {};\n }\n\n // Build UI config with operand information\n const config: any = {\n operand: {\n id: selectedResult.value,\n name: selectedResult.name,\n type: 'result'\n }\n };\n\n // Add delimiter configuration if selected\n const delimitBy = formData.delimit_by?.[0]?.value;\n const hasDelimiter = delimitBy !== undefined && delimitBy !== '';\n\n if (hasDelimiter) {\n config.index = parseInt(formData.delimit_index?.[0]?.value ?? '0', 10);\n config.delimiter = delimitBy;\n }\n\n return config;\n }\n};\n"]}
@@ -1,7 +1,158 @@
1
- import { COLORS } from '../types';
1
+ import { SPLIT_GROUPS } from '../types';
2
+ import { generateUUID } from '../../utils';
3
+ import { SCHEMES } from '../utils';
4
+ import { resultNameField } from './shared';
5
+ // Helper function to get scheme options for the select dropdown
6
+ const getSchemeOptions = () => {
7
+ return SCHEMES.map((scheme) => ({
8
+ value: scheme.scheme,
9
+ name: scheme.name
10
+ }));
11
+ };
12
+ // Helper function to create a switch router with scheme cases
13
+ const createSchemeRouter = (selectedSchemes, existingCategories = [], existingExits = [], existingCases = [], resultName = '') => {
14
+ const categories = [];
15
+ const exits = [];
16
+ const cases = [];
17
+ // Create categories, exits, and cases for each selected scheme
18
+ selectedSchemes.forEach((scheme) => {
19
+ const schemeObj = SCHEMES.find((s) => s.scheme === scheme);
20
+ const schemeName = (schemeObj === null || schemeObj === void 0 ? void 0 : schemeObj.name) || scheme;
21
+ // Try to find existing category by scheme name
22
+ const existingCategory = existingCategories.find((cat) => cat.name === schemeName);
23
+ const existingExit = existingCategory
24
+ ? existingExits.find((exit) => exit.uuid === existingCategory.exit_uuid)
25
+ : null;
26
+ const existingCase = existingCases.find((c) => { var _a; return ((_a = c.arguments) === null || _a === void 0 ? void 0 : _a[0]) === scheme; });
27
+ const exitUuid = (existingExit === null || existingExit === void 0 ? void 0 : existingExit.uuid) || generateUUID();
28
+ const categoryUuid = (existingCategory === null || existingCategory === void 0 ? void 0 : existingCategory.uuid) || generateUUID();
29
+ const caseUuid = (existingCase === null || existingCase === void 0 ? void 0 : existingCase.uuid) || generateUUID();
30
+ categories.push({
31
+ uuid: categoryUuid,
32
+ name: schemeName,
33
+ exit_uuid: exitUuid
34
+ });
35
+ exits.push({
36
+ uuid: exitUuid,
37
+ destination_uuid: (existingExit === null || existingExit === void 0 ? void 0 : existingExit.destination_uuid) || null
38
+ });
39
+ cases.push({
40
+ uuid: caseUuid,
41
+ type: 'has_only_phrase',
42
+ arguments: [scheme],
43
+ category_uuid: categoryUuid
44
+ });
45
+ });
46
+ // Add default "Other" category for schemes not in the selected list
47
+ const existingOtherCategory = existingCategories.find((cat) => {
48
+ const matchesSelected = selectedSchemes.some((scheme) => {
49
+ const schemeObj = SCHEMES.find((s) => s.scheme === scheme);
50
+ return (schemeObj === null || schemeObj === void 0 ? void 0 : schemeObj.name) === cat.name;
51
+ });
52
+ return cat.name === 'Other' && !matchesSelected;
53
+ });
54
+ const existingOtherExit = existingOtherCategory
55
+ ? existingExits.find((exit) => exit.uuid === existingOtherCategory.exit_uuid)
56
+ : null;
57
+ const otherExitUuid = (existingOtherExit === null || existingOtherExit === void 0 ? void 0 : existingOtherExit.uuid) || generateUUID();
58
+ const otherCategoryUuid = (existingOtherCategory === null || existingOtherCategory === void 0 ? void 0 : existingOtherCategory.uuid) || generateUUID();
59
+ categories.push({
60
+ uuid: otherCategoryUuid,
61
+ name: 'Other',
62
+ exit_uuid: otherExitUuid
63
+ });
64
+ exits.push({
65
+ uuid: otherExitUuid,
66
+ destination_uuid: (existingOtherExit === null || existingOtherExit === void 0 ? void 0 : existingOtherExit.destination_uuid) || null
67
+ });
68
+ return {
69
+ router: {
70
+ type: 'switch',
71
+ cases: cases,
72
+ categories: categories,
73
+ default_category_uuid: otherCategoryUuid,
74
+ operand: '@(urn_parts(contact.urn).scheme)',
75
+ result_name: resultName
76
+ },
77
+ exits: exits
78
+ };
79
+ };
2
80
  export const split_by_scheme = {
3
81
  type: 'split_by_scheme',
4
82
  name: 'Split by URN Type',
5
- color: COLORS.split
83
+ group: SPLIT_GROUPS.split,
84
+ form: {
85
+ schemes: {
86
+ type: 'select',
87
+ label: 'Channel Types',
88
+ helpText: "The contact's URN is the address they used to reach you such as their phone number or a Facebook ID. Select which URN types to split by.",
89
+ required: true,
90
+ options: getSchemeOptions(),
91
+ multi: true,
92
+ searchable: true,
93
+ placeholder: 'Select the channels to split by...'
94
+ },
95
+ result_name: resultNameField
96
+ },
97
+ layout: ['schemes', 'result_name'],
98
+ validate: (formData) => {
99
+ const errors = {};
100
+ if (!formData.schemes ||
101
+ !Array.isArray(formData.schemes) ||
102
+ formData.schemes.length === 0) {
103
+ errors.schemes = 'At least one channel type is required';
104
+ }
105
+ return {
106
+ valid: Object.keys(errors).length === 0,
107
+ errors
108
+ };
109
+ },
110
+ toFormData: (node) => {
111
+ var _a, _b;
112
+ // Extract schemes from the existing node structure
113
+ const schemes = [];
114
+ if ((_a = node.router) === null || _a === void 0 ? void 0 : _a.cases) {
115
+ node.router.cases.forEach((c) => {
116
+ var _a;
117
+ if (c.type === 'has_only_phrase' && ((_a = c.arguments) === null || _a === void 0 ? void 0 : _a.length) > 0) {
118
+ schemes.push(c.arguments[0]);
119
+ }
120
+ });
121
+ }
122
+ return {
123
+ uuid: node.uuid,
124
+ schemes: schemes.map((scheme) => {
125
+ const schemeObj = SCHEMES.find((s) => s.scheme === scheme);
126
+ return {
127
+ value: scheme,
128
+ name: (schemeObj === null || schemeObj === void 0 ? void 0 : schemeObj.name) || scheme
129
+ };
130
+ }),
131
+ result_name: ((_b = node.router) === null || _b === void 0 ? void 0 : _b.result_name) || ''
132
+ };
133
+ },
134
+ fromFormData: (formData, originalNode) => {
135
+ var _a, _b;
136
+ // Get selected schemes (handle both array of objects and array of strings)
137
+ const selectedSchemes = (formData.schemes || [])
138
+ .filter((scheme) => scheme)
139
+ .map((scheme) => typeof scheme === 'string' ? scheme : scheme.value);
140
+ // Create router and exits using existing data when possible
141
+ const existingCategories = ((_a = originalNode.router) === null || _a === void 0 ? void 0 : _a.categories) || [];
142
+ const existingExits = originalNode.exits || [];
143
+ const existingCases = ((_b = originalNode.router) === null || _b === void 0 ? void 0 : _b.cases) || [];
144
+ const { router, exits } = createSchemeRouter(selectedSchemes, existingCategories, existingExits, existingCases, formData.result_name || '');
145
+ // Return the complete node
146
+ return {
147
+ uuid: originalNode.uuid,
148
+ actions: originalNode.actions || [],
149
+ router: router,
150
+ exits: exits
151
+ };
152
+ },
153
+ router: {
154
+ type: 'switch',
155
+ operand: '@(urn_parts(contact.urn).scheme)'
156
+ }
6
157
  };
7
158
  //# sourceMappingURL=split_by_scheme.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"split_by_scheme.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_scheme.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAc,MAAM,UAAU,CAAC;AAE9C,MAAM,CAAC,MAAM,eAAe,GAAe;IACzC,IAAI,EAAE,iBAAiB;IACvB,IAAI,EAAE,mBAAmB;IACzB,KAAK,EAAE,MAAM,CAAC,KAAK;CACpB,CAAC","sourcesContent":["import { COLORS, NodeConfig } from '../types';\n\nexport const split_by_scheme: NodeConfig = {\n type: 'split_by_scheme',\n name: 'Split by URN Type',\n color: COLORS.split\n};\n"]}
1
+ {"version":3,"file":"split_by_scheme.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_scheme.ts"],"names":[],"mappings":"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","sourcesContent":["import { SPLIT_GROUPS, FormData, NodeConfig } from '../types';\nimport { Node, Category, Exit, Case } from '../../store/flow-definition.d';\nimport { generateUUID } from '../../utils';\nimport { SCHEMES } from '../utils';\nimport { resultNameField } from './shared';\n\n// Helper function to get scheme options for the select dropdown\nconst getSchemeOptions = () => {\n return SCHEMES.map((scheme) => ({\n value: scheme.scheme,\n name: scheme.name\n }));\n};\n\n// Helper function to create a switch router with scheme cases\nconst createSchemeRouter = (\n selectedSchemes: string[],\n existingCategories: Category[] = [],\n existingExits: Exit[] = [],\n existingCases: Case[] = [],\n resultName: string = ''\n) => {\n const categories: Category[] = [];\n const exits: Exit[] = [];\n const cases: Case[] = [];\n\n // Create categories, exits, and cases for each selected scheme\n selectedSchemes.forEach((scheme) => {\n const schemeObj = SCHEMES.find((s) => s.scheme === scheme);\n const schemeName = schemeObj?.name || scheme;\n\n // Try to find existing category by scheme name\n const existingCategory = existingCategories.find(\n (cat) => cat.name === schemeName\n );\n const existingExit = existingCategory\n ? existingExits.find((exit) => exit.uuid === existingCategory.exit_uuid)\n : null;\n const existingCase = existingCases.find((c) => c.arguments?.[0] === scheme);\n\n const exitUuid = existingExit?.uuid || generateUUID();\n const categoryUuid = existingCategory?.uuid || generateUUID();\n const caseUuid = existingCase?.uuid || generateUUID();\n\n categories.push({\n uuid: categoryUuid,\n name: schemeName,\n exit_uuid: exitUuid\n });\n\n exits.push({\n uuid: exitUuid,\n destination_uuid: existingExit?.destination_uuid || null\n });\n\n cases.push({\n uuid: caseUuid,\n type: 'has_only_phrase',\n arguments: [scheme],\n category_uuid: categoryUuid\n });\n });\n\n // Add default \"Other\" category for schemes not in the selected list\n const existingOtherCategory = existingCategories.find((cat) => {\n const matchesSelected = selectedSchemes.some((scheme) => {\n const schemeObj = SCHEMES.find((s) => s.scheme === scheme);\n return schemeObj?.name === cat.name;\n });\n return cat.name === 'Other' && !matchesSelected;\n });\n const existingOtherExit = existingOtherCategory\n ? existingExits.find(\n (exit) => exit.uuid === existingOtherCategory.exit_uuid\n )\n : null;\n\n const otherExitUuid = existingOtherExit?.uuid || generateUUID();\n const otherCategoryUuid = existingOtherCategory?.uuid || generateUUID();\n\n categories.push({\n uuid: otherCategoryUuid,\n name: 'Other',\n exit_uuid: otherExitUuid\n });\n\n exits.push({\n uuid: otherExitUuid,\n destination_uuid: existingOtherExit?.destination_uuid || null\n });\n\n return {\n router: {\n type: 'switch' as const,\n cases: cases,\n categories: categories,\n default_category_uuid: otherCategoryUuid,\n operand: '@(urn_parts(contact.urn).scheme)',\n result_name: resultName\n },\n exits: exits\n };\n};\n\nexport const split_by_scheme: NodeConfig = {\n type: 'split_by_scheme',\n name: 'Split by URN Type',\n group: SPLIT_GROUPS.split,\n form: {\n schemes: {\n type: 'select',\n label: 'Channel Types',\n helpText:\n \"The contact's URN is the address they used to reach you such as their phone number or a Facebook ID. Select which URN types to split by.\",\n required: true,\n options: getSchemeOptions(),\n multi: true,\n searchable: true,\n placeholder: 'Select the channels to split by...'\n },\n result_name: resultNameField\n },\n layout: ['schemes', 'result_name'],\n validate: (formData: FormData) => {\n const errors: { [key: string]: string } = {};\n\n if (\n !formData.schemes ||\n !Array.isArray(formData.schemes) ||\n formData.schemes.length === 0\n ) {\n errors.schemes = 'At least one channel type is required';\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n toFormData: (node: Node) => {\n // Extract schemes from the existing node structure\n const schemes: string[] = [];\n\n if (node.router?.cases) {\n node.router.cases.forEach((c: Case) => {\n if (c.type === 'has_only_phrase' && c.arguments?.length > 0) {\n schemes.push(c.arguments[0]);\n }\n });\n }\n\n return {\n uuid: node.uuid,\n schemes: schemes.map((scheme) => {\n const schemeObj = SCHEMES.find((s) => s.scheme === scheme);\n return {\n value: scheme,\n name: schemeObj?.name || scheme\n };\n }),\n result_name: node.router?.result_name || ''\n };\n },\n fromFormData: (formData: FormData, originalNode: Node): Node => {\n // Get selected schemes (handle both array of objects and array of strings)\n const selectedSchemes = (formData.schemes || [])\n .filter((scheme: any) => scheme)\n .map((scheme: any) =>\n typeof scheme === 'string' ? scheme : scheme.value\n );\n\n // Create router and exits using existing data when possible\n const existingCategories = originalNode.router?.categories || [];\n const existingExits = originalNode.exits || [];\n const existingCases = originalNode.router?.cases || [];\n\n const { router, exits } = createSchemeRouter(\n selectedSchemes,\n existingCategories,\n existingExits,\n existingCases,\n formData.result_name || ''\n );\n\n // Return the complete node\n return {\n uuid: originalNode.uuid,\n actions: originalNode.actions || [],\n router: router,\n exits: exits\n };\n },\n router: {\n type: 'switch',\n operand: '@(urn_parts(contact.urn).scheme)'\n }\n};\n"]}
@@ -1,10 +1,12 @@
1
- import { COLORS } from '../types';
1
+ import { ACTION_GROUPS } from '../types';
2
2
  import { generateUUID } from '../../utils';
3
3
  import { html } from 'lit';
4
+ import { renderNamedObjects } from '../utils';
4
5
  export const split_by_subflow = {
5
6
  type: 'split_by_subflow',
6
7
  name: 'Enter a Flow',
7
- color: COLORS.execute,
8
+ group: ACTION_GROUPS.trigger,
9
+ showAsAction: true,
8
10
  form: {
9
11
  flow: {
10
12
  type: 'select',
@@ -18,11 +20,11 @@ export const split_by_subflow = {
18
20
  },
19
21
  layout: ['flow'],
20
22
  render: (node) => {
21
- var _a, _b;
23
+ var _a;
22
24
  const enterFlowAction = (_a = node.actions) === null || _a === void 0 ? void 0 : _a.find((action) => action.type === 'enter_flow');
23
25
  return html `
24
26
  <div class="body">
25
- ${((_b = enterFlowAction === null || enterFlowAction === void 0 ? void 0 : enterFlowAction.flow) === null || _b === void 0 ? void 0 : _b.name) || 'Configure subflow'}
27
+ ${renderNamedObjects([enterFlowAction === null || enterFlowAction === void 0 ? void 0 : enterFlowAction.flow], 'flow')}
26
28
  </div>
27
29
  `;
28
30
  },
@@ -1 +1 @@
1
- {"version":3,"file":"split_by_subflow.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_subflow.ts"],"names":[],"mappings":"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","sourcesContent":["import { COLORS, NodeConfig } from '../types';\nimport { Node } from '../../store/flow-definition';\nimport { generateUUID } from '../../utils';\nimport { html } from 'lit';\n\nexport const split_by_subflow: NodeConfig = {\n type: 'split_by_subflow',\n name: 'Enter a Flow',\n color: COLORS.execute,\n form: {\n flow: {\n type: 'select',\n required: true,\n placeholder: 'Select a flow...',\n helpText:\n 'Once the subflow is complete or expires, the contact will return here',\n endpoint: '/api/v2/flows.json',\n valueKey: 'uuid',\n nameKey: 'name'\n }\n },\n layout: ['flow'],\n render: (node: Node) => {\n const enterFlowAction = node.actions?.find(\n (action) => action.type === 'enter_flow'\n ) as any;\n return html`\n <div class=\"body\">\n ${enterFlowAction?.flow?.name || 'Configure subflow'}\n </div>\n `;\n },\n toFormData: (node: Node) => {\n // Extract data from the existing node structure\n const enterFlowAction = node.actions?.find(\n (action) => action.type === 'enter_flow'\n ) as any;\n\n return {\n uuid: node.uuid,\n flow: enterFlowAction?.flow\n ? [{ uuid: enterFlowAction.flow.uuid, name: enterFlowAction.flow.name }]\n : []\n };\n },\n fromFormData: (formData: any, originalNode: Node): Node => {\n // Get flow selection\n const flowSelection =\n Array.isArray(formData.flow) && formData.flow.length > 0\n ? formData.flow[0]\n : null;\n\n // Find existing enter_flow action to preserve its UUID\n const existingEnterFlowAction = originalNode.actions?.find(\n (action) => action.type === 'enter_flow'\n );\n const enterFlowUuid = existingEnterFlowAction?.uuid || generateUUID();\n\n // Create enter_flow action\n const enterFlowAction: any = {\n type: 'enter_flow',\n uuid: enterFlowUuid,\n flow: flowSelection\n ? {\n uuid: flowSelection.uuid || flowSelection.value,\n name: flowSelection.name\n }\n : { uuid: '', name: '' }\n };\n\n // Create categories and exits for Complete and Expired\n const existingCategories = originalNode.router?.categories || [];\n const existingExits = originalNode.exits || [];\n const existingCases = originalNode.router?.cases || [];\n\n // Find existing Complete category\n const existingCompleteCategory = existingCategories.find(\n (cat) => cat.name === 'Complete'\n );\n const existingCompleteExit = existingCompleteCategory\n ? existingExits.find(\n (exit) => exit.uuid === existingCompleteCategory.exit_uuid\n )\n : null;\n const existingCompleteCase = existingCompleteCategory\n ? existingCases.find(\n (case_) => case_.category_uuid === existingCompleteCategory.uuid\n )\n : null;\n\n const completeCategoryUuid =\n existingCompleteCategory?.uuid || generateUUID();\n const completeExitUuid = existingCompleteExit?.uuid || generateUUID();\n const completeCaseUuid = existingCompleteCase?.uuid || generateUUID();\n\n // Find existing Expired category\n const existingExpiredCategory = existingCategories.find(\n (cat) => cat.name === 'Expired'\n );\n const existingExpiredExit = existingExpiredCategory\n ? existingExits.find(\n (exit) => exit.uuid === existingExpiredCategory.exit_uuid\n )\n : null;\n\n const expiredCategoryUuid = existingExpiredCategory?.uuid || generateUUID();\n const expiredExitUuid = existingExpiredExit?.uuid || generateUUID();\n\n const categories = [\n {\n uuid: completeCategoryUuid,\n name: 'Complete',\n exit_uuid: completeExitUuid\n },\n {\n uuid: expiredCategoryUuid,\n name: 'Expired',\n exit_uuid: expiredExitUuid\n }\n ];\n\n const exits = [\n {\n uuid: completeExitUuid,\n destination_uuid: existingCompleteExit?.destination_uuid || null\n },\n {\n uuid: expiredExitUuid,\n destination_uuid: existingExpiredExit?.destination_uuid || null\n }\n ];\n\n const cases = [\n {\n uuid: completeCaseUuid,\n type: 'has_only_text',\n arguments: ['completed'],\n category_uuid: completeCategoryUuid\n }\n ];\n\n // Create the router\n const router = {\n type: 'switch' as const,\n categories: categories,\n default_category_uuid: expiredCategoryUuid,\n operand: '@child.status',\n cases: cases\n };\n\n // Return the complete node\n return {\n uuid: originalNode.uuid,\n actions: [enterFlowAction],\n router: router,\n exits: exits\n };\n }\n};\n"]}
1
+ {"version":3,"file":"split_by_subflow.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_subflow.ts"],"names":[],"mappings":"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","sourcesContent":["import { ACTION_GROUPS, FormData, NodeConfig } from '../types';\nimport { Node } from '../../store/flow-definition';\nimport { generateUUID } from '../../utils';\nimport { html } from 'lit';\nimport { renderNamedObjects } from '../utils';\n\nexport const split_by_subflow: NodeConfig = {\n type: 'split_by_subflow',\n name: 'Enter a Flow',\n group: ACTION_GROUPS.trigger,\n showAsAction: true,\n form: {\n flow: {\n type: 'select',\n required: true,\n placeholder: 'Select a flow...',\n helpText:\n 'Once the subflow is complete or expires, the contact will return here',\n endpoint: '/api/v2/flows.json',\n valueKey: 'uuid',\n nameKey: 'name'\n }\n },\n layout: ['flow'],\n render: (node: Node) => {\n const enterFlowAction = node.actions?.find(\n (action) => action.type === 'enter_flow'\n ) as any;\n return html`\n <div class=\"body\">\n ${renderNamedObjects([enterFlowAction?.flow], 'flow')}\n </div>\n `;\n },\n toFormData: (node: Node) => {\n // Extract data from the existing node structure\n const enterFlowAction = node.actions?.find(\n (action) => action.type === 'enter_flow'\n ) as any;\n\n return {\n uuid: node.uuid,\n flow: enterFlowAction?.flow\n ? [{ uuid: enterFlowAction.flow.uuid, name: enterFlowAction.flow.name }]\n : []\n };\n },\n fromFormData: (formData: FormData, originalNode: Node): Node => {\n // Get flow selection\n const flowSelection =\n Array.isArray(formData.flow) && formData.flow.length > 0\n ? formData.flow[0]\n : null;\n\n // Find existing enter_flow action to preserve its UUID\n const existingEnterFlowAction = originalNode.actions?.find(\n (action) => action.type === 'enter_flow'\n );\n const enterFlowUuid = existingEnterFlowAction?.uuid || generateUUID();\n\n // Create enter_flow action\n const enterFlowAction: any = {\n type: 'enter_flow',\n uuid: enterFlowUuid,\n flow: flowSelection\n ? {\n uuid: flowSelection.uuid || flowSelection.value,\n name: flowSelection.name\n }\n : { uuid: '', name: '' }\n };\n\n // Create categories and exits for Complete and Expired\n const existingCategories = originalNode.router?.categories || [];\n const existingExits = originalNode.exits || [];\n const existingCases = originalNode.router?.cases || [];\n\n // Find existing Complete category\n const existingCompleteCategory = existingCategories.find(\n (cat) => cat.name === 'Complete'\n );\n const existingCompleteExit = existingCompleteCategory\n ? existingExits.find(\n (exit) => exit.uuid === existingCompleteCategory.exit_uuid\n )\n : null;\n const existingCompleteCase = existingCompleteCategory\n ? existingCases.find(\n (case_) => case_.category_uuid === existingCompleteCategory.uuid\n )\n : null;\n\n const completeCategoryUuid =\n existingCompleteCategory?.uuid || generateUUID();\n const completeExitUuid = existingCompleteExit?.uuid || generateUUID();\n const completeCaseUuid = existingCompleteCase?.uuid || generateUUID();\n\n // Find existing Expired category\n const existingExpiredCategory = existingCategories.find(\n (cat) => cat.name === 'Expired'\n );\n const existingExpiredExit = existingExpiredCategory\n ? existingExits.find(\n (exit) => exit.uuid === existingExpiredCategory.exit_uuid\n )\n : null;\n\n const expiredCategoryUuid = existingExpiredCategory?.uuid || generateUUID();\n const expiredExitUuid = existingExpiredExit?.uuid || generateUUID();\n\n const categories = [\n {\n uuid: completeCategoryUuid,\n name: 'Complete',\n exit_uuid: completeExitUuid\n },\n {\n uuid: expiredCategoryUuid,\n name: 'Expired',\n exit_uuid: expiredExitUuid\n }\n ];\n\n const exits = [\n {\n uuid: completeExitUuid,\n destination_uuid: existingCompleteExit?.destination_uuid || null\n },\n {\n uuid: expiredExitUuid,\n destination_uuid: existingExpiredExit?.destination_uuid || null\n }\n ];\n\n const cases = [\n {\n uuid: completeCaseUuid,\n type: 'has_only_text',\n arguments: ['completed'],\n category_uuid: completeCategoryUuid\n }\n ];\n\n // Create the router\n const router = {\n type: 'switch' as const,\n categories: categories,\n default_category_uuid: expiredCategoryUuid,\n operand: '@child.status',\n cases: cases\n };\n\n // Return the complete node\n return {\n uuid: originalNode.uuid,\n actions: [enterFlowAction],\n router: router,\n exits: exits\n };\n }\n};\n"]}