@nyaruka/temba-components 0.140.0 → 0.141.1

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 (297) hide show
  1. package/.lintstagedrc.js +10 -0
  2. package/CHANGELOG.md +22 -0
  3. package/dist/locales/es.js +5 -5
  4. package/dist/locales/es.js.map +1 -1
  5. package/dist/locales/fr.js +5 -5
  6. package/dist/locales/fr.js.map +1 -1
  7. package/dist/locales/locale-codes.js +11 -2
  8. package/dist/locales/locale-codes.js.map +1 -1
  9. package/dist/locales/pt.js +5 -5
  10. package/dist/locales/pt.js.map +1 -1
  11. package/dist/temba-components.js +263 -156
  12. package/dist/temba-components.js.map +1 -1
  13. package/out-tsc/src/display/FloatingTab.js +1 -1
  14. package/out-tsc/src/display/FloatingTab.js.map +1 -1
  15. package/out-tsc/src/flow/CanvasNode.js +1 -1
  16. package/out-tsc/src/flow/CanvasNode.js.map +1 -1
  17. package/out-tsc/src/flow/Editor.js +239 -43
  18. package/out-tsc/src/flow/Editor.js.map +1 -1
  19. package/out-tsc/src/flow/Plumber.js +61 -14
  20. package/out-tsc/src/flow/Plumber.js.map +1 -1
  21. package/out-tsc/src/flow/actions/add_contact_groups.js +4 -1
  22. package/out-tsc/src/flow/actions/add_contact_groups.js.map +1 -1
  23. package/out-tsc/src/flow/actions/add_input_labels.js +4 -1
  24. package/out-tsc/src/flow/actions/add_input_labels.js.map +1 -1
  25. package/out-tsc/src/flow/actions/remove_contact_groups.js +6 -1
  26. package/out-tsc/src/flow/actions/remove_contact_groups.js.map +1 -1
  27. package/out-tsc/src/flow/actions/send_broadcast.js +6 -2
  28. package/out-tsc/src/flow/actions/send_broadcast.js.map +1 -1
  29. package/out-tsc/src/flow/actions/set_contact_channel.js +13 -0
  30. package/out-tsc/src/flow/actions/set_contact_channel.js.map +1 -1
  31. package/out-tsc/src/flow/actions/set_contact_status.js +7 -5
  32. package/out-tsc/src/flow/actions/set_contact_status.js.map +1 -1
  33. package/out-tsc/src/flow/actions/start_session.js +10 -3
  34. package/out-tsc/src/flow/actions/start_session.js.map +1 -1
  35. package/out-tsc/src/flow/nodes/split_by_contact_field.js +18 -5
  36. package/out-tsc/src/flow/nodes/split_by_contact_field.js.map +1 -1
  37. package/out-tsc/src/flow/nodes/split_by_expression.js +1 -1
  38. package/out-tsc/src/flow/nodes/split_by_expression.js.map +1 -1
  39. package/out-tsc/src/flow/nodes/split_by_llm_categorize.js +0 -1
  40. package/out-tsc/src/flow/nodes/split_by_llm_categorize.js.map +1 -1
  41. package/out-tsc/src/flow/nodes/split_by_random.js +0 -1
  42. package/out-tsc/src/flow/nodes/split_by_random.js.map +1 -1
  43. package/out-tsc/src/flow/nodes/split_by_run_result.js +10 -4
  44. package/out-tsc/src/flow/nodes/split_by_run_result.js.map +1 -1
  45. package/out-tsc/src/flow/nodes/wait_for_digits.js +1 -1
  46. package/out-tsc/src/flow/nodes/wait_for_digits.js.map +1 -1
  47. package/out-tsc/src/flow/nodes/wait_for_response.js +1 -1
  48. package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -1
  49. package/out-tsc/src/form/FieldRenderer.js +7 -0
  50. package/out-tsc/src/form/FieldRenderer.js.map +1 -1
  51. package/out-tsc/src/layout/Dialog.js +0 -1
  52. package/out-tsc/src/layout/Dialog.js.map +1 -1
  53. package/out-tsc/src/layout/Modax.js +20 -2
  54. package/out-tsc/src/layout/Modax.js.map +1 -1
  55. package/out-tsc/src/list/ContentMenu.js +14 -1
  56. package/out-tsc/src/list/ContentMenu.js.map +1 -1
  57. package/out-tsc/src/live/ContactChat.js +10 -1
  58. package/out-tsc/src/live/ContactChat.js.map +1 -1
  59. package/out-tsc/src/live/TembaChart.js.map +1 -1
  60. package/out-tsc/src/locales/es.js +5 -5
  61. package/out-tsc/src/locales/es.js.map +1 -1
  62. package/out-tsc/src/locales/fr.js +5 -5
  63. package/out-tsc/src/locales/fr.js.map +1 -1
  64. package/out-tsc/src/locales/locale-codes.js +11 -2
  65. package/out-tsc/src/locales/locale-codes.js.map +1 -1
  66. package/out-tsc/src/locales/pt.js +5 -5
  67. package/out-tsc/src/locales/pt.js.map +1 -1
  68. package/out-tsc/src/simulator/Simulator.js +11 -0
  69. package/out-tsc/src/simulator/Simulator.js.map +1 -1
  70. package/out-tsc/src/store/AppState.js +13 -0
  71. package/out-tsc/src/store/AppState.js.map +1 -1
  72. package/out-tsc/src/version.js +9 -0
  73. package/out-tsc/src/version.js.map +1 -0
  74. package/out-tsc/test/actions/add_contact_groups.test.js +35 -0
  75. package/out-tsc/test/actions/add_contact_groups.test.js.map +1 -1
  76. package/out-tsc/test/actions/add_input_labels.test.js +53 -0
  77. package/out-tsc/test/actions/add_input_labels.test.js.map +1 -0
  78. package/out-tsc/test/actions/enter_flow.test.js +71 -0
  79. package/out-tsc/test/actions/enter_flow.test.js.map +1 -0
  80. package/out-tsc/test/actions/remove_contact_groups.test.js +24 -0
  81. package/out-tsc/test/actions/remove_contact_groups.test.js.map +1 -1
  82. package/out-tsc/test/actions/send_broadcast.test.js +41 -0
  83. package/out-tsc/test/actions/send_broadcast.test.js.map +1 -1
  84. package/out-tsc/test/actions/set_contact_channel.test.js +67 -0
  85. package/out-tsc/test/actions/set_contact_channel.test.js.map +1 -0
  86. package/out-tsc/test/actions/set_contact_field.test.js +52 -0
  87. package/out-tsc/test/actions/set_contact_field.test.js.map +1 -0
  88. package/out-tsc/test/actions/set_contact_language.test.js +39 -0
  89. package/out-tsc/test/actions/set_contact_language.test.js.map +1 -0
  90. package/out-tsc/test/actions/set_contact_name.test.js +28 -0
  91. package/out-tsc/test/actions/set_contact_name.test.js.map +1 -0
  92. package/out-tsc/test/actions/set_contact_status.test.js +44 -0
  93. package/out-tsc/test/actions/set_contact_status.test.js.map +1 -0
  94. package/out-tsc/test/actions/set_run_result.test.js +47 -0
  95. package/out-tsc/test/actions/set_run_result.test.js.map +1 -0
  96. package/out-tsc/test/actions/start_session.test.js +76 -0
  97. package/out-tsc/test/actions/start_session.test.js.map +1 -1
  98. package/out-tsc/test/nodes/split_by_contact_field.test.js +50 -0
  99. package/out-tsc/test/nodes/split_by_contact_field.test.js.map +1 -1
  100. package/out-tsc/test/nodes/split_by_run_result.test.js +82 -0
  101. package/out-tsc/test/nodes/split_by_run_result.test.js.map +1 -1
  102. package/out-tsc/test/nodes/split_by_ticket.test.js +139 -0
  103. package/out-tsc/test/nodes/split_by_ticket.test.js.map +1 -0
  104. package/out-tsc/test/nodes/split_by_webhook.test.js +111 -0
  105. package/out-tsc/test/nodes/split_by_webhook.test.js.map +1 -0
  106. package/out-tsc/test/temba-contact-chat.test.js +12 -0
  107. package/out-tsc/test/temba-contact-chat.test.js.map +1 -1
  108. package/out-tsc/test/temba-flow-editor.test.js +206 -0
  109. package/out-tsc/test/temba-flow-editor.test.js.map +1 -1
  110. package/out-tsc/test/temba-flow-plumber.test.js +19 -0
  111. package/out-tsc/test/temba-flow-plumber.test.js.map +1 -1
  112. package/out-tsc/test/temba-select.test.js +4 -1
  113. package/out-tsc/test/temba-select.test.js.map +1 -1
  114. package/out-tsc/test/utils.test.js +4 -2
  115. package/out-tsc/test/utils.test.js.map +1 -1
  116. package/package.json +3 -9
  117. package/rollup.components.mjs +7 -1
  118. package/screenshots/truth/actions/add_contact_groups/render/descriptive-group-names.png +0 -0
  119. package/screenshots/truth/actions/add_contact_groups/render/long-group-names.png +0 -0
  120. package/screenshots/truth/actions/add_contact_groups/render/many-groups.png +0 -0
  121. package/screenshots/truth/actions/add_contact_groups/render/multiple-groups.png +0 -0
  122. package/screenshots/truth/actions/add_contact_groups/render/single-group.png +0 -0
  123. package/screenshots/truth/actions/add_contact_urn/render/expression-facebook.png +0 -0
  124. package/screenshots/truth/actions/add_contact_urn/render/expression-phone.png +0 -0
  125. package/screenshots/truth/actions/add_contact_urn/render/facebook-id.png +0 -0
  126. package/screenshots/truth/actions/add_contact_urn/render/instagram-handle.png +0 -0
  127. package/screenshots/truth/actions/add_contact_urn/render/line-id.png +0 -0
  128. package/screenshots/truth/actions/add_contact_urn/render/phone-number.png +0 -0
  129. package/screenshots/truth/actions/add_contact_urn/render/telegram-id.png +0 -0
  130. package/screenshots/truth/actions/add_contact_urn/render/viber-id.png +0 -0
  131. package/screenshots/truth/actions/add_contact_urn/render/wechat-id.png +0 -0
  132. package/screenshots/truth/actions/add_contact_urn/render/whatsapp.png +0 -0
  133. package/screenshots/truth/actions/add_input_labels/editor/multiple-labels.png +0 -0
  134. package/screenshots/truth/actions/add_input_labels/editor/single-label.png +0 -0
  135. package/screenshots/truth/actions/add_input_labels/render/multiple-labels.png +0 -0
  136. package/screenshots/truth/actions/add_input_labels/render/single-label.png +0 -0
  137. package/screenshots/truth/actions/enter_flow/editor/basic-flow.png +0 -0
  138. package/screenshots/truth/actions/enter_flow/editor/long-flow-name.png +0 -0
  139. package/screenshots/truth/actions/enter_flow/render/basic-flow.png +0 -0
  140. package/screenshots/truth/actions/enter_flow/render/long-flow-name.png +0 -0
  141. package/screenshots/truth/actions/play_audio/render/expression-url.png +0 -0
  142. package/screenshots/truth/actions/play_audio/render/static-url.png +0 -0
  143. package/screenshots/truth/actions/remove_contact_groups/render/cleanup-groups.png +0 -0
  144. package/screenshots/truth/actions/remove_contact_groups/render/long-descriptive-group-names.png +0 -0
  145. package/screenshots/truth/actions/remove_contact_groups/render/many-groups.png +0 -0
  146. package/screenshots/truth/actions/remove_contact_groups/render/multiple-groups.png +0 -0
  147. package/screenshots/truth/actions/remove_contact_groups/render/remove-from-all-groups.png +0 -0
  148. package/screenshots/truth/actions/remove_contact_groups/render/single-group.png +0 -0
  149. package/screenshots/truth/actions/say_msg/render/multiline-text.png +0 -0
  150. package/screenshots/truth/actions/say_msg/render/simple-text.png +0 -0
  151. package/screenshots/truth/actions/say_msg/render/text-with-audio-url.png +0 -0
  152. package/screenshots/truth/actions/send_broadcast/render/contacts-only.png +0 -0
  153. package/screenshots/truth/actions/send_broadcast/render/groups-and-contacts.png +0 -0
  154. package/screenshots/truth/actions/send_broadcast/render/groups-only.png +0 -0
  155. package/screenshots/truth/actions/send_broadcast/render/many-groups.png +0 -0
  156. package/screenshots/truth/actions/send_broadcast/render/multiline-text.png +0 -0
  157. package/screenshots/truth/actions/send_email/render/complex-business-email.png +0 -0
  158. package/screenshots/truth/actions/send_email/render/empty-body.png +0 -0
  159. package/screenshots/truth/actions/send_email/render/empty-subject.png +0 -0
  160. package/screenshots/truth/actions/send_email/render/long-subject.png +0 -0
  161. package/screenshots/truth/actions/send_email/render/multiline-body.png +0 -0
  162. package/screenshots/truth/actions/send_email/render/multiple-recipients.png +0 -0
  163. package/screenshots/truth/actions/send_email/render/simple-email.png +0 -0
  164. package/screenshots/truth/actions/send_email/render/with-expressions.png +0 -0
  165. package/screenshots/truth/actions/send_msg/render/long-quick-replies.png +0 -0
  166. package/screenshots/truth/actions/send_msg/render/multiline-text-with-replies.png +0 -0
  167. package/screenshots/truth/actions/send_msg/render/simple-text.png +0 -0
  168. package/screenshots/truth/actions/send_msg/render/text-with-linebreaks.png +0 -0
  169. package/screenshots/truth/actions/send_msg/render/text-with-many-quick-replies.png +0 -0
  170. package/screenshots/truth/actions/send_msg/render/text-with-quick-replies.png +0 -0
  171. package/screenshots/truth/actions/send_msg/render/text-without-quick-replies.png +0 -0
  172. package/screenshots/truth/actions/set_contact_channel/editor/sms-channel.png +0 -0
  173. package/screenshots/truth/actions/set_contact_channel/editor/whatsapp-channel.png +0 -0
  174. package/screenshots/truth/actions/set_contact_channel/render/sms-channel.png +0 -0
  175. package/screenshots/truth/actions/set_contact_channel/render/whatsapp-channel.png +0 -0
  176. package/screenshots/truth/actions/set_contact_field/editor/clear-value.png +0 -0
  177. package/screenshots/truth/actions/set_contact_field/editor/set-value.png +0 -0
  178. package/screenshots/truth/actions/set_contact_field/render/clear-value.png +0 -0
  179. package/screenshots/truth/actions/set_contact_field/render/set-value.png +0 -0
  180. package/screenshots/truth/actions/set_contact_language/editor/english.png +0 -0
  181. package/screenshots/truth/actions/set_contact_language/editor/french.png +0 -0
  182. package/screenshots/truth/actions/set_contact_language/render/english.png +0 -0
  183. package/screenshots/truth/actions/set_contact_language/render/french.png +0 -0
  184. package/screenshots/truth/actions/set_contact_name/editor/expression-name.png +0 -0
  185. package/screenshots/truth/actions/set_contact_name/editor/static-name.png +0 -0
  186. package/screenshots/truth/actions/set_contact_name/render/expression-name.png +0 -0
  187. package/screenshots/truth/actions/set_contact_name/render/static-name.png +0 -0
  188. package/screenshots/truth/actions/set_contact_status/editor/active.png +0 -0
  189. package/screenshots/truth/actions/set_contact_status/editor/archived.png +0 -0
  190. package/screenshots/truth/actions/set_contact_status/editor/blocked.png +0 -0
  191. package/screenshots/truth/actions/set_contact_status/render/active.png +0 -0
  192. package/screenshots/truth/actions/set_contact_status/render/archived.png +0 -0
  193. package/screenshots/truth/actions/set_contact_status/render/blocked.png +0 -0
  194. package/screenshots/truth/actions/set_run_result/editor/expression-value.png +0 -0
  195. package/screenshots/truth/actions/set_run_result/editor/with-category.png +0 -0
  196. package/screenshots/truth/actions/set_run_result/render/expression-value.png +0 -0
  197. package/screenshots/truth/actions/set_run_result/render/with-category.png +0 -0
  198. package/screenshots/truth/actions/start_session/render/contact-query.png +0 -0
  199. package/screenshots/truth/actions/start_session/render/contacts-only.png +0 -0
  200. package/screenshots/truth/actions/start_session/render/create-contact.png +0 -0
  201. package/screenshots/truth/actions/start_session/render/groups-and-contacts.png +0 -0
  202. package/screenshots/truth/actions/start_session/render/groups-only.png +0 -0
  203. package/screenshots/truth/actions/start_session/render/many-recipients.png +0 -0
  204. package/screenshots/truth/editor/wait.png +0 -0
  205. package/screenshots/truth/nodes/split_by_llm/render/information-extraction.png +0 -0
  206. package/screenshots/truth/nodes/split_by_llm/render/sentiment-analysis.png +0 -0
  207. package/screenshots/truth/nodes/split_by_llm/render/summarization.png +0 -0
  208. package/screenshots/truth/nodes/split_by_llm/render/translation-task.png +0 -0
  209. package/screenshots/truth/nodes/split_by_llm_categorize/editor/basic-categorization.png +0 -0
  210. package/screenshots/truth/nodes/split_by_llm_categorize/editor/custom-input-and-result-name.png +0 -0
  211. package/screenshots/truth/nodes/split_by_llm_categorize/editor/feedback-categorization.png +0 -0
  212. package/screenshots/truth/nodes/split_by_llm_categorize/editor/many-categories.png +0 -0
  213. package/screenshots/truth/nodes/split_by_llm_categorize/editor/minimal-categories.png +0 -0
  214. package/screenshots/truth/nodes/split_by_llm_categorize/render/basic-categorization.png +0 -0
  215. package/screenshots/truth/nodes/split_by_llm_categorize/render/custom-input-and-result-name.png +0 -0
  216. package/screenshots/truth/nodes/split_by_llm_categorize/render/feedback-categorization.png +0 -0
  217. package/screenshots/truth/nodes/split_by_llm_categorize/render/many-categories.png +0 -0
  218. package/screenshots/truth/nodes/split_by_llm_categorize/render/minimal-categories.png +0 -0
  219. package/screenshots/truth/nodes/split_by_random/editor/ab-test-multiple-variants.png +0 -0
  220. package/screenshots/truth/nodes/split_by_random/editor/sampling-split.png +0 -0
  221. package/screenshots/truth/nodes/split_by_random/editor/three-way-split.png +0 -0
  222. package/screenshots/truth/nodes/split_by_random/editor/two-bucket-split.png +0 -0
  223. package/screenshots/truth/nodes/split_by_random/render/ab-test-multiple-variants.png +0 -0
  224. package/screenshots/truth/nodes/split_by_random/render/sampling-split.png +0 -0
  225. package/screenshots/truth/nodes/split_by_random/render/three-way-split.png +0 -0
  226. package/screenshots/truth/nodes/split_by_random/render/two-bucket-split.png +0 -0
  227. package/screenshots/truth/nodes/wait_for_audio/render/basic-audio-wait.png +0 -0
  228. package/screenshots/truth/nodes/wait_for_dial/render/basic-dial.png +0 -0
  229. package/screenshots/truth/nodes/wait_for_dial/render/dial-with-limits.png +0 -0
  230. package/screenshots/truth/nodes/wait_for_digits/editor/basic-digits-wait.png +0 -0
  231. package/screenshots/truth/nodes/wait_for_digits/editor/digits-with-rules.png +0 -0
  232. package/screenshots/truth/nodes/wait_for_digits/render/basic-digits-wait.png +0 -0
  233. package/screenshots/truth/nodes/wait_for_digits/render/digits-with-rules.png +0 -0
  234. package/screenshots/truth/nodes/wait_for_menu/render/menu-with-digits.png +0 -0
  235. package/screenshots/truth/nodes/wait_for_response/editor/basic-wait.png +0 -0
  236. package/screenshots/truth/nodes/wait_for_response/editor/custom-result-name.png +0 -0
  237. package/screenshots/truth/nodes/wait_for_response/editor/no-timeout.png +0 -0
  238. package/screenshots/truth/nodes/wait_for_response/editor/short-timeout.png +0 -0
  239. package/screenshots/truth/nodes/wait_for_response/render/basic-wait.png +0 -0
  240. package/screenshots/truth/nodes/wait_for_response/render/custom-result-name.png +0 -0
  241. package/screenshots/truth/nodes/wait_for_response/render/no-timeout.png +0 -0
  242. package/screenshots/truth/nodes/wait_for_response/render/short-timeout.png +0 -0
  243. package/src/display/FloatingTab.ts +1 -1
  244. package/src/flow/CanvasNode.ts +1 -1
  245. package/src/flow/Editor.ts +299 -88
  246. package/src/flow/Plumber.ts +89 -14
  247. package/src/flow/actions/add_contact_groups.ts +4 -1
  248. package/src/flow/actions/add_input_labels.ts +4 -1
  249. package/src/flow/actions/remove_contact_groups.ts +6 -1
  250. package/src/flow/actions/send_broadcast.ts +6 -2
  251. package/src/flow/actions/set_contact_channel.ts +13 -1
  252. package/src/flow/actions/set_contact_status.ts +7 -5
  253. package/src/flow/actions/start_session.ts +10 -3
  254. package/src/flow/nodes/split_by_contact_field.ts +16 -5
  255. package/src/flow/nodes/split_by_expression.ts +1 -1
  256. package/src/flow/nodes/split_by_llm_categorize.ts +0 -1
  257. package/src/flow/nodes/split_by_random.ts +0 -1
  258. package/src/flow/nodes/split_by_run_result.ts +10 -4
  259. package/src/flow/nodes/wait_for_digits.ts +2 -1
  260. package/src/flow/nodes/wait_for_response.ts +1 -1
  261. package/src/form/FieldRenderer.ts +7 -0
  262. package/src/layout/Dialog.ts +0 -1
  263. package/src/layout/Modax.ts +19 -2
  264. package/src/list/ContentMenu.ts +15 -1
  265. package/src/live/ContactChat.ts +10 -1
  266. package/src/live/TembaChart.ts +1 -1
  267. package/src/locales/es.ts +18 -13
  268. package/src/locales/fr.ts +18 -13
  269. package/src/locales/locale-codes.ts +11 -2
  270. package/src/locales/pt.ts +18 -13
  271. package/src/simulator/Simulator.ts +12 -0
  272. package/src/store/AppState.ts +15 -0
  273. package/src/store/flow-definition.d.ts +1 -0
  274. package/src/version.ts +10 -0
  275. package/test/actions/add_contact_groups.test.ts +38 -0
  276. package/test/actions/add_input_labels.test.ts +67 -0
  277. package/test/actions/enter_flow.test.ts +88 -0
  278. package/test/actions/remove_contact_groups.test.ts +29 -0
  279. package/test/actions/send_broadcast.test.ts +44 -0
  280. package/test/actions/set_contact_channel.test.ts +88 -0
  281. package/test/actions/set_contact_field.test.ts +68 -0
  282. package/test/actions/set_contact_language.test.ts +55 -0
  283. package/test/actions/set_contact_name.test.ts +39 -0
  284. package/test/actions/set_contact_status.test.ts +64 -0
  285. package/test/actions/set_run_result.test.ts +61 -0
  286. package/test/actions/start_session.test.ts +82 -0
  287. package/test/nodes/split_by_contact_field.test.ts +59 -0
  288. package/test/nodes/split_by_run_result.test.ts +100 -0
  289. package/test/nodes/split_by_ticket.test.ts +157 -0
  290. package/test/nodes/split_by_webhook.test.ts +131 -0
  291. package/test/temba-contact-chat.test.ts +17 -0
  292. package/test/temba-flow-editor.test.ts +264 -0
  293. package/test/temba-flow-plumber.test.ts +62 -0
  294. package/test/temba-select.test.ts +6 -1
  295. package/test/utils.test.ts +4 -2
  296. package/web-dev-server.config.mjs +5 -1
  297. package/web-test-runner.config.mjs +4 -1
