@nyaruka/temba-components 0.131.1 → 0.131.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/publish.yml +4 -1
- package/CHANGELOG.md +75 -1
- package/demo/components/floating-tabs/example.html +400 -0
- package/demo/components/flow/index.html +1 -1
- package/demo/data/flows/food-order.json +2 -2
- package/demo/data/flows/sample-flow.json +113 -125
- package/demo/data/flows/voicemail.json +613 -0
- package/demo/index.html +6 -0
- package/dist/locales/es.js +5 -5
- package/dist/locales/es.js.map +1 -1
- package/dist/locales/fr.js +5 -5
- package/dist/locales/fr.js.map +1 -1
- package/dist/locales/locale-codes.js +11 -2
- package/dist/locales/locale-codes.js.map +1 -1
- package/dist/locales/pt.js +5 -5
- package/dist/locales/pt.js.map +1 -1
- package/dist/static/svg/index.svg +1 -1
- package/dist/temba-components.js +1773 -662
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/Icons.js +4 -1
- package/out-tsc/src/Icons.js.map +1 -1
- package/out-tsc/src/display/FloatingTab.js +167 -0
- package/out-tsc/src/display/FloatingTab.js.map +1 -0
- package/out-tsc/src/display/ProgressBar.js +22 -2
- package/out-tsc/src/display/ProgressBar.js.map +1 -1
- package/out-tsc/src/events.js.map +1 -1
- package/out-tsc/src/flow/CanvasMenu.js +200 -0
- package/out-tsc/src/flow/CanvasMenu.js.map +1 -0
- package/out-tsc/src/flow/CanvasNode.js +489 -47
- package/out-tsc/src/flow/CanvasNode.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +1417 -67
- package/out-tsc/src/flow/Editor.js.map +1 -1
- package/out-tsc/src/flow/NodeEditor.js +479 -112
- package/out-tsc/src/flow/NodeEditor.js.map +1 -1
- package/out-tsc/src/flow/NodeTypeSelector.js +540 -0
- package/out-tsc/src/flow/NodeTypeSelector.js.map +1 -0
- package/out-tsc/src/flow/StickyNote.js +12 -3
- package/out-tsc/src/flow/StickyNote.js.map +1 -1
- package/out-tsc/src/flow/actions/add_contact_groups.js +4 -3
- package/out-tsc/src/flow/actions/add_contact_groups.js.map +1 -1
- package/out-tsc/src/flow/actions/add_contact_urn.js +63 -4
- package/out-tsc/src/flow/actions/add_contact_urn.js.map +1 -1
- package/out-tsc/src/flow/actions/add_input_labels.js +4 -3
- package/out-tsc/src/flow/actions/add_input_labels.js.map +1 -1
- package/out-tsc/src/flow/actions/play_audio.js +3 -2
- package/out-tsc/src/flow/actions/play_audio.js.map +1 -1
- package/out-tsc/src/flow/actions/remove_contact_groups.js +7 -5
- package/out-tsc/src/flow/actions/remove_contact_groups.js.map +1 -1
- package/out-tsc/src/flow/actions/request_optin.js +3 -2
- package/out-tsc/src/flow/actions/request_optin.js.map +1 -1
- package/out-tsc/src/flow/actions/say_msg.js +3 -2
- package/out-tsc/src/flow/actions/say_msg.js.map +1 -1
- package/out-tsc/src/flow/actions/send_broadcast.js +77 -23
- package/out-tsc/src/flow/actions/send_broadcast.js.map +1 -1
- package/out-tsc/src/flow/actions/send_email.js +5 -5
- package/out-tsc/src/flow/actions/send_email.js.map +1 -1
- package/out-tsc/src/flow/actions/send_msg.js +101 -21
- package/out-tsc/src/flow/actions/send_msg.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_channel.js +6 -9
- package/out-tsc/src/flow/actions/set_contact_channel.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_field.js +20 -20
- package/out-tsc/src/flow/actions/set_contact_field.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_language.js +3 -2
- package/out-tsc/src/flow/actions/set_contact_language.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_name.js +3 -12
- package/out-tsc/src/flow/actions/set_contact_name.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_status.js +3 -2
- package/out-tsc/src/flow/actions/set_contact_status.js.map +1 -1
- package/out-tsc/src/flow/actions/set_run_result.js +4 -3
- package/out-tsc/src/flow/actions/set_run_result.js.map +1 -1
- package/out-tsc/src/flow/actions/start_session.js +181 -6
- package/out-tsc/src/flow/actions/start_session.js.map +1 -1
- package/out-tsc/src/flow/config.js +11 -23
- package/out-tsc/src/flow/config.js.map +1 -1
- package/out-tsc/src/flow/currencies.js +45 -0
- package/out-tsc/src/flow/currencies.js.map +1 -0
- package/out-tsc/src/flow/nodes/shared-rules.js +257 -0
- package/out-tsc/src/flow/nodes/shared-rules.js.map +1 -0
- package/out-tsc/src/flow/nodes/shared.js +71 -0
- package/out-tsc/src/flow/nodes/shared.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_airtime.js +211 -5
- package/out-tsc/src/flow/nodes/split_by_airtime.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_contact_field.js +152 -3
- package/out-tsc/src/flow/nodes/split_by_contact_field.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_expression.js +73 -2
- package/out-tsc/src/flow/nodes/split_by_expression.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_groups.js +18 -10
- package/out-tsc/src/flow/nodes/split_by_groups.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_intent.js +8 -0
- package/out-tsc/src/flow/nodes/split_by_intent.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_llm.js +11 -3
- package/out-tsc/src/flow/nodes/split_by_llm.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_llm_categorize.js +10 -3
- package/out-tsc/src/flow/nodes/split_by_llm_categorize.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_random.js +10 -4
- package/out-tsc/src/flow/nodes/split_by_random.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_resthook.js +113 -0
- package/out-tsc/src/flow/nodes/split_by_resthook.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_run_result.js +211 -3
- package/out-tsc/src/flow/nodes/split_by_run_result.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_scheme.js +158 -2
- package/out-tsc/src/flow/nodes/split_by_scheme.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_subflow.js +13 -5
- package/out-tsc/src/flow/nodes/split_by_subflow.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_ticket.js +10 -3
- package/out-tsc/src/flow/nodes/split_by_ticket.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_webhook.js +10 -3
- package/out-tsc/src/flow/nodes/split_by_webhook.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_digits.js +3 -2
- package/out-tsc/src/flow/nodes/wait_for_digits.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_menu.js +3 -2
- package/out-tsc/src/flow/nodes/wait_for_menu.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_response.js +38 -568
- package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -1
- package/out-tsc/src/flow/types.js +86 -12
- package/out-tsc/src/flow/types.js.map +1 -1
- package/out-tsc/src/flow/utils.js +101 -14
- package/out-tsc/src/flow/utils.js.map +1 -1
- package/out-tsc/src/form/FieldRenderer.js +2 -4
- package/out-tsc/src/form/FieldRenderer.js.map +1 -1
- package/out-tsc/src/interfaces.js +3 -0
- package/out-tsc/src/interfaces.js.map +1 -1
- package/out-tsc/src/layout/FloatingWindow.js +346 -0
- package/out-tsc/src/layout/FloatingWindow.js.map +1 -0
- package/out-tsc/src/list/SortableList.js +98 -33
- package/out-tsc/src/list/SortableList.js.map +1 -1
- package/out-tsc/src/live/ContactChat.js +6 -25
- package/out-tsc/src/live/ContactChat.js.map +1 -1
- package/out-tsc/src/locales/es.js +5 -5
- package/out-tsc/src/locales/es.js.map +1 -1
- package/out-tsc/src/locales/fr.js +5 -5
- package/out-tsc/src/locales/fr.js.map +1 -1
- package/out-tsc/src/locales/locale-codes.js +11 -2
- package/out-tsc/src/locales/locale-codes.js.map +1 -1
- package/out-tsc/src/locales/pt.js +5 -5
- package/out-tsc/src/locales/pt.js.map +1 -1
- package/out-tsc/src/store/AppState.js +120 -0
- package/out-tsc/src/store/AppState.js.map +1 -1
- package/out-tsc/src/utils.js +254 -13
- package/out-tsc/src/utils.js.map +1 -1
- package/out-tsc/temba-modules.js +8 -0
- package/out-tsc/temba-modules.js.map +1 -1
- package/out-tsc/test/ActionHelper.js +3 -3
- package/out-tsc/test/ActionHelper.js.map +1 -1
- package/out-tsc/test/NodeHelper.js +6 -3
- package/out-tsc/test/NodeHelper.js.map +1 -1
- package/out-tsc/test/actions/add_contact_urn.test.js +202 -0
- package/out-tsc/test/actions/add_contact_urn.test.js.map +1 -0
- package/out-tsc/test/actions/send_broadcast.test.js +148 -0
- package/out-tsc/test/actions/send_broadcast.test.js.map +1 -0
- package/out-tsc/test/actions/send_email.test.js +17 -23
- package/out-tsc/test/actions/send_email.test.js.map +1 -1
- package/out-tsc/test/actions/send_msg.test.js +33 -15
- package/out-tsc/test/actions/send_msg.test.js.map +1 -1
- package/out-tsc/test/actions/start_session.test.js +116 -0
- package/out-tsc/test/actions/start_session.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_airtime.test.js +604 -0
- package/out-tsc/test/nodes/split_by_airtime.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_contact_field.test.js +387 -0
- package/out-tsc/test/nodes/split_by_contact_field.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_expression.test.js +614 -0
- package/out-tsc/test/nodes/split_by_expression.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_random.test.js +3 -3
- package/out-tsc/test/nodes/split_by_random.test.js.map +1 -1
- package/out-tsc/test/nodes/split_by_resthook.test.js +337 -0
- package/out-tsc/test/nodes/split_by_resthook.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_run_result.test.js +920 -0
- package/out-tsc/test/nodes/split_by_run_result.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_scheme.test.js +399 -0
- package/out-tsc/test/nodes/split_by_scheme.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_subflow.test.js +333 -0
- package/out-tsc/test/nodes/split_by_subflow.test.js.map +1 -0
- package/out-tsc/test/nodes/wait_for_digits.test.js +2 -2
- package/out-tsc/test/nodes/wait_for_digits.test.js.map +1 -1
- package/out-tsc/test/nodes/wait_for_response.test.js +2 -1
- package/out-tsc/test/nodes/wait_for_response.test.js.map +1 -1
- package/out-tsc/test/temba-action-drag-between-nodes.test.js +252 -0
- package/out-tsc/test/temba-action-drag-between-nodes.test.js.map +1 -0
- package/out-tsc/test/temba-canvas-menu.test.js +122 -0
- package/out-tsc/test/temba-canvas-menu.test.js.map +1 -0
- package/out-tsc/test/temba-floating-tab.test.js +91 -0
- package/out-tsc/test/temba-floating-tab.test.js.map +1 -0
- package/out-tsc/test/temba-floating-window.test.js +301 -0
- package/out-tsc/test/temba-floating-window.test.js.map +1 -0
- package/out-tsc/test/temba-flow-editor-node.test.js +202 -2
- package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
- package/out-tsc/test/temba-flow-editor.test.js +7 -8
- package/out-tsc/test/temba-flow-editor.test.js.map +1 -1
- package/out-tsc/test/temba-localization.test.js +471 -0
- package/out-tsc/test/temba-localization.test.js.map +1 -0
- package/out-tsc/test/temba-node-editor.test.js +3 -1
- package/out-tsc/test/temba-node-editor.test.js.map +1 -1
- package/out-tsc/test/temba-node-type-selector.test.js +265 -0
- package/out-tsc/test/temba-node-type-selector.test.js.map +1 -0
- package/out-tsc/test/temba-omnibox.test.js +2 -1
- package/out-tsc/test/temba-omnibox.test.js.map +1 -1
- package/out-tsc/test/temba-sortable-list.test.js +51 -0
- package/out-tsc/test/temba-sortable-list.test.js.map +1 -1
- package/out-tsc/test/temba-utils-index.test.js +1 -27
- package/out-tsc/test/temba-utils-index.test.js.map +1 -1
- package/out-tsc/test/utils.test.js +20 -0
- package/out-tsc/test/utils.test.js.map +1 -1
- package/package.json +2 -1
- package/screenshots/truth/actions/add_contact_groups/editor/descriptive-group-names.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/editor/long-group-names.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/editor/many-groups.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/editor/multiple-groups.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/editor/single-group.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/descriptive-group-names.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/long-group-names.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/many-groups.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/multiple-groups.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/single-group.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/expression-facebook.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/expression-phone.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/facebook-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/instagram-handle.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/line-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/phone-number.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/telegram-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/viber-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/wechat-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/editor/whatsapp.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/expression-facebook.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/expression-phone.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/facebook-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/instagram-handle.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/line-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/phone-number.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/telegram-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/viber-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/wechat-id.png +0 -0
- package/screenshots/truth/actions/add_contact_urn/render/whatsapp.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/cleanup-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/long-descriptive-group-names.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/many-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/multiple-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/remove-from-all-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/single-group.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/cleanup-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/long-descriptive-group-names.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/many-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/multiple-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/remove-from-all-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/single-group.png +0 -0
- package/screenshots/truth/actions/send_broadcast/editor/contacts-only.png +0 -0
- package/screenshots/truth/actions/send_broadcast/editor/groups-and-contacts.png +0 -0
- package/screenshots/truth/actions/send_broadcast/editor/groups-only.png +0 -0
- package/screenshots/truth/actions/send_broadcast/editor/many-groups.png +0 -0
- package/screenshots/truth/actions/send_broadcast/editor/multiline-text.png +0 -0
- package/screenshots/truth/actions/send_broadcast/editor/with-attachments.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/contacts-only.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/groups-and-contacts.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/groups-only.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/many-groups.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/multiline-text.png +0 -0
- package/screenshots/truth/actions/send_broadcast/render/with-attachments.png +0 -0
- package/screenshots/truth/actions/send_email/editor/complex-business-email.png +0 -0
- package/screenshots/truth/actions/send_email/editor/empty-body.png +0 -0
- package/screenshots/truth/actions/send_email/editor/empty-subject.png +0 -0
- package/screenshots/truth/actions/send_email/editor/long-subject.png +0 -0
- package/screenshots/truth/actions/send_email/editor/multiline-body.png +0 -0
- package/screenshots/truth/actions/send_email/editor/multiple-recipients.png +0 -0
- package/screenshots/truth/actions/send_email/editor/simple-email.png +0 -0
- package/screenshots/truth/actions/send_email/editor/with-expressions.png +0 -0
- package/screenshots/truth/actions/send_email/render/complex-business-email.png +0 -0
- package/screenshots/truth/actions/send_email/render/empty-body.png +0 -0
- package/screenshots/truth/actions/send_email/render/empty-subject.png +0 -0
- package/screenshots/truth/actions/send_email/render/long-subject.png +0 -0
- package/screenshots/truth/actions/send_email/render/multiline-body.png +0 -0
- package/screenshots/truth/actions/send_email/render/multiple-recipients.png +0 -0
- package/screenshots/truth/actions/send_email/render/simple-email.png +0 -0
- package/screenshots/truth/actions/send_email/render/with-expressions.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/long-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/multiline-text-with-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/simple-text.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-with-linebreaks.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-with-many-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-with-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-without-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/long-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/multiline-text-with-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/simple-text.png +0 -0
- package/screenshots/truth/actions/send_msg/render/text-with-linebreaks.png +0 -0
- package/screenshots/truth/actions/send_msg/render/text-with-many-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/text-with-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/render/text-without-quick-replies.png +0 -0
- package/screenshots/truth/actions/start_session/editor/contact-query.png +0 -0
- package/screenshots/truth/actions/start_session/editor/contacts-only.png +0 -0
- package/screenshots/truth/actions/start_session/editor/create-contact.png +0 -0
- package/screenshots/truth/actions/start_session/editor/groups-and-contacts.png +0 -0
- package/screenshots/truth/actions/start_session/editor/groups-only.png +0 -0
- package/screenshots/truth/actions/start_session/editor/many-recipients.png +0 -0
- package/screenshots/truth/actions/start_session/render/contact-query.png +0 -0
- package/screenshots/truth/actions/start_session/render/contacts-only.png +0 -0
- package/screenshots/truth/actions/start_session/render/create-contact.png +0 -0
- package/screenshots/truth/actions/start_session/render/groups-and-contacts.png +0 -0
- package/screenshots/truth/actions/start_session/render/groups-only.png +0 -0
- package/screenshots/truth/actions/start_session/render/many-recipients.png +0 -0
- package/screenshots/truth/canvas-menu/open.png +0 -0
- package/screenshots/truth/editor/router.png +0 -0
- package/screenshots/truth/editor/wait.png +0 -0
- package/screenshots/truth/floating-tab/default.png +0 -0
- package/screenshots/truth/floating-tab/gray.png +0 -0
- package/screenshots/truth/floating-tab/green.png +0 -0
- package/screenshots/truth/floating-tab/hidden.png +0 -0
- package/screenshots/truth/floating-tab/hover.png +0 -0
- package/screenshots/truth/floating-tab/purple.png +0 -0
- package/screenshots/truth/floating-window/chromeless.png +0 -0
- package/screenshots/truth/floating-window/custom-size.png +0 -0
- package/screenshots/truth/floating-window/default.png +0 -0
- package/screenshots/truth/floating-window/with-header.png +0 -0
- package/screenshots/truth/list/fields-dragging.png +0 -0
- package/screenshots/truth/list/sortable-dragging.png +0 -0
- package/screenshots/truth/node-type-selector/action-mode.png +0 -0
- package/screenshots/truth/node-type-selector/split-mode.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/editor/information-extraction.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/editor/sentiment-analysis.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/editor/summarization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/editor/translation-task.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/information-extraction.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/sentiment-analysis.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/summarization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/translation-task.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/basic-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/custom-input-and-result-name.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/feedback-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/many-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/minimal-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/basic-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/custom-input-and-result-name.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/feedback-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/many-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/render/minimal-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_random/editor/ab-test-multiple-variants.png +0 -0
- package/screenshots/truth/nodes/split_by_random/editor/sampling-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/editor/three-way-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/editor/two-bucket-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/ab-test-multiple-variants.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/sampling-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/three-way-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/render/two-bucket-split.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/basic-digits-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/phone-number-collection.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/single-digit-with-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/verification-code.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/basic-digits-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/phone-number-collection.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/single-digit-with-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/render/verification-code.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/basic-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/custom-result-name.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/no-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/short-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/basic-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/custom-result-name.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/no-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/short-timeout.png +0 -0
- package/src/Icons.ts +4 -1
- package/src/display/FloatingTab.ts +174 -0
- package/src/display/ProgressBar.ts +22 -2
- package/src/events.ts +2 -8
- package/src/flow/CanvasMenu.ts +217 -0
- package/src/flow/CanvasNode.ts +596 -40
- package/src/flow/Editor.ts +1721 -45
- package/src/flow/NodeEditor.ts +621 -144
- package/src/flow/NodeTypeSelector.ts +636 -0
- package/src/flow/StickyNote.ts +12 -3
- package/src/flow/actions/add_contact_groups.ts +5 -4
- package/src/flow/actions/add_contact_urn.ts +78 -4
- package/src/flow/actions/add_input_labels.ts +5 -4
- package/src/flow/actions/play_audio.ts +3 -2
- package/src/flow/actions/remove_contact_groups.ts +16 -6
- package/src/flow/actions/request_optin.ts +3 -2
- package/src/flow/actions/say_msg.ts +3 -2
- package/src/flow/actions/send_broadcast.ts +86 -23
- package/src/flow/actions/send_email.ts +12 -6
- package/src/flow/actions/send_msg.ts +155 -34
- package/src/flow/actions/set_contact_channel.ts +6 -11
- package/src/flow/actions/set_contact_field.ts +21 -25
- package/src/flow/actions/set_contact_language.ts +11 -4
- package/src/flow/actions/set_contact_name.ts +4 -15
- package/src/flow/actions/set_contact_status.ts +4 -3
- package/src/flow/actions/set_run_result.ts +5 -4
- package/src/flow/actions/start_session.ts +210 -6
- package/src/flow/config.ts +11 -23
- package/src/flow/currencies.ts +51 -0
- package/src/flow/nodes/shared-rules.ts +301 -0
- package/src/flow/nodes/shared.ts +87 -0
- package/src/flow/nodes/split_by_airtime.ts +255 -5
- package/src/flow/nodes/split_by_contact_field.ts +195 -3
- package/src/flow/nodes/split_by_expression.ts +104 -2
- package/src/flow/nodes/split_by_groups.ts +26 -11
- package/src/flow/nodes/split_by_intent.ts +8 -0
- package/src/flow/nodes/split_by_llm.ts +22 -4
- package/src/flow/nodes/split_by_llm_categorize.ts +22 -5
- package/src/flow/nodes/split_by_random.ts +16 -6
- package/src/flow/nodes/split_by_resthook.ts +140 -0
- package/src/flow/nodes/split_by_run_result.ts +259 -3
- package/src/flow/nodes/split_by_scheme.ts +202 -2
- package/src/flow/nodes/split_by_subflow.ts +17 -5
- package/src/flow/nodes/split_by_ticket.ts +15 -4
- package/src/flow/nodes/split_by_webhook.ts +17 -6
- package/src/flow/nodes/wait_for_digits.ts +3 -2
- package/src/flow/nodes/wait_for_menu.ts +3 -2
- package/src/flow/nodes/wait_for_response.ts +59 -680
- package/src/flow/types.ts +156 -23
- package/src/flow/utils.ts +108 -14
- package/src/form/FieldRenderer.ts +2 -4
- package/src/interfaces.ts +3 -0
- package/src/layout/FloatingWindow.ts +386 -0
- package/src/list/SortableList.ts +109 -34
- package/src/live/ContactChat.ts +7 -25
- package/src/locales/es.ts +18 -13
- package/src/locales/fr.ts +18 -13
- package/src/locales/locale-codes.ts +11 -2
- package/src/locales/pt.ts +18 -13
- package/src/store/AppState.ts +173 -0
- package/src/store/flow-definition.d.ts +2 -5
- package/src/utils.ts +332 -12
- package/static/api/channels.json +46 -0
- package/static/api/llms.json +18 -0
- package/static/api/resthooks.json +31 -0
- package/static/svg/index.svg +1 -1
- package/static/svg/work/traced/lightning-02.svg +1 -0
- package/static/svg/work/used/lightning-02.svg +3 -0
- package/temba-modules.ts +8 -0
- package/test/ActionHelper.ts +3 -3
- package/test/NodeHelper.ts +6 -3
- package/test/actions/add_contact_urn.test.ts +287 -0
- package/test/actions/send_broadcast.test.ts +190 -0
- package/test/actions/send_email.test.ts +17 -23
- package/test/actions/send_msg.test.ts +39 -15
- package/test/actions/start_session.test.ts +151 -0
- package/test/nodes/split_by_airtime.test.ts +673 -0
- package/test/nodes/split_by_contact_field.test.ts +451 -0
- package/test/nodes/split_by_expression.test.ts +751 -0
- package/test/nodes/split_by_random.test.ts +3 -3
- package/test/nodes/split_by_resthook.test.ts +398 -0
- package/test/nodes/split_by_run_result.test.ts +1109 -0
- package/test/nodes/split_by_scheme.test.ts +486 -0
- package/test/nodes/split_by_subflow.test.ts +381 -0
- package/test/nodes/wait_for_digits.test.ts +2 -2
- package/test/nodes/wait_for_response.test.ts +2 -1
- package/test/temba-action-drag-between-nodes.test.ts +301 -0
- package/test/temba-canvas-menu.test.ts +156 -0
- package/test/temba-floating-tab.test.ts +110 -0
- package/test/temba-floating-window.test.ts +477 -0
- package/test/temba-flow-editor-node.test.ts +246 -2
- package/test/temba-flow-editor.test.ts +7 -8
- package/test/temba-localization.test.ts +611 -0
- package/test/temba-node-editor.test.ts +3 -1
- package/test/temba-node-type-selector.test.ts +355 -0
- package/test/temba-omnibox.test.ts +2 -1
- package/test/temba-sortable-list.test.ts +69 -0
- package/test/temba-utils-index.test.ts +0 -35
- package/test/utils.test.ts +22 -0
- package/test-assets/contacts/history.json +14 -21
- package/test-assets/select/llms.json +2 -2
- package/web-dev-server.config.mjs +49 -1
- package/web-test-runner.config.mjs +0 -1
- package/out-tsc/src/flow/actions/call_classifier.js +0 -11
- package/out-tsc/src/flow/actions/call_classifier.js.map +0 -1
- package/out-tsc/src/flow/actions/call_resthook.js +0 -11
- package/out-tsc/src/flow/actions/call_resthook.js.map +0 -1
- package/out-tsc/src/flow/actions/split_by_expression_example.js +0 -77
- package/out-tsc/src/flow/actions/split_by_expression_example.js.map +0 -1
- package/out-tsc/src/flow/actions/transfer_airtime.js +0 -11
- package/out-tsc/src/flow/actions/transfer_airtime.js.map +0 -1
- package/out-tsc/src/flow/nodes/wait_for_audio.js +0 -7
- package/out-tsc/src/flow/nodes/wait_for_audio.js.map +0 -1
- package/out-tsc/src/flow/nodes/wait_for_image.js +0 -7
- package/out-tsc/src/flow/nodes/wait_for_image.js.map +0 -1
- package/out-tsc/src/flow/nodes/wait_for_location.js +0 -7
- package/out-tsc/src/flow/nodes/wait_for_location.js.map +0 -1
- package/out-tsc/src/flow/nodes/wait_for_video.js +0 -7
- package/out-tsc/src/flow/nodes/wait_for_video.js.map +0 -1
- package/src/flow/actions/call_classifier.ts +0 -12
- package/src/flow/actions/call_resthook.ts +0 -12
- package/src/flow/actions/split_by_expression_example.ts +0 -88
- package/src/flow/actions/transfer_airtime.ts +0 -12
- package/src/flow/nodes/wait_for_audio.ts +0 -7
- package/src/flow/nodes/wait_for_image.ts +0 -7
- package/src/flow/nodes/wait_for_location.ts +0 -7
- package/src/flow/nodes/wait_for_video.ts +0 -7
|
@@ -3,10 +3,13 @@ import { html, css } from 'lit';
|
|
|
3
3
|
import { property, state } from 'lit/decorators.js';
|
|
4
4
|
import { RapidElement } from '../RapidElement';
|
|
5
5
|
import { NODE_CONFIG, ACTION_CONFIG } from './config';
|
|
6
|
+
import { ACTION_GROUP_METADATA, SPLIT_GROUP_METADATA } from './types';
|
|
6
7
|
import { CustomEventType } from '../interfaces';
|
|
7
8
|
import { generateUUID } from '../utils';
|
|
8
9
|
import { FieldRenderer } from '../form/FieldRenderer';
|
|
9
10
|
import { renderMarkdownInline } from '../markdown';
|
|
11
|
+
import { fromStore, zustand } from '../store/AppState';
|
|
12
|
+
import { getStore } from '../store/Store';
|
|
10
13
|
export class NodeEditor extends RapidElement {
|
|
11
14
|
constructor() {
|
|
12
15
|
super(...arguments);
|
|
@@ -16,6 +19,7 @@ export class NodeEditor extends RapidElement {
|
|
|
16
19
|
this.errors = {};
|
|
17
20
|
this.groupCollapseState = {};
|
|
18
21
|
this.groupHoverState = {};
|
|
22
|
+
this.revealedOptionalFields = new Set();
|
|
19
23
|
}
|
|
20
24
|
static get styles() {
|
|
21
25
|
return css `
|
|
@@ -25,7 +29,6 @@ export class NodeEditor extends RapidElement {
|
|
|
25
29
|
flex-direction: column;
|
|
26
30
|
gap: 15px;
|
|
27
31
|
min-width: 400px;
|
|
28
|
-
padding-bottom: 40px;
|
|
29
32
|
|
|
30
33
|
--color-bubble-bg: rgba(var(--primary-rgb), 0.7);
|
|
31
34
|
--color-bubble-border: rgba(0, 0, 0, 0.2);
|
|
@@ -88,6 +91,28 @@ export class NodeEditor extends RapidElement {
|
|
|
88
91
|
align-items: center;
|
|
89
92
|
}
|
|
90
93
|
|
|
94
|
+
.form-row-wrapper {
|
|
95
|
+
display: flex;
|
|
96
|
+
flex-direction: column;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.form-row-label {
|
|
100
|
+
margin-bottom: 5px;
|
|
101
|
+
margin-left: 4px;
|
|
102
|
+
display: block;
|
|
103
|
+
font-weight: 400;
|
|
104
|
+
font-size: var(--label-size);
|
|
105
|
+
letter-spacing: 0.05em;
|
|
106
|
+
line-height: normal;
|
|
107
|
+
color: var(--color-label, #777);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.form-row-help {
|
|
111
|
+
font-size: 12px;
|
|
112
|
+
color: #666;
|
|
113
|
+
margin-top: 6px;
|
|
114
|
+
}
|
|
115
|
+
|
|
91
116
|
.form-group {
|
|
92
117
|
border: 1px solid #e0e0e0;
|
|
93
118
|
border-radius: 6px;
|
|
@@ -276,6 +301,69 @@ export class NodeEditor extends RapidElement {
|
|
|
276
301
|
.gutter-fields temba-select {
|
|
277
302
|
min-width: 120px;
|
|
278
303
|
}
|
|
304
|
+
|
|
305
|
+
.optional-field-link {
|
|
306
|
+
margin: 10px 0;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
.optional-field-link a {
|
|
310
|
+
color: var(--color-link-primary, #0066cc);
|
|
311
|
+
text-decoration: none;
|
|
312
|
+
font-size: 13px;
|
|
313
|
+
cursor: pointer;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
.optional-field-link a:hover {
|
|
317
|
+
text-decoration: underline;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
.original-value {
|
|
321
|
+
background: #fff8dc;
|
|
322
|
+
padding: 10px;
|
|
323
|
+
border-radius: 4px;
|
|
324
|
+
font-size: 13px;
|
|
325
|
+
color: #666;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
.original-value-content {
|
|
329
|
+
color: #333;
|
|
330
|
+
white-space: pre-wrap;
|
|
331
|
+
word-break: break-word;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
.category-localization-table {
|
|
335
|
+
width: 100%;
|
|
336
|
+
display: flex;
|
|
337
|
+
flex-direction: column;
|
|
338
|
+
gap: 5px;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
.category-localization-row {
|
|
342
|
+
display: grid;
|
|
343
|
+
grid-template-columns: 40% 60%;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.category-localization-row:last-child {
|
|
347
|
+
border-bottom: none;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
.original-name {
|
|
351
|
+
padding: 10px 20px;
|
|
352
|
+
background: #fff8dc;
|
|
353
|
+
display: flex;
|
|
354
|
+
align-items: center;
|
|
355
|
+
border-radius: var(--curvature);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
.localized-name {
|
|
359
|
+
padding: 10px;
|
|
360
|
+
display: flex;
|
|
361
|
+
align-items: center;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
.localized-name temba-textinput {
|
|
365
|
+
width: 100%;
|
|
366
|
+
}
|
|
279
367
|
`;
|
|
280
368
|
}
|
|
281
369
|
connectedCallback() {
|
|
@@ -307,11 +395,20 @@ export class NodeEditor extends RapidElement {
|
|
|
307
395
|
this.isOpen = true;
|
|
308
396
|
}
|
|
309
397
|
initializeFormData() {
|
|
398
|
+
var _a, _b, _c, _d, _e;
|
|
310
399
|
const nodeConfig = this.getNodeConfig();
|
|
311
400
|
if ((!nodeConfig || nodeConfig.type === 'execute_actions') && this.action) {
|
|
312
401
|
// Action editing mode - use action config
|
|
313
402
|
const actionConfig = ACTION_CONFIG[this.action.type];
|
|
314
|
-
|
|
403
|
+
// Check if we're in localization mode
|
|
404
|
+
if (this.isTranslating &&
|
|
405
|
+
(actionConfig === null || actionConfig === void 0 ? void 0 : actionConfig.localizable) &&
|
|
406
|
+
actionConfig.toLocalizationFormData) {
|
|
407
|
+
// Get localized values for this action
|
|
408
|
+
const localization = ((_c = (_b = (_a = this.flowDefinition) === null || _a === void 0 ? void 0 : _a.localization) === null || _b === void 0 ? void 0 : _b[this.languageCode]) === null || _c === void 0 ? void 0 : _c[this.action.uuid]) || {};
|
|
409
|
+
this.formData = actionConfig.toLocalizationFormData(this.action, localization);
|
|
410
|
+
}
|
|
411
|
+
else if (actionConfig === null || actionConfig === void 0 ? void 0 : actionConfig.toFormData) {
|
|
315
412
|
this.formData = actionConfig.toFormData(this.action);
|
|
316
413
|
}
|
|
317
414
|
else {
|
|
@@ -325,8 +422,16 @@ export class NodeEditor extends RapidElement {
|
|
|
325
422
|
else if (this.node) {
|
|
326
423
|
// Node editing mode - use node config
|
|
327
424
|
const nodeConfig = this.getNodeConfig();
|
|
328
|
-
|
|
329
|
-
|
|
425
|
+
// Check if we're in localization mode for a node with localizable categories
|
|
426
|
+
if (this.isTranslating &&
|
|
427
|
+
(nodeConfig === null || nodeConfig === void 0 ? void 0 : nodeConfig.localizable) === 'categories' &&
|
|
428
|
+
nodeConfig.toLocalizationFormData) {
|
|
429
|
+
// Get localized values for this node's categories
|
|
430
|
+
const localization = ((_e = (_d = this.flowDefinition) === null || _d === void 0 ? void 0 : _d.localization) === null || _e === void 0 ? void 0 : _e[this.languageCode]) || {};
|
|
431
|
+
this.formData = nodeConfig.toLocalizationFormData(this.node, localization);
|
|
432
|
+
}
|
|
433
|
+
else if (nodeConfig === null || nodeConfig === void 0 ? void 0 : nodeConfig.toFormData) {
|
|
434
|
+
this.formData = nodeConfig.toFormData(this.node, this.nodeUI);
|
|
330
435
|
}
|
|
331
436
|
else {
|
|
332
437
|
this.formData = { ...this.node };
|
|
@@ -433,8 +538,12 @@ export class NodeEditor extends RapidElement {
|
|
|
433
538
|
return this.nodeUI.type ? NODE_CONFIG[this.nodeUI.type] : null;
|
|
434
539
|
}
|
|
435
540
|
getHeaderColor() {
|
|
541
|
+
var _a, _b;
|
|
436
542
|
const config = this.getConfig();
|
|
437
|
-
return (config === null || config === void 0 ? void 0 : config.
|
|
543
|
+
return (config === null || config === void 0 ? void 0 : config.group)
|
|
544
|
+
? ((_a = ACTION_GROUP_METADATA[config.group]) === null || _a === void 0 ? void 0 : _a.color) ||
|
|
545
|
+
((_b = SPLIT_GROUP_METADATA[config.group]) === null || _b === void 0 ? void 0 : _b.color)
|
|
546
|
+
: '#aaaaaa';
|
|
438
547
|
}
|
|
439
548
|
handleDialogButtonClick(event) {
|
|
440
549
|
const button = event.detail.button;
|
|
@@ -446,24 +555,77 @@ export class NodeEditor extends RapidElement {
|
|
|
446
555
|
}
|
|
447
556
|
}
|
|
448
557
|
handleSave() {
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
if (!validation.valid) {
|
|
452
|
-
this.errors = validation.errors;
|
|
453
|
-
// Expand any groups that contain validation errors
|
|
454
|
-
this.expandGroupsWithErrors(validation.errors);
|
|
455
|
-
return;
|
|
456
|
-
}
|
|
457
|
-
// Process form data to convert key-value arrays to Records before saving
|
|
558
|
+
var _a, _b, _c, _d;
|
|
559
|
+
// Process form data first
|
|
458
560
|
const processedFormData = this.processFormDataForSave();
|
|
561
|
+
// Skip validation if we're in localization mode
|
|
562
|
+
// (localization only deals with translating text, not changing structure)
|
|
563
|
+
if (!this.isTranslating) {
|
|
564
|
+
// Validate the form
|
|
565
|
+
const validation = this.validateForm();
|
|
566
|
+
if (!validation.valid) {
|
|
567
|
+
this.errors = validation.errors;
|
|
568
|
+
// Expand any groups that contain validation errors
|
|
569
|
+
this.expandGroupsWithErrors(validation.errors);
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
// Check if we're in localization mode
|
|
574
|
+
if (this.isTranslating) {
|
|
575
|
+
// Handle action localization
|
|
576
|
+
if (this.action) {
|
|
577
|
+
const actionConfig = ACTION_CONFIG[this.action.type];
|
|
578
|
+
if ((actionConfig === null || actionConfig === void 0 ? void 0 : actionConfig.localizable) &&
|
|
579
|
+
actionConfig.fromLocalizationFormData) {
|
|
580
|
+
// Save to localization structure
|
|
581
|
+
const localizationData = actionConfig.fromLocalizationFormData(processedFormData, this.action);
|
|
582
|
+
// Update the flow definition's localization
|
|
583
|
+
this.updateLocalization(this.languageCode, this.action.uuid, localizationData);
|
|
584
|
+
// Close the dialog
|
|
585
|
+
this.fireCustomEvent(CustomEventType.NodeEditCancelled, {});
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
// Handle node localization (for router categories)
|
|
590
|
+
if (this.node) {
|
|
591
|
+
const nodeConfig = this.getNodeConfig();
|
|
592
|
+
if ((nodeConfig === null || nodeConfig === void 0 ? void 0 : nodeConfig.localizable) === 'categories' &&
|
|
593
|
+
nodeConfig.fromLocalizationFormData) {
|
|
594
|
+
// Get localization data for all categories
|
|
595
|
+
const localizationData = nodeConfig.fromLocalizationFormData(processedFormData, this.node);
|
|
596
|
+
const languageLocalization = ((_b = (_a = this.flowDefinition) === null || _a === void 0 ? void 0 : _a.localization) === null || _b === void 0 ? void 0 : _b[this.languageCode]) || {};
|
|
597
|
+
const categories = ((_d = (_c = this.node) === null || _c === void 0 ? void 0 : _c.router) === null || _d === void 0 ? void 0 : _d.categories) || [];
|
|
598
|
+
categories.forEach((category) => {
|
|
599
|
+
const categoryUuid = category.uuid;
|
|
600
|
+
const nextLocalization = localizationData[categoryUuid];
|
|
601
|
+
if (nextLocalization) {
|
|
602
|
+
this.updateLocalization(this.languageCode, categoryUuid, nextLocalization);
|
|
603
|
+
}
|
|
604
|
+
else if (languageLocalization[categoryUuid]) {
|
|
605
|
+
// Remove existing localization when the translation was cleared
|
|
606
|
+
this.updateLocalization(this.languageCode, categoryUuid, {});
|
|
607
|
+
}
|
|
608
|
+
});
|
|
609
|
+
// Close the dialog
|
|
610
|
+
this.fireCustomEvent(CustomEventType.NodeEditCancelled, {});
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
}
|
|
459
615
|
// Determine whether to use node or action saving based on context
|
|
460
616
|
// If we have a node with a router, always use node saving (even if action is set)
|
|
461
617
|
// because router configuration is handled at the node level
|
|
462
618
|
if (this.node && this.node.router) {
|
|
463
619
|
// Node editing mode with router - use formDataToNode
|
|
464
620
|
const updatedNode = this.formDataToNode(processedFormData);
|
|
621
|
+
// Generate UI config if the node config provides a toUIConfig function
|
|
622
|
+
const nodeConfig = this.getNodeConfig();
|
|
623
|
+
const uiConfig = (nodeConfig === null || nodeConfig === void 0 ? void 0 : nodeConfig.toUIConfig)
|
|
624
|
+
? nodeConfig.toUIConfig(processedFormData)
|
|
625
|
+
: undefined;
|
|
465
626
|
this.fireCustomEvent(CustomEventType.NodeSaved, {
|
|
466
|
-
node: updatedNode
|
|
627
|
+
node: updatedNode,
|
|
628
|
+
uiConfig
|
|
467
629
|
});
|
|
468
630
|
}
|
|
469
631
|
else if (this.action) {
|
|
@@ -476,11 +638,23 @@ export class NodeEditor extends RapidElement {
|
|
|
476
638
|
else if (this.node) {
|
|
477
639
|
// Node editing mode without router
|
|
478
640
|
const updatedNode = this.formDataToNode(processedFormData);
|
|
641
|
+
// Generate UI config if the node config provides a toUIConfig function
|
|
642
|
+
const nodeConfig = this.getNodeConfig();
|
|
643
|
+
const uiConfig = (nodeConfig === null || nodeConfig === void 0 ? void 0 : nodeConfig.toUIConfig)
|
|
644
|
+
? nodeConfig.toUIConfig(processedFormData)
|
|
645
|
+
: undefined;
|
|
479
646
|
this.fireCustomEvent(CustomEventType.NodeSaved, {
|
|
480
|
-
node: updatedNode
|
|
647
|
+
node: updatedNode,
|
|
648
|
+
uiConfig
|
|
481
649
|
});
|
|
482
650
|
}
|
|
483
651
|
}
|
|
652
|
+
updateLocalization(languageCode, actionUuid, localizationData) {
|
|
653
|
+
// Use the store method to properly update localization with immer
|
|
654
|
+
zustand
|
|
655
|
+
.getState()
|
|
656
|
+
.updateLocalization(languageCode, actionUuid, localizationData);
|
|
657
|
+
}
|
|
484
658
|
processFormDataForSave() {
|
|
485
659
|
const processed = { ...this.formData };
|
|
486
660
|
// Convert key-value arrays to Records
|
|
@@ -532,8 +706,9 @@ export class NodeEditor extends RapidElement {
|
|
|
532
706
|
'There was an error creating' + ' "' + selected.name + '"';
|
|
533
707
|
}
|
|
534
708
|
}
|
|
535
|
-
// Check required fields
|
|
536
|
-
if (
|
|
709
|
+
// Check required fields (skip in localization mode since all fields are optional)
|
|
710
|
+
if (!this.isTranslating &&
|
|
711
|
+
fieldConfig.required &&
|
|
537
712
|
(!value || (Array.isArray(value) && value.length === 0))) {
|
|
538
713
|
errors[fieldName] = `${fieldConfig.label || fieldName} is required.`;
|
|
539
714
|
}
|
|
@@ -642,8 +817,14 @@ export class NodeEditor extends RapidElement {
|
|
|
642
817
|
if (!this.node)
|
|
643
818
|
throw new Error('No node to update');
|
|
644
819
|
let updatedNode = { ...this.node };
|
|
820
|
+
// Check if node config has fromFormData - if so, it handles the entire transformation
|
|
821
|
+
const nodeConfig = this.getNodeConfig();
|
|
822
|
+
const nodeHasFromFormData = (nodeConfig === null || nodeConfig === void 0 ? void 0 : nodeConfig.fromFormData) !== undefined;
|
|
645
823
|
// Handle actions using action config transformations if available
|
|
646
|
-
if
|
|
824
|
+
// Skip this if the node has its own fromFormData (which handles actions itself)
|
|
825
|
+
if (!nodeHasFromFormData &&
|
|
826
|
+
this.node.actions &&
|
|
827
|
+
this.node.actions.length > 0) {
|
|
647
828
|
updatedNode.actions = this.node.actions.map((action) => {
|
|
648
829
|
// If we're editing a specific action, only transform that one
|
|
649
830
|
if (this.action && action.uuid === this.action.uuid) {
|
|
@@ -664,53 +845,83 @@ export class NodeEditor extends RapidElement {
|
|
|
664
845
|
});
|
|
665
846
|
}
|
|
666
847
|
// Handle router configuration using node config
|
|
667
|
-
if (
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
848
|
+
if (nodeHasFromFormData) {
|
|
849
|
+
// Use node-specific form data transformation
|
|
850
|
+
// When a node has fromFormData, it's responsible for creating the entire
|
|
851
|
+
// node structure including actions and router (regardless of whether router exists yet)
|
|
852
|
+
updatedNode = nodeConfig.fromFormData(formData, updatedNode);
|
|
853
|
+
}
|
|
854
|
+
else if (this.node.router) {
|
|
855
|
+
// Default router handling when no nodeConfig.fromFormData
|
|
856
|
+
updatedNode.router = { ...this.node.router };
|
|
857
|
+
// Apply form data to router fields if they exist
|
|
858
|
+
if (formData.result_name !== undefined) {
|
|
859
|
+
updatedNode.router.result_name = formData.result_name;
|
|
672
860
|
}
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
//
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
861
|
+
// Handle preconfigured rules from node config
|
|
862
|
+
if ((_a = nodeConfig === null || nodeConfig === void 0 ? void 0 : nodeConfig.router) === null || _a === void 0 ? void 0 : _a.rules) {
|
|
863
|
+
// Build a complete new set of categories and exits based on node config
|
|
864
|
+
const existingCategories = updatedNode.router.categories || [];
|
|
865
|
+
const existingExits = updatedNode.exits || [];
|
|
866
|
+
const newCategories = [];
|
|
867
|
+
const newExits = [];
|
|
868
|
+
// Group rules by category name to handle multiple rules pointing to the same category
|
|
869
|
+
const categoryNameToRules = new Map();
|
|
870
|
+
nodeConfig.router.rules.forEach((rule) => {
|
|
871
|
+
if (!categoryNameToRules.has(rule.categoryName)) {
|
|
872
|
+
categoryNameToRules.set(rule.categoryName, []);
|
|
873
|
+
}
|
|
874
|
+
categoryNameToRules.get(rule.categoryName).push(rule);
|
|
875
|
+
});
|
|
876
|
+
// Create categories for all unique category names
|
|
877
|
+
categoryNameToRules.forEach((rules, categoryName) => {
|
|
878
|
+
// Check if category already exists to preserve its UUID and exit_uuid
|
|
879
|
+
const existingCategory = existingCategories.find((cat) => cat.name === categoryName);
|
|
880
|
+
if (existingCategory) {
|
|
881
|
+
// Preserve existing category and its associated exit
|
|
882
|
+
newCategories.push(existingCategory);
|
|
883
|
+
const associatedExit = existingExits.find((exit) => exit.uuid === existingCategory.exit_uuid);
|
|
884
|
+
if (associatedExit) {
|
|
885
|
+
newExits.push(associatedExit);
|
|
692
886
|
}
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
887
|
+
}
|
|
888
|
+
else {
|
|
889
|
+
// Create new category and exit
|
|
890
|
+
const categoryUuid = generateUUID();
|
|
891
|
+
const exitUuid = generateUUID();
|
|
892
|
+
newCategories.push({
|
|
893
|
+
uuid: categoryUuid,
|
|
894
|
+
name: categoryName,
|
|
895
|
+
exit_uuid: exitUuid
|
|
896
|
+
});
|
|
897
|
+
newExits.push({
|
|
898
|
+
uuid: exitUuid,
|
|
899
|
+
destination_uuid: null
|
|
900
|
+
});
|
|
901
|
+
}
|
|
902
|
+
});
|
|
903
|
+
// Add default category if specified
|
|
904
|
+
if (nodeConfig.router.defaultCategory) {
|
|
905
|
+
// Check if default category already exists in our new list
|
|
906
|
+
const existingDefault = newCategories.find((cat) => cat.name === nodeConfig.router.defaultCategory);
|
|
907
|
+
if (!existingDefault) {
|
|
908
|
+
// Check if it exists in the original categories
|
|
909
|
+
const originalDefault = existingCategories.find((cat) => cat.name === nodeConfig.router.defaultCategory);
|
|
910
|
+
if (originalDefault) {
|
|
911
|
+
// Preserve existing default category and its exit
|
|
912
|
+
newCategories.push(originalDefault);
|
|
913
|
+
const associatedExit = existingExits.find((exit) => exit.uuid === originalDefault.exit_uuid);
|
|
703
914
|
if (associatedExit) {
|
|
704
915
|
newExits.push(associatedExit);
|
|
705
916
|
}
|
|
706
917
|
}
|
|
707
918
|
else {
|
|
708
|
-
// Create new category and exit
|
|
919
|
+
// Create new default category and exit
|
|
709
920
|
const categoryUuid = generateUUID();
|
|
710
921
|
const exitUuid = generateUUID();
|
|
711
922
|
newCategories.push({
|
|
712
923
|
uuid: categoryUuid,
|
|
713
|
-
name:
|
|
924
|
+
name: nodeConfig.router.defaultCategory,
|
|
714
925
|
exit_uuid: exitUuid
|
|
715
926
|
});
|
|
716
927
|
newExits.push({
|
|
@@ -718,42 +929,11 @@ export class NodeEditor extends RapidElement {
|
|
|
718
929
|
destination_uuid: null
|
|
719
930
|
});
|
|
720
931
|
}
|
|
721
|
-
});
|
|
722
|
-
// Add default category if specified
|
|
723
|
-
if (nodeConfig.router.defaultCategory) {
|
|
724
|
-
// Check if default category already exists in our new list
|
|
725
|
-
const existingDefault = newCategories.find((cat) => cat.name === nodeConfig.router.defaultCategory);
|
|
726
|
-
if (!existingDefault) {
|
|
727
|
-
// Check if it exists in the original categories
|
|
728
|
-
const originalDefault = existingCategories.find((cat) => cat.name === nodeConfig.router.defaultCategory);
|
|
729
|
-
if (originalDefault) {
|
|
730
|
-
// Preserve existing default category and its exit
|
|
731
|
-
newCategories.push(originalDefault);
|
|
732
|
-
const associatedExit = existingExits.find((exit) => exit.uuid === originalDefault.exit_uuid);
|
|
733
|
-
if (associatedExit) {
|
|
734
|
-
newExits.push(associatedExit);
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
else {
|
|
738
|
-
// Create new default category and exit
|
|
739
|
-
const categoryUuid = generateUUID();
|
|
740
|
-
const exitUuid = generateUUID();
|
|
741
|
-
newCategories.push({
|
|
742
|
-
uuid: categoryUuid,
|
|
743
|
-
name: nodeConfig.router.defaultCategory,
|
|
744
|
-
exit_uuid: exitUuid
|
|
745
|
-
});
|
|
746
|
-
newExits.push({
|
|
747
|
-
uuid: exitUuid,
|
|
748
|
-
destination_uuid: null
|
|
749
|
-
});
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
932
|
}
|
|
753
|
-
// Replace the entire categories and exits lists with our complete new sets
|
|
754
|
-
updatedNode.router.categories = newCategories;
|
|
755
|
-
updatedNode.exits = newExits;
|
|
756
933
|
}
|
|
934
|
+
// Replace the entire categories and exits lists with our complete new sets
|
|
935
|
+
updatedNode.router.categories = newCategories;
|
|
936
|
+
updatedNode.exits = newExits;
|
|
757
937
|
}
|
|
758
938
|
}
|
|
759
939
|
else {
|
|
@@ -862,36 +1042,144 @@ export class NodeEditor extends RapidElement {
|
|
|
862
1042
|
}
|
|
863
1043
|
});
|
|
864
1044
|
}
|
|
865
|
-
|
|
1045
|
+
/**
|
|
1046
|
+
* Helper method to check if a field is visible based on its conditions
|
|
1047
|
+
*/
|
|
1048
|
+
isFieldVisible(fieldName, config) {
|
|
866
1049
|
var _a;
|
|
867
|
-
// Check visibility condition
|
|
868
1050
|
if ((_a = config.conditions) === null || _a === void 0 ? void 0 : _a.visible) {
|
|
869
1051
|
try {
|
|
870
|
-
|
|
871
|
-
if (!isVisible) {
|
|
872
|
-
return html ``;
|
|
873
|
-
}
|
|
1052
|
+
return config.conditions.visible(this.formData);
|
|
874
1053
|
}
|
|
875
1054
|
catch (error) {
|
|
876
1055
|
console.error(`Error checking visibility for ${fieldName}:`, error);
|
|
877
1056
|
// If there's an error, show the field by default
|
|
1057
|
+
return true;
|
|
878
1058
|
}
|
|
879
1059
|
}
|
|
1060
|
+
return true;
|
|
1061
|
+
}
|
|
1062
|
+
renderNewField(fieldName, config, value) {
|
|
1063
|
+
// Check visibility condition
|
|
1064
|
+
if (!this.isFieldVisible(fieldName, config)) {
|
|
1065
|
+
return html ``;
|
|
1066
|
+
}
|
|
880
1067
|
const errors = this.errors[fieldName] ? [this.errors[fieldName]] : [];
|
|
881
1068
|
// Build container style with maxWidth if specified
|
|
882
1069
|
const containerStyle = config.maxWidth
|
|
883
1070
|
? `max-width: ${config.maxWidth};`
|
|
884
1071
|
: '';
|
|
1072
|
+
// Render original value if in localization mode and action has the field
|
|
1073
|
+
const originalValueDisplay = this.isTranslating && this.action && fieldName in this.action
|
|
1074
|
+
? this.renderOriginalValue(fieldName, this.action[fieldName])
|
|
1075
|
+
: html ``;
|
|
885
1076
|
const fieldContent = this.renderFieldContent(fieldName, config, value, errors);
|
|
1077
|
+
const content = html ` ${originalValueDisplay} ${fieldContent} `;
|
|
886
1078
|
// Wrap in container with style if maxWidth is specified
|
|
887
1079
|
if (containerStyle) {
|
|
888
|
-
return html `<div style="${containerStyle}">${
|
|
1080
|
+
return html `<div style="${containerStyle}">${content}</div>`;
|
|
1081
|
+
}
|
|
1082
|
+
return content;
|
|
1083
|
+
}
|
|
1084
|
+
renderOptionalField(fieldName, config, value) {
|
|
1085
|
+
// If the field has a value or has been revealed, show it
|
|
1086
|
+
const hasValue = value && value.toString().trim() !== '';
|
|
1087
|
+
const isRevealed = this.revealedOptionalFields.has(fieldName);
|
|
1088
|
+
if (hasValue || isRevealed) {
|
|
1089
|
+
// Render the field normally
|
|
1090
|
+
return this.renderNewField(fieldName, config, value);
|
|
1091
|
+
}
|
|
1092
|
+
// Show the "Save as..." link
|
|
1093
|
+
return html `
|
|
1094
|
+
<div class="optional-field-link">
|
|
1095
|
+
<a
|
|
1096
|
+
href="#"
|
|
1097
|
+
@click="${(e) => {
|
|
1098
|
+
e.preventDefault();
|
|
1099
|
+
this.revealOptionalField(fieldName);
|
|
1100
|
+
}}"
|
|
1101
|
+
>
|
|
1102
|
+
${config.optionalLink}
|
|
1103
|
+
</a>
|
|
1104
|
+
</div>
|
|
1105
|
+
`;
|
|
1106
|
+
}
|
|
1107
|
+
revealOptionalField(fieldName) {
|
|
1108
|
+
this.revealedOptionalFields = new Set([
|
|
1109
|
+
...this.revealedOptionalFields,
|
|
1110
|
+
fieldName
|
|
1111
|
+
]);
|
|
1112
|
+
}
|
|
1113
|
+
renderCategoryLocalizationTable() {
|
|
1114
|
+
const categories = this.formData.categories || {};
|
|
1115
|
+
const categoryEntries = Object.entries(categories);
|
|
1116
|
+
if (categoryEntries.length === 0) {
|
|
1117
|
+
return html `<div>No categories to localize</div>`;
|
|
1118
|
+
}
|
|
1119
|
+
const languageName = getStore().getLanguageName(this.languageCode);
|
|
1120
|
+
return html `
|
|
1121
|
+
<div class="category-localization-table">
|
|
1122
|
+
${categoryEntries.map(([categoryUuid, categoryData]) => html `
|
|
1123
|
+
<div class="category-localization-row">
|
|
1124
|
+
<div class="original-name">${categoryData.originalName}</div>
|
|
1125
|
+
<div class="localized-name">
|
|
1126
|
+
<temba-textinput
|
|
1127
|
+
name="${categoryUuid}"
|
|
1128
|
+
placeholder="${languageName} Translation"
|
|
1129
|
+
value="${categoryData.localizedName || ''}"
|
|
1130
|
+
@change=${(e) => this.handleCategoryLocalizationChange(categoryUuid, e.target.value)}
|
|
1131
|
+
></temba-textinput>
|
|
1132
|
+
</div>
|
|
1133
|
+
</div>
|
|
1134
|
+
`)}
|
|
1135
|
+
</div>
|
|
1136
|
+
`;
|
|
1137
|
+
}
|
|
1138
|
+
handleCategoryLocalizationChange(categoryUuid, value) {
|
|
1139
|
+
// Update formData with new localized value
|
|
1140
|
+
if (!this.formData.categories) {
|
|
1141
|
+
this.formData.categories = {};
|
|
889
1142
|
}
|
|
890
|
-
|
|
1143
|
+
if (!this.formData.categories[categoryUuid]) {
|
|
1144
|
+
this.formData.categories[categoryUuid] = {};
|
|
1145
|
+
}
|
|
1146
|
+
this.formData.categories[categoryUuid].localizedName = value;
|
|
1147
|
+
// Trigger a re-render
|
|
1148
|
+
this.requestUpdate();
|
|
1149
|
+
}
|
|
1150
|
+
renderOriginalValue(fieldName, originalValue) {
|
|
1151
|
+
// Format the original value for display
|
|
1152
|
+
let displayValue = '';
|
|
1153
|
+
if (Array.isArray(originalValue)) {
|
|
1154
|
+
if (originalValue.length === 0) {
|
|
1155
|
+
return html ``; // Don't show anything for empty arrays
|
|
1156
|
+
}
|
|
1157
|
+
// For arrays, join with commas
|
|
1158
|
+
displayValue = originalValue.join(', ');
|
|
1159
|
+
}
|
|
1160
|
+
else if (typeof originalValue === 'string') {
|
|
1161
|
+
displayValue = originalValue;
|
|
1162
|
+
}
|
|
1163
|
+
else if (originalValue) {
|
|
1164
|
+
displayValue = String(originalValue);
|
|
1165
|
+
}
|
|
1166
|
+
// Don't show if empty
|
|
1167
|
+
if (!displayValue || displayValue.trim() === '') {
|
|
1168
|
+
return html ``;
|
|
1169
|
+
}
|
|
1170
|
+
return html `
|
|
1171
|
+
<div class="original-value">
|
|
1172
|
+
<div class="original-value-content">${displayValue}</div>
|
|
1173
|
+
</div>
|
|
1174
|
+
`;
|
|
891
1175
|
}
|
|
892
1176
|
renderFieldContent(fieldName, config, value, errors) {
|
|
1177
|
+
// In localization mode, make all fields optional (not required)
|
|
1178
|
+
const fieldConfig = this.isTranslating
|
|
1179
|
+
? { ...config, required: false }
|
|
1180
|
+
: config;
|
|
893
1181
|
// Use FieldRenderer for consistent field rendering
|
|
894
|
-
return FieldRenderer.renderField(fieldName,
|
|
1182
|
+
return FieldRenderer.renderField(fieldName, fieldConfig, value, {
|
|
895
1183
|
errors,
|
|
896
1184
|
onChange: (e) => {
|
|
897
1185
|
// Handle different change event types
|
|
@@ -977,7 +1265,12 @@ export class NodeEditor extends RapidElement {
|
|
|
977
1265
|
case 'field':
|
|
978
1266
|
if (config.form[item.field] && !renderedFields.has(item.field)) {
|
|
979
1267
|
renderedFields.add(item.field);
|
|
980
|
-
|
|
1268
|
+
const fieldConfig = config.form[item.field];
|
|
1269
|
+
// Handle optional link fields
|
|
1270
|
+
if (fieldConfig.optionalLink) {
|
|
1271
|
+
return this.renderOptionalField(item.field, fieldConfig, this.formData[item.field]);
|
|
1272
|
+
}
|
|
1273
|
+
return this.renderNewField(item.field, fieldConfig, this.formData[item.field]);
|
|
981
1274
|
}
|
|
982
1275
|
return html ``;
|
|
983
1276
|
case 'row':
|
|
@@ -989,24 +1282,68 @@ export class NodeEditor extends RapidElement {
|
|
|
989
1282
|
}
|
|
990
1283
|
}
|
|
991
1284
|
renderRow(rowConfig, config, renderedFields) {
|
|
992
|
-
const { items, gap = '1rem' } = rowConfig;
|
|
1285
|
+
const { items, gap = '1rem', label, helpText } = rowConfig;
|
|
993
1286
|
// Collect all fields from this row for width calculations
|
|
994
1287
|
const fieldsInRow = this.collectFieldsFromItems(items);
|
|
995
1288
|
const validFields = fieldsInRow.filter((fieldName) => { var _a; return (_a = config.form) === null || _a === void 0 ? void 0 : _a[fieldName]; });
|
|
996
|
-
|
|
1289
|
+
// Filter for visible fields only to handle conditional visibility
|
|
1290
|
+
const visibleFields = validFields.filter((fieldName) => {
|
|
1291
|
+
const fieldConfig = config.form[fieldName];
|
|
1292
|
+
return this.isFieldVisible(fieldName, fieldConfig);
|
|
1293
|
+
});
|
|
1294
|
+
if (visibleFields.length === 0) {
|
|
997
1295
|
return html ``;
|
|
998
1296
|
}
|
|
999
|
-
//
|
|
1000
|
-
|
|
1297
|
+
// Build a map of field flex styles
|
|
1298
|
+
// Fields with maxWidth get flex: 0 0 {maxWidth} (fixed)
|
|
1299
|
+
// Fields without maxWidth get flex: 1 1 0 (grow to fill space)
|
|
1300
|
+
const fieldFlexStyles = new Map();
|
|
1301
|
+
visibleFields.forEach((fieldName) => {
|
|
1001
1302
|
const fieldConfig = config.form[fieldName];
|
|
1002
|
-
|
|
1303
|
+
if (fieldConfig.maxWidth) {
|
|
1304
|
+
// Fixed width field: no grow, no shrink, basis = maxWidth
|
|
1305
|
+
fieldFlexStyles.set(fieldName, `flex: 0 0 ${fieldConfig.maxWidth};`);
|
|
1306
|
+
}
|
|
1307
|
+
else {
|
|
1308
|
+
// Flexible field: grow to fill remaining space
|
|
1309
|
+
fieldFlexStyles.set(fieldName, `flex: 1 1 0;`);
|
|
1310
|
+
}
|
|
1003
1311
|
});
|
|
1312
|
+
const rowContent = html `
|
|
1313
|
+
<div class="form-row" style="display: flex; gap: ${gap};">
|
|
1314
|
+
${items.map((item) => {
|
|
1315
|
+
// Get the field name from the item
|
|
1316
|
+
const fieldName = typeof item === 'string'
|
|
1317
|
+
? item
|
|
1318
|
+
: item.type === 'field'
|
|
1319
|
+
? item.field
|
|
1320
|
+
: null;
|
|
1321
|
+
// Get flex style for this field if it's a visible field
|
|
1322
|
+
const flexStyle = fieldName && fieldFlexStyles.has(fieldName)
|
|
1323
|
+
? fieldFlexStyles.get(fieldName)
|
|
1324
|
+
: '';
|
|
1325
|
+
const itemContent = this.renderLayoutItem(item, config, renderedFields);
|
|
1326
|
+
// Wrap in a div with flex style if we have a flex style
|
|
1327
|
+
return flexStyle
|
|
1328
|
+
? html `<div style="${flexStyle}">${itemContent}</div>`
|
|
1329
|
+
: itemContent;
|
|
1330
|
+
})}
|
|
1331
|
+
</div>
|
|
1332
|
+
`;
|
|
1333
|
+
// If no label or helpText, return just the row content
|
|
1334
|
+
if (!label && !helpText) {
|
|
1335
|
+
return rowContent;
|
|
1336
|
+
}
|
|
1337
|
+
// Otherwise, wrap with label on top, content, then helpText below (matching field pattern)
|
|
1004
1338
|
return html `
|
|
1005
|
-
<div
|
|
1006
|
-
class="form-row"
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1339
|
+
<div class="form-row-wrapper">
|
|
1340
|
+
${label ? html `<label class="form-row-label">${label}</label>` : ''}
|
|
1341
|
+
${rowContent}
|
|
1342
|
+
${helpText
|
|
1343
|
+
? html `<div class="form-row-help">
|
|
1344
|
+
${renderMarkdownInline(helpText)}
|
|
1345
|
+
</div>`
|
|
1346
|
+
: ''}
|
|
1010
1347
|
</div>
|
|
1011
1348
|
`;
|
|
1012
1349
|
}
|
|
@@ -1186,6 +1523,12 @@ export class NodeEditor extends RapidElement {
|
|
|
1186
1523
|
if (!config) {
|
|
1187
1524
|
return html ` <div>No configuration available</div> `;
|
|
1188
1525
|
}
|
|
1526
|
+
// Special rendering for category localization
|
|
1527
|
+
if (this.isTranslating &&
|
|
1528
|
+
config.localizable === 'categories' &&
|
|
1529
|
+
this.formData.categories) {
|
|
1530
|
+
return this.renderCategoryLocalizationTable();
|
|
1531
|
+
}
|
|
1189
1532
|
// Use the new fields configuration system
|
|
1190
1533
|
if (config.form) {
|
|
1191
1534
|
// If layout is specified, use it
|
|
@@ -1230,6 +1573,10 @@ export class NodeEditor extends RapidElement {
|
|
|
1230
1573
|
if (!(config === null || config === void 0 ? void 0 : config.gutter) || config.gutter.length === 0) {
|
|
1231
1574
|
return html ``;
|
|
1232
1575
|
}
|
|
1576
|
+
// Don't show gutter when localizing categories
|
|
1577
|
+
if (this.isTranslating && config.localizable === 'categories') {
|
|
1578
|
+
return html ``;
|
|
1579
|
+
}
|
|
1233
1580
|
// Use the same layout rendering system for gutter fields
|
|
1234
1581
|
const renderedFields = new Set();
|
|
1235
1582
|
return html `
|
|
@@ -1299,17 +1646,25 @@ export class NodeEditor extends RapidElement {
|
|
|
1299
1646
|
if (!this.isOpen) {
|
|
1300
1647
|
return html ``;
|
|
1301
1648
|
}
|
|
1302
|
-
const headerColor = this.getHeaderColor();
|
|
1649
|
+
const headerColor = this.isTranslating ? '#505050' : this.getHeaderColor();
|
|
1650
|
+
const headerTextColor = this.isTranslating ? '#fff' : '#fff';
|
|
1303
1651
|
const config = this.getConfig();
|
|
1304
1652
|
const dialogSize = (config === null || config === void 0 ? void 0 : config.dialogSize) || 'medium'; // Default to 'large' if not specified
|
|
1653
|
+
const languageName = this.isTranslating
|
|
1654
|
+
? getStore().getLanguageName(this.languageCode)
|
|
1655
|
+
: '';
|
|
1656
|
+
let header = (config === null || config === void 0 ? void 0 : config.name) || 'Edit';
|
|
1657
|
+
if (this.isTranslating) {
|
|
1658
|
+
header = languageName ? `${languageName} - ${header}` : header;
|
|
1659
|
+
}
|
|
1305
1660
|
return html `
|
|
1306
1661
|
<temba-dialog
|
|
1307
|
-
header="${
|
|
1662
|
+
header="${header}"
|
|
1308
1663
|
.open="${this.isOpen}"
|
|
1309
1664
|
@temba-button-clicked=${this.handleDialogButtonClick}
|
|
1310
1665
|
primaryButtonName="Save"
|
|
1311
1666
|
cancelButtonName="Cancel"
|
|
1312
|
-
style="--header-bg: ${headerColor}"
|
|
1667
|
+
style="--header-bg: ${headerColor}; --header-text: ${headerTextColor};"
|
|
1313
1668
|
size="${dialogSize}"
|
|
1314
1669
|
>
|
|
1315
1670
|
<div class="node-editor-form">
|
|
@@ -1351,4 +1706,16 @@ __decorate([
|
|
|
1351
1706
|
__decorate([
|
|
1352
1707
|
state()
|
|
1353
1708
|
], NodeEditor.prototype, "groupHoverState", void 0);
|
|
1709
|
+
__decorate([
|
|
1710
|
+
state()
|
|
1711
|
+
], NodeEditor.prototype, "revealedOptionalFields", void 0);
|
|
1712
|
+
__decorate([
|
|
1713
|
+
fromStore(zustand, (state) => state.languageCode)
|
|
1714
|
+
], NodeEditor.prototype, "languageCode", void 0);
|
|
1715
|
+
__decorate([
|
|
1716
|
+
fromStore(zustand, (state) => state.isTranslating)
|
|
1717
|
+
], NodeEditor.prototype, "isTranslating", void 0);
|
|
1718
|
+
__decorate([
|
|
1719
|
+
fromStore(zustand, (state) => state.flowDefinition)
|
|
1720
|
+
], NodeEditor.prototype, "flowDefinition", void 0);
|
|
1354
1721
|
//# sourceMappingURL=NodeEditor.js.map
|