@nyaruka/temba-components 0.139.0 → 0.141.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/cla.yml +1 -1
- package/.github/workflows/copilot-setup-steps.yml +6 -1
- package/.lintstagedrc.js +10 -0
- package/CHANGELOG.md +32 -0
- package/demo/data/flows/sample-flow.json +24 -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/temba-components.js +702 -338
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/display/Chat.js +10 -7
- package/out-tsc/src/display/Chat.js.map +1 -1
- package/out-tsc/src/display/Dropdown.js +3 -1
- package/out-tsc/src/display/Dropdown.js.map +1 -1
- package/out-tsc/src/display/FloatingTab.js +4 -4
- package/out-tsc/src/display/FloatingTab.js.map +1 -1
- package/out-tsc/src/display/Thumbnail.js +163 -5
- package/out-tsc/src/display/Thumbnail.js.map +1 -1
- package/out-tsc/src/flow/CanvasNode.js +65 -23
- package/out-tsc/src/flow/CanvasNode.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +369 -49
- package/out-tsc/src/flow/Editor.js.map +1 -1
- package/out-tsc/src/flow/NodeEditor.js +118 -10
- package/out-tsc/src/flow/NodeEditor.js.map +1 -1
- package/out-tsc/src/flow/Plumber.js +61 -14
- package/out-tsc/src/flow/Plumber.js.map +1 -1
- package/out-tsc/src/flow/StickyNote.js +13 -4
- package/out-tsc/src/flow/StickyNote.js.map +1 -1
- package/out-tsc/src/flow/actions/add_contact_groups.js +4 -1
- package/out-tsc/src/flow/actions/add_contact_groups.js.map +1 -1
- package/out-tsc/src/flow/actions/add_input_labels.js +4 -1
- package/out-tsc/src/flow/actions/add_input_labels.js.map +1 -1
- package/out-tsc/src/flow/actions/audio-player.js +112 -0
- package/out-tsc/src/flow/actions/audio-player.js.map +1 -0
- package/out-tsc/src/flow/actions/enter_flow.js +43 -0
- package/out-tsc/src/flow/actions/enter_flow.js.map +1 -0
- package/out-tsc/src/flow/actions/play_audio.js +57 -4
- package/out-tsc/src/flow/actions/play_audio.js.map +1 -1
- package/out-tsc/src/flow/actions/remove_contact_groups.js +6 -1
- package/out-tsc/src/flow/actions/remove_contact_groups.js.map +1 -1
- package/out-tsc/src/flow/actions/say_msg.js +86 -3
- package/out-tsc/src/flow/actions/say_msg.js.map +1 -1
- package/out-tsc/src/flow/actions/send_broadcast.js +6 -2
- package/out-tsc/src/flow/actions/send_broadcast.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_channel.js +13 -0
- package/out-tsc/src/flow/actions/set_contact_channel.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_status.js +7 -5
- package/out-tsc/src/flow/actions/set_contact_status.js.map +1 -1
- package/out-tsc/src/flow/actions/start_session.js +10 -3
- package/out-tsc/src/flow/actions/start_session.js.map +1 -1
- package/out-tsc/src/flow/config.js +11 -3
- package/out-tsc/src/flow/config.js.map +1 -1
- package/out-tsc/src/flow/nodes/shared-rules.js +1 -1
- package/out-tsc/src/flow/nodes/shared-rules.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_contact_field.js +18 -5
- package/out-tsc/src/flow/nodes/split_by_contact_field.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_expression.js +1 -1
- package/out-tsc/src/flow/nodes/split_by_expression.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_llm_categorize.js +0 -1
- package/out-tsc/src/flow/nodes/split_by_llm_categorize.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_random.js +0 -1
- package/out-tsc/src/flow/nodes/split_by_random.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_run_result.js +10 -4
- package/out-tsc/src/flow/nodes/split_by_run_result.js.map +1 -1
- package/out-tsc/src/flow/nodes/terminal.js +7 -0
- package/out-tsc/src/flow/nodes/terminal.js.map +1 -0
- package/out-tsc/src/flow/nodes/wait_for_audio.js +77 -0
- package/out-tsc/src/flow/nodes/wait_for_audio.js.map +1 -0
- package/out-tsc/src/flow/nodes/wait_for_dial.js +151 -0
- package/out-tsc/src/flow/nodes/wait_for_dial.js.map +1 -0
- package/out-tsc/src/flow/nodes/wait_for_digits.js +61 -1
- package/out-tsc/src/flow/nodes/wait_for_digits.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_menu.js +173 -2
- package/out-tsc/src/flow/nodes/wait_for_menu.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_response.js +1 -1
- package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -1
- package/out-tsc/src/flow/operators.js +21 -5
- package/out-tsc/src/flow/operators.js.map +1 -1
- package/out-tsc/src/flow/types.js.map +1 -1
- package/out-tsc/src/flow/utils.js +79 -3
- package/out-tsc/src/flow/utils.js.map +1 -1
- package/out-tsc/src/form/ArrayEditor.js +4 -2
- package/out-tsc/src/form/ArrayEditor.js.map +1 -1
- package/out-tsc/src/form/FieldRenderer.js +56 -0
- package/out-tsc/src/form/FieldRenderer.js.map +1 -1
- package/out-tsc/src/interfaces.js +1 -0
- package/out-tsc/src/interfaces.js.map +1 -1
- package/out-tsc/src/layout/Dialog.js +51 -7
- package/out-tsc/src/layout/Dialog.js.map +1 -1
- package/out-tsc/src/layout/Modax.js +20 -2
- package/out-tsc/src/layout/Modax.js.map +1 -1
- package/out-tsc/src/list/ContentMenu.js +14 -1
- package/out-tsc/src/list/ContentMenu.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/simulator/Simulator.js +21 -4
- package/out-tsc/src/simulator/Simulator.js.map +1 -1
- package/out-tsc/src/store/AppState.js +102 -3
- package/out-tsc/src/store/AppState.js.map +1 -1
- package/out-tsc/test/actions/add_contact_groups.test.js +35 -0
- package/out-tsc/test/actions/add_contact_groups.test.js.map +1 -1
- package/out-tsc/test/actions/add_input_labels.test.js +53 -0
- package/out-tsc/test/actions/add_input_labels.test.js.map +1 -0
- package/out-tsc/test/actions/enter_flow.test.js +71 -0
- package/out-tsc/test/actions/enter_flow.test.js.map +1 -0
- package/out-tsc/test/actions/play_audio.test.js +118 -0
- package/out-tsc/test/actions/play_audio.test.js.map +1 -0
- package/out-tsc/test/actions/remove_contact_groups.test.js +24 -0
- package/out-tsc/test/actions/remove_contact_groups.test.js.map +1 -1
- package/out-tsc/test/actions/say_msg.test.js +158 -0
- package/out-tsc/test/actions/say_msg.test.js.map +1 -0
- package/out-tsc/test/actions/send_broadcast.test.js +41 -0
- package/out-tsc/test/actions/send_broadcast.test.js.map +1 -1
- package/out-tsc/test/actions/set_contact_channel.test.js +67 -0
- package/out-tsc/test/actions/set_contact_channel.test.js.map +1 -0
- package/out-tsc/test/actions/set_contact_field.test.js +52 -0
- package/out-tsc/test/actions/set_contact_field.test.js.map +1 -0
- package/out-tsc/test/actions/set_contact_language.test.js +39 -0
- package/out-tsc/test/actions/set_contact_language.test.js.map +1 -0
- package/out-tsc/test/actions/set_contact_name.test.js +28 -0
- package/out-tsc/test/actions/set_contact_name.test.js.map +1 -0
- package/out-tsc/test/actions/set_contact_status.test.js +44 -0
- package/out-tsc/test/actions/set_contact_status.test.js.map +1 -0
- package/out-tsc/test/actions/set_run_result.test.js +47 -0
- package/out-tsc/test/actions/set_run_result.test.js.map +1 -0
- package/out-tsc/test/actions/start_session.test.js +76 -0
- package/out-tsc/test/actions/start_session.test.js.map +1 -1
- package/out-tsc/test/nodes/split_by_contact_field.test.js +50 -0
- package/out-tsc/test/nodes/split_by_contact_field.test.js.map +1 -1
- package/out-tsc/test/nodes/split_by_run_result.test.js +82 -0
- package/out-tsc/test/nodes/split_by_run_result.test.js.map +1 -1
- package/out-tsc/test/nodes/split_by_ticket.test.js +139 -0
- package/out-tsc/test/nodes/split_by_ticket.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_webhook.test.js +111 -0
- package/out-tsc/test/nodes/split_by_webhook.test.js.map +1 -0
- package/out-tsc/test/nodes/wait_for_audio.test.js +156 -0
- package/out-tsc/test/nodes/wait_for_audio.test.js.map +1 -0
- package/out-tsc/test/nodes/wait_for_dial.test.js +336 -0
- package/out-tsc/test/nodes/wait_for_dial.test.js.map +1 -0
- package/out-tsc/test/nodes/wait_for_digits.test.js +198 -84
- package/out-tsc/test/nodes/wait_for_digits.test.js.map +1 -1
- package/out-tsc/test/nodes/wait_for_menu.test.js +340 -0
- package/out-tsc/test/nodes/wait_for_menu.test.js.map +1 -0
- package/out-tsc/test/temba-flow-collision.test.js +261 -6
- package/out-tsc/test/temba-flow-collision.test.js.map +1 -1
- package/out-tsc/test/temba-flow-editor.test.js +187 -0
- package/out-tsc/test/temba-flow-editor.test.js.map +1 -1
- package/out-tsc/test/temba-flow-plumber.test.js +19 -0
- package/out-tsc/test/temba-flow-plumber.test.js.map +1 -1
- package/out-tsc/test/temba-node-type-selector.test.js +6 -6
- package/out-tsc/test/temba-node-type-selector.test.js.map +1 -1
- package/out-tsc/test/temba-select.test.js +4 -1
- package/out-tsc/test/temba-select.test.js.map +1 -1
- package/out-tsc/test/utils.test.js +4 -2
- package/out-tsc/test/utils.test.js.map +1 -1
- package/package.json +3 -9
- 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/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/add_input_labels/editor/multiple-labels.png +0 -0
- package/screenshots/truth/actions/add_input_labels/editor/single-label.png +0 -0
- package/screenshots/truth/actions/add_input_labels/render/multiple-labels.png +0 -0
- package/screenshots/truth/actions/add_input_labels/render/single-label.png +0 -0
- package/screenshots/truth/actions/enter_flow/editor/basic-flow.png +0 -0
- package/screenshots/truth/actions/enter_flow/editor/long-flow-name.png +0 -0
- package/screenshots/truth/actions/enter_flow/render/basic-flow.png +0 -0
- package/screenshots/truth/actions/enter_flow/render/long-flow-name.png +0 -0
- package/screenshots/truth/actions/play_audio/editor/expression-url.png +0 -0
- package/screenshots/truth/actions/play_audio/editor/static-url.png +0 -0
- package/screenshots/truth/actions/play_audio/render/expression-url.png +0 -0
- package/screenshots/truth/actions/play_audio/render/static-url.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/say_msg/editor/multiline-text.png +0 -0
- package/screenshots/truth/actions/say_msg/editor/simple-text.png +0 -0
- package/screenshots/truth/actions/say_msg/editor/text-with-audio-url.png +0 -0
- package/screenshots/truth/actions/say_msg/render/multiline-text.png +0 -0
- package/screenshots/truth/actions/say_msg/render/simple-text.png +0 -0
- package/screenshots/truth/actions/say_msg/render/text-with-audio-url.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_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/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/set_contact_channel/editor/sms-channel.png +0 -0
- package/screenshots/truth/actions/set_contact_channel/editor/whatsapp-channel.png +0 -0
- package/screenshots/truth/actions/set_contact_channel/render/sms-channel.png +0 -0
- package/screenshots/truth/actions/set_contact_channel/render/whatsapp-channel.png +0 -0
- package/screenshots/truth/actions/set_contact_field/editor/clear-value.png +0 -0
- package/screenshots/truth/actions/set_contact_field/editor/set-value.png +0 -0
- package/screenshots/truth/actions/set_contact_field/render/clear-value.png +0 -0
- package/screenshots/truth/actions/set_contact_field/render/set-value.png +0 -0
- package/screenshots/truth/actions/set_contact_language/editor/english.png +0 -0
- package/screenshots/truth/actions/set_contact_language/editor/french.png +0 -0
- package/screenshots/truth/actions/set_contact_language/render/english.png +0 -0
- package/screenshots/truth/actions/set_contact_language/render/french.png +0 -0
- package/screenshots/truth/actions/set_contact_name/editor/expression-name.png +0 -0
- package/screenshots/truth/actions/set_contact_name/editor/static-name.png +0 -0
- package/screenshots/truth/actions/set_contact_name/render/expression-name.png +0 -0
- package/screenshots/truth/actions/set_contact_name/render/static-name.png +0 -0
- package/screenshots/truth/actions/set_contact_status/editor/active.png +0 -0
- package/screenshots/truth/actions/set_contact_status/editor/archived.png +0 -0
- package/screenshots/truth/actions/set_contact_status/editor/blocked.png +0 -0
- package/screenshots/truth/actions/set_contact_status/render/active.png +0 -0
- package/screenshots/truth/actions/set_contact_status/render/archived.png +0 -0
- package/screenshots/truth/actions/set_contact_status/render/blocked.png +0 -0
- package/screenshots/truth/actions/set_run_result/editor/expression-value.png +0 -0
- package/screenshots/truth/actions/set_run_result/editor/with-category.png +0 -0
- package/screenshots/truth/actions/set_run_result/render/expression-value.png +0 -0
- package/screenshots/truth/actions/set_run_result/render/with-category.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/editor/router.png +0 -0
- package/screenshots/truth/editor/wait.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_audio/editor/basic-audio-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_audio/render/basic-audio-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_dial/editor/basic-dial.png +0 -0
- package/screenshots/truth/nodes/wait_for_dial/editor/dial-with-limits.png +0 -0
- package/screenshots/truth/nodes/wait_for_dial/render/basic-dial.png +0 -0
- package/screenshots/truth/nodes/wait_for_dial/render/dial-with-limits.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/digits-with-rules.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/digits-with-rules.png +0 -0
- package/screenshots/truth/nodes/wait_for_menu/editor/menu-with-digits.png +0 -0
- package/screenshots/truth/nodes/wait_for_menu/render/menu-with-digits.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/display/Chat.ts +13 -7
- package/src/display/Dropdown.ts +3 -1
- package/src/display/FloatingTab.ts +4 -4
- package/src/display/Thumbnail.ts +162 -2
- package/src/flow/CanvasNode.ts +70 -24
- package/src/flow/Editor.ts +440 -99
- package/src/flow/NodeEditor.ts +137 -9
- package/src/flow/Plumber.ts +89 -14
- package/src/flow/StickyNote.ts +14 -4
- package/src/flow/actions/add_contact_groups.ts +4 -1
- package/src/flow/actions/add_input_labels.ts +4 -1
- package/src/flow/actions/audio-player.ts +127 -0
- package/src/flow/actions/enter_flow.ts +44 -0
- package/src/flow/actions/play_audio.ts +64 -5
- package/src/flow/actions/remove_contact_groups.ts +6 -1
- package/src/flow/actions/say_msg.ts +94 -4
- package/src/flow/actions/send_broadcast.ts +6 -2
- package/src/flow/actions/set_contact_channel.ts +13 -1
- package/src/flow/actions/set_contact_status.ts +7 -5
- package/src/flow/actions/start_session.ts +10 -3
- package/src/flow/config.ts +11 -3
- package/src/flow/nodes/shared-rules.ts +1 -1
- package/src/flow/nodes/split_by_contact_field.ts +16 -5
- package/src/flow/nodes/split_by_expression.ts +1 -1
- package/src/flow/nodes/split_by_llm_categorize.ts +0 -1
- package/src/flow/nodes/split_by_random.ts +0 -1
- package/src/flow/nodes/split_by_run_result.ts +10 -4
- package/src/flow/nodes/terminal.ts +9 -0
- package/src/flow/nodes/wait_for_audio.ts +88 -0
- package/src/flow/nodes/wait_for_dial.ts +176 -0
- package/src/flow/nodes/wait_for_digits.ts +87 -2
- package/src/flow/nodes/wait_for_menu.ts +209 -3
- package/src/flow/nodes/wait_for_response.ts +1 -1
- package/src/flow/operators.ts +23 -5
- package/src/flow/types.ts +23 -1
- package/src/flow/utils.ts +82 -3
- package/src/form/ArrayEditor.ts +4 -2
- package/src/form/FieldRenderer.ts +71 -1
- package/src/interfaces.ts +2 -1
- package/src/layout/Dialog.ts +52 -7
- package/src/layout/Modax.ts +19 -2
- package/src/list/ContentMenu.ts +15 -1
- 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/simulator/Simulator.ts +25 -4
- package/src/store/AppState.ts +120 -1
- package/src/store/flow-definition.d.ts +2 -0
- package/test/actions/add_contact_groups.test.ts +38 -0
- package/test/actions/add_input_labels.test.ts +67 -0
- package/test/actions/enter_flow.test.ts +88 -0
- package/test/actions/play_audio.test.ts +155 -0
- package/test/actions/remove_contact_groups.test.ts +29 -0
- package/test/actions/say_msg.test.ts +196 -0
- package/test/actions/send_broadcast.test.ts +44 -0
- package/test/actions/set_contact_channel.test.ts +88 -0
- package/test/actions/set_contact_field.test.ts +68 -0
- package/test/actions/set_contact_language.test.ts +55 -0
- package/test/actions/set_contact_name.test.ts +39 -0
- package/test/actions/set_contact_status.test.ts +64 -0
- package/test/actions/set_run_result.test.ts +61 -0
- package/test/actions/start_session.test.ts +82 -0
- package/test/nodes/split_by_contact_field.test.ts +59 -0
- package/test/nodes/split_by_run_result.test.ts +100 -0
- package/test/nodes/split_by_ticket.test.ts +157 -0
- package/test/nodes/split_by_webhook.test.ts +131 -0
- package/test/nodes/wait_for_audio.test.ts +182 -0
- package/test/nodes/wait_for_dial.test.ts +382 -0
- package/test/nodes/wait_for_digits.test.ts +233 -109
- package/test/nodes/wait_for_menu.test.ts +383 -0
- package/test/temba-flow-collision.test.ts +286 -6
- package/test/temba-flow-editor.test.ts +240 -0
- package/test/temba-flow-plumber.test.ts +62 -0
- package/test/temba-node-type-selector.test.ts +6 -6
- package/test/temba-select.test.ts +6 -1
- package/test/utils.test.ts +4 -2
- 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/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/src/display/Thumbnail.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { PropertyValueMap, css, html } from 'lit';
|
|
2
2
|
import { RapidElement } from '../RapidElement';
|
|
3
|
-
import { property } from 'lit/decorators.js';
|
|
3
|
+
import { property, state } from 'lit/decorators.js';
|
|
4
4
|
import { getClasses } from '../utils';
|
|
5
5
|
import { Lightbox } from './Lightbox';
|
|
6
6
|
import { WebChatIcon } from '../webchat';
|
|
@@ -67,11 +67,57 @@ export class Thumbnail extends RapidElement {
|
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
.thumb.document,
|
|
70
|
-
.thumb.audio,
|
|
71
70
|
.thumb.video {
|
|
72
71
|
border: 1px solid #eee;
|
|
73
72
|
}
|
|
74
73
|
|
|
74
|
+
.audio-player {
|
|
75
|
+
display: flex;
|
|
76
|
+
align-items: center;
|
|
77
|
+
gap: 6px;
|
|
78
|
+
padding: 6px 8px;
|
|
79
|
+
background: rgba(0, 0, 0, 0.05);
|
|
80
|
+
border-radius: var(--curvature);
|
|
81
|
+
cursor: default;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.audio-play-btn {
|
|
85
|
+
cursor: pointer;
|
|
86
|
+
color: #666;
|
|
87
|
+
display: flex;
|
|
88
|
+
align-items: center;
|
|
89
|
+
flex-shrink: 0;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.audio-play-btn:hover {
|
|
93
|
+
color: #333;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.audio-progress-bar {
|
|
97
|
+
flex: 1;
|
|
98
|
+
height: 3px;
|
|
99
|
+
background: #ddd;
|
|
100
|
+
border-radius: 2px;
|
|
101
|
+
overflow: hidden;
|
|
102
|
+
min-width: 60px;
|
|
103
|
+
cursor: pointer;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.audio-progress-fill {
|
|
107
|
+
height: 100%;
|
|
108
|
+
background: var(--color-primary, #2387ca);
|
|
109
|
+
border-radius: 2px;
|
|
110
|
+
transition: width 0.15s linear;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.audio-time {
|
|
114
|
+
font-size: 11px;
|
|
115
|
+
color: #999;
|
|
116
|
+
flex-shrink: 0;
|
|
117
|
+
min-width: 28px;
|
|
118
|
+
text-align: right;
|
|
119
|
+
}
|
|
120
|
+
|
|
75
121
|
.wrapper:hover .thumb.icon {
|
|
76
122
|
}
|
|
77
123
|
|
|
@@ -133,6 +179,74 @@ export class Thumbnail extends RapidElement {
|
|
|
133
179
|
@property({ type: String, attribute: false })
|
|
134
180
|
private tileUrl: string = '';
|
|
135
181
|
|
|
182
|
+
// audio player state
|
|
183
|
+
private audio: HTMLAudioElement | null = null;
|
|
184
|
+
|
|
185
|
+
@state()
|
|
186
|
+
private audioPlaying = false;
|
|
187
|
+
|
|
188
|
+
@state()
|
|
189
|
+
private audioProgress = 0;
|
|
190
|
+
|
|
191
|
+
@state()
|
|
192
|
+
private audioDuration = 0;
|
|
193
|
+
|
|
194
|
+
private handleAudioPlayClick(e: Event) {
|
|
195
|
+
e.stopPropagation();
|
|
196
|
+
|
|
197
|
+
if (!this.audio) {
|
|
198
|
+
this.audio = new Audio(this.url);
|
|
199
|
+
this.audio.addEventListener('timeupdate', () => {
|
|
200
|
+
if (this.audio.duration) {
|
|
201
|
+
this.audioProgress = this.audio.currentTime / this.audio.duration;
|
|
202
|
+
this.audioDuration = this.audio.duration;
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
this.audio.addEventListener('ended', () => {
|
|
206
|
+
this.audioPlaying = false;
|
|
207
|
+
this.audioProgress = 0;
|
|
208
|
+
});
|
|
209
|
+
this.audio.addEventListener('error', () => {
|
|
210
|
+
this.audioPlaying = false;
|
|
211
|
+
this.audioProgress = 0;
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (this.audioPlaying) {
|
|
216
|
+
this.audio.pause();
|
|
217
|
+
this.audioPlaying = false;
|
|
218
|
+
} else {
|
|
219
|
+
this.audio.play().catch(() => {
|
|
220
|
+
this.audioPlaying = false;
|
|
221
|
+
});
|
|
222
|
+
this.audioPlaying = true;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
private handleProgressClick(e: MouseEvent) {
|
|
227
|
+
e.stopPropagation();
|
|
228
|
+
if (!this.audio || !this.audio.duration) return;
|
|
229
|
+
const bar = e.currentTarget as HTMLElement;
|
|
230
|
+
const rect = bar.getBoundingClientRect();
|
|
231
|
+
const pct = (e.clientX - rect.left) / rect.width;
|
|
232
|
+
this.audio.currentTime = pct * this.audio.duration;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
private formatTime(seconds: number): string {
|
|
236
|
+
const s = Math.floor(seconds);
|
|
237
|
+
const m = Math.floor(s / 60);
|
|
238
|
+
const rem = s % 60;
|
|
239
|
+
return `${m}:${rem.toString().padStart(2, '0')}`;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
disconnectedCallback() {
|
|
243
|
+
super.disconnectedCallback();
|
|
244
|
+
if (this.audio) {
|
|
245
|
+
this.audio.pause();
|
|
246
|
+
this.audio = null;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
136
250
|
// convert lat/lng to tile coordinates for OSM
|
|
137
251
|
private latLngToTile(lat: number, lng: number, zoom: number) {
|
|
138
252
|
const n = Math.pow(2, zoom);
|
|
@@ -227,6 +341,8 @@ export class Thumbnail extends RapidElement {
|
|
|
227
341
|
// open location in openstreetmap
|
|
228
342
|
const osmUrl = `https://www.openstreetmap.org/?mlat=${this.latitude}&mlon=${this.longitude}#map=15/${this.latitude}/${this.longitude}`;
|
|
229
343
|
window.open(osmUrl, '_blank');
|
|
344
|
+
} else if (this.contentType === ThumbnailContentType.AUDIO) {
|
|
345
|
+
// audio has inline controls, no click action needed
|
|
230
346
|
} else {
|
|
231
347
|
window.open(this.url, '_blank');
|
|
232
348
|
}
|
|
@@ -245,6 +361,9 @@ export class Thumbnail extends RapidElement {
|
|
|
245
361
|
<div
|
|
246
362
|
@click=${this.handleThumbnailClicked.bind(this)}
|
|
247
363
|
class="${getClasses({ wrapper: true, zoom: this.zoom })}"
|
|
364
|
+
style="${this.contentType === ThumbnailContentType.AUDIO
|
|
365
|
+
? 'cursor: default;'
|
|
366
|
+
: ''}"
|
|
248
367
|
url=${this.url}
|
|
249
368
|
>
|
|
250
369
|
${this.contentType === ThumbnailContentType.IMAGE && this.preview
|
|
@@ -254,6 +373,47 @@ export class Thumbnail extends RapidElement {
|
|
|
254
373
|
class="observe thumb ${this.contentType}"
|
|
255
374
|
src="${this.url}"
|
|
256
375
|
></img></div>`
|
|
376
|
+
: this.contentType === ThumbnailContentType.AUDIO
|
|
377
|
+
? html`<div class="audio-player">
|
|
378
|
+
<div class="audio-play-btn" @click=${this.handleAudioPlayClick}>
|
|
379
|
+
${this.audioPlaying
|
|
380
|
+
? html`<svg
|
|
381
|
+
viewBox="0 0 24 24"
|
|
382
|
+
width="14"
|
|
383
|
+
height="14"
|
|
384
|
+
fill="currentColor"
|
|
385
|
+
>
|
|
386
|
+
<rect x="5" y="3" width="4" height="18" />
|
|
387
|
+
<rect x="15" y="3" width="4" height="18" />
|
|
388
|
+
</svg>`
|
|
389
|
+
: html`<svg
|
|
390
|
+
viewBox="0 0 24 24"
|
|
391
|
+
width="14"
|
|
392
|
+
height="14"
|
|
393
|
+
fill="currentColor"
|
|
394
|
+
>
|
|
395
|
+
<polygon points="6,3 20,12 6,21" />
|
|
396
|
+
</svg>`}
|
|
397
|
+
</div>
|
|
398
|
+
<div
|
|
399
|
+
class="audio-progress-bar"
|
|
400
|
+
@click=${this.handleProgressClick}
|
|
401
|
+
>
|
|
402
|
+
<div
|
|
403
|
+
class="audio-progress-fill"
|
|
404
|
+
style="width: ${this.audioProgress * 100}%"
|
|
405
|
+
></div>
|
|
406
|
+
</div>
|
|
407
|
+
<div class="audio-time">
|
|
408
|
+
${this.audioDuration
|
|
409
|
+
? this.formatTime(
|
|
410
|
+
this.audioPlaying || this.audioProgress > 0
|
|
411
|
+
? this.audio?.currentTime || 0
|
|
412
|
+
: this.audioDuration
|
|
413
|
+
)
|
|
414
|
+
: ''}
|
|
415
|
+
</div>
|
|
416
|
+
</div>`
|
|
257
417
|
: html`
|
|
258
418
|
${this.contentType === ThumbnailContentType.LOCATION
|
|
259
419
|
? html`<img
|
package/src/flow/CanvasNode.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { getClasses } from '../utils';
|
|
|
9
9
|
import { Plumber } from './Plumber';
|
|
10
10
|
import { getStore } from '../store/Store';
|
|
11
11
|
import { CustomEventType } from '../interfaces';
|
|
12
|
-
import { AppState, fromStore, zustand } from '../store/AppState';
|
|
12
|
+
import { AppState, FlowIssue, fromStore, zustand } from '../store/AppState';
|
|
13
13
|
|
|
14
14
|
const DRAG_THRESHOLD = 5;
|
|
15
15
|
|
|
@@ -49,6 +49,12 @@ export class CanvasNode extends RapidElement {
|
|
|
49
49
|
@fromStore(zustand, (state: AppState) => state.getCurrentActivity())
|
|
50
50
|
private activity!: any;
|
|
51
51
|
|
|
52
|
+
@fromStore(zustand, (state: AppState) => state.issuesByNode)
|
|
53
|
+
private issuesByNode!: Map<string, FlowIssue[]>;
|
|
54
|
+
|
|
55
|
+
@fromStore(zustand, (state: AppState) => state.issuesByAction)
|
|
56
|
+
private issuesByAction!: Map<string, FlowIssue[]>;
|
|
57
|
+
|
|
52
58
|
// Track exits that are in "removing" state
|
|
53
59
|
private exitRemovalTimeouts: Map<string, number> = new Map();
|
|
54
60
|
|
|
@@ -169,7 +175,7 @@ export class CanvasNode extends RapidElement {
|
|
|
169
175
|
z-index: 10;
|
|
170
176
|
transition: all 100ms ease-in-out;
|
|
171
177
|
align-self: center;
|
|
172
|
-
margin-right:0.
|
|
178
|
+
margin-right: 0.3em;
|
|
173
179
|
border: 0px solid red;
|
|
174
180
|
width: 1em;
|
|
175
181
|
pointer-events: auto; /* Ensure remove button can receive events */
|
|
@@ -185,6 +191,12 @@ export class CanvasNode extends RapidElement {
|
|
|
185
191
|
pointer-events: none !important;
|
|
186
192
|
}
|
|
187
193
|
|
|
194
|
+
/* Issue indicators - hatched red title bar */
|
|
195
|
+
.action-content.has-issues .cn-title,
|
|
196
|
+
.node.has-issues > .router .cn-title {
|
|
197
|
+
background: repeating-linear-gradient(120deg, tomato, tomato 6px, #ff7056 0, #ff7056 18px) !important;
|
|
198
|
+
}
|
|
199
|
+
|
|
188
200
|
.action.sortable {
|
|
189
201
|
display: flex;
|
|
190
202
|
align-items: stretch;
|
|
@@ -548,14 +560,17 @@ export class CanvasNode extends RapidElement {
|
|
|
548
560
|
// make our initial connections
|
|
549
561
|
// We use setTimeout to allow for DOM updates to complete before querying for exits
|
|
550
562
|
this.connectionTimeout = window.setTimeout(() => {
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
this.plumber.
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
563
|
+
// Terminal nodes have no visible exits
|
|
564
|
+
if (this.ui?.type !== 'terminal') {
|
|
565
|
+
for (const exit of this.node.exits) {
|
|
566
|
+
this.plumber.makeSource(exit.uuid);
|
|
567
|
+
if (exit.destination_uuid) {
|
|
568
|
+
this.plumber.connectIds(
|
|
569
|
+
this.node.uuid,
|
|
570
|
+
exit.uuid,
|
|
571
|
+
exit.destination_uuid
|
|
572
|
+
);
|
|
573
|
+
}
|
|
559
574
|
}
|
|
560
575
|
}
|
|
561
576
|
// Note: revalidation is handled by plumber's processPendingConnections which calls repaintEverything
|
|
@@ -949,6 +964,11 @@ export class CanvasNode extends RapidElement {
|
|
|
949
964
|
this.requestUpdate();
|
|
950
965
|
}
|
|
951
966
|
|
|
967
|
+
private getTopCenter(el: Element): { x: number; y: number } {
|
|
968
|
+
const rect = el.getBoundingClientRect();
|
|
969
|
+
return { x: rect.left + rect.width / 2, y: rect.top };
|
|
970
|
+
}
|
|
971
|
+
|
|
952
972
|
private handleActionMouseDown(event: MouseEvent, action: Action): void {
|
|
953
973
|
// Don't handle clicks on the remove button, drag handle, or when action is in removing state
|
|
954
974
|
const target = event.target as HTMLElement;
|
|
@@ -1002,10 +1022,18 @@ export class CanvasNode extends RapidElement {
|
|
|
1002
1022
|
// Only fire the action edit event if we haven't dragged beyond the threshold
|
|
1003
1023
|
// AND either there's no Editor parent (test case) or the Editor didn't drag the node
|
|
1004
1024
|
if (distance <= DRAG_THRESHOLD && (!editor || !editorWasDragging)) {
|
|
1025
|
+
// Use top-center of the action element as the dialog origin
|
|
1026
|
+
const actionEl = event.currentTarget as Element;
|
|
1027
|
+
const origin = actionEl
|
|
1028
|
+
? this.getTopCenter(actionEl)
|
|
1029
|
+
: { x: event.clientX, y: event.clientY };
|
|
1030
|
+
|
|
1005
1031
|
// Fire event to request action editing
|
|
1006
1032
|
this.fireCustomEvent(CustomEventType.ActionEditRequested, {
|
|
1007
1033
|
action,
|
|
1008
|
-
nodeUuid: this.node.uuid
|
|
1034
|
+
nodeUuid: this.node.uuid,
|
|
1035
|
+
originX: origin.x,
|
|
1036
|
+
originY: origin.y
|
|
1009
1037
|
});
|
|
1010
1038
|
}
|
|
1011
1039
|
}
|
|
@@ -1125,17 +1153,24 @@ export class CanvasNode extends RapidElement {
|
|
|
1125
1153
|
// Using literal 5 instead of DRAG_THRESHOLD since it's not imported
|
|
1126
1154
|
// Fire event to request node editing if the node has a router
|
|
1127
1155
|
if (this.node.router) {
|
|
1156
|
+
// Use top-center of the node as the dialog origin
|
|
1157
|
+
const origin = this.getTopCenter(this);
|
|
1158
|
+
|
|
1128
1159
|
// If router node has exactly one action, open the action editor directly
|
|
1129
1160
|
if (this.node.actions && this.node.actions.length === 1) {
|
|
1130
1161
|
this.fireCustomEvent(CustomEventType.ActionEditRequested, {
|
|
1131
1162
|
action: this.node.actions[0],
|
|
1132
|
-
nodeUuid: this.node.uuid
|
|
1163
|
+
nodeUuid: this.node.uuid,
|
|
1164
|
+
originX: origin.x,
|
|
1165
|
+
originY: origin.y
|
|
1133
1166
|
});
|
|
1134
1167
|
} else {
|
|
1135
1168
|
// Otherwise open the node editor as before
|
|
1136
1169
|
this.fireCustomEvent(CustomEventType.NodeEditRequested, {
|
|
1137
1170
|
node: this.node,
|
|
1138
|
-
nodeUI: this.ui
|
|
1171
|
+
nodeUI: this.ui,
|
|
1172
|
+
originX: origin.x,
|
|
1173
|
+
originY: origin.y
|
|
1139
1174
|
});
|
|
1140
1175
|
}
|
|
1141
1176
|
}
|
|
@@ -1310,13 +1345,11 @@ export class CanvasNode extends RapidElement {
|
|
|
1310
1345
|
const color = config.group
|
|
1311
1346
|
? ACTION_GROUP_METADATA[config.group]?.color
|
|
1312
1347
|
: '#aaaaaa';
|
|
1348
|
+
const isTerminal = this.ui?.type === 'terminal';
|
|
1313
1349
|
return html`<div class="cn-title" style="background:${color}">
|
|
1314
|
-
${
|
|
1315
|
-
? html`<
|
|
1316
|
-
|
|
1317
|
-
name="sort"
|
|
1318
|
-
></temba-icon>`
|
|
1319
|
-
: this.node?.actions?.length > 1
|
|
1350
|
+
${isTerminal
|
|
1351
|
+
? html`<div class="title-spacer"></div>`
|
|
1352
|
+
: this.ui?.type === 'execute_actions' || this.node?.actions?.length > 1
|
|
1320
1353
|
? html`<temba-icon
|
|
1321
1354
|
class="drag-handle ${this.isReadOnly() ? 'read-only-hidden' : ''}"
|
|
1322
1355
|
name="sort"
|
|
@@ -1325,7 +1358,9 @@ export class CanvasNode extends RapidElement {
|
|
|
1325
1358
|
|
|
1326
1359
|
<div class="name">${isRemoving ? 'Remove?' : config.name}</div>
|
|
1327
1360
|
<div
|
|
1328
|
-
class="remove-button ${this.isReadOnly()
|
|
1361
|
+
class="remove-button ${isTerminal || this.isReadOnly()
|
|
1362
|
+
? 'read-only-hidden'
|
|
1363
|
+
: ''}"
|
|
1329
1364
|
@click=${(e: MouseEvent) =>
|
|
1330
1365
|
this.handleActionRemoveClick(e, action, index)}
|
|
1331
1366
|
title="Remove action"
|
|
@@ -1438,6 +1473,7 @@ export class CanvasNode extends RapidElement {
|
|
|
1438
1473
|
const displayAction = this.getLocalizedAction(action);
|
|
1439
1474
|
|
|
1440
1475
|
if (config) {
|
|
1476
|
+
const hasIssues = this.issuesByAction?.has(action.uuid);
|
|
1441
1477
|
const classes = [
|
|
1442
1478
|
'action',
|
|
1443
1479
|
'sortable',
|
|
@@ -1452,7 +1488,7 @@ export class CanvasNode extends RapidElement {
|
|
|
1452
1488
|
|
|
1453
1489
|
return html`<div class="${classes}" id="action-${index}">
|
|
1454
1490
|
<div
|
|
1455
|
-
class="action-content"
|
|
1491
|
+
class="action-content ${hasIssues ? 'has-issues' : ''}"
|
|
1456
1492
|
@mousedown=${(e: MouseEvent) =>
|
|
1457
1493
|
!isDisabled && this.handleActionMouseDown(e, action)}
|
|
1458
1494
|
@mouseup=${(e: MouseEvent) =>
|
|
@@ -1628,13 +1664,19 @@ export class CanvasNode extends RapidElement {
|
|
|
1628
1664
|
const activeCount =
|
|
1629
1665
|
(this.activity?.nodes && this.activity.nodes[this.node.uuid]) || 0;
|
|
1630
1666
|
|
|
1667
|
+
// Check for node-level issues or action-level issues on any action in this node
|
|
1668
|
+
const nodeHasIssues =
|
|
1669
|
+
this.issuesByNode?.has(this.node.uuid) ||
|
|
1670
|
+
this.node.actions?.some((a) => this.issuesByAction?.has(a.uuid));
|
|
1671
|
+
|
|
1631
1672
|
return html`
|
|
1632
1673
|
<div
|
|
1633
1674
|
id="${this.node.uuid}"
|
|
1634
1675
|
class=${getClasses({
|
|
1635
1676
|
node: true,
|
|
1636
1677
|
'execute-actions': this.ui.type === 'execute_actions',
|
|
1637
|
-
'non-localizable': isNodeDisabled
|
|
1678
|
+
'non-localizable': isNodeDisabled,
|
|
1679
|
+
'has-issues': nodeHasIssues
|
|
1638
1680
|
})}
|
|
1639
1681
|
style="left:${this.ui.position.left}px;top:${this.ui.position.top}px"
|
|
1640
1682
|
>
|
|
@@ -1643,7 +1685,9 @@ export class CanvasNode extends RapidElement {
|
|
|
1643
1685
|
${activeCount.toLocaleString()}
|
|
1644
1686
|
</div>`
|
|
1645
1687
|
: ''}
|
|
1646
|
-
${nodeConfig &&
|
|
1688
|
+
${nodeConfig &&
|
|
1689
|
+
nodeConfig.type !== 'execute_actions' &&
|
|
1690
|
+
nodeConfig.type !== 'terminal'
|
|
1647
1691
|
? html`<div class="router" style="position: relative;">
|
|
1648
1692
|
<div
|
|
1649
1693
|
@mousedown=${(e: MouseEvent) => this.handleNodeMouseDown(e)}
|
|
@@ -1661,7 +1705,7 @@ export class CanvasNode extends RapidElement {
|
|
|
1661
1705
|
: null}
|
|
1662
1706
|
</div>
|
|
1663
1707
|
</div>`
|
|
1664
|
-
: this.node.actions
|
|
1708
|
+
: this.node.actions?.length > 0
|
|
1665
1709
|
? this.ui.type === 'execute_actions'
|
|
1666
1710
|
? html`<temba-sortable-list
|
|
1667
1711
|
dragHandle="drag-handle"
|
|
@@ -1691,6 +1735,8 @@ export class CanvasNode extends RapidElement {
|
|
|
1691
1735
|
${this.renderRouter(this.node.router, this.ui)}
|
|
1692
1736
|
${this.renderCategories(this.node)}
|
|
1693
1737
|
</div>`
|
|
1738
|
+
: this.ui.type === 'terminal'
|
|
1739
|
+
? ''
|
|
1694
1740
|
: html`<div class="action-exits">
|
|
1695
1741
|
${repeat(
|
|
1696
1742
|
this.node.exits,
|