@@ -56,7 +56,12 @@ export const remove_contact_groups = {
56
56
  return {
57
57
  uuid: formData.uuid,
58
58
  type: 'remove_contact_groups',
59
- groups: formData.all_groups ? [] : formData.groups || [],
59
+ groups: formData.all_groups
60
+ ? []
61
+ : (formData.groups || []).map((g) => ({
62
+ uuid: g.uuid,
63
+ name: g.name
64
+ })),
60
65
  all_groups: formData.all_groups || false
61
66
  };
62
67
  }
@@ -1 +1 @@
1
- {"version":3,"file":"remove_contact_groups.js","sourceRoot":"","sources":["../../../../src/flow/actions/remove_contact_groups.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAEL,aAAa,EAGb,SAAS,EACV,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAE9C,MAAM,CAAC,MAAM,qBAAqB,GAAiB;IACjD,IAAI,EAAE,mBAAmB;IACzB,KAAK,EAAE,aAAa,CAAC,QAAQ;IAC7B,SAAS,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,UAAU,CAAC;IACrE,MAAM,EAAE,CAAC,KAAW,EAAE,MAAuB,EAAE,EAAE;QAC/C,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YACtB,OAAO,IAAI,CAAA,mCAAmC,CAAC;QACjD,CAAC;QACD,OAAO,IAAI,CAAA,QAAQ,kBAAkB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC;IACxE,CAAC;IACD,UAAU,EAAE,CAAC,MAAuB,EAAE,EAAE;QACtC,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,KAAK;YACtC,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,IAAI;SAC9B,CAAC;IACJ,CAAC;IACD,IAAI,EAAE;QACJ,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,QAAQ;YACf,QAAQ,EAAE,8CAA8C;YACxD,OAAO,EAAE,EAAE;YACX,KAAK,EAAE,IAAI;YACX,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,qBAAqB;YAC/B,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,MAAM;YACf,WAAW,EAAE,sBAAsB;YACnC,UAAU,EAAE;gBACV,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,UAAU;aAC5C;SACF;QACD,UAAU,EAAE;YACV,IAAI,EAAE,UAAU;YAChB,KAAK,EAAE,wBAAwB;YAC/B,QAAQ,EACN,2EAA2E;SAC9E;KACF;IACD,QAAQ,EAAE,CAAC,QAAkB,EAAoB,EAAE;QACjD,MAAM,MAAM,GAA8B,EAAE,CAAC;QAE7C,IACE,CAAC,QAAQ,CAAC,UAAU;YACpB,CAAC,CAAC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,EAClD,CAAC;YACD,MAAM,CAAC,MAAM;gBACX,uEAAuE,CAAC;QAC5E,CAAC;QAED,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC;YACvC,MAAM;SACP,CAAC;IACJ,CAAC;IACD,YAAY,EAAE,CAAC,QAAkB,EAAmB,EAAE;QACpD,OAAO;YACL,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,IAAI,EAAE,uBAAuB;YAC7B,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,IAAI,EAAE;YACxD,UAAU,EAAE,QAAQ,CAAC,UAAU,IAAI,KAAK;SACzC,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport {\n ActionConfig,\n ACTION_GROUPS,\n FormData,\n ValidationResult,\n FlowTypes\n} from '../types';\nimport { Node, RemoveFromGroup } from '../../store/flow-definition';\nimport { renderNamedObjects } from '../utils';\n\nexport const remove_contact_groups: ActionConfig = {\n name: 'Remove from Group',\n group: ACTION_GROUPS.contacts,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n render: (_node: Node, action: RemoveFromGroup) => {\n if (action.all_groups) {\n return html`<div>Remove from all groups</div>`;\n }\n return html`<div>${renderNamedObjects(action.groups, 'group')}</div>`;\n },\n toFormData: (action: RemoveFromGroup) => {\n return {\n uuid: action.uuid,\n all_groups: action.all_groups || false,\n groups: action.groups || null\n };\n },\n form: {\n groups: {\n type: 'select',\n label: 'Groups',\n helpText: 'Select the groups to remove the contact from',\n options: [],\n multi: true,\n searchable: true,\n endpoint: '/api/v2/groups.json',\n valueKey: 'uuid',\n nameKey: 'name',\n placeholder: 'Search for groups...',\n conditions: {\n visible: (formData) => !formData.all_groups\n }\n },\n all_groups: {\n type: 'checkbox',\n label: 'Remove from All Groups',\n helpText:\n 'Check this to remove the contact from all groups instead of specific ones'\n }\n },\n validate: (formData: FormData): ValidationResult => {\n const errors: { [key: string]: string } = {};\n\n if (\n !formData.all_groups &&\n (!formData.groups || formData.groups.length === 0)\n ) {\n errors.groups =\n 'At least one group must be selected or check \"Remove from All Groups\"';\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n fromFormData: (formData: FormData): RemoveFromGroup => {\n return {\n uuid: formData.uuid,\n type: 'remove_contact_groups',\n groups: formData.all_groups ? [] : formData.groups || [],\n all_groups: formData.all_groups || false\n };\n }\n};\n"]}
1
+ {"version":3,"file":"remove_contact_groups.js","sourceRoot":"","sources":["../../../../src/flow/actions/remove_contact_groups.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAEL,aAAa,EAGb,SAAS,EACV,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAE9C,MAAM,CAAC,MAAM,qBAAqB,GAAiB;IACjD,IAAI,EAAE,mBAAmB;IACzB,KAAK,EAAE,aAAa,CAAC,QAAQ;IAC7B,SAAS,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,UAAU,CAAC;IACrE,MAAM,EAAE,CAAC,KAAW,EAAE,MAAuB,EAAE,EAAE;QAC/C,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YACtB,OAAO,IAAI,CAAA,mCAAmC,CAAC;QACjD,CAAC;QACD,OAAO,IAAI,CAAA,QAAQ,kBAAkB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC;IACxE,CAAC;IACD,UAAU,EAAE,CAAC,MAAuB,EAAE,EAAE;QACtC,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,KAAK;YACtC,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,IAAI;SAC9B,CAAC;IACJ,CAAC;IACD,IAAI,EAAE;QACJ,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,QAAQ;YACf,QAAQ,EAAE,8CAA8C;YACxD,OAAO,EAAE,EAAE;YACX,KAAK,EAAE,IAAI;YACX,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,qBAAqB;YAC/B,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,MAAM;YACf,WAAW,EAAE,sBAAsB;YACnC,UAAU,EAAE;gBACV,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,UAAU;aAC5C;SACF;QACD,UAAU,EAAE;YACV,IAAI,EAAE,UAAU;YAChB,KAAK,EAAE,wBAAwB;YAC/B,QAAQ,EACN,2EAA2E;SAC9E;KACF;IACD,QAAQ,EAAE,CAAC,QAAkB,EAAoB,EAAE;QACjD,MAAM,MAAM,GAA8B,EAAE,CAAC;QAE7C,IACE,CAAC,QAAQ,CAAC,UAAU;YACpB,CAAC,CAAC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,EAClD,CAAC;YACD,MAAM,CAAC,MAAM;gBACX,uEAAuE,CAAC;QAC5E,CAAC;QAED,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC;YACvC,MAAM;SACP,CAAC;IACJ,CAAC;IACD,YAAY,EAAE,CAAC,QAAkB,EAAmB,EAAE;QACpD,OAAO;YACL,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,IAAI,EAAE,uBAAuB;YAC7B,MAAM,EAAE,QAAQ,CAAC,UAAU;gBACzB,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC;oBACvC,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,IAAI,EAAE,CAAC,CAAC,IAAI;iBACb,CAAC,CAAC;YACP,UAAU,EAAE,QAAQ,CAAC,UAAU,IAAI,KAAK;SACzC,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport {\n ActionConfig,\n ACTION_GROUPS,\n FormData,\n ValidationResult,\n FlowTypes\n} from '../types';\nimport { Node, RemoveFromGroup } from '../../store/flow-definition';\nimport { renderNamedObjects } from '../utils';\n\nexport const remove_contact_groups: ActionConfig = {\n name: 'Remove from Group',\n group: ACTION_GROUPS.contacts,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n render: (_node: Node, action: RemoveFromGroup) => {\n if (action.all_groups) {\n return html`<div>Remove from all groups</div>`;\n }\n return html`<div>${renderNamedObjects(action.groups, 'group')}</div>`;\n },\n toFormData: (action: RemoveFromGroup) => {\n return {\n uuid: action.uuid,\n all_groups: action.all_groups || false,\n groups: action.groups || null\n };\n },\n form: {\n groups: {\n type: 'select',\n label: 'Groups',\n helpText: 'Select the groups to remove the contact from',\n options: [],\n multi: true,\n searchable: true,\n endpoint: '/api/v2/groups.json',\n valueKey: 'uuid',\n nameKey: 'name',\n placeholder: 'Search for groups...',\n conditions: {\n visible: (formData) => !formData.all_groups\n }\n },\n all_groups: {\n type: 'checkbox',\n label: 'Remove from All Groups',\n helpText:\n 'Check this to remove the contact from all groups instead of specific ones'\n }\n },\n validate: (formData: FormData): ValidationResult => {\n const errors: { [key: string]: string } = {};\n\n if (\n !formData.all_groups &&\n (!formData.groups || formData.groups.length === 0)\n ) {\n errors.groups =\n 'At least one group must be selected or check \"Remove from All Groups\"';\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n fromFormData: (formData: FormData): RemoveFromGroup => {\n return {\n uuid: formData.uuid,\n type: 'remove_contact_groups',\n groups: formData.all_groups\n ? []\n : (formData.groups || []).map((g: any) => ({\n uuid: g.uuid,\n name: g.name\n })),\n all_groups: formData.all_groups || false\n };\n }\n};\n"]}
@@ -62,8 +62,12 @@ export const send_broadcast = {
62
62
  },
63
63
  fromFormData: (formData) => {
64
64
  const recipients = formData.recipients || [];
65
- const contacts = recipients.filter((r) => !r.group);
66
- const groups = recipients.filter((r) => r.group);
65
+ const contacts = recipients
66
+ .filter((r) => !r.group)
67
+ .map((c) => ({ uuid: c.uuid, name: c.name }));
68
+ const groups = recipients
69
+ .filter((r) => r.group)
70
+ .map((g) => ({ uuid: g.uuid, name: g.name }));
67
71
  const result = {
68
72
  uuid: formData.uuid,
69
73
  type: 'send_broadcast',
@@ -1 +1 @@
1
- {"version":3,"file":"send_broadcast.js","sourceRoot":"","sources":["../../../../src/flow/actions/send_broadcast.ts"],"names":[],"mappings":"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","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, ACTION_GROUPS, FormData, FlowTypes } from '../types';\nimport { Node, SendBroadcast } from '../../store/flow-definition';\nimport { renderStringList } from '../utils';\nimport { Icon } from '../../Icons';\n\nexport const send_broadcast: ActionConfig = {\n name: 'Send Broadcast',\n group: ACTION_GROUPS.broadcast,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n render: (_node: Node, action: SendBroadcast) => {\n const recipients = [\n ...(action.contacts || []).map((c) => c.name),\n ...(action.groups || []).map((g) => g.name)\n ];\n\n return html`<div>\n <div>${renderStringList(recipients, Icon.contacts)}</div>\n <div style=\"margin-top: 0.5em\">\n <div\n style=\"word-wrap: break-word; overflow-wrap: break-word; hyphens: auto;\"\n >\n ${action.text}\n </div>\n </div>\n </div>`;\n },\n\n form: {\n recipients: {\n type: 'select',\n label: 'Recipients',\n helpText: 'Select the contacts or groups to receive the broadcast',\n options: [],\n multi: true,\n searchable: true,\n endpoint: '/api/v2/contacts.json',\n valueKey: 'uuid',\n nameKey: 'name',\n placeholder: 'Search for contacts or groups...',\n required: true\n },\n text: {\n type: 'message-editor',\n label: 'Message',\n helpText:\n 'Enter the message to send with optional attachments. You can use expressions like @contact.name',\n required: true,\n evaluated: true,\n placeholder: 'Type your message here...',\n maxAttachments: 10,\n accept: '',\n endpoint: '/api/v2/media.json',\n counter: 'temba-charcount',\n gsm: true,\n autogrow: true\n }\n },\n\n layout: ['recipients', 'text'],\n\n toFormData: (action: SendBroadcast) => {\n return {\n uuid: action.uuid,\n recipients: [...(action.contacts || []), ...(action.groups || [])],\n text: action.text || '',\n attachments: action.attachments || []\n };\n },\n\n fromFormData: (formData: FormData): SendBroadcast => {\n const recipients = formData.recipients || [];\n const contacts = recipients.filter((r: any) => !r.group);\n const groups = recipients.filter((r: any) => r.group);\n\n const result: SendBroadcast = {\n uuid: formData.uuid,\n type: 'send_broadcast',\n text: formData.text || '',\n contacts,\n groups,\n attachments: formData.attachments || []\n };\n\n // Remove empty attachments array to match original format\n if (result.attachments.length === 0) {\n delete result.attachments;\n }\n\n return result;\n },\n\n sanitize: (formData: FormData): void => {\n if (formData.text && typeof formData.text === 'string') {\n formData.text = formData.text.trim();\n }\n }\n};\n"]}
1
+ {"version":3,"file":"send_broadcast.js","sourceRoot":"","sources":["../../../../src/flow/actions/send_broadcast.ts"],"names":[],"mappings":"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","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, ACTION_GROUPS, FormData, FlowTypes } from '../types';\nimport { Node, SendBroadcast } from '../../store/flow-definition';\nimport { renderStringList } from '../utils';\nimport { Icon } from '../../Icons';\n\nexport const send_broadcast: ActionConfig = {\n name: 'Send Broadcast',\n group: ACTION_GROUPS.broadcast,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n render: (_node: Node, action: SendBroadcast) => {\n const recipients = [\n ...(action.contacts || []).map((c) => c.name),\n ...(action.groups || []).map((g) => g.name)\n ];\n\n return html`<div>\n <div>${renderStringList(recipients, Icon.contacts)}</div>\n <div style=\"margin-top: 0.5em\">\n <div\n style=\"word-wrap: break-word; overflow-wrap: break-word; hyphens: auto;\"\n >\n ${action.text}\n </div>\n </div>\n </div>`;\n },\n\n form: {\n recipients: {\n type: 'select',\n label: 'Recipients',\n helpText: 'Select the contacts or groups to receive the broadcast',\n options: [],\n multi: true,\n searchable: true,\n endpoint: '/api/v2/contacts.json',\n valueKey: 'uuid',\n nameKey: 'name',\n placeholder: 'Search for contacts or groups...',\n required: true\n },\n text: {\n type: 'message-editor',\n label: 'Message',\n helpText:\n 'Enter the message to send with optional attachments. You can use expressions like @contact.name',\n required: true,\n evaluated: true,\n placeholder: 'Type your message here...',\n maxAttachments: 10,\n accept: '',\n endpoint: '/api/v2/media.json',\n counter: 'temba-charcount',\n gsm: true,\n autogrow: true\n }\n },\n\n layout: ['recipients', 'text'],\n\n toFormData: (action: SendBroadcast) => {\n return {\n uuid: action.uuid,\n recipients: [...(action.contacts || []), ...(action.groups || [])],\n text: action.text || '',\n attachments: action.attachments || []\n };\n },\n\n fromFormData: (formData: FormData): SendBroadcast => {\n const recipients = formData.recipients || [];\n const contacts = recipients\n .filter((r: any) => !r.group)\n .map((c: any) => ({ uuid: c.uuid, name: c.name }));\n const groups = recipients\n .filter((r: any) => r.group)\n .map((g: any) => ({ uuid: g.uuid, name: g.name }));\n\n const result: SendBroadcast = {\n uuid: formData.uuid,\n type: 'send_broadcast',\n text: formData.text || '',\n contacts,\n groups,\n attachments: formData.attachments || []\n };\n\n // Remove empty attachments array to match original format\n if (result.attachments.length === 0) {\n delete result.attachments;\n }\n\n return result;\n },\n\n sanitize: (formData: FormData): void => {\n if (formData.text && typeof formData.text === 'string') {\n formData.text = formData.text.trim();\n }\n }\n};\n"]}
@@ -17,6 +17,7 @@ export const set_contact_channel = {
17
17
  endpoint: '/api/v2/channels.json',
18
18
  valueKey: 'uuid',
19
19
  nameKey: 'name',
20
+ placeholder: 'Select channel',
20
21
  helpText: 'Select the channel to set for the contact'
21
22
  }
22
23
  },
@@ -25,6 +26,18 @@ export const set_contact_channel = {
25
26
  uuid: action.uuid,
26
27
  channel: action.channel ? [action.channel] : null
27
28
  };
29
+ },
30
+ fromFormData: (formData) => {
31
+ var _a;
32
+ const channel = (_a = formData.channel) === null || _a === void 0 ? void 0 : _a[0];
33
+ return {
34
+ uuid: formData.uuid,
35
+ type: 'set_contact_channel',
36
+ channel: {
37
+ uuid: channel.uuid || channel.value,
38
+ name: channel.name
39
+ }
40
+ };
28
41
  }
29
42
  };
30
43
  //# sourceMappingURL=set_contact_channel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"set_contact_channel.js","sourceRoot":"","sources":["../../../../src/flow/actions/set_contact_channel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,aAAa,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAGlE,MAAM,CAAC,MAAM,mBAAmB,GAAiB;IAC/C,IAAI,EAAE,gBAAgB;IACtB,KAAK,EAAE,aAAa,CAAC,QAAQ;IAC7B,SAAS,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,UAAU,CAAC;IACrE,MAAM,EAAE,CAAC,KAAW,EAAE,MAAyB,EAAE,EAAE;QACjD,OAAO,IAAI,CAAA,uBAAuB,MAAM,CAAC,OAAO,CAAC,IAAI,iBAAiB,CAAC;IACzE,CAAC;IACD,IAAI,EAAE;QACJ,OAAO,EAAE;YACP,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,SAAS;YAChB,QAAQ,EAAE,IAAI;YACd,UAAU,EAAE,IAAI;YAChB,SAAS,EAAE,KAAK;YAChB,QAAQ,EAAE,uBAAuB;YACjC,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,MAAM;YACf,QAAQ,EAAE,2CAA2C;SACtD;KACF;IACD,UAAU,EAAE,CAAC,MAAyB,EAAE,EAAE;QACxC,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI;SAClD,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, ACTION_GROUPS, FlowTypes } from '../types';\nimport { Node, SetContactChannel } from '../../store/flow-definition';\n\nexport const set_contact_channel: ActionConfig = {\n name: 'Update Channel',\n group: ACTION_GROUPS.contacts,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n render: (_node: Node, action: SetContactChannel) => {\n return html`<div>Set to <strong>${action.channel.name}</strong></div>`;\n },\n form: {\n channel: {\n type: 'select',\n label: 'Channel',\n required: true,\n searchable: true,\n clearable: false,\n endpoint: '/api/v2/channels.json',\n valueKey: 'uuid',\n nameKey: 'name',\n helpText: 'Select the channel to set for the contact'\n }\n },\n toFormData: (action: SetContactChannel) => {\n return {\n uuid: action.uuid,\n channel: action.channel ? [action.channel] : null\n };\n }\n};\n"]}
1
+ {"version":3,"file":"set_contact_channel.js","sourceRoot":"","sources":["../../../../src/flow/actions/set_contact_channel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,aAAa,EAAY,SAAS,EAAE,MAAM,UAAU,CAAC;AAG5E,MAAM,CAAC,MAAM,mBAAmB,GAAiB;IAC/C,IAAI,EAAE,gBAAgB;IACtB,KAAK,EAAE,aAAa,CAAC,QAAQ;IAC7B,SAAS,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,UAAU,CAAC;IACrE,MAAM,EAAE,CAAC,KAAW,EAAE,MAAyB,EAAE,EAAE;QACjD,OAAO,IAAI,CAAA,uBAAuB,MAAM,CAAC,OAAO,CAAC,IAAI,iBAAiB,CAAC;IACzE,CAAC;IACD,IAAI,EAAE;QACJ,OAAO,EAAE;YACP,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,SAAS;YAChB,QAAQ,EAAE,IAAI;YACd,UAAU,EAAE,IAAI;YAChB,SAAS,EAAE,KAAK;YAChB,QAAQ,EAAE,uBAAuB;YACjC,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,MAAM;YACf,WAAW,EAAE,gBAAgB;YAC7B,QAAQ,EAAE,2CAA2C;SACtD;KACF;IACD,UAAU,EAAE,CAAC,MAAyB,EAAE,EAAE;QACxC,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI;SAClD,CAAC;IACJ,CAAC;IACD,YAAY,EAAE,CAAC,QAAkB,EAAqB,EAAE;;QACtD,MAAM,OAAO,GAAG,MAAA,QAAQ,CAAC,OAAO,0CAAG,CAAC,CAAC,CAAC;QACtC,OAAO;YACL,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,IAAI,EAAE,qBAAqB;YAC3B,OAAO,EAAE;gBACP,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,KAAK;gBACnC,IAAI,EAAE,OAAO,CAAC,IAAI;aACnB;SACF,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, ACTION_GROUPS, FormData, FlowTypes } from '../types';\nimport { Node, SetContactChannel } from '../../store/flow-definition';\n\nexport const set_contact_channel: ActionConfig = {\n name: 'Update Channel',\n group: ACTION_GROUPS.contacts,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n render: (_node: Node, action: SetContactChannel) => {\n return html`<div>Set to <strong>${action.channel.name}</strong></div>`;\n },\n form: {\n channel: {\n type: 'select',\n label: 'Channel',\n required: true,\n searchable: true,\n clearable: false,\n endpoint: '/api/v2/channels.json',\n valueKey: 'uuid',\n nameKey: 'name',\n placeholder: 'Select channel',\n helpText: 'Select the channel to set for the contact'\n }\n },\n toFormData: (action: SetContactChannel) => {\n return {\n uuid: action.uuid,\n channel: action.channel ? [action.channel] : null\n };\n },\n fromFormData: (formData: FormData): SetContactChannel => {\n const channel = formData.channel?.[0];\n return {\n uuid: formData.uuid,\n type: 'set_contact_channel',\n channel: {\n uuid: channel.uuid || channel.value,\n name: channel.name\n }\n };\n }\n};\n"]}
@@ -10,11 +10,13 @@ export const set_contact_status = {
10
10
  },
11
11
  toFormData: (action) => {
12
12
  return {
13
- ...action,
14
- status: {
15
- name: titleCase(action.status || 'active'),
16
- value: action.status || 'active'
17
- }
13
+ uuid: action.uuid,
14
+ status: [
15
+ {
16
+ name: titleCase(action.status || 'active'),
17
+ value: action.status || 'active'
18
+ }
19
+ ]
18
20
  };
19
21
  },
20
22
  fromFormData: (formData) => {
@@ -1 +1 @@
1
- {"version":3,"file":"set_contact_status.js","sourceRoot":"","sources":["../../../../src/flow/actions/set_contact_status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,aAAa,EAAY,SAAS,EAAE,MAAM,UAAU,CAAC;AAE5E,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,MAAM,CAAC,MAAM,kBAAkB,GAAiB;IAC9C,IAAI,EAAE,eAAe;IACrB,KAAK,EAAE,aAAa,CAAC,QAAQ;IAC7B,SAAS,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,UAAU,CAAC;IACrE,MAAM,EAAE,CAAC,KAAW,EAAE,MAAwB,EAAE,EAAE;QAChD,OAAO,IAAI,CAAA,uBAAuB,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC;IAC9E,CAAC;IACD,UAAU,EAAE,CAAC,MAAwB,EAAE,EAAE;QACvC,OAAO;YACL,GAAG,MAAM;YACT,MAAM,EAAE;gBACN,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,IAAI,QAAQ,CAAC;gBAC1C,KAAK,EAAE,MAAM,CAAC,MAAM,IAAI,QAAQ;aACjC;SACF,CAAC;IACJ,CAAC;IACD,YAAY,EAAE,CAAC,QAAkB,EAAoB,EAAE;QACrD,OAAO;YACL,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK;YAChC,IAAI,EAAE,oBAAoB;YAC1B,IAAI,EAAE,QAAQ,CAAC,IAAI;SACpB,CAAC;IACJ,CAAC;IACD,IAAI,EAAE;QACJ,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,QAAQ;YACf,QAAQ,EAAE,IAAI;YACd,UAAU,EAAE,KAAK;YACjB,SAAS,EAAE,KAAK;YAChB,OAAO,EAAE;gBACP,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACnC,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE;gBACvC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE;gBACrC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE;aACtC;YACD,QAAQ,EAAE,0CAA0C;SACrD;KACF;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, ACTION_GROUPS, FormData, FlowTypes } from '../types';\nimport { Node, SetContactStatus } from '../../store/flow-definition';\nimport { titleCase } from '../../utils';\n\nexport const set_contact_status: ActionConfig = {\n name: 'Update Status',\n group: ACTION_GROUPS.contacts,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n render: (_node: Node, action: SetContactStatus) => {\n return html`<div>Set to <strong>${titleCase(action.status)}</strong></div>`;\n },\n toFormData: (action: SetContactStatus) => {\n return {\n ...action,\n status: {\n name: titleCase(action.status || 'active'),\n value: action.status || 'active'\n }\n };\n },\n fromFormData: (formData: FormData): SetContactStatus => {\n return {\n status: formData.status[0].value,\n type: 'set_contact_status',\n uuid: formData.uuid\n };\n },\n form: {\n status: {\n type: 'select',\n label: 'Status',\n required: true,\n searchable: false,\n clearable: false,\n options: [\n { value: 'active', name: 'Active' },\n { value: 'archived', name: 'Archived' },\n { value: 'stopped', name: 'Stopped' },\n { value: 'blocked', name: 'Blocked' }\n ],\n helpText: 'Select the status to set for the contact'\n }\n }\n};\n"]}
1
+ {"version":3,"file":"set_contact_status.js","sourceRoot":"","sources":["../../../../src/flow/actions/set_contact_status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,aAAa,EAAY,SAAS,EAAE,MAAM,UAAU,CAAC;AAE5E,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,MAAM,CAAC,MAAM,kBAAkB,GAAiB;IAC9C,IAAI,EAAE,eAAe;IACrB,KAAK,EAAE,aAAa,CAAC,QAAQ;IAC7B,SAAS,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,UAAU,CAAC;IACrE,MAAM,EAAE,CAAC,KAAW,EAAE,MAAwB,EAAE,EAAE;QAChD,OAAO,IAAI,CAAA,uBAAuB,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC;IAC9E,CAAC;IACD,UAAU,EAAE,CAAC,MAAwB,EAAE,EAAE;QACvC,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,MAAM,EAAE;gBACN;oBACE,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,IAAI,QAAQ,CAAC;oBAC1C,KAAK,EAAE,MAAM,CAAC,MAAM,IAAI,QAAQ;iBACjC;aACF;SACF,CAAC;IACJ,CAAC;IACD,YAAY,EAAE,CAAC,QAAkB,EAAoB,EAAE;QACrD,OAAO;YACL,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK;YAChC,IAAI,EAAE,oBAAoB;YAC1B,IAAI,EAAE,QAAQ,CAAC,IAAI;SACpB,CAAC;IACJ,CAAC;IACD,IAAI,EAAE;QACJ,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,QAAQ;YACf,QAAQ,EAAE,IAAI;YACd,UAAU,EAAE,KAAK;YACjB,SAAS,EAAE,KAAK;YAChB,OAAO,EAAE;gBACP,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACnC,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE;gBACvC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE;gBACrC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE;aACtC;YACD,QAAQ,EAAE,0CAA0C;SACrD;KACF;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, ACTION_GROUPS, FormData, FlowTypes } from '../types';\nimport { Node, SetContactStatus } from '../../store/flow-definition';\nimport { titleCase } from '../../utils';\n\nexport const set_contact_status: ActionConfig = {\n name: 'Update Status',\n group: ACTION_GROUPS.contacts,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n render: (_node: Node, action: SetContactStatus) => {\n return html`<div>Set to <strong>${titleCase(action.status)}</strong></div>`;\n },\n toFormData: (action: SetContactStatus) => {\n return {\n uuid: action.uuid,\n status: [\n {\n name: titleCase(action.status || 'active'),\n value: action.status || 'active'\n }\n ]\n };\n },\n fromFormData: (formData: FormData): SetContactStatus => {\n return {\n status: formData.status[0].value,\n type: 'set_contact_status',\n uuid: formData.uuid\n };\n },\n form: {\n status: {\n type: 'select',\n label: 'Status',\n required: true,\n searchable: false,\n clearable: false,\n options: [\n { value: 'active', name: 'Active' },\n { value: 'archived', name: 'Archived' },\n { value: 'stopped', name: 'Stopped' },\n { value: 'blocked', name: 'Blocked' }\n ],\n helpText: 'Select the status to set for the contact'\n }\n }\n};\n"]}
@@ -157,7 +157,10 @@ export const start_session = {
157
157
  const action = {
158
158
  uuid: formData.uuid,
159
159
  type: 'start_session',
160
- flow: formData.flow[0],
160
+ flow: {
161
+ uuid: formData.flow[0].uuid || formData.flow[0].value,
162
+ name: formData.flow[0].name
163
+ },
161
164
  groups: [],
162
165
  contacts: []
163
166
  };
@@ -173,8 +176,12 @@ export const start_session = {
173
176
  else {
174
177
  // Manual selection - separate contacts and groups
175
178
  const recipients = formData.recipients || [];
176
- action.contacts = recipients.filter((r) => !r.group);
177
- action.groups = recipients.filter((r) => r.group);
179
+ action.contacts = recipients
180
+ .filter((r) => !r.group)
181
+ .map((c) => ({ uuid: c.uuid, name: c.name }));
182
+ action.groups = recipients
183
+ .filter((r) => r.group)
184
+ .map((g) => ({ uuid: g.uuid, name: g.name }));
178
185
  }
179
186
  // Add exclusions if set
180
187
  if (formData.skipContactsInFlow) {
@@ -1 +1 @@
1
- {"version":3,"file":"start_session.js","sourceRoot":"","sources":["../../../../src/flow/actions/start_session.ts"],"names":[],"mappings":"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","sourcesContent":["import { html } from 'lit-html';\nimport {\n ActionConfig,\n ACTION_GROUPS,\n FormData,\n ValidationResult,\n FlowTypes\n} from '../types';\nimport { Node, StartSession } from '../../store/flow-definition';\nimport { renderNamedObjects } from '../utils';\n\nexport const start_session: ActionConfig = {\n name: 'Start Flow',\n group: ACTION_GROUPS.broadcast,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n render: (_node: Node, action: StartSession) => {\n const hasGroups = action.groups && action.groups.length > 0;\n const hasContacts = action.contacts && action.contacts.length > 0;\n const hasRecipients = hasGroups || hasContacts;\n\n // Build the recipients display\n let recipientsDisplay = html``;\n if (action.create_contact) {\n recipientsDisplay = html`Create a new contact`;\n } else if ((action as any).contact_query) {\n recipientsDisplay = html`${(action as any).contact_query}`;\n } else if (hasRecipients) {\n const allRecipients = [\n ...(action.contacts || []),\n ...(action.groups || [])\n ];\n recipientsDisplay = html`${renderNamedObjects(\n allRecipients,\n hasGroups ? 'group' : 'contact'\n )}`;\n }\n\n return html`\n <div>\n <div\n style=\"padding: 3px 10px; background: #f5f5f5; padding-bottom: 0px; font-size: 11px; border-radius: var(--curvature); margin-bottom: 10px;\"\n >\n ${recipientsDisplay}\n </div>\n <div style=\"padding: 0px 10px;\">\n ${renderNamedObjects([action.flow], 'flow')}\n </div>\n </div>\n `;\n },\n\n toFormData: (action: StartSession) => {\n const extendedAction = action as StartSession & {\n contact_query?: string;\n exclusions?: { in_a_flow?: boolean };\n };\n\n // Determine start type based on action properties\n let startTypeValue = 'manual';\n if (action.create_contact) {\n startTypeValue = 'create';\n } else if (extendedAction.contact_query) {\n startTypeValue = 'query';\n }\n\n // Map value to full option object for proper display\n const startTypeOptions = [\n { value: 'manual', name: 'Select recipients manually' },\n { value: 'query', name: 'Select a contact with a query' },\n { value: 'create', name: 'Create a new contact' }\n ];\n const startType =\n startTypeOptions.find((opt) => opt.value === startTypeValue) ||\n startTypeOptions[0];\n\n return {\n flow: action.flow ? [action.flow] : null,\n recipients: [...(action.contacts || []), ...(action.groups || [])],\n startType: [startType],\n contactQuery: extendedAction.contact_query || '',\n skipContactsInFlow: extendedAction.exclusions?.in_a_flow || false,\n uuid: action.uuid\n };\n },\n\n form: {\n flow: {\n type: 'select',\n label: 'Flow',\n helpText: 'Select the flow to start',\n required: true,\n searchable: true,\n endpoint: '/api/v2/flows.json',\n valueKey: 'uuid',\n nameKey: 'name',\n placeholder: 'Select a flow...'\n },\n startType: {\n type: 'select',\n label: 'Start Type',\n helpText: 'How should contacts be selected?',\n required: true,\n options: [\n { value: 'manual', name: 'Select recipients manually' },\n { value: 'query', name: 'Select a contact with a query' },\n { value: 'create', name: 'Create a new contact' }\n ]\n },\n recipients: {\n type: 'select',\n label: 'Recipients',\n helpText: 'Select who should be started in the flow',\n options: [],\n multi: true,\n searchable: true,\n endpoint: '/api/v2/contacts.json',\n valueKey: 'uuid',\n nameKey: 'name',\n placeholder: 'Search for contacts or groups...',\n conditions: {\n visible: (formData: FormData) => {\n const startType = formData.startType?.[0]?.value;\n return startType === 'manual';\n }\n }\n },\n contactQuery: {\n type: 'text',\n evaluated: true,\n label: 'Contact Query',\n helpText: 'Only one matching contact will be started',\n placeholder: 'household_id = @fields.household_id',\n conditions: {\n visible: (formData: FormData) => {\n const startType = formData.startType?.[0]?.value;\n return startType === 'query';\n }\n }\n },\n skipContactsInFlow: {\n type: 'checkbox',\n label: 'Skip contacts currently in a flow',\n helpText: 'Avoid interrupting a contact who is already in a flow'\n }\n },\n\n layout: [\n 'flow',\n 'startType',\n 'recipients',\n 'contactQuery',\n 'skipContactsInFlow'\n ],\n\n validate: (formData: FormData): ValidationResult => {\n const errors: { [key: string]: string } = {};\n\n const startType = formData.startType?.[0]?.value;\n\n // Check if manual selection has recipients\n if (\n startType === 'manual' &&\n (!formData.recipients || formData.recipients.length === 0)\n ) {\n errors.recipients = 'At least one contact or group must be selected';\n }\n\n // Check if query has a query string\n if (\n startType === 'query' &&\n (!formData.contactQuery || !formData.contactQuery.trim())\n ) {\n errors.contactQuery = 'Contact query is required';\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n\n fromFormData: (formData: FormData): StartSession => {\n const action: StartSession & {\n contact_query?: string;\n exclusions?: { in_a_flow: boolean };\n } = {\n uuid: formData.uuid,\n type: 'start_session',\n flow: formData.flow[0],\n groups: [],\n contacts: []\n };\n\n // Get the start type value from array\n const startTypeValue = formData.startType[0].value;\n\n // Handle different start types\n if (startTypeValue === 'create') {\n action.create_contact = true;\n } else if (startTypeValue === 'query') {\n action.contact_query = formData.contactQuery || '';\n } else {\n // Manual selection - separate contacts and groups\n const recipients = formData.recipients || [];\n action.contacts = recipients.filter((r: any) => !r.group);\n action.groups = recipients.filter((r: any) => r.group);\n }\n\n // Add exclusions if set\n if (formData.skipContactsInFlow) {\n action.exclusions = { in_a_flow: true };\n }\n\n return action;\n }\n};\n"]}
1
+ {"version":3,"file":"start_session.js","sourceRoot":"","sources":["../../../../src/flow/actions/start_session.ts"],"names":[],"mappings":"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","sourcesContent":["import { html } from 'lit-html';\nimport {\n ActionConfig,\n ACTION_GROUPS,\n FormData,\n ValidationResult,\n FlowTypes\n} from '../types';\nimport { Node, StartSession } from '../../store/flow-definition';\nimport { renderNamedObjects } from '../utils';\n\nexport const start_session: ActionConfig = {\n name: 'Start Flow',\n group: ACTION_GROUPS.broadcast,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n render: (_node: Node, action: StartSession) => {\n const hasGroups = action.groups && action.groups.length > 0;\n const hasContacts = action.contacts && action.contacts.length > 0;\n const hasRecipients = hasGroups || hasContacts;\n\n // Build the recipients display\n let recipientsDisplay = html``;\n if (action.create_contact) {\n recipientsDisplay = html`Create a new contact`;\n } else if ((action as any).contact_query) {\n recipientsDisplay = html`${(action as any).contact_query}`;\n } else if (hasRecipients) {\n const allRecipients = [\n ...(action.contacts || []),\n ...(action.groups || [])\n ];\n recipientsDisplay = html`${renderNamedObjects(\n allRecipients,\n hasGroups ? 'group' : 'contact'\n )}`;\n }\n\n return html`\n <div>\n <div\n style=\"padding: 3px 10px; background: #f5f5f5; padding-bottom: 0px; font-size: 11px; border-radius: var(--curvature); margin-bottom: 10px;\"\n >\n ${recipientsDisplay}\n </div>\n <div style=\"padding: 0px 10px;\">\n ${renderNamedObjects([action.flow], 'flow')}\n </div>\n </div>\n `;\n },\n\n toFormData: (action: StartSession) => {\n const extendedAction = action as StartSession & {\n contact_query?: string;\n exclusions?: { in_a_flow?: boolean };\n };\n\n // Determine start type based on action properties\n let startTypeValue = 'manual';\n if (action.create_contact) {\n startTypeValue = 'create';\n } else if (extendedAction.contact_query) {\n startTypeValue = 'query';\n }\n\n // Map value to full option object for proper display\n const startTypeOptions = [\n { value: 'manual', name: 'Select recipients manually' },\n { value: 'query', name: 'Select a contact with a query' },\n { value: 'create', name: 'Create a new contact' }\n ];\n const startType =\n startTypeOptions.find((opt) => opt.value === startTypeValue) ||\n startTypeOptions[0];\n\n return {\n flow: action.flow ? [action.flow] : null,\n recipients: [...(action.contacts || []), ...(action.groups || [])],\n startType: [startType],\n contactQuery: extendedAction.contact_query || '',\n skipContactsInFlow: extendedAction.exclusions?.in_a_flow || false,\n uuid: action.uuid\n };\n },\n\n form: {\n flow: {\n type: 'select',\n label: 'Flow',\n helpText: 'Select the flow to start',\n required: true,\n searchable: true,\n endpoint: '/api/v2/flows.json',\n valueKey: 'uuid',\n nameKey: 'name',\n placeholder: 'Select a flow...'\n },\n startType: {\n type: 'select',\n label: 'Start Type',\n helpText: 'How should contacts be selected?',\n required: true,\n options: [\n { value: 'manual', name: 'Select recipients manually' },\n { value: 'query', name: 'Select a contact with a query' },\n { value: 'create', name: 'Create a new contact' }\n ]\n },\n recipients: {\n type: 'select',\n label: 'Recipients',\n helpText: 'Select who should be started in the flow',\n options: [],\n multi: true,\n searchable: true,\n endpoint: '/api/v2/contacts.json',\n valueKey: 'uuid',\n nameKey: 'name',\n placeholder: 'Search for contacts or groups...',\n conditions: {\n visible: (formData: FormData) => {\n const startType = formData.startType?.[0]?.value;\n return startType === 'manual';\n }\n }\n },\n contactQuery: {\n type: 'text',\n evaluated: true,\n label: 'Contact Query',\n helpText: 'Only one matching contact will be started',\n placeholder: 'household_id = @fields.household_id',\n conditions: {\n visible: (formData: FormData) => {\n const startType = formData.startType?.[0]?.value;\n return startType === 'query';\n }\n }\n },\n skipContactsInFlow: {\n type: 'checkbox',\n label: 'Skip contacts currently in a flow',\n helpText: 'Avoid interrupting a contact who is already in a flow'\n }\n },\n\n layout: [\n 'flow',\n 'startType',\n 'recipients',\n 'contactQuery',\n 'skipContactsInFlow'\n ],\n\n validate: (formData: FormData): ValidationResult => {\n const errors: { [key: string]: string } = {};\n\n const startType = formData.startType?.[0]?.value;\n\n // Check if manual selection has recipients\n if (\n startType === 'manual' &&\n (!formData.recipients || formData.recipients.length === 0)\n ) {\n errors.recipients = 'At least one contact or group must be selected';\n }\n\n // Check if query has a query string\n if (\n startType === 'query' &&\n (!formData.contactQuery || !formData.contactQuery.trim())\n ) {\n errors.contactQuery = 'Contact query is required';\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n\n fromFormData: (formData: FormData): StartSession => {\n const action: StartSession & {\n contact_query?: string;\n exclusions?: { in_a_flow: boolean };\n } = {\n uuid: formData.uuid,\n type: 'start_session',\n flow: {\n uuid: formData.flow[0].uuid || formData.flow[0].value,\n name: formData.flow[0].name\n },\n groups: [],\n contacts: []\n };\n\n // Get the start type value from array\n const startTypeValue = formData.startType[0].value;\n\n // Handle different start types\n if (startTypeValue === 'create') {\n action.create_contact = true;\n } else if (startTypeValue === 'query') {\n action.contact_query = formData.contactQuery || '';\n } else {\n // Manual selection - separate contacts and groups\n const recipients = formData.recipients || [];\n action.contacts = recipients\n .filter((r: any) => !r.group)\n .map((c: any) => ({ uuid: c.uuid, name: c.name }));\n action.groups = recipients\n .filter((r: any) => r.group)\n .map((g: any) => ({ uuid: g.uuid, name: g.name }));\n }\n\n // Add exclusions if set\n if (formData.skipContactsInFlow) {\n action.exclusions = { in_a_flow: true };\n }\n\n return action;\n }\n};\n"]}
@@ -23,10 +23,10 @@ const getOperandForField = (field) => {
23
23
  }
24
24
  // For system properties, use the id
25
25
  if (field.type === 'property') {
26
- return `@contact.${field.id}`;
26
+ return `@contact.${field.id || field.value}`;
27
27
  }
28
- // Fallback to key
29
- return `@fields.${field.key}`;
28
+ // For custom fields, use key with fallbacks
29
+ return `@fields.${field.key || field.id || field.value}`;
30
30
  };
31
31
  export const split_by_contact_field = {
32
32
  type: 'split_by_contact_field',
@@ -59,7 +59,7 @@ export const split_by_contact_field = {
59
59
  }))
60
60
  ]
61
61
  },
62
- rules: createRulesArrayConfig(operatorsToSelectOptions(getWaitForResponseOperators()), 'Define rules to split the contact field into categories'),
62
+ rules: createRulesArrayConfig(operatorsToSelectOptions(getWaitForResponseOperators()), ''),
63
63
  result_name: resultNameField
64
64
  },
65
65
  layout: ['field', 'rules', 'result_name'],
@@ -76,7 +76,20 @@ export const split_by_contact_field = {
76
76
  toFormData: (node, nodeUI) => {
77
77
  var _a, _b;
78
78
  // Get the field from the UI config operand (source of truth)
79
- const field = ((_a = nodeUI === null || nodeUI === void 0 ? void 0 : nodeUI.config) === null || _a === void 0 ? void 0 : _a.operand) || CONTACT_PROPERTIES.name;
79
+ const operand = ((_a = nodeUI === null || nodeUI === void 0 ? void 0 : nodeUI.config) === null || _a === void 0 ? void 0 : _a.operand) || CONTACT_PROPERTIES.name;
80
+ // Normalize the field object to include properties expected by
81
+ // the Select component (valueKey: 'key') and getOperandForField.
82
+ // toUIConfig saves only { id, name, type }, so we need to add
83
+ // 'key' for custom fields and 'value' for static option matching.
84
+ const field = { ...operand };
85
+ if (field.type === 'field') {
86
+ if (!field.key)
87
+ field.key = field.id;
88
+ }
89
+ else {
90
+ if (!field.value)
91
+ field.value = field.id;
92
+ }
80
93
  // Extract rules from router cases using shared function
81
94
  const rules = casesToFormRules(node);
82
95
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"split_by_contact_field.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_contact_field.ts"],"names":[],"mappings":"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","sourcesContent":["import { SPLIT_GROUPS, FormData, NodeConfig, FlowTypes } from '../types';\nimport { Node } from '../../store/flow-definition';\nimport { createRulesRouter } from '../../utils';\nimport {\n getWaitForResponseOperators,\n operatorsToSelectOptions,\n getOperatorConfig\n} from '../operators';\nimport {\n resultNameField,\n categoriesToLocalizationFormData,\n localizationFormDataToCategories\n} from './shared';\nimport {\n createRulesArrayConfig,\n extractUserRules,\n casesToFormRules\n} from './shared-rules';\nimport { SCHEMES } from '../utils';\nimport { html } from 'lit';\n\n// System contact properties that can be split on\nexport const CONTACT_PROPERTIES = {\n name: { id: 'name', name: 'Name', type: 'property' },\n language: { id: 'language', name: 'Language', type: 'property' },\n status: { id: 'status', name: 'Status', type: 'property' },\n channel: { id: 'channel', name: 'Channel', type: 'property' }\n};\n\n// Helper to get operand for the selected field\nconst getOperandForField = (field: any): string => {\n // For URN schemes, split on the URN path (the actual ID value like Facebook ID)\n // Note: This is different from split_by_scheme which splits on the scheme type itself\n if (field.type === 'scheme') {\n // field.id or field.value will be the scheme name like 'facebook', 'whatsapp', etc\n const schemeId = field.id || field.value;\n return `@(default(urn_parts(urns.${schemeId}).path, \"\"))`;\n }\n // For system properties, use the id\n if (field.type === 'property') {\n return `@contact.${field.id}`;\n }\n // Fallback to key\n return `@fields.${field.key}`;\n};\n\nexport const split_by_contact_field: NodeConfig = {\n type: 'split_by_contact_field',\n name: 'Split by Contact Field',\n group: SPLIT_GROUPS.split,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n dialogSize: 'large',\n form: {\n field: {\n type: 'select',\n required: true,\n searchable: true,\n clearable: false,\n endpoint: '/api/v2/fields.json',\n valueKey: 'key',\n nameKey: 'name',\n placeholder: 'Select a field...',\n // Provide system properties as fixed options at the top\n options: [\n ...Object.values(CONTACT_PROPERTIES).map((prop) => ({\n value: prop.id,\n name: prop.name,\n type: prop.type\n })),\n // Add all URN scheme options (they represent splitting on the URN value, like Facebook ID)\n ...SCHEMES.filter((scheme) => !scheme.excludeFromSplit).map(\n (scheme) => ({\n value: scheme.scheme,\n name: scheme.path,\n type: 'scheme'\n })\n )\n ]\n },\n rules: createRulesArrayConfig(\n operatorsToSelectOptions(getWaitForResponseOperators()),\n 'Define rules to split the contact field into categories'\n ),\n result_name: resultNameField\n },\n layout: ['field', 'rules', 'result_name'],\n validate: (formData: FormData) => {\n const errors: { [key: string]: string } = {};\n\n if (!formData.field || formData.field.length === 0) {\n errors.field = 'A field 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 field from the UI config operand (source of truth)\n const field = nodeUI?.config?.operand || CONTACT_PROPERTIES.name;\n\n // Extract rules from router cases using shared function\n const rules = casesToFormRules(node);\n\n return {\n uuid: node.uuid,\n field: [field],\n rules: rules,\n result_name: node.router?.result_name || ''\n };\n },\n fromFormData: (formData: FormData, originalNode: Node): Node => {\n // Get selected field (it's an array from the select component)\n const selectedField = formData.field?.[0];\n\n if (!selectedField) {\n return originalNode;\n }\n\n // Get operand for the selected field\n const operand = getOperandForField(selectedField);\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 field (it's an array from the select component)\n const selectedField = formData.field?.[0];\n\n if (!selectedField) {\n return {};\n }\n\n // For scheme types, the id should be the scheme name (facebook, whatsapp, etc)\n // For custom fields, the id should be the field key\n // For system properties, the id should be the property id\n let operandId =\n selectedField.id || selectedField.value || selectedField.key;\n\n // If this is a scheme type, ensure we use the scheme name as the id\n if (selectedField.type === 'scheme') {\n operandId = selectedField.value || selectedField.id;\n }\n\n let type = selectedField.type;\n if (type !== 'property' && type !== 'scheme') {\n type = 'field';\n }\n\n // Return UI config with operand information for persistence\n return {\n operand: {\n id: operandId,\n name: selectedField.name || selectedField.label,\n type\n }\n };\n },\n renderTitle: (node: Node, nodeUI?: any) => {\n return html`<div>Split by ${nodeUI.config.operand.name}</div>`;\n },\n\n // Localization support for categories\n localizable: 'categories',\n toLocalizationFormData: categoriesToLocalizationFormData,\n fromLocalizationFormData: localizationFormDataToCategories\n};\n"]}
1
+ {"version":3,"file":"split_by_contact_field.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_contact_field.ts"],"names":[],"mappings":"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","sourcesContent":["import { SPLIT_GROUPS, FormData, NodeConfig, FlowTypes } from '../types';\nimport { Node } from '../../store/flow-definition';\nimport { createRulesRouter } from '../../utils';\nimport {\n getWaitForResponseOperators,\n operatorsToSelectOptions,\n getOperatorConfig\n} from '../operators';\nimport {\n resultNameField,\n categoriesToLocalizationFormData,\n localizationFormDataToCategories\n} from './shared';\nimport {\n createRulesArrayConfig,\n extractUserRules,\n casesToFormRules\n} from './shared-rules';\nimport { SCHEMES } from '../utils';\nimport { html } from 'lit';\n\n// System contact properties that can be split on\nexport const CONTACT_PROPERTIES = {\n name: { id: 'name', name: 'Name', type: 'property' },\n language: { id: 'language', name: 'Language', type: 'property' },\n status: { id: 'status', name: 'Status', type: 'property' },\n channel: { id: 'channel', name: 'Channel', type: 'property' }\n};\n\n// Helper to get operand for the selected field\nconst getOperandForField = (field: any): string => {\n // For URN schemes, split on the URN path (the actual ID value like Facebook ID)\n // Note: This is different from split_by_scheme which splits on the scheme type itself\n if (field.type === 'scheme') {\n // field.id or field.value will be the scheme name like 'facebook', 'whatsapp', etc\n const schemeId = field.id || field.value;\n return `@(default(urn_parts(urns.${schemeId}).path, \"\"))`;\n }\n // For system properties, use the id\n if (field.type === 'property') {\n return `@contact.${field.id || field.value}`;\n }\n // For custom fields, use key with fallbacks\n return `@fields.${field.key || field.id || field.value}`;\n};\n\nexport const split_by_contact_field: NodeConfig = {\n type: 'split_by_contact_field',\n name: 'Split by Contact Field',\n group: SPLIT_GROUPS.split,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n dialogSize: 'large',\n form: {\n field: {\n type: 'select',\n required: true,\n searchable: true,\n clearable: false,\n endpoint: '/api/v2/fields.json',\n valueKey: 'key',\n nameKey: 'name',\n placeholder: 'Select a field...',\n // Provide system properties as fixed options at the top\n options: [\n ...Object.values(CONTACT_PROPERTIES).map((prop) => ({\n value: prop.id,\n name: prop.name,\n type: prop.type\n })),\n // Add all URN scheme options (they represent splitting on the URN value, like Facebook ID)\n ...SCHEMES.filter((scheme) => !scheme.excludeFromSplit).map(\n (scheme) => ({\n value: scheme.scheme,\n name: scheme.path,\n type: 'scheme'\n })\n )\n ]\n },\n rules: createRulesArrayConfig(\n operatorsToSelectOptions(getWaitForResponseOperators()),\n ''\n ),\n result_name: resultNameField\n },\n layout: ['field', 'rules', 'result_name'],\n validate: (formData: FormData) => {\n const errors: { [key: string]: string } = {};\n\n if (!formData.field || formData.field.length === 0) {\n errors.field = 'A field 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 field from the UI config operand (source of truth)\n const operand = nodeUI?.config?.operand || CONTACT_PROPERTIES.name;\n\n // Normalize the field object to include properties expected by\n // the Select component (valueKey: 'key') and getOperandForField.\n // toUIConfig saves only { id, name, type }, so we need to add\n // 'key' for custom fields and 'value' for static option matching.\n const field = { ...operand };\n if (field.type === 'field') {\n if (!field.key) field.key = field.id;\n } else {\n if (!field.value) field.value = field.id;\n }\n\n // Extract rules from router cases using shared function\n const rules = casesToFormRules(node);\n\n return {\n uuid: node.uuid,\n field: [field],\n rules: rules,\n result_name: node.router?.result_name || ''\n };\n },\n fromFormData: (formData: FormData, originalNode: Node): Node => {\n // Get selected field (it's an array from the select component)\n const selectedField = formData.field?.[0];\n\n if (!selectedField) {\n return originalNode;\n }\n\n // Get operand for the selected field\n const operand = getOperandForField(selectedField);\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 field (it's an array from the select component)\n const selectedField = formData.field?.[0];\n\n if (!selectedField) {\n return {};\n }\n\n // For scheme types, the id should be the scheme name (facebook, whatsapp, etc)\n // For custom fields, the id should be the field key\n // For system properties, the id should be the property id\n let operandId =\n selectedField.id || selectedField.value || selectedField.key;\n\n // If this is a scheme type, ensure we use the scheme name as the id\n if (selectedField.type === 'scheme') {\n operandId = selectedField.value || selectedField.id;\n }\n\n let type = selectedField.type;\n if (type !== 'property' && type !== 'scheme') {\n type = 'field';\n }\n\n // Return UI config with operand information for persistence\n return {\n operand: {\n id: operandId,\n name: selectedField.name || selectedField.label,\n type\n }\n };\n },\n renderTitle: (node: Node, nodeUI?: any) => {\n return html`<div>Split by ${nodeUI.config.operand.name}</div>`;\n },\n\n // Localization support for categories\n localizable: 'categories',\n toLocalizationFormData: categoriesToLocalizationFormData,\n fromLocalizationFormData: localizationFormDataToCategories\n};\n"]}
@@ -18,7 +18,7 @@ export const split_by_expression = {
18
18
  evaluated: true,
19
19
  placeholder: '@fields.age'
20
20
  },
21
- rules: createRulesArrayConfig(operatorsToSelectOptions(getWaitForResponseOperators()), 'Define rules to categorize the expression result'),
21
+ rules: createRulesArrayConfig(operatorsToSelectOptions(getWaitForResponseOperators()), ''),
22
22
  result_name: resultNameField
23
23
  },
24
24
  layout: ['operand', 'rules', 'result_name'],
@@ -1 +1 @@
1
- {"version":3,"file":"split_by_expression.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_expression.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAwB,SAAS,EAAE,MAAM,UAAU,CAAC;AAEzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EACL,2BAA2B,EAC3B,wBAAwB,EACxB,iBAAiB,EAClB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,eAAe,EACf,gCAAgC,EAChC,gCAAgC,EACjC,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,gBAAgB,CAAC;AAExB,MAAM,CAAC,MAAM,mBAAmB,GAAe;IAC7C,IAAI,EAAE,qBAAqB;IAC3B,IAAI,EAAE,qBAAqB;IAC3B,KAAK,EAAE,YAAY,CAAC,KAAK;IACzB,SAAS,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,UAAU,CAAC;IACrE,UAAU,EAAE,OAAO;IACnB,IAAI,EAAE;QACJ,OAAO,EAAE;YACP,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,YAAY;YACnB,QAAQ,EAAE,yCAAyC;YACnD,QAAQ,EAAE,IAAI;YACd,SAAS,EAAE,IAAI;YACf,WAAW,EAAE,aAAa;SAC3B;QACD,KAAK,EAAE,sBAAsB,CAC3B,wBAAwB,CAAC,2BAA2B,EAAE,CAAC,EACvD,kDAAkD,CACnD;QACD,WAAW,EAAE,eAAe;KAC7B;IACD,MAAM,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,aAAa,CAAC;IAC3C,QAAQ,EAAE,CAAC,QAAkB,EAAE,EAAE;QAC/B,MAAM,MAAM,GAA8B,EAAE,CAAC;QAE7C,+BAA+B;QAC/B,IAAI,CAAC,QAAQ,CAAC,OAAO,IAAI,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACxD,MAAM,CAAC,OAAO,GAAG,wBAAwB,CAAC;QAC5C,CAAC;QAED,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC;YACvC,MAAM;SACP,CAAC;IACJ,CAAC;IACD,UAAU,EAAE,CAAC,IAAU,EAAE,EAAE;;QACzB,wDAAwD;QACxD,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAErC,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,CAAA,MAAA,IAAI,CAAC,MAAM,0CAAE,OAAO,KAAI,aAAa;YAC9C,KAAK,EAAE,KAAK;YACZ,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,kDAAkD;QAClD,MAAM,SAAS,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAE7C,6BAA6B;QAC7B,MAAM,OAAO,GAAG,CAAA,MAAA,QAAQ,CAAC,OAAO,0CAAE,IAAI,EAAE,KAAI,aAAa,CAAC;QAE1D,4CAA4C;QAC5C,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,4DAA4D;QAC5D,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,iBAAiB,CACzC,OAAO,EACP,SAAS,EACT,iBAAiB,EACjB,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,OAAO;YACL,GAAG,YAAY;YACf,MAAM,EAAE,WAAW;YACnB,KAAK,EAAE,KAAK;SACb,CAAC;IACJ,CAAC;IAED,sCAAsC;IACtC,WAAW,EAAE,YAAY;IACzB,sBAAsB,EAAE,gCAAgC;IACxD,wBAAwB,EAAE,gCAAgC;CAC3D,CAAC","sourcesContent":["import { SPLIT_GROUPS, FormData, NodeConfig, FlowTypes } from '../types';\nimport { Node } from '../../store/flow-definition';\nimport { createRulesRouter } from '../../utils';\nimport {\n getWaitForResponseOperators,\n operatorsToSelectOptions,\n getOperatorConfig\n} from '../operators';\nimport {\n resultNameField,\n categoriesToLocalizationFormData,\n localizationFormDataToCategories\n} from './shared';\nimport {\n createRulesArrayConfig,\n extractUserRules,\n casesToFormRules\n} from './shared-rules';\n\nexport const split_by_expression: NodeConfig = {\n type: 'split_by_expression',\n name: 'Split by Expression',\n group: SPLIT_GROUPS.split,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n dialogSize: 'large',\n form: {\n operand: {\n type: 'text',\n label: 'Expression',\n helpText: 'The expression to evaluate and split on',\n required: true,\n evaluated: true,\n placeholder: '@fields.age'\n },\n rules: createRulesArrayConfig(\n operatorsToSelectOptions(getWaitForResponseOperators()),\n 'Define rules to categorize the expression result'\n ),\n result_name: resultNameField\n },\n layout: ['operand', 'rules', 'result_name'],\n validate: (formData: FormData) => {\n const errors: { [key: string]: string } = {};\n\n // Validate operand is provided\n if (!formData.operand || formData.operand.trim() === '') {\n errors.operand = 'Expression is required';\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n toFormData: (node: Node) => {\n // Extract rules from router cases using shared function\n const rules = casesToFormRules(node);\n\n return {\n uuid: node.uuid,\n operand: node.router?.operand || '@input.text',\n rules: rules,\n result_name: node.router?.result_name || ''\n };\n },\n fromFormData: (formData: FormData, originalNode: Node): Node => {\n // Get user rules using shared extraction function\n const userRules = extractUserRules(formData);\n\n // Get operand from form data\n const operand = formData.operand?.trim() || '@input.text';\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\n // Localization support for categories\n localizable: 'categories',\n toLocalizationFormData: categoriesToLocalizationFormData,\n fromLocalizationFormData: localizationFormDataToCategories\n};\n"]}
1
+ {"version":3,"file":"split_by_expression.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_expression.ts"],"names":[],"mappings":"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","sourcesContent":["import { SPLIT_GROUPS, FormData, NodeConfig, FlowTypes } from '../types';\nimport { Node } from '../../store/flow-definition';\nimport { createRulesRouter } from '../../utils';\nimport {\n getWaitForResponseOperators,\n operatorsToSelectOptions,\n getOperatorConfig\n} from '../operators';\nimport {\n resultNameField,\n categoriesToLocalizationFormData,\n localizationFormDataToCategories\n} from './shared';\nimport {\n createRulesArrayConfig,\n extractUserRules,\n casesToFormRules\n} from './shared-rules';\n\nexport const split_by_expression: NodeConfig = {\n type: 'split_by_expression',\n name: 'Split by Expression',\n group: SPLIT_GROUPS.split,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n dialogSize: 'large',\n form: {\n operand: {\n type: 'text',\n label: 'Expression',\n helpText: 'The expression to evaluate and split on',\n required: true,\n evaluated: true,\n placeholder: '@fields.age'\n },\n rules: createRulesArrayConfig(\n operatorsToSelectOptions(getWaitForResponseOperators()),\n ''\n ),\n result_name: resultNameField\n },\n layout: ['operand', 'rules', 'result_name'],\n validate: (formData: FormData) => {\n const errors: { [key: string]: string } = {};\n\n // Validate operand is provided\n if (!formData.operand || formData.operand.trim() === '') {\n errors.operand = 'Expression is required';\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n toFormData: (node: Node) => {\n // Extract rules from router cases using shared function\n const rules = casesToFormRules(node);\n\n return {\n uuid: node.uuid,\n operand: node.router?.operand || '@input.text',\n rules: rules,\n result_name: node.router?.result_name || ''\n };\n },\n fromFormData: (formData: FormData, originalNode: Node): Node => {\n // Get user rules using shared extraction function\n const userRules = extractUserRules(formData);\n\n // Get operand from form data\n const operand = formData.operand?.trim() || '@input.text';\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\n // Localization support for categories\n localizable: 'categories',\n toLocalizationFormData: categoriesToLocalizationFormData,\n fromLocalizationFormData: localizationFormDataToCategories\n};\n"]}
@@ -29,7 +29,6 @@ export const split_by_llm_categorize = {
29
29
  },
30
30
  categories: {
31
31
  type: 'array',
32
- label: 'Categories',
33
32
  helpText: 'Define the categories for classification',
34
33
  required: true,
35
34
  sortable: true,
@@ -1 +1 @@
1
- {"version":3,"file":"split_by_llm_categorize.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_llm_categorize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,aAAa,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzE,OAAO,EAAE,YAAY,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAC3B,OAAO,EACL,gCAAgC,EAChC,gCAAgC,EACjC,MAAM,UAAU,CAAC;AAElB,MAAM,CAAC,MAAM,uBAAuB,GAAe;IACjD,IAAI,EAAE,yBAAyB;IAC/B,IAAI,EAAE,aAAa;IACnB,KAAK,EAAE,aAAa,CAAC,QAAQ;IAC7B,SAAS,EAAE,EAAE;IACb,QAAQ,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;IACvB,IAAI,EAAE;QACJ,GAAG,EAAE;YACH,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,KAAK;YACZ,QAAQ,EAAE,0CAA0C;YACpD,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,+BAA+B;YACzC,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,MAAM;YACf,WAAW,EAAE,kBAAkB;SAChC;QACD,KAAK,EAAE;YACL,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,OAAO;YACd,QAAQ,EAAE,0CAA0C;YACpD,QAAQ,EAAE,IAAI;YACd,SAAS,EAAE,IAAI;YACf,WAAW,EAAE,QAAQ;SACtB;QACD,UAAU,EAAE;YACV,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,YAAY;YACnB,QAAQ,EAAE,0CAA0C;YACpD,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,IAAI;YACd,SAAS,EAAE,UAAU;YACrB,QAAQ,EAAE,CAAC;YACX,QAAQ,EAAE,EAAE;YACZ,WAAW,EAAE,CAAC,IAAS,EAAE,EAAE;gBACzB,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;YAC/C,CAAC;YACD,UAAU,EAAE;gBACV,IAAI,EAAE;oBACJ,IAAI,EAAE,MAAM;oBACZ,WAAW,EAAE,eAAe;oBAC5B,QAAQ,EAAE,IAAI;iBACf;aACF;SACF;KACF;IACD,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,YAAY,CAAC;IACtC,QAAQ,EAAE,CAAC,QAAkB,EAAE,EAAE;QAC/B,MAAM,MAAM,GAA8B,EAAE,CAAC;QAE7C,qCAAqC;QACrC,IAAI,QAAQ,CAAC,UAAU,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9D,MAAM,UAAU,GAAG,QAAQ,CAAC,UAAU,CAAC,MAAM,CAC3C,CAAC,IAAS,EAAE,EAAE,CAAC,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,IAAI,KAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CACrD,CAAC;YAEF,8DAA8D;YAC9D,MAAM,mBAAmB,GAAG,EAAE,CAAC;YAC/B,MAAM,YAAY,GAAG,IAAI,GAAG,EAAE,CAAC;YAE/B,wDAAwD;YACxD,UAAU,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;gBAC9B,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;gBACrD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;oBACjC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;gBAClC,CAAC;gBACD,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YACzD,CAAC,CAAC,CAAC;YAEH,4DAA4D;YAC5D,YAAY,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,EAAE;gBACrC,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC7B,mBAAmB,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,CAAC;gBAC7C,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,IAAI,mBAAmB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACnC,MAAM,gBAAgB,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC;gBAC3D,MAAM,CAAC,UAAU,GAAG,mCAAmC,gBAAgB,CAAC,IAAI,CAC1E,IAAI,CACL,EAAE,CAAC;YACN,CAAC;QACH,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,aAAa,GAAG,MAAA,IAAI,CAAC,OAAO,0CAAE,IAAI,CACtC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,UAAU,CAC5B,CAAC;QACb,OAAO,IAAI,CAAA;0CAC2B,aAAa,CAAC,GAAG,CAAC,IAAI;KAC3D,CAAC;IACJ,CAAC;IACD,UAAU,EAAE,CAAC,IAAU,EAAE,EAAE;;QACzB,gDAAgD;QAChD,MAAM,aAAa,GAAG,MAAA,IAAI,CAAC,OAAO,0CAAE,IAAI,CACtC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,UAAU,CAChC,CAAC;QACT,MAAM,UAAU,GACd,CAAA,MAAA,MAAA,IAAI,CAAC,MAAM,0CAAE,UAAU,0CACnB,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,OAAO,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,EAC/D,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,KAAI,EAAE,CAAC;QAE9C,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,GAAG,EAAE,CAAA,aAAa,aAAb,aAAa,uBAAb,aAAa,CAAE,GAAG;gBACrB,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;gBACnE,CAAC,CAAC,EAAE;YACN,KAAK,EAAE,CAAA,aAAa,aAAb,aAAa,uBAAb,aAAa,CAAE,KAAK,KAAI,QAAQ;YACvC,UAAU,EAAE,UAAU;SACvB,CAAC;IACJ,CAAC;IACD,YAAY,EAAE,CAAC,QAAkB,EAAE,YAAkB,EAAQ,EAAE;;QAC7D,oBAAoB;QACpB,MAAM,YAAY,GAChB,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC;YACpD,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;YACjB,CAAC,CAAC,IAAI,CAAC;QAEX,sBAAsB;QACtB,MAAM,cAAc,GAAG,CAAC,QAAQ,CAAC,UAAU,IAAI,EAAE,CAAC;aAC/C,MAAM,CAAC,CAAC,IAAS,EAAE,EAAE,WAAC,OAAA,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,IAAI,0CAAE,IAAI,EAAE,CAAA,EAAA,CAAC;aACzC,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAExC,qDAAqD;QACrD,MAAM,qBAAqB,GAAG,MAAA,YAAY,CAAC,OAAO,0CAAE,IAAI,CACtD,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,UAAU,CACvC,CAAC;QACF,MAAM,WAAW,GAAG,CAAA,qBAAqB,aAArB,qBAAqB,uBAArB,qBAAqB,CAAE,IAAI,KAAI,YAAY,EAAE,CAAC;QAElE,sEAAsE;QACtE,MAAM,aAAa,GAAY;YAC7B,IAAI,EAAE,UAAU;YAChB,IAAI,EAAE,WAAW;YACjB,GAAG,EAAE,YAAY;gBACf,CAAC,CAAC,EAAE,IAAI,EAAE,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,YAAY,CAAC,IAAI,EAAE;gBACvD,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;YAC1B,YAAY,EAAE,wDAAwD;YACtE,KAAK,EAAE,QAAQ,CAAC,KAAK,IAAI,QAAQ;YACjC,YAAY,EAAE,aAAa;SAC5B,CAAC;QAEF,8BAA8B;QAC9B,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,yBAAyB,CACjD,qBAAqB,EACrB,cAAc,EACd,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;YACjB,IAAI,EAAE,eAAe;YACrB,SAAS,EAAE,CAAC,YAAY,CAAC;SAC1B,CAAC,EACF,kBAAkB,EAClB,aAAa,EACb,aAAa,CACd,CAAC;QAEF,2BAA2B;QAC3B,OAAO;YACL,IAAI,EAAE,YAAY,CAAC,IAAI;YACvB,OAAO,EAAE,CAAC,aAAa,CAAC;YACxB,MAAM,EAAE,MAAM;YACd,KAAK,EAAE,KAAK;SACb,CAAC;IACJ,CAAC;IAED,sCAAsC;IACtC,WAAW,EAAE,YAAY;IACzB,sBAAsB,EAAE,gCAAgC;IACxD,wBAAwB,EAAE,gCAAgC;CAC3D,CAAC","sourcesContent":["import { FormData, NodeConfig, ACTION_GROUPS, Features } from '../types';\nimport { CallLLM, Node } from '../../store/flow-definition';\nimport { generateUUID, createMultiCategoryRouter } from '../../utils';\nimport { html } from 'lit';\nimport {\n categoriesToLocalizationFormData,\n localizationFormDataToCategories\n} from './shared';\n\nexport const split_by_llm_categorize: NodeConfig = {\n type: 'split_by_llm_categorize',\n name: 'Split by AI',\n group: ACTION_GROUPS.services,\n flowTypes: [],\n features: [Features.AI],\n form: {\n llm: {\n type: 'select',\n label: 'LLM',\n helpText: 'Select the LLM to use for categorization',\n required: true,\n endpoint: '/test-assets/select/llms.json',\n valueKey: 'uuid',\n nameKey: 'name',\n placeholder: 'Select an LLM...'\n },\n input: {\n type: 'text',\n label: 'Input',\n helpText: 'The input to categorize (usually @input)',\n required: true,\n evaluated: true,\n placeholder: '@input'\n },\n categories: {\n type: 'array',\n label: 'Categories',\n helpText: 'Define the categories for classification',\n required: true,\n sortable: true,\n itemLabel: 'Category',\n minItems: 1,\n maxItems: 10,\n isEmptyItem: (item: any) => {\n return !item.name || item.name.trim() === '';\n },\n itemConfig: {\n name: {\n type: 'text',\n placeholder: 'Category name',\n required: true\n }\n }\n }\n },\n layout: ['llm', 'input', 'categories'],\n validate: (formData: FormData) => {\n const errors: { [key: string]: string } = {};\n\n // Check for duplicate category names\n if (formData.categories && Array.isArray(formData.categories)) {\n const categories = formData.categories.filter(\n (item: any) => item?.name && item.name.trim() !== ''\n );\n\n // Find all categories that have duplicates (case-insensitive)\n const duplicateCategories = [];\n const lowerCaseMap = new Map();\n\n // First pass: map lowercase names to all original cases\n categories.forEach((category) => {\n const lowerName = category.name.trim().toLowerCase();\n if (!lowerCaseMap.has(lowerName)) {\n lowerCaseMap.set(lowerName, []);\n }\n lowerCaseMap.get(lowerName).push(category.name.trim());\n });\n\n // Second pass: collect all names that appear more than once\n lowerCaseMap.forEach((originalNames) => {\n if (originalNames.length > 1) {\n duplicateCategories.push(...originalNames);\n }\n });\n\n if (duplicateCategories.length > 0) {\n const uniqueDuplicates = [...new Set(duplicateCategories)];\n errors.categories = `Duplicate category names found: ${uniqueDuplicates.join(\n ', '\n )}`;\n }\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n render: (node: Node) => {\n const callLlmAction = node.actions?.find(\n (action) => action.type === 'call_llm'\n ) as CallLLM;\n return html`\n <div class=\"body\">Categorize with ${callLlmAction.llm.name}</div>\n `;\n },\n toFormData: (node: Node) => {\n // Extract data from the existing node structure\n const callLlmAction = node.actions?.find(\n (action) => action.type === 'call_llm'\n ) as any;\n const categories =\n node.router?.categories\n ?.filter((cat) => cat.name !== 'Other' && cat.name !== 'Failure')\n .map((cat) => ({ name: cat.name })) || [];\n\n return {\n uuid: node.uuid,\n llm: callLlmAction?.llm\n ? [{ value: callLlmAction.llm.uuid, name: callLlmAction.llm.name }]\n : [],\n input: callLlmAction?.input || '@input',\n categories: categories\n };\n },\n fromFormData: (formData: FormData, originalNode: Node): Node => {\n // Get LLM selection\n const llmSelection =\n Array.isArray(formData.llm) && formData.llm.length > 0\n ? formData.llm[0]\n : null;\n\n // Get user categories\n const userCategories = (formData.categories || [])\n .filter((item: any) => item?.name?.trim())\n .map((item: any) => item.name.trim());\n\n // Find existing call_llm action to preserve its UUID\n const existingCallLlmAction = originalNode.actions?.find(\n (action) => action.type === 'call_llm'\n );\n const callLlmUuid = existingCallLlmAction?.uuid || generateUUID();\n\n // Create call_llm action (using any type to match the example format)\n const callLlmAction: CallLLM = {\n type: 'call_llm',\n uuid: callLlmUuid,\n llm: llmSelection\n ? { uuid: llmSelection.value, name: llmSelection.name }\n : { uuid: '', name: '' },\n instructions: `@(prompt(\"categorize\", slice(node.categories, 0, -2)))`,\n input: formData.input || '@input',\n output_local: '_llm_output'\n };\n\n // Create categories and exits\n const existingCategories = originalNode.router?.categories || [];\n const existingExits = originalNode.exits || [];\n const existingCases = originalNode.router?.cases || [];\n\n const { router, exits } = createMultiCategoryRouter(\n '@locals._llm_output',\n userCategories,\n (categoryName) => ({\n type: 'has_only_text',\n arguments: [categoryName]\n }),\n existingCategories,\n existingExits,\n existingCases\n );\n\n // Return the complete node\n return {\n uuid: originalNode.uuid,\n actions: [callLlmAction],\n router: router,\n exits: exits\n };\n },\n\n // Localization support for categories\n localizable: 'categories',\n toLocalizationFormData: categoriesToLocalizationFormData,\n fromLocalizationFormData: localizationFormDataToCategories\n};\n"]}
1
+ {"version":3,"file":"split_by_llm_categorize.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_llm_categorize.ts"],"names":[],"mappings":"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","sourcesContent":["import { FormData, NodeConfig, ACTION_GROUPS, Features } from '../types';\nimport { CallLLM, Node } from '../../store/flow-definition';\nimport { generateUUID, createMultiCategoryRouter } from '../../utils';\nimport { html } from 'lit';\nimport {\n categoriesToLocalizationFormData,\n localizationFormDataToCategories\n} from './shared';\n\nexport const split_by_llm_categorize: NodeConfig = {\n type: 'split_by_llm_categorize',\n name: 'Split by AI',\n group: ACTION_GROUPS.services,\n flowTypes: [],\n features: [Features.AI],\n form: {\n llm: {\n type: 'select',\n label: 'LLM',\n helpText: 'Select the LLM to use for categorization',\n required: true,\n endpoint: '/test-assets/select/llms.json',\n valueKey: 'uuid',\n nameKey: 'name',\n placeholder: 'Select an LLM...'\n },\n input: {\n type: 'text',\n label: 'Input',\n helpText: 'The input to categorize (usually @input)',\n required: true,\n evaluated: true,\n placeholder: '@input'\n },\n categories: {\n type: 'array',\n helpText: 'Define the categories for classification',\n required: true,\n sortable: true,\n itemLabel: 'Category',\n minItems: 1,\n maxItems: 10,\n isEmptyItem: (item: any) => {\n return !item.name || item.name.trim() === '';\n },\n itemConfig: {\n name: {\n type: 'text',\n placeholder: 'Category name',\n required: true\n }\n }\n }\n },\n layout: ['llm', 'input', 'categories'],\n validate: (formData: FormData) => {\n const errors: { [key: string]: string } = {};\n\n // Check for duplicate category names\n if (formData.categories && Array.isArray(formData.categories)) {\n const categories = formData.categories.filter(\n (item: any) => item?.name && item.name.trim() !== ''\n );\n\n // Find all categories that have duplicates (case-insensitive)\n const duplicateCategories = [];\n const lowerCaseMap = new Map();\n\n // First pass: map lowercase names to all original cases\n categories.forEach((category) => {\n const lowerName = category.name.trim().toLowerCase();\n if (!lowerCaseMap.has(lowerName)) {\n lowerCaseMap.set(lowerName, []);\n }\n lowerCaseMap.get(lowerName).push(category.name.trim());\n });\n\n // Second pass: collect all names that appear more than once\n lowerCaseMap.forEach((originalNames) => {\n if (originalNames.length > 1) {\n duplicateCategories.push(...originalNames);\n }\n });\n\n if (duplicateCategories.length > 0) {\n const uniqueDuplicates = [...new Set(duplicateCategories)];\n errors.categories = `Duplicate category names found: ${uniqueDuplicates.join(\n ', '\n )}`;\n }\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n render: (node: Node) => {\n const callLlmAction = node.actions?.find(\n (action) => action.type === 'call_llm'\n ) as CallLLM;\n return html`\n <div class=\"body\">Categorize with ${callLlmAction.llm.name}</div>\n `;\n },\n toFormData: (node: Node) => {\n // Extract data from the existing node structure\n const callLlmAction = node.actions?.find(\n (action) => action.type === 'call_llm'\n ) as any;\n const categories =\n node.router?.categories\n ?.filter((cat) => cat.name !== 'Other' && cat.name !== 'Failure')\n .map((cat) => ({ name: cat.name })) || [];\n\n return {\n uuid: node.uuid,\n llm: callLlmAction?.llm\n ? [{ value: callLlmAction.llm.uuid, name: callLlmAction.llm.name }]\n : [],\n input: callLlmAction?.input || '@input',\n categories: categories\n };\n },\n fromFormData: (formData: FormData, originalNode: Node): Node => {\n // Get LLM selection\n const llmSelection =\n Array.isArray(formData.llm) && formData.llm.length > 0\n ? formData.llm[0]\n : null;\n\n // Get user categories\n const userCategories = (formData.categories || [])\n .filter((item: any) => item?.name?.trim())\n .map((item: any) => item.name.trim());\n\n // Find existing call_llm action to preserve its UUID\n const existingCallLlmAction = originalNode.actions?.find(\n (action) => action.type === 'call_llm'\n );\n const callLlmUuid = existingCallLlmAction?.uuid || generateUUID();\n\n // Create call_llm action (using any type to match the example format)\n const callLlmAction: CallLLM = {\n type: 'call_llm',\n uuid: callLlmUuid,\n llm: llmSelection\n ? { uuid: llmSelection.value, name: llmSelection.name }\n : { uuid: '', name: '' },\n instructions: `@(prompt(\"categorize\", slice(node.categories, 0, -2)))`,\n input: formData.input || '@input',\n output_local: '_llm_output'\n };\n\n // Create categories and exits\n const existingCategories = originalNode.router?.categories || [];\n const existingExits = originalNode.exits || [];\n const existingCases = originalNode.router?.cases || [];\n\n const { router, exits } = createMultiCategoryRouter(\n '@locals._llm_output',\n userCategories,\n (categoryName) => ({\n type: 'has_only_text',\n arguments: [categoryName]\n }),\n existingCategories,\n existingExits,\n existingCases\n );\n\n // Return the complete node\n return {\n uuid: originalNode.uuid,\n actions: [callLlmAction],\n router: router,\n exits: exits\n };\n },\n\n // Localization support for categories\n localizable: 'categories',\n toLocalizationFormData: categoriesToLocalizationFormData,\n fromLocalizationFormData: localizationFormDataToCategories\n};\n"]}
@@ -40,7 +40,6 @@ export const split_by_random = {
40
40
  form: {
41
41
  categories: {
42
42
  type: 'array',
43
- label: 'Buckets',
44
43
  helpText: 'Define the buckets to randomly split contacts into',
45
44
  required: true,
46
45
  itemLabel: 'Bucket',
@@ -1 +1 @@
1
- {"version":3,"file":"split_by_random.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_random.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAwB,SAAS,EAAE,MAAM,UAAU,CAAC;AAEzE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,gCAAgC,EAChC,gCAAgC,EACjC,MAAM,UAAU,CAAC;AAElB,4DAA4D;AAC5D,MAAM,kBAAkB,GAAG,CACzB,cAAwB,EACxB,qBAAiC,EAAE,EACnC,gBAAwB,EAAE,EAC1B,EAAE;IACF,MAAM,UAAU,GAAe,EAAE,CAAC;IAClC,MAAM,KAAK,GAAW,EAAE,CAAC;IAEzB,uDAAuD;IACvD,cAAc,CAAC,OAAO,CAAC,CAAC,YAAY,EAAE,EAAE;QACtC,wCAAwC;QACxC,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,IAAI,CAC9C,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,YAAY,CACnC,CAAC;QACF,MAAM,YAAY,GAAG,gBAAgB;YACnC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,gBAAgB,CAAC,SAAS,CAAC;YACxE,CAAC,CAAC,IAAI,CAAC;QAET,MAAM,QAAQ,GAAG,CAAA,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,IAAI,KAAI,YAAY,EAAE,CAAC;QACtD,MAAM,YAAY,GAAG,CAAA,gBAAgB,aAAhB,gBAAgB,uBAAhB,gBAAgB,CAAE,IAAI,KAAI,YAAY,EAAE,CAAC;QAE9D,UAAU,CAAC,IAAI,CAAC;YACd,IAAI,EAAE,YAAY;YAClB,IAAI,EAAE,YAAY;YAClB,SAAS,EAAE,QAAQ;SACpB,CAAC,CAAC;QAEH,KAAK,CAAC,IAAI,CAAC;YACT,IAAI,EAAE,QAAQ;YACd,gBAAgB,EAAE,CAAA,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,gBAAgB,KAAI,IAAI;SACzD,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,MAAM,EAAE;YACN,IAAI,EAAE,QAAiB;YACvB,UAAU,EAAE,UAAU;SACvB;QACD,KAAK,EAAE,KAAK;KACb,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAe;IACzC,IAAI,EAAE,iBAAiB;IACvB,IAAI,EAAE,cAAc;IACpB,KAAK,EAAE,YAAY,CAAC,KAAK;IACzB,SAAS,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,UAAU,CAAC;IACrE,IAAI,EAAE;QACJ,UAAU,EAAE;YACV,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,SAAS;YAChB,QAAQ,EAAE,oDAAoD;YAC9D,QAAQ,EAAE,IAAI;YACd,SAAS,EAAE,QAAQ;YACnB,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,CAAC;YACX,QAAQ,EAAE,EAAE;YACZ,WAAW,EAAE,CAAC,IAAS,EAAE,EAAE;gBACzB,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;YAC/C,CAAC;YACD,UAAU,EAAE;gBACV,IAAI,EAAE;oBACJ,IAAI,EAAE,MAAM;oBACZ,WAAW,EAAE,aAAa;oBAC1B,QAAQ,EAAE,IAAI;iBACf;aACF;SACF;KACF;IACD,MAAM,EAAE,CAAC,YAAY,CAAC;IACtB,QAAQ,EAAE,CAAC,QAAkB,EAAE,EAAE;QAC/B,MAAM,MAAM,GAA8B,EAAE,CAAC;QAE7C,qCAAqC;QACrC,IAAI,QAAQ,CAAC,UAAU,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9D,MAAM,UAAU,GAAG,QAAQ,CAAC,UAAU,CAAC,MAAM,CAC3C,CAAC,IAAS,EAAE,EAAE,CAAC,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,IAAI,KAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CACrD,CAAC;YAEF,yBAAyB;YACzB,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,MAAM,CAAC,UAAU,GAAG,kDAAkD,CAAC;YACzE,CAAC;YAED,8DAA8D;YAC9D,MAAM,mBAAmB,GAAG,EAAE,CAAC;YAC/B,MAAM,YAAY,GAAG,IAAI,GAAG,EAAE,CAAC;YAE/B,wDAAwD;YACxD,UAAU,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;gBAC9B,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;gBACrD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;oBACjC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;gBAClC,CAAC;gBACD,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YACzD,CAAC,CAAC,CAAC;YAEH,4DAA4D;YAC5D,YAAY,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,EAAE;gBACrC,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC7B,mBAAmB,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,CAAC;gBAC7C,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,IAAI,mBAAmB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACnC,MAAM,gBAAgB,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC;gBAC3D,MAAM,CAAC,UAAU,GAAG,iCAAiC,gBAAgB,CAAC,IAAI,CACxE,IAAI,CACL,EAAE,CAAC;YACN,CAAC;QACH,CAAC;QAED,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC;YACvC,MAAM;SACP,CAAC;IACJ,CAAC;IACD,UAAU,EAAE,CAAC,IAAU,EAAE,EAAE;;QACzB,sDAAsD;QACtD,MAAM,UAAU,GACd,CAAA,MAAA,MAAA,IAAI,CAAC,MAAM,0CAAE,UAAU,0CAAE,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,KAAI,EAAE,CAAC;QAEpE,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,UAAU,EAAE,UAAU;SACvB,CAAC;IACJ,CAAC;IACD,YAAY,EAAE,CAAC,QAAkB,EAAE,YAAkB,EAAQ,EAAE;;QAC7D,sBAAsB;QACtB,MAAM,cAAc,GAAG,CAAC,QAAQ,CAAC,UAAU,IAAI,EAAE,CAAC;aAC/C,MAAM,CAAC,CAAC,IAAS,EAAE,EAAE,WAAC,OAAA,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,IAAI,0CAAE,IAAI,EAAE,CAAA,EAAA,CAAC;aACzC,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAExC,4DAA4D;QAC5D,MAAM,kBAAkB,GAAG,CAAA,MAAA,YAAY,CAAC,MAAM,0CAAE,UAAU,KAAI,EAAE,CAAC;QACjE,MAAM,aAAa,GAAG,YAAY,CAAC,KAAK,IAAI,EAAE,CAAC;QAE/C,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,kBAAkB,CAC1C,cAAc,EACd,kBAAkB,EAClB,aAAa,CACd,CAAC;QAEF,2BAA2B;QAC3B,OAAO;YACL,IAAI,EAAE,YAAY,CAAC,IAAI;YACvB,OAAO,EAAE,YAAY,CAAC,OAAO,IAAI,EAAE;YACnC,MAAM,EAAE,MAAM;YACd,KAAK,EAAE,KAAK;SACb,CAAC;IACJ,CAAC;IACD,MAAM,EAAE;QACN,IAAI,EAAE,QAAQ;KACf;IAED,sCAAsC;IACtC,WAAW,EAAE,YAAY;IACzB,sBAAsB,EAAE,gCAAgC;IACxD,wBAAwB,EAAE,gCAAgC;CAC3D,CAAC","sourcesContent":["import { SPLIT_GROUPS, FormData, NodeConfig, FlowTypes } from '../types';\nimport { Node, Category, Exit } from '../../store/flow-definition.d';\nimport { generateUUID } from '../../utils';\nimport {\n categoriesToLocalizationFormData,\n localizationFormDataToCategories\n} from './shared';\n\n// Helper function to create a random router with categories\nconst createRandomRouter = (\n userCategories: string[],\n existingCategories: Category[] = [],\n existingExits: Exit[] = []\n) => {\n const categories: Category[] = [];\n const exits: Exit[] = [];\n\n // Create categories and exits for user-defined buckets\n userCategories.forEach((categoryName) => {\n // Try to find existing category by name\n const existingCategory = existingCategories.find(\n (cat) => cat.name === categoryName\n );\n const existingExit = existingCategory\n ? existingExits.find((exit) => exit.uuid === existingCategory.exit_uuid)\n : null;\n\n const exitUuid = existingExit?.uuid || generateUUID();\n const categoryUuid = existingCategory?.uuid || generateUUID();\n\n categories.push({\n uuid: categoryUuid,\n name: categoryName,\n exit_uuid: exitUuid\n });\n\n exits.push({\n uuid: exitUuid,\n destination_uuid: existingExit?.destination_uuid || null\n });\n });\n\n return {\n router: {\n type: 'random' as const,\n categories: categories\n },\n exits: exits\n };\n};\n\nexport const split_by_random: NodeConfig = {\n type: 'split_by_random',\n name: 'Random Split',\n group: SPLIT_GROUPS.split,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n form: {\n categories: {\n type: 'array',\n label: 'Buckets',\n helpText: 'Define the buckets to randomly split contacts into',\n required: true,\n itemLabel: 'Bucket',\n sortable: true,\n minItems: 2,\n maxItems: 10,\n isEmptyItem: (item: any) => {\n return !item.name || item.name.trim() === '';\n },\n itemConfig: {\n name: {\n type: 'text',\n placeholder: 'Bucket name',\n required: true\n }\n }\n }\n },\n layout: ['categories'],\n validate: (formData: FormData) => {\n const errors: { [key: string]: string } = {};\n\n // Check for duplicate category names\n if (formData.categories && Array.isArray(formData.categories)) {\n const categories = formData.categories.filter(\n (item: any) => item?.name && item.name.trim() !== ''\n );\n\n // Ensure minimum buckets\n if (categories.length < 2) {\n errors.categories = 'At least 2 buckets are required for random split';\n }\n\n // Find all categories that have duplicates (case-insensitive)\n const duplicateCategories = [];\n const lowerCaseMap = new Map();\n\n // First pass: map lowercase names to all original cases\n categories.forEach((category) => {\n const lowerName = category.name.trim().toLowerCase();\n if (!lowerCaseMap.has(lowerName)) {\n lowerCaseMap.set(lowerName, []);\n }\n lowerCaseMap.get(lowerName).push(category.name.trim());\n });\n\n // Second pass: collect all names that appear more than once\n lowerCaseMap.forEach((originalNames) => {\n if (originalNames.length > 1) {\n duplicateCategories.push(...originalNames);\n }\n });\n\n if (duplicateCategories.length > 0) {\n const uniqueDuplicates = [...new Set(duplicateCategories)];\n errors.categories = `Duplicate bucket names found: ${uniqueDuplicates.join(\n ', '\n )}`;\n }\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n toFormData: (node: Node) => {\n // Extract categories from the existing node structure\n const categories =\n node.router?.categories?.map((cat) => ({ name: cat.name })) || [];\n\n return {\n uuid: node.uuid,\n categories: categories\n };\n },\n fromFormData: (formData: FormData, originalNode: Node): Node => {\n // Get user categories\n const userCategories = (formData.categories || [])\n .filter((item: any) => item?.name?.trim())\n .map((item: any) => item.name.trim());\n\n // Create router and exits using existing data when possible\n const existingCategories = originalNode.router?.categories || [];\n const existingExits = originalNode.exits || [];\n\n const { router, exits } = createRandomRouter(\n userCategories,\n existingCategories,\n existingExits\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: 'random'\n },\n\n // Localization support for categories\n localizable: 'categories',\n toLocalizationFormData: categoriesToLocalizationFormData,\n fromLocalizationFormData: localizationFormDataToCategories\n};\n"]}
1
+ {"version":3,"file":"split_by_random.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_random.ts"],"names":[],"mappings":"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","sourcesContent":["import { SPLIT_GROUPS, FormData, NodeConfig, FlowTypes } from '../types';\nimport { Node, Category, Exit } from '../../store/flow-definition.d';\nimport { generateUUID } from '../../utils';\nimport {\n categoriesToLocalizationFormData,\n localizationFormDataToCategories\n} from './shared';\n\n// Helper function to create a random router with categories\nconst createRandomRouter = (\n userCategories: string[],\n existingCategories: Category[] = [],\n existingExits: Exit[] = []\n) => {\n const categories: Category[] = [];\n const exits: Exit[] = [];\n\n // Create categories and exits for user-defined buckets\n userCategories.forEach((categoryName) => {\n // Try to find existing category by name\n const existingCategory = existingCategories.find(\n (cat) => cat.name === categoryName\n );\n const existingExit = existingCategory\n ? existingExits.find((exit) => exit.uuid === existingCategory.exit_uuid)\n : null;\n\n const exitUuid = existingExit?.uuid || generateUUID();\n const categoryUuid = existingCategory?.uuid || generateUUID();\n\n categories.push({\n uuid: categoryUuid,\n name: categoryName,\n exit_uuid: exitUuid\n });\n\n exits.push({\n uuid: exitUuid,\n destination_uuid: existingExit?.destination_uuid || null\n });\n });\n\n return {\n router: {\n type: 'random' as const,\n categories: categories\n },\n exits: exits\n };\n};\n\nexport const split_by_random: NodeConfig = {\n type: 'split_by_random',\n name: 'Random Split',\n group: SPLIT_GROUPS.split,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n form: {\n categories: {\n type: 'array',\n helpText: 'Define the buckets to randomly split contacts into',\n required: true,\n itemLabel: 'Bucket',\n sortable: true,\n minItems: 2,\n maxItems: 10,\n isEmptyItem: (item: any) => {\n return !item.name || item.name.trim() === '';\n },\n itemConfig: {\n name: {\n type: 'text',\n placeholder: 'Bucket name',\n required: true\n }\n }\n }\n },\n layout: ['categories'],\n validate: (formData: FormData) => {\n const errors: { [key: string]: string } = {};\n\n // Check for duplicate category names\n if (formData.categories && Array.isArray(formData.categories)) {\n const categories = formData.categories.filter(\n (item: any) => item?.name && item.name.trim() !== ''\n );\n\n // Ensure minimum buckets\n if (categories.length < 2) {\n errors.categories = 'At least 2 buckets are required for random split';\n }\n\n // Find all categories that have duplicates (case-insensitive)\n const duplicateCategories = [];\n const lowerCaseMap = new Map();\n\n // First pass: map lowercase names to all original cases\n categories.forEach((category) => {\n const lowerName = category.name.trim().toLowerCase();\n if (!lowerCaseMap.has(lowerName)) {\n lowerCaseMap.set(lowerName, []);\n }\n lowerCaseMap.get(lowerName).push(category.name.trim());\n });\n\n // Second pass: collect all names that appear more than once\n lowerCaseMap.forEach((originalNames) => {\n if (originalNames.length > 1) {\n duplicateCategories.push(...originalNames);\n }\n });\n\n if (duplicateCategories.length > 0) {\n const uniqueDuplicates = [...new Set(duplicateCategories)];\n errors.categories = `Duplicate bucket names found: ${uniqueDuplicates.join(\n ', '\n )}`;\n }\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n toFormData: (node: Node) => {\n // Extract categories from the existing node structure\n const categories =\n node.router?.categories?.map((cat) => ({ name: cat.name })) || [];\n\n return {\n uuid: node.uuid,\n categories: categories\n };\n },\n fromFormData: (formData: FormData, originalNode: Node): Node => {\n // Get user categories\n const userCategories = (formData.categories || [])\n .filter((item: any) => item?.name?.trim())\n .map((item: any) => item.name.trim());\n\n // Create router and exits using existing data when possible\n const existingCategories = originalNode.router?.categories || [];\n const existingExits = originalNode.exits || [];\n\n const { router, exits } = createRandomRouter(\n userCategories,\n existingCategories,\n existingExits\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: 'random'\n },\n\n // Localization support for categories\n localizable: 'categories',\n toLocalizationFormData: categoriesToLocalizationFormData,\n fromLocalizationFormData: localizationFormDataToCategories\n};\n"]}
@@ -87,7 +87,7 @@ export const split_by_run_result = {
87
87
  }
88
88
  }
89
89
  },
90
- rules: createRulesArrayConfig(operatorsToSelectOptions(getWaitForResponseOperators()), 'Define rules to categorize the result'),
90
+ rules: createRulesArrayConfig(operatorsToSelectOptions(getWaitForResponseOperators()), ''),
91
91
  result_name: resultNameField
92
92
  },
93
93
  layout: [
@@ -114,7 +114,12 @@ export const split_by_run_result = {
114
114
  toFormData: (node, nodeUI) => {
115
115
  var _a, _b, _c;
116
116
  // Get the result from the UI config operand (source of truth)
117
- const result = (_a = nodeUI === null || nodeUI === void 0 ? void 0 : nodeUI.config) === null || _a === void 0 ? void 0 : _a.operand;
117
+ // Normalize: toUIConfig saves { id, name, type } but the Select component
118
+ // (valueKey: 'value') and fromFormData expect a 'value' property.
119
+ const savedOperand = (_a = nodeUI === null || nodeUI === void 0 ? void 0 : nodeUI.config) === null || _a === void 0 ? void 0 : _a.operand;
120
+ const result = savedOperand
121
+ ? { ...savedOperand, value: savedOperand.value || savedOperand.id }
122
+ : null;
118
123
  // Extract rules from router cases using shared function
119
124
  const rules = casesToFormRules(node);
120
125
  // Extract delimiter configuration by checking the actual operand string
@@ -150,17 +155,18 @@ export const split_by_run_result = {
150
155
  }
151
156
  // Build operand based on whether delimiter is selected
152
157
  let operand;
158
+ const resultKey = selectedResult.value || selectedResult.id;
153
159
  const delimitBy = (_c = (_b = formData.delimit_by) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.value;
154
160
  const hasDelimiter = delimitBy !== undefined && delimitBy !== '';
155
161
  if (hasDelimiter) {
156
162
  // Get delimiter configuration
157
163
  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';
158
164
  // Build operand with field() function
159
- operand = `@(field(results.${selectedResult.value}, ${delimitIndex}, "${delimitBy}"))`;
165
+ operand = `@(field(results.${resultKey}, ${delimitIndex}, "${delimitBy}"))`;
160
166
  }
161
167
  else {
162
168
  // Standard operand without delimiter
163
- operand = `@results.${selectedResult.value}`;
169
+ operand = `@results.${resultKey}`;
164
170
  }
165
171
  // Get user rules using shared extraction function
166
172
  const userRules = extractUserRules(formData);