@nyaruka/temba-components 0.131.0 → 0.131.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/publish.yml +4 -1
- package/CHANGELOG.md +67 -1
- package/demo/data/flows/food-order.json +2 -2
- package/demo/data/flows/sample-flow.json +74 -125
- package/dist/static/svg/index.svg +1 -1
- package/dist/temba-components.js +1156 -619
- 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/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 +327 -19
- package/out-tsc/src/flow/CanvasNode.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +562 -66
- package/out-tsc/src/flow/Editor.js.map +1 -1
- package/out-tsc/src/flow/NodeEditor.js +240 -93
- package/out-tsc/src/flow/NodeEditor.js.map +1 -1
- package/out-tsc/src/flow/NodeTypeSelector.js +499 -0
- package/out-tsc/src/flow/NodeTypeSelector.js.map +1 -0
- package/out-tsc/src/flow/actions/add_contact_groups.js +3 -3
- package/out-tsc/src/flow/actions/add_contact_groups.js.map +1 -1
- package/out-tsc/src/flow/actions/add_contact_urn.js +62 -4
- package/out-tsc/src/flow/actions/add_contact_urn.js.map +1 -1
- package/out-tsc/src/flow/actions/add_input_labels.js +3 -3
- package/out-tsc/src/flow/actions/add_input_labels.js.map +1 -1
- package/out-tsc/src/flow/actions/play_audio.js +2 -2
- package/out-tsc/src/flow/actions/play_audio.js.map +1 -1
- package/out-tsc/src/flow/actions/remove_contact_groups.js +6 -5
- package/out-tsc/src/flow/actions/remove_contact_groups.js.map +1 -1
- package/out-tsc/src/flow/actions/request_optin.js +2 -2
- package/out-tsc/src/flow/actions/request_optin.js.map +1 -1
- package/out-tsc/src/flow/actions/say_msg.js +2 -2
- package/out-tsc/src/flow/actions/say_msg.js.map +1 -1
- package/out-tsc/src/flow/actions/send_broadcast.js +76 -23
- package/out-tsc/src/flow/actions/send_broadcast.js.map +1 -1
- package/out-tsc/src/flow/actions/send_email.js +4 -5
- package/out-tsc/src/flow/actions/send_email.js.map +1 -1
- package/out-tsc/src/flow/actions/send_msg.js +9 -19
- package/out-tsc/src/flow/actions/send_msg.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_channel.js +5 -9
- package/out-tsc/src/flow/actions/set_contact_channel.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_field.js +19 -20
- package/out-tsc/src/flow/actions/set_contact_field.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_language.js +2 -2
- package/out-tsc/src/flow/actions/set_contact_language.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_name.js +2 -12
- package/out-tsc/src/flow/actions/set_contact_name.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_status.js +2 -2
- package/out-tsc/src/flow/actions/set_contact_status.js.map +1 -1
- package/out-tsc/src/flow/actions/set_run_result.js +3 -3
- package/out-tsc/src/flow/actions/set_run_result.js.map +1 -1
- package/out-tsc/src/flow/actions/start_session.js +180 -6
- package/out-tsc/src/flow/actions/start_session.js.map +1 -1
- package/out-tsc/src/flow/config.js +11 -15
- 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 +17 -0
- package/out-tsc/src/flow/nodes/shared.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_airtime.js +205 -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 +147 -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 +68 -2
- package/out-tsc/src/flow/nodes/split_by_expression.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_groups.js +12 -9
- package/out-tsc/src/flow/nodes/split_by_groups.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_intent.js +7 -0
- package/out-tsc/src/flow/nodes/split_by_intent.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_llm.js +3 -2
- package/out-tsc/src/flow/nodes/split_by_llm.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_llm_categorize.js +2 -2
- package/out-tsc/src/flow/nodes/split_by_llm_categorize.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_random.js +3 -3
- package/out-tsc/src/flow/nodes/split_by_random.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_resthook.js +108 -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 +206 -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 +153 -2
- package/out-tsc/src/flow/nodes/split_by_scheme.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_subflow.js +6 -4
- package/out-tsc/src/flow/nodes/split_by_subflow.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_ticket.js +3 -2
- package/out-tsc/src/flow/nodes/split_by_ticket.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_webhook.js +3 -2
- package/out-tsc/src/flow/nodes/split_by_webhook.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_audio.js +2 -2
- package/out-tsc/src/flow/nodes/wait_for_audio.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_digits.js +2 -2
- package/out-tsc/src/flow/nodes/wait_for_digits.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_image.js +2 -2
- package/out-tsc/src/flow/nodes/wait_for_image.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_location.js +2 -2
- package/out-tsc/src/flow/nodes/wait_for_location.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_menu.js +2 -2
- package/out-tsc/src/flow/nodes/wait_for_menu.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_response.js +32 -567
- package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_video.js +2 -2
- package/out-tsc/src/flow/nodes/wait_for_video.js.map +1 -1
- package/out-tsc/src/flow/types.js +71 -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/ContactSearch.js +1 -1
- package/out-tsc/src/form/ContactSearch.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/list/SortableList.js +98 -33
- package/out-tsc/src/list/SortableList.js.map +1 -1
- package/out-tsc/src/live/ContactChat.js +15 -18
- package/out-tsc/src/live/ContactChat.js.map +1 -1
- package/out-tsc/src/store/AppState.js +53 -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 +4 -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-flow-editor-node.test.js +85 -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-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 +115 -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 +2 -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/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/events.ts +2 -6
- package/src/flow/CanvasMenu.ts +217 -0
- package/src/flow/CanvasNode.ts +408 -10
- package/src/flow/Editor.ts +683 -44
- package/src/flow/NodeEditor.ts +304 -125
- package/src/flow/NodeTypeSelector.ts +592 -0
- package/src/flow/actions/add_contact_groups.ts +4 -4
- package/src/flow/actions/add_contact_urn.ts +76 -4
- package/src/flow/actions/add_input_labels.ts +4 -4
- package/src/flow/actions/play_audio.ts +2 -2
- package/src/flow/actions/remove_contact_groups.ts +14 -6
- package/src/flow/actions/request_optin.ts +2 -2
- package/src/flow/actions/say_msg.ts +2 -2
- package/src/flow/actions/send_broadcast.ts +85 -23
- package/src/flow/actions/send_email.ts +10 -6
- package/src/flow/actions/send_msg.ts +22 -32
- package/src/flow/actions/set_contact_channel.ts +5 -11
- package/src/flow/actions/set_contact_field.ts +20 -25
- package/src/flow/actions/set_contact_language.ts +9 -4
- package/src/flow/actions/set_contact_name.ts +3 -15
- package/src/flow/actions/set_contact_status.ts +3 -3
- package/src/flow/actions/set_run_result.ts +4 -4
- package/src/flow/actions/start_session.ts +208 -6
- package/src/flow/config.ts +13 -15
- package/src/flow/currencies.ts +51 -0
- package/src/flow/nodes/shared-rules.ts +301 -0
- package/src/flow/nodes/shared.ts +18 -0
- package/src/flow/nodes/split_by_airtime.ts +238 -5
- package/src/flow/nodes/split_by_contact_field.ts +185 -3
- package/src/flow/nodes/split_by_expression.ts +94 -2
- package/src/flow/nodes/split_by_groups.ts +15 -10
- package/src/flow/nodes/split_by_intent.ts +7 -0
- package/src/flow/nodes/split_by_llm.ts +4 -3
- package/src/flow/nodes/split_by_llm_categorize.ts +4 -4
- package/src/flow/nodes/split_by_random.ts +5 -5
- package/src/flow/nodes/split_by_resthook.ts +130 -0
- package/src/flow/nodes/split_by_run_result.ts +249 -3
- package/src/flow/nodes/split_by_scheme.ts +192 -2
- package/src/flow/nodes/split_by_subflow.ts +6 -4
- package/src/flow/nodes/split_by_ticket.ts +4 -3
- package/src/flow/nodes/split_by_webhook.ts +6 -5
- package/src/flow/nodes/wait_for_audio.ts +2 -2
- package/src/flow/nodes/wait_for_digits.ts +2 -2
- package/src/flow/nodes/wait_for_image.ts +2 -2
- package/src/flow/nodes/wait_for_location.ts +2 -2
- package/src/flow/nodes/wait_for_menu.ts +2 -2
- package/src/flow/nodes/wait_for_response.ts +48 -679
- package/src/flow/nodes/wait_for_video.ts +2 -2
- package/src/flow/types.ts +109 -23
- package/src/flow/utils.ts +108 -14
- package/src/form/ContactSearch.ts +1 -1
- package/src/form/FieldRenderer.ts +2 -4
- package/src/interfaces.ts +3 -0
- package/src/list/SortableList.ts +109 -34
- package/src/live/ContactChat.ts +15 -18
- package/src/store/AppState.ts +69 -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/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 +4 -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-flow-editor-node.test.ts +102 -2
- package/test/temba-flow-editor.test.ts +7 -8
- package/test/temba-node-editor.test.ts +3 -1
- package/test/temba-node-type-selector.test.ts +152 -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 +2 -0
- package/test-assets/contacts/history.json +14 -20
- package/web-dev-server.config.mjs +3 -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/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
|
@@ -2,6 +2,7 @@ import { __decorate } from "tslib";
|
|
|
2
2
|
import { css, html } from 'lit';
|
|
3
3
|
import { repeat } from 'lit/directives/repeat.js';
|
|
4
4
|
import { ACTION_CONFIG, NODE_CONFIG } from './config';
|
|
5
|
+
import { ACTION_GROUP_METADATA, SPLIT_GROUP_METADATA } from './types';
|
|
5
6
|
import { property } from 'lit/decorators.js';
|
|
6
7
|
import { RapidElement } from '../RapidElement';
|
|
7
8
|
import { getClasses } from '../utils';
|
|
@@ -126,7 +127,7 @@ export class CanvasNode extends RapidElement {
|
|
|
126
127
|
pointer-events: auto; /* Ensure drag handle can receive events */
|
|
127
128
|
}
|
|
128
129
|
.title-spacer {
|
|
129
|
-
width:
|
|
130
|
+
width: 1.8em;
|
|
130
131
|
|
|
131
132
|
}
|
|
132
133
|
|
|
@@ -305,6 +306,36 @@ export class CanvasNode extends RapidElement {
|
|
|
305
306
|
border-top-left-radius: var(--curvature);
|
|
306
307
|
border-top-right-radius: var(--curvature);
|
|
307
308
|
}
|
|
309
|
+
|
|
310
|
+
/* Add action button */
|
|
311
|
+
.add-action-button {
|
|
312
|
+
position: absolute;
|
|
313
|
+
bottom: 0.5em;
|
|
314
|
+
right: 0.5em;
|
|
315
|
+
width: 1.5em;
|
|
316
|
+
height: 1.5em;
|
|
317
|
+
border-radius: 50%;
|
|
318
|
+
background: var(--color-primary, #3b82f6);
|
|
319
|
+
color: white;
|
|
320
|
+
display: flex;
|
|
321
|
+
align-items: center;
|
|
322
|
+
justify-content: center;
|
|
323
|
+
cursor: pointer;
|
|
324
|
+
opacity: 0;
|
|
325
|
+
transition: opacity 200ms ease-in-out;
|
|
326
|
+
z-index: 10;
|
|
327
|
+
pointer-events: auto;
|
|
328
|
+
font-size: 0.9em;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.node.execute-actions:hover .add-action-button {
|
|
332
|
+
opacity: 0.8;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.add-action-button:hover {
|
|
336
|
+
opacity: 1 !important;
|
|
337
|
+
transform: scale(1.1);
|
|
338
|
+
}
|
|
308
339
|
}`;
|
|
309
340
|
}
|
|
310
341
|
constructor() {
|
|
@@ -323,10 +354,34 @@ export class CanvasNode extends RapidElement {
|
|
|
323
354
|
// Track node click state to distinguish from drag
|
|
324
355
|
this.nodeClickStartPos = null;
|
|
325
356
|
this.pendingNodeClick = null;
|
|
357
|
+
// Track the height of the action being dragged (captured at drag start)
|
|
358
|
+
this.draggedActionHeight = 0;
|
|
359
|
+
// Track external action drag (action being dragged from another node)
|
|
360
|
+
this.externalDragInfo = null;
|
|
326
361
|
this.handleActionOrderChanged = this.handleActionOrderChanged.bind(this);
|
|
362
|
+
this.handleActionDragStart = this.handleActionDragStart.bind(this);
|
|
363
|
+
this.handleActionDragExternal = this.handleActionDragExternal.bind(this);
|
|
364
|
+
this.handleActionDragInternal = this.handleActionDragInternal.bind(this);
|
|
365
|
+
this.handleActionDragStop = this.handleActionDragStop.bind(this);
|
|
366
|
+
this.handleExternalActionDragOver =
|
|
367
|
+
this.handleExternalActionDragOver.bind(this);
|
|
368
|
+
this.handleExternalActionDrop = this.handleExternalActionDrop.bind(this);
|
|
369
|
+
this.handleExternalActionDragLeave =
|
|
370
|
+
this.handleExternalActionDragLeave.bind(this);
|
|
371
|
+
this.handleActionShowGhost = this.handleActionShowGhost.bind(this);
|
|
372
|
+
this.handleActionHideGhost = this.handleActionHideGhost.bind(this);
|
|
373
|
+
}
|
|
374
|
+
connectedCallback() {
|
|
375
|
+
super.connectedCallback();
|
|
376
|
+
// Listen for external action drag events from Editor
|
|
377
|
+
this.addEventListener('action-drag-over', this.handleExternalActionDragOver);
|
|
378
|
+
this.addEventListener('action-drop', this.handleExternalActionDrop);
|
|
379
|
+
this.addEventListener('action-drag-leave', this.handleExternalActionDragLeave);
|
|
380
|
+
this.addEventListener('action-show-ghost', this.handleActionShowGhost);
|
|
381
|
+
this.addEventListener('action-hide-ghost', this.handleActionHideGhost);
|
|
327
382
|
}
|
|
328
383
|
updated(changes) {
|
|
329
|
-
var
|
|
384
|
+
var _b;
|
|
330
385
|
super.updated(changes);
|
|
331
386
|
if (changes.has('node')) {
|
|
332
387
|
// Only proceed if plumber is available (for tests that don't set it up)
|
|
@@ -348,13 +403,19 @@ export class CanvasNode extends RapidElement {
|
|
|
348
403
|
const ele = this.parentElement;
|
|
349
404
|
if (ele) {
|
|
350
405
|
const rect = ele.getBoundingClientRect();
|
|
351
|
-
(
|
|
406
|
+
(_b = getStore()) === null || _b === void 0 ? void 0 : _b.getState().expandCanvas(this.ui.position.left + rect.width, this.ui.position.top + rect.height);
|
|
352
407
|
}
|
|
353
408
|
}
|
|
354
409
|
}
|
|
355
410
|
disconnectedCallback() {
|
|
356
411
|
// Remove the event listener when the component is removed
|
|
357
412
|
super.disconnectedCallback();
|
|
413
|
+
// Remove external drag event listeners
|
|
414
|
+
this.removeEventListener('action-drag-over', this.handleExternalActionDragOver);
|
|
415
|
+
this.removeEventListener('action-drop', this.handleExternalActionDrop);
|
|
416
|
+
this.removeEventListener('action-drag-leave', this.handleExternalActionDragLeave);
|
|
417
|
+
this.removeEventListener('action-show-ghost', this.handleActionShowGhost);
|
|
418
|
+
this.removeEventListener('action-hide-ghost', this.handleActionHideGhost);
|
|
358
419
|
// Clear any pending exit removal timeouts
|
|
359
420
|
this.exitRemovalTimeouts.forEach((timeoutId) => {
|
|
360
421
|
clearTimeout(timeoutId);
|
|
@@ -401,7 +462,7 @@ export class CanvasNode extends RapidElement {
|
|
|
401
462
|
this.exitRemovalTimeouts.set(exitId, timeoutId);
|
|
402
463
|
}
|
|
403
464
|
disconnectExit(exit) {
|
|
404
|
-
var
|
|
465
|
+
var _b;
|
|
405
466
|
const exitId = exit.uuid;
|
|
406
467
|
// Clear the UI state
|
|
407
468
|
this.exitRemovingState.delete(exitId);
|
|
@@ -420,7 +481,7 @@ export class CanvasNode extends RapidElement {
|
|
|
420
481
|
const updatedExits = this.node.exits.map((e) => e.uuid === exitId ? updatedExit : e);
|
|
421
482
|
// Update the node
|
|
422
483
|
const updatedNode = { ...this.node, exits: updatedExits };
|
|
423
|
-
(
|
|
484
|
+
(_b = getStore()) === null || _b === void 0 ? void 0 : _b.getState().updateNode(this.node.uuid, updatedNode);
|
|
424
485
|
// Request update to reflect changes
|
|
425
486
|
this.requestUpdate();
|
|
426
487
|
}
|
|
@@ -450,7 +511,7 @@ export class CanvasNode extends RapidElement {
|
|
|
450
511
|
}
|
|
451
512
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
452
513
|
removeAction(action, _index) {
|
|
453
|
-
var
|
|
514
|
+
var _b;
|
|
454
515
|
const actionId = action.uuid;
|
|
455
516
|
// Clear the UI state
|
|
456
517
|
this.actionRemovingState.delete(actionId);
|
|
@@ -470,7 +531,7 @@ export class CanvasNode extends RapidElement {
|
|
|
470
531
|
else {
|
|
471
532
|
// Update the node with remaining actions
|
|
472
533
|
const updatedNode = { ...this.node, actions: updatedActions };
|
|
473
|
-
(
|
|
534
|
+
(_b = getStore()) === null || _b === void 0 ? void 0 : _b.getState().updateNode(this.node.uuid, updatedNode);
|
|
474
535
|
// Request update to reflect changes
|
|
475
536
|
this.requestUpdate();
|
|
476
537
|
}
|
|
@@ -514,7 +575,7 @@ export class CanvasNode extends RapidElement {
|
|
|
514
575
|
});
|
|
515
576
|
}
|
|
516
577
|
handleActionOrderChanged(event) {
|
|
517
|
-
var
|
|
578
|
+
var _b;
|
|
518
579
|
const [fromIdx, toIdx] = event.detail.swap;
|
|
519
580
|
// swap our actions
|
|
520
581
|
const newActions = [...this.node.actions];
|
|
@@ -524,7 +585,73 @@ export class CanvasNode extends RapidElement {
|
|
|
524
585
|
// since the editor will update us from it's definition subscription
|
|
525
586
|
// but it makes testing a lot easier
|
|
526
587
|
this.node = { ...this.node, actions: newActions };
|
|
527
|
-
(
|
|
588
|
+
(_b = getStore()) === null || _b === void 0 ? void 0 : _b.getState().updateNode(this.node.uuid, { ...this.node, actions: newActions });
|
|
589
|
+
}
|
|
590
|
+
handleActionDragStart(event) {
|
|
591
|
+
// Capture the height of the action being dragged
|
|
592
|
+
const actionId = event.detail.id;
|
|
593
|
+
const actionElement = this.querySelector(`#${actionId}`);
|
|
594
|
+
if (actionElement) {
|
|
595
|
+
const rect = actionElement.getBoundingClientRect();
|
|
596
|
+
this.draggedActionHeight = rect.height;
|
|
597
|
+
}
|
|
598
|
+
else {
|
|
599
|
+
// Fallback to a reasonable default
|
|
600
|
+
this.draggedActionHeight = 60;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
handleActionDragExternal(event) {
|
|
604
|
+
// stop propagation of the original event from SortableList
|
|
605
|
+
event.stopPropagation();
|
|
606
|
+
// get the action being dragged
|
|
607
|
+
const actionId = event.detail.id;
|
|
608
|
+
const splitId = actionId.split('-');
|
|
609
|
+
if (splitId.length < 2 || isNaN(parseInt(splitId[1], 10))) {
|
|
610
|
+
// invalid format, do not proceed
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
const actionIndex = parseInt(splitId[1], 10);
|
|
614
|
+
const action = this.node.actions[actionIndex];
|
|
615
|
+
// fire event to editor to show canvas drop preview, including the captured height
|
|
616
|
+
this.fireCustomEvent(CustomEventType.DragExternal, {
|
|
617
|
+
action,
|
|
618
|
+
nodeUuid: this.node.uuid,
|
|
619
|
+
actionIndex,
|
|
620
|
+
mouseX: event.detail.mouseX,
|
|
621
|
+
mouseY: event.detail.mouseY,
|
|
622
|
+
actionHeight: this.draggedActionHeight
|
|
623
|
+
});
|
|
624
|
+
}
|
|
625
|
+
handleActionDragInternal(_event) {
|
|
626
|
+
// stop propagation of the original event from SortableList
|
|
627
|
+
_event.stopPropagation();
|
|
628
|
+
// fire event to editor to hide canvas drop preview
|
|
629
|
+
this.fireCustomEvent(CustomEventType.DragInternal, {});
|
|
630
|
+
}
|
|
631
|
+
handleActionDragStop(event) {
|
|
632
|
+
const isExternal = event.detail.isExternal;
|
|
633
|
+
if (isExternal) {
|
|
634
|
+
// stop propagation of the original event from SortableList
|
|
635
|
+
event.stopPropagation();
|
|
636
|
+
// get the action being dragged
|
|
637
|
+
const actionId = event.detail.id;
|
|
638
|
+
const split = actionId.split('-');
|
|
639
|
+
if (split.length < 2 || isNaN(Number(split[1]))) {
|
|
640
|
+
// invalid actionId format, do not proceed
|
|
641
|
+
return;
|
|
642
|
+
}
|
|
643
|
+
const actionIndex = parseInt(split[1], 10);
|
|
644
|
+
const action = this.node.actions[actionIndex];
|
|
645
|
+
// fire event to editor to create new node
|
|
646
|
+
this.fireCustomEvent(CustomEventType.DragStop, {
|
|
647
|
+
action,
|
|
648
|
+
nodeUuid: this.node.uuid,
|
|
649
|
+
actionIndex,
|
|
650
|
+
isExternal: true,
|
|
651
|
+
mouseX: event.detail.mouseX,
|
|
652
|
+
mouseY: event.detail.mouseY
|
|
653
|
+
});
|
|
654
|
+
}
|
|
528
655
|
}
|
|
529
656
|
handleActionMouseDown(event, action) {
|
|
530
657
|
// Don't handle clicks on the remove button, drag handle, or when action is in removing state
|
|
@@ -690,12 +817,138 @@ export class CanvasNode extends RapidElement {
|
|
|
690
817
|
this.nodeClickStartPos = null;
|
|
691
818
|
this.pendingNodeClick = null;
|
|
692
819
|
}
|
|
820
|
+
handleAddActionClick(event) {
|
|
821
|
+
event.preventDefault();
|
|
822
|
+
event.stopPropagation();
|
|
823
|
+
// Fire event to request adding a new action to this node
|
|
824
|
+
this.fireCustomEvent(CustomEventType.AddActionRequested, {
|
|
825
|
+
nodeUuid: this.node.uuid
|
|
826
|
+
});
|
|
827
|
+
}
|
|
828
|
+
calculateDropIndex(mouseY) {
|
|
829
|
+
var _b, _c;
|
|
830
|
+
// Get the sortable list element
|
|
831
|
+
const sortableList = this.querySelector('temba-sortable-list');
|
|
832
|
+
if (!sortableList || !this.node.actions)
|
|
833
|
+
return (_c = (_b = this.node.actions) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0;
|
|
834
|
+
// Get all action elements
|
|
835
|
+
const actionElements = Array.from(sortableList.querySelectorAll('.action.sortable'));
|
|
836
|
+
if (actionElements.length === 0) {
|
|
837
|
+
return 0;
|
|
838
|
+
}
|
|
839
|
+
// Find where to insert based on mouse Y position
|
|
840
|
+
for (let i = 0; i < actionElements.length; i++) {
|
|
841
|
+
const actionElement = actionElements[i];
|
|
842
|
+
const rect = actionElement.getBoundingClientRect();
|
|
843
|
+
const centerY = rect.top + rect.height / 2;
|
|
844
|
+
if (mouseY < centerY) {
|
|
845
|
+
return i;
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
// If past all elements, insert at the end
|
|
849
|
+
return actionElements.length;
|
|
850
|
+
}
|
|
851
|
+
handleExternalActionDragOver(event) {
|
|
852
|
+
// Only handle if this is an execute_actions node
|
|
853
|
+
if (this.ui.type !== 'execute_actions')
|
|
854
|
+
return;
|
|
855
|
+
const { action, sourceNodeUuid, actionIndex, mouseY, actionHeight } = event.detail;
|
|
856
|
+
// Don't accept drops from the same node
|
|
857
|
+
if (sourceNodeUuid === this.node.uuid)
|
|
858
|
+
return;
|
|
859
|
+
// Calculate where to drop
|
|
860
|
+
const dropIndex = this.calculateDropIndex(mouseY);
|
|
861
|
+
// Store the drag info
|
|
862
|
+
this.externalDragInfo = {
|
|
863
|
+
action,
|
|
864
|
+
sourceNodeUuid,
|
|
865
|
+
actionIndex,
|
|
866
|
+
dropIndex,
|
|
867
|
+
actionHeight: actionHeight || 60 // fallback to 60px if not provided
|
|
868
|
+
};
|
|
869
|
+
// Request update to show placeholder
|
|
870
|
+
this.requestUpdate();
|
|
871
|
+
}
|
|
872
|
+
handleExternalActionDragLeave(_event) {
|
|
873
|
+
// Clear external drag state when drag leaves this node
|
|
874
|
+
this.externalDragInfo = null;
|
|
875
|
+
this.requestUpdate();
|
|
876
|
+
}
|
|
877
|
+
handleActionShowGhost(_event) {
|
|
878
|
+
// Show the ghost element in the sortable list
|
|
879
|
+
const sortableList = this.querySelector('temba-sortable-list');
|
|
880
|
+
if (sortableList) {
|
|
881
|
+
const ghostElement = document.querySelector('.ghost');
|
|
882
|
+
if (ghostElement) {
|
|
883
|
+
ghostElement.style.display = 'block';
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
handleActionHideGhost(_event) {
|
|
888
|
+
// Hide the ghost element in the sortable list
|
|
889
|
+
const sortableList = this.querySelector('temba-sortable-list');
|
|
890
|
+
if (sortableList) {
|
|
891
|
+
const ghostElement = document.querySelector('.ghost');
|
|
892
|
+
if (ghostElement) {
|
|
893
|
+
ghostElement.style.display = 'none';
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
handleExternalActionDrop(event) {
|
|
898
|
+
var _b, _c, _d, _e, _f, _g;
|
|
899
|
+
// Only handle if this is an execute_actions node
|
|
900
|
+
if (this.ui.type !== 'execute_actions')
|
|
901
|
+
return;
|
|
902
|
+
const { action, sourceNodeUuid, actionIndex } = event.detail;
|
|
903
|
+
// Don't accept drops from the same node
|
|
904
|
+
if (sourceNodeUuid === this.node.uuid)
|
|
905
|
+
return;
|
|
906
|
+
// Get the drop index from our tracking state
|
|
907
|
+
const dropIndex = (_e = (_c = (_b = this.externalDragInfo) === null || _b === void 0 ? void 0 : _b.dropIndex) !== null && _c !== void 0 ? _c : (_d = this.node.actions) === null || _d === void 0 ? void 0 : _d.length) !== null && _e !== void 0 ? _e : 0;
|
|
908
|
+
// Clear external drag state
|
|
909
|
+
this.externalDragInfo = null;
|
|
910
|
+
// Remove the action from the source node
|
|
911
|
+
const store = getStore();
|
|
912
|
+
if (!store)
|
|
913
|
+
return;
|
|
914
|
+
const flowDefinition = store.getState().flowDefinition;
|
|
915
|
+
if (!flowDefinition)
|
|
916
|
+
return;
|
|
917
|
+
const sourceNode = flowDefinition.nodes.find((n) => n.uuid === sourceNodeUuid);
|
|
918
|
+
if (sourceNode) {
|
|
919
|
+
const updatedSourceActions = sourceNode.actions.filter((_a, idx) => idx !== actionIndex);
|
|
920
|
+
// If source node has no actions left, remove it
|
|
921
|
+
if (updatedSourceActions.length === 0) {
|
|
922
|
+
this.fireCustomEvent(CustomEventType.NodeDeleted, {
|
|
923
|
+
uuid: sourceNodeUuid
|
|
924
|
+
});
|
|
925
|
+
}
|
|
926
|
+
else {
|
|
927
|
+
// Update source node
|
|
928
|
+
const updatedSourceNode = {
|
|
929
|
+
...sourceNode,
|
|
930
|
+
actions: updatedSourceActions
|
|
931
|
+
};
|
|
932
|
+
(_f = getStore()) === null || _f === void 0 ? void 0 : _f.getState().updateNode(sourceNodeUuid, updatedSourceNode);
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
// Add the action to this node at the calculated position
|
|
936
|
+
const newActions = [...this.node.actions];
|
|
937
|
+
newActions.splice(dropIndex, 0, action);
|
|
938
|
+
const updatedNode = { ...this.node, actions: newActions };
|
|
939
|
+
(_g = getStore()) === null || _g === void 0 ? void 0 : _g.getState().updateNode(this.node.uuid, updatedNode);
|
|
940
|
+
// Request update
|
|
941
|
+
this.requestUpdate();
|
|
942
|
+
}
|
|
693
943
|
renderTitle(config, action, index, isRemoving = false) {
|
|
694
|
-
var
|
|
695
|
-
|
|
696
|
-
|
|
944
|
+
var _b, _c, _d;
|
|
945
|
+
const color = config.group
|
|
946
|
+
? (_b = ACTION_GROUP_METADATA[config.group]) === null || _b === void 0 ? void 0 : _b.color
|
|
947
|
+
: '#aaaaaa';
|
|
948
|
+
return html `<div class="cn-title" style="background:${color}">
|
|
949
|
+
${((_d = (_c = this.node) === null || _c === void 0 ? void 0 : _c.actions) === null || _d === void 0 ? void 0 : _d.length) > 1
|
|
697
950
|
? html `<temba-icon class="drag-handle" name="sort"></temba-icon>`
|
|
698
|
-
:
|
|
951
|
+
: html `<div class="title-spacer"></div>`}
|
|
699
952
|
|
|
700
953
|
<div class="name">${isRemoving ? 'Remove?' : config.name}</div>
|
|
701
954
|
<div
|
|
@@ -707,13 +960,25 @@ export class CanvasNode extends RapidElement {
|
|
|
707
960
|
</div>
|
|
708
961
|
</div>`;
|
|
709
962
|
}
|
|
710
|
-
renderNodeTitle(config, isRemoving = false) {
|
|
963
|
+
renderNodeTitle(config, node, ui, isRemoving = false) {
|
|
964
|
+
var _b, _c;
|
|
965
|
+
// Get color from the appropriate metadata (either ACTION or SPLIT)
|
|
966
|
+
const color = config.group
|
|
967
|
+
? ((_b = ACTION_GROUP_METADATA[config.group]) === null || _b === void 0 ? void 0 : _b.color) ||
|
|
968
|
+
((_c = SPLIT_GROUP_METADATA[config.group]) === null || _c === void 0 ? void 0 : _c.color)
|
|
969
|
+
: '#aaaaaa';
|
|
711
970
|
return html `<div
|
|
712
971
|
class="cn-title ${isRemoving ? 'removing' : ''}"
|
|
713
|
-
style="background:${
|
|
972
|
+
style="background:${color}"
|
|
714
973
|
>
|
|
715
974
|
<div class="title-spacer"></div>
|
|
716
|
-
<div class="name"
|
|
975
|
+
<div class="name">
|
|
976
|
+
${isRemoving
|
|
977
|
+
? 'Remove?'
|
|
978
|
+
: config.renderTitle
|
|
979
|
+
? config.renderTitle(node, ui)
|
|
980
|
+
: html `${config.name}`}
|
|
981
|
+
</div>
|
|
717
982
|
<div
|
|
718
983
|
class="remove-button"
|
|
719
984
|
@click=${(e) => this.handleNodeRemoveClick(e)}
|
|
@@ -723,6 +988,14 @@ export class CanvasNode extends RapidElement {
|
|
|
723
988
|
</div>
|
|
724
989
|
</div>`;
|
|
725
990
|
}
|
|
991
|
+
renderDropPlaceholder() {
|
|
992
|
+
var _b;
|
|
993
|
+
const height = ((_b = this.externalDragInfo) === null || _b === void 0 ? void 0 : _b.actionHeight) || 60;
|
|
994
|
+
return html `<div
|
|
995
|
+
class="action sortable drop-placeholder"
|
|
996
|
+
style="height: ${height}px; background: #f3f4f6; border: 2px dashed #d1d5db; border-radius: var(--curvature);"
|
|
997
|
+
></div>`;
|
|
998
|
+
}
|
|
726
999
|
renderAction(node, action, index) {
|
|
727
1000
|
const config = ACTION_CONFIG[action.type];
|
|
728
1001
|
const isRemoving = this.actionRemovingState.has(action.uuid);
|
|
@@ -760,6 +1033,25 @@ export class CanvasNode extends RapidElement {
|
|
|
760
1033
|
${action.type}
|
|
761
1034
|
</div>`;
|
|
762
1035
|
}
|
|
1036
|
+
renderActionsWithPlaceholder() {
|
|
1037
|
+
if (!this.externalDragInfo) {
|
|
1038
|
+
// No external drag, render normally
|
|
1039
|
+
return this.node.actions.map((action, index) => this.renderAction(this.node, action, index));
|
|
1040
|
+
}
|
|
1041
|
+
// Insert placeholder at the drop index
|
|
1042
|
+
const result = [];
|
|
1043
|
+
for (let i = 0; i < this.node.actions.length; i++) {
|
|
1044
|
+
if (i === this.externalDragInfo.dropIndex) {
|
|
1045
|
+
result.push(this.renderDropPlaceholder());
|
|
1046
|
+
}
|
|
1047
|
+
result.push(this.renderAction(this.node, this.node.actions[i], i));
|
|
1048
|
+
}
|
|
1049
|
+
// If dropping at the end, add placeholder after all actions
|
|
1050
|
+
if (this.externalDragInfo.dropIndex >= this.node.actions.length) {
|
|
1051
|
+
result.push(this.renderDropPlaceholder());
|
|
1052
|
+
}
|
|
1053
|
+
return result;
|
|
1054
|
+
}
|
|
763
1055
|
renderRouter(router, ui) {
|
|
764
1056
|
const nodeConfig = NODE_CONFIG[ui.type];
|
|
765
1057
|
if (nodeConfig) {
|
|
@@ -830,17 +1122,24 @@ export class CanvasNode extends RapidElement {
|
|
|
830
1122
|
@mouseup=${(e) => this.handleNodeMouseUp(e)}
|
|
831
1123
|
style="cursor: pointer;"
|
|
832
1124
|
>
|
|
833
|
-
${this.renderNodeTitle(nodeConfig, this.actionRemovingState.has(this.node.uuid))}
|
|
834
|
-
${nodeConfig.render
|
|
1125
|
+
${this.renderNodeTitle(nodeConfig, this.node, this.ui, this.actionRemovingState.has(this.node.uuid))}
|
|
1126
|
+
${nodeConfig.render
|
|
1127
|
+
? nodeConfig.render(this.node, this.ui)
|
|
1128
|
+
: null}
|
|
835
1129
|
</div>
|
|
836
1130
|
</div>`
|
|
837
1131
|
: this.node.actions.length > 0
|
|
838
1132
|
? this.ui.type === 'execute_actions'
|
|
839
1133
|
? html `<temba-sortable-list
|
|
840
1134
|
dragHandle="drag-handle"
|
|
1135
|
+
externalDrag
|
|
841
1136
|
@temba-order-changed="${this.handleActionOrderChanged}"
|
|
1137
|
+
@temba-drag-start="${this.handleActionDragStart}"
|
|
1138
|
+
@temba-drag-external="${this.handleActionDragExternal}"
|
|
1139
|
+
@temba-drag-internal="${this.handleActionDragInternal}"
|
|
1140
|
+
@temba-drag-stop="${this.handleActionDragStop}"
|
|
842
1141
|
>
|
|
843
|
-
${this.
|
|
1142
|
+
${this.renderActionsWithPlaceholder()}
|
|
844
1143
|
</temba-sortable-list>`
|
|
845
1144
|
: html `${this.node.actions.map((action, index) => this.renderAction(this.node, action, index))}`
|
|
846
1145
|
: ''}
|
|
@@ -850,6 +1149,15 @@ export class CanvasNode extends RapidElement {
|
|
|
850
1149
|
: html `<div class="action-exits">
|
|
851
1150
|
${repeat(this.node.exits, (exit) => exit.uuid, (exit) => this.renderExit(exit))}
|
|
852
1151
|
</div>`}
|
|
1152
|
+
${this.ui.type === 'execute_actions'
|
|
1153
|
+
? html `<div
|
|
1154
|
+
class="add-action-button"
|
|
1155
|
+
@click=${(e) => this.handleAddActionClick(e)}
|
|
1156
|
+
title="Add action"
|
|
1157
|
+
>
|
|
1158
|
+
<temba-icon name="add"></temba-icon>
|
|
1159
|
+
</div>`
|
|
1160
|
+
: ''}
|
|
853
1161
|
</div>
|
|
854
1162
|
`;
|
|
855
1163
|
}
|