@nyaruka/temba-components 0.139.0 → 0.140.0

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 (155) hide show
  1. package/.github/workflows/cla.yml +1 -1
  2. package/.github/workflows/copilot-setup-steps.yml +6 -1
  3. package/CHANGELOG.md +17 -0
  4. package/demo/data/flows/sample-flow.json +24 -0
  5. package/dist/temba-components.js +562 -296
  6. package/dist/temba-components.js.map +1 -1
  7. package/out-tsc/src/display/Chat.js +10 -7
  8. package/out-tsc/src/display/Chat.js.map +1 -1
  9. package/out-tsc/src/display/Dropdown.js +3 -1
  10. package/out-tsc/src/display/Dropdown.js.map +1 -1
  11. package/out-tsc/src/display/FloatingTab.js +3 -3
  12. package/out-tsc/src/display/FloatingTab.js.map +1 -1
  13. package/out-tsc/src/display/Thumbnail.js +163 -5
  14. package/out-tsc/src/display/Thumbnail.js.map +1 -1
  15. package/out-tsc/src/flow/CanvasNode.js +64 -22
  16. package/out-tsc/src/flow/CanvasNode.js.map +1 -1
  17. package/out-tsc/src/flow/Editor.js +142 -8
  18. package/out-tsc/src/flow/Editor.js.map +1 -1
  19. package/out-tsc/src/flow/NodeEditor.js +118 -10
  20. package/out-tsc/src/flow/NodeEditor.js.map +1 -1
  21. package/out-tsc/src/flow/StickyNote.js +13 -4
  22. package/out-tsc/src/flow/StickyNote.js.map +1 -1
  23. package/out-tsc/src/flow/actions/audio-player.js +112 -0
  24. package/out-tsc/src/flow/actions/audio-player.js.map +1 -0
  25. package/out-tsc/src/flow/actions/enter_flow.js +43 -0
  26. package/out-tsc/src/flow/actions/enter_flow.js.map +1 -0
  27. package/out-tsc/src/flow/actions/play_audio.js +57 -4
  28. package/out-tsc/src/flow/actions/play_audio.js.map +1 -1
  29. package/out-tsc/src/flow/actions/say_msg.js +86 -3
  30. package/out-tsc/src/flow/actions/say_msg.js.map +1 -1
  31. package/out-tsc/src/flow/config.js +11 -3
  32. package/out-tsc/src/flow/config.js.map +1 -1
  33. package/out-tsc/src/flow/nodes/shared-rules.js +1 -1
  34. package/out-tsc/src/flow/nodes/shared-rules.js.map +1 -1
  35. package/out-tsc/src/flow/nodes/terminal.js +7 -0
  36. package/out-tsc/src/flow/nodes/terminal.js.map +1 -0
  37. package/out-tsc/src/flow/nodes/wait_for_audio.js +77 -0
  38. package/out-tsc/src/flow/nodes/wait_for_audio.js.map +1 -0
  39. package/out-tsc/src/flow/nodes/wait_for_dial.js +151 -0
  40. package/out-tsc/src/flow/nodes/wait_for_dial.js.map +1 -0
  41. package/out-tsc/src/flow/nodes/wait_for_digits.js +61 -1
  42. package/out-tsc/src/flow/nodes/wait_for_digits.js.map +1 -1
  43. package/out-tsc/src/flow/nodes/wait_for_menu.js +173 -2
  44. package/out-tsc/src/flow/nodes/wait_for_menu.js.map +1 -1
  45. package/out-tsc/src/flow/operators.js +21 -5
  46. package/out-tsc/src/flow/operators.js.map +1 -1
  47. package/out-tsc/src/flow/types.js.map +1 -1
  48. package/out-tsc/src/flow/utils.js +79 -3
  49. package/out-tsc/src/flow/utils.js.map +1 -1
  50. package/out-tsc/src/form/ArrayEditor.js +4 -2
  51. package/out-tsc/src/form/ArrayEditor.js.map +1 -1
  52. package/out-tsc/src/form/FieldRenderer.js +49 -0
  53. package/out-tsc/src/form/FieldRenderer.js.map +1 -1
  54. package/out-tsc/src/interfaces.js +1 -0
  55. package/out-tsc/src/interfaces.js.map +1 -1
  56. package/out-tsc/src/layout/Dialog.js +52 -7
  57. package/out-tsc/src/layout/Dialog.js.map +1 -1
  58. package/out-tsc/src/live/TembaChart.js.map +1 -1
  59. package/out-tsc/src/simulator/Simulator.js +10 -4
  60. package/out-tsc/src/simulator/Simulator.js.map +1 -1
  61. package/out-tsc/src/store/AppState.js +89 -3
  62. package/out-tsc/src/store/AppState.js.map +1 -1
  63. package/out-tsc/test/actions/play_audio.test.js +118 -0
  64. package/out-tsc/test/actions/play_audio.test.js.map +1 -0
  65. package/out-tsc/test/actions/say_msg.test.js +158 -0
  66. package/out-tsc/test/actions/say_msg.test.js.map +1 -0
  67. package/out-tsc/test/nodes/wait_for_audio.test.js +156 -0
  68. package/out-tsc/test/nodes/wait_for_audio.test.js.map +1 -0
  69. package/out-tsc/test/nodes/wait_for_dial.test.js +336 -0
  70. package/out-tsc/test/nodes/wait_for_dial.test.js.map +1 -0
  71. package/out-tsc/test/nodes/wait_for_digits.test.js +198 -84
  72. package/out-tsc/test/nodes/wait_for_digits.test.js.map +1 -1
  73. package/out-tsc/test/nodes/wait_for_menu.test.js +340 -0
  74. package/out-tsc/test/nodes/wait_for_menu.test.js.map +1 -0
  75. package/out-tsc/test/temba-flow-collision.test.js +261 -6
  76. package/out-tsc/test/temba-flow-collision.test.js.map +1 -1
  77. package/out-tsc/test/temba-node-type-selector.test.js +6 -6
  78. package/out-tsc/test/temba-node-type-selector.test.js.map +1 -1
  79. package/package.json +1 -1
  80. package/screenshots/truth/actions/play_audio/editor/expression-url.png +0 -0
  81. package/screenshots/truth/actions/play_audio/editor/static-url.png +0 -0
  82. package/screenshots/truth/actions/play_audio/render/expression-url.png +0 -0
  83. package/screenshots/truth/actions/play_audio/render/static-url.png +0 -0
  84. package/screenshots/truth/actions/say_msg/editor/multiline-text.png +0 -0
  85. package/screenshots/truth/actions/say_msg/editor/simple-text.png +0 -0
  86. package/screenshots/truth/actions/say_msg/editor/text-with-audio-url.png +0 -0
  87. package/screenshots/truth/actions/say_msg/render/multiline-text.png +0 -0
  88. package/screenshots/truth/actions/say_msg/render/simple-text.png +0 -0
  89. package/screenshots/truth/actions/say_msg/render/text-with-audio-url.png +0 -0
  90. package/screenshots/truth/editor/router.png +0 -0
  91. package/screenshots/truth/editor/wait.png +0 -0
  92. package/screenshots/truth/nodes/wait_for_audio/editor/basic-audio-wait.png +0 -0
  93. package/screenshots/truth/nodes/wait_for_audio/render/basic-audio-wait.png +0 -0
  94. package/screenshots/truth/nodes/wait_for_dial/editor/basic-dial.png +0 -0
  95. package/screenshots/truth/nodes/wait_for_dial/editor/dial-with-limits.png +0 -0
  96. package/screenshots/truth/nodes/wait_for_dial/render/basic-dial.png +0 -0
  97. package/screenshots/truth/nodes/wait_for_dial/render/dial-with-limits.png +0 -0
  98. package/screenshots/truth/nodes/wait_for_digits/editor/basic-digits-wait.png +0 -0
  99. package/screenshots/truth/nodes/wait_for_digits/editor/digits-with-rules.png +0 -0
  100. package/screenshots/truth/nodes/wait_for_digits/render/basic-digits-wait.png +0 -0
  101. package/screenshots/truth/nodes/wait_for_digits/render/digits-with-rules.png +0 -0
  102. package/screenshots/truth/nodes/wait_for_menu/editor/menu-with-digits.png +0 -0
  103. package/screenshots/truth/nodes/wait_for_menu/render/menu-with-digits.png +0 -0
  104. package/screenshots/truth/nodes/wait_for_response/editor/basic-wait.png +0 -0
  105. package/screenshots/truth/nodes/wait_for_response/editor/custom-result-name.png +0 -0
  106. package/screenshots/truth/nodes/wait_for_response/editor/no-timeout.png +0 -0
  107. package/screenshots/truth/nodes/wait_for_response/editor/short-timeout.png +0 -0
  108. package/screenshots/truth/nodes/wait_for_response/render/basic-wait.png +0 -0
  109. package/screenshots/truth/nodes/wait_for_response/render/custom-result-name.png +0 -0
  110. package/screenshots/truth/nodes/wait_for_response/render/no-timeout.png +0 -0
  111. package/screenshots/truth/nodes/wait_for_response/render/short-timeout.png +0 -0
  112. package/src/display/Chat.ts +13 -7
  113. package/src/display/Dropdown.ts +3 -1
  114. package/src/display/FloatingTab.ts +3 -3
  115. package/src/display/Thumbnail.ts +162 -2
  116. package/src/flow/CanvasNode.ts +69 -23
  117. package/src/flow/Editor.ts +156 -13
  118. package/src/flow/NodeEditor.ts +137 -9
  119. package/src/flow/StickyNote.ts +14 -4
  120. package/src/flow/actions/audio-player.ts +127 -0
  121. package/src/flow/actions/enter_flow.ts +44 -0
  122. package/src/flow/actions/play_audio.ts +64 -5
  123. package/src/flow/actions/say_msg.ts +94 -4
  124. package/src/flow/config.ts +11 -3
  125. package/src/flow/nodes/shared-rules.ts +1 -1
  126. package/src/flow/nodes/terminal.ts +9 -0
  127. package/src/flow/nodes/wait_for_audio.ts +88 -0
  128. package/src/flow/nodes/wait_for_dial.ts +176 -0
  129. package/src/flow/nodes/wait_for_digits.ts +86 -2
  130. package/src/flow/nodes/wait_for_menu.ts +209 -3
  131. package/src/flow/operators.ts +23 -5
  132. package/src/flow/types.ts +23 -1
  133. package/src/flow/utils.ts +82 -3
  134. package/src/form/ArrayEditor.ts +4 -2
  135. package/src/form/FieldRenderer.ts +64 -1
  136. package/src/interfaces.ts +2 -1
  137. package/src/layout/Dialog.ts +53 -7
  138. package/src/live/TembaChart.ts +1 -1
  139. package/src/simulator/Simulator.ts +13 -4
  140. package/src/store/AppState.ts +105 -1
  141. package/src/store/flow-definition.d.ts +2 -0
  142. package/test/actions/play_audio.test.ts +155 -0
  143. package/test/actions/say_msg.test.ts +196 -0
  144. package/test/nodes/wait_for_audio.test.ts +182 -0
  145. package/test/nodes/wait_for_dial.test.ts +382 -0
  146. package/test/nodes/wait_for_digits.test.ts +233 -109
  147. package/test/nodes/wait_for_menu.test.ts +383 -0
  148. package/test/temba-flow-collision.test.ts +286 -6
  149. package/test/temba-node-type-selector.test.ts +6 -6
  150. package/screenshots/truth/nodes/wait_for_digits/editor/phone-number-collection.png +0 -0
  151. package/screenshots/truth/nodes/wait_for_digits/editor/single-digit-with-timeout.png +0 -0
  152. package/screenshots/truth/nodes/wait_for_digits/editor/verification-code.png +0 -0
  153. package/screenshots/truth/nodes/wait_for_digits/render/phone-number-collection.png +0 -0
  154. package/screenshots/truth/nodes/wait_for_digits/render/single-digit-with-timeout.png +0 -0
  155. package/screenshots/truth/nodes/wait_for_digits/render/verification-code.png +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"shared-rules.js","sourceRoot":"","sources":["../../../../src/flow/nodes/shared-rules.ts"],"names":[],"mappings":"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","sourcesContent":["import { getOperatorConfig } from '../operators';\nimport { generateDefaultCategoryName } from '../../utils';\nimport { FormData } from '../types';\n\n/**\n * Shared helper function to get operator value from various formats.\n * Handles string, object, and array formats that can come from the form system.\n */\nexport const getOperatorValue = (operator: any): string => {\n if (typeof operator === 'string') {\n return operator.trim();\n } else if (Array.isArray(operator) && operator.length > 0) {\n const firstOperator = operator[0];\n if (\n firstOperator &&\n typeof firstOperator === 'object' &&\n firstOperator.value\n ) {\n return firstOperator.value.trim();\n }\n } else if (operator && typeof operator === 'object' && operator.value) {\n return operator.value.trim();\n }\n return '';\n};\n\n/**\n * Shared isEmptyItem function for rules array.\n * Determines if a rule item is considered empty and should be filtered out.\n */\nexport const isEmptyRuleItem = (item: any): boolean => {\n // Check if operator and category are provided\n const operatorValue = getOperatorValue(item.operator);\n if (!operatorValue || !item.category || item.category.trim() === '') {\n return true;\n }\n\n // Check if value is required based on operator configuration\n const operatorConfig = getOperatorConfig(operatorValue);\n if (operatorConfig && operatorConfig.operands === 1) {\n return !item.value1 || item.value1.trim() === '';\n } else if (operatorConfig && operatorConfig.operands === 2) {\n return (\n !item.value1 ||\n item.value1.trim() === '' ||\n !item.value2 ||\n item.value2.trim() === ''\n );\n }\n\n return false;\n};\n\n/**\n * Shared onItemChange function for rules array.\n * Handles auto-updating category names based on operator and value changes.\n */\nexport const createRuleItemChangeHandler = () => {\n return (itemIndex: number, field: string, value: any, allItems: any[]) => {\n const updatedItems = [...allItems];\n const item = { ...updatedItems[itemIndex] };\n\n // Update the changed field\n item[field] = value;\n\n // Get operator values (before and after the change)\n const oldItem = allItems[itemIndex] || {};\n const oldOperatorValue =\n field === 'operator'\n ? getOperatorValue(oldItem.operator)\n : getOperatorValue(item.operator);\n const newOperatorValue = getOperatorValue(item.operator);\n\n // Calculate what the default category name should be before the change\n const oldDefaultCategory = generateDefaultCategoryName(\n oldOperatorValue,\n getOperatorConfig,\n field === 'value1' ? oldItem.value1 : item.value1,\n field === 'value2' ? oldItem.value2 : item.value2\n );\n\n // Calculate what the new default category name should be after the change\n const newDefaultCategory = generateDefaultCategoryName(\n newOperatorValue,\n getOperatorConfig,\n item.value1,\n item.value2\n );\n\n // Determine if we should auto-update the category\n const shouldUpdateCategory =\n !item.category ||\n item.category.trim() === '' ||\n item.category === oldDefaultCategory;\n\n // Auto-populate or update category if conditions are met\n if (shouldUpdateCategory && newDefaultCategory) {\n item.category = newDefaultCategory;\n }\n\n updatedItems[itemIndex] = item;\n return updatedItems;\n };\n};\n\n/**\n * Shared visibility condition for value1 field.\n */\nexport const value1VisibilityCondition = (formData: Record<string, any>) => {\n const operatorValue = getOperatorValue(formData.operator);\n const operatorConfig = getOperatorConfig(operatorValue);\n return operatorConfig ? operatorConfig.operands >= 1 : true;\n};\n\n/**\n * Shared visibility condition for value2 field.\n */\nexport const value2VisibilityCondition = (formData: Record<string, any>) => {\n const operatorValue = getOperatorValue(formData.operator);\n const operatorConfig = getOperatorConfig(operatorValue);\n return operatorConfig ? operatorConfig.operands === 2 : false;\n};\n\n/**\n * Shared item configuration for rules array.\n * This defines the operator, value1, value2, and category fields.\n */\nexport const createRulesItemConfig = () => ({\n operator: {\n type: 'select' as const,\n required: true,\n multi: false,\n options: [], // Will be set by the caller\n flavor: 'xsmall' as const,\n width: '200px'\n },\n value1: {\n type: 'text' as const,\n flavor: 'xsmall' as const,\n conditions: {\n visible: value1VisibilityCondition\n }\n },\n value2: {\n type: 'text' as const,\n flavor: 'xsmall' as const,\n conditions: {\n visible: value2VisibilityCondition\n }\n },\n category: {\n type: 'text' as const,\n placeholder: 'Category',\n required: true,\n maxWidth: '120px',\n flavor: 'xsmall' as const\n }\n});\n\n/**\n * Shared function to extract rules from form data.\n * Filters and transforms form rules into the format expected by createRulesRouter.\n */\nexport const extractUserRules = (formData: FormData) => {\n return (formData.rules || [])\n .filter((rule: any) => {\n const operatorValue = getOperatorValue(rule?.operator);\n if (\n !operatorValue ||\n !rule?.category ||\n operatorValue === '' ||\n rule.category.trim() === ''\n ) {\n return false;\n }\n\n const operatorConfig = getOperatorConfig(operatorValue);\n if (operatorConfig && operatorConfig.operands === 1) {\n return rule?.value1 && rule.value1.trim() !== '';\n } else if (operatorConfig && operatorConfig.operands === 2) {\n return (\n rule?.value1 &&\n rule.value1.trim() !== '' &&\n rule?.value2 &&\n rule.value2.trim() !== ''\n );\n }\n\n return true;\n })\n .map((rule: any) => {\n const operatorValue = getOperatorValue(rule.operator);\n const operatorConfig = getOperatorConfig(operatorValue);\n\n let value = '';\n\n if (operatorConfig && operatorConfig.operands === 1) {\n value = rule.value1 ? rule.value1.trim() : '';\n } else if (operatorConfig && operatorConfig.operands === 2) {\n const val1 = rule.value1 ? rule.value1.trim() : '';\n const val2 = rule.value2 ? rule.value2.trim() : '';\n value = `${val1} ${val2}`.trim();\n } else {\n value = '';\n }\n\n return {\n operator: operatorValue,\n value: value,\n category: rule.category.trim()\n };\n });\n};\n\n/**\n * Shared function to transform router cases to form rules.\n * Converts node router cases back into the form data structure.\n */\nexport const casesToFormRules = (node: any) => {\n const rules = [];\n if (node.router?.cases && node.router?.categories) {\n node.router.cases.forEach((case_: any) => {\n // Find the category for this case\n const category = node.router!.categories.find(\n (cat: any) => cat.uuid === case_.category_uuid\n );\n\n // Skip system categories\n if (category && !isSystemCategory(category.name)) {\n // Handle different operator types\n const operatorConfig = getOperatorConfig(case_.type);\n const operatorDisplayName = operatorConfig\n ? operatorConfig.name\n : case_.type;\n let value1 = '';\n let value2 = '';\n\n if (operatorConfig && operatorConfig.operands === 0) {\n value1 = '';\n value2 = '';\n } else if (operatorConfig && operatorConfig.operands === 1) {\n value1 = case_.arguments.join(' ');\n value2 = '';\n } else if (operatorConfig && operatorConfig.operands === 2) {\n value1 = case_.arguments[0] || '';\n value2 = case_.arguments[1] || '';\n } else {\n value1 = case_.arguments.join(' ');\n value2 = '';\n }\n\n rules.push({\n operator: { value: case_.type, name: operatorDisplayName },\n value1: value1,\n value2: value2,\n category: category.name\n });\n }\n });\n }\n return rules;\n};\n\n/**\n * Helper to check if a category is a system category\n */\nfunction isSystemCategory(categoryName: string): boolean {\n return ['No Response', 'Other', 'All Responses', 'Timeout'].includes(\n categoryName\n );\n}\n\n/**\n * Creates a complete rules array configuration for forms.\n * This is the shared configuration used by both wait_for_response and split_by_expression.\n *\n * @param operatorOptions - The operator options to use (from operatorsToSelectOptions)\n * @param helpText - The help text to display for the rules array\n * @returns A complete array field configuration object\n */\nexport const createRulesArrayConfig = (\n operatorOptions: any[],\n helpText: string = 'Define rules to categorize responses'\n) => ({\n type: 'array' as const,\n helpText,\n itemLabel: 'Rule',\n minItems: 0,\n maxItems: 100,\n sortable: true,\n maintainEmptyItem: true,\n isEmptyItem: isEmptyRuleItem,\n onItemChange: createRuleItemChangeHandler(),\n itemConfig: {\n ...createRulesItemConfig(),\n operator: {\n ...createRulesItemConfig().operator,\n options: operatorOptions\n }\n }\n});\n"]}
