@nyaruka/temba-components 0.131.1 → 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.
- package/.github/workflows/publish.yml +4 -1
- package/CHANGELOG.md +75 -1
- package/demo/components/floating-tabs/example.html +400 -0
- package/demo/components/flow/index.html +1 -1
- package/demo/data/flows/food-order.json +2 -2
- package/demo/data/flows/sample-flow.json +113 -125
- package/demo/data/flows/voicemail.json +613 -0
- package/demo/index.html +6 -0
- package/dist/locales/es.js +5 -5
- package/dist/locales/es.js.map +1 -1
- package/dist/locales/fr.js +5 -5
- package/dist/locales/fr.js.map +1 -1
- package/dist/locales/locale-codes.js +11 -2
- package/dist/locales/locale-codes.js.map +1 -1
- package/dist/locales/pt.js +5 -5
- package/dist/locales/pt.js.map +1 -1
- package/dist/static/svg/index.svg +1 -1
- package/dist/temba-components.js +1773 -662
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/Icons.js +4 -1
- package/out-tsc/src/Icons.js.map +1 -1
- package/out-tsc/src/display/FloatingTab.js +167 -0
- package/out-tsc/src/display/FloatingTab.js.map +1 -0
- package/out-tsc/src/display/ProgressBar.js +22 -2
- package/out-tsc/src/display/ProgressBar.js.map +1 -1
- package/out-tsc/src/events.js.map +1 -1
- package/out-tsc/src/flow/CanvasMenu.js +200 -0
- package/out-tsc/src/flow/CanvasMenu.js.map +1 -0
- package/out-tsc/src/flow/CanvasNode.js +489 -47
- package/out-tsc/src/flow/CanvasNode.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +1417 -67
- package/out-tsc/src/flow/Editor.js.map +1 -1
- package/out-tsc/src/flow/NodeEditor.js +479 -112
- package/out-tsc/src/flow/NodeEditor.js.map +1 -1
- package/out-tsc/src/flow/NodeTypeSelector.js +540 -0
- package/out-tsc/src/flow/NodeTypeSelector.js.map +1 -0
- package/out-tsc/src/flow/StickyNote.js +12 -3
- package/out-tsc/src/flow/StickyNote.js.map +1 -1
- package/out-tsc/src/flow/actions/add_contact_groups.js +4 -3
- package/out-tsc/src/flow/actions/add_contact_groups.js.map +1 -1
- package/out-tsc/src/flow/actions/add_contact_urn.js +63 -4
- package/out-tsc/src/flow/actions/add_contact_urn.js.map +1 -1
- package/out-tsc/src/flow/actions/add_input_labels.js +4 -3
- package/out-tsc/src/flow/actions/add_input_labels.js.map +1 -1
- package/out-tsc/src/flow/actions/play_audio.js +3 -2
- package/out-tsc/src/flow/actions/play_audio.js.map +1 -1
- package/out-tsc/src/flow/actions/remove_contact_groups.js +7 -5
- package/out-tsc/src/flow/actions/remove_contact_groups.js.map +1 -1
- package/out-tsc/src/flow/actions/request_optin.js +3 -2
- package/out-tsc/src/flow/actions/request_optin.js.map +1 -1
- package/out-tsc/src/flow/actions/say_msg.js +3 -2
- package/out-tsc/src/flow/actions/say_msg.js.map +1 -1
- package/out-tsc/src/flow/actions/send_broadcast.js +77 -23
- package/out-tsc/src/flow/actions/send_broadcast.js.map +1 -1
- package/out-tsc/src/flow/actions/send_email.js +5 -5
- package/out-tsc/src/flow/actions/send_email.js.map +1 -1
- package/out-tsc/src/flow/actions/send_msg.js +101 -21
- package/out-tsc/src/flow/actions/send_msg.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_channel.js +6 -9
- package/out-tsc/src/flow/actions/set_contact_channel.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_field.js +20 -20
- package/out-tsc/src/flow/actions/set_contact_field.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_language.js +3 -2
- package/out-tsc/src/flow/actions/set_contact_language.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_name.js +3 -12
- package/out-tsc/src/flow/actions/set_contact_name.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_status.js +3 -2
- package/out-tsc/src/flow/actions/set_contact_status.js.map +1 -1
- package/out-tsc/src/flow/actions/set_run_result.js +4 -3
- package/out-tsc/src/flow/actions/set_run_result.js.map +1 -1
- package/out-tsc/src/flow/actions/start_session.js +181 -6
- package/out-tsc/src/flow/actions/start_session.js.map +1 -1
- package/out-tsc/src/flow/config.js +11 -23
- package/out-tsc/src/flow/config.js.map +1 -1
- package/out-tsc/src/flow/currencies.js +45 -0
- package/out-tsc/src/flow/currencies.js.map +1 -0
- package/out-tsc/src/flow/nodes/shared-rules.js +257 -0
- package/out-tsc/src/flow/nodes/shared-rules.js.map +1 -0
- package/out-tsc/src/flow/nodes/shared.js +71 -0
- package/out-tsc/src/flow/nodes/shared.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_airtime.js +211 -5
- package/out-tsc/src/flow/nodes/split_by_airtime.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_contact_field.js +152 -3
- package/out-tsc/src/flow/nodes/split_by_contact_field.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_expression.js +73 -2
- package/out-tsc/src/flow/nodes/split_by_expression.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_groups.js +18 -10
- package/out-tsc/src/flow/nodes/split_by_groups.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_intent.js +8 -0
- package/out-tsc/src/flow/nodes/split_by_intent.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_llm.js +11 -3
- package/out-tsc/src/flow/nodes/split_by_llm.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_llm_categorize.js +10 -3
- package/out-tsc/src/flow/nodes/split_by_llm_categorize.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_random.js +10 -4
- package/out-tsc/src/flow/nodes/split_by_random.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_resthook.js +113 -0
- package/out-tsc/src/flow/nodes/split_by_resthook.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_run_result.js +211 -3
- package/out-tsc/src/flow/nodes/split_by_run_result.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_scheme.js +158 -2
- package/out-tsc/src/flow/nodes/split_by_scheme.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_subflow.js +13 -5
- package/out-tsc/src/flow/nodes/split_by_subflow.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_ticket.js +10 -3
- package/out-tsc/src/flow/nodes/split_by_ticket.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_webhook.js +10 -3
- package/out-tsc/src/flow/nodes/split_by_webhook.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_digits.js +3 -2
- package/out-tsc/src/flow/nodes/wait_for_digits.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_menu.js +3 -2
- package/out-tsc/src/flow/nodes/wait_for_menu.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_response.js +38 -568
- package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -1
- package/out-tsc/src/flow/types.js +86 -12
- package/out-tsc/src/flow/types.js.map +1 -1
- package/out-tsc/src/flow/utils.js +101 -14
- package/out-tsc/src/flow/utils.js.map +1 -1
- package/out-tsc/src/form/FieldRenderer.js +2 -4
- package/out-tsc/src/form/FieldRenderer.js.map +1 -1
- package/out-tsc/src/interfaces.js +3 -0
- package/out-tsc/src/interfaces.js.map +1 -1
- package/out-tsc/src/layout/FloatingWindow.js +346 -0
- package/out-tsc/src/layout/FloatingWindow.js.map +1 -0
- package/out-tsc/src/list/SortableList.js +98 -33
- package/out-tsc/src/list/SortableList.js.map +1 -1
- package/out-tsc/src/live/ContactChat.js +6 -25
- package/out-tsc/src/live/ContactChat.js.map +1 -1
- package/out-tsc/src/locales/es.js +5 -5
- package/out-tsc/src/locales/es.js.map +1 -1
- package/out-tsc/src/locales/fr.js +5 -5
- package/out-tsc/src/locales/fr.js.map +1 -1
- package/out-tsc/src/locales/locale-codes.js +11 -2
- package/out-tsc/src/locales/locale-codes.js.map +1 -1
- package/out-tsc/src/locales/pt.js +5 -5
- package/out-tsc/src/locales/pt.js.map +1 -1
- package/out-tsc/src/store/AppState.js +120 -0
- package/out-tsc/src/store/AppState.js.map +1 -1
- package/out-tsc/src/utils.js +254 -13
- package/out-tsc/src/utils.js.map +1 -1
- package/out-tsc/temba-modules.js +8 -0
- package/out-tsc/temba-modules.js.map +1 -1
- package/out-tsc/test/ActionHelper.js +3 -3
- package/out-tsc/test/ActionHelper.js.map +1 -1
- package/out-tsc/test/NodeHelper.js +6 -3
- package/out-tsc/test/NodeHelper.js.map +1 -1
- package/out-tsc/test/actions/add_contact_urn.test.js +202 -0
- package/out-tsc/test/actions/add_contact_urn.test.js.map +1 -0
- package/out-tsc/test/actions/send_broadcast.test.js +148 -0
- package/out-tsc/test/actions/send_broadcast.test.js.map +1 -0
- package/out-tsc/test/actions/send_email.test.js +17 -23
- package/out-tsc/test/actions/send_email.test.js.map +1 -1
- package/out-tsc/test/actions/send_msg.test.js +33 -15
- package/out-tsc/test/actions/send_msg.test.js.map +1 -1
- package/out-tsc/test/actions/start_session.test.js +116 -0
- package/out-tsc/test/actions/start_session.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_airtime.test.js +604 -0
- package/out-tsc/test/nodes/split_by_airtime.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_contact_field.test.js +387 -0
- package/out-tsc/test/nodes/split_by_contact_field.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_expression.test.js +614 -0
- package/out-tsc/test/nodes/split_by_expression.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_random.test.js +3 -3
- package/out-tsc/test/nodes/split_by_random.test.js.map +1 -1
- package/out-tsc/test/nodes/split_by_resthook.test.js +337 -0
- package/out-tsc/test/nodes/split_by_resthook.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_run_result.test.js +920 -0
- package/out-tsc/test/nodes/split_by_run_result.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_scheme.test.js +399 -0
- package/out-tsc/test/nodes/split_by_scheme.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_subflow.test.js +333 -0
- package/out-tsc/test/nodes/split_by_subflow.test.js.map +1 -0
- package/out-tsc/test/nodes/wait_for_digits.test.js +2 -2
- package/out-tsc/test/nodes/wait_for_digits.test.js.map +1 -1
- package/out-tsc/test/nodes/wait_for_response.test.js +2 -1
- package/out-tsc/test/nodes/wait_for_response.test.js.map +1 -1
- package/out-tsc/test/temba-action-drag-between-nodes.test.js +252 -0
- package/out-tsc/test/temba-action-drag-between-nodes.test.js.map +1 -0
- package/out-tsc/test/temba-canvas-menu.test.js +122 -0
- package/out-tsc/test/temba-canvas-menu.test.js.map +1 -0
- package/out-tsc/test/temba-floating-tab.test.js +91 -0
- package/out-tsc/test/temba-floating-tab.test.js.map +1 -0
- package/out-tsc/test/temba-floating-window.test.js +301 -0
- package/out-tsc/test/temba-floating-window.test.js.map +1 -0
- package/out-tsc/test/temba-flow-editor-node.test.js +202 -2
- package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
- package/out-tsc/test/temba-flow-editor.test.js +7 -8
- package/out-tsc/test/temba-flow-editor.test.js.map +1 -1
- package/out-tsc/test/temba-localization.test.js +471 -0
- package/out-tsc/test/temba-localization.test.js.map +1 -0
- package/out-tsc/test/temba-node-editor.test.js +3 -1
- package/out-tsc/test/temba-node-editor.test.js.map +1 -1
- package/out-tsc/test/temba-node-type-selector.test.js +265 -0
- package/out-tsc/test/temba-node-type-selector.test.js.map +1 -0
- package/out-tsc/test/temba-omnibox.test.js +2 -1
- package/out-tsc/test/temba-omnibox.test.js.map +1 -1
- package/out-tsc/test/temba-sortable-list.test.js +51 -0
- package/out-tsc/test/temba-sortable-list.test.js.map +1 -1
- package/out-tsc/test/temba-utils-index.test.js +1 -27
- package/out-tsc/test/temba-utils-index.test.js.map +1 -1
- package/out-tsc/test/utils.test.js +20 -0
- package/out-tsc/test/utils.test.js.map +1 -1
- package/package.json +2 -1
- package/screenshots/truth/actions/add_contact_groups/editor/descriptive-group-names.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/editor/long-group-names.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/editor/many-groups.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/editor/multiple-groups.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/editor/single-group.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/descriptive-group-names.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/long-group-names.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/many-groups.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/multiple-groups.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/single-group.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/expression-facebook.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/expression-phone.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/facebook-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/instagram-handle.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/line-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/phone-number.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/telegram-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/viber-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/wechat-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/whatsapp.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/expression-facebook.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/expression-phone.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/facebook-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/instagram-handle.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/line-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/phone-number.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/telegram-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/viber-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/wechat-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/whatsapp.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/cleanup-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/long-descriptive-group-names.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/many-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/multiple-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/remove-from-all-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/single-group.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/cleanup-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/long-descriptive-group-names.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/many-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/multiple-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/remove-from-all-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/single-group.png +0 -0
- package/screenshots/truth/actions/send_broadcast/editor/contacts-only.png +0 -0
- package/screenshots/truth/actions/send_broadcast/editor/groups-and-contacts.png +0 -0
- package/screenshots/truth/actions/send_broadcast/editor/groups-only.png +0 -0
- package/screenshots/truth/actions/send_broadcast/editor/many-groups.png +0 -0
- package/screenshots/truth/actions/send_broadcast/editor/multiline-text.png +0 -0
- package/screenshots/truth/actions/send_broadcast/editor/with-attachments.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/contacts-only.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/groups-and-contacts.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/groups-only.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/many-groups.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/multiline-text.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/with-attachments.png +0 -0
- package/screenshots/truth/actions/send_email/editor/complex-business-email.png +0 -0
- package/screenshots/truth/actions/send_email/editor/empty-body.png +0 -0
- package/screenshots/truth/actions/send_email/editor/empty-subject.png +0 -0
- package/screenshots/truth/actions/send_email/editor/long-subject.png +0 -0
- package/screenshots/truth/actions/send_email/editor/multiline-body.png +0 -0
- package/screenshots/truth/actions/send_email/editor/multiple-recipients.png +0 -0
- package/screenshots/truth/actions/send_email/editor/simple-email.png +0 -0
- package/screenshots/truth/actions/send_email/editor/with-expressions.png +0 -0
- package/screenshots/truth/actions/send_email/render/complex-business-email.png +0 -0
- package/screenshots/truth/actions/send_email/render/empty-body.png +0 -0
- package/screenshots/truth/actions/send_email/render/empty-subject.png +0 -0
- package/screenshots/truth/actions/send_email/render/long-subject.png +0 -0
- package/screenshots/truth/actions/send_email/render/multiline-body.png +0 -0
- package/screenshots/truth/actions/send_email/render/multiple-recipients.png +0 -0
- package/screenshots/truth/actions/send_email/render/simple-email.png +0 -0
- package/screenshots/truth/actions/send_email/render/with-expressions.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/long-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/multiline-text-with-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/simple-text.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-with-linebreaks.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-with-many-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-with-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-without-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/long-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/multiline-text-with-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/simple-text.png +0 -0
- package/screenshots/truth/actions/send_msg/render/text-with-linebreaks.png +0 -0
- package/screenshots/truth/actions/send_msg/render/text-with-many-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/text-with-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/text-without-quick-replies.png +0 -0
- package/screenshots/truth/actions/start_session/editor/contact-query.png +0 -0
- package/screenshots/truth/actions/start_session/editor/contacts-only.png +0 -0
- package/screenshots/truth/actions/start_session/editor/create-contact.png +0 -0
- package/screenshots/truth/actions/start_session/editor/groups-and-contacts.png +0 -0
- package/screenshots/truth/actions/start_session/editor/groups-only.png +0 -0
- package/screenshots/truth/actions/start_session/editor/many-recipients.png +0 -0
- package/screenshots/truth/actions/start_session/render/contact-query.png +0 -0
- package/screenshots/truth/actions/start_session/render/contacts-only.png +0 -0
- package/screenshots/truth/actions/start_session/render/create-contact.png +0 -0
- package/screenshots/truth/actions/start_session/render/groups-and-contacts.png +0 -0
- package/screenshots/truth/actions/start_session/render/groups-only.png +0 -0
- package/screenshots/truth/actions/start_session/render/many-recipients.png +0 -0
- package/screenshots/truth/canvas-menu/open.png +0 -0
- package/screenshots/truth/editor/router.png +0 -0
- package/screenshots/truth/editor/wait.png +0 -0
- package/screenshots/truth/floating-tab/default.png +0 -0
- package/screenshots/truth/floating-tab/gray.png +0 -0
- package/screenshots/truth/floating-tab/green.png +0 -0
- package/screenshots/truth/floating-tab/hidden.png +0 -0
- package/screenshots/truth/floating-tab/hover.png +0 -0
- package/screenshots/truth/floating-tab/purple.png +0 -0
- package/screenshots/truth/floating-window/chromeless.png +0 -0
- package/screenshots/truth/floating-window/custom-size.png +0 -0
- package/screenshots/truth/floating-window/default.png +0 -0
- package/screenshots/truth/floating-window/with-header.png +0 -0
- package/screenshots/truth/list/fields-dragging.png +0 -0
- package/screenshots/truth/list/sortable-dragging.png +0 -0
- package/screenshots/truth/node-type-selector/action-mode.png +0 -0
- package/screenshots/truth/node-type-selector/split-mode.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/editor/information-extraction.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/editor/sentiment-analysis.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/editor/summarization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/editor/translation-task.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/information-extraction.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/sentiment-analysis.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/summarization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/translation-task.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/basic-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/custom-input-and-result-name.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/feedback-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/many-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/minimal-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/basic-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/custom-input-and-result-name.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/feedback-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/many-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/minimal-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_random/editor/ab-test-multiple-variants.png +0 -0
- package/screenshots/truth/nodes/split_by_random/editor/sampling-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/editor/three-way-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/editor/two-bucket-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/ab-test-multiple-variants.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/sampling-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/three-way-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/two-bucket-split.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/basic-digits-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/phone-number-collection.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/single-digit-with-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/verification-code.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/basic-digits-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/phone-number-collection.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/single-digit-with-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/verification-code.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/basic-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/custom-result-name.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/no-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/short-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/basic-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/custom-result-name.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/no-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/short-timeout.png +0 -0
- package/src/Icons.ts +4 -1
- package/src/display/FloatingTab.ts +174 -0
- package/src/display/ProgressBar.ts +22 -2
- package/src/events.ts +2 -8
- package/src/flow/CanvasMenu.ts +217 -0
- package/src/flow/CanvasNode.ts +596 -40
- package/src/flow/Editor.ts +1721 -45
- package/src/flow/NodeEditor.ts +621 -144
- package/src/flow/NodeTypeSelector.ts +636 -0
- package/src/flow/StickyNote.ts +12 -3
- package/src/flow/actions/add_contact_groups.ts +5 -4
- package/src/flow/actions/add_contact_urn.ts +78 -4
- package/src/flow/actions/add_input_labels.ts +5 -4
- package/src/flow/actions/play_audio.ts +3 -2
- package/src/flow/actions/remove_contact_groups.ts +16 -6
- package/src/flow/actions/request_optin.ts +3 -2
- package/src/flow/actions/say_msg.ts +3 -2
- package/src/flow/actions/send_broadcast.ts +86 -23
- package/src/flow/actions/send_email.ts +12 -6
- package/src/flow/actions/send_msg.ts +155 -34
- package/src/flow/actions/set_contact_channel.ts +6 -11
- package/src/flow/actions/set_contact_field.ts +21 -25
- package/src/flow/actions/set_contact_language.ts +11 -4
- package/src/flow/actions/set_contact_name.ts +4 -15
- package/src/flow/actions/set_contact_status.ts +4 -3
- package/src/flow/actions/set_run_result.ts +5 -4
- package/src/flow/actions/start_session.ts +210 -6
- package/src/flow/config.ts +11 -23
- package/src/flow/currencies.ts +51 -0
- package/src/flow/nodes/shared-rules.ts +301 -0
- package/src/flow/nodes/shared.ts +87 -0
- package/src/flow/nodes/split_by_airtime.ts +255 -5
- package/src/flow/nodes/split_by_contact_field.ts +195 -3
- package/src/flow/nodes/split_by_expression.ts +104 -2
- package/src/flow/nodes/split_by_groups.ts +26 -11
- package/src/flow/nodes/split_by_intent.ts +8 -0
- package/src/flow/nodes/split_by_llm.ts +22 -4
- package/src/flow/nodes/split_by_llm_categorize.ts +22 -5
- package/src/flow/nodes/split_by_random.ts +16 -6
- package/src/flow/nodes/split_by_resthook.ts +140 -0
- package/src/flow/nodes/split_by_run_result.ts +259 -3
- package/src/flow/nodes/split_by_scheme.ts +202 -2
- package/src/flow/nodes/split_by_subflow.ts +17 -5
- package/src/flow/nodes/split_by_ticket.ts +15 -4
- package/src/flow/nodes/split_by_webhook.ts +17 -6
- package/src/flow/nodes/wait_for_digits.ts +3 -2
- package/src/flow/nodes/wait_for_menu.ts +3 -2
- package/src/flow/nodes/wait_for_response.ts +59 -680
- package/src/flow/types.ts +156 -23
- package/src/flow/utils.ts +108 -14
- package/src/form/FieldRenderer.ts +2 -4
- package/src/interfaces.ts +3 -0
- package/src/layout/FloatingWindow.ts +386 -0
- package/src/list/SortableList.ts +109 -34
- package/src/live/ContactChat.ts +7 -25
- package/src/locales/es.ts +18 -13
- package/src/locales/fr.ts +18 -13
- package/src/locales/locale-codes.ts +11 -2
- package/src/locales/pt.ts +18 -13
- package/src/store/AppState.ts +173 -0
- package/src/store/flow-definition.d.ts +2 -5
- package/src/utils.ts +332 -12
- package/static/api/channels.json +46 -0
- package/static/api/llms.json +18 -0
- package/static/api/resthooks.json +31 -0
- package/static/svg/index.svg +1 -1
- package/static/svg/work/traced/lightning-02.svg +1 -0
- package/static/svg/work/used/lightning-02.svg +3 -0
- package/temba-modules.ts +8 -0
- package/test/ActionHelper.ts +3 -3
- package/test/NodeHelper.ts +6 -3
- package/test/actions/add_contact_urn.test.ts +287 -0
- package/test/actions/send_broadcast.test.ts +190 -0
- package/test/actions/send_email.test.ts +17 -23
- package/test/actions/send_msg.test.ts +39 -15
- package/test/actions/start_session.test.ts +151 -0
- package/test/nodes/split_by_airtime.test.ts +673 -0
- package/test/nodes/split_by_contact_field.test.ts +451 -0
- package/test/nodes/split_by_expression.test.ts +751 -0
- package/test/nodes/split_by_random.test.ts +3 -3
- package/test/nodes/split_by_resthook.test.ts +398 -0
- package/test/nodes/split_by_run_result.test.ts +1109 -0
- package/test/nodes/split_by_scheme.test.ts +486 -0
- package/test/nodes/split_by_subflow.test.ts +381 -0
- package/test/nodes/wait_for_digits.test.ts +2 -2
- package/test/nodes/wait_for_response.test.ts +2 -1
- package/test/temba-action-drag-between-nodes.test.ts +301 -0
- package/test/temba-canvas-menu.test.ts +156 -0
- package/test/temba-floating-tab.test.ts +110 -0
- package/test/temba-floating-window.test.ts +477 -0
- package/test/temba-flow-editor-node.test.ts +246 -2
- package/test/temba-flow-editor.test.ts +7 -8
- package/test/temba-localization.test.ts +611 -0
- package/test/temba-node-editor.test.ts +3 -1
- package/test/temba-node-type-selector.test.ts +355 -0
- package/test/temba-omnibox.test.ts +2 -1
- package/test/temba-sortable-list.test.ts +69 -0
- package/test/temba-utils-index.test.ts +0 -35
- package/test/utils.test.ts +22 -0
- package/test-assets/contacts/history.json +14 -21
- package/test-assets/select/llms.json +2 -2
- package/web-dev-server.config.mjs +49 -1
- package/web-test-runner.config.mjs +0 -1
- package/out-tsc/src/flow/actions/call_classifier.js +0 -11
- package/out-tsc/src/flow/actions/call_classifier.js.map +0 -1
- package/out-tsc/src/flow/actions/call_resthook.js +0 -11
- package/out-tsc/src/flow/actions/call_resthook.js.map +0 -1
- package/out-tsc/src/flow/actions/split_by_expression_example.js +0 -77
- package/out-tsc/src/flow/actions/split_by_expression_example.js.map +0 -1
- package/out-tsc/src/flow/actions/transfer_airtime.js +0 -11
- package/out-tsc/src/flow/actions/transfer_airtime.js.map +0 -1
- package/out-tsc/src/flow/nodes/wait_for_audio.js +0 -7
- package/out-tsc/src/flow/nodes/wait_for_audio.js.map +0 -1
- package/out-tsc/src/flow/nodes/wait_for_image.js +0 -7
- package/out-tsc/src/flow/nodes/wait_for_image.js.map +0 -1
- package/out-tsc/src/flow/nodes/wait_for_location.js +0 -7
- package/out-tsc/src/flow/nodes/wait_for_location.js.map +0 -1
- package/out-tsc/src/flow/nodes/wait_for_video.js +0 -7
- package/out-tsc/src/flow/nodes/wait_for_video.js.map +0 -1
- package/src/flow/actions/call_classifier.ts +0 -12
- package/src/flow/actions/call_resthook.ts +0 -12
- package/src/flow/actions/split_by_expression_example.ts +0 -88
- package/src/flow/actions/transfer_airtime.ts +0 -12
- package/src/flow/nodes/wait_for_audio.ts +0 -7
- package/src/flow/nodes/wait_for_image.ts +0 -7
- package/src/flow/nodes/wait_for_location.ts +0 -7
- package/src/flow/nodes/wait_for_video.ts +0 -7
|
@@ -0,0 +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"]}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared result_name field configuration for router nodes.
|
|
3
|
+
* This provides a consistent "Save as..." optional field interface across all splits.
|
|
4
|
+
*
|
|
5
|
+
* The field is hidden by default and revealed via a "Save as..." link.
|
|
6
|
+
* Once revealed, it cannot be hidden again (the link disappears).
|
|
7
|
+
* If the field already has a value, it's shown immediately without the link.
|
|
8
|
+
*/
|
|
9
|
+
export const resultNameField = {
|
|
10
|
+
type: 'text',
|
|
11
|
+
label: 'Result Name',
|
|
12
|
+
required: false,
|
|
13
|
+
placeholder: '(optional)',
|
|
14
|
+
helpText: 'The name to use to reference this result in the flow',
|
|
15
|
+
optionalLink: 'Save result as...'
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Shared category localization functions for router nodes.
|
|
19
|
+
* These provide a consistent way to localize category names across all router types.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Converts a node's categories to localization form data.
|
|
23
|
+
* @param node - The node containing categories to localize
|
|
24
|
+
* @param localization - The existing localization data for this language
|
|
25
|
+
* @returns Form data with category UUIDs mapped to original and localized names
|
|
26
|
+
*/
|
|
27
|
+
export function categoriesToLocalizationFormData(node, localization) {
|
|
28
|
+
var _a;
|
|
29
|
+
const categories = ((_a = node.router) === null || _a === void 0 ? void 0 : _a.categories) || [];
|
|
30
|
+
const localizationData = {};
|
|
31
|
+
categories.forEach((category) => {
|
|
32
|
+
const categoryUuid = category.uuid;
|
|
33
|
+
const categoryLocalization = localization[categoryUuid];
|
|
34
|
+
localizationData[categoryUuid] = {
|
|
35
|
+
originalName: category.name,
|
|
36
|
+
localizedName: categoryLocalization && categoryLocalization.name
|
|
37
|
+
? Array.isArray(categoryLocalization.name)
|
|
38
|
+
? categoryLocalization.name[0] || ''
|
|
39
|
+
: categoryLocalization.name
|
|
40
|
+
: ''
|
|
41
|
+
};
|
|
42
|
+
});
|
|
43
|
+
return {
|
|
44
|
+
categories: localizationData
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Converts localization form data back to the localization structure.
|
|
49
|
+
* @param formData - The form data containing category localizations
|
|
50
|
+
* @param _node - The original node (reserved for future validation)
|
|
51
|
+
* @returns Record mapping category UUIDs to their localization data
|
|
52
|
+
*/
|
|
53
|
+
export function localizationFormDataToCategories(formData, _node) {
|
|
54
|
+
const localizationData = {};
|
|
55
|
+
if (formData.categories) {
|
|
56
|
+
Object.keys(formData.categories).forEach((categoryUuid) => {
|
|
57
|
+
var _a, _b;
|
|
58
|
+
const categoryData = formData.categories[categoryUuid];
|
|
59
|
+
const localizedName = ((_a = categoryData.localizedName) === null || _a === void 0 ? void 0 : _a.trim()) || '';
|
|
60
|
+
const originalName = ((_b = categoryData.originalName) === null || _b === void 0 ? void 0 : _b.trim()) || '';
|
|
61
|
+
// Only save if localized name is different from original and not empty
|
|
62
|
+
if (localizedName && localizedName !== originalName) {
|
|
63
|
+
localizationData[categoryUuid] = {
|
|
64
|
+
name: [localizedName]
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return localizationData;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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,9 +1,215 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { ACTION_GROUPS, FlowTypes, Features } from '../types';
|
|
2
|
+
import { generateUUID, createSuccessFailureRouter } from '../../utils';
|
|
3
|
+
import { html } from 'lit';
|
|
4
|
+
import { CURRENCY_OPTIONS, CURRENCIES } from '../currencies';
|
|
5
|
+
import { resultNameField, categoriesToLocalizationFormData, localizationFormDataToCategories } from './shared';
|
|
3
6
|
export const split_by_airtime = {
|
|
4
7
|
type: 'split_by_airtime',
|
|
5
|
-
name: '
|
|
6
|
-
|
|
7
|
-
|
|
8
|
+
name: 'Send Airtime',
|
|
9
|
+
group: ACTION_GROUPS.services,
|
|
10
|
+
flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
|
|
11
|
+
features: [Features.AIRTIME],
|
|
12
|
+
showAsAction: true,
|
|
13
|
+
form: {
|
|
14
|
+
amounts: {
|
|
15
|
+
type: 'array',
|
|
16
|
+
label: 'Airtime Amounts',
|
|
17
|
+
helpText: 'Define the currencies and amounts to transfer',
|
|
18
|
+
required: true,
|
|
19
|
+
itemLabel: 'Amount',
|
|
20
|
+
sortable: false,
|
|
21
|
+
minItems: 1,
|
|
22
|
+
maxItems: 10,
|
|
23
|
+
isEmptyItem: (item) => {
|
|
24
|
+
return !item.currency || !item.amount || item.amount.trim() === '';
|
|
25
|
+
},
|
|
26
|
+
itemConfig: {
|
|
27
|
+
currency: {
|
|
28
|
+
type: 'select',
|
|
29
|
+
placeholder: 'Select a currency',
|
|
30
|
+
required: true,
|
|
31
|
+
options: CURRENCY_OPTIONS,
|
|
32
|
+
searchable: true,
|
|
33
|
+
multi: false,
|
|
34
|
+
width: '200px'
|
|
35
|
+
},
|
|
36
|
+
amount: {
|
|
37
|
+
type: 'text',
|
|
38
|
+
placeholder: 'Amount',
|
|
39
|
+
required: true
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
result_name: resultNameField
|
|
44
|
+
},
|
|
45
|
+
layout: ['amounts', 'result_name'],
|
|
46
|
+
validate: (formData) => {
|
|
47
|
+
const errors = {};
|
|
48
|
+
// Validate that we have at least one amount
|
|
49
|
+
if (formData.amounts && Array.isArray(formData.amounts)) {
|
|
50
|
+
const validAmounts = formData.amounts.filter((item) => (item === null || item === void 0 ? void 0 : item.currency) && (item === null || item === void 0 ? void 0 : item.amount) && item.amount.trim() !== '');
|
|
51
|
+
if (validAmounts.length === 0) {
|
|
52
|
+
errors.amounts = 'At least one currency and amount is required';
|
|
53
|
+
return {
|
|
54
|
+
valid: false,
|
|
55
|
+
errors
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
// Check for duplicate currencies
|
|
59
|
+
const currencies = new Set();
|
|
60
|
+
const duplicates = [];
|
|
61
|
+
validAmounts.forEach((item) => {
|
|
62
|
+
var _a;
|
|
63
|
+
// Extract currency code from selection
|
|
64
|
+
const currencyCode = Array.isArray(item.currency) && item.currency.length > 0
|
|
65
|
+
? item.currency[0].value
|
|
66
|
+
: typeof item.currency === 'string'
|
|
67
|
+
? item.currency
|
|
68
|
+
: (_a = item.currency) === null || _a === void 0 ? void 0 : _a.value;
|
|
69
|
+
if (currencies.has(currencyCode)) {
|
|
70
|
+
duplicates.push(currencyCode);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
currencies.add(currencyCode);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
if (duplicates.length > 0) {
|
|
77
|
+
errors.amounts = `Duplicate currencies found: ${duplicates.join(', ')}`;
|
|
78
|
+
}
|
|
79
|
+
// Validate amounts are numeric
|
|
80
|
+
for (const item of validAmounts) {
|
|
81
|
+
const amount = item.amount.trim();
|
|
82
|
+
if (isNaN(Number(amount)) || Number(amount) <= 0) {
|
|
83
|
+
errors.amounts = 'All amounts must be valid positive numbers';
|
|
84
|
+
return {
|
|
85
|
+
valid: false,
|
|
86
|
+
errors
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
errors.amounts = 'At least one currency and amount is required';
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
valid: Object.keys(errors).length === 0,
|
|
96
|
+
errors
|
|
97
|
+
};
|
|
98
|
+
},
|
|
99
|
+
render: (node) => {
|
|
100
|
+
var _a;
|
|
101
|
+
const transferAirtimeAction = (_a = node.actions) === null || _a === void 0 ? void 0 : _a.find((action) => action.type === 'transfer_airtime');
|
|
102
|
+
if (!transferAirtimeAction || !transferAirtimeAction.amounts) {
|
|
103
|
+
return html `<div class="body">Configure airtime transfer</div>`;
|
|
104
|
+
}
|
|
105
|
+
const amounts = transferAirtimeAction.amounts;
|
|
106
|
+
const currencies = Object.keys(amounts);
|
|
107
|
+
if (currencies.length === 0) {
|
|
108
|
+
return html `<div class="body">Configure airtime transfer</div>`;
|
|
109
|
+
}
|
|
110
|
+
// Display the first currency amount, with indicator if there are more
|
|
111
|
+
const firstCurrency = currencies[0];
|
|
112
|
+
const firstAmount = amounts[firstCurrency];
|
|
113
|
+
const moreCount = currencies.length - 1;
|
|
114
|
+
return html `
|
|
115
|
+
<div class="body">
|
|
116
|
+
${firstCurrency}
|
|
117
|
+
${firstAmount}${moreCount > 0
|
|
118
|
+
? html ` <span style="color: #999;">+${moreCount} more</span>`
|
|
119
|
+
: ''}
|
|
120
|
+
</div>
|
|
121
|
+
`;
|
|
122
|
+
},
|
|
123
|
+
toFormData: (node) => {
|
|
124
|
+
var _a, _b;
|
|
125
|
+
// Extract data from the existing node structure
|
|
126
|
+
const transferAirtimeAction = (_a = node.actions) === null || _a === void 0 ? void 0 : _a.find((action) => action.type === 'transfer_airtime');
|
|
127
|
+
const amounts = [];
|
|
128
|
+
if (transferAirtimeAction && transferAirtimeAction.amounts) {
|
|
129
|
+
Object.entries(transferAirtimeAction.amounts).forEach(([currency, amount]) => {
|
|
130
|
+
var _a;
|
|
131
|
+
amounts.push({
|
|
132
|
+
currency: [
|
|
133
|
+
{
|
|
134
|
+
value: currency,
|
|
135
|
+
name: ((_a = CURRENCIES[currency]) === null || _a === void 0 ? void 0 : _a.name)
|
|
136
|
+
? `${CURRENCIES[currency].name} (${currency})`
|
|
137
|
+
: currency
|
|
138
|
+
}
|
|
139
|
+
],
|
|
140
|
+
amount: String(amount)
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
uuid: node.uuid,
|
|
146
|
+
amounts: amounts,
|
|
147
|
+
result_name: ((_b = node.router) === null || _b === void 0 ? void 0 : _b.result_name) || ''
|
|
148
|
+
};
|
|
149
|
+
},
|
|
150
|
+
fromFormData: (formData, originalNode) => {
|
|
151
|
+
var _a, _b, _c;
|
|
152
|
+
// Get user amounts and convert to amounts object
|
|
153
|
+
const amountsObject = {};
|
|
154
|
+
if (formData.amounts && Array.isArray(formData.amounts)) {
|
|
155
|
+
formData.amounts.forEach((item) => {
|
|
156
|
+
var _a;
|
|
157
|
+
if (!(item === null || item === void 0 ? void 0 : item.currency) || !(item === null || item === void 0 ? void 0 : item.amount) || item.amount.trim() === '') {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
// Extract currency code from selection (handle both array and object formats)
|
|
161
|
+
let currencyCode;
|
|
162
|
+
if (Array.isArray(item.currency) && item.currency.length > 0) {
|
|
163
|
+
currencyCode = item.currency[0].value;
|
|
164
|
+
}
|
|
165
|
+
else if (typeof item.currency === 'string') {
|
|
166
|
+
currencyCode = item.currency;
|
|
167
|
+
}
|
|
168
|
+
else if ((_a = item.currency) === null || _a === void 0 ? void 0 : _a.value) {
|
|
169
|
+
currencyCode = item.currency.value;
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
const amount = parseFloat(item.amount.trim());
|
|
175
|
+
if (!isNaN(amount) && amount > 0) {
|
|
176
|
+
amountsObject[currencyCode] = amount;
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
// Find existing transfer_airtime action to preserve its UUID
|
|
181
|
+
const existingTransferAirtimeAction = (_a = originalNode.actions) === null || _a === void 0 ? void 0 : _a.find((action) => action.type === 'transfer_airtime');
|
|
182
|
+
const transferAirtimeUuid = (existingTransferAirtimeAction === null || existingTransferAirtimeAction === void 0 ? void 0 : existingTransferAirtimeAction.uuid) || generateUUID();
|
|
183
|
+
// Create transfer_airtime action
|
|
184
|
+
const transferAirtimeAction = {
|
|
185
|
+
type: 'transfer_airtime',
|
|
186
|
+
uuid: transferAirtimeUuid,
|
|
187
|
+
amounts: amountsObject
|
|
188
|
+
};
|
|
189
|
+
// Create categories and exits for Success and Failure
|
|
190
|
+
const existingCategories = ((_b = originalNode.router) === null || _b === void 0 ? void 0 : _b.categories) || [];
|
|
191
|
+
const existingExits = originalNode.exits || [];
|
|
192
|
+
const existingCases = ((_c = originalNode.router) === null || _c === void 0 ? void 0 : _c.cases) || [];
|
|
193
|
+
const { router, exits } = createSuccessFailureRouter('@locals._new_transfer', {
|
|
194
|
+
type: 'has_text',
|
|
195
|
+
arguments: []
|
|
196
|
+
}, existingCategories, existingExits, existingCases);
|
|
197
|
+
// Add result_name if provided
|
|
198
|
+
const finalRouter = { ...router };
|
|
199
|
+
if (formData.result_name && formData.result_name.trim() !== '') {
|
|
200
|
+
finalRouter.result_name = formData.result_name.trim();
|
|
201
|
+
}
|
|
202
|
+
// Return the complete node
|
|
203
|
+
return {
|
|
204
|
+
uuid: originalNode.uuid,
|
|
205
|
+
actions: [transferAirtimeAction],
|
|
206
|
+
router: finalRouter,
|
|
207
|
+
exits: exits
|
|
208
|
+
};
|
|
209
|
+
},
|
|
210
|
+
// Localization support for categories
|
|
211
|
+
localizable: 'categories',
|
|
212
|
+
toLocalizationFormData: categoriesToLocalizationFormData,
|
|
213
|
+
fromLocalizationFormData: localizationFormDataToCategories
|
|
8
214
|
};
|
|
9
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,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAc,MAAM,UAAU,CAAC;AAE9C,MAAM,CAAC,MAAM,gBAAgB,GAAe;IAC1C,IAAI,EAAE,kBAAkB;IACxB,IAAI,EAAE,2BAA2B;IACjC,KAAK,EAAE,MAAM,CAAC,IAAI;IAClB,MAAM,EAAE,gBAAgB;CACzB,CAAC","sourcesContent":["import { transfer_airtime } from '../actions/transfer_airtime';\nimport { COLORS, NodeConfig } from '../types';\n\nexport const split_by_airtime: NodeConfig = {\n type: 'split_by_airtime',\n name: 'Split by Airtime Transfer',\n color: COLORS.send,\n action: transfer_airtime\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,156 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SPLIT_GROUPS, FlowTypes } from '../types';
|
|
2
|
+
import { createRulesRouter } from '../../utils';
|
|
3
|
+
import { getWaitForResponseOperators, operatorsToSelectOptions, getOperatorConfig } from '../operators';
|
|
4
|
+
import { resultNameField, categoriesToLocalizationFormData, localizationFormDataToCategories } from './shared';
|
|
5
|
+
import { createRulesArrayConfig, extractUserRules, casesToFormRules } from './shared-rules';
|
|
6
|
+
import { SCHEMES } from '../utils';
|
|
7
|
+
import { html } from 'lit';
|
|
8
|
+
// System contact properties that can be split on
|
|
9
|
+
export const CONTACT_PROPERTIES = {
|
|
10
|
+
name: { id: 'name', name: 'Name', type: 'property' },
|
|
11
|
+
language: { id: 'language', name: 'Language', type: 'property' },
|
|
12
|
+
status: { id: 'status', name: 'Status', type: 'property' },
|
|
13
|
+
channel: { id: 'channel', name: 'Channel', type: 'property' }
|
|
14
|
+
};
|
|
15
|
+
// Helper to get operand for the selected field
|
|
16
|
+
const getOperandForField = (field) => {
|
|
17
|
+
// For URN schemes, split on the URN path (the actual ID value like Facebook ID)
|
|
18
|
+
// Note: This is different from split_by_scheme which splits on the scheme type itself
|
|
19
|
+
if (field.type === 'scheme') {
|
|
20
|
+
// field.id or field.value will be the scheme name like 'facebook', 'whatsapp', etc
|
|
21
|
+
const schemeId = field.id || field.value;
|
|
22
|
+
return `@(default(urn_parts(urns.${schemeId}).path, ""))`;
|
|
23
|
+
}
|
|
24
|
+
// For system properties, use the id
|
|
25
|
+
if (field.type === 'property') {
|
|
26
|
+
return `@contact.${field.id}`;
|
|
27
|
+
}
|
|
28
|
+
// Fallback to key
|
|
29
|
+
return `@fields.${field.key}`;
|
|
30
|
+
};
|
|
2
31
|
export const split_by_contact_field = {
|
|
3
32
|
type: 'split_by_contact_field',
|
|
4
|
-
name: 'Split by
|
|
5
|
-
|
|
33
|
+
name: 'Split by Contact Field',
|
|
34
|
+
group: SPLIT_GROUPS.split,
|
|
35
|
+
flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
|
|
36
|
+
dialogSize: 'large',
|
|
37
|
+
form: {
|
|
38
|
+
field: {
|
|
39
|
+
type: 'select',
|
|
40
|
+
required: true,
|
|
41
|
+
searchable: true,
|
|
42
|
+
clearable: false,
|
|
43
|
+
endpoint: '/api/v2/fields.json',
|
|
44
|
+
valueKey: 'key',
|
|
45
|
+
nameKey: 'name',
|
|
46
|
+
placeholder: 'Select a field...',
|
|
47
|
+
// Provide system properties as fixed options at the top
|
|
48
|
+
options: [
|
|
49
|
+
...Object.values(CONTACT_PROPERTIES).map((prop) => ({
|
|
50
|
+
value: prop.id,
|
|
51
|
+
name: prop.name,
|
|
52
|
+
type: prop.type
|
|
53
|
+
})),
|
|
54
|
+
// Add all URN scheme options (they represent splitting on the URN value, like Facebook ID)
|
|
55
|
+
...SCHEMES.filter((scheme) => !scheme.excludeFromSplit).map((scheme) => ({
|
|
56
|
+
value: scheme.scheme,
|
|
57
|
+
name: scheme.path,
|
|
58
|
+
type: 'scheme'
|
|
59
|
+
}))
|
|
60
|
+
]
|
|
61
|
+
},
|
|
62
|
+
rules: createRulesArrayConfig(operatorsToSelectOptions(getWaitForResponseOperators()), 'Define rules to split the contact field into categories'),
|
|
63
|
+
result_name: resultNameField
|
|
64
|
+
},
|
|
65
|
+
layout: ['field', 'rules', 'result_name'],
|
|
66
|
+
validate: (formData) => {
|
|
67
|
+
const errors = {};
|
|
68
|
+
if (!formData.field || formData.field.length === 0) {
|
|
69
|
+
errors.field = 'A field is required';
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
valid: Object.keys(errors).length === 0,
|
|
73
|
+
errors
|
|
74
|
+
};
|
|
75
|
+
},
|
|
76
|
+
toFormData: (node, nodeUI) => {
|
|
77
|
+
var _a, _b;
|
|
78
|
+
// Get the field from the UI config operand (source of truth)
|
|
79
|
+
const field = ((_a = nodeUI === null || nodeUI === void 0 ? void 0 : nodeUI.config) === null || _a === void 0 ? void 0 : _a.operand) || CONTACT_PROPERTIES.name;
|
|
80
|
+
// Extract rules from router cases using shared function
|
|
81
|
+
const rules = casesToFormRules(node);
|
|
82
|
+
return {
|
|
83
|
+
uuid: node.uuid,
|
|
84
|
+
field: [field],
|
|
85
|
+
rules: rules,
|
|
86
|
+
result_name: ((_b = node.router) === null || _b === void 0 ? void 0 : _b.result_name) || ''
|
|
87
|
+
};
|
|
88
|
+
},
|
|
89
|
+
fromFormData: (formData, originalNode) => {
|
|
90
|
+
var _a, _b, _c;
|
|
91
|
+
// Get selected field (it's an array from the select component)
|
|
92
|
+
const selectedField = (_a = formData.field) === null || _a === void 0 ? void 0 : _a[0];
|
|
93
|
+
if (!selectedField) {
|
|
94
|
+
return originalNode;
|
|
95
|
+
}
|
|
96
|
+
// Get operand for the selected field
|
|
97
|
+
const operand = getOperandForField(selectedField);
|
|
98
|
+
// Get user rules using shared extraction function
|
|
99
|
+
const userRules = extractUserRules(formData);
|
|
100
|
+
// Get existing router data for preservation
|
|
101
|
+
const existingCategories = ((_b = originalNode.router) === null || _b === void 0 ? void 0 : _b.categories) || [];
|
|
102
|
+
const existingExits = originalNode.exits || [];
|
|
103
|
+
const existingCases = ((_c = originalNode.router) === null || _c === void 0 ? void 0 : _c.cases) || [];
|
|
104
|
+
// Create router and exits using existing data when possible
|
|
105
|
+
const { router, exits } = createRulesRouter(operand, userRules, getOperatorConfig, existingCategories, existingExits, existingCases);
|
|
106
|
+
// Build final router with result_name
|
|
107
|
+
const finalRouter = {
|
|
108
|
+
...router
|
|
109
|
+
};
|
|
110
|
+
// Only set result_name if provided
|
|
111
|
+
if (formData.result_name && formData.result_name.trim() !== '') {
|
|
112
|
+
finalRouter.result_name = formData.result_name.trim();
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
...originalNode,
|
|
116
|
+
router: finalRouter,
|
|
117
|
+
exits: exits
|
|
118
|
+
};
|
|
119
|
+
},
|
|
120
|
+
toUIConfig: (formData) => {
|
|
121
|
+
var _a;
|
|
122
|
+
// Get selected field (it's an array from the select component)
|
|
123
|
+
const selectedField = (_a = formData.field) === null || _a === void 0 ? void 0 : _a[0];
|
|
124
|
+
if (!selectedField) {
|
|
125
|
+
return {};
|
|
126
|
+
}
|
|
127
|
+
// For scheme types, the id should be the scheme name (facebook, whatsapp, etc)
|
|
128
|
+
// For custom fields, the id should be the field key
|
|
129
|
+
// For system properties, the id should be the property id
|
|
130
|
+
let operandId = selectedField.id || selectedField.value || selectedField.key;
|
|
131
|
+
// If this is a scheme type, ensure we use the scheme name as the id
|
|
132
|
+
if (selectedField.type === 'scheme') {
|
|
133
|
+
operandId = selectedField.value || selectedField.id;
|
|
134
|
+
}
|
|
135
|
+
let type = selectedField.type;
|
|
136
|
+
if (type !== 'property' && type !== 'scheme') {
|
|
137
|
+
type = 'field';
|
|
138
|
+
}
|
|
139
|
+
// Return UI config with operand information for persistence
|
|
140
|
+
return {
|
|
141
|
+
operand: {
|
|
142
|
+
id: operandId,
|
|
143
|
+
name: selectedField.name || selectedField.label,
|
|
144
|
+
type
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
},
|
|
148
|
+
renderTitle: (node, nodeUI) => {
|
|
149
|
+
return html `<div>Split by ${nodeUI.config.operand.name}</div>`;
|
|
150
|
+
},
|
|
151
|
+
// Localization support for categories
|
|
152
|
+
localizable: 'categories',
|
|
153
|
+
toLocalizationFormData: categoriesToLocalizationFormData,
|
|
154
|
+
fromLocalizationFormData: localizationFormDataToCategories
|
|
6
155
|
};
|
|
7
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":"AAAA,OAAO,EAAE,MAAM,EAAc,MAAM,UAAU,CAAC;AAE9C,MAAM,CAAC,MAAM,sBAAsB,GAAe;IAChD,IAAI,EAAE,wBAAwB;IAC9B,IAAI,EAAE,+BAA+B;IACrC,KAAK,EAAE,MAAM,CAAC,KAAK;CACpB,CAAC","sourcesContent":["import { COLORS, NodeConfig } from '../types';\n\nexport const split_by_contact_field: NodeConfig = {\n type: 'split_by_contact_field',\n name: 'Split by <Contact Field Name>',\n color: COLORS.split\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"]}
|