@nyaruka/temba-components 0.130.1 → 0.130.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/CHANGELOG.md +34 -4
- package/DEV_DATA.md +89 -0
- package/demo/data/flows/food-order.json +4 -4
- package/demo/data/flows/sample-flow.json +132 -147
- package/dist/temba-components.js +787 -659
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/display/Chat.js +5 -3
- package/out-tsc/src/display/Chat.js.map +1 -1
- package/out-tsc/src/events.js.map +1 -1
- package/out-tsc/src/flow/CanvasNode.js +83 -78
- package/out-tsc/src/flow/CanvasNode.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +1 -0
- package/out-tsc/src/flow/Editor.js.map +1 -1
- package/out-tsc/src/flow/NodeEditor.js +47 -3
- package/out-tsc/src/flow/NodeEditor.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/set_contact_channel.js +1 -1
- package/out-tsc/src/flow/actions/set_contact_channel.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_field.js +2 -1
- package/out-tsc/src/flow/actions/set_contact_field.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_language.js +3 -1
- package/out-tsc/src/flow/actions/set_contact_language.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_name.js +1 -1
- package/out-tsc/src/flow/actions/set_contact_name.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_status.js +17 -14
- package/out-tsc/src/flow/actions/set_contact_status.js.map +1 -1
- package/out-tsc/src/flow/actions/set_run_result.js +1 -1
- package/out-tsc/src/flow/actions/set_run_result.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_llm.js +12 -12
- package/out-tsc/src/flow/nodes/split_by_llm.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_response.js +609 -6
- package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -1
- package/out-tsc/src/flow/operators.js +194 -0
- package/out-tsc/src/flow/operators.js.map +1 -0
- package/out-tsc/src/flow/types.js.map +1 -1
- package/out-tsc/src/form/ArrayEditor.js +84 -19
- package/out-tsc/src/form/ArrayEditor.js.map +1 -1
- package/out-tsc/src/form/Checkbox.js +12 -0
- package/out-tsc/src/form/Checkbox.js.map +1 -1
- package/out-tsc/src/form/FieldRenderer.js +13 -3
- package/out-tsc/src/form/FieldRenderer.js.map +1 -1
- package/out-tsc/src/form/TextInput.js +20 -1
- package/out-tsc/src/form/TextInput.js.map +1 -1
- package/out-tsc/src/form/select/Select.js +7 -0
- package/out-tsc/src/form/select/Select.js.map +1 -1
- package/out-tsc/src/interfaces.js.map +1 -1
- package/out-tsc/src/layout/Dialog.js +3 -4
- package/out-tsc/src/layout/Dialog.js.map +1 -1
- package/out-tsc/src/list/RunList.js +2 -2
- package/out-tsc/src/list/RunList.js.map +1 -1
- package/out-tsc/src/live/ContactChat.js +101 -44
- package/out-tsc/src/live/ContactChat.js.map +1 -1
- package/out-tsc/src/live/ContactDetails.js +7 -0
- package/out-tsc/src/live/ContactDetails.js.map +1 -1
- package/out-tsc/src/live/ContactNameFetch.js +1 -1
- package/out-tsc/src/live/ContactNameFetch.js.map +1 -1
- package/out-tsc/src/webchat/index.js +0 -11
- package/out-tsc/src/webchat/index.js.map +1 -1
- package/out-tsc/test/NodeHelper.js +25 -27
- package/out-tsc/test/NodeHelper.js.map +1 -1
- package/out-tsc/test/nodes/split_by_llm.test.js +12 -4
- package/out-tsc/test/nodes/split_by_llm.test.js.map +1 -1
- package/out-tsc/test/nodes/split_by_llm_categorize.test.js +101 -91
- package/out-tsc/test/nodes/split_by_llm_categorize.test.js.map +1 -1
- package/out-tsc/test/nodes/split_by_random.test.js +120 -112
- package/out-tsc/test/nodes/split_by_random.test.js.map +1 -1
- package/out-tsc/test/nodes/wait_for_digits.test.js +131 -111
- package/out-tsc/test/nodes/wait_for_digits.test.js.map +1 -1
- package/out-tsc/test/nodes/wait_for_response.test.js +549 -85
- package/out-tsc/test/nodes/wait_for_response.test.js.map +1 -1
- package/out-tsc/test/temba-checkbox.test.js +32 -32
- package/out-tsc/test/temba-checkbox.test.js.map +1 -1
- package/out-tsc/test/temba-contact-chat.test.js +2 -1
- package/out-tsc/test/temba-contact-chat.test.js.map +1 -1
- package/out-tsc/test/temba-dropdown.test.js +0 -4
- package/out-tsc/test/temba-dropdown.test.js.map +1 -1
- package/out-tsc/test/temba-flow-editor-node.test.js +9 -4
- package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
- package/out-tsc/test/temba-integration-markdown.test.js +13 -15
- package/out-tsc/test/temba-integration-markdown.test.js.map +1 -1
- package/out-tsc/test/temba-node-editor.test.js +5 -38
- package/out-tsc/test/temba-node-editor.test.js.map +1 -1
- package/out-tsc/test/temba-run-list.test.js +2 -2
- package/out-tsc/test/temba-run-list.test.js.map +1 -1
- package/out-tsc/test/utils.test.js +2 -1
- package/out-tsc/test/utils.test.js.map +1 -1
- package/package.json +6 -2
- 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/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_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/checkbox/checkbox-label-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/editor/wait.png +0 -0
- package/screenshots/truth/integration/textinput-markdown-errors.png +0 -0
- package/screenshots/truth/lightbox/img-zoomed.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/screenshots/truth/run-list/basic.png +0 -0
- package/screenshots/truth/templates/default.png +0 -0
- package/screenshots/truth/wait-for-response/rules-editor.png +0 -0
- package/screenshots/truth/wait-for-response/timeout-editor-unchecked.png +0 -0
- package/screenshots/truth/wait-for-response/timeout-editor.png +0 -0
- package/scripts/dev-data-sync.mjs +182 -0
- package/src/display/Chat.ts +6 -4
- package/src/events.ts +6 -6
- package/src/flow/CanvasNode.ts +89 -79
- package/src/flow/Editor.ts +1 -0
- package/src/flow/NodeEditor.ts +55 -3
- package/src/flow/actions/add_contact_urn.ts +1 -1
- package/src/flow/actions/set_contact_channel.ts +1 -1
- package/src/flow/actions/set_contact_field.ts +2 -1
- package/src/flow/actions/set_contact_language.ts +3 -1
- package/src/flow/actions/set_contact_name.ts +1 -1
- package/src/flow/actions/set_contact_status.ts +18 -18
- package/src/flow/actions/set_run_result.ts +1 -1
- package/src/flow/nodes/split_by_llm.ts +14 -13
- package/src/flow/nodes/wait_for_response.ts +717 -5
- package/src/flow/operators.ts +215 -0
- package/src/flow/types.ts +10 -2
- package/src/form/ArrayEditor.ts +117 -37
- package/src/form/Checkbox.ts +12 -0
- package/src/form/FieldRenderer.ts +24 -3
- package/src/form/TextInput.ts +19 -1
- package/src/form/select/Select.ts +7 -0
- package/src/interfaces.ts +1 -1
- package/src/layout/Dialog.ts +4 -4
- package/src/list/RunList.ts +2 -2
- package/src/live/ContactChat.ts +128 -67
- package/src/live/ContactDetails.ts +7 -0
- package/src/live/ContactNameFetch.ts +1 -1
- package/src/webchat/index.ts +0 -16
- package/static/api/labels.json +6 -1
- package/test/NodeHelper.ts +38 -40
- package/test/nodes/split_by_llm.test.ts +43 -32
- package/test/nodes/split_by_llm_categorize.test.ts +130 -120
- package/test/nodes/split_by_random.test.ts +136 -128
- package/test/nodes/wait_for_digits.test.ts +147 -127
- package/test/nodes/wait_for_response.test.ts +657 -104
- package/test/temba-checkbox.test.ts +36 -32
- package/test/temba-contact-chat.test.ts +2 -1
- package/test/temba-dropdown.test.ts +0 -12
- package/test/temba-flow-editor-node.test.ts +11 -4
- package/test/temba-integration-markdown.test.ts +16 -17
- package/test/temba-node-editor.test.ts +5 -43
- package/test/temba-run-list.test.ts +2 -2
- package/test/utils.test.ts +2 -1
- package/test-assets/contacts/history.json +4 -7
- package/test-assets/list/runs.json +8 -8
- package/web-dev-mock.mjs +86 -30
- package/web-dev-server.config.mjs +272 -31
- package/screenshots/truth/dropdown/bottom-edge-collision.png +0 -0
- package/screenshots/truth/dropdown/right-edge-collision.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/integration/checkbox-markdown-errors.png +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wait_for_response.js","sourceRoot":"","sources":["../../../../src/flow/nodes/wait_for_response.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAc,MAAM,UAAU,CAAC;AAG9C,MAAM,CAAC,MAAM,iBAAiB,GAAe;IAC3C,IAAI,EAAE,mBAAmB;IACzB,IAAI,EAAE,mBAAmB;IACzB,KAAK,EAAE,MAAM,CAAC,IAAI;IAClB,IAAI,EAAE;QACJ,WAAW,EAAE;YACX,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,aAAa;YACpB,QAAQ,EAAE,kCAAkC;YAC5C,WAAW,EAAE,UAAU;SACxB;KACF;IACD,MAAM,EAAE,CAAC,SAAS,EAAE,aAAa,CAAC;IAClC,UAAU,EAAE,CAAC,IAAU,EAAE,EAAE;;QACzB,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,WAAW,EAAE,CAAA,MAAA,IAAI,CAAC,MAAM,0CAAE,WAAW,KAAI,UAAU;SACpD,CAAC;IACJ,CAAC;IACD,YAAY,EAAE,CAAC,QAAa,EAAE,YAAkB,EAAQ,EAAE;QACxD,MAAM,MAAM,GAAQ;YAClB,GAAG,YAAY,CAAC,MAAM;YACtB,WAAW,EAAE,QAAQ,CAAC,WAAW,IAAI,UAAU;SAChD,CAAC;QAEF,OAAO;YACL,GAAG,YAAY;YACf,MAAM;SACP,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import { COLORS, NodeConfig } from '../types';\nimport { Node } from '../../store/flow-definition';\n\nexport const wait_for_response: NodeConfig = {\n type: 'wait_for_response',\n name: 'Wait for Response',\n color: COLORS.wait,\n form: {\n result_name: {\n type: 'text',\n label: 'Result Name',\n helpText: 'The name to save the response as',\n placeholder: 'response'\n }\n },\n layout: ['timeout', 'result_name'],\n toFormData: (node: Node) => {\n return {\n uuid: node.uuid,\n result_name: node.router?.result_name || 'response'\n };\n },\n fromFormData: (formData: any, originalNode: Node): Node => {\n const router: any = {\n ...originalNode.router,\n result_name: formData.result_name || 'response'\n };\n\n return {\n ...originalNode,\n router\n };\n }\n};\n"]}
|
|
1
|
+
{"version":3,"file":"wait_for_response.js","sourceRoot":"","sources":["../../../../src/flow/nodes/wait_for_response.ts"],"names":[],"mappings":"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","sourcesContent":["import { COLORS, NodeConfig } from '../types';\nimport { Node, Category, Exit, Case } from '../../store/flow-definition';\nimport { generateUUID } from '../../utils';\nimport {\n getWaitForResponseOperators,\n operatorsToSelectOptions,\n getOperatorConfig\n} from '../operators';\n\nconst TIMEOUT_OPTIONS = [\n { value: '60', name: '1 minute' },\n { value: '120', name: '2 minutes' },\n { value: '180', name: '3 minutes' },\n { value: '240', name: '4 minutes' },\n { value: '300', name: '5 minutes' },\n { value: '600', name: '10 minutes' },\n { value: '900', name: '15 minutes' },\n { value: '1800', name: '30 minutes' },\n { value: '3600', name: '1 hour' },\n { value: '7200', name: '2 hours' },\n { value: '10800', name: '3 hours' },\n { value: '21600', name: '6 hours' },\n { value: '43200', name: '12 hours' },\n { value: '64800', name: '18 hours' },\n { value: '86400', name: '1 day' },\n { value: '172800', name: '2 days' },\n { value: '259200', name: '3 days' },\n { value: '604800', name: '1 week' }\n];\n\n// Helper function to create a wait_for_response router with user rules\nconst createWaitForResponseRouter = (\n userRules: any[],\n existingCategories: Category[] = [],\n existingExits: Exit[] = [],\n existingCases: Case[] = []\n) => {\n const categories: Category[] = [];\n const exits: Exit[] = [];\n const cases: Case[] = [];\n\n // Filter existing categories to get only user-defined rules (exclude system categories)\n const existingUserCategories = existingCategories.filter(\n (cat) =>\n cat.name !== 'No Response' &&\n cat.name !== 'Other' &&\n cat.name !== 'Timeout'\n );\n\n // Group rules by category name (case-insensitive) to merge them\n const rulesByCategory = new Map<string, any[]>();\n userRules.forEach((rule) => {\n const categoryKey = rule.category.trim().toLowerCase();\n if (!rulesByCategory.has(categoryKey)) {\n rulesByCategory.set(categoryKey, []);\n }\n rulesByCategory.get(categoryKey)!.push(rule);\n });\n\n // Track category creation order to preserve UUID mapping\n const categoryOrder: string[] = [];\n userRules.forEach((rule) => {\n const categoryKey = rule.category.trim().toLowerCase();\n if (!categoryOrder.includes(categoryKey)) {\n categoryOrder.push(categoryKey);\n }\n });\n\n // Create categories, exits, and cases for each unique category\n categoryOrder.forEach((categoryKey, categoryIndex) => {\n const rulesForCategory = rulesByCategory.get(categoryKey)!;\n const categoryName = rulesForCategory[0].category.trim(); // Use the first occurrence's casing\n\n // Try to find existing category by position/index to preserve UUIDs when names change\n const existingCategory = existingUserCategories[categoryIndex];\n const existingExit = existingCategory\n ? existingExits.find((exit) => exit.uuid === existingCategory.exit_uuid)\n : null;\n\n const exitUuid = existingExit?.uuid || generateUUID();\n const categoryUuid = existingCategory?.uuid || generateUUID();\n\n // Create single category for all rules with this category name\n categories.push({\n uuid: categoryUuid,\n name: categoryName,\n exit_uuid: exitUuid\n });\n\n exits.push({\n uuid: exitUuid,\n destination_uuid: existingExit?.destination_uuid || null\n });\n\n // Create a case for each rule in this category\n rulesForCategory.forEach((rule) => {\n // Try to find existing case for this rule by looking at the original rule order\n const originalRuleIndex = userRules.findIndex((r) => r === rule);\n const existingCase = existingCases[originalRuleIndex];\n\n const caseUuid = existingCase?.uuid || generateUUID();\n\n // Parse rule value based on operator configuration\n const operatorConfig = getOperatorConfig(rule.operator);\n let arguments_: string[] = [];\n\n if (operatorConfig) {\n if (operatorConfig.operands === 0) {\n // No operands needed\n arguments_ = [];\n } else if (operatorConfig.operands === 2) {\n // Split value for two operands (e.g., \"1 10\" for between)\n arguments_ = rule.value\n .split(' ')\n .filter((arg: string) => arg.trim());\n } else {\n // Single operand - but split words for operators that expect multiple words\n if (rule.value && rule.value.trim()) {\n // Split on spaces and filter out empty strings\n arguments_ = rule.value\n .trim()\n .split(/\\s+/)\n .filter((arg: string) => arg.length > 0);\n } else {\n arguments_ = [];\n }\n }\n } else {\n // Fallback for unknown operators - split on spaces if value exists\n if (rule.value && rule.value.trim()) {\n arguments_ = rule.value\n .trim()\n .split(/\\s+/)\n .filter((arg: string) => arg.length > 0);\n } else {\n arguments_ = [];\n }\n }\n\n cases.push({\n uuid: caseUuid,\n type: rule.operator,\n arguments: arguments_,\n category_uuid: categoryUuid\n });\n });\n });\n\n // Preserve existing timeout categories like \"No Response\"\n existingCategories.forEach((category) => {\n if (category.name === 'No Response' || category.name === 'Timeout') {\n const existingExit = existingExits.find(\n (exit) => exit.uuid === category.exit_uuid\n );\n\n if (existingExit) {\n categories.push(category);\n exits.push(existingExit);\n }\n }\n });\n\n // Add \"Other\" category (default) only if there are user rules\n if (userRules.length > 0) {\n const existingOtherCategory = existingCategories.find(\n (cat) => cat.name === 'Other'\n );\n const existingOtherExit = existingOtherCategory\n ? existingExits.find(\n (exit) => exit.uuid === existingOtherCategory.exit_uuid\n )\n : null;\n\n const otherExitUuid = existingOtherExit?.uuid || generateUUID();\n const otherCategoryUuid = existingOtherCategory?.uuid || generateUUID();\n\n categories.push({\n uuid: otherCategoryUuid,\n name: 'Other',\n exit_uuid: otherExitUuid\n });\n\n exits.push({\n uuid: otherExitUuid,\n destination_uuid: existingOtherExit?.destination_uuid || null\n });\n }\n\n return {\n router: {\n type: 'switch' as const,\n categories: categories,\n default_category_uuid: categories.find((cat) => cat.name === 'Other')\n ?.uuid,\n operand: '@input.text',\n cases: cases\n },\n exits: exits\n };\n};\n\nexport const wait_for_response: NodeConfig = {\n type: 'wait_for_response',\n name: 'Wait for Response',\n color: COLORS.wait,\n dialogSize: 'large',\n form: {\n rules: {\n type: 'array',\n helpText: 'Define rules to categorize responses',\n itemLabel: 'Rule',\n minItems: 0,\n maxItems: 100,\n maintainEmptyItem: true, // Explicitly enable empty item maintenance\n isEmptyItem: (item: any) => {\n // Helper function to get operator value from various formats\n const getOperatorValue = (operator: any): string => {\n if (typeof operator === 'string') {\n return operator.trim();\n } else if (Array.isArray(operator) && operator.length > 0) {\n // Handle array format: [{value: \"has_any_word\", name: \"...\"}]\n const firstOperator = operator[0];\n if (\n firstOperator &&\n typeof firstOperator === 'object' &&\n firstOperator.value\n ) {\n return firstOperator.value.trim();\n }\n } else if (\n operator &&\n typeof operator === 'object' &&\n operator.value\n ) {\n // Handle object format: {value: \"has_any_word\", name: \"...\"}\n return operator.value.trim();\n }\n return '';\n };\n\n // Check if operator and category are provided\n const operatorValue = getOperatorValue(item.operator);\n if (!operatorValue || !item.category || item.category.trim() === '') {\n return true;\n }\n\n // Check if value is required based on operator configuration\n const operatorConfig = getOperatorConfig(operatorValue);\n if (operatorConfig && operatorConfig.operands === 1) {\n // value1 is required for this operator\n return !item.value1 || item.value1.trim() === '';\n } else if (operatorConfig && operatorConfig.operands === 2) {\n // Both value1 and value2 are required for this operator\n return (\n !item.value1 ||\n item.value1.trim() === '' ||\n !item.value2 ||\n item.value2.trim() === ''\n );\n }\n\n // No value required for this operator\n return false;\n },\n itemConfig: {\n operator: {\n type: 'select',\n required: true,\n multi: false, // Explicitly set as single-select\n options: operatorsToSelectOptions(getWaitForResponseOperators()),\n flavor: 'xsmall',\n width: '200px'\n },\n value1: {\n type: 'text',\n flavor: 'xsmall',\n conditions: {\n visible: (formData: Record<string, any>) => {\n // Helper function to get operator value from various formats\n const getOperatorValue = (operator: any): string => {\n if (typeof operator === 'string') {\n return operator.trim();\n } else if (Array.isArray(operator) && operator.length > 0) {\n const firstOperator = operator[0];\n if (\n firstOperator &&\n typeof firstOperator === 'object' &&\n firstOperator.value\n ) {\n return firstOperator.value.trim();\n }\n } else if (\n operator &&\n typeof operator === 'object' &&\n operator.value\n ) {\n return operator.value.trim();\n }\n return '';\n };\n\n // Show value1 field for operators that require 1 or 2 operands\n const operatorValue = getOperatorValue(formData.operator);\n const operatorConfig = getOperatorConfig(operatorValue);\n return operatorConfig ? operatorConfig.operands >= 1 : true;\n }\n }\n },\n value2: {\n type: 'text',\n flavor: 'xsmall',\n conditions: {\n visible: (formData: Record<string, any>) => {\n // Helper function to get operator value from various formats\n const getOperatorValue = (operator: any): string => {\n if (typeof operator === 'string') {\n return operator.trim();\n } else if (Array.isArray(operator) && operator.length > 0) {\n const firstOperator = operator[0];\n if (\n firstOperator &&\n typeof firstOperator === 'object' &&\n firstOperator.value\n ) {\n return firstOperator.value.trim();\n }\n } else if (\n operator &&\n typeof operator === 'object' &&\n operator.value\n ) {\n return operator.value.trim();\n }\n return '';\n };\n\n // Show value2 field only if operator requires exactly 2 operands\n const operatorValue = getOperatorValue(formData.operator);\n const operatorConfig = getOperatorConfig(operatorValue);\n return operatorConfig ? operatorConfig.operands === 2 : false;\n }\n }\n },\n category: {\n type: 'text',\n placeholder: 'Category',\n required: true,\n maxWidth: '120px',\n flavor: 'xsmall'\n }\n }\n },\n timeout_enabled: {\n type: 'checkbox',\n label: (formData: Record<string, any>) => {\n return formData.timeout_enabled\n ? 'Continue when there is no response for'\n : 'Continue when there is no response..';\n },\n labelPadding: '4px 8px'\n },\n timeout_duration: {\n type: 'select',\n placeholder: '5 minutes',\n multi: false,\n maxWidth: '150px',\n flavor: 'xsmall',\n options: TIMEOUT_OPTIONS,\n conditions: {\n visible: (formData: Record<string, any>) => {\n return formData.timeout_enabled === true;\n }\n }\n },\n result_name: {\n type: 'text',\n label: 'Result Name',\n helpText: 'The name to save the response as',\n placeholder: 'response'\n }\n },\n layout: ['rules', 'result_name'],\n gutter: [\n {\n type: 'row',\n items: ['timeout_enabled', 'timeout_duration'],\n gap: '0.5rem'\n }\n ],\n validate: (_formData: any) => {\n const errors: { [key: string]: string } = {};\n\n // No validation needed - allow multiple rules to use same category name\n // Rules with the same category name will be merged to use the same exit\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n toFormData: (node: Node) => {\n // Extract rules from router cases\n const rules = [];\n if (node.router?.cases && node.router?.categories) {\n node.router.cases.forEach((case_) => {\n // Find the category for this case\n const category = node.router!.categories.find(\n (cat) => cat.uuid === case_.category_uuid\n );\n\n // Skip timeout/system categories like \"No Response\"\n if (\n category &&\n category.name !== 'No Response' &&\n category.name !== 'Other'\n ) {\n // Handle different operator types\n const operatorConfig = getOperatorConfig(case_.type);\n const operatorDisplayName = operatorConfig\n ? operatorConfig.name\n : case_.type;\n let value1 = '';\n let value2 = '';\n\n if (operatorConfig && operatorConfig.operands === 0) {\n // No value needed for operators like has_text, has_number\n value1 = '';\n value2 = '';\n } else if (operatorConfig && operatorConfig.operands === 1) {\n // Single value for operators like has_number_lt - use value1\n value1 = case_.arguments.join(' ');\n value2 = '';\n } else if (operatorConfig && operatorConfig.operands === 2) {\n // Two separate values for operators like has_number_between\n value1 = case_.arguments[0] || '';\n value2 = case_.arguments[1] || '';\n } else {\n // Fallback: use first argument for unknown operators\n value1 = case_.arguments.join(' ');\n value2 = '';\n }\n\n rules.push({\n operator: { value: case_.type, name: operatorDisplayName },\n value1: value1,\n value2: value2,\n category: category.name\n });\n }\n });\n }\n\n // Extract timeout configuration\n const timeoutSeconds = node.router?.wait?.timeout?.seconds;\n let timeoutOption = TIMEOUT_OPTIONS.find(\n (opt) => opt.value === String(timeoutSeconds)\n );\n\n if (!timeoutOption) {\n timeoutOption = { value: '300', name: '5 minutes' };\n }\n\n return {\n uuid: node.uuid,\n rules: rules,\n timeout_enabled: !!timeoutSeconds,\n timeout_duration: timeoutOption,\n result_name: node.router?.result_name || 'response'\n };\n },\n fromFormData: (formData: any, originalNode: Node): Node => {\n // Helper function to get operator value from various formats\n const getOperatorValue = (operator: any): string => {\n if (typeof operator === 'string') {\n return operator.trim();\n } else if (Array.isArray(operator) && operator.length > 0) {\n // Handle array format: [{value: \"has_any_word\", name: \"...\"}]\n const firstOperator = operator[0];\n if (\n firstOperator &&\n typeof firstOperator === 'object' &&\n firstOperator.value\n ) {\n return firstOperator.value.trim();\n }\n } else if (operator && typeof operator === 'object' && operator.value) {\n // Handle object format: {value: \"has_any_word\", name: \"...\"}\n return operator.value.trim();\n }\n return '';\n };\n\n // Get user rules\n const userRules = (formData.rules || [])\n .filter((rule: any) => {\n // Always need operator and category\n const operatorValue = getOperatorValue(rule?.operator);\n if (\n !operatorValue ||\n !rule?.category ||\n operatorValue === '' ||\n rule.category.trim() === ''\n ) {\n return false;\n }\n\n // Check if value is required based on operator\n const operatorConfig = getOperatorConfig(operatorValue);\n if (operatorConfig && operatorConfig.operands === 1) {\n // value1 is required for this operator\n return rule?.value1 && rule.value1.trim() !== '';\n } else if (operatorConfig && operatorConfig.operands === 2) {\n // Both value1 and value2 are required for this operator\n return (\n rule?.value1 &&\n rule.value1.trim() !== '' &&\n rule?.value2 &&\n rule.value2.trim() !== ''\n );\n }\n\n // No value required for this operator\n return true;\n })\n .map((rule: any) => {\n const operatorValue = getOperatorValue(rule.operator);\n const operatorConfig = getOperatorConfig(operatorValue);\n\n let value = '';\n\n if (operatorConfig && operatorConfig.operands === 1) {\n // Single value from value1\n value = rule.value1 ? rule.value1.trim() : '';\n } else if (operatorConfig && operatorConfig.operands === 2) {\n // Two values - combine them with space\n const val1 = rule.value1 ? rule.value1.trim() : '';\n const val2 = rule.value2 ? rule.value2.trim() : '';\n value = `${val1} ${val2}`.trim();\n } else {\n // No value needed for 0-operand operators\n value = '';\n }\n\n return {\n operator: operatorValue,\n value: value,\n category: rule.category.trim()\n };\n });\n\n // If no user rules, clear cases but preserve other router config\n if (userRules.length === 0) {\n const router: any = {\n ...originalNode.router,\n result_name: formData.result_name || 'response'\n };\n\n // Only set cases to empty if the original node had cases\n if (originalNode.router?.cases !== undefined) {\n router.cases = []; // Clear all cases when no rules\n }\n\n // Build wait configuration based on form data\n const waitConfig: any = {\n type: 'msg'\n };\n\n // Add timeout if enabled\n if (formData.timeout_enabled) {\n // Extract timeout value (handle both string and object formats)\n let timeoutSeconds;\n\n if (formData.timeout_duration) {\n if (\n Array.isArray(formData.timeout_duration) &&\n formData.timeout_duration.length > 0\n ) {\n // Handle array of selected options (multi-select behavior)\n timeoutSeconds = parseInt(formData.timeout_duration[0].value, 10);\n } else if (typeof formData.timeout_duration === 'string') {\n timeoutSeconds = parseInt(formData.timeout_duration, 10);\n } else if (\n formData.timeout_duration &&\n typeof formData.timeout_duration === 'object' &&\n formData.timeout_duration.value\n ) {\n timeoutSeconds = parseInt(formData.timeout_duration.value, 10);\n } else {\n timeoutSeconds = 300; // Default to 5 minutes\n }\n } else {\n // No duration selected, use default\n timeoutSeconds = 300; // Default to 5 minutes\n }\n\n // Validate that we got a valid number\n if (isNaN(timeoutSeconds) || timeoutSeconds <= 0) {\n timeoutSeconds = 300; // Default to 5 minutes\n }\n\n // Find or create the \"No Response\" category\n let noResponseCategory = originalNode.router?.categories?.find(\n (cat: any) => cat.name === 'No Response'\n );\n\n if (!noResponseCategory) {\n noResponseCategory = {\n uuid: generateUUID(),\n name: 'No Response',\n exit_uuid: generateUUID()\n };\n\n // Add to router categories\n router.categories = router.categories || [];\n router.categories.push(noResponseCategory);\n }\n\n waitConfig.timeout = {\n seconds: timeoutSeconds,\n category_uuid: noResponseCategory.uuid\n };\n }\n\n router.wait = waitConfig;\n\n return {\n ...originalNode,\n router\n };\n }\n\n // Get existing router data for preservation\n const existingCategories = originalNode.router?.categories || [];\n const existingExits = originalNode.exits || [];\n const existingCases = originalNode.router?.cases || [];\n\n // Create router and exits using existing data when possible\n const { router, exits } = createWaitForResponseRouter(\n userRules,\n existingCategories,\n existingExits,\n existingCases\n );\n\n // Build final router with wait configuration and result_name\n const finalRouter: any = {\n ...router,\n result_name: formData.result_name || 'response'\n };\n\n // Build wait configuration based on form data\n const waitConfig: any = {\n type: 'msg'\n };\n\n try {\n // Handle timeout configuration\n if (formData.timeout_enabled) {\n // Extract timeout value (handle both string and object formats)\n let timeoutSeconds;\n\n if (formData.timeout_duration) {\n try {\n timeoutSeconds = parseInt(formData.timeout_duration[0].value, 10);\n } catch (e) {\n timeoutSeconds = 300; // Default to 5 minutes\n }\n }\n\n // Find or create the \"No Response\" category\n const existingNoResponseCategory =\n originalNode.router?.categories?.find(\n (cat: any) => cat.name === 'No Response'\n );\n\n const noResponseCategory = existingNoResponseCategory || {\n uuid: generateUUID(),\n name: 'No Response',\n exit_uuid: generateUUID()\n };\n\n waitConfig.timeout = {\n seconds: timeoutSeconds,\n category_uuid: noResponseCategory.uuid\n };\n\n // Ensure No Response category and exit exist\n if (\n !router.categories?.some((cat: any) => cat.name === 'No Response')\n ) {\n router.categories = router.categories || [];\n router.categories.push(noResponseCategory);\n\n // Add corresponding exit if it doesn't exist\n if (\n !exits.some(\n (exit: any) => exit.uuid === noResponseCategory.exit_uuid\n )\n ) {\n const noResponseExit = {\n uuid: noResponseCategory.exit_uuid,\n destination_uuid: existingNoResponseCategory?.exit_uuid\n ? originalNode.exits?.find(\n (exit) => exit.uuid === existingNoResponseCategory.exit_uuid\n )?.destination_uuid || null\n : null\n };\n exits.push(noResponseExit);\n }\n }\n } else {\n // Remove \"No Response\" category if timeout is disabled\n if (router.categories) {\n const noResponseCategoryIndex = router.categories.findIndex(\n (cat: any) => cat.name === 'No Response'\n );\n if (noResponseCategoryIndex !== -1) {\n const noResponseCategory =\n router.categories[noResponseCategoryIndex];\n\n // Remove the category\n router.categories.splice(noResponseCategoryIndex, 1);\n\n // Remove corresponding exit\n const exitIndex = exits.findIndex(\n (exit: any) => exit.uuid === noResponseCategory.exit_uuid\n );\n if (exitIndex !== -1) {\n exits.splice(exitIndex, 1);\n }\n }\n }\n }\n } catch (error) {\n console.error('Error processing timeout configuration:', error);\n // Continue without timeout in case of error\n }\n\n finalRouter.wait = waitConfig;\n return {\n ...originalNode,\n router: finalRouter,\n exits: exits\n };\n }\n};\n"]}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
// Flow router operator configurations
|
|
2
|
+
// These define the available operators for rule-based routing in flow nodes
|
|
3
|
+
// All available operators for flow routing
|
|
4
|
+
export const OPERATORS = [
|
|
5
|
+
// Text operators
|
|
6
|
+
{
|
|
7
|
+
type: 'has_any_word',
|
|
8
|
+
name: 'has any of the words',
|
|
9
|
+
operands: 1
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
type: 'has_all_words',
|
|
13
|
+
name: 'has all of the words',
|
|
14
|
+
operands: 1
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
type: 'has_phrase',
|
|
18
|
+
name: 'has the phrase',
|
|
19
|
+
operands: 1
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
type: 'has_only_phrase',
|
|
23
|
+
name: 'has only the phrase',
|
|
24
|
+
operands: 1
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
type: 'has_beginning',
|
|
28
|
+
name: 'starts with',
|
|
29
|
+
operands: 1
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
type: 'has_text',
|
|
33
|
+
name: 'has some text',
|
|
34
|
+
operands: 0,
|
|
35
|
+
categoryName: 'Has Text'
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
type: 'has_pattern',
|
|
39
|
+
name: 'matches regex',
|
|
40
|
+
operands: 1
|
|
41
|
+
},
|
|
42
|
+
// Number operators
|
|
43
|
+
{
|
|
44
|
+
type: 'has_number',
|
|
45
|
+
name: 'has a number',
|
|
46
|
+
operands: 0,
|
|
47
|
+
categoryName: 'Has Number'
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
type: 'has_number_between',
|
|
51
|
+
name: 'has a number between',
|
|
52
|
+
operands: 2
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
type: 'has_number_lt',
|
|
56
|
+
name: 'has a number below',
|
|
57
|
+
operands: 1
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
type: 'has_number_lte',
|
|
61
|
+
name: 'has a number at or below',
|
|
62
|
+
operands: 1
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
type: 'has_number_eq',
|
|
66
|
+
name: 'has a number equal to',
|
|
67
|
+
operands: 1
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
type: 'has_number_gte',
|
|
71
|
+
name: 'has a number at or above',
|
|
72
|
+
operands: 1
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
type: 'has_number_gt',
|
|
76
|
+
name: 'has a number above',
|
|
77
|
+
operands: 1
|
|
78
|
+
},
|
|
79
|
+
// Date operators
|
|
80
|
+
{
|
|
81
|
+
type: 'has_date',
|
|
82
|
+
name: 'has a date',
|
|
83
|
+
operands: 0,
|
|
84
|
+
categoryName: 'Has Date'
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
type: 'has_date_lt',
|
|
88
|
+
name: 'has a date before',
|
|
89
|
+
operands: 1
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
type: 'has_date_eq',
|
|
93
|
+
name: 'has a date equal to',
|
|
94
|
+
operands: 1
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
type: 'has_date_gt',
|
|
98
|
+
name: 'has a date after',
|
|
99
|
+
operands: 1
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
type: 'has_time',
|
|
103
|
+
name: 'has a time',
|
|
104
|
+
operands: 0,
|
|
105
|
+
categoryName: 'Has Time'
|
|
106
|
+
},
|
|
107
|
+
// Contact data operators
|
|
108
|
+
{
|
|
109
|
+
type: 'has_phone',
|
|
110
|
+
name: 'has a phone number',
|
|
111
|
+
operands: 0,
|
|
112
|
+
categoryName: 'Has Phone'
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
type: 'has_email',
|
|
116
|
+
name: 'has an email',
|
|
117
|
+
operands: 0,
|
|
118
|
+
categoryName: 'Has Email'
|
|
119
|
+
},
|
|
120
|
+
// Location operators (require location feature)
|
|
121
|
+
{
|
|
122
|
+
type: 'has_state',
|
|
123
|
+
name: 'has state',
|
|
124
|
+
operands: 0,
|
|
125
|
+
categoryName: 'Has State',
|
|
126
|
+
filter: 'HAS_LOCATIONS'
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
type: 'has_district',
|
|
130
|
+
name: 'has district',
|
|
131
|
+
operands: 1,
|
|
132
|
+
categoryName: 'Has District',
|
|
133
|
+
filter: 'HAS_LOCATIONS'
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
type: 'has_ward',
|
|
137
|
+
name: 'has ward',
|
|
138
|
+
operands: 2,
|
|
139
|
+
categoryName: 'Has Ward',
|
|
140
|
+
filter: 'HAS_LOCATIONS'
|
|
141
|
+
},
|
|
142
|
+
// Hidden/system operators
|
|
143
|
+
{
|
|
144
|
+
type: 'has_group',
|
|
145
|
+
name: 'is in the group',
|
|
146
|
+
operands: 1,
|
|
147
|
+
visibility: 'hidden'
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
type: 'has_category',
|
|
151
|
+
name: 'has the category',
|
|
152
|
+
operands: 0,
|
|
153
|
+
visibility: 'hidden'
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
type: 'has_error',
|
|
157
|
+
name: 'has an error',
|
|
158
|
+
operands: 0,
|
|
159
|
+
categoryName: 'Has Error',
|
|
160
|
+
visibility: 'hidden'
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
type: 'has_value',
|
|
164
|
+
name: 'is not empty',
|
|
165
|
+
operands: 0,
|
|
166
|
+
categoryName: 'Not Empty',
|
|
167
|
+
visibility: 'hidden'
|
|
168
|
+
}
|
|
169
|
+
];
|
|
170
|
+
// Get operators suitable for wait_for_response rules
|
|
171
|
+
export const getWaitForResponseOperators = () => {
|
|
172
|
+
return OPERATORS.filter((op) => op.visibility !== 'hidden' && !op.filter // For now, exclude location operators unless we support feature detection
|
|
173
|
+
);
|
|
174
|
+
};
|
|
175
|
+
// Get operator configuration by type
|
|
176
|
+
export const getOperatorConfig = (type) => {
|
|
177
|
+
return OPERATORS.find((op) => op.type === type);
|
|
178
|
+
};
|
|
179
|
+
// Convert operators to select options
|
|
180
|
+
export const operatorsToSelectOptions = (operators) => {
|
|
181
|
+
return operators.map((op) => ({
|
|
182
|
+
value: op.type,
|
|
183
|
+
name: op.name
|
|
184
|
+
}));
|
|
185
|
+
};
|
|
186
|
+
// Create an operator object for select components
|
|
187
|
+
export const createOperatorOption = (type) => {
|
|
188
|
+
const config = getOperatorConfig(type);
|
|
189
|
+
return {
|
|
190
|
+
value: type,
|
|
191
|
+
name: config ? config.name : type
|
|
192
|
+
};
|
|
193
|
+
};
|
|
194
|
+
//# sourceMappingURL=operators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operators.js","sourceRoot":"","sources":["../../../src/flow/operators.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,4EAA4E;AAW5E,2CAA2C;AAC3C,MAAM,CAAC,MAAM,SAAS,GAAqB;IACzC,iBAAiB;IACjB;QACE,IAAI,EAAE,cAAc;QACpB,IAAI,EAAE,sBAAsB;QAC5B,QAAQ,EAAE,CAAC;KACZ;IACD;QACE,IAAI,EAAE,eAAe;QACrB,IAAI,EAAE,sBAAsB;QAC5B,QAAQ,EAAE,CAAC;KACZ;IACD;QACE,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE,gBAAgB;QACtB,QAAQ,EAAE,CAAC;KACZ;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,IAAI,EAAE,qBAAqB;QAC3B,QAAQ,EAAE,CAAC;KACZ;IACD;QACE,IAAI,EAAE,eAAe;QACrB,IAAI,EAAE,aAAa;QACnB,QAAQ,EAAE,CAAC;KACZ;IACD;QACE,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,eAAe;QACrB,QAAQ,EAAE,CAAC;QACX,YAAY,EAAE,UAAU;KACzB;IACD;QACE,IAAI,EAAE,aAAa;QACnB,IAAI,EAAE,eAAe;QACrB,QAAQ,EAAE,CAAC;KACZ;IAED,mBAAmB;IACnB;QACE,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE,cAAc;QACpB,QAAQ,EAAE,CAAC;QACX,YAAY,EAAE,YAAY;KAC3B;IACD;QACE,IAAI,EAAE,oBAAoB;QAC1B,IAAI,EAAE,sBAAsB;QAC5B,QAAQ,EAAE,CAAC;KACZ;IACD;QACE,IAAI,EAAE,eAAe;QACrB,IAAI,EAAE,oBAAoB;QAC1B,QAAQ,EAAE,CAAC;KACZ;IACD;QACE,IAAI,EAAE,gBAAgB;QACtB,IAAI,EAAE,0BAA0B;QAChC,QAAQ,EAAE,CAAC;KACZ;IACD;QACE,IAAI,EAAE,eAAe;QACrB,IAAI,EAAE,uBAAuB;QAC7B,QAAQ,EAAE,CAAC;KACZ;IACD;QACE,IAAI,EAAE,gBAAgB;QACtB,IAAI,EAAE,0BAA0B;QAChC,QAAQ,EAAE,CAAC;KACZ;IACD;QACE,IAAI,EAAE,eAAe;QACrB,IAAI,EAAE,oBAAoB;QAC1B,QAAQ,EAAE,CAAC;KACZ;IAED,iBAAiB;IACjB;QACE,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,YAAY;QAClB,QAAQ,EAAE,CAAC;QACX,YAAY,EAAE,UAAU;KACzB;IACD;QACE,IAAI,EAAE,aAAa;QACnB,IAAI,EAAE,mBAAmB;QACzB,QAAQ,EAAE,CAAC;KACZ;IACD;QACE,IAAI,EAAE,aAAa;QACnB,IAAI,EAAE,qBAAqB;QAC3B,QAAQ,EAAE,CAAC;KACZ;IACD;QACE,IAAI,EAAE,aAAa;QACnB,IAAI,EAAE,kBAAkB;QACxB,QAAQ,EAAE,CAAC;KACZ;IACD;QACE,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,YAAY;QAClB,QAAQ,EAAE,CAAC;QACX,YAAY,EAAE,UAAU;KACzB;IAED,yBAAyB;IACzB;QACE,IAAI,EAAE,WAAW;QACjB,IAAI,EAAE,oBAAoB;QAC1B,QAAQ,EAAE,CAAC;QACX,YAAY,EAAE,WAAW;KAC1B;IACD;QACE,IAAI,EAAE,WAAW;QACjB,IAAI,EAAE,cAAc;QACpB,QAAQ,EAAE,CAAC;QACX,YAAY,EAAE,WAAW;KAC1B;IAED,gDAAgD;IAChD;QACE,IAAI,EAAE,WAAW;QACjB,IAAI,EAAE,WAAW;QACjB,QAAQ,EAAE,CAAC;QACX,YAAY,EAAE,WAAW;QACzB,MAAM,EAAE,eAAe;KACxB;IACD;QACE,IAAI,EAAE,cAAc;QACpB,IAAI,EAAE,cAAc;QACpB,QAAQ,EAAE,CAAC;QACX,YAAY,EAAE,cAAc;QAC5B,MAAM,EAAE,eAAe;KACxB;IACD;QACE,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE,CAAC;QACX,YAAY,EAAE,UAAU;QACxB,MAAM,EAAE,eAAe;KACxB;IAED,0BAA0B;IAC1B;QACE,IAAI,EAAE,WAAW;QACjB,IAAI,EAAE,iBAAiB;QACvB,QAAQ,EAAE,CAAC;QACX,UAAU,EAAE,QAAQ;KACrB;IACD;QACE,IAAI,EAAE,cAAc;QACpB,IAAI,EAAE,kBAAkB;QACxB,QAAQ,EAAE,CAAC;QACX,UAAU,EAAE,QAAQ;KACrB;IACD;QACE,IAAI,EAAE,WAAW;QACjB,IAAI,EAAE,cAAc;QACpB,QAAQ,EAAE,CAAC;QACX,YAAY,EAAE,WAAW;QACzB,UAAU,EAAE,QAAQ;KACrB;IACD;QACE,IAAI,EAAE,WAAW;QACjB,IAAI,EAAE,cAAc;QACpB,QAAQ,EAAE,CAAC;QACX,YAAY,EAAE,WAAW;QACzB,UAAU,EAAE,QAAQ;KACrB;CACF,CAAC;AAEF,qDAAqD;AACrD,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAqB,EAAE;IAChE,OAAO,SAAS,CAAC,MAAM,CACrB,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,KAAK,QAAQ,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,0EAA0E;KAC5H,CAAC;AACJ,CAAC,CAAC;AAEF,qCAAqC;AACrC,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,IAAY,EAA8B,EAAE;IAC5E,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AAClD,CAAC,CAAC;AAEF,sCAAsC;AACtC,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,SAA2B,EAAE,EAAE;IACtE,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QAC5B,KAAK,EAAE,EAAE,CAAC,IAAI;QACd,IAAI,EAAE,EAAE,CAAC,IAAI;KACd,CAAC,CAAC,CAAC;AACN,CAAC,CAAC;AAEF,kDAAkD;AAClD,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,IAAY,EACqB,EAAE;IACnC,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACvC,OAAO;QACL,KAAK,EAAE,IAAI;QACX,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;KAClC,CAAC;AACJ,CAAC,CAAC","sourcesContent":["// Flow router operator configurations\n// These define the available operators for rule-based routing in flow nodes\n\nexport interface OperatorConfig {\n type: string;\n name: string;\n operands: number; // Number of operands required (0 = no input needed, 1 = single value, 2 = two values)\n categoryName?: string; // Default category name when operands is 0\n visibility?: 'hidden' | 'visible'; // Whether to show in UI\n filter?: string; // Feature filter requirement\n}\n\n// All available operators for flow routing\nexport const OPERATORS: OperatorConfig[] = [\n // Text operators\n {\n type: 'has_any_word',\n name: 'has any of the words',\n operands: 1\n },\n {\n type: 'has_all_words',\n name: 'has all of the words',\n operands: 1\n },\n {\n type: 'has_phrase',\n name: 'has the phrase',\n operands: 1\n },\n {\n type: 'has_only_phrase',\n name: 'has only the phrase',\n operands: 1\n },\n {\n type: 'has_beginning',\n name: 'starts with',\n operands: 1\n },\n {\n type: 'has_text',\n name: 'has some text',\n operands: 0,\n categoryName: 'Has Text'\n },\n {\n type: 'has_pattern',\n name: 'matches regex',\n operands: 1\n },\n\n // Number operators\n {\n type: 'has_number',\n name: 'has a number',\n operands: 0,\n categoryName: 'Has Number'\n },\n {\n type: 'has_number_between',\n name: 'has a number between',\n operands: 2\n },\n {\n type: 'has_number_lt',\n name: 'has a number below',\n operands: 1\n },\n {\n type: 'has_number_lte',\n name: 'has a number at or below',\n operands: 1\n },\n {\n type: 'has_number_eq',\n name: 'has a number equal to',\n operands: 1\n },\n {\n type: 'has_number_gte',\n name: 'has a number at or above',\n operands: 1\n },\n {\n type: 'has_number_gt',\n name: 'has a number above',\n operands: 1\n },\n\n // Date operators\n {\n type: 'has_date',\n name: 'has a date',\n operands: 0,\n categoryName: 'Has Date'\n },\n {\n type: 'has_date_lt',\n name: 'has a date before',\n operands: 1\n },\n {\n type: 'has_date_eq',\n name: 'has a date equal to',\n operands: 1\n },\n {\n type: 'has_date_gt',\n name: 'has a date after',\n operands: 1\n },\n {\n type: 'has_time',\n name: 'has a time',\n operands: 0,\n categoryName: 'Has Time'\n },\n\n // Contact data operators\n {\n type: 'has_phone',\n name: 'has a phone number',\n operands: 0,\n categoryName: 'Has Phone'\n },\n {\n type: 'has_email',\n name: 'has an email',\n operands: 0,\n categoryName: 'Has Email'\n },\n\n // Location operators (require location feature)\n {\n type: 'has_state',\n name: 'has state',\n operands: 0,\n categoryName: 'Has State',\n filter: 'HAS_LOCATIONS'\n },\n {\n type: 'has_district',\n name: 'has district',\n operands: 1,\n categoryName: 'Has District',\n filter: 'HAS_LOCATIONS'\n },\n {\n type: 'has_ward',\n name: 'has ward',\n operands: 2,\n categoryName: 'Has Ward',\n filter: 'HAS_LOCATIONS'\n },\n\n // Hidden/system operators\n {\n type: 'has_group',\n name: 'is in the group',\n operands: 1,\n visibility: 'hidden'\n },\n {\n type: 'has_category',\n name: 'has the category',\n operands: 0,\n visibility: 'hidden'\n },\n {\n type: 'has_error',\n name: 'has an error',\n operands: 0,\n categoryName: 'Has Error',\n visibility: 'hidden'\n },\n {\n type: 'has_value',\n name: 'is not empty',\n operands: 0,\n categoryName: 'Not Empty',\n visibility: 'hidden'\n }\n];\n\n// Get operators suitable for wait_for_response rules\nexport const getWaitForResponseOperators = (): OperatorConfig[] => {\n return OPERATORS.filter(\n (op) => op.visibility !== 'hidden' && !op.filter // For now, exclude location operators unless we support feature detection\n );\n};\n\n// Get operator configuration by type\nexport const getOperatorConfig = (type: string): OperatorConfig | undefined => {\n return OPERATORS.find((op) => op.type === type);\n};\n\n// Convert operators to select options\nexport const operatorsToSelectOptions = (operators: OperatorConfig[]) => {\n return operators.map((op) => ({\n value: op.type,\n name: op.name\n }));\n};\n\n// Create an operator object for select components\nexport const createOperatorOption = (\n type: string\n): { value: string; name: string } => {\n const config = getOperatorConfig(type);\n return {\n value: type,\n name: config ? config.name : type\n };\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/flow/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/flow/types.ts"],"names":[],"mappings":"AA0QA,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,IAAI,EAAE,SAAS;IACf,MAAM,EAAE,SAAS;IACjB,SAAS,EAAE,SAAS;IACpB,IAAI,EAAE,SAAS;IACf,MAAM,EAAE,SAAS;IACjB,IAAI,EAAE,SAAS;IACf,KAAK,EAAE,SAAS;IAChB,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,SAAS;IACf,GAAG,EAAE,SAAS;IACd,MAAM,EAAE,SAAS;CAClB,CAAC","sourcesContent":["import { TemplateResult } from 'lit-html';\nimport { Action, Node } from '../store/flow-definition';\n\nexport interface ValidationResult {\n valid: boolean;\n errors: { [key: string]: string };\n}\n\n// Component attribute interfaces - these define what's allowed for each component type\nexport interface TextInputAttributes {\n type?: 'text' | 'email' | 'number' | 'url' | 'tel';\n placeholder?: string;\n clearable?: boolean;\n maxlength?: number;\n gsm?: boolean;\n autogrow?: boolean;\n textarea?: boolean;\n submitOnEnter?: boolean;\n}\n\nexport interface CompletionAttributes {\n placeholder?: string;\n clearable?: boolean;\n maxlength?: number;\n gsm?: boolean;\n autogrow?: boolean;\n textarea?: boolean;\n expressions?: string;\n counter?: string;\n minHeight?: number;\n}\n\nexport interface SelectAttributes {\n placeholder?: string;\n multi?: boolean;\n searchable?: boolean;\n tags?: boolean;\n emails?: boolean;\n clearable?: boolean;\n endpoint?: string;\n valueKey?: string;\n nameKey?: string;\n queryParam?: string;\n maxItems?: number;\n maxItemsText?: string;\n expressions?: string;\n options?: Array<{ name: string; value: any }>;\n sorted?: boolean;\n allowCreate?: boolean;\n jsonValue?: boolean;\n spaceSelect?: boolean;\n infoText?: string;\n}\n\nexport interface CheckboxAttributes {\n label?: string;\n size?: number;\n disabled?: boolean;\n animateChange?: string;\n}\n\nexport interface SliderAttributes {\n min?: number;\n max?: number;\n range?: boolean;\n}\n\nexport interface FormData extends Record<string, any> {}\n\nexport interface FormConfig {\n form?: Record<string, FieldConfig>;\n layout?: LayoutItem[];\n gutter?: LayoutItem[];\n sanitize?: (formData: FormData) => void;\n validate?: (formData: FormData) => ValidationResult;\n}\n\nexport interface NodeConfig extends FormConfig {\n type: string;\n name?: string;\n color?: string;\n dialogSize?: 'small' | 'medium' | 'large' | 'xlarge';\n action?: ActionConfig;\n router?: {\n type: 'switch' | 'random';\n defaultCategory?: string;\n operand?: string;\n configurable?: boolean; // can the rules be configured in the UI\n rules?: {\n type:\n | 'has_number_between'\n | 'has_string'\n | 'has_value'\n | 'has_not_value'\n | 'has_text';\n arguments: string[];\n categoryName: string;\n }[];\n };\n\n toFormData?: (node: Node) => FormData;\n fromFormData?: (formData: FormData, originalNode: Node) => Node;\n render?: (node: Node) => TemplateResult;\n}\n\n// New field configuration system for generic form generation\nexport interface BaseFieldConfig {\n label?: string | ((formData: Record<string, any>) => string);\n required?: boolean;\n evaluated?: boolean;\n dependsOn?: string[];\n computeValue?: (\n values: Record<string, any>,\n currentValue: any,\n originalValues?: Record<string, any>\n ) => any;\n\n // Validation properties\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n helpText?: string;\n\n // Layout properties\n maxWidth?: string;\n width?: string;\n\n // Conditional rendering\n conditions?: {\n visible?: (formData: Record<string, any>) => boolean;\n disabled?: (formData: Record<string, any>) => boolean;\n };\n}\n\nexport interface TextFieldConfig extends BaseFieldConfig {\n type: 'text';\n placeholder?: string;\n flavor?: 'xsmall' | 'small' | 'large';\n}\n\nexport interface TextareaFieldConfig extends BaseFieldConfig {\n type: 'textarea';\n placeholder?: string;\n rows?: number;\n minHeight?: number;\n}\n\nexport interface SelectFieldConfig extends BaseFieldConfig {\n type: 'select';\n options?: string[] | { value: string; name: string }[];\n multi?: boolean;\n clearable?: boolean;\n searchable?: boolean;\n tags?: boolean;\n placeholder?: string;\n maxItems?: number;\n valueKey?: string;\n nameKey?: string;\n endpoint?: string;\n emails?: boolean;\n getName?: (item: any) => string;\n flavor?: 'xsmall' | 'small' | 'large';\n createArbitraryOption?: (input: string, options: any[]) => any;\n allowCreate?: boolean;\n getDynamicOptions?: () => Array<{ value: string; name: string }>;\n}\n\nexport interface KeyValueFieldConfig extends BaseFieldConfig {\n type: 'key-value';\n sortable?: boolean;\n keyPlaceholder?: string;\n valuePlaceholder?: string;\n minRows?: number;\n}\n\nexport interface ArrayFieldConfig extends BaseFieldConfig {\n type: 'array';\n itemConfig: Record<string, FieldConfig>;\n sortable?: boolean;\n minItems?: number;\n maxItems?: number;\n itemLabel?: string;\n maintainEmptyItem?: boolean;\n onItemChange?: (\n itemIndex: number,\n field: string,\n value: any,\n allItems: any[]\n ) => any[];\n isEmptyItem?: (item: any) => boolean;\n}\n\nexport interface CheckboxFieldConfig extends BaseFieldConfig {\n type: 'checkbox';\n size?: number;\n animateChange?: string;\n labelPadding?: string;\n}\n\nexport interface MessageEditorFieldConfig extends BaseFieldConfig {\n type: 'message-editor';\n placeholder?: string;\n minHeight?: number;\n maxAttachments?: number;\n accept?: string;\n endpoint?: string;\n counter?: string;\n gsm?: boolean;\n autogrow?: boolean;\n disableCompletion?: boolean;\n}\n\nexport type FieldConfig =\n | TextFieldConfig\n | TextareaFieldConfig\n | SelectFieldConfig\n | KeyValueFieldConfig\n | ArrayFieldConfig\n | CheckboxFieldConfig\n | MessageEditorFieldConfig;\n\n// Layout configurations for better form organization\n// Recursive layout system - any layout item can contain other layout items\n\nexport interface FieldItemConfig {\n type: 'field';\n field: string; // field name to render\n}\n\nexport interface RowLayoutConfig {\n type: 'row';\n items: LayoutItem[]; // can contain fields, groups, or other rows\n gap?: string; // CSS gap value, defaults to '1rem'\n}\n\nexport interface GroupLayoutConfig {\n type: 'group';\n label: string;\n items: LayoutItem[]; // can contain fields, rows, or other groups\n collapsible?: boolean;\n collapsed?: boolean | ((formData: any) => boolean); // initial state if collapsible - can be a function\n helpText?: string;\n getGroupValueCount?: (formData: any) => number; // optional function to get count for bubble display\n}\n\nexport type LayoutItem =\n | FieldItemConfig\n | RowLayoutConfig\n | GroupLayoutConfig\n | string; // string is shorthand for field\n\nexport interface ActionConfig extends FormConfig {\n name: string;\n color: string;\n dialogSize?: 'small' | 'medium' | 'large' | 'xlarge';\n evaluated?: string[];\n render?: (node: any, action: any) => TemplateResult;\n\n form?: Record<string, FieldConfig>;\n layout?: LayoutItem[]; // optional layout configuration - array of layout items\n gutter?: LayoutItem[]; // fields to render in the dialog gutter (left side of buttons)\n\n toFormData?: (action: Action) => any;\n fromFormData?: (formData: any) => Action;\n}\n\nexport const COLORS = {\n send: '#3498db',\n update: '#01c1af',\n broadcast: '#8e5ea7',\n call: '#e68628',\n create: '#df419f',\n save: '#1a777c',\n split: '#aaaaaa',\n execute: '#666666',\n wait: '#4d7dad',\n add: '#309c42',\n remove: '#e74c3c'\n};\n"]}
|
|
@@ -76,10 +76,20 @@ let TembaArrayEditor = class TembaArrayEditor extends BaseListEditor {
|
|
|
76
76
|
}
|
|
77
77
|
renderArrayField(itemIndex, fieldName, config) {
|
|
78
78
|
const computedValue = this.computeFieldValue(itemIndex, fieldName, config);
|
|
79
|
+
// Extract flavor from select config if available
|
|
80
|
+
const flavor = config.type === 'select' ? config.flavor || 'small' : 'small';
|
|
81
|
+
// Build container style with width/maxWidth if specified
|
|
82
|
+
let containerStyle = '';
|
|
83
|
+
if (config.width) {
|
|
84
|
+
containerStyle = `width: ${config.width};`;
|
|
85
|
+
}
|
|
86
|
+
else if (config.maxWidth) {
|
|
87
|
+
containerStyle = `max-width: ${config.maxWidth};`;
|
|
88
|
+
}
|
|
79
89
|
// Use FieldRenderer for consistent field rendering
|
|
80
|
-
|
|
90
|
+
const fieldContent = FieldRenderer.renderField(fieldName, config, computedValue, {
|
|
81
91
|
showLabel: false, // ArrayEditor doesn't show labels for individual fields
|
|
82
|
-
flavor:
|
|
92
|
+
flavor: flavor,
|
|
83
93
|
extraClasses: 'form-control',
|
|
84
94
|
onChange: (e) => {
|
|
85
95
|
let value;
|
|
@@ -96,27 +106,65 @@ let TembaArrayEditor = class TembaArrayEditor extends BaseListEditor {
|
|
|
96
106
|
this.handleFieldChange(itemIndex, fieldName, value);
|
|
97
107
|
}
|
|
98
108
|
});
|
|
109
|
+
// Wrap in container with style if maxWidth is specified
|
|
110
|
+
if (containerStyle) {
|
|
111
|
+
return html `<div style="${containerStyle}">${fieldContent}</div>`;
|
|
112
|
+
}
|
|
113
|
+
return fieldContent;
|
|
99
114
|
}
|
|
100
115
|
renderItem(item, index) {
|
|
101
116
|
const canRemove = this.canRemoveItem(index);
|
|
117
|
+
// Render fields and track if any value fields are visible
|
|
118
|
+
const fieldElements = [];
|
|
119
|
+
let hasVisibleValueField = false;
|
|
120
|
+
Object.entries(this.itemConfig).forEach(([fieldName, config]) => {
|
|
121
|
+
var _a;
|
|
122
|
+
// Check visibility condition
|
|
123
|
+
let isVisible = true;
|
|
124
|
+
if ((_a = config.conditions) === null || _a === void 0 ? void 0 : _a.visible) {
|
|
125
|
+
try {
|
|
126
|
+
const currentItem = this._items[index] || {};
|
|
127
|
+
isVisible = config.conditions.visible(currentItem);
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
console.error(`Error checking visibility for ${fieldName}:`, error);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (isVisible) {
|
|
134
|
+
// Check if this is a value field (text input without fixed sizing)
|
|
135
|
+
const isValueField = !config.width && !config.maxWidth && config.type === 'text';
|
|
136
|
+
if (isValueField) {
|
|
137
|
+
hasVisibleValueField = true;
|
|
138
|
+
}
|
|
139
|
+
fieldElements.push(html `
|
|
140
|
+
<div
|
|
141
|
+
class="field ${config.width ||
|
|
142
|
+
config.maxWidth ||
|
|
143
|
+
config.type === 'select'
|
|
144
|
+
? 'field-fixed'
|
|
145
|
+
: 'field-flex'}"
|
|
146
|
+
>
|
|
147
|
+
${this.renderArrayField(index, fieldName, config)}
|
|
148
|
+
</div>
|
|
149
|
+
`);
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
// If no value fields are visible, add a spacer to maintain alignment
|
|
153
|
+
if (!hasVisibleValueField) {
|
|
154
|
+
// Insert spacer after operator (first field) and before category (last field)
|
|
155
|
+
fieldElements.splice(-1, 0, html `<div class="field field-flex spacer"></div>`);
|
|
156
|
+
}
|
|
102
157
|
return html `
|
|
103
158
|
<div class="array-item">
|
|
104
159
|
<div class="item-fields">
|
|
105
|
-
${
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
@click=${() => this.removeItem(index)}
|
|
114
|
-
class="remove-btn"
|
|
115
|
-
>
|
|
116
|
-
<temba-icon name="x"></temba-icon>
|
|
117
|
-
</button>
|
|
118
|
-
`
|
|
119
|
-
: ''}
|
|
160
|
+
${fieldElements}
|
|
161
|
+
<button
|
|
162
|
+
@click=${canRemove ? () => this.removeItem(index) : undefined}
|
|
163
|
+
class="remove-btn ${canRemove ? '' : 'invisible'}"
|
|
164
|
+
?disabled=${!canRemove}
|
|
165
|
+
>
|
|
166
|
+
<temba-icon name="x"></temba-icon>
|
|
167
|
+
</button>
|
|
120
168
|
</div>
|
|
121
169
|
</div>
|
|
122
170
|
`;
|
|
@@ -152,12 +200,24 @@ let TembaArrayEditor = class TembaArrayEditor extends BaseListEditor {
|
|
|
152
200
|
}
|
|
153
201
|
|
|
154
202
|
.field {
|
|
155
|
-
|
|
203
|
+
/* Base field styles */
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.field-flex {
|
|
207
|
+
flex: 1; /* Grow to fill remaining space */
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.field-fixed {
|
|
211
|
+
flex: none; /* Don't grow, use content/maxWidth size */
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.spacer {
|
|
215
|
+
/* Empty spacer to maintain layout alignment */
|
|
156
216
|
}
|
|
157
217
|
|
|
158
218
|
.add-btn,
|
|
159
219
|
.remove-btn {
|
|
160
|
-
padding:
|
|
220
|
+
padding: 4px;
|
|
161
221
|
border: 1px solid #ccc;
|
|
162
222
|
border-radius: 4px;
|
|
163
223
|
background: white;
|
|
@@ -174,6 +234,11 @@ let TembaArrayEditor = class TembaArrayEditor extends BaseListEditor {
|
|
|
174
234
|
background: #fefefe;
|
|
175
235
|
color: #999;
|
|
176
236
|
}
|
|
237
|
+
|
|
238
|
+
.remove-btn.invisible {
|
|
239
|
+
visibility: hidden;
|
|
240
|
+
cursor: default;
|
|
241
|
+
}
|
|
177
242
|
`;
|
|
178
243
|
}
|
|
179
244
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ArrayEditor.js","sourceRoot":"","sources":["../../../src/form/ArrayEditor.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, css, TemplateResult } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { FieldConfig } from '../flow/types';\nimport { BaseListEditor, ListItem } from './BaseListEditor';\nimport { FieldRenderer } from './FieldRenderer';\n\n@customElement('temba-array-editor')\nexport class TembaArrayEditor extends BaseListEditor<ListItem> {\n @property({ type: Object })\n itemConfig: Record<string, FieldConfig> = {};\n\n @property({ type: String })\n itemLabel = 'Item';\n\n @property({ type: Function })\n onItemChange?: (\n itemIndex: number,\n field: string,\n value: any,\n allItems: any[]\n ) => any[];\n\n @property({ type: Function })\n isEmptyItemFn?: (item: any) => boolean;\n\n @property({ type: Boolean })\n maintainEmptyItem = true; // Enable by default for better UX\n\n constructor() {\n super();\n this._items = [];\n }\n\n // External API\n @property({ type: Array })\n get value(): any[] {\n return [...this._items];\n }\n\n set value(newValue: any[]) {\n this._items = newValue || [];\n this.requestUpdate();\n }\n\n // Implement abstract methods\n isEmptyItem(item: ListItem): boolean {\n // Use configurable function if provided\n if (this.isEmptyItemFn) {\n return this.isEmptyItemFn(item);\n }\n\n // Default behavior: check if all values are empty\n const values = Object.values(item);\n if (values.length === 0) {\n return true;\n }\n\n return values.every(\n (value) => value === undefined || value === null || value === ''\n );\n }\n\n // Override cleanItems to be more permissive for form data\n protected cleanItems(items: ListItem[]): any {\n // For runtime attachments, keep items that have at least one non-empty field\n return items.filter((item) => {\n const values = Object.values(item);\n return (\n values.length > 0 &&\n values.some(\n (value) => value !== undefined && value !== null && value !== ''\n )\n );\n });\n }\n\n createEmptyItem(): ListItem {\n return {};\n }\n\n protected handleFieldChange(\n itemIndex: number,\n fieldName: string,\n newValue: any\n ) {\n let updatedItems: any[];\n\n if (this.onItemChange) {\n updatedItems = this.onItemChange(\n itemIndex,\n fieldName,\n newValue,\n this._items\n );\n } else {\n updatedItems = [...this._items];\n updatedItems[itemIndex] = {\n ...updatedItems[itemIndex],\n [fieldName]: newValue\n };\n }\n\n this.updateValue(updatedItems);\n }\n\n private computeFieldValue(\n itemIndex: number,\n fieldName: string,\n config: FieldConfig\n ): any {\n const item = this._items[itemIndex] || {};\n const currentValue = item[fieldName];\n\n if (config.computeValue) {\n return config.computeValue(item, currentValue);\n }\n\n // For select fields, ensure we return the right type\n /*if (config.type === 'select') {\n console.log('computeFieldValue select', currentValue, config);\n const selectConfig = config as SelectFieldConfig;\n if (currentValue === undefined || currentValue === null) {\n return selectConfig.multi ? [] : '';\n }\n }*/\n\n return currentValue;\n }\n\n private renderArrayField(\n itemIndex: number,\n fieldName: string,\n config: FieldConfig\n ): TemplateResult {\n const computedValue = this.computeFieldValue(itemIndex, fieldName, config);\n\n // Use FieldRenderer for consistent field rendering\n return FieldRenderer.renderField(fieldName, config, computedValue, {\n showLabel: false, // ArrayEditor doesn't show labels for individual fields\n flavor: 'small', // ArrayEditor uses small flavor\n extraClasses: 'form-control',\n onChange: (e: Event) => {\n let value: any;\n const target = e.target as any;\n\n // Handle different field types and their change events\n if (config.type === 'select') {\n // Use consistent temba-select value normalization\n value = target.values;\n } else {\n // For other field types, use the target value directly\n value = target.value;\n }\n\n this.handleFieldChange(itemIndex, fieldName, value);\n }\n });\n }\n\n renderItem(item: ListItem, index: number): TemplateResult {\n const canRemove = this.canRemoveItem(index);\n\n return html`\n <div class=\"array-item\">\n <div class=\"item-fields\">\n ${Object.entries(this.itemConfig).map(\n ([fieldName, config]) => html`\n <div class=\"field\">\n ${this.renderArrayField(index, fieldName, config)}\n </div>\n `\n )}\n ${canRemove\n ? html`\n <button\n @click=${() => this.removeItem(index)}\n class=\"remove-btn\"\n >\n <temba-icon name=\"x\"></temba-icon>\n </button>\n `\n : ''}\n </div>\n </div>\n `;\n }\n\n protected getContainerClass(): string {\n return 'array-editor';\n }\n\n static get styles() {\n return css`\n ${super.styles}\n\n .array-editor {\n }\n\n .array-item {\n }\n\n .item-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n\n .item-title {\n font-weight: 600;\n color: #333;\n }\n\n .item-fields {\n display: flex;\n gap: 12px;\n align-items: center;\n }\n\n .field {\n flex: 1;\n }\n\n .add-btn,\n .remove-btn {\n padding: 8px;\n border: 1px solid #ccc;\n border-radius: 4px;\n background: white;\n cursor: pointer;\n font-size: 14px;\n }\n\n .add-btn:hover,\n .remove-btn:hover {\n background: #f8f8f8;\n }\n\n .remove-btn {\n background: #fefefe;\n color: #999;\n }\n `;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ArrayEditor.js","sourceRoot":"","sources":["../../../src/form/ArrayEditor.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, css, TemplateResult } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { FieldConfig } from '../flow/types';\nimport { BaseListEditor, ListItem } from './BaseListEditor';\nimport { FieldRenderer } from './FieldRenderer';\n\n@customElement('temba-array-editor')\nexport class TembaArrayEditor extends BaseListEditor<ListItem> {\n @property({ type: Object })\n itemConfig: Record<string, FieldConfig> = {};\n\n @property({ type: String })\n itemLabel = 'Item';\n\n @property({ type: Function })\n onItemChange?: (\n itemIndex: number,\n field: string,\n value: any,\n allItems: any[]\n ) => any[];\n\n @property({ type: Function })\n isEmptyItemFn?: (item: any) => boolean;\n\n @property({ type: Boolean })\n maintainEmptyItem = true; // Enable by default for better UX\n\n constructor() {\n super();\n this._items = [];\n }\n\n // External API\n @property({ type: Array })\n get value(): any[] {\n return [...this._items];\n }\n\n set value(newValue: any[]) {\n this._items = newValue || [];\n this.requestUpdate();\n }\n\n // Implement abstract methods\n isEmptyItem(item: ListItem): boolean {\n // Use configurable function if provided\n if (this.isEmptyItemFn) {\n return this.isEmptyItemFn(item);\n }\n\n // Default behavior: check if all values are empty\n const values = Object.values(item);\n if (values.length === 0) {\n return true;\n }\n\n return values.every(\n (value) => value === undefined || value === null || value === ''\n );\n }\n\n // Override cleanItems to be more permissive for form data\n protected cleanItems(items: ListItem[]): any {\n // For runtime attachments, keep items that have at least one non-empty field\n return items.filter((item) => {\n const values = Object.values(item);\n return (\n values.length > 0 &&\n values.some(\n (value) => value !== undefined && value !== null && value !== ''\n )\n );\n });\n }\n\n createEmptyItem(): ListItem {\n return {};\n }\n\n protected handleFieldChange(\n itemIndex: number,\n fieldName: string,\n newValue: any\n ) {\n let updatedItems: any[];\n\n if (this.onItemChange) {\n updatedItems = this.onItemChange(\n itemIndex,\n fieldName,\n newValue,\n this._items\n );\n } else {\n updatedItems = [...this._items];\n updatedItems[itemIndex] = {\n ...updatedItems[itemIndex],\n [fieldName]: newValue\n };\n }\n\n this.updateValue(updatedItems);\n }\n\n private computeFieldValue(\n itemIndex: number,\n fieldName: string,\n config: FieldConfig\n ): any {\n const item = this._items[itemIndex] || {};\n const currentValue = item[fieldName];\n\n if (config.computeValue) {\n return config.computeValue(item, currentValue);\n }\n\n // For select fields, ensure we return the right type\n /*if (config.type === 'select') {\n console.log('computeFieldValue select', currentValue, config);\n const selectConfig = config as SelectFieldConfig;\n if (currentValue === undefined || currentValue === null) {\n return selectConfig.multi ? [] : '';\n }\n }*/\n\n return currentValue;\n }\n\n private renderArrayField(\n itemIndex: number,\n fieldName: string,\n config: FieldConfig\n ): TemplateResult {\n const computedValue = this.computeFieldValue(itemIndex, fieldName, config);\n\n // Extract flavor from select config if available\n const flavor =\n config.type === 'select' ? (config as any).flavor || 'small' : 'small';\n\n // Build container style with width/maxWidth if specified\n let containerStyle = '';\n if (config.width) {\n containerStyle = `width: ${config.width};`;\n } else if (config.maxWidth) {\n containerStyle = `max-width: ${config.maxWidth};`;\n }\n\n // Use FieldRenderer for consistent field rendering\n const fieldContent = FieldRenderer.renderField(\n fieldName,\n config,\n computedValue,\n {\n showLabel: false, // ArrayEditor doesn't show labels for individual fields\n flavor: flavor,\n extraClasses: 'form-control',\n onChange: (e: Event) => {\n let value: any;\n const target = e.target as any;\n\n // Handle different field types and their change events\n if (config.type === 'select') {\n // Use consistent temba-select value normalization\n value = target.values;\n } else {\n // For other field types, use the target value directly\n value = target.value;\n }\n\n this.handleFieldChange(itemIndex, fieldName, value);\n }\n }\n );\n\n // Wrap in container with style if maxWidth is specified\n if (containerStyle) {\n return html`<div style=\"${containerStyle}\">${fieldContent}</div>`;\n }\n\n return fieldContent;\n }\n\n renderItem(item: ListItem, index: number): TemplateResult {\n const canRemove = this.canRemoveItem(index);\n\n // Render fields and track if any value fields are visible\n const fieldElements: TemplateResult[] = [];\n let hasVisibleValueField = false;\n\n Object.entries(this.itemConfig).forEach(([fieldName, config]) => {\n // Check visibility condition\n let isVisible = true;\n if (config.conditions?.visible) {\n try {\n const currentItem = this._items[index] || {};\n isVisible = config.conditions.visible(currentItem);\n } catch (error) {\n console.error(`Error checking visibility for ${fieldName}:`, error);\n }\n }\n\n if (isVisible) {\n // Check if this is a value field (text input without fixed sizing)\n const isValueField =\n !config.width && !config.maxWidth && config.type === 'text';\n if (isValueField) {\n hasVisibleValueField = true;\n }\n\n fieldElements.push(html`\n <div\n class=\"field ${config.width ||\n config.maxWidth ||\n config.type === 'select'\n ? 'field-fixed'\n : 'field-flex'}\"\n >\n ${this.renderArrayField(index, fieldName, config)}\n </div>\n `);\n }\n });\n\n // If no value fields are visible, add a spacer to maintain alignment\n if (!hasVisibleValueField) {\n // Insert spacer after operator (first field) and before category (last field)\n fieldElements.splice(\n -1,\n 0,\n html`<div class=\"field field-flex spacer\"></div>`\n );\n }\n\n return html`\n <div class=\"array-item\">\n <div class=\"item-fields\">\n ${fieldElements}\n <button\n @click=${canRemove ? () => this.removeItem(index) : undefined}\n class=\"remove-btn ${canRemove ? '' : 'invisible'}\"\n ?disabled=${!canRemove}\n >\n <temba-icon name=\"x\"></temba-icon>\n </button>\n </div>\n </div>\n `;\n }\n\n protected getContainerClass(): string {\n return 'array-editor';\n }\n\n static get styles() {\n return css`\n ${super.styles}\n\n .array-editor {\n }\n\n .array-item {\n }\n\n .item-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n\n .item-title {\n font-weight: 600;\n color: #333;\n }\n\n .item-fields {\n display: flex;\n gap: 12px;\n align-items: center;\n }\n\n .field {\n /* Base field styles */\n }\n\n .field-flex {\n flex: 1; /* Grow to fill remaining space */\n }\n\n .field-fixed {\n flex: none; /* Don't grow, use content/maxWidth size */\n }\n\n .spacer {\n /* Empty spacer to maintain layout alignment */\n }\n\n .add-btn,\n .remove-btn {\n padding: 4px;\n border: 1px solid #ccc;\n border-radius: 4px;\n background: white;\n cursor: pointer;\n font-size: 14px;\n }\n\n .add-btn:hover,\n .remove-btn:hover {\n background: #f8f8f8;\n }\n\n .remove-btn {\n background: #fefefe;\n color: #999;\n }\n\n .remove-btn.invisible {\n visibility: hidden;\n cursor: default;\n }\n `;\n }\n}\n"]}
|
|
@@ -25,6 +25,16 @@ export class Checkbox extends FieldElement {
|
|
|
25
25
|
width: 100%;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
.checkbox-background {
|
|
29
|
+
position: absolute;
|
|
30
|
+
margin-top: 2px;
|
|
31
|
+
margin-left: 2px;
|
|
32
|
+
width: 12px;
|
|
33
|
+
height: 12px;
|
|
34
|
+
background: var(--checkbox-background, rgba(255, 255, 255, 0.8));
|
|
35
|
+
border-radius: 2px;
|
|
36
|
+
}
|
|
37
|
+
|
|
28
38
|
.wrapper.label {
|
|
29
39
|
padding: var(--checkbox-padding, 10px);
|
|
30
40
|
border-radius: var(--curvature);
|
|
@@ -142,7 +152,9 @@ export class Checkbox extends FieldElement {
|
|
|
142
152
|
@click=${this.handleClick}
|
|
143
153
|
>
|
|
144
154
|
<div class="checkbox-container ${this.disabled ? 'disabled' : ''}">
|
|
155
|
+
<div class="checkbox-background"></div>
|
|
145
156
|
${icon}
|
|
157
|
+
|
|
146
158
|
<div class="label-and-help">
|
|
147
159
|
${this.label && String(this.label).trim()
|
|
148
160
|
? html `<div class="checkbox-label">${this.label}</div>`
|