1
+ {"version":3,"file":"shared-rules.js","sourceRoot":"","sources":["../../../../src/flow/nodes/shared-rules.ts"],"names":[],"mappings":"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","sourcesContent":["import { getOperatorConfig } from '../operators';\nimport { generateDefaultCategoryName } from '../../utils';\nimport { FormData } from '../types';\n\n/**\n * Shared helper function to get operator value from various formats.\n * Handles string, object, and array formats that can come from the form system.\n */\nexport const getOperatorValue = (operator: any): string => {\n if (typeof operator === 'string') {\n return operator.trim();\n } else if (Array.isArray(operator) && operator.length > 0) {\n const firstOperator = operator[0];\n if (\n firstOperator &&\n typeof firstOperator === 'object' &&\n firstOperator.value\n ) {\n return firstOperator.value.trim();\n }\n } else if (operator && typeof operator === 'object' && operator.value) {\n return operator.value.trim();\n }\n return '';\n};\n\n/**\n * Shared isEmptyItem function for rules array.\n * Determines if a rule item is considered empty and should be filtered out.\n */\nexport const isEmptyRuleItem = (item: any): boolean => {\n // Check if operator and category are provided\n const operatorValue = getOperatorValue(item.operator);\n if (!operatorValue || !item.category || item.category.trim() === '') {\n return true;\n }\n\n // Check if value is required based on operator configuration\n const operatorConfig = getOperatorConfig(operatorValue);\n if (operatorConfig && operatorConfig.operands === 1) {\n return !item.value1 || item.value1.trim() === '';\n } else if (operatorConfig && operatorConfig.operands === 2) {\n return (\n !item.value1 ||\n item.value1.trim() === '' ||\n !item.value2 ||\n item.value2.trim() === ''\n );\n }\n\n return false;\n};\n\n/**\n * Shared onItemChange function for rules array.\n * Handles auto-updating category names based on operator and value changes.\n */\nexport const createRuleItemChangeHandler = () => {\n return (itemIndex: number, field: string, value: any, allItems: any[]) => {\n const updatedItems = [...allItems];\n const item = { ...updatedItems[itemIndex] };\n\n // Update the changed field\n item[field] = value;\n\n // Get operator values (before and after the change)\n const oldItem = allItems[itemIndex] || {};\n const oldOperatorValue =\n field === 'operator'\n ? getOperatorValue(oldItem.operator)\n : getOperatorValue(item.operator);\n const newOperatorValue = getOperatorValue(item.operator);\n\n // Calculate what the default category name should be before the change\n const oldDefaultCategory = generateDefaultCategoryName(\n oldOperatorValue,\n getOperatorConfig,\n field === 'value1' ? oldItem.value1 : item.value1,\n field === 'value2' ? oldItem.value2 : item.value2\n );\n\n // Calculate what the new default category name should be after the change\n const newDefaultCategory = generateDefaultCategoryName(\n newOperatorValue,\n getOperatorConfig,\n item.value1,\n item.value2\n );\n\n // Determine if we should auto-update the category\n const shouldUpdateCategory =\n !item.category ||\n item.category.trim() === '' ||\n item.category === oldDefaultCategory;\n\n // Auto-populate or update category if conditions are met\n if (shouldUpdateCategory && newDefaultCategory) {\n item.category = newDefaultCategory;\n }\n\n updatedItems[itemIndex] = item;\n return updatedItems;\n };\n};\n\n/**\n * Shared visibility condition for value1 field.\n */\nexport const value1VisibilityCondition = (formData: Record<string, any>) => {\n const operatorValue = getOperatorValue(formData.operator);\n const operatorConfig = getOperatorConfig(operatorValue);\n return operatorConfig ? operatorConfig.operands >= 1 : true;\n};\n\n/**\n * Shared visibility condition for value2 field.\n */\nexport const value2VisibilityCondition = (formData: Record<string, any>) => {\n const operatorValue = getOperatorValue(formData.operator);\n const operatorConfig = getOperatorConfig(operatorValue);\n return operatorConfig ? operatorConfig.operands === 2 : false;\n};\n\n/**\n * Shared item configuration for rules array.\n * This defines the operator, value1, value2, and category fields.\n */\nexport const createRulesItemConfig = () => ({\n operator: {\n type: 'select' as const,\n required: true,\n multi: false,\n options: [], // Will be set by the caller\n flavor: 'xsmall' as const,\n width: '220px'\n },\n value1: {\n type: 'text' as const,\n flavor: 'xsmall' as const,\n conditions: {\n visible: value1VisibilityCondition\n }\n },\n value2: {\n type: 'text' as const,\n flavor: 'xsmall' as const,\n conditions: {\n visible: value2VisibilityCondition\n }\n },\n category: {\n type: 'text' as const,\n placeholder: 'Category',\n required: true,\n maxWidth: '120px',\n flavor: 'xsmall' as const\n }\n});\n\n/**\n * Shared function to extract rules from form data.\n * Filters and transforms form rules into the format expected by createRulesRouter.\n */\nexport const extractUserRules = (formData: FormData) => {\n return (formData.rules || [])\n .filter((rule: any) => {\n const operatorValue = getOperatorValue(rule?.operator);\n if (\n !operatorValue ||\n !rule?.category ||\n operatorValue === '' ||\n rule.category.trim() === ''\n ) {\n return false;\n }\n\n const operatorConfig = getOperatorConfig(operatorValue);\n if (operatorConfig && operatorConfig.operands === 1) {\n return rule?.value1 && rule.value1.trim() !== '';\n } else if (operatorConfig && operatorConfig.operands === 2) {\n return (\n rule?.value1 &&\n rule.value1.trim() !== '' &&\n rule?.value2 &&\n rule.value2.trim() !== ''\n );\n }\n\n return true;\n })\n .map((rule: any) => {\n const operatorValue = getOperatorValue(rule.operator);\n const operatorConfig = getOperatorConfig(operatorValue);\n\n let value = '';\n\n if (operatorConfig && operatorConfig.operands === 1) {\n value = rule.value1 ? rule.value1.trim() : '';\n } else if (operatorConfig && operatorConfig.operands === 2) {\n const val1 = rule.value1 ? rule.value1.trim() : '';\n const val2 = rule.value2 ? rule.value2.trim() : '';\n value = `${val1} ${val2}`.trim();\n } else {\n value = '';\n }\n\n return {\n operator: operatorValue,\n value: value,\n category: rule.category.trim()\n };\n });\n};\n\n/**\n * Shared function to transform router cases to form rules.\n * Converts node router cases back into the form data structure.\n */\nexport const casesToFormRules = (node: any) => {\n const rules = [];\n if (node.router?.cases && node.router?.categories) {\n node.router.cases.forEach((case_: any) => {\n // Find the category for this case\n const category = node.router!.categories.find(\n (cat: any) => cat.uuid === case_.category_uuid\n );\n\n // Skip system categories\n if (category && !isSystemCategory(category.name)) {\n // Handle different operator types\n const operatorConfig = getOperatorConfig(case_.type);\n const operatorDisplayName = operatorConfig\n ? operatorConfig.name\n : case_.type;\n let value1 = '';\n let value2 = '';\n\n if (operatorConfig && operatorConfig.operands === 0) {\n value1 = '';\n value2 = '';\n } else if (operatorConfig && operatorConfig.operands === 1) {\n value1 = case_.arguments.join(' ');\n value2 = '';\n } else if (operatorConfig && operatorConfig.operands === 2) {\n value1 = case_.arguments[0] || '';\n value2 = case_.arguments[1] || '';\n } else {\n value1 = case_.arguments.join(' ');\n value2 = '';\n }\n\n rules.push({\n operator: { value: case_.type, name: operatorDisplayName },\n value1: value1,\n value2: value2,\n category: category.name\n });\n }\n });\n }\n return rules;\n};\n\n/**\n * Helper to check if a category is a system category\n */\nfunction isSystemCategory(categoryName: string): boolean {\n return ['No Response', 'Other', 'All Responses', 'Timeout'].includes(\n categoryName\n );\n}\n\n/**\n * Creates a complete rules array configuration for forms.\n * This is the shared configuration used by both wait_for_response and split_by_expression.\n *\n * @param operatorOptions - The operator options to use (from operatorsToSelectOptions)\n * @param helpText - The help text to display for the rules array\n * @returns A complete array field configuration object\n */\nexport const createRulesArrayConfig = (\n operatorOptions: any[],\n helpText: string = 'Define rules to categorize responses'\n) => ({\n type: 'array' as const,\n helpText,\n itemLabel: 'Rule',\n minItems: 0,\n maxItems: 100,\n sortable: true,\n maintainEmptyItem: true,\n isEmptyItem: isEmptyRuleItem,\n onItemChange: createRuleItemChangeHandler(),\n itemConfig: {\n ...createRulesItemConfig(),\n operator: {\n ...createRulesItemConfig().operator,\n options: operatorOptions\n }\n }\n});\n"]}
@@ -0,0 +1,7 @@
1
+ // Temporary: Legacy support for terminal nodes (nodes with a terminal action
2
+ // like enter_flow with terminal: true). This node type and its reclassification
3
+ // logic in AppState.ts can be removed once we stop supporting terminal nodes.
4
+ export const terminal = {
5
+ type: 'terminal'
6
+ };
7
+ //# sourceMappingURL=terminal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal.js","sourceRoot":"","sources":["../../../../src/flow/nodes/terminal.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,gFAAgF;AAChF,8EAA8E;AAI9E,MAAM,CAAC,MAAM,QAAQ,GAAe;IAClC,IAAI,EAAE,UAAU;CACjB,CAAC","sourcesContent":["// Temporary: Legacy support for terminal nodes (nodes with a terminal action\n// like enter_flow with terminal: true). This node type and its reclassification\n// logic in AppState.ts can be removed once we stop supporting terminal nodes.\n\nimport { NodeConfig } from '../types';\n\nexport const terminal: NodeConfig = {\n type: 'terminal'\n};\n"]}
@@ -0,0 +1,77 @@
1
+ import { SPLIT_GROUPS, FlowTypes } from '../types';
2
+ import { generateUUID } from '../../utils';
3
+ import { categoriesToLocalizationFormData, localizationFormDataToCategories } from './shared';
4
+ export const wait_for_audio = {
5
+ type: 'wait_for_audio',
6
+ name: 'Make Recording',
7
+ group: SPLIT_GROUPS.wait,
8
+ flowTypes: [FlowTypes.VOICE],
9
+ form: {
10
+ result_name: {
11
+ type: 'text',
12
+ label: 'Result Name',
13
+ required: false,
14
+ placeholder: '(optional)',
15
+ helpText: 'The name to use to reference this result in the flow'
16
+ }
17
+ },
18
+ layout: ['result_name'],
19
+ toFormData: (node) => {
20
+ var _a;
21
+ return {
22
+ uuid: node.uuid,
23
+ result_name: ((_a = node.router) === null || _a === void 0 ? void 0 : _a.result_name) || ''
24
+ };
25
+ },
26
+ fromFormData: (formData, originalNode) => {
27
+ var _a;
28
+ // Preserve or create "All Responses" category
29
+ const existingCategories = ((_a = originalNode.router) === null || _a === void 0 ? void 0 : _a.categories) || [];
30
+ const existingExits = originalNode.exits || [];
31
+ let allResponsesCategory = existingCategories.find((cat) => cat.name === 'All Responses');
32
+ let allResponsesExit;
33
+ if (allResponsesCategory) {
34
+ allResponsesExit = existingExits.find((exit) => exit.uuid === allResponsesCategory.exit_uuid) || {
35
+ uuid: allResponsesCategory.exit_uuid,
36
+ destination_uuid: null
37
+ };
38
+ }
39
+ else {
40
+ const exitUuid = generateUUID();
41
+ allResponsesCategory = {
42
+ uuid: generateUUID(),
43
+ name: 'All Responses',
44
+ exit_uuid: exitUuid
45
+ };
46
+ allResponsesExit = {
47
+ uuid: exitUuid,
48
+ destination_uuid: null
49
+ };
50
+ }
51
+ const router = {
52
+ type: 'switch',
53
+ operand: '@input',
54
+ default_category_uuid: allResponsesCategory.uuid,
55
+ cases: [],
56
+ categories: [allResponsesCategory],
57
+ wait: {
58
+ type: 'msg',
59
+ hint: {
60
+ type: 'audio'
61
+ }
62
+ }
63
+ };
64
+ if (formData.result_name && formData.result_name.trim() !== '') {
65
+ router.result_name = formData.result_name.trim();
66
+ }
67
+ return {
68
+ ...originalNode,
69
+ router,
70
+ exits: [allResponsesExit]
71
+ };
72
+ },
73
+ localizable: 'categories',
74
+ toLocalizationFormData: categoriesToLocalizationFormData,
75
+ fromLocalizationFormData: localizationFormDataToCategories
76
+ };
77
+ //# sourceMappingURL=wait_for_audio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wait_for_audio.js","sourceRoot":"","sources":["../../../../src/flow/nodes/wait_for_audio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAwB,SAAS,EAAE,MAAM,UAAU,CAAC;AAEzE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,gCAAgC,EAChC,gCAAgC,EACjC,MAAM,UAAU,CAAC;AAElB,MAAM,CAAC,MAAM,cAAc,GAAe;IACxC,IAAI,EAAE,gBAAgB;IACtB,IAAI,EAAE,gBAAgB;IACtB,KAAK,EAAE,YAAY,CAAC,IAAI;IACxB,SAAS,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC;IAC5B,IAAI,EAAE;QACJ,WAAW,EAAE;YACX,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,aAAa;YACpB,QAAQ,EAAE,KAAK;YACf,WAAW,EAAE,YAAY;YACzB,QAAQ,EAAE,sDAAsD;SACjE;KACF;IACD,MAAM,EAAE,CAAC,aAAa,CAAC;IACvB,UAAU,EAAE,CAAC,IAAU,EAAE,EAAE;;QACzB,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,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,8CAA8C;QAC9C,MAAM,kBAAkB,GAAG,CAAA,MAAA,YAAY,CAAC,MAAM,0CAAE,UAAU,KAAI,EAAE,CAAC;QACjE,MAAM,aAAa,GAAG,YAAY,CAAC,KAAK,IAAI,EAAE,CAAC;QAE/C,IAAI,oBAAoB,GAAG,kBAAkB,CAAC,IAAI,CAChD,CAAC,GAAa,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,eAAe,CAChD,CAAC;QAEF,IAAI,gBAAsB,CAAC;QAE3B,IAAI,oBAAoB,EAAE,CAAC;YACzB,gBAAgB,GAAG,aAAa,CAAC,IAAI,CACnC,CAAC,IAAU,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,oBAAqB,CAAC,SAAS,CAC9D,IAAI;gBACH,IAAI,EAAE,oBAAoB,CAAC,SAAS;gBACpC,gBAAgB,EAAE,IAAI;aACvB,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;YAChC,oBAAoB,GAAG;gBACrB,IAAI,EAAE,YAAY,EAAE;gBACpB,IAAI,EAAE,eAAe;gBACrB,SAAS,EAAE,QAAQ;aACpB,CAAC;YACF,gBAAgB,GAAG;gBACjB,IAAI,EAAE,QAAQ;gBACd,gBAAgB,EAAE,IAAI;aACvB,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAQ;YAClB,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,QAAQ;YACjB,qBAAqB,EAAE,oBAAoB,CAAC,IAAI;YAChD,KAAK,EAAE,EAAE;YACT,UAAU,EAAE,CAAC,oBAAoB,CAAC;YAClC,IAAI,EAAE;gBACJ,IAAI,EAAE,KAAK;gBACX,IAAI,EAAE;oBACJ,IAAI,EAAE,OAAO;iBACd;aACF;SACF,CAAC;QAEF,IAAI,QAAQ,CAAC,WAAW,IAAI,QAAQ,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAC/D,MAAM,CAAC,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;QACnD,CAAC;QAED,OAAO;YACL,GAAG,YAAY;YACf,MAAM;YACN,KAAK,EAAE,CAAC,gBAAgB,CAAC;SAC1B,CAAC;IACJ,CAAC;IACD,WAAW,EAAE,YAAY;IACzB,sBAAsB,EAAE,gCAAgC;IACxD,wBAAwB,EAAE,gCAAgC;CAC3D,CAAC","sourcesContent":["import { SPLIT_GROUPS, FormData, NodeConfig, FlowTypes } from '../types';\nimport { Node, Category, Exit } from '../../store/flow-definition';\nimport { generateUUID } from '../../utils';\nimport {\n categoriesToLocalizationFormData,\n localizationFormDataToCategories\n} from './shared';\n\nexport const wait_for_audio: NodeConfig = {\n type: 'wait_for_audio',\n name: 'Make Recording',\n group: SPLIT_GROUPS.wait,\n flowTypes: [FlowTypes.VOICE],\n form: {\n result_name: {\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 }\n },\n layout: ['result_name'],\n toFormData: (node: Node) => {\n return {\n uuid: node.uuid,\n result_name: node.router?.result_name || ''\n };\n },\n fromFormData: (formData: FormData, originalNode: Node): Node => {\n // Preserve or create \"All Responses\" category\n const existingCategories = originalNode.router?.categories || [];\n const existingExits = originalNode.exits || [];\n\n let allResponsesCategory = existingCategories.find(\n (cat: Category) => cat.name === 'All Responses'\n );\n\n let allResponsesExit: Exit;\n\n if (allResponsesCategory) {\n allResponsesExit = existingExits.find(\n (exit: Exit) => exit.uuid === allResponsesCategory!.exit_uuid\n ) || {\n uuid: allResponsesCategory.exit_uuid,\n destination_uuid: null\n };\n } else {\n const exitUuid = generateUUID();\n allResponsesCategory = {\n uuid: generateUUID(),\n name: 'All Responses',\n exit_uuid: exitUuid\n };\n allResponsesExit = {\n uuid: exitUuid,\n destination_uuid: null\n };\n }\n\n const router: any = {\n type: 'switch',\n operand: '@input',\n default_category_uuid: allResponsesCategory.uuid,\n cases: [],\n categories: [allResponsesCategory],\n wait: {\n type: 'msg',\n hint: {\n type: 'audio'\n }\n }\n };\n\n if (formData.result_name && formData.result_name.trim() !== '') {\n router.result_name = formData.result_name.trim();\n }\n\n return {\n ...originalNode,\n router,\n exits: [allResponsesExit]\n };\n },\n localizable: 'categories',\n toLocalizationFormData: categoriesToLocalizationFormData,\n fromLocalizationFormData: localizationFormDataToCategories\n};\n"]}
@@ -0,0 +1,151 @@
1
+ import { SPLIT_GROUPS, FlowTypes } from '../types';
2
+ import { generateUUID } from '../../utils';
3
+ import { resultNameField, categoriesToLocalizationFormData, localizationFormDataToCategories } from './shared';
4
+ const DIAL_CATEGORIES = ['Answered', 'No Answer', 'Busy', 'Failed'];
5
+ const DIAL_CASES = [
6
+ { type: 'has_only_text', arguments: ['answered'], categoryName: 'Answered' },
7
+ {
8
+ type: 'has_only_text',
9
+ arguments: ['no_answer'],
10
+ categoryName: 'No Answer'
11
+ },
12
+ { type: 'has_only_text', arguments: ['busy'], categoryName: 'Busy' }
13
+ ];
14
+ export const wait_for_dial = {
15
+ type: 'wait_for_dial',
16
+ name: 'Redirect Call',
17
+ group: SPLIT_GROUPS.wait,
18
+ flowTypes: [FlowTypes.VOICE],
19
+ router: {
20
+ type: 'switch',
21
+ defaultCategory: 'Failed',
22
+ rules: DIAL_CASES.map((c) => ({
23
+ type: c.type,
24
+ arguments: c.arguments,
25
+ categoryName: c.categoryName
26
+ }))
27
+ },
28
+ form: {
29
+ phone: {
30
+ type: 'text',
31
+ label: 'Phone Number',
32
+ required: true,
33
+ evaluated: true,
34
+ placeholder: 'Phone number or expression'
35
+ },
36
+ dial_limit_seconds: {
37
+ type: 'text',
38
+ label: 'Dial Limit (seconds)',
39
+ required: false,
40
+ placeholder: '60'
41
+ },
42
+ call_limit_seconds: {
43
+ type: 'text',
44
+ label: 'Call Limit (seconds)',
45
+ required: false,
46
+ placeholder: '7200'
47
+ },
48
+ result_name: resultNameField
49
+ },
50
+ layout: [
51
+ 'phone',
52
+ {
53
+ type: 'row',
54
+ items: ['dial_limit_seconds', 'call_limit_seconds']
55
+ },
56
+ 'result_name'
57
+ ],
58
+ toFormData: (node) => {
59
+ var _a, _b;
60
+ const wait = (_a = node.router) === null || _a === void 0 ? void 0 : _a.wait;
61
+ return {
62
+ uuid: node.uuid,
63
+ phone: (wait === null || wait === void 0 ? void 0 : wait.phone) || '',
64
+ dial_limit_seconds: (wait === null || wait === void 0 ? void 0 : wait.dial_limit_seconds)
65
+ ? String(wait.dial_limit_seconds)
66
+ : '',
67
+ call_limit_seconds: (wait === null || wait === void 0 ? void 0 : wait.call_limit_seconds)
68
+ ? String(wait.call_limit_seconds)
69
+ : '',
70
+ result_name: ((_b = node.router) === null || _b === void 0 ? void 0 : _b.result_name) || ''
71
+ };
72
+ },
73
+ fromFormData: (formData, originalNode) => {
74
+ var _a, _b;
75
+ const existingCategories = ((_a = originalNode.router) === null || _a === void 0 ? void 0 : _a.categories) || [];
76
+ const existingExits = originalNode.exits || [];
77
+ const existingCases = ((_b = originalNode.router) === null || _b === void 0 ? void 0 : _b.cases) || [];
78
+ const categories = [];
79
+ const exits = [];
80
+ const cases = [];
81
+ // Build categories and cases for each dial outcome
82
+ for (const catName of DIAL_CATEGORIES) {
83
+ const existing = existingCategories.find((c) => c.name === catName);
84
+ if (existing) {
85
+ categories.push(existing);
86
+ const existingExit = existingExits.find((e) => e.uuid === existing.exit_uuid);
87
+ exits.push(existingExit || {
88
+ uuid: existing.exit_uuid,
89
+ destination_uuid: null
90
+ });
91
+ }
92
+ else {
93
+ const exitUuid = generateUUID();
94
+ categories.push({
95
+ uuid: generateUUID(),
96
+ name: catName,
97
+ exit_uuid: exitUuid
98
+ });
99
+ exits.push({ uuid: exitUuid, destination_uuid: null });
100
+ }
101
+ }
102
+ // Build cases for non-default categories
103
+ for (const dialCase of DIAL_CASES) {
104
+ const category = categories.find((c) => c.name === dialCase.categoryName);
105
+ if (!category)
106
+ continue;
107
+ const existingCase = existingCases.find((c) => { var _a; return c.type === dialCase.type && ((_a = c.arguments) === null || _a === void 0 ? void 0 : _a[0]) === dialCase.arguments[0]; });
108
+ cases.push({
109
+ uuid: (existingCase === null || existingCase === void 0 ? void 0 : existingCase.uuid) || generateUUID(),
110
+ type: dialCase.type,
111
+ arguments: dialCase.arguments,
112
+ category_uuid: category.uuid
113
+ });
114
+ }
115
+ const failedCategory = categories.find((c) => c.name === 'Failed');
116
+ // Build wait config
117
+ const phone = (formData.phone || '').trim();
118
+ const dialLimit = parseInt(formData.dial_limit_seconds, 10);
119
+ const callLimit = parseInt(formData.call_limit_seconds, 10);
120
+ const waitConfig = {
121
+ type: 'dial',
122
+ phone
123
+ };
124
+ if (!isNaN(dialLimit) && dialLimit > 0) {
125
+ waitConfig.dial_limit_seconds = dialLimit;
126
+ }
127
+ if (!isNaN(callLimit) && callLimit > 0) {
128
+ waitConfig.call_limit_seconds = callLimit;
129
+ }
130
+ const router = {
131
+ type: 'switch',
132
+ operand: '@(default(resume.dial.status, ""))',
133
+ default_category_uuid: failedCategory === null || failedCategory === void 0 ? void 0 : failedCategory.uuid,
134
+ cases,
135
+ categories,
136
+ wait: waitConfig
137
+ };
138
+ if (formData.result_name && formData.result_name.trim() !== '') {
139
+ router.result_name = formData.result_name.trim();
140
+ }
141
+ return {
142
+ ...originalNode,
143
+ router,
144
+ exits
145
+ };
146
+ },
147
+ localizable: 'categories',
148
+ toLocalizationFormData: categoriesToLocalizationFormData,
149
+ fromLocalizationFormData: localizationFormDataToCategories
150
+ };
151
+ //# sourceMappingURL=wait_for_dial.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wait_for_dial.js","sourceRoot":"","sources":["../../../../src/flow/nodes/wait_for_dial.ts"],"names":[],"mappings":"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","sourcesContent":["import { SPLIT_GROUPS, FormData, NodeConfig, FlowTypes } from '../types';\nimport { Node, Category, Exit } from '../../store/flow-definition';\nimport { generateUUID } from '../../utils';\nimport {\n resultNameField,\n categoriesToLocalizationFormData,\n localizationFormDataToCategories\n} from './shared';\n\nconst DIAL_CATEGORIES = ['Answered', 'No Answer', 'Busy', 'Failed'];\nconst DIAL_CASES = [\n { type: 'has_only_text', arguments: ['answered'], categoryName: 'Answered' },\n {\n type: 'has_only_text',\n arguments: ['no_answer'],\n categoryName: 'No Answer'\n },\n { type: 'has_only_text', arguments: ['busy'], categoryName: 'Busy' }\n];\n\nexport const wait_for_dial: NodeConfig = {\n type: 'wait_for_dial',\n name: 'Redirect Call',\n group: SPLIT_GROUPS.wait,\n flowTypes: [FlowTypes.VOICE],\n router: {\n type: 'switch',\n defaultCategory: 'Failed',\n rules: DIAL_CASES.map((c) => ({\n type: c.type as any,\n arguments: c.arguments,\n categoryName: c.categoryName\n }))\n },\n form: {\n phone: {\n type: 'text',\n label: 'Phone Number',\n required: true,\n evaluated: true,\n placeholder: 'Phone number or expression'\n },\n dial_limit_seconds: {\n type: 'text',\n label: 'Dial Limit (seconds)',\n required: false,\n placeholder: '60'\n },\n call_limit_seconds: {\n type: 'text',\n label: 'Call Limit (seconds)',\n required: false,\n placeholder: '7200'\n },\n result_name: resultNameField\n },\n layout: [\n 'phone',\n {\n type: 'row',\n items: ['dial_limit_seconds', 'call_limit_seconds']\n },\n 'result_name'\n ],\n toFormData: (node: Node) => {\n const wait = node.router?.wait;\n return {\n uuid: node.uuid,\n phone: wait?.phone || '',\n dial_limit_seconds: wait?.dial_limit_seconds\n ? String(wait.dial_limit_seconds)\n : '',\n call_limit_seconds: wait?.call_limit_seconds\n ? String(wait.call_limit_seconds)\n : '',\n result_name: node.router?.result_name || ''\n };\n },\n fromFormData: (formData: FormData, originalNode: Node): Node => {\n const existingCategories = originalNode.router?.categories || [];\n const existingExits = originalNode.exits || [];\n const existingCases = originalNode.router?.cases || [];\n\n const categories: Category[] = [];\n const exits: Exit[] = [];\n const cases: any[] = [];\n\n // Build categories and cases for each dial outcome\n for (const catName of DIAL_CATEGORIES) {\n const existing = existingCategories.find(\n (c: Category) => c.name === catName\n );\n\n if (existing) {\n categories.push(existing);\n const existingExit = existingExits.find(\n (e: Exit) => e.uuid === existing.exit_uuid\n );\n exits.push(\n existingExit || {\n uuid: existing.exit_uuid,\n destination_uuid: null\n }\n );\n } else {\n const exitUuid = generateUUID();\n categories.push({\n uuid: generateUUID(),\n name: catName,\n exit_uuid: exitUuid\n });\n exits.push({ uuid: exitUuid, destination_uuid: null });\n }\n }\n\n // Build cases for non-default categories\n for (const dialCase of DIAL_CASES) {\n const category = categories.find((c) => c.name === dialCase.categoryName);\n if (!category) continue;\n\n const existingCase = existingCases.find(\n (c: any) =>\n c.type === dialCase.type && c.arguments?.[0] === dialCase.arguments[0]\n );\n\n cases.push({\n uuid: existingCase?.uuid || generateUUID(),\n type: dialCase.type,\n arguments: dialCase.arguments,\n category_uuid: category.uuid\n });\n }\n\n const failedCategory = categories.find((c) => c.name === 'Failed');\n\n // Build wait config\n const phone = (formData.phone || '').trim();\n const dialLimit = parseInt(formData.dial_limit_seconds, 10);\n const callLimit = parseInt(formData.call_limit_seconds, 10);\n\n const waitConfig: any = {\n type: 'dial',\n phone\n };\n\n if (!isNaN(dialLimit) && dialLimit > 0) {\n waitConfig.dial_limit_seconds = dialLimit;\n }\n\n if (!isNaN(callLimit) && callLimit > 0) {\n waitConfig.call_limit_seconds = callLimit;\n }\n\n const router: any = {\n type: 'switch',\n operand: '@(default(resume.dial.status, \"\"))',\n default_category_uuid: failedCategory?.uuid,\n cases,\n categories,\n wait: waitConfig\n };\n\n if (formData.result_name && formData.result_name.trim() !== '') {\n router.result_name = formData.result_name.trim();\n }\n\n return {\n ...originalNode,\n router,\n exits\n };\n },\n localizable: 'categories',\n toLocalizationFormData: categoriesToLocalizationFormData,\n fromLocalizationFormData: localizationFormDataToCategories\n};\n"]}
@@ -1,8 +1,68 @@
1
1
  import { SPLIT_GROUPS, FlowTypes } from '../types';
2
+ import { createRulesRouter } from '../../utils';
3
+ import { getDigitOperators, operatorsToSelectOptions, getOperatorConfig } from '../operators';
4
+ import { resultNameField, categoriesToLocalizationFormData, localizationFormDataToCategories } from './shared';
5
+ import { createRulesArrayConfig, extractUserRules, casesToFormRules } from './shared-rules';
2
6
  export const wait_for_digits = {
3
7
  type: 'wait_for_digits',
4
8
  name: 'Wait for Digits',
5
9
  group: SPLIT_GROUPS.wait,
6
- flowTypes: [FlowTypes.VOICE]
10
+ flowTypes: [FlowTypes.VOICE],
11
+ dialogSize: 'large',
12
+ form: {
13
+ rules: createRulesArrayConfig(operatorsToSelectOptions(getDigitOperators())),
14
+ result_name: resultNameField
15
+ },
16
+ layout: [
17
+ {
18
+ type: 'text',
19
+ text: 'Rules match against all digits pressed by the caller followed by the # sign.'
20
+ },
21
+ 'rules',
22
+ 'result_name'
23
+ ],
24
+ validate: (_formData) => {
25
+ return {
26
+ valid: true,
27
+ errors: {}
28
+ };
29
+ },
30
+ toFormData: (node) => {
31
+ var _a;
32
+ const rules = casesToFormRules(node);
33
+ return {
34
+ uuid: node.uuid,
35
+ rules,
36
+ result_name: ((_a = node.router) === null || _a === void 0 ? void 0 : _a.result_name) || ''
37
+ };
38
+ },
39
+ fromFormData: (formData, originalNode) => {
40
+ var _a, _b;
41
+ const userRules = extractUserRules(formData);
42
+ const existingCategories = ((_a = originalNode.router) === null || _a === void 0 ? void 0 : _a.categories) || [];
43
+ const existingExits = originalNode.exits || [];
44
+ const existingCases = ((_b = originalNode.router) === null || _b === void 0 ? void 0 : _b.cases) || [];
45
+ const { router, exits } = createRulesRouter('@input.text', userRules, getOperatorConfig, existingCategories, existingExits, existingCases);
46
+ const finalRouter = {
47
+ ...router,
48
+ wait: {
49
+ type: 'msg',
50
+ hint: {
51
+ type: 'digits'
52
+ }
53
+ }
54
+ };
55
+ if (formData.result_name && formData.result_name.trim() !== '') {
56
+ finalRouter.result_name = formData.result_name.trim();
57
+ }
58
+ return {
59
+ ...originalNode,
60
+ router: finalRouter,
61
+ exits
62
+ };
63
+ },
64
+ localizable: 'categories',
65
+ toLocalizationFormData: categoriesToLocalizationFormData,
66
+ fromLocalizationFormData: localizationFormDataToCategories
7
67
  };
8
68
  //# sourceMappingURL=wait_for_digits.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"wait_for_digits.js","sourceRoot":"","sources":["../../../../src/flow/nodes/wait_for_digits.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAc,SAAS,EAAE,MAAM,UAAU,CAAC;AAE/D,MAAM,CAAC,MAAM,eAAe,GAAe;IACzC,IAAI,EAAE,iBAAiB;IACvB,IAAI,EAAE,iBAAiB;IACvB,KAAK,EAAE,YAAY,CAAC,IAAI;IACxB,SAAS,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC;CAC7B,CAAC","sourcesContent":["import { SPLIT_GROUPS, NodeConfig, FlowTypes } from '../types';\n\nexport const wait_for_digits: NodeConfig = {\n type: 'wait_for_digits',\n name: 'Wait for Digits',\n group: SPLIT_GROUPS.wait,\n flowTypes: [FlowTypes.VOICE]\n};\n"]}
1
+ {"version":3,"file":"wait_for_digits.js","sourceRoot":"","sources":["../../../../src/flow/nodes/wait_for_digits.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAwB,SAAS,EAAE,MAAM,UAAU,CAAC;AAEzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACxB,iBAAiB,EAClB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,eAAe,EACf,gCAAgC,EAChC,gCAAgC,EACjC,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,gBAAgB,CAAC;AAExB,MAAM,CAAC,MAAM,eAAe,GAAe;IACzC,IAAI,EAAE,iBAAiB;IACvB,IAAI,EAAE,iBAAiB;IACvB,KAAK,EAAE,YAAY,CAAC,IAAI;IACxB,SAAS,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC;IAC5B,UAAU,EAAE,OAAO;IACnB,IAAI,EAAE;QACJ,KAAK,EAAE,sBAAsB,CAC3B,wBAAwB,CAAC,iBAAiB,EAAE,CAAC,CAC9C;QACD,WAAW,EAAE,eAAe;KAC7B;IACD,MAAM,EAAE;QACN;YACE,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,8EAA8E;SACrF;QACD,OAAO;QACP,aAAa;KACd;IACD,QAAQ,EAAE,CAAC,SAAmB,EAAE,EAAE;QAChC,OAAO;YACL,KAAK,EAAE,IAAI;YACX,MAAM,EAAE,EAAE;SACX,CAAC;IACJ,CAAC;IACD,UAAU,EAAE,CAAC,IAAU,EAAE,EAAE;;QACzB,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACrC,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK;YACL,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,MAAM,SAAS,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAC7C,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,iBAAiB,CACzC,aAAa,EACb,SAAS,EACT,iBAAiB,EACjB,kBAAkB,EAClB,aAAa,EACb,aAAa,CACd,CAAC;QAEF,MAAM,WAAW,GAAQ;YACvB,GAAG,MAAM;YACT,IAAI,EAAE;gBACJ,IAAI,EAAE,KAAK;gBACX,IAAI,EAAE;oBACJ,IAAI,EAAE,QAAQ;iBACf;aACF;SACF,CAAC;QAEF,IAAI,QAAQ,CAAC,WAAW,IAAI,QAAQ,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAC/D,WAAW,CAAC,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;QACxD,CAAC;QAED,OAAO;YACL,GAAG,YAAY;YACf,MAAM,EAAE,WAAW;YACnB,KAAK;SACN,CAAC;IACJ,CAAC;IACD,WAAW,EAAE,YAAY;IACzB,sBAAsB,EAAE,gCAAgC;IACxD,wBAAwB,EAAE,gCAAgC;CAC3D,CAAC","sourcesContent":["import { SPLIT_GROUPS, FormData, NodeConfig, FlowTypes } from '../types';\nimport { Node } from '../../store/flow-definition';\nimport { createRulesRouter } from '../../utils';\nimport {\n getDigitOperators,\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 wait_for_digits: NodeConfig = {\n type: 'wait_for_digits',\n name: 'Wait for Digits',\n group: SPLIT_GROUPS.wait,\n flowTypes: [FlowTypes.VOICE],\n dialogSize: 'large',\n form: {\n rules: createRulesArrayConfig(\n operatorsToSelectOptions(getDigitOperators())\n ),\n result_name: resultNameField\n },\n layout: [\n {\n type: 'text',\n text: 'Rules match against all digits pressed by the caller followed by the # sign.'\n },\n 'rules',\n 'result_name'\n ],\n validate: (_formData: FormData) => {\n return {\n valid: true,\n errors: {}\n };\n },\n toFormData: (node: Node) => {\n const rules = casesToFormRules(node);\n return {\n uuid: node.uuid,\n rules,\n result_name: node.router?.result_name || ''\n };\n },\n fromFormData: (formData: FormData, originalNode: Node): Node => {\n const userRules = extractUserRules(formData);\n const existingCategories = originalNode.router?.categories || [];\n const existingExits = originalNode.exits || [];\n const existingCases = originalNode.router?.cases || [];\n\n const { router, exits } = createRulesRouter(\n '@input.text',\n userRules,\n getOperatorConfig,\n existingCategories,\n existingExits,\n existingCases\n );\n\n const finalRouter: any = {\n ...router,\n wait: {\n type: 'msg',\n hint: {\n type: 'digits'\n }\n }\n };\n\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\n };\n },\n localizable: 'categories',\n toLocalizationFormData: categoriesToLocalizationFormData,\n fromLocalizationFormData: localizationFormDataToCategories\n};\n"]}
@@ -1,8 +1,179 @@
1
1
  import { SPLIT_GROUPS, FlowTypes } from '../types';
2
+ import { generateUUID } from '../../utils';
3
+ import { resultNameField, categoriesToLocalizationFormData, localizationFormDataToCategories } from './shared';
4
+ // Menu digits in display order: 1-9 then 0
5
+ const MENU_DIGITS = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'];
6
+ function digitFieldKey(digit) {
7
+ return `digit_${digit}`;
8
+ }
2
9
  export const wait_for_menu = {
3
10
  type: 'wait_for_menu',
4
- name: 'Wait for Menu Selection',
11
+ name: 'Wait for Menu',
5
12
  group: SPLIT_GROUPS.wait,
6
- flowTypes: [FlowTypes.VOICE]
13
+ flowTypes: [FlowTypes.VOICE],
14
+ form: {
15
+ ...Object.fromEntries(MENU_DIGITS.map((digit) => [
16
+ digitFieldKey(digit),
17
+ {
18
+ type: 'text',
19
+ required: false,
20
+ placeholder: '',
21
+ flavor: 'xsmall'
22
+ }
23
+ ])),
24
+ result_name: resultNameField
25
+ },
26
+ layout: [
27
+ {
28
+ type: 'row',
29
+ items: ['digit_1', 'digit_2', 'digit_3'],
30
+ gap: '2rem',
31
+ marginBottom: '0.5rem',
32
+ inlineLabels: { digit_1: '1', digit_2: '2', digit_3: '3' }
33
+ },
34
+ {
35
+ type: 'row',
36
+ items: ['digit_4', 'digit_5', 'digit_6'],
37
+ gap: '2rem',
38
+ marginBottom: '0.5rem',
39
+ inlineLabels: { digit_4: '4', digit_5: '5', digit_6: '6' }
40
+ },
41
+ {
42
+ type: 'row',
43
+ items: ['digit_7', 'digit_8', 'digit_9'],
44
+ gap: '2rem',
45
+ marginBottom: '0.5rem',
46
+ inlineLabels: { digit_7: '7', digit_8: '8', digit_9: '9' }
47
+ },
48
+ {
49
+ type: 'row',
50
+ items: [
51
+ { type: 'spacer' },
52
+ 'digit_0',
53
+ { type: 'spacer' }
54
+ ],
55
+ gap: '2rem',
56
+ inlineLabels: { digit_0: '0' }
57
+ },
58
+ 'result_name'
59
+ ],
60
+ toFormData: (node) => {
61
+ var _a, _b, _c, _d;
62
+ const formData = {
63
+ uuid: node.uuid,
64
+ result_name: ((_a = node.router) === null || _a === void 0 ? void 0 : _a.result_name) || ''
65
+ };
66
+ // Initialize all digit fields as empty
67
+ for (const digit of MENU_DIGITS) {
68
+ formData[digitFieldKey(digit)] = '';
69
+ }
70
+ // Fill in category names from cases
71
+ if (((_b = node.router) === null || _b === void 0 ? void 0 : _b.cases) && ((_c = node.router) === null || _c === void 0 ? void 0 : _c.categories)) {
72
+ for (const case_ of node.router.cases) {
73
+ if (case_.type === 'has_number_eq' && ((_d = case_.arguments) === null || _d === void 0 ? void 0 : _d[0])) {
74
+ const digit = case_.arguments[0];
75
+ const category = node.router.categories.find((cat) => cat.uuid === case_.category_uuid);
76
+ if (category && MENU_DIGITS.includes(digit)) {
77
+ formData[digitFieldKey(digit)] = category.name;
78
+ }
79
+ }
80
+ }
81
+ }
82
+ return formData;
83
+ },
84
+ fromFormData: (formData, originalNode) => {
85
+ var _a, _b;
86
+ const existingCategories = ((_a = originalNode.router) === null || _a === void 0 ? void 0 : _a.categories) || [];
87
+ const existingExits = originalNode.exits || [];
88
+ const existingCases = ((_b = originalNode.router) === null || _b === void 0 ? void 0 : _b.cases) || [];
89
+ const categories = [];
90
+ const exits = [];
91
+ const cases = [];
92
+ // Build categories and cases for each filled digit
93
+ for (const digit of MENU_DIGITS) {
94
+ const categoryName = (formData[digitFieldKey(digit)] || '').trim();
95
+ if (!categoryName)
96
+ continue;
97
+ // Check if a category with this name already exists in our new list
98
+ let category = categories.find((c) => c.name === categoryName);
99
+ if (!category) {
100
+ // Try to find existing category with same name to preserve UUIDs
101
+ const existingCat = existingCategories.find((c) => c.name === categoryName);
102
+ if (existingCat) {
103
+ category = existingCat;
104
+ const existingExit = existingExits.find((e) => e.uuid === existingCat.exit_uuid);
105
+ categories.push(category);
106
+ exits.push(existingExit || {
107
+ uuid: existingCat.exit_uuid,
108
+ destination_uuid: null
109
+ });
110
+ }
111
+ else {
112
+ const exitUuid = generateUUID();
113
+ category = {
114
+ uuid: generateUUID(),
115
+ name: categoryName,
116
+ exit_uuid: exitUuid
117
+ };
118
+ categories.push(category);
119
+ exits.push({ uuid: exitUuid, destination_uuid: null });
120
+ }
121
+ }
122
+ // Find existing case for this digit to preserve UUID
123
+ const existingCase = existingCases.find((c) => { var _a; return c.type === 'has_number_eq' && ((_a = c.arguments) === null || _a === void 0 ? void 0 : _a[0]) === digit; });
124
+ cases.push({
125
+ uuid: (existingCase === null || existingCase === void 0 ? void 0 : existingCase.uuid) || generateUUID(),
126
+ type: 'has_number_eq',
127
+ arguments: [digit],
128
+ category_uuid: category.uuid
129
+ });
130
+ }
131
+ // Add "Other" default category
132
+ const existingOther = existingCategories.find((c) => c.name === 'Other');
133
+ let otherCategory;
134
+ if (existingOther) {
135
+ otherCategory = existingOther;
136
+ const existingExit = existingExits.find((e) => e.uuid === existingOther.exit_uuid);
137
+ exits.push(existingExit || {
138
+ uuid: existingOther.exit_uuid,
139
+ destination_uuid: null
140
+ });
141
+ }
142
+ else {
143
+ const exitUuid = generateUUID();
144
+ otherCategory = {
145
+ uuid: generateUUID(),
146
+ name: 'Other',
147
+ exit_uuid: exitUuid
148
+ };
149
+ exits.push({ uuid: exitUuid, destination_uuid: null });
150
+ }
151
+ categories.push(otherCategory);
152
+ const router = {
153
+ type: 'switch',
154
+ operand: '@input.text',
155
+ default_category_uuid: otherCategory.uuid,
156
+ cases,
157
+ categories,
158
+ wait: {
159
+ type: 'msg',
160
+ hint: {
161
+ type: 'digits',
162
+ count: 1
163
+ }
164
+ }
165
+ };
166
+ if (formData.result_name && formData.result_name.trim() !== '') {
167
+ router.result_name = formData.result_name.trim();
168
+ }
169
+ return {
170
+ ...originalNode,
171
+ router,
172
+ exits
173
+ };
174
+ },
175
+ localizable: 'categories',
176
+ toLocalizationFormData: categoriesToLocalizationFormData,
177
+ fromLocalizationFormData: localizationFormDataToCategories
7
178
  };
8
179
  //# sourceMappingURL=wait_for_menu.js.map