@nyaruka/temba-components 0.129.10 → 0.130.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/CHANGELOG.md +16 -0
- package/demo/components/flow/example.html +5 -1
- package/demo/data/flows/sample-flow.json +217 -113
- package/dist/temba-components.js +310 -356
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/events.js.map +1 -1
- package/out-tsc/src/flow/CanvasNode.js +3 -35
- package/out-tsc/src/flow/CanvasNode.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +9 -6
- package/out-tsc/src/flow/Editor.js.map +1 -1
- package/out-tsc/src/flow/NodeEditor.js +44 -11
- package/out-tsc/src/flow/NodeEditor.js.map +1 -1
- package/out-tsc/src/flow/actions/add_contact_groups.js +1 -1
- package/out-tsc/src/flow/actions/add_contact_groups.js.map +1 -1
- package/out-tsc/src/flow/actions/add_contact_urn.js +1 -1
- package/out-tsc/src/flow/actions/add_contact_urn.js.map +1 -1
- package/out-tsc/src/flow/actions/add_input_labels.js +1 -1
- package/out-tsc/src/flow/actions/add_input_labels.js.map +1 -1
- package/out-tsc/src/flow/actions/remove_contact_groups.js +1 -1
- package/out-tsc/src/flow/actions/remove_contact_groups.js.map +1 -1
- package/out-tsc/src/flow/actions/send_email.js +9 -0
- package/out-tsc/src/flow/actions/send_email.js.map +1 -1
- package/out-tsc/src/flow/actions/send_msg.js +7 -8
- package/out-tsc/src/flow/actions/send_msg.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_channel.js +25 -4
- package/out-tsc/src/flow/actions/set_contact_channel.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_field.js +51 -1
- package/out-tsc/src/flow/actions/set_contact_field.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_language.js +70 -2
- package/out-tsc/src/flow/actions/set_contact_language.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_name.js +27 -2
- package/out-tsc/src/flow/actions/set_contact_name.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_status.js +32 -2
- package/out-tsc/src/flow/actions/set_contact_status.js.map +1 -1
- package/out-tsc/src/flow/actions/set_run_result.js +13 -11
- package/out-tsc/src/flow/actions/set_run_result.js.map +1 -1
- package/out-tsc/src/flow/actions/split_by_expression_example.js +4 -4
- package/out-tsc/src/flow/actions/split_by_expression_example.js.map +1 -1
- package/out-tsc/src/flow/config.js +2 -8
- package/out-tsc/src/flow/config.js.map +1 -1
- package/out-tsc/src/flow/forms/index.js +2 -0
- package/out-tsc/src/flow/forms/index.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_llm.js +101 -0
- package/out-tsc/src/flow/nodes/split_by_llm.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_llm_categorize.js +4 -89
- package/out-tsc/src/flow/nodes/split_by_llm_categorize.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_random.js +117 -0
- package/out-tsc/src/flow/nodes/split_by_random.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_subflow.js +123 -3
- package/out-tsc/src/flow/nodes/split_by_subflow.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_ticket.js +114 -13
- package/out-tsc/src/flow/nodes/split_by_ticket.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_webhook.js +158 -12
- package/out-tsc/src/flow/nodes/split_by_webhook.js.map +1 -1
- package/out-tsc/src/flow/types.js.map +1 -1
- package/out-tsc/src/form/ArrayEditor.js +9 -25
- package/out-tsc/src/form/ArrayEditor.js.map +1 -1
- package/out-tsc/src/form/FieldRenderer.js +6 -64
- package/out-tsc/src/form/FieldRenderer.js.map +1 -1
- package/out-tsc/src/form/select/Select.js +29 -58
- package/out-tsc/src/form/select/Select.js.map +1 -1
- package/out-tsc/src/live/ContactChat.js +48 -66
- package/out-tsc/src/live/ContactChat.js.map +1 -1
- package/out-tsc/src/utils.js +118 -0
- package/out-tsc/src/utils.js.map +1 -1
- package/out-tsc/test/nodes/split_by_llm.test.js +174 -0
- package/out-tsc/test/nodes/split_by_llm.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_random.test.js +0 -6
- package/out-tsc/test/nodes/split_by_random.test.js.map +1 -1
- package/out-tsc/test/temba-field-renderer.test.js +6 -3
- package/out-tsc/test/temba-field-renderer.test.js.map +1 -1
- package/out-tsc/test/utils.test.js +18 -0
- package/out-tsc/test/utils.test.js.map +1 -1
- package/package.json +1 -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/call_llm/editor/information-extraction.png +0 -0
- package/screenshots/truth/actions/call_llm/editor/sentiment-analysis.png +0 -0
- package/screenshots/truth/actions/call_llm/editor/summarization.png +0 -0
- package/screenshots/truth/actions/call_llm/editor/translation-task.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_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_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/checkbox/checkbox-label-background-hover.png +0 -0
- package/screenshots/truth/checkbox/checkbox-no-label-no-background-hover.png +0 -0
- package/screenshots/truth/checkbox/checkbox-whitespace-label-no-background-hover.png +0 -0
- package/screenshots/truth/checkbox/checkbox-with-help-text.png +0 -0
- package/screenshots/truth/checkbox/checked.png +0 -0
- package/screenshots/truth/checkbox/default.png +0 -0
- package/screenshots/truth/colorpicker/default.png +0 -0
- package/screenshots/truth/colorpicker/focused.png +0 -0
- package/screenshots/truth/colorpicker/initialized.png +0 -0
- package/screenshots/truth/colorpicker/selected.png +0 -0
- package/screenshots/truth/compose/attachments-tab.png +0 -0
- package/screenshots/truth/compose/attachments-with-files.png +0 -0
- package/screenshots/truth/compose/intial-text.png +0 -0
- package/screenshots/truth/compose/no-counter.png +0 -0
- package/screenshots/truth/compose/wraps-text-and-spaces.png +0 -0
- package/screenshots/truth/compose/wraps-text-and-url.png +0 -0
- package/screenshots/truth/compose/wraps-text-no-spaces.png +0 -0
- package/screenshots/truth/contacts/chat-failure.png +0 -0
- package/screenshots/truth/contacts/chat-for-active-contact.png +0 -0
- package/screenshots/truth/contacts/chat-sends-attachments-only.png +0 -0
- package/screenshots/truth/contacts/chat-sends-text-and-attachments.png +0 -0
- package/screenshots/truth/contacts/chat-sends-text-only.png +0 -0
- package/screenshots/truth/counter/summary.png +0 -0
- package/screenshots/truth/counter/text.png +0 -0
- package/screenshots/truth/counter/unicode-variables.png +0 -0
- package/screenshots/truth/counter/unicode.png +0 -0
- package/screenshots/truth/counter/variable.png +0 -0
- package/screenshots/truth/datepicker/date-truncated-time.png +0 -0
- package/screenshots/truth/datepicker/date.png +0 -0
- package/screenshots/truth/datepicker/initial-timezone.png +0 -0
- package/screenshots/truth/datepicker/range-picker-editing-start.png +0 -0
- package/screenshots/truth/datepicker/updated-keyboard-date.png +0 -0
- package/screenshots/truth/dialog/focused.png +0 -0
- package/screenshots/truth/dropdown/right-edge-collision.png +0 -0
- package/screenshots/truth/editor/router.png +0 -0
- package/screenshots/truth/editor/send_msg.png +0 -0
- package/screenshots/truth/editor/set_contact_language.png +0 -0
- package/screenshots/truth/editor/set_contact_name.png +0 -0
- package/screenshots/truth/editor/set_run_result.png +0 -0
- package/screenshots/truth/editor/wait.png +0 -0
- package/screenshots/truth/field-renderer/checkbox-checked.png +0 -0
- package/screenshots/truth/field-renderer/checkbox-unchecked.png +0 -0
- package/screenshots/truth/field-renderer/checkbox-with-errors.png +0 -0
- package/screenshots/truth/field-renderer/context-comparison.png +0 -0
- package/screenshots/truth/field-renderer/key-value-with-label.png +0 -0
- package/screenshots/truth/field-renderer/message-editor-with-label.png +0 -0
- package/screenshots/truth/field-renderer/select-multi.png +0 -0
- package/screenshots/truth/field-renderer/select-no-label.png +0 -0
- package/screenshots/truth/field-renderer/select-with-label.png +0 -0
- package/screenshots/truth/field-renderer/text-evaluated.png +0 -0
- package/screenshots/truth/field-renderer/text-no-label.png +0 -0
- package/screenshots/truth/field-renderer/text-with-errors.png +0 -0
- package/screenshots/truth/field-renderer/text-with-label.png +0 -0
- package/screenshots/truth/field-renderer/textarea-evaluated.png +0 -0
- package/screenshots/truth/field-renderer/textarea-with-label.png +0 -0
- package/screenshots/truth/integration/checkbox-markdown-errors.png +0 -0
- package/screenshots/truth/list/fields-dragging.png +0 -0
- package/screenshots/truth/list/fields-filtered.png +0 -0
- package/screenshots/truth/list/fields-hovered.png +0 -0
- package/screenshots/truth/list/fields.png +0 -0
- package/screenshots/truth/list/items-selected.png +0 -0
- package/screenshots/truth/list/items-updated.png +0 -0
- package/screenshots/truth/list/items.png +0 -0
- package/screenshots/truth/menu/menu-focused-with items.png +0 -0
- package/screenshots/truth/menu/menu-refresh-1.png +0 -0
- package/screenshots/truth/menu/menu-refresh-2.png +0 -0
- package/screenshots/truth/menu/menu-submenu.png +0 -0
- package/screenshots/truth/menu/menu-tasks-nextup.png +0 -0
- package/screenshots/truth/menu/menu-tasks.png +0 -0
- package/screenshots/truth/message-editor/autogrow-initial-content.png +0 -0
- package/screenshots/truth/message-editor/default.png +0 -0
- package/screenshots/truth/message-editor/drag-highlight.png +0 -0
- package/screenshots/truth/message-editor/filtered-attachments.png +0 -0
- package/screenshots/truth/message-editor/with-completion.png +0 -0
- package/screenshots/truth/message-editor/with-properties.png +0 -0
- package/screenshots/truth/modax/form.png +0 -0
- package/screenshots/truth/modax/simple.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_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/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_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/omnibox/selected.png +0 -0
- package/screenshots/truth/options/block.png +0 -0
- package/screenshots/truth/run-list/basic.png +0 -0
- package/screenshots/truth/select/disabled-multi-selection.png +0 -0
- package/screenshots/truth/select/disabled-selection.png +0 -0
- package/screenshots/truth/select/disabled.png +0 -0
- package/screenshots/truth/select/embedded.png +0 -0
- package/screenshots/truth/select/empty-options.png +0 -0
- package/screenshots/truth/select/expression-selected.png +0 -0
- package/screenshots/truth/select/expressions.png +0 -0
- package/screenshots/truth/select/functions.png +0 -0
- package/screenshots/truth/select/local-options.png +0 -0
- package/screenshots/truth/select/multi-with-endpoint.png +0 -0
- package/screenshots/truth/select/multiple-initial-values.png +0 -0
- package/screenshots/truth/select/remote-options.png +0 -0
- package/screenshots/truth/select/search-enabled.png +0 -0
- package/screenshots/truth/select/search-multi-no-matches.png +0 -0
- package/screenshots/truth/select/search-selected-focus.png +0 -0
- package/screenshots/truth/select/search-selected.png +0 -0
- package/screenshots/truth/select/search-with-selected.png +0 -0
- package/screenshots/truth/select/searching.png +0 -0
- package/screenshots/truth/select/selected-multi-maxitems-reached.png +0 -0
- package/screenshots/truth/select/selected-multi.png +0 -0
- package/screenshots/truth/select/selected-single.png +0 -0
- package/screenshots/truth/select/selection-clearable.png +0 -0
- package/screenshots/truth/select/static-initial-value.png +0 -0
- package/screenshots/truth/select/static-initial-via-selected.png +0 -0
- package/screenshots/truth/select/truncated-selection.png +0 -0
- package/screenshots/truth/select/with-placeholder.png +0 -0
- package/screenshots/truth/select/without-placeholder.png +0 -0
- package/screenshots/truth/slider/update-slider-on-circle-dragged.png +0 -0
- package/screenshots/truth/templates/default.png +0 -0
- package/screenshots/truth/templates/unapproved.png +0 -0
- package/screenshots/truth/textinput/autogrow-initial.png +0 -0
- package/screenshots/truth/textinput/input-disabled.png +0 -0
- package/screenshots/truth/textinput/input-focused.png +0 -0
- package/screenshots/truth/textinput/input-form.png +0 -0
- package/screenshots/truth/textinput/input-inserted.png +0 -0
- package/screenshots/truth/textinput/input-placeholder.png +0 -0
- package/screenshots/truth/textinput/input-updated.png +0 -0
- package/screenshots/truth/textinput/input.png +0 -0
- package/screenshots/truth/textinput/textarea-focused.png +0 -0
- package/screenshots/truth/textinput/textarea.png +0 -0
- package/src/events.ts +4 -2
- package/src/flow/CanvasNode.ts +2 -39
- package/src/flow/Editor.ts +6 -3
- package/src/flow/NodeEditor.ts +54 -13
- package/src/flow/actions/add_contact_groups.ts +1 -1
- package/src/flow/actions/add_contact_urn.ts +1 -1
- package/src/flow/actions/add_input_labels.ts +1 -1
- package/src/flow/actions/remove_contact_groups.ts +1 -1
- package/src/flow/actions/send_email.ts +11 -1
- package/src/flow/actions/send_msg.ts +20 -11
- package/src/flow/actions/set_contact_channel.ts +28 -5
- package/src/flow/actions/set_contact_field.ts +56 -2
- package/src/flow/actions/set_contact_language.ts +74 -3
- package/src/flow/actions/set_contact_name.ts +31 -3
- package/src/flow/actions/set_contact_status.ts +36 -3
- package/src/flow/actions/set_run_result.ts +13 -15
- package/src/flow/actions/split_by_expression_example.ts +4 -4
- package/src/flow/config.ts +2 -8
- package/src/flow/forms/index.ts +1 -0
- package/src/flow/nodes/split_by_llm.ts +119 -0
- package/src/flow/nodes/split_by_llm_categorize.ts +13 -116
- package/src/flow/nodes/split_by_random.ts +148 -0
- package/src/flow/nodes/split_by_subflow.ts +153 -3
- package/src/flow/nodes/split_by_ticket.ts +134 -12
- package/src/flow/nodes/split_by_webhook.ts +185 -12
- package/src/flow/types.ts +2 -1
- package/src/form/ArrayEditor.ts +6 -20
- package/src/form/FieldRenderer.ts +6 -65
- package/src/form/select/Select.ts +34 -66
- package/src/live/ContactChat.ts +56 -58
- package/src/store/flow-definition.d.ts +8 -2
- package/src/utils.ts +196 -0
- package/static/api/fields.json +93 -1208
- package/static/api/workspace.json +23 -0
- package/test/nodes/split_by_llm.test.ts +232 -0
- package/test/nodes/split_by_random.test.ts +0 -7
- package/test/temba-field-renderer.test.ts +26 -13
- package/test/utils.test.ts +20 -0
- package/test-assets/style.css +36 -234
- package/web-dev-server.config.mjs +28 -0
- package/web-test-runner.config.mjs +38 -1
- package/out-tsc/src/flow/actions/call_llm.js +0 -64
- package/out-tsc/src/flow/actions/call_llm.js.map +0 -1
- package/out-tsc/src/flow/actions/call_webhook.js +0 -131
- package/out-tsc/src/flow/actions/call_webhook.js.map +0 -1
- package/out-tsc/src/flow/actions/enter_flow.js +0 -14
- package/out-tsc/src/flow/actions/enter_flow.js.map +0 -1
- package/out-tsc/src/flow/actions/open_ticket.js +0 -73
- package/out-tsc/src/flow/actions/open_ticket.js.map +0 -1
- package/out-tsc/test/actions/call_llm.test.js +0 -103
- package/out-tsc/test/actions/call_llm.test.js.map +0 -1
- package/src/flow/actions/call_llm.ts +0 -66
- package/src/flow/actions/call_webhook.ts +0 -143
- package/src/flow/actions/enter_flow.ts +0 -15
- package/src/flow/actions/open_ticket.ts +0 -83
- package/test/actions/call_llm.test.ts +0 -137
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/screenshots/truth/nodes/split_by_llm_categorize/editor/custom-input-and-result-name.png
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/src/events.ts
CHANGED
|
@@ -30,8 +30,10 @@ export interface ChannelEvent extends ContactEvent {
|
|
|
30
30
|
|
|
31
31
|
export interface ContactLanguageChangedEvent extends ContactEvent {
|
|
32
32
|
language: string;
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface ContactStatusChangedEvent extends ContactEvent {
|
|
36
|
+
status: string;
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
export interface OptInEvent extends ContactEvent {
|
package/src/flow/CanvasNode.ts
CHANGED
|
@@ -873,30 +873,7 @@ export class CanvasNode extends RapidElement {
|
|
|
873
873
|
private renderRouter(router: Router, ui: NodeUI) {
|
|
874
874
|
const nodeConfig = NODE_CONFIG[ui.type];
|
|
875
875
|
if (nodeConfig) {
|
|
876
|
-
// For tests that call renderRouter directly without setting this.node
|
|
877
|
-
const hasActions = this.node ? this.node.actions.length > 0 : false;
|
|
878
|
-
const isRemoving =
|
|
879
|
-
this.node &&
|
|
880
|
-
this.node.actions.length === 0 &&
|
|
881
|
-
this.actionRemovingState.has(this.node.uuid);
|
|
882
|
-
|
|
883
876
|
return html`<div class="router" style="position: relative;">
|
|
884
|
-
${!hasActions
|
|
885
|
-
? html` <button
|
|
886
|
-
class="remove-button"
|
|
887
|
-
@click=${(e: MouseEvent) => this.handleNodeRemoveClick(e)}
|
|
888
|
-
title="Remove node"
|
|
889
|
-
>
|
|
890
|
-
✕
|
|
891
|
-
</button>
|
|
892
|
-
<div
|
|
893
|
-
@mousedown=${(e: MouseEvent) => this.handleNodeMouseDown(e)}
|
|
894
|
-
@mouseup=${(e: MouseEvent) => this.handleNodeMouseUp(e)}
|
|
895
|
-
style="cursor: pointer;"
|
|
896
|
-
>
|
|
897
|
-
${this.renderNodeTitle(nodeConfig, isRemoving)}
|
|
898
|
-
</div>`
|
|
899
|
-
: ''}
|
|
900
877
|
${router.result_name
|
|
901
878
|
? html`<div
|
|
902
879
|
class="body"
|
|
@@ -969,7 +946,7 @@ export class CanvasNode extends RapidElement {
|
|
|
969
946
|
: ''}"
|
|
970
947
|
style="left:${this.ui.position.left}px;top:${this.ui.position.top}px"
|
|
971
948
|
>
|
|
972
|
-
${nodeConfig && nodeConfig.
|
|
949
|
+
${nodeConfig && nodeConfig.type !== 'execute_actions'
|
|
973
950
|
? html`<div class="router" style="position: relative;">
|
|
974
951
|
<button
|
|
975
952
|
class="remove-button"
|
|
@@ -987,7 +964,7 @@ export class CanvasNode extends RapidElement {
|
|
|
987
964
|
nodeConfig,
|
|
988
965
|
this.actionRemovingState.has(this.node.uuid)
|
|
989
966
|
)}
|
|
990
|
-
${nodeConfig.render(this.node)}
|
|
967
|
+
${nodeConfig.render ? nodeConfig.render(this.node) : null}
|
|
991
968
|
</div>
|
|
992
969
|
</div>`
|
|
993
970
|
: this.node.actions.length > 0
|
|
@@ -1007,20 +984,6 @@ export class CanvasNode extends RapidElement {
|
|
|
1007
984
|
(action) => action.uuid,
|
|
1008
985
|
(action, index) => this.renderAction(this.node, action, index)
|
|
1009
986
|
)}`
|
|
1010
|
-
: !this.node.router && nodeConfig && nodeConfig.name
|
|
1011
|
-
? html`<div class="router" style="position: relative;">
|
|
1012
|
-
<button
|
|
1013
|
-
class="remove-button"
|
|
1014
|
-
@click=${(e: MouseEvent) => this.handleNodeRemoveClick(e)}
|
|
1015
|
-
title="Remove node"
|
|
1016
|
-
>
|
|
1017
|
-
✕
|
|
1018
|
-
</button>
|
|
1019
|
-
${this.renderNodeTitle(
|
|
1020
|
-
nodeConfig,
|
|
1021
|
-
this.actionRemovingState.has(this.node.uuid)
|
|
1022
|
-
)}
|
|
1023
|
-
</div>`
|
|
1024
987
|
: ''}
|
|
1025
988
|
${this.node.router
|
|
1026
989
|
? html` ${this.renderRouter(this.node.router, this.ui)}
|
package/src/flow/Editor.ts
CHANGED
|
@@ -653,7 +653,7 @@ export class Editor extends RapidElement {
|
|
|
653
653
|
this.definition?.nodes.forEach((node) => {
|
|
654
654
|
const nodeElement = this.querySelector(`[id="${node.uuid}"]`);
|
|
655
655
|
if (nodeElement) {
|
|
656
|
-
const position = this.definition._ui
|
|
656
|
+
const position = this.definition._ui?.nodes[node.uuid]?.position;
|
|
657
657
|
if (position) {
|
|
658
658
|
const rect = nodeElement.getBoundingClientRect();
|
|
659
659
|
const canvasRect =
|
|
@@ -1085,8 +1085,11 @@ export class Editor extends RapidElement {
|
|
|
1085
1085
|
this.definition.nodes,
|
|
1086
1086
|
(node) => node.uuid,
|
|
1087
1087
|
(node) => {
|
|
1088
|
-
const position =
|
|
1089
|
-
|
|
1088
|
+
const position = this.definition._ui?.nodes[node.uuid]
|
|
1089
|
+
?.position || {
|
|
1090
|
+
left: 0,
|
|
1091
|
+
top: 0
|
|
1092
|
+
};
|
|
1090
1093
|
|
|
1091
1094
|
const dragging =
|
|
1092
1095
|
this.isDragging &&
|
package/src/flow/NodeEditor.ts
CHANGED
|
@@ -320,14 +320,6 @@ export class NodeEditor extends RapidElement {
|
|
|
320
320
|
this.isOpen = true;
|
|
321
321
|
}
|
|
322
322
|
|
|
323
|
-
private closeDialog(): void {
|
|
324
|
-
this.isOpen = false;
|
|
325
|
-
this.formData = {};
|
|
326
|
-
this.errors = {};
|
|
327
|
-
this.groupCollapseState = {};
|
|
328
|
-
this.groupHoverState = {};
|
|
329
|
-
}
|
|
330
|
-
|
|
331
323
|
private initializeFormData(): void {
|
|
332
324
|
const nodeConfig = this.getNodeConfig();
|
|
333
325
|
|
|
@@ -393,9 +385,51 @@ export class NodeEditor extends RapidElement {
|
|
|
393
385
|
}
|
|
394
386
|
});
|
|
395
387
|
|
|
388
|
+
// Convert select fields to array format
|
|
389
|
+
const config = this.getConfig();
|
|
390
|
+
if (config?.form) {
|
|
391
|
+
this.processSelectFields(processed, config.form);
|
|
392
|
+
}
|
|
393
|
+
|
|
396
394
|
this.formData = processed;
|
|
397
395
|
}
|
|
398
396
|
|
|
397
|
+
private processSelectFields(data: any, formConfig: any): void {
|
|
398
|
+
Object.entries(formConfig).forEach(
|
|
399
|
+
([fieldName, fieldConfig]: [string, any]) => {
|
|
400
|
+
const value = data[fieldName];
|
|
401
|
+
|
|
402
|
+
// Handle top-level select fields
|
|
403
|
+
if (fieldConfig.type === 'select' && value) {
|
|
404
|
+
data[fieldName] = this.convertToSelectArray(value);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// Handle select fields within array items
|
|
408
|
+
if (
|
|
409
|
+
fieldConfig.type === 'array' &&
|
|
410
|
+
Array.isArray(value) &&
|
|
411
|
+
fieldConfig.itemConfig
|
|
412
|
+
) {
|
|
413
|
+
value.forEach((item: any) => {
|
|
414
|
+
this.processSelectFields(item, fieldConfig.itemConfig);
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
private convertToSelectArray(value: any): any[] {
|
|
422
|
+
if (Array.isArray(value)) {
|
|
423
|
+
return value.map((v) =>
|
|
424
|
+
typeof v === 'string' ? { name: v, value: v } : v
|
|
425
|
+
);
|
|
426
|
+
} else if (typeof value === 'string') {
|
|
427
|
+
return [{ name: value, value: value }];
|
|
428
|
+
} else {
|
|
429
|
+
return [value];
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
399
433
|
private isKeyValueField(fieldName: string): boolean {
|
|
400
434
|
// Check if this field is configured as a key-value type
|
|
401
435
|
const config = this.getConfig();
|
|
@@ -533,6 +567,18 @@ export class NodeEditor extends RapidElement {
|
|
|
533
567
|
if (config.form) {
|
|
534
568
|
Object.entries(config.form).forEach(([fieldName, fieldConfig]) => {
|
|
535
569
|
const value = this.formData[fieldName];
|
|
570
|
+
if (fieldConfig.type === 'select' && fieldConfig.allowCreate) {
|
|
571
|
+
// check our values to see if any have arbitrary set
|
|
572
|
+
let selected = this.formData[fieldName];
|
|
573
|
+
selected = Array.isArray(selected)
|
|
574
|
+
? selected.find((v: any) => v.arbitrary)
|
|
575
|
+
: null;
|
|
576
|
+
|
|
577
|
+
if (selected && selected.arbitrary) {
|
|
578
|
+
errors[fieldName] =
|
|
579
|
+
'There was an error creating' + ' "' + selected.name + '"';
|
|
580
|
+
}
|
|
581
|
+
}
|
|
536
582
|
|
|
537
583
|
// Check required fields
|
|
538
584
|
if (
|
|
@@ -856,11 +902,6 @@ export class NodeEditor extends RapidElement {
|
|
|
856
902
|
// Handle different component types like ActionEditor does
|
|
857
903
|
if (target.tagName === 'TEMBA-CHECKBOX') {
|
|
858
904
|
value = target.checked;
|
|
859
|
-
} else if (
|
|
860
|
-
target.tagName === 'TEMBA-SELECT' &&
|
|
861
|
-
(target.multi || target.emails || target.tags)
|
|
862
|
-
) {
|
|
863
|
-
value = target.values || [];
|
|
864
905
|
} else if (target.values !== undefined) {
|
|
865
906
|
value = target.values;
|
|
866
907
|
} else {
|
|
@@ -5,7 +5,7 @@ import { renderNamedObjects } from '../utils';
|
|
|
5
5
|
|
|
6
6
|
export const add_contact_groups: ActionConfig = {
|
|
7
7
|
name: 'Add to Group',
|
|
8
|
-
color: COLORS.
|
|
8
|
+
color: COLORS.update,
|
|
9
9
|
render: (_node: Node, action: AddToGroup) => {
|
|
10
10
|
return html`<div>${renderNamedObjects(action.groups, 'group')}</div>`;
|
|
11
11
|
},
|
|
@@ -4,7 +4,7 @@ import { Node, AddContactUrn } from '../../store/flow-definition';
|
|
|
4
4
|
import { urnSchemeMap } from '../utils';
|
|
5
5
|
|
|
6
6
|
export const add_contact_urn: ActionConfig = {
|
|
7
|
-
name: 'Add
|
|
7
|
+
name: 'Add URN',
|
|
8
8
|
color: COLORS.update,
|
|
9
9
|
render: (_node: Node, action: AddContactUrn) => {
|
|
10
10
|
const friendlyScheme = urnSchemeMap[action.scheme] || action.scheme;
|
|
@@ -5,7 +5,7 @@ import { renderNamedObjects } from '../utils';
|
|
|
5
5
|
|
|
6
6
|
export const add_input_labels: ActionConfig = {
|
|
7
7
|
name: 'Add Input Labels',
|
|
8
|
-
color: COLORS.
|
|
8
|
+
color: COLORS.save,
|
|
9
9
|
render: (_node: Node, action: AddInputLabels) => {
|
|
10
10
|
return html`<div>${renderNamedObjects(action.labels, 'label')}</div>`;
|
|
11
11
|
},
|
|
@@ -5,7 +5,7 @@ import { renderNamedObjects } from '../utils';
|
|
|
5
5
|
|
|
6
6
|
export const remove_contact_groups: ActionConfig = {
|
|
7
7
|
name: 'Remove from Group',
|
|
8
|
-
color: COLORS.
|
|
8
|
+
color: COLORS.update,
|
|
9
9
|
render: (_node: Node, action: RemoveFromGroup) => {
|
|
10
10
|
if (action.all_groups) {
|
|
11
11
|
return html`<div>Remove from all groups</div>`;
|
|
@@ -19,7 +19,6 @@ export const send_email: ActionConfig = {
|
|
|
19
19
|
</div>
|
|
20
20
|
</div>`;
|
|
21
21
|
},
|
|
22
|
-
|
|
23
22
|
form: {
|
|
24
23
|
addresses: {
|
|
25
24
|
type: 'select',
|
|
@@ -44,6 +43,17 @@ export const send_email: ActionConfig = {
|
|
|
44
43
|
minHeight: 175
|
|
45
44
|
}
|
|
46
45
|
},
|
|
46
|
+
fromFormData: (formData: any): SendEmail => {
|
|
47
|
+
return {
|
|
48
|
+
uuid: formData.uuid,
|
|
49
|
+
type: 'send_email',
|
|
50
|
+
addresses: formData.addresses.map(
|
|
51
|
+
(addr: { name: string; value: string }) => addr.value
|
|
52
|
+
),
|
|
53
|
+
subject: formData.subject,
|
|
54
|
+
body: formData.body
|
|
55
|
+
};
|
|
56
|
+
},
|
|
47
57
|
validate: (action: SendEmail): ValidationResult => {
|
|
48
58
|
const errors: { [key: string]: string } = {};
|
|
49
59
|
|
|
@@ -2,6 +2,7 @@ import { html } from 'lit-html';
|
|
|
2
2
|
import { unsafeHTML } from 'lit-html/directives/unsafe-html.js';
|
|
3
3
|
import { ActionConfig, COLORS, ValidationResult } from '../types';
|
|
4
4
|
import { Node, SendMsg } from '../../store/flow-definition';
|
|
5
|
+
import { titleCase } from '../../utils';
|
|
5
6
|
|
|
6
7
|
export const send_msg: ActionConfig = {
|
|
7
8
|
name: 'Send Message',
|
|
@@ -65,10 +66,10 @@ export const send_msg: ActionConfig = {
|
|
|
65
66
|
type: {
|
|
66
67
|
type: 'select',
|
|
67
68
|
options: [
|
|
68
|
-
{ value: 'image',
|
|
69
|
-
{ value: 'audio',
|
|
70
|
-
{ value: 'video',
|
|
71
|
-
{ value: 'document',
|
|
69
|
+
{ value: 'image', name: 'Image' },
|
|
70
|
+
{ value: 'audio', name: 'Audio' },
|
|
71
|
+
{ value: 'video', name: 'Video' },
|
|
72
|
+
{ value: 'document', name: 'Document' }
|
|
72
73
|
],
|
|
73
74
|
required: true,
|
|
74
75
|
searchable: false
|
|
@@ -116,7 +117,10 @@ export const send_msg: ActionConfig = {
|
|
|
116
117
|
],
|
|
117
118
|
toFormData: (action: SendMsg) => {
|
|
118
119
|
// Extract runtime attachments from the text field attachments
|
|
119
|
-
const runtimeAttachments: {
|
|
120
|
+
const runtimeAttachments: {
|
|
121
|
+
type: { name: string; value: string };
|
|
122
|
+
expression: string;
|
|
123
|
+
}[] = [];
|
|
120
124
|
const staticAttachments: string[] = [];
|
|
121
125
|
|
|
122
126
|
if (action.attachments && Array.isArray(action.attachments)) {
|
|
@@ -127,13 +131,11 @@ export const send_msg: ActionConfig = {
|
|
|
127
131
|
const value = attachment.substring(colonIndex + 1);
|
|
128
132
|
|
|
129
133
|
if (!contentType.includes('/')) {
|
|
130
|
-
// This is a runtime attachment
|
|
131
134
|
runtimeAttachments.push({
|
|
132
|
-
type: contentType,
|
|
135
|
+
type: { name: titleCase(contentType), value: contentType },
|
|
133
136
|
expression: value
|
|
134
137
|
});
|
|
135
138
|
} else {
|
|
136
|
-
// This is a static attachment
|
|
137
139
|
staticAttachments.push(attachment);
|
|
138
140
|
}
|
|
139
141
|
}
|
|
@@ -165,10 +167,17 @@ export const send_msg: ActionConfig = {
|
|
|
165
167
|
// Combine static attachments from text field with runtime attachments
|
|
166
168
|
const staticAttachments = data.attachments || [];
|
|
167
169
|
const runtimeAttachments = (data.runtime_attachments || [])
|
|
168
|
-
.filter(
|
|
170
|
+
.filter(
|
|
171
|
+
(item: {
|
|
172
|
+
type: [{ name: string; value: string }];
|
|
173
|
+
expression: string;
|
|
174
|
+
}) => item && item.type && item.expression
|
|
175
|
+
) // Filter out invalid items
|
|
169
176
|
.map(
|
|
170
|
-
(item: {
|
|
171
|
-
|
|
177
|
+
(item: {
|
|
178
|
+
type: [{ name: string; value: string }];
|
|
179
|
+
expression: string;
|
|
180
|
+
}) => `${item.type[0].value}:${item.expression}`
|
|
172
181
|
);
|
|
173
182
|
|
|
174
183
|
result.attachments = [...staticAttachments, ...runtimeAttachments];
|
|
@@ -1,13 +1,36 @@
|
|
|
1
1
|
import { html } from 'lit-html';
|
|
2
|
-
import { ActionConfig, COLORS } from '../types';
|
|
2
|
+
import { ActionConfig, COLORS, ValidationResult } from '../types';
|
|
3
3
|
import { Node, SetContactChannel } from '../../store/flow-definition';
|
|
4
4
|
|
|
5
5
|
export const set_contact_channel: ActionConfig = {
|
|
6
|
-
name: 'Update
|
|
6
|
+
name: 'Update Channel',
|
|
7
7
|
color: COLORS.update,
|
|
8
8
|
render: (_node: Node, action: SetContactChannel) => {
|
|
9
|
-
return html`<div>
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
return html`<div>Set to <b>${action.channel.name}</b></div>`;
|
|
10
|
+
},
|
|
11
|
+
form: {
|
|
12
|
+
channel: {
|
|
13
|
+
type: 'select',
|
|
14
|
+
label: 'Channel',
|
|
15
|
+
required: true,
|
|
16
|
+
searchable: true,
|
|
17
|
+
clearable: false,
|
|
18
|
+
endpoint: '/api/v2/channels.json',
|
|
19
|
+
valueKey: 'uuid',
|
|
20
|
+
nameKey: 'name',
|
|
21
|
+
helpText: 'Select the channel to set for the contact'
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
validate: (formData: SetContactChannel): ValidationResult => {
|
|
25
|
+
const errors: { [key: string]: string } = {};
|
|
26
|
+
|
|
27
|
+
if (!formData.channel) {
|
|
28
|
+
errors.channel = 'Channel is required';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
valid: Object.keys(errors).length === 0,
|
|
33
|
+
errors
|
|
34
|
+
};
|
|
12
35
|
}
|
|
13
36
|
};
|
|
@@ -1,13 +1,67 @@
|
|
|
1
1
|
import { html } from 'lit-html';
|
|
2
|
-
import { ActionConfig, COLORS } from '../types';
|
|
2
|
+
import { ActionConfig, COLORS, ValidationResult } from '../types';
|
|
3
3
|
import { Node, SetContactField } from '../../store/flow-definition';
|
|
4
4
|
|
|
5
5
|
export const set_contact_field: ActionConfig = {
|
|
6
|
-
name: 'Update
|
|
6
|
+
name: 'Update Field',
|
|
7
7
|
color: COLORS.update,
|
|
8
8
|
render: (_node: Node, action: SetContactField) => {
|
|
9
9
|
return html`<div>
|
|
10
10
|
Set <b>${action.field.name}</b> to <b>${action.value}</b>
|
|
11
11
|
</div>`;
|
|
12
|
+
},
|
|
13
|
+
form: {
|
|
14
|
+
field: {
|
|
15
|
+
type: 'select',
|
|
16
|
+
label: 'Field',
|
|
17
|
+
required: true,
|
|
18
|
+
searchable: true,
|
|
19
|
+
clearable: false,
|
|
20
|
+
nameKey: 'name',
|
|
21
|
+
valueKey: 'key',
|
|
22
|
+
endpoint: '/api/v2/fields.json',
|
|
23
|
+
helpText: 'Select the contact field to update',
|
|
24
|
+
allowCreate: true,
|
|
25
|
+
createArbitraryOption: (input: string) => ({ key: input, name: input })
|
|
26
|
+
},
|
|
27
|
+
value: {
|
|
28
|
+
type: 'text',
|
|
29
|
+
label: 'Value',
|
|
30
|
+
placeholder: 'Enter field value...',
|
|
31
|
+
required: true,
|
|
32
|
+
evaluated: true,
|
|
33
|
+
helpText:
|
|
34
|
+
'The new value for the contact field. You can use expressions like @contact.name'
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
fromFormData: (formData: SetContactField): SetContactField => {
|
|
38
|
+
const field = formData.field[0];
|
|
39
|
+
return {
|
|
40
|
+
uuid: formData.uuid,
|
|
41
|
+
type: 'set_contact_field',
|
|
42
|
+
field: { name: field.name, key: field.key },
|
|
43
|
+
value: formData.value
|
|
44
|
+
};
|
|
45
|
+
},
|
|
46
|
+
validate: (formData: SetContactField): ValidationResult => {
|
|
47
|
+
const errors: { [key: string]: string } = {};
|
|
48
|
+
|
|
49
|
+
if (!formData.field) {
|
|
50
|
+
errors.field = 'Field is required';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!formData.value || formData.value.trim() === '') {
|
|
54
|
+
errors.value = 'Field value is required';
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
valid: Object.keys(errors).length === 0,
|
|
59
|
+
errors
|
|
60
|
+
};
|
|
61
|
+
},
|
|
62
|
+
sanitize: (formData: SetContactField): void => {
|
|
63
|
+
if (formData.value && typeof formData.value === 'string') {
|
|
64
|
+
formData.value = formData.value.trim();
|
|
65
|
+
}
|
|
12
66
|
}
|
|
13
67
|
};
|