@nyaruka/temba-components 0.131.2 → 0.131.3

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 (223) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/demo/components/floating-tabs/example.html +400 -0
  3. package/demo/components/flow/index.html +1 -1
  4. package/demo/data/flows/sample-flow.json +41 -2
  5. package/demo/data/flows/voicemail.json +613 -0
  6. package/demo/index.html +6 -0
  7. package/dist/locales/es.js +5 -5
  8. package/dist/locales/es.js.map +1 -1
  9. package/dist/locales/fr.js +5 -5
  10. package/dist/locales/fr.js.map +1 -1
  11. package/dist/locales/locale-codes.js +11 -2
  12. package/dist/locales/locale-codes.js.map +1 -1
  13. package/dist/locales/pt.js +5 -5
  14. package/dist/locales/pt.js.map +1 -1
  15. package/dist/temba-components.js +1109 -535
  16. package/dist/temba-components.js.map +1 -1
  17. package/out-tsc/src/display/FloatingTab.js +167 -0
  18. package/out-tsc/src/display/FloatingTab.js.map +1 -0
  19. package/out-tsc/src/display/ProgressBar.js +22 -2
  20. package/out-tsc/src/display/ProgressBar.js.map +1 -1
  21. package/out-tsc/src/events.js.map +1 -1
  22. package/out-tsc/src/flow/CanvasNode.js +165 -31
  23. package/out-tsc/src/flow/CanvasNode.js.map +1 -1
  24. package/out-tsc/src/flow/Editor.js +857 -3
  25. package/out-tsc/src/flow/Editor.js.map +1 -1
  26. package/out-tsc/src/flow/NodeEditor.js +239 -19
  27. package/out-tsc/src/flow/NodeEditor.js.map +1 -1
  28. package/out-tsc/src/flow/NodeTypeSelector.js +44 -3
  29. package/out-tsc/src/flow/NodeTypeSelector.js.map +1 -1
  30. package/out-tsc/src/flow/StickyNote.js +12 -3
  31. package/out-tsc/src/flow/StickyNote.js.map +1 -1
  32. package/out-tsc/src/flow/actions/add_contact_groups.js +2 -1
  33. package/out-tsc/src/flow/actions/add_contact_groups.js.map +1 -1
  34. package/out-tsc/src/flow/actions/add_contact_urn.js +2 -1
  35. package/out-tsc/src/flow/actions/add_contact_urn.js.map +1 -1
  36. package/out-tsc/src/flow/actions/add_input_labels.js +2 -1
  37. package/out-tsc/src/flow/actions/add_input_labels.js.map +1 -1
  38. package/out-tsc/src/flow/actions/play_audio.js +2 -1
  39. package/out-tsc/src/flow/actions/play_audio.js.map +1 -1
  40. package/out-tsc/src/flow/actions/remove_contact_groups.js +2 -1
  41. package/out-tsc/src/flow/actions/remove_contact_groups.js.map +1 -1
  42. package/out-tsc/src/flow/actions/request_optin.js +1 -0
  43. package/out-tsc/src/flow/actions/request_optin.js.map +1 -1
  44. package/out-tsc/src/flow/actions/say_msg.js +2 -1
  45. package/out-tsc/src/flow/actions/say_msg.js.map +1 -1
  46. package/out-tsc/src/flow/actions/send_broadcast.js +2 -1
  47. package/out-tsc/src/flow/actions/send_broadcast.js.map +1 -1
  48. package/out-tsc/src/flow/actions/send_email.js +2 -1
  49. package/out-tsc/src/flow/actions/send_email.js.map +1 -1
  50. package/out-tsc/src/flow/actions/send_msg.js +93 -3
  51. package/out-tsc/src/flow/actions/send_msg.js.map +1 -1
  52. package/out-tsc/src/flow/actions/set_contact_channel.js +2 -1
  53. package/out-tsc/src/flow/actions/set_contact_channel.js.map +1 -1
  54. package/out-tsc/src/flow/actions/set_contact_field.js +2 -1
  55. package/out-tsc/src/flow/actions/set_contact_field.js.map +1 -1
  56. package/out-tsc/src/flow/actions/set_contact_language.js +2 -1
  57. package/out-tsc/src/flow/actions/set_contact_language.js.map +1 -1
  58. package/out-tsc/src/flow/actions/set_contact_name.js +2 -1
  59. package/out-tsc/src/flow/actions/set_contact_name.js.map +1 -1
  60. package/out-tsc/src/flow/actions/set_contact_status.js +2 -1
  61. package/out-tsc/src/flow/actions/set_contact_status.js.map +1 -1
  62. package/out-tsc/src/flow/actions/set_run_result.js +2 -1
  63. package/out-tsc/src/flow/actions/set_run_result.js.map +1 -1
  64. package/out-tsc/src/flow/actions/start_session.js +2 -1
  65. package/out-tsc/src/flow/actions/start_session.js.map +1 -1
  66. package/out-tsc/src/flow/config.js +2 -10
  67. package/out-tsc/src/flow/config.js.map +1 -1
  68. package/out-tsc/src/flow/nodes/shared.js +54 -0
  69. package/out-tsc/src/flow/nodes/shared.js.map +1 -1
  70. package/out-tsc/src/flow/nodes/split_by_airtime.js +9 -3
  71. package/out-tsc/src/flow/nodes/split_by_airtime.js.map +1 -1
  72. package/out-tsc/src/flow/nodes/split_by_contact_field.js +8 -3
  73. package/out-tsc/src/flow/nodes/split_by_contact_field.js.map +1 -1
  74. package/out-tsc/src/flow/nodes/split_by_expression.js +8 -3
  75. package/out-tsc/src/flow/nodes/split_by_expression.js.map +1 -1
  76. package/out-tsc/src/flow/nodes/split_by_groups.js +8 -3
  77. package/out-tsc/src/flow/nodes/split_by_groups.js.map +1 -1
  78. package/out-tsc/src/flow/nodes/split_by_intent.js +3 -2
  79. package/out-tsc/src/flow/nodes/split_by_intent.js.map +1 -1
  80. package/out-tsc/src/flow/nodes/split_by_llm.js +9 -2
  81. package/out-tsc/src/flow/nodes/split_by_llm.js.map +1 -1
  82. package/out-tsc/src/flow/nodes/split_by_llm_categorize.js +9 -2
  83. package/out-tsc/src/flow/nodes/split_by_llm_categorize.js.map +1 -1
  84. package/out-tsc/src/flow/nodes/split_by_random.js +8 -2
  85. package/out-tsc/src/flow/nodes/split_by_random.js.map +1 -1
  86. package/out-tsc/src/flow/nodes/split_by_resthook.js +8 -3
  87. package/out-tsc/src/flow/nodes/split_by_resthook.js.map +1 -1
  88. package/out-tsc/src/flow/nodes/split_by_run_result.js +8 -3
  89. package/out-tsc/src/flow/nodes/split_by_run_result.js.map +1 -1
  90. package/out-tsc/src/flow/nodes/split_by_scheme.js +8 -3
  91. package/out-tsc/src/flow/nodes/split_by_scheme.js.map +1 -1
  92. package/out-tsc/src/flow/nodes/split_by_subflow.js +8 -2
  93. package/out-tsc/src/flow/nodes/split_by_subflow.js.map +1 -1
  94. package/out-tsc/src/flow/nodes/split_by_ticket.js +8 -2
  95. package/out-tsc/src/flow/nodes/split_by_ticket.js.map +1 -1
  96. package/out-tsc/src/flow/nodes/split_by_webhook.js +8 -2
  97. package/out-tsc/src/flow/nodes/split_by_webhook.js.map +1 -1
  98. package/out-tsc/src/flow/nodes/wait_for_digits.js +3 -2
  99. package/out-tsc/src/flow/nodes/wait_for_digits.js.map +1 -1
  100. package/out-tsc/src/flow/nodes/wait_for_menu.js +3 -2
  101. package/out-tsc/src/flow/nodes/wait_for_menu.js.map +1 -1
  102. package/out-tsc/src/flow/nodes/wait_for_response.js +8 -3
  103. package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -1
  104. package/out-tsc/src/flow/types.js +15 -0
  105. package/out-tsc/src/flow/types.js.map +1 -1
  106. package/out-tsc/src/layout/FloatingWindow.js +346 -0
  107. package/out-tsc/src/layout/FloatingWindow.js.map +1 -0
  108. package/out-tsc/src/live/ContactChat.js +3 -19
  109. package/out-tsc/src/live/ContactChat.js.map +1 -1
  110. package/out-tsc/src/locales/es.js +5 -5
  111. package/out-tsc/src/locales/es.js.map +1 -1
  112. package/out-tsc/src/locales/fr.js +5 -5
  113. package/out-tsc/src/locales/fr.js.map +1 -1
  114. package/out-tsc/src/locales/locale-codes.js +11 -2
  115. package/out-tsc/src/locales/locale-codes.js.map +1 -1
  116. package/out-tsc/src/locales/pt.js +5 -5
  117. package/out-tsc/src/locales/pt.js.map +1 -1
  118. package/out-tsc/src/store/AppState.js +67 -0
  119. package/out-tsc/src/store/AppState.js.map +1 -1
  120. package/out-tsc/temba-modules.js +4 -0
  121. package/out-tsc/temba-modules.js.map +1 -1
  122. package/out-tsc/test/temba-floating-tab.test.js +91 -0
  123. package/out-tsc/test/temba-floating-tab.test.js.map +1 -0
  124. package/out-tsc/test/temba-floating-window.test.js +301 -0
  125. package/out-tsc/test/temba-floating-window.test.js.map +1 -0
  126. package/out-tsc/test/temba-flow-editor-node.test.js +117 -0
  127. package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
  128. package/out-tsc/test/temba-localization.test.js +471 -0
  129. package/out-tsc/test/temba-localization.test.js.map +1 -0
  130. package/out-tsc/test/temba-node-type-selector.test.js +150 -0
  131. package/out-tsc/test/temba-node-type-selector.test.js.map +1 -1
  132. package/out-tsc/test/utils.test.js +18 -0
  133. package/out-tsc/test/utils.test.js.map +1 -1
  134. package/package.json +1 -1
  135. package/screenshots/truth/floating-tab/default.png +0 -0
  136. package/screenshots/truth/floating-tab/gray.png +0 -0
  137. package/screenshots/truth/floating-tab/green.png +0 -0
  138. package/screenshots/truth/floating-tab/hidden.png +0 -0
  139. package/screenshots/truth/floating-tab/hover.png +0 -0
  140. package/screenshots/truth/floating-tab/purple.png +0 -0
  141. package/screenshots/truth/floating-window/chromeless.png +0 -0
  142. package/screenshots/truth/floating-window/custom-size.png +0 -0
  143. package/screenshots/truth/floating-window/default.png +0 -0
  144. package/screenshots/truth/floating-window/with-header.png +0 -0
  145. package/screenshots/truth/node-type-selector/action-mode.png +0 -0
  146. package/screenshots/truth/node-type-selector/split-mode.png +0 -0
  147. package/screenshots/truth/nodes/split_by_llm_categorize/editor/feedback-categorization.png +0 -0
  148. package/src/display/FloatingTab.ts +174 -0
  149. package/src/display/ProgressBar.ts +22 -2
  150. package/src/events.ts +2 -4
  151. package/src/flow/CanvasNode.ts +190 -32
  152. package/src/flow/Editor.ts +1040 -3
  153. package/src/flow/NodeEditor.ts +317 -19
  154. package/src/flow/NodeTypeSelector.ts +47 -3
  155. package/src/flow/StickyNote.ts +12 -3
  156. package/src/flow/actions/add_contact_groups.ts +2 -1
  157. package/src/flow/actions/add_contact_urn.ts +3 -1
  158. package/src/flow/actions/add_input_labels.ts +2 -1
  159. package/src/flow/actions/play_audio.ts +2 -1
  160. package/src/flow/actions/remove_contact_groups.ts +3 -1
  161. package/src/flow/actions/request_optin.ts +1 -0
  162. package/src/flow/actions/say_msg.ts +2 -1
  163. package/src/flow/actions/send_broadcast.ts +2 -1
  164. package/src/flow/actions/send_email.ts +3 -1
  165. package/src/flow/actions/send_msg.ts +134 -3
  166. package/src/flow/actions/set_contact_channel.ts +2 -1
  167. package/src/flow/actions/set_contact_field.ts +2 -1
  168. package/src/flow/actions/set_contact_language.ts +3 -1
  169. package/src/flow/actions/set_contact_name.ts +2 -1
  170. package/src/flow/actions/set_contact_status.ts +2 -1
  171. package/src/flow/actions/set_run_result.ts +2 -1
  172. package/src/flow/actions/start_session.ts +3 -1
  173. package/src/flow/config.ts +2 -12
  174. package/src/flow/nodes/shared.ts +70 -1
  175. package/src/flow/nodes/split_by_airtime.ts +20 -3
  176. package/src/flow/nodes/split_by_contact_field.ts +13 -3
  177. package/src/flow/nodes/split_by_expression.ts +13 -3
  178. package/src/flow/nodes/split_by_groups.ts +13 -3
  179. package/src/flow/nodes/split_by_intent.ts +3 -2
  180. package/src/flow/nodes/split_by_llm.ts +19 -2
  181. package/src/flow/nodes/split_by_llm_categorize.ts +19 -2
  182. package/src/flow/nodes/split_by_random.ts +12 -2
  183. package/src/flow/nodes/split_by_resthook.ts +13 -3
  184. package/src/flow/nodes/split_by_run_result.ts +13 -3
  185. package/src/flow/nodes/split_by_scheme.ts +13 -3
  186. package/src/flow/nodes/split_by_subflow.ts +12 -2
  187. package/src/flow/nodes/split_by_ticket.ts +12 -2
  188. package/src/flow/nodes/split_by_webhook.ts +12 -2
  189. package/src/flow/nodes/wait_for_digits.ts +3 -2
  190. package/src/flow/nodes/wait_for_menu.ts +3 -2
  191. package/src/flow/nodes/wait_for_response.ts +13 -3
  192. package/src/flow/types.ts +47 -0
  193. package/src/layout/FloatingWindow.ts +386 -0
  194. package/src/live/ContactChat.ts +4 -19
  195. package/src/locales/es.ts +18 -13
  196. package/src/locales/fr.ts +18 -13
  197. package/src/locales/locale-codes.ts +11 -2
  198. package/src/locales/pt.ts +18 -13
  199. package/src/store/AppState.ts +104 -0
  200. package/static/api/llms.json +18 -0
  201. package/temba-modules.ts +4 -0
  202. package/test/temba-floating-tab.test.ts +110 -0
  203. package/test/temba-floating-window.test.ts +477 -0
  204. package/test/temba-flow-editor-node.test.ts +144 -0
  205. package/test/temba-localization.test.ts +611 -0
  206. package/test/temba-node-type-selector.test.ts +203 -0
  207. package/test/utils.test.ts +20 -0
  208. package/test-assets/contacts/history.json +5 -6
  209. package/test-assets/select/llms.json +2 -2
  210. package/web-dev-server.config.mjs +47 -1
  211. package/web-test-runner.config.mjs +0 -1
  212. package/out-tsc/src/flow/nodes/wait_for_audio.js +0 -7
  213. package/out-tsc/src/flow/nodes/wait_for_audio.js.map +0 -1
  214. package/out-tsc/src/flow/nodes/wait_for_image.js +0 -7
  215. package/out-tsc/src/flow/nodes/wait_for_image.js.map +0 -1
  216. package/out-tsc/src/flow/nodes/wait_for_location.js +0 -7
  217. package/out-tsc/src/flow/nodes/wait_for_location.js.map +0 -1
  218. package/out-tsc/src/flow/nodes/wait_for_video.js +0 -7
  219. package/out-tsc/src/flow/nodes/wait_for_video.js.map +0 -1
  220. package/src/flow/nodes/wait_for_audio.ts +0 -7
  221. package/src/flow/nodes/wait_for_image.ts +0 -7
  222. package/src/flow/nodes/wait_for_location.ts +0 -7
  223. package/src/flow/nodes/wait_for_video.ts +0 -7
@@ -1 +1 @@
1
- {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../../../src/flow/nodes/shared.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAoB;IAC9C,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,aAAa;IACpB,QAAQ,EAAE,KAAK;IACf,WAAW,EAAE,YAAY;IACzB,QAAQ,EAAE,sDAAsD;IAChE,YAAY,EAAE,mBAAmB;CAClC,CAAC","sourcesContent":["import { TextFieldConfig } from '../types';\n\n/**\n * Shared result_name field configuration for router nodes.\n * This provides a consistent \"Save as...\" optional field interface across all splits.\n *\n * The field is hidden by default and revealed via a \"Save as...\" link.\n * Once revealed, it cannot be hidden again (the link disappears).\n * If the field already has a value, it's shown immediately without the link.\n */\nexport const resultNameField: TextFieldConfig = {\n type: 'text',\n label: 'Result Name',\n required: false,\n placeholder: '(optional)',\n helpText: 'The name to use to reference this result in the flow',\n optionalLink: 'Save result as...'\n};\n"]}
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../../../src/flow/nodes/shared.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAoB;IAC9C,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,aAAa;IACpB,QAAQ,EAAE,KAAK;IACf,WAAW,EAAE,YAAY;IACzB,QAAQ,EAAE,sDAAsD;IAChE,YAAY,EAAE,mBAAmB;CAClC,CAAC;AAEF;;;GAGG;AAEH;;;;;GAKG;AACH,MAAM,UAAU,gCAAgC,CAC9C,IAAU,EACV,YAAiC;;IAEjC,MAAM,UAAU,GAAG,CAAA,MAAA,IAAI,CAAC,MAAM,0CAAE,UAAU,KAAI,EAAE,CAAC;IACjD,MAAM,gBAAgB,GAAwB,EAAE,CAAC;IAEjD,UAAU,CAAC,OAAO,CAAC,CAAC,QAAa,EAAE,EAAE;QACnC,MAAM,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC;QACnC,MAAM,oBAAoB,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;QAExD,gBAAgB,CAAC,YAAY,CAAC,GAAG;YAC/B,YAAY,EAAE,QAAQ,CAAC,IAAI;YAC3B,aAAa,EACX,oBAAoB,IAAI,oBAAoB,CAAC,IAAI;gBAC/C,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,oBAAoB,CAAC,IAAI,CAAC;oBACxC,CAAC,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE;oBACpC,CAAC,CAAC,oBAAoB,CAAC,IAAI;gBAC7B,CAAC,CAAC,EAAE;SACT,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,UAAU,EAAE,gBAAgB;KAC7B,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gCAAgC,CAC9C,QAAkB,EAClB,KAAW;IAEX,MAAM,gBAAgB,GAAwB,EAAE,CAAC;IAEjD,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;QACxB,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,YAAY,EAAE,EAAE;;YACxD,MAAM,YAAY,GAAG,QAAQ,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;YACvD,MAAM,aAAa,GAAG,CAAA,MAAA,YAAY,CAAC,aAAa,0CAAE,IAAI,EAAE,KAAI,EAAE,CAAC;YAC/D,MAAM,YAAY,GAAG,CAAA,MAAA,YAAY,CAAC,YAAY,0CAAE,IAAI,EAAE,KAAI,EAAE,CAAC;YAE7D,uEAAuE;YACvE,IAAI,aAAa,IAAI,aAAa,KAAK,YAAY,EAAE,CAAC;gBACpD,gBAAgB,CAAC,YAAY,CAAC,GAAG;oBAC/B,IAAI,EAAE,CAAC,aAAa,CAAC;iBACtB,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,gBAAgB,CAAC;AAC1B,CAAC","sourcesContent":["import { FormData, TextFieldConfig } from '../types';\nimport { Node } from '../../store/flow-definition';\n\n/**\n * Shared result_name field configuration for router nodes.\n * This provides a consistent \"Save as...\" optional field interface across all splits.\n *\n * The field is hidden by default and revealed via a \"Save as...\" link.\n * Once revealed, it cannot be hidden again (the link disappears).\n * If the field already has a value, it's shown immediately without the link.\n */\nexport const resultNameField: TextFieldConfig = {\n type: 'text',\n label: 'Result Name',\n required: false,\n placeholder: '(optional)',\n helpText: 'The name to use to reference this result in the flow',\n optionalLink: 'Save result as...'\n};\n\n/**\n * Shared category localization functions for router nodes.\n * These provide a consistent way to localize category names across all router types.\n */\n\n/**\n * Converts a node's categories to localization form data.\n * @param node - The node containing categories to localize\n * @param localization - The existing localization data for this language\n * @returns Form data with category UUIDs mapped to original and localized names\n */\nexport function categoriesToLocalizationFormData(\n node: Node,\n localization: Record<string, any>\n): FormData {\n const categories = node.router?.categories || [];\n const localizationData: Record<string, any> = {};\n\n categories.forEach((category: any) => {\n const categoryUuid = category.uuid;\n const categoryLocalization = localization[categoryUuid];\n\n localizationData[categoryUuid] = {\n originalName: category.name,\n localizedName:\n categoryLocalization && categoryLocalization.name\n ? Array.isArray(categoryLocalization.name)\n ? categoryLocalization.name[0] || ''\n : categoryLocalization.name\n : ''\n };\n });\n\n return {\n categories: localizationData\n };\n}\n\n/**\n * Converts localization form data back to the localization structure.\n * @param formData - The form data containing category localizations\n * @param _node - The original node (reserved for future validation)\n * @returns Record mapping category UUIDs to their localization data\n */\nexport function localizationFormDataToCategories(\n formData: FormData,\n _node: Node\n): Record<string, any> {\n const localizationData: Record<string, any> = {};\n\n if (formData.categories) {\n Object.keys(formData.categories).forEach((categoryUuid) => {\n const categoryData = formData.categories[categoryUuid];\n const localizedName = categoryData.localizedName?.trim() || '';\n const originalName = categoryData.originalName?.trim() || '';\n\n // Only save if localized name is different from original and not empty\n if (localizedName && localizedName !== originalName) {\n localizationData[categoryUuid] = {\n name: [localizedName]\n };\n }\n });\n }\n\n return localizationData;\n}\n"]}
@@ -1,12 +1,14 @@
1
- import { ACTION_GROUPS } from '../types';
1
+ import { ACTION_GROUPS, FlowTypes, Features } from '../types';
2
2
  import { generateUUID, createSuccessFailureRouter } from '../../utils';
3
3
  import { html } from 'lit';
4
4
  import { CURRENCY_OPTIONS, CURRENCIES } from '../currencies';
5
- import { resultNameField } from './shared';
5
+ import { resultNameField, categoriesToLocalizationFormData, localizationFormDataToCategories } from './shared';
6
6
  export const split_by_airtime = {
7
7
  type: 'split_by_airtime',
8
8
  name: 'Send Airtime',
9
9
  group: ACTION_GROUPS.services,
10
+ flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
11
+ features: [Features.AIRTIME],
10
12
  showAsAction: true,
11
13
  form: {
12
14
  amounts: {
@@ -204,6 +206,10 @@ export const split_by_airtime = {
204
206
  router: finalRouter,
205
207
  exits: exits
206
208
  };
207
- }
209
+ },
210
+ // Localization support for categories
211
+ localizable: 'categories',
212
+ toLocalizationFormData: categoriesToLocalizationFormData,
213
+ fromLocalizationFormData: localizationFormDataToCategories
208
214
  };
209
215
  //# sourceMappingURL=split_by_airtime.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"split_by_airtime.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_airtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAwB,MAAM,UAAU,CAAC;AAE/D,OAAO,EAAE,YAAY,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C,MAAM,CAAC,MAAM,gBAAgB,GAAe;IAC1C,IAAI,EAAE,kBAAkB;IACxB,IAAI,EAAE,cAAc;IACpB,KAAK,EAAE,aAAa,CAAC,QAAQ;IAC7B,YAAY,EAAE,IAAI;IAClB,IAAI,EAAE;QACJ,OAAO,EAAE;YACP,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,iBAAiB;YACxB,QAAQ,EAAE,+CAA+C;YACzD,QAAQ,EAAE,IAAI;YACd,SAAS,EAAE,QAAQ;YACnB,QAAQ,EAAE,KAAK;YACf,QAAQ,EAAE,CAAC;YACX,QAAQ,EAAE,EAAE;YACZ,WAAW,EAAE,CAAC,IAAS,EAAE,EAAE;gBACzB,OAAO,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;YACrE,CAAC;YACD,UAAU,EAAE;gBACV,QAAQ,EAAE;oBACR,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,mBAAmB;oBAChC,QAAQ,EAAE,IAAI;oBACd,OAAO,EAAE,gBAAgB;oBACzB,UAAU,EAAE,IAAI;oBAChB,KAAK,EAAE,KAAK;oBACZ,KAAK,EAAE,OAAO;iBACf;gBACD,MAAM,EAAE;oBACN,IAAI,EAAE,MAAM;oBACZ,WAAW,EAAE,QAAQ;oBACrB,QAAQ,EAAE,IAAI;iBACf;aACF;SACF;QACD,WAAW,EAAE,eAAe;KAC7B;IACD,MAAM,EAAE,CAAC,SAAS,EAAE,aAAa,CAAC;IAClC,QAAQ,EAAE,CAAC,QAAkB,EAAE,EAAE;QAC/B,MAAM,MAAM,GAA8B,EAAE,CAAC;QAE7C,4CAA4C;QAC5C,IAAI,QAAQ,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YACxD,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAC1C,CAAC,IAAS,EAAE,EAAE,CACZ,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,QAAQ,MAAI,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,MAAM,CAAA,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,CAC9D,CAAC;YAEF,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC9B,MAAM,CAAC,OAAO,GAAG,8CAA8C,CAAC;gBAChE,OAAO;oBACL,KAAK,EAAE,KAAK;oBACZ,MAAM;iBACP,CAAC;YACJ,CAAC;YAED,iCAAiC;YACjC,MAAM,UAAU,GAAG,IAAI,GAAG,EAAE,CAAC;YAC7B,MAAM,UAAU,GAAa,EAAE,CAAC;YAEhC,YAAY,CAAC,OAAO,CAAC,CAAC,IAAS,EAAE,EAAE;;gBACjC,uCAAuC;gBACvC,MAAM,YAAY,GAChB,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;oBACtD,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK;oBACxB,CAAC,CAAC,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ;wBACnC,CAAC,CAAC,IAAI,CAAC,QAAQ;wBACf,CAAC,CAAC,MAAA,IAAI,CAAC,QAAQ,0CAAE,KAAK,CAAC;gBAE3B,IAAI,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;oBACjC,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;gBAChC,CAAC;qBAAM,CAAC;oBACN,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;gBAC/B,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,MAAM,CAAC,OAAO,GAAG,+BAA+B,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1E,CAAC;YAED,+BAA+B;YAC/B,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;gBAChC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;gBAClC,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;oBACjD,MAAM,CAAC,OAAO,GAAG,4CAA4C,CAAC;oBAC9D,OAAO;wBACL,KAAK,EAAE,KAAK;wBACZ,MAAM;qBACP,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,OAAO,GAAG,8CAA8C,CAAC;QAClE,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,qBAAqB,GAAG,MAAA,IAAI,CAAC,OAAO,0CAAE,IAAI,CAC9C,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,kBAAkB,CAC5B,CAAC;QAErB,IAAI,CAAC,qBAAqB,IAAI,CAAC,qBAAqB,CAAC,OAAO,EAAE,CAAC;YAC7D,OAAO,IAAI,CAAA,oDAAoD,CAAC;QAClE,CAAC;QAED,MAAM,OAAO,GAAG,qBAAqB,CAAC,OAAO,CAAC;QAC9C,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAExC,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAA,oDAAoD,CAAC;QAClE,CAAC;QAED,sEAAsE;QACtE,MAAM,aAAa,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QACpC,MAAM,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;QAC3C,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;QAExC,OAAO,IAAI,CAAA;;UAEL,aAAa;UACb,WAAW,GAAG,SAAS,GAAG,CAAC;YAC3B,CAAC,CAAC,IAAI,CAAA,gCAAgC,SAAS,cAAc;YAC7D,CAAC,CAAC,EAAE;;KAET,CAAC;IACJ,CAAC;IACD,UAAU,EAAE,CAAC,IAAU,EAAE,EAAE;;QACzB,gDAAgD;QAChD,MAAM,qBAAqB,GAAG,MAAA,IAAI,CAAC,OAAO,0CAAE,IAAI,CAC9C,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,kBAAkB,CAC5B,CAAC;QAErB,MAAM,OAAO,GAAU,EAAE,CAAC;QAC1B,IAAI,qBAAqB,IAAI,qBAAqB,CAAC,OAAO,EAAE,CAAC;YAC3D,MAAM,CAAC,OAAO,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC,OAAO,CACnD,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE;;gBACrB,OAAO,CAAC,IAAI,CAAC;oBACX,QAAQ,EAAE;wBACR;4BACE,KAAK,EAAE,QAAQ;4BACf,IAAI,EAAE,CAAA,MAAA,UAAU,CAAC,QAAQ,CAAC,0CAAE,IAAI;gCAC9B,CAAC,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,IAAI,KAAK,QAAQ,GAAG;gCAC9C,CAAC,CAAC,QAAQ;yBACb;qBACF;oBACD,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC;iBACvB,CAAC,CAAC;YACL,CAAC,CACF,CAAC;QACJ,CAAC;QAED,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,OAAO;YAChB,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,iDAAiD;QACjD,MAAM,aAAa,GAA2B,EAAE,CAAC;QAEjD,IAAI,QAAQ,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YACxD,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAS,EAAE,EAAE;;gBACrC,IAAI,CAAC,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,QAAQ,CAAA,IAAI,CAAC,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,MAAM,CAAA,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;oBAClE,OAAO;gBACT,CAAC;gBAED,8EAA8E;gBAC9E,IAAI,YAAoB,CAAC;gBACzB,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC7D,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;gBACxC,CAAC;qBAAM,IAAI,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;oBAC7C,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC;gBAC/B,CAAC;qBAAM,IAAI,MAAA,IAAI,CAAC,QAAQ,0CAAE,KAAK,EAAE,CAAC;oBAChC,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBACrC,CAAC;qBAAM,CAAC;oBACN,OAAO;gBACT,CAAC;gBAED,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;gBAC9C,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;oBACjC,aAAa,CAAC,YAAY,CAAC,GAAG,MAAM,CAAC;gBACvC,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QAED,6DAA6D;QAC7D,MAAM,6BAA6B,GAAG,MAAA,YAAY,CAAC,OAAO,0CAAE,IAAI,CAC9D,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,kBAAkB,CAC/C,CAAC;QACF,MAAM,mBAAmB,GACvB,CAAA,6BAA6B,aAA7B,6BAA6B,uBAA7B,6BAA6B,CAAE,IAAI,KAAI,YAAY,EAAE,CAAC;QAExD,iCAAiC;QACjC,MAAM,qBAAqB,GAAoB;YAC7C,IAAI,EAAE,kBAAkB;YACxB,IAAI,EAAE,mBAAmB;YACzB,OAAO,EAAE,aAAa;SACvB,CAAC;QAEF,sDAAsD;QACtD,MAAM,kBAAkB,GAAG,CAAA,MAAA,YAAY,CAAC,MAAM,0CAAE,UAAU,KAAI,EAAE,CAAC;QACjE,MAAM,aAAa,GAAG,YAAY,CAAC,KAAK,IAAI,EAAE,CAAC;QAC/C,MAAM,aAAa,GAAG,CAAA,MAAA,YAAY,CAAC,MAAM,0CAAE,KAAK,KAAI,EAAE,CAAC;QAEvD,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,0BAA0B,CAClD,uBAAuB,EACvB;YACE,IAAI,EAAE,UAAU;YAChB,SAAS,EAAE,EAAE;SACd,EACD,kBAAkB,EAClB,aAAa,EACb,aAAa,CACd,CAAC;QAEF,8BAA8B;QAC9B,MAAM,WAAW,GAAQ,EAAE,GAAG,MAAM,EAAE,CAAC;QACvC,IAAI,QAAQ,CAAC,WAAW,IAAI,QAAQ,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAC/D,WAAW,CAAC,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;QACxD,CAAC;QAED,2BAA2B;QAC3B,OAAO;YACL,IAAI,EAAE,YAAY,CAAC,IAAI;YACvB,OAAO,EAAE,CAAC,qBAAqB,CAAC;YAChC,MAAM,EAAE,WAAW;YACnB,KAAK,EAAE,KAAK;SACb,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import { ACTION_GROUPS, FormData, NodeConfig } from '../types';\nimport { TransferAirtime, Node } from '../../store/flow-definition';\nimport { generateUUID, createSuccessFailureRouter } from '../../utils';\nimport { html } from 'lit';\nimport { CURRENCY_OPTIONS, CURRENCIES } from '../currencies';\nimport { resultNameField } from './shared';\n\nexport const split_by_airtime: NodeConfig = {\n type: 'split_by_airtime',\n name: 'Send Airtime',\n group: ACTION_GROUPS.services,\n showAsAction: true,\n form: {\n amounts: {\n type: 'array',\n label: 'Airtime Amounts',\n helpText: 'Define the currencies and amounts to transfer',\n required: true,\n itemLabel: 'Amount',\n sortable: false,\n minItems: 1,\n maxItems: 10,\n isEmptyItem: (item: any) => {\n return !item.currency || !item.amount || item.amount.trim() === '';\n },\n itemConfig: {\n currency: {\n type: 'select',\n placeholder: 'Select a currency',\n required: true,\n options: CURRENCY_OPTIONS,\n searchable: true,\n multi: false,\n width: '200px'\n },\n amount: {\n type: 'text',\n placeholder: 'Amount',\n required: true\n }\n }\n },\n result_name: resultNameField\n },\n layout: ['amounts', 'result_name'],\n validate: (formData: FormData) => {\n const errors: { [key: string]: string } = {};\n\n // Validate that we have at least one amount\n if (formData.amounts && Array.isArray(formData.amounts)) {\n const validAmounts = formData.amounts.filter(\n (item: any) =>\n item?.currency && item?.amount && item.amount.trim() !== ''\n );\n\n if (validAmounts.length === 0) {\n errors.amounts = 'At least one currency and amount is required';\n return {\n valid: false,\n errors\n };\n }\n\n // Check for duplicate currencies\n const currencies = new Set();\n const duplicates: string[] = [];\n\n validAmounts.forEach((item: any) => {\n // Extract currency code from selection\n const currencyCode =\n Array.isArray(item.currency) && item.currency.length > 0\n ? item.currency[0].value\n : typeof item.currency === 'string'\n ? item.currency\n : item.currency?.value;\n\n if (currencies.has(currencyCode)) {\n duplicates.push(currencyCode);\n } else {\n currencies.add(currencyCode);\n }\n });\n\n if (duplicates.length > 0) {\n errors.amounts = `Duplicate currencies found: ${duplicates.join(', ')}`;\n }\n\n // Validate amounts are numeric\n for (const item of validAmounts) {\n const amount = item.amount.trim();\n if (isNaN(Number(amount)) || Number(amount) <= 0) {\n errors.amounts = 'All amounts must be valid positive numbers';\n return {\n valid: false,\n errors\n };\n }\n }\n } else {\n errors.amounts = 'At least one currency and amount is required';\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n render: (node: Node) => {\n const transferAirtimeAction = node.actions?.find(\n (action) => action.type === 'transfer_airtime'\n ) as TransferAirtime;\n\n if (!transferAirtimeAction || !transferAirtimeAction.amounts) {\n return html`<div class=\"body\">Configure airtime transfer</div>`;\n }\n\n const amounts = transferAirtimeAction.amounts;\n const currencies = Object.keys(amounts);\n\n if (currencies.length === 0) {\n return html`<div class=\"body\">Configure airtime transfer</div>`;\n }\n\n // Display the first currency amount, with indicator if there are more\n const firstCurrency = currencies[0];\n const firstAmount = amounts[firstCurrency];\n const moreCount = currencies.length - 1;\n\n return html`\n <div class=\"body\">\n ${firstCurrency}\n ${firstAmount}${moreCount > 0\n ? html` <span style=\"color: #999;\">+${moreCount} more</span>`\n : ''}\n </div>\n `;\n },\n toFormData: (node: Node) => {\n // Extract data from the existing node structure\n const transferAirtimeAction = node.actions?.find(\n (action) => action.type === 'transfer_airtime'\n ) as TransferAirtime;\n\n const amounts: any[] = [];\n if (transferAirtimeAction && transferAirtimeAction.amounts) {\n Object.entries(transferAirtimeAction.amounts).forEach(\n ([currency, amount]) => {\n amounts.push({\n currency: [\n {\n value: currency,\n name: CURRENCIES[currency]?.name\n ? `${CURRENCIES[currency].name} (${currency})`\n : currency\n }\n ],\n amount: String(amount)\n });\n }\n );\n }\n\n return {\n uuid: node.uuid,\n amounts: amounts,\n result_name: node.router?.result_name || ''\n };\n },\n fromFormData: (formData: FormData, originalNode: Node): Node => {\n // Get user amounts and convert to amounts object\n const amountsObject: Record<string, number> = {};\n\n if (formData.amounts && Array.isArray(formData.amounts)) {\n formData.amounts.forEach((item: any) => {\n if (!item?.currency || !item?.amount || item.amount.trim() === '') {\n return;\n }\n\n // Extract currency code from selection (handle both array and object formats)\n let currencyCode: string;\n if (Array.isArray(item.currency) && item.currency.length > 0) {\n currencyCode = item.currency[0].value;\n } else if (typeof item.currency === 'string') {\n currencyCode = item.currency;\n } else if (item.currency?.value) {\n currencyCode = item.currency.value;\n } else {\n return;\n }\n\n const amount = parseFloat(item.amount.trim());\n if (!isNaN(amount) && amount > 0) {\n amountsObject[currencyCode] = amount;\n }\n });\n }\n\n // Find existing transfer_airtime action to preserve its UUID\n const existingTransferAirtimeAction = originalNode.actions?.find(\n (action) => action.type === 'transfer_airtime'\n );\n const transferAirtimeUuid =\n existingTransferAirtimeAction?.uuid || generateUUID();\n\n // Create transfer_airtime action\n const transferAirtimeAction: TransferAirtime = {\n type: 'transfer_airtime',\n uuid: transferAirtimeUuid,\n amounts: amountsObject\n };\n\n // Create categories and exits for Success and Failure\n const existingCategories = originalNode.router?.categories || [];\n const existingExits = originalNode.exits || [];\n const existingCases = originalNode.router?.cases || [];\n\n const { router, exits } = createSuccessFailureRouter(\n '@locals._new_transfer',\n {\n type: 'has_text',\n arguments: []\n },\n existingCategories,\n existingExits,\n existingCases\n );\n\n // Add result_name if provided\n const finalRouter: any = { ...router };\n if (formData.result_name && formData.result_name.trim() !== '') {\n finalRouter.result_name = formData.result_name.trim();\n }\n\n // Return the complete node\n return {\n uuid: originalNode.uuid,\n actions: [transferAirtimeAction],\n router: finalRouter,\n exits: exits\n };\n }\n};\n"]}
1
+ {"version":3,"file":"split_by_airtime.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_airtime.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ACTION_GROUPS,\n FormData,\n NodeConfig,\n FlowTypes,\n Features\n} from '../types';\nimport { TransferAirtime, Node } from '../../store/flow-definition';\nimport { generateUUID, createSuccessFailureRouter } from '../../utils';\nimport { html } from 'lit';\nimport { CURRENCY_OPTIONS, CURRENCIES } from '../currencies';\nimport {\n resultNameField,\n categoriesToLocalizationFormData,\n localizationFormDataToCategories\n} from './shared';\n\nexport const split_by_airtime: NodeConfig = {\n type: 'split_by_airtime',\n name: 'Send Airtime',\n group: ACTION_GROUPS.services,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n features: [Features.AIRTIME],\n showAsAction: true,\n form: {\n amounts: {\n type: 'array',\n label: 'Airtime Amounts',\n helpText: 'Define the currencies and amounts to transfer',\n required: true,\n itemLabel: 'Amount',\n sortable: false,\n minItems: 1,\n maxItems: 10,\n isEmptyItem: (item: any) => {\n return !item.currency || !item.amount || item.amount.trim() === '';\n },\n itemConfig: {\n currency: {\n type: 'select',\n placeholder: 'Select a currency',\n required: true,\n options: CURRENCY_OPTIONS,\n searchable: true,\n multi: false,\n width: '200px'\n },\n amount: {\n type: 'text',\n placeholder: 'Amount',\n required: true\n }\n }\n },\n result_name: resultNameField\n },\n layout: ['amounts', 'result_name'],\n validate: (formData: FormData) => {\n const errors: { [key: string]: string } = {};\n\n // Validate that we have at least one amount\n if (formData.amounts && Array.isArray(formData.amounts)) {\n const validAmounts = formData.amounts.filter(\n (item: any) =>\n item?.currency && item?.amount && item.amount.trim() !== ''\n );\n\n if (validAmounts.length === 0) {\n errors.amounts = 'At least one currency and amount is required';\n return {\n valid: false,\n errors\n };\n }\n\n // Check for duplicate currencies\n const currencies = new Set();\n const duplicates: string[] = [];\n\n validAmounts.forEach((item: any) => {\n // Extract currency code from selection\n const currencyCode =\n Array.isArray(item.currency) && item.currency.length > 0\n ? item.currency[0].value\n : typeof item.currency === 'string'\n ? item.currency\n : item.currency?.value;\n\n if (currencies.has(currencyCode)) {\n duplicates.push(currencyCode);\n } else {\n currencies.add(currencyCode);\n }\n });\n\n if (duplicates.length > 0) {\n errors.amounts = `Duplicate currencies found: ${duplicates.join(', ')}`;\n }\n\n // Validate amounts are numeric\n for (const item of validAmounts) {\n const amount = item.amount.trim();\n if (isNaN(Number(amount)) || Number(amount) <= 0) {\n errors.amounts = 'All amounts must be valid positive numbers';\n return {\n valid: false,\n errors\n };\n }\n }\n } else {\n errors.amounts = 'At least one currency and amount is required';\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n render: (node: Node) => {\n const transferAirtimeAction = node.actions?.find(\n (action) => action.type === 'transfer_airtime'\n ) as TransferAirtime;\n\n if (!transferAirtimeAction || !transferAirtimeAction.amounts) {\n return html`<div class=\"body\">Configure airtime transfer</div>`;\n }\n\n const amounts = transferAirtimeAction.amounts;\n const currencies = Object.keys(amounts);\n\n if (currencies.length === 0) {\n return html`<div class=\"body\">Configure airtime transfer</div>`;\n }\n\n // Display the first currency amount, with indicator if there are more\n const firstCurrency = currencies[0];\n const firstAmount = amounts[firstCurrency];\n const moreCount = currencies.length - 1;\n\n return html`\n <div class=\"body\">\n ${firstCurrency}\n ${firstAmount}${moreCount > 0\n ? html` <span style=\"color: #999;\">+${moreCount} more</span>`\n : ''}\n </div>\n `;\n },\n toFormData: (node: Node) => {\n // Extract data from the existing node structure\n const transferAirtimeAction = node.actions?.find(\n (action) => action.type === 'transfer_airtime'\n ) as TransferAirtime;\n\n const amounts: any[] = [];\n if (transferAirtimeAction && transferAirtimeAction.amounts) {\n Object.entries(transferAirtimeAction.amounts).forEach(\n ([currency, amount]) => {\n amounts.push({\n currency: [\n {\n value: currency,\n name: CURRENCIES[currency]?.name\n ? `${CURRENCIES[currency].name} (${currency})`\n : currency\n }\n ],\n amount: String(amount)\n });\n }\n );\n }\n\n return {\n uuid: node.uuid,\n amounts: amounts,\n result_name: node.router?.result_name || ''\n };\n },\n fromFormData: (formData: FormData, originalNode: Node): Node => {\n // Get user amounts and convert to amounts object\n const amountsObject: Record<string, number> = {};\n\n if (formData.amounts && Array.isArray(formData.amounts)) {\n formData.amounts.forEach((item: any) => {\n if (!item?.currency || !item?.amount || item.amount.trim() === '') {\n return;\n }\n\n // Extract currency code from selection (handle both array and object formats)\n let currencyCode: string;\n if (Array.isArray(item.currency) && item.currency.length > 0) {\n currencyCode = item.currency[0].value;\n } else if (typeof item.currency === 'string') {\n currencyCode = item.currency;\n } else if (item.currency?.value) {\n currencyCode = item.currency.value;\n } else {\n return;\n }\n\n const amount = parseFloat(item.amount.trim());\n if (!isNaN(amount) && amount > 0) {\n amountsObject[currencyCode] = amount;\n }\n });\n }\n\n // Find existing transfer_airtime action to preserve its UUID\n const existingTransferAirtimeAction = originalNode.actions?.find(\n (action) => action.type === 'transfer_airtime'\n );\n const transferAirtimeUuid =\n existingTransferAirtimeAction?.uuid || generateUUID();\n\n // Create transfer_airtime action\n const transferAirtimeAction: TransferAirtime = {\n type: 'transfer_airtime',\n uuid: transferAirtimeUuid,\n amounts: amountsObject\n };\n\n // Create categories and exits for Success and Failure\n const existingCategories = originalNode.router?.categories || [];\n const existingExits = originalNode.exits || [];\n const existingCases = originalNode.router?.cases || [];\n\n const { router, exits } = createSuccessFailureRouter(\n '@locals._new_transfer',\n {\n type: 'has_text',\n arguments: []\n },\n existingCategories,\n existingExits,\n existingCases\n );\n\n // Add result_name if provided\n const finalRouter: any = { ...router };\n if (formData.result_name && formData.result_name.trim() !== '') {\n finalRouter.result_name = formData.result_name.trim();\n }\n\n // Return the complete node\n return {\n uuid: originalNode.uuid,\n actions: [transferAirtimeAction],\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,7 +1,7 @@
1
- import { SPLIT_GROUPS } from '../types';
1
+ import { SPLIT_GROUPS, FlowTypes } from '../types';
2
2
  import { createRulesRouter } from '../../utils';
3
3
  import { getWaitForResponseOperators, operatorsToSelectOptions, getOperatorConfig } from '../operators';
4
- import { resultNameField } from './shared';
4
+ import { resultNameField, categoriesToLocalizationFormData, localizationFormDataToCategories } from './shared';
5
5
  import { createRulesArrayConfig, extractUserRules, casesToFormRules } from './shared-rules';
6
6
  import { SCHEMES } from '../utils';
7
7
  import { html } from 'lit';
@@ -32,6 +32,7 @@ export const split_by_contact_field = {
32
32
  type: 'split_by_contact_field',
33
33
  name: 'Split by Contact Field',
34
34
  group: SPLIT_GROUPS.split,
35
+ flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
35
36
  dialogSize: 'large',
36
37
  form: {
37
38
  field: {
@@ -146,6 +147,10 @@ export const split_by_contact_field = {
146
147
  },
147
148
  renderTitle: (node, nodeUI) => {
148
149
  return html `<div>Split by ${nodeUI.config.operand.name}</div>`;
149
- }
150
+ },
151
+ // Localization support for categories
152
+ localizable: 'categories',
153
+ toLocalizationFormData: categoriesToLocalizationFormData,
154
+ fromLocalizationFormData: localizationFormDataToCategories
150
155
  };
151
156
  //# sourceMappingURL=split_by_contact_field.js.map
@@ -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 } from '../types';\nimport { Node } from '../../store/flow-definition';\nimport { createRulesRouter } from '../../utils';\nimport {\n getWaitForResponseOperators,\n operatorsToSelectOptions,\n getOperatorConfig\n} from '../operators';\nimport { resultNameField } from './shared';\nimport {\n createRulesArrayConfig,\n extractUserRules,\n casesToFormRules\n} from './shared-rules';\nimport { 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 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"]}
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,12 +1,13 @@
1
- import { SPLIT_GROUPS } from '../types';
1
+ import { SPLIT_GROUPS, FlowTypes } from '../types';
2
2
  import { createRulesRouter } from '../../utils';
3
3
  import { getWaitForResponseOperators, operatorsToSelectOptions, getOperatorConfig } from '../operators';
4
- import { resultNameField } from './shared';
4
+ import { resultNameField, categoriesToLocalizationFormData, localizationFormDataToCategories } from './shared';
5
5
  import { createRulesArrayConfig, extractUserRules, casesToFormRules } from './shared-rules';
6
6
  export const split_by_expression = {
7
7
  type: 'split_by_expression',
8
8
  name: 'Split by Expression',
9
9
  group: SPLIT_GROUPS.split,
10
+ flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
10
11
  dialogSize: 'large',
11
12
  form: {
12
13
  operand: {
@@ -68,6 +69,10 @@ export const split_by_expression = {
68
69
  router: finalRouter,
69
70
  exits: exits
70
71
  };
71
- }
72
+ },
73
+ // Localization support for categories
74
+ localizable: 'categories',
75
+ toLocalizationFormData: categoriesToLocalizationFormData,
76
+ fromLocalizationFormData: localizationFormDataToCategories
72
77
  };
73
78
  //# sourceMappingURL=split_by_expression.js.map
@@ -1 +1 @@
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 } from '../types';\nimport { Node } from '../../store/flow-definition';\nimport { createRulesRouter } from '../../utils';\nimport {\n getWaitForResponseOperators,\n operatorsToSelectOptions,\n getOperatorConfig\n} from '../operators';\nimport { resultNameField } from './shared';\nimport {\n createRulesArrayConfig,\n extractUserRules,\n casesToFormRules\n} from './shared-rules';\n\nexport const split_by_expression: NodeConfig = {\n type: 'split_by_expression',\n name: 'Split by Expression',\n group: SPLIT_GROUPS.split,\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"]}
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 '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,6 +1,6 @@
1
- import { SPLIT_GROUPS } from '../types';
1
+ import { SPLIT_GROUPS, FlowTypes } from '../types';
2
2
  import { generateUUID } from '../../utils';
3
- import { resultNameField } from './shared';
3
+ import { resultNameField, categoriesToLocalizationFormData, localizationFormDataToCategories } from './shared';
4
4
  // Helper function to create a switch router with group cases
5
5
  const createGroupRouter = (userGroups, existingCategories = [], existingExits = [], existingCases = [], resultName = '') => {
6
6
  const categories = [];
@@ -66,6 +66,7 @@ export const split_by_groups = {
66
66
  type: 'split_by_groups',
67
67
  name: 'Split by Group',
68
68
  group: SPLIT_GROUPS.split,
69
+ flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
69
70
  form: {
70
71
  groups: {
71
72
  type: 'select',
@@ -153,6 +154,10 @@ export const split_by_groups = {
153
154
  router: {
154
155
  type: 'switch',
155
156
  operand: '@contact.groups'
156
- }
157
+ },
158
+ // Localization support for categories
159
+ localizable: 'categories',
160
+ toLocalizationFormData: categoriesToLocalizationFormData,
161
+ fromLocalizationFormData: localizationFormDataToCategories
157
162
  };
158
163
  //# sourceMappingURL=split_by_groups.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"split_by_groups.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_groups.ts"],"names":[],"mappings":"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","sourcesContent":["import { SPLIT_GROUPS, FormData, NodeConfig } from '../types';\nimport { Node, Category, Exit, Case } from '../../store/flow-definition.d';\nimport { generateUUID } from '../../utils';\nimport { resultNameField } from './shared';\n\n// Helper function to create a switch router with group cases\nconst createGroupRouter = (\n userGroups: { uuid: string; name: string }[],\n existingCategories: Category[] = [],\n existingExits: Exit[] = [],\n existingCases: Case[] = [],\n resultName: string = ''\n) => {\n const categories: Category[] = [];\n const exits: Exit[] = [];\n const cases: Case[] = [];\n\n // Create categories, exits, and cases for each selected group\n userGroups.forEach((group) => {\n // Try to find existing category by group name\n const existingCategory = existingCategories.find(\n (cat) => cat.name === group.name\n );\n const existingExit = existingCategory\n ? existingExits.find((exit) => exit.uuid === existingCategory.exit_uuid)\n : null;\n const existingCase = existingCases.find(\n (c) => c.arguments?.[0] === group.uuid\n );\n\n const exitUuid = existingExit?.uuid || generateUUID();\n const categoryUuid = existingCategory?.uuid || generateUUID();\n const caseUuid = existingCase?.uuid || generateUUID();\n\n categories.push({\n uuid: categoryUuid,\n name: group.name,\n exit_uuid: exitUuid\n });\n\n exits.push({\n uuid: exitUuid,\n destination_uuid: existingExit?.destination_uuid || null\n });\n\n cases.push({\n uuid: caseUuid,\n type: 'has_group',\n arguments: [group.uuid, group.name],\n category_uuid: categoryUuid\n });\n });\n\n // Add default \"Other\" category for contacts not in any selected group\n const existingOtherCategory = existingCategories.find(\n (cat) =>\n cat.name === 'Other' &&\n !userGroups.some((group) => group.name === cat.name)\n );\n const existingOtherExit = existingOtherCategory\n ? existingExits.find(\n (exit) => exit.uuid === existingOtherCategory.exit_uuid\n )\n : null;\n\n const otherExitUuid = existingOtherExit?.uuid || generateUUID();\n const otherCategoryUuid = existingOtherCategory?.uuid || generateUUID();\n\n categories.push({\n uuid: otherCategoryUuid,\n name: 'Other',\n exit_uuid: otherExitUuid\n });\n\n exits.push({\n uuid: otherExitUuid,\n destination_uuid: existingOtherExit?.destination_uuid || null\n });\n\n return {\n router: {\n type: 'switch' as const,\n cases: cases,\n categories: categories,\n default_category_uuid: otherCategoryUuid,\n operand: '@contact.groups',\n result_name: resultName\n },\n exits: exits\n };\n};\n\nexport const split_by_groups: NodeConfig = {\n type: 'split_by_groups',\n name: 'Split by Group',\n group: SPLIT_GROUPS.split,\n form: {\n groups: {\n type: 'select',\n label: 'Groups',\n helpText:\n 'Select the groups to split contacts by. Contacts will be routed based on their group membership.',\n required: true,\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 allowCreate: true,\n createArbitraryOption: (input: string, options: any[]) => {\n // Check if a group with this name already exists\n const existing = options.find(\n (option) =>\n option.name.toLowerCase().trim() === input.toLowerCase().trim()\n );\n if (!existing && input.trim()) {\n return {\n name: input.trim(),\n arbitrary: true\n };\n }\n return null;\n }\n },\n result_name: resultNameField\n },\n layout: ['groups', 'result_name'],\n validate: (formData: FormData) => {\n const errors: { [key: string]: string } = {};\n\n if (\n !formData.groups ||\n !Array.isArray(formData.groups) ||\n formData.groups.length === 0\n ) {\n errors.groups = 'At least one group is required';\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n toFormData: (node: Node) => {\n // Extract groups from the existing node structure\n const groups: { uuid: string; name: string }[] = [];\n\n if (node.router?.cases) {\n node.router.cases.forEach((c: Case) => {\n if (c.type === 'has_group' && c.arguments?.length >= 2) {\n groups.push({\n uuid: c.arguments[0],\n name: c.arguments[1]\n });\n }\n });\n }\n\n return {\n uuid: node.uuid,\n groups: groups,\n result_name: node.router?.result_name || ''\n };\n },\n fromFormData: (formData: FormData, originalNode: Node): Node => {\n // Get selected groups\n const selectedGroups = (formData.groups || [])\n .filter((group: any) => group?.uuid || group?.arbitrary)\n .map((group: any) => ({\n uuid: group.uuid || generateUUID(), // Generate UUID for arbitrary groups\n name: group.name\n }));\n\n // Create router and exits using existing data when possible\n const existingCategories = originalNode.router?.categories || [];\n const existingExits = originalNode.exits || [];\n const existingCases = originalNode.router?.cases || [];\n\n const { router, exits } = createGroupRouter(\n selectedGroups,\n existingCategories,\n existingExits,\n existingCases,\n formData.result_name || ''\n );\n\n // Return the complete node\n return {\n uuid: originalNode.uuid,\n actions: originalNode.actions || [],\n router: router,\n exits: exits\n };\n },\n router: {\n type: 'switch',\n operand: '@contact.groups'\n }\n};\n"]}
1
+ {"version":3,"file":"split_by_groups.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_groups.ts"],"names":[],"mappings":"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","sourcesContent":["import { SPLIT_GROUPS, FormData, NodeConfig, FlowTypes } from '../types';\nimport { Node, Category, Exit, Case } from '../../store/flow-definition.d';\nimport { generateUUID } from '../../utils';\nimport {\n resultNameField,\n categoriesToLocalizationFormData,\n localizationFormDataToCategories\n} from './shared';\n\n// Helper function to create a switch router with group cases\nconst createGroupRouter = (\n userGroups: { uuid: string; name: string }[],\n existingCategories: Category[] = [],\n existingExits: Exit[] = [],\n existingCases: Case[] = [],\n resultName: string = ''\n) => {\n const categories: Category[] = [];\n const exits: Exit[] = [];\n const cases: Case[] = [];\n\n // Create categories, exits, and cases for each selected group\n userGroups.forEach((group) => {\n // Try to find existing category by group name\n const existingCategory = existingCategories.find(\n (cat) => cat.name === group.name\n );\n const existingExit = existingCategory\n ? existingExits.find((exit) => exit.uuid === existingCategory.exit_uuid)\n : null;\n const existingCase = existingCases.find(\n (c) => c.arguments?.[0] === group.uuid\n );\n\n const exitUuid = existingExit?.uuid || generateUUID();\n const categoryUuid = existingCategory?.uuid || generateUUID();\n const caseUuid = existingCase?.uuid || generateUUID();\n\n categories.push({\n uuid: categoryUuid,\n name: group.name,\n exit_uuid: exitUuid\n });\n\n exits.push({\n uuid: exitUuid,\n destination_uuid: existingExit?.destination_uuid || null\n });\n\n cases.push({\n uuid: caseUuid,\n type: 'has_group',\n arguments: [group.uuid, group.name],\n category_uuid: categoryUuid\n });\n });\n\n // Add default \"Other\" category for contacts not in any selected group\n const existingOtherCategory = existingCategories.find(\n (cat) =>\n cat.name === 'Other' &&\n !userGroups.some((group) => group.name === cat.name)\n );\n const existingOtherExit = existingOtherCategory\n ? existingExits.find(\n (exit) => exit.uuid === existingOtherCategory.exit_uuid\n )\n : null;\n\n const otherExitUuid = existingOtherExit?.uuid || generateUUID();\n const otherCategoryUuid = existingOtherCategory?.uuid || generateUUID();\n\n categories.push({\n uuid: otherCategoryUuid,\n name: 'Other',\n exit_uuid: otherExitUuid\n });\n\n exits.push({\n uuid: otherExitUuid,\n destination_uuid: existingOtherExit?.destination_uuid || null\n });\n\n return {\n router: {\n type: 'switch' as const,\n cases: cases,\n categories: categories,\n default_category_uuid: otherCategoryUuid,\n operand: '@contact.groups',\n result_name: resultName\n },\n exits: exits\n };\n};\n\nexport const split_by_groups: NodeConfig = {\n type: 'split_by_groups',\n name: 'Split by Group',\n group: SPLIT_GROUPS.split,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n form: {\n groups: {\n type: 'select',\n label: 'Groups',\n helpText:\n 'Select the groups to split contacts by. Contacts will be routed based on their group membership.',\n required: true,\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 allowCreate: true,\n createArbitraryOption: (input: string, options: any[]) => {\n // Check if a group with this name already exists\n const existing = options.find(\n (option) =>\n option.name.toLowerCase().trim() === input.toLowerCase().trim()\n );\n if (!existing && input.trim()) {\n return {\n name: input.trim(),\n arbitrary: true\n };\n }\n return null;\n }\n },\n result_name: resultNameField\n },\n layout: ['groups', 'result_name'],\n validate: (formData: FormData) => {\n const errors: { [key: string]: string } = {};\n\n if (\n !formData.groups ||\n !Array.isArray(formData.groups) ||\n formData.groups.length === 0\n ) {\n errors.groups = 'At least one group is required';\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n toFormData: (node: Node) => {\n // Extract groups from the existing node structure\n const groups: { uuid: string; name: string }[] = [];\n\n if (node.router?.cases) {\n node.router.cases.forEach((c: Case) => {\n if (c.type === 'has_group' && c.arguments?.length >= 2) {\n groups.push({\n uuid: c.arguments[0],\n name: c.arguments[1]\n });\n }\n });\n }\n\n return {\n uuid: node.uuid,\n groups: groups,\n result_name: node.router?.result_name || ''\n };\n },\n fromFormData: (formData: FormData, originalNode: Node): Node => {\n // Get selected groups\n const selectedGroups = (formData.groups || [])\n .filter((group: any) => group?.uuid || group?.arbitrary)\n .map((group: any) => ({\n uuid: group.uuid || generateUUID(), // Generate UUID for arbitrary groups\n name: group.name\n }));\n\n // Create router and exits using existing data when possible\n const existingCategories = originalNode.router?.categories || [];\n const existingExits = originalNode.exits || [];\n const existingCases = originalNode.router?.cases || [];\n\n const { router, exits } = createGroupRouter(\n selectedGroups,\n existingCategories,\n existingExits,\n existingCases,\n formData.result_name || ''\n );\n\n // Return the complete node\n return {\n uuid: originalNode.uuid,\n actions: originalNode.actions || [],\n router: router,\n exits: exits\n };\n },\n router: {\n type: 'switch',\n operand: '@contact.groups'\n },\n\n // Localization support for categories\n localizable: 'categories',\n toLocalizationFormData: categoriesToLocalizationFormData,\n fromLocalizationFormData: localizationFormDataToCategories\n};\n"]}
@@ -1,7 +1,8 @@
1
- import { ACTION_GROUPS } from '../types';
1
+ import { ACTION_GROUPS, FlowTypes } from '../types';
2
2
  export const split_by_llm_categorize = {
3
3
  type: 'split_by_intent',
4
4
  name: 'Call classifier',
5
- group: ACTION_GROUPS.services
5
+ group: ACTION_GROUPS.services,
6
+ flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND]
6
7
  };
7
8
  //# sourceMappingURL=split_by_intent.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"split_by_intent.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_intent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,aAAa,EAAE,MAAM,UAAU,CAAC;AAErD,MAAM,CAAC,MAAM,uBAAuB,GAAe;IACjD,IAAI,EAAE,iBAAiB;IACvB,IAAI,EAAE,iBAAiB;IACvB,KAAK,EAAE,aAAa,CAAC,QAAQ;CAC9B,CAAC","sourcesContent":["import { NodeConfig, ACTION_GROUPS } from '../types';\n\nexport const split_by_llm_categorize: NodeConfig = {\n type: 'split_by_intent',\n name: 'Call classifier',\n group: ACTION_GROUPS.services\n};\n"]}
1
+ {"version":3,"file":"split_by_intent.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_intent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,aAAa,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAEhE,MAAM,CAAC,MAAM,uBAAuB,GAAe;IACjD,IAAI,EAAE,iBAAiB;IACvB,IAAI,EAAE,iBAAiB;IACvB,KAAK,EAAE,aAAa,CAAC,QAAQ;IAC7B,SAAS,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,UAAU,CAAC;CACtE,CAAC","sourcesContent":["import { NodeConfig, ACTION_GROUPS, FlowTypes } from '../types';\n\nexport const split_by_llm_categorize: NodeConfig = {\n type: 'split_by_intent',\n name: 'Call classifier',\n group: ACTION_GROUPS.services,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND]\n};\n"]}
@@ -1,10 +1,13 @@
1
- import { ACTION_GROUPS } from '../types';
1
+ import { ACTION_GROUPS, FlowTypes, Features } from '../types';
2
2
  import { generateUUID, createSuccessFailureRouter } from '../../utils';
3
3
  import { html } from 'lit';
4
+ import { categoriesToLocalizationFormData, localizationFormDataToCategories } from './shared';
4
5
  export const split_by_llm = {
5
6
  type: 'split_by_llm',
6
7
  name: 'Call AI',
7
8
  group: ACTION_GROUPS.services,
9
+ flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
10
+ features: [Features.AI],
8
11
  showAsAction: true,
9
12
  render: (node) => {
10
13
  var _a;
@@ -97,6 +100,10 @@ export const split_by_llm = {
97
100
  router: router,
98
101
  exits: exits
99
102
  };
100
- }
103
+ },
104
+ // Localization support for categories
105
+ localizable: 'categories',
106
+ toLocalizationFormData: categoriesToLocalizationFormData,
107
+ fromLocalizationFormData: localizationFormDataToCategories
101
108
  };
102
109
  //# sourceMappingURL=split_by_llm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"split_by_llm.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_llm.ts"],"names":[],"mappings":"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","sourcesContent":["import { ACTION_GROUPS, FormData, NodeConfig } from '../types';\nimport { CallLLM, Node } from '../../store/flow-definition';\nimport { generateUUID, createSuccessFailureRouter } from '../../utils';\nimport { html } from 'lit';\n\nexport const split_by_llm: NodeConfig = {\n type: 'split_by_llm',\n name: 'Call AI',\n group: ACTION_GROUPS.services,\n showAsAction: true,\n render: (node: Node) => {\n const callLlmAction = node.actions?.find(\n (action) => action.type === 'call_llm'\n ) as CallLLM;\n return html`\n <div\n class=\"body\"\n style=\"word-wrap: break-word; overflow-wrap: break-word; hyphens: auto; max-width: 180px; max-height: 6.2em; margin-bottom:10px; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 6; -webkit-box-orient: vertical;\"\n >\n ${callLlmAction?.instructions || 'Configure AI instructions'}\n </div>\n `;\n },\n\n form: {\n llm: {\n type: 'select',\n label: 'LLM',\n required: true,\n options: [],\n endpoint: '/test-assets/select/llms.json',\n searchable: true,\n valueKey: 'uuid',\n nameKey: 'name',\n placeholder: 'Select an LLM...'\n },\n input: {\n type: 'text',\n label: 'Input',\n helpText: 'The input the AI will process',\n required: true,\n evaluated: true,\n placeholder: '@input'\n },\n instructions: {\n type: 'textarea',\n label: 'Instructions',\n helpText:\n 'Tell the AI what to do with the input. The result can be referenced as **`@locals._llm_output`**',\n required: true,\n evaluated: true,\n placeholder: 'Enter instructions for the AI model...',\n minHeight: 130\n }\n },\n layout: ['llm', 'input', 'instructions'],\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 CallLLM;\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 instructions: callLlmAction?.instructions || ''\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 // 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\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 input: formData.input || '@input',\n instructions: formData.instructions || '',\n output_local: '_llm_output'\n };\n\n // Create categories and exits for Success and Failure\n const existingCategories = originalNode.router?.categories || [];\n const existingExits = originalNode.exits || [];\n const existingCases = originalNode.router?.cases || [];\n\n const { router, exits } = createSuccessFailureRouter(\n '@locals._llm_output',\n {\n type: 'has_text',\n arguments: []\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"]}
1
+ {"version":3,"file":"split_by_llm.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_llm.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ACTION_GROUPS,\n FormData,\n NodeConfig,\n FlowTypes,\n Features\n} from '../types';\nimport { CallLLM, Node } from '../../store/flow-definition';\nimport { generateUUID, createSuccessFailureRouter } from '../../utils';\nimport { html } from 'lit';\nimport {\n categoriesToLocalizationFormData,\n localizationFormDataToCategories\n} from './shared';\n\nexport const split_by_llm: NodeConfig = {\n type: 'split_by_llm',\n name: 'Call AI',\n group: ACTION_GROUPS.services,\n flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\n features: [Features.AI],\n showAsAction: true,\n render: (node: Node) => {\n const callLlmAction = node.actions?.find(\n (action) => action.type === 'call_llm'\n ) as CallLLM;\n return html`\n <div\n class=\"body\"\n style=\"word-wrap: break-word; overflow-wrap: break-word; hyphens: auto; max-width: 180px; max-height: 6.2em; margin-bottom:10px; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 6; -webkit-box-orient: vertical;\"\n >\n ${callLlmAction?.instructions || 'Configure AI instructions'}\n </div>\n `;\n },\n\n form: {\n llm: {\n type: 'select',\n label: 'LLM',\n required: true,\n options: [],\n endpoint: '/test-assets/select/llms.json',\n searchable: true,\n valueKey: 'uuid',\n nameKey: 'name',\n placeholder: 'Select an LLM...'\n },\n input: {\n type: 'text',\n label: 'Input',\n helpText: 'The input the AI will process',\n required: true,\n evaluated: true,\n placeholder: '@input'\n },\n instructions: {\n type: 'textarea',\n label: 'Instructions',\n helpText:\n 'Tell the AI what to do with the input. The result can be referenced as **`@locals._llm_output`**',\n required: true,\n evaluated: true,\n placeholder: 'Enter instructions for the AI model...',\n minHeight: 130\n }\n },\n layout: ['llm', 'input', 'instructions'],\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 CallLLM;\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 instructions: callLlmAction?.instructions || ''\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 // 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\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 input: formData.input || '@input',\n instructions: formData.instructions || '',\n output_local: '_llm_output'\n };\n\n // Create categories and exits for Success and Failure\n const existingCategories = originalNode.router?.categories || [];\n const existingExits = originalNode.exits || [];\n const existingCases = originalNode.router?.cases || [];\n\n const { router, exits } = createSuccessFailureRouter(\n '@locals._llm_output',\n {\n type: 'has_text',\n arguments: []\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,10 +1,13 @@
1
- import { ACTION_GROUPS } from '../types';
1
+ import { ACTION_GROUPS, FlowTypes, Features } from '../types';
2
2
  import { generateUUID, createMultiCategoryRouter } from '../../utils';
3
3
  import { html } from 'lit';
4
+ import { categoriesToLocalizationFormData, localizationFormDataToCategories } from './shared';
4
5
  export const split_by_llm_categorize = {
5
6
  type: 'split_by_llm_categorize',
6
7
  name: 'Split by AI',
7
8
  group: ACTION_GROUPS.services,
9
+ flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
10
+ features: [Features.AI],
8
11
  form: {
9
12
  llm: {
10
13
  type: 'select',
@@ -138,6 +141,10 @@ export const split_by_llm_categorize = {
138
141
  router: router,
139
142
  exits: exits
140
143
  };
141
- }
144
+ },
145
+ // Localization support for categories
146
+ localizable: 'categories',
147
+ toLocalizationFormData: categoriesToLocalizationFormData,
148
+ fromLocalizationFormData: localizationFormDataToCategories
142
149
  };
143
150
  //# sourceMappingURL=split_by_llm_categorize.js.map
@@ -1 +1 @@
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 } from '../types';\nimport { CallLLM, Node } from '../../store/flow-definition';\nimport { generateUUID, createMultiCategoryRouter } from '../../utils';\nimport { html } from 'lit';\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 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"]}
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 {\n FormData,\n NodeConfig,\n ACTION_GROUPS,\n FlowTypes,\n Features\n} 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: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],\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,5 +1,6 @@
1
- import { SPLIT_GROUPS } from '../types';
1
+ import { SPLIT_GROUPS, FlowTypes } from '../types';
2
2
  import { generateUUID } from '../../utils';
3
+ import { categoriesToLocalizationFormData, localizationFormDataToCategories } from './shared';
3
4
  // Helper function to create a random router with categories
4
5
  const createRandomRouter = (userCategories, existingCategories = [], existingExits = []) => {
5
6
  const categories = [];
@@ -35,6 +36,7 @@ export const split_by_random = {
35
36
  type: 'split_by_random',
36
37
  name: 'Random Split',
37
38
  group: SPLIT_GROUPS.split,
39
+ flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
38
40
  form: {
39
41
  categories: {
40
42
  type: 'array',
@@ -123,6 +125,10 @@ export const split_by_random = {
123
125
  },
124
126
  router: {
125
127
  type: 'random'
126
- }
128
+ },
129
+ // Localization support for categories
130
+ localizable: 'categories',
131
+ toLocalizationFormData: categoriesToLocalizationFormData,
132
+ fromLocalizationFormData: localizationFormDataToCategories
127
133
  };
128
134
  //# sourceMappingURL=split_by_random.js.map