@nyaruka/temba-components 0.129.11 → 0.130.1

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.
Files changed (120) hide show
  1. package/CHANGELOG.md +13 -4
  2. package/demo/components/flow/example.html +5 -1
  3. package/demo/data/flows/sample-flow.json +144 -80
  4. package/dist/temba-components.js +290 -346
  5. package/dist/temba-components.js.map +1 -1
  6. package/out-tsc/src/flow/CanvasNode.js +3 -35
  7. package/out-tsc/src/flow/CanvasNode.js.map +1 -1
  8. package/out-tsc/src/flow/NodeEditor.js +44 -11
  9. package/out-tsc/src/flow/NodeEditor.js.map +1 -1
  10. package/out-tsc/src/flow/actions/add_contact_groups.js +14 -2
  11. package/out-tsc/src/flow/actions/add_contact_groups.js.map +1 -1
  12. package/out-tsc/src/flow/actions/add_contact_urn.js +1 -1
  13. package/out-tsc/src/flow/actions/add_contact_urn.js.map +1 -1
  14. package/out-tsc/src/flow/actions/add_input_labels.js +2 -1
  15. package/out-tsc/src/flow/actions/add_input_labels.js.map +1 -1
  16. package/out-tsc/src/flow/actions/remove_contact_groups.js +1 -1
  17. package/out-tsc/src/flow/actions/remove_contact_groups.js.map +1 -1
  18. package/out-tsc/src/flow/actions/send_email.js +9 -0
  19. package/out-tsc/src/flow/actions/send_email.js.map +1 -1
  20. package/out-tsc/src/flow/actions/send_msg.js +7 -8
  21. package/out-tsc/src/flow/actions/send_msg.js.map +1 -1
  22. package/out-tsc/src/flow/actions/set_contact_channel.js +25 -4
  23. package/out-tsc/src/flow/actions/set_contact_channel.js.map +1 -1
  24. package/out-tsc/src/flow/actions/set_contact_field.js +51 -1
  25. package/out-tsc/src/flow/actions/set_contact_field.js.map +1 -1
  26. package/out-tsc/src/flow/actions/set_contact_language.js +70 -2
  27. package/out-tsc/src/flow/actions/set_contact_language.js.map +1 -1
  28. package/out-tsc/src/flow/actions/set_contact_name.js +27 -2
  29. package/out-tsc/src/flow/actions/set_contact_name.js.map +1 -1
  30. package/out-tsc/src/flow/actions/set_contact_status.js +32 -2
  31. package/out-tsc/src/flow/actions/set_contact_status.js.map +1 -1
  32. package/out-tsc/src/flow/actions/set_run_result.js +13 -11
  33. package/out-tsc/src/flow/actions/set_run_result.js.map +1 -1
  34. package/out-tsc/src/flow/actions/split_by_expression_example.js +4 -4
  35. package/out-tsc/src/flow/actions/split_by_expression_example.js.map +1 -1
  36. package/out-tsc/src/flow/forms/index.js +2 -0
  37. package/out-tsc/src/flow/forms/index.js.map +1 -0
  38. package/out-tsc/src/flow/nodes/split_by_random.js +117 -0
  39. package/out-tsc/src/flow/nodes/split_by_random.js.map +1 -1
  40. package/out-tsc/src/flow/nodes/split_by_ticket.js +0 -1
  41. package/out-tsc/src/flow/nodes/split_by_ticket.js.map +1 -1
  42. package/out-tsc/src/flow/nodes/split_by_webhook.js +1 -3
  43. package/out-tsc/src/flow/nodes/split_by_webhook.js.map +1 -1
  44. package/out-tsc/src/flow/types.js.map +1 -1
  45. package/out-tsc/src/form/ArrayEditor.js +9 -25
  46. package/out-tsc/src/form/ArrayEditor.js.map +1 -1
  47. package/out-tsc/src/form/FieldRenderer.js +6 -64
  48. package/out-tsc/src/form/FieldRenderer.js.map +1 -1
  49. package/out-tsc/src/form/select/Select.js +35 -58
  50. package/out-tsc/src/form/select/Select.js.map +1 -1
  51. package/out-tsc/src/utils.js +3 -0
  52. package/out-tsc/src/utils.js.map +1 -1
  53. package/out-tsc/test/nodes/split_by_random.test.js +0 -6
  54. package/out-tsc/test/nodes/split_by_random.test.js.map +1 -1
  55. package/out-tsc/test/temba-field-renderer.test.js +6 -3
  56. package/out-tsc/test/temba-field-renderer.test.js.map +1 -1
  57. package/out-tsc/test/utils.test.js +18 -0
  58. package/out-tsc/test/utils.test.js.map +1 -1
  59. package/package.json +1 -1
  60. package/screenshots/truth/actions/add_contact_groups/editor/descriptive-group-names.png +0 -0
  61. package/screenshots/truth/actions/add_contact_groups/editor/long-group-names.png +0 -0
  62. package/screenshots/truth/actions/add_contact_groups/editor/many-groups.png +0 -0
  63. package/screenshots/truth/actions/add_contact_groups/editor/multiple-groups.png +0 -0
  64. package/screenshots/truth/actions/add_contact_groups/editor/single-group.png +0 -0
  65. package/screenshots/truth/actions/add_contact_groups/render/descriptive-group-names.png +0 -0
  66. package/screenshots/truth/actions/add_contact_groups/render/long-group-names.png +0 -0
  67. package/screenshots/truth/actions/add_contact_groups/render/many-groups.png +0 -0
  68. package/screenshots/truth/actions/add_contact_groups/render/multiple-groups.png +0 -0
  69. package/screenshots/truth/actions/add_contact_groups/render/single-group.png +0 -0
  70. package/screenshots/truth/actions/remove_contact_groups/editor/cleanup-groups.png +0 -0
  71. package/screenshots/truth/actions/remove_contact_groups/editor/long-descriptive-group-names.png +0 -0
  72. package/screenshots/truth/actions/remove_contact_groups/editor/many-groups.png +0 -0
  73. package/screenshots/truth/actions/remove_contact_groups/editor/multiple-groups.png +0 -0
  74. package/screenshots/truth/actions/remove_contact_groups/editor/remove-from-all-groups.png +0 -0
  75. package/screenshots/truth/actions/remove_contact_groups/editor/single-group.png +0 -0
  76. package/screenshots/truth/actions/remove_contact_groups/render/cleanup-groups.png +0 -0
  77. package/screenshots/truth/actions/remove_contact_groups/render/long-descriptive-group-names.png +0 -0
  78. package/screenshots/truth/actions/remove_contact_groups/render/many-groups.png +0 -0
  79. package/screenshots/truth/actions/remove_contact_groups/render/multiple-groups.png +0 -0
  80. package/screenshots/truth/actions/remove_contact_groups/render/remove-from-all-groups.png +0 -0
  81. package/screenshots/truth/actions/remove_contact_groups/render/single-group.png +0 -0
  82. package/screenshots/truth/editor/set_contact_language.png +0 -0
  83. package/screenshots/truth/editor/set_contact_name.png +0 -0
  84. package/screenshots/truth/editor/set_run_result.png +0 -0
  85. package/screenshots/truth/nodes/split_by_random/editor/ab-test-multiple-variants.png +0 -0
  86. package/screenshots/truth/nodes/split_by_random/editor/sampling-split.png +0 -0
  87. package/screenshots/truth/nodes/split_by_random/editor/three-way-split.png +0 -0
  88. package/screenshots/truth/nodes/split_by_random/editor/two-bucket-split.png +0 -0
  89. package/src/flow/CanvasNode.ts +2 -39
  90. package/src/flow/NodeEditor.ts +54 -13
  91. package/src/flow/actions/add_contact_groups.ts +17 -2
  92. package/src/flow/actions/add_contact_urn.ts +1 -1
  93. package/src/flow/actions/add_input_labels.ts +2 -1
  94. package/src/flow/actions/remove_contact_groups.ts +1 -1
  95. package/src/flow/actions/send_email.ts +11 -1
  96. package/src/flow/actions/send_msg.ts +20 -11
  97. package/src/flow/actions/set_contact_channel.ts +28 -5
  98. package/src/flow/actions/set_contact_field.ts +56 -2
  99. package/src/flow/actions/set_contact_language.ts +74 -3
  100. package/src/flow/actions/set_contact_name.ts +31 -3
  101. package/src/flow/actions/set_contact_status.ts +36 -3
  102. package/src/flow/actions/set_run_result.ts +13 -15
  103. package/src/flow/actions/split_by_expression_example.ts +4 -4
  104. package/src/flow/forms/index.ts +1 -0
  105. package/src/flow/nodes/split_by_random.ts +148 -0
  106. package/src/flow/nodes/split_by_ticket.ts +0 -1
  107. package/src/flow/nodes/split_by_webhook.ts +1 -3
  108. package/src/flow/types.ts +2 -1
  109. package/src/form/ArrayEditor.ts +6 -20
  110. package/src/form/FieldRenderer.ts +6 -65
  111. package/src/form/select/Select.ts +38 -66
  112. package/src/store/flow-definition.d.ts +6 -1
  113. package/src/utils.ts +4 -0
  114. package/static/api/fields.json +93 -1208
  115. package/static/api/workspace.json +23 -0
  116. package/test/nodes/split_by_random.test.ts +0 -7
  117. package/test/temba-field-renderer.test.ts +26 -13
  118. package/test/utils.test.ts +20 -0
  119. package/web-dev-server.config.mjs +2 -0
  120. package/web-test-runner.config.mjs +37 -0
@@ -1,6 +1,7 @@
1
1
  import { html } from 'lit-html';
2
2
  import { unsafeHTML } from 'lit-html/directives/unsafe-html.js';
3
3
  import { COLORS } from '../types';
4
+ import { titleCase } from '../../utils';
4
5
  export const send_msg = {
5
6
  name: 'Send Message',
6
7
  color: COLORS.send,
@@ -63,10 +64,10 @@ export const send_msg = {
63
64
  type: {
64
65
  type: 'select',
65
66
  options: [
66
- { value: 'image', label: 'Image' },
67
- { value: 'audio', label: 'Audio' },
68
- { value: 'video', label: 'Video' },
69
- { value: 'document', label: 'Document' }
67
+ { value: 'image', name: 'Image' },
68
+ { value: 'audio', name: 'Audio' },
69
+ { value: 'video', name: 'Video' },
70
+ { value: 'document', name: 'Document' }
70
71
  ],
71
72
  required: true,
72
73
  searchable: false
@@ -120,14 +121,12 @@ export const send_msg = {
120
121
  const contentType = attachment.substring(0, colonIndex);
121
122
  const value = attachment.substring(colonIndex + 1);
122
123
  if (!contentType.includes('/')) {
123
- // This is a runtime attachment
124
124
  runtimeAttachments.push({
125
- type: contentType,
125
+ type: { name: titleCase(contentType), value: contentType },
126
126
  expression: value
127
127
  });
128
128
  }
129
129
  else {
130
- // This is a static attachment
131
130
  staticAttachments.push(attachment);
132
131
  }
133
132
  }
@@ -156,7 +155,7 @@ export const send_msg = {
156
155
  const staticAttachments = data.attachments || [];
157
156
  const runtimeAttachments = (data.runtime_attachments || [])
158
157
  .filter((item) => item && item.type && item.expression) // Filter out invalid items
159
- .map((item) => `${item.type}:${item.expression}`);
158
+ .map((item) => `${item.type[0].value}:${item.expression}`);
160
159
  result.attachments = [...staticAttachments, ...runtimeAttachments];
161
160
  // Remove quick_replies if empty to match original format
162
161
  if (result.quick_replies.length === 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"send_msg.js","sourceRoot":"","sources":["../../../../src/flow/actions/send_msg.ts"],"names":[],"mappings":"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","sourcesContent":["import { html } from 'lit-html';\nimport { unsafeHTML } from 'lit-html/directives/unsafe-html.js';\nimport { ActionConfig, COLORS, ValidationResult } from '../types';\nimport { Node, SendMsg } from '../../store/flow-definition';\n\nexport const send_msg: ActionConfig = {\n name: 'Send Message',\n color: COLORS.send,\n render: (_node: Node, action: SendMsg) => {\n const text = action.text.replace(/\\n/g, '<br>');\n return html`\n ${unsafeHTML(text)}\n ${action.quick_replies?.length > 0\n ? html`<div class=\"quick-replies\">\n ${action.quick_replies.map((reply) => {\n return html`<div class=\"quick-reply\">${reply}</div>`;\n })}\n ${action.template\n ? html`<div\n style=\"border: 1px solid var(--color-widget-border);padding: 0.5em;margin-top: 1em;border-radius: var(--curvature); display:flex;background: rgba(0,0,0,.03);\"\n >\n <temba-icon name=\"channel_wac\"></temba-icon>\n <div style=\"margin-left:0.5em\">${action.template.name}</div>\n </div>`\n : null}\n </div>`\n : null}\n `;\n },\n form: {\n text: {\n type: 'message-editor',\n label: 'Message',\n helpText:\n 'Enter the message to send with optional attachments. You can use expressions like @contact.name',\n required: true,\n evaluated: true,\n placeholder: 'Type your message here...',\n maxAttachments: 10,\n accept: '',\n endpoint: '/api/v2/media.json',\n counter: 'temba-charcount',\n gsm: true,\n autogrow: true\n },\n quick_replies: {\n type: 'select',\n options: [],\n multi: true,\n tags: true,\n searchable: true,\n placeholder: 'Add quick replies...',\n maxItems: 10,\n evaluated: true\n },\n runtime_attachments: {\n type: 'array',\n helpText: 'Add dynamic attachments using expressions',\n itemLabel: 'Attachment',\n maxItems: 10,\n isEmptyItem: (item: any) => {\n return !item.expression || item.expression.trim() === '';\n },\n itemConfig: {\n type: {\n type: 'select',\n options: [\n { value: 'image', label: 'Image' },\n { value: 'audio', label: 'Audio' },\n { value: 'video', label: 'Video' },\n { value: 'document', label: 'Document' }\n ],\n required: true,\n searchable: false\n },\n expression: {\n type: 'text',\n placeholder: 'Expression (e.g. @contact.photo)',\n required: true,\n evaluated: true\n }\n }\n }\n },\n layout: [\n 'text',\n {\n type: 'group',\n label: 'Quick Replies',\n items: ['quick_replies'],\n collapsible: true,\n collapsed: (formData: any) => {\n // Collapse only if there are no quick replies\n return !formData.quick_replies || formData.quick_replies.length === 0;\n },\n getGroupValueCount: (formData: any) => {\n return formData.quick_replies?.length || 0;\n }\n },\n {\n type: 'group',\n label: 'Runtime Attachments',\n items: ['runtime_attachments'],\n collapsible: true,\n collapsed: true,\n helpText: 'Add dynamic attachments that are evaluated at runtime',\n getGroupValueCount: (formData: any) => {\n return (\n formData.runtime_attachments?.filter(\n (item: any) =>\n item && item.expression && item.expression.trim() !== ''\n ).length || 0\n );\n }\n }\n ],\n toFormData: (action: SendMsg) => {\n // Extract runtime attachments from the text field attachments\n const runtimeAttachments: { type: string; expression: string }[] = [];\n const staticAttachments: string[] = [];\n\n if (action.attachments && Array.isArray(action.attachments)) {\n action.attachments.forEach((attachment) => {\n if (typeof attachment === 'string' && attachment.includes(':')) {\n const colonIndex = attachment.indexOf(':');\n const contentType = attachment.substring(0, colonIndex);\n const value = attachment.substring(colonIndex + 1);\n\n if (!contentType.includes('/')) {\n // This is a runtime attachment\n runtimeAttachments.push({\n type: contentType,\n expression: value\n });\n } else {\n // This is a static attachment\n staticAttachments.push(attachment);\n }\n }\n });\n }\n\n return {\n uuid: action.uuid,\n text: action.text || '',\n attachments: staticAttachments,\n runtime_attachments: runtimeAttachments,\n quick_replies: (action.quick_replies || []).map((reply) => ({\n name: reply,\n value: reply\n }))\n };\n },\n fromFormData: (data: Record<string, any>) => {\n const result = {\n uuid: data.uuid,\n type: 'send_msg',\n text: data.text || '',\n attachments: [],\n quick_replies: (data.quick_replies || []).map((reply: any) =>\n typeof reply === 'string' ? reply : reply.value || reply.name || reply\n )\n };\n\n // Combine static attachments from text field with runtime attachments\n const staticAttachments = data.attachments || [];\n const runtimeAttachments = (data.runtime_attachments || [])\n .filter((item: any) => item && item.type && item.expression) // Filter out invalid items\n .map(\n (item: { type: string; expression: string }) =>\n `${item.type}:${item.expression}`\n );\n\n result.attachments = [...staticAttachments, ...runtimeAttachments];\n\n // Remove quick_replies if empty to match original format\n if (result.quick_replies.length === 0) {\n delete (result as any).quick_replies;\n }\n\n return result as SendMsg;\n },\n sanitize: (formData: any): void => {\n if (formData.text && typeof formData.text === 'string') {\n formData.text = formData.text.trim();\n }\n },\n validate: (action: SendMsg): ValidationResult => {\n const errors: { [key: string]: string } = {};\n\n if (!action.text || action.text.trim() === '') {\n errors.text = 'Message text is required';\n }\n\n const attachments = action.attachments || [];\n if (attachments.length > 10) {\n const staticAttachments = attachments.filter(\n (attachment) =>\n typeof attachment === 'string' &&\n attachment.substring(0, attachment.indexOf(':')).includes('/')\n );\n\n const runtimeAttachments = attachments.filter(\n (attachment) =>\n typeof attachment === 'string' &&\n !attachment.substring(0, attachment.indexOf(':')).includes('/')\n );\n\n if (runtimeAttachments.length > 0) {\n errors.runtime_attachments =\n 'Each message can only have up to 10 attachments';\n }\n\n if (staticAttachments.length > 0) {\n const message = 'Each message can only have up to 10 total attachments';\n if (errors.text) {\n errors.text += ` ${message}`;\n } else {\n errors.text = message;\n }\n }\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n }\n};\n"]}
1
+ {"version":3,"file":"send_msg.js","sourceRoot":"","sources":["../../../../src/flow/actions/send_msg.ts"],"names":[],"mappings":"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","sourcesContent":["import { html } from 'lit-html';\nimport { unsafeHTML } from 'lit-html/directives/unsafe-html.js';\nimport { ActionConfig, COLORS, ValidationResult } from '../types';\nimport { Node, SendMsg } from '../../store/flow-definition';\nimport { titleCase } from '../../utils';\n\nexport const send_msg: ActionConfig = {\n name: 'Send Message',\n color: COLORS.send,\n render: (_node: Node, action: SendMsg) => {\n const text = action.text.replace(/\\n/g, '<br>');\n return html`\n ${unsafeHTML(text)}\n ${action.quick_replies?.length > 0\n ? html`<div class=\"quick-replies\">\n ${action.quick_replies.map((reply) => {\n return html`<div class=\"quick-reply\">${reply}</div>`;\n })}\n ${action.template\n ? html`<div\n style=\"border: 1px solid var(--color-widget-border);padding: 0.5em;margin-top: 1em;border-radius: var(--curvature); display:flex;background: rgba(0,0,0,.03);\"\n >\n <temba-icon name=\"channel_wac\"></temba-icon>\n <div style=\"margin-left:0.5em\">${action.template.name}</div>\n </div>`\n : null}\n </div>`\n : null}\n `;\n },\n form: {\n text: {\n type: 'message-editor',\n label: 'Message',\n helpText:\n 'Enter the message to send with optional attachments. You can use expressions like @contact.name',\n required: true,\n evaluated: true,\n placeholder: 'Type your message here...',\n maxAttachments: 10,\n accept: '',\n endpoint: '/api/v2/media.json',\n counter: 'temba-charcount',\n gsm: true,\n autogrow: true\n },\n quick_replies: {\n type: 'select',\n options: [],\n multi: true,\n tags: true,\n searchable: true,\n placeholder: 'Add quick replies...',\n maxItems: 10,\n evaluated: true\n },\n runtime_attachments: {\n type: 'array',\n helpText: 'Add dynamic attachments using expressions',\n itemLabel: 'Attachment',\n maxItems: 10,\n isEmptyItem: (item: any) => {\n return !item.expression || item.expression.trim() === '';\n },\n itemConfig: {\n type: {\n type: 'select',\n options: [\n { value: 'image', name: 'Image' },\n { value: 'audio', name: 'Audio' },\n { value: 'video', name: 'Video' },\n { value: 'document', name: 'Document' }\n ],\n required: true,\n searchable: false\n },\n expression: {\n type: 'text',\n placeholder: 'Expression (e.g. @contact.photo)',\n required: true,\n evaluated: true\n }\n }\n }\n },\n layout: [\n 'text',\n {\n type: 'group',\n label: 'Quick Replies',\n items: ['quick_replies'],\n collapsible: true,\n collapsed: (formData: any) => {\n // Collapse only if there are no quick replies\n return !formData.quick_replies || formData.quick_replies.length === 0;\n },\n getGroupValueCount: (formData: any) => {\n return formData.quick_replies?.length || 0;\n }\n },\n {\n type: 'group',\n label: 'Runtime Attachments',\n items: ['runtime_attachments'],\n collapsible: true,\n collapsed: true,\n helpText: 'Add dynamic attachments that are evaluated at runtime',\n getGroupValueCount: (formData: any) => {\n return (\n formData.runtime_attachments?.filter(\n (item: any) =>\n item && item.expression && item.expression.trim() !== ''\n ).length || 0\n );\n }\n }\n ],\n toFormData: (action: SendMsg) => {\n // Extract runtime attachments from the text field attachments\n const runtimeAttachments: {\n type: { name: string; value: string };\n expression: string;\n }[] = [];\n const staticAttachments: string[] = [];\n\n if (action.attachments && Array.isArray(action.attachments)) {\n action.attachments.forEach((attachment) => {\n if (typeof attachment === 'string' && attachment.includes(':')) {\n const colonIndex = attachment.indexOf(':');\n const contentType = attachment.substring(0, colonIndex);\n const value = attachment.substring(colonIndex + 1);\n\n if (!contentType.includes('/')) {\n runtimeAttachments.push({\n type: { name: titleCase(contentType), value: contentType },\n expression: value\n });\n } else {\n staticAttachments.push(attachment);\n }\n }\n });\n }\n\n return {\n uuid: action.uuid,\n text: action.text || '',\n attachments: staticAttachments,\n runtime_attachments: runtimeAttachments,\n quick_replies: (action.quick_replies || []).map((reply) => ({\n name: reply,\n value: reply\n }))\n };\n },\n fromFormData: (data: Record<string, any>) => {\n const result = {\n uuid: data.uuid,\n type: 'send_msg',\n text: data.text || '',\n attachments: [],\n quick_replies: (data.quick_replies || []).map((reply: any) =>\n typeof reply === 'string' ? reply : reply.value || reply.name || reply\n )\n };\n\n // Combine static attachments from text field with runtime attachments\n const staticAttachments = data.attachments || [];\n const runtimeAttachments = (data.runtime_attachments || [])\n .filter(\n (item: {\n type: [{ name: string; value: string }];\n expression: string;\n }) => item && item.type && item.expression\n ) // Filter out invalid items\n .map(\n (item: {\n type: [{ name: string; value: string }];\n expression: string;\n }) => `${item.type[0].value}:${item.expression}`\n );\n\n result.attachments = [...staticAttachments, ...runtimeAttachments];\n\n // Remove quick_replies if empty to match original format\n if (result.quick_replies.length === 0) {\n delete (result as any).quick_replies;\n }\n\n return result as SendMsg;\n },\n sanitize: (formData: any): void => {\n if (formData.text && typeof formData.text === 'string') {\n formData.text = formData.text.trim();\n }\n },\n validate: (action: SendMsg): ValidationResult => {\n const errors: { [key: string]: string } = {};\n\n if (!action.text || action.text.trim() === '') {\n errors.text = 'Message text is required';\n }\n\n const attachments = action.attachments || [];\n if (attachments.length > 10) {\n const staticAttachments = attachments.filter(\n (attachment) =>\n typeof attachment === 'string' &&\n attachment.substring(0, attachment.indexOf(':')).includes('/')\n );\n\n const runtimeAttachments = attachments.filter(\n (attachment) =>\n typeof attachment === 'string' &&\n !attachment.substring(0, attachment.indexOf(':')).includes('/')\n );\n\n if (runtimeAttachments.length > 0) {\n errors.runtime_attachments =\n 'Each message can only have up to 10 attachments';\n }\n\n if (staticAttachments.length > 0) {\n const message = 'Each message can only have up to 10 total attachments';\n if (errors.text) {\n errors.text += ` ${message}`;\n } else {\n errors.text = message;\n }\n }\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n }\n};\n"]}
@@ -1,12 +1,33 @@
1
1
  import { html } from 'lit-html';
2
2
  import { COLORS } from '../types';
3
3
  export const set_contact_channel = {
4
- name: 'Update Contact',
4
+ name: 'Update Channel',
5
5
  color: COLORS.update,
6
6
  render: (_node, action) => {
7
- return html `<div>
8
- Set contact channel to <b>${action.channel.name}</b>
9
- </div>`;
7
+ return html `<div>Set to <b>${action.channel.name}</b></div>`;
8
+ },
9
+ form: {
10
+ channel: {
11
+ type: 'select',
12
+ label: 'Channel',
13
+ required: true,
14
+ searchable: true,
15
+ clearable: false,
16
+ endpoint: '/api/v2/channels.json',
17
+ valueKey: 'uuid',
18
+ nameKey: 'name',
19
+ helpText: 'Select the channel to set for the contact'
20
+ }
21
+ },
22
+ validate: (formData) => {
23
+ const errors = {};
24
+ if (!formData.channel) {
25
+ errors.channel = 'Channel is required';
26
+ }
27
+ return {
28
+ valid: Object.keys(errors).length === 0,
29
+ errors
30
+ };
10
31
  }
11
32
  };
12
33
  //# sourceMappingURL=set_contact_channel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"set_contact_channel.js","sourceRoot":"","sources":["../../../../src/flow/actions/set_contact_channel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,MAAM,EAAE,MAAM,UAAU,CAAC;AAGhD,MAAM,CAAC,MAAM,mBAAmB,GAAiB;IAC/C,IAAI,EAAE,gBAAgB;IACtB,KAAK,EAAE,MAAM,CAAC,MAAM;IACpB,MAAM,EAAE,CAAC,KAAW,EAAE,MAAyB,EAAE,EAAE;QACjD,OAAO,IAAI,CAAA;kCACmB,MAAM,CAAC,OAAO,CAAC,IAAI;WAC1C,CAAC;IACV,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, COLORS } from '../types';\nimport { Node, SetContactChannel } from '../../store/flow-definition';\n\nexport const set_contact_channel: ActionConfig = {\n name: 'Update Contact',\n color: COLORS.update,\n render: (_node: Node, action: SetContactChannel) => {\n return html`<div>\n Set contact channel to <b>${action.channel.name}</b>\n </div>`;\n }\n};\n"]}
1
+ {"version":3,"file":"set_contact_channel.js","sourceRoot":"","sources":["../../../../src/flow/actions/set_contact_channel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,MAAM,EAAoB,MAAM,UAAU,CAAC;AAGlE,MAAM,CAAC,MAAM,mBAAmB,GAAiB;IAC/C,IAAI,EAAE,gBAAgB;IACtB,KAAK,EAAE,MAAM,CAAC,MAAM;IACpB,MAAM,EAAE,CAAC,KAAW,EAAE,MAAyB,EAAE,EAAE;QACjD,OAAO,IAAI,CAAA,kBAAkB,MAAM,CAAC,OAAO,CAAC,IAAI,YAAY,CAAC;IAC/D,CAAC;IACD,IAAI,EAAE;QACJ,OAAO,EAAE;YACP,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,SAAS;YAChB,QAAQ,EAAE,IAAI;YACd,UAAU,EAAE,IAAI;YAChB,SAAS,EAAE,KAAK;YAChB,QAAQ,EAAE,uBAAuB;YACjC,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,MAAM;YACf,QAAQ,EAAE,2CAA2C;SACtD;KACF;IACD,QAAQ,EAAE,CAAC,QAA2B,EAAoB,EAAE;QAC1D,MAAM,MAAM,GAA8B,EAAE,CAAC;QAE7C,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YACtB,MAAM,CAAC,OAAO,GAAG,qBAAqB,CAAC;QACzC,CAAC;QAED,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC;YACvC,MAAM;SACP,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, COLORS, ValidationResult } from '../types';\nimport { Node, SetContactChannel } from '../../store/flow-definition';\n\nexport const set_contact_channel: ActionConfig = {\n name: 'Update Channel',\n color: COLORS.update,\n render: (_node: Node, action: SetContactChannel) => {\n return html`<div>Set to <b>${action.channel.name}</b></div>`;\n },\n form: {\n channel: {\n type: 'select',\n label: 'Channel',\n required: true,\n searchable: true,\n clearable: false,\n endpoint: '/api/v2/channels.json',\n valueKey: 'uuid',\n nameKey: 'name',\n helpText: 'Select the channel to set for the contact'\n }\n },\n validate: (formData: SetContactChannel): ValidationResult => {\n const errors: { [key: string]: string } = {};\n\n if (!formData.channel) {\n errors.channel = 'Channel is required';\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n }\n};\n"]}
@@ -1,12 +1,62 @@
1
1
  import { html } from 'lit-html';
2
2
  import { COLORS } from '../types';
3
3
  export const set_contact_field = {
4
- name: 'Update Contact',
4
+ name: 'Update Field',
5
5
  color: COLORS.update,
6
6
  render: (_node, action) => {
7
7
  return html `<div>
8
8
  Set <b>${action.field.name}</b> to <b>${action.value}</b>
9
9
  </div>`;
10
+ },
11
+ form: {
12
+ field: {
13
+ type: 'select',
14
+ label: 'Field',
15
+ required: true,
16
+ searchable: true,
17
+ clearable: false,
18
+ nameKey: 'name',
19
+ valueKey: 'key',
20
+ endpoint: '/api/v2/fields.json',
21
+ helpText: 'Select the contact field to update',
22
+ allowCreate: true,
23
+ createArbitraryOption: (input) => ({ key: input, name: input })
24
+ },
25
+ value: {
26
+ type: 'text',
27
+ label: 'Value',
28
+ placeholder: 'Enter field value...',
29
+ required: true,
30
+ evaluated: true,
31
+ helpText: 'The new value for the contact field. You can use expressions like @contact.name'
32
+ }
33
+ },
34
+ fromFormData: (formData) => {
35
+ const field = formData.field[0];
36
+ return {
37
+ uuid: formData.uuid,
38
+ type: 'set_contact_field',
39
+ field: { name: field.name, key: field.key },
40
+ value: formData.value
41
+ };
42
+ },
43
+ validate: (formData) => {
44
+ const errors = {};
45
+ if (!formData.field) {
46
+ errors.field = 'Field is required';
47
+ }
48
+ if (!formData.value || formData.value.trim() === '') {
49
+ errors.value = 'Field value is required';
50
+ }
51
+ return {
52
+ valid: Object.keys(errors).length === 0,
53
+ errors
54
+ };
55
+ },
56
+ sanitize: (formData) => {
57
+ if (formData.value && typeof formData.value === 'string') {
58
+ formData.value = formData.value.trim();
59
+ }
10
60
  }
11
61
  };
12
62
  //# sourceMappingURL=set_contact_field.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"set_contact_field.js","sourceRoot":"","sources":["../../../../src/flow/actions/set_contact_field.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,MAAM,EAAE,MAAM,UAAU,CAAC;AAGhD,MAAM,CAAC,MAAM,iBAAiB,GAAiB;IAC7C,IAAI,EAAE,gBAAgB;IACtB,KAAK,EAAE,MAAM,CAAC,MAAM;IACpB,MAAM,EAAE,CAAC,KAAW,EAAE,MAAuB,EAAE,EAAE;QAC/C,OAAO,IAAI,CAAA;eACA,MAAM,CAAC,KAAK,CAAC,IAAI,cAAc,MAAM,CAAC,KAAK;WAC/C,CAAC;IACV,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, COLORS } from '../types';\nimport { Node, SetContactField } from '../../store/flow-definition';\n\nexport const set_contact_field: ActionConfig = {\n name: 'Update Contact',\n color: COLORS.update,\n render: (_node: Node, action: SetContactField) => {\n return html`<div>\n Set <b>${action.field.name}</b> to <b>${action.value}</b>\n </div>`;\n }\n};\n"]}
1
+ {"version":3,"file":"set_contact_field.js","sourceRoot":"","sources":["../../../../src/flow/actions/set_contact_field.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,MAAM,EAAoB,MAAM,UAAU,CAAC;AAGlE,MAAM,CAAC,MAAM,iBAAiB,GAAiB;IAC7C,IAAI,EAAE,cAAc;IACpB,KAAK,EAAE,MAAM,CAAC,MAAM;IACpB,MAAM,EAAE,CAAC,KAAW,EAAE,MAAuB,EAAE,EAAE;QAC/C,OAAO,IAAI,CAAA;eACA,MAAM,CAAC,KAAK,CAAC,IAAI,cAAc,MAAM,CAAC,KAAK;WAC/C,CAAC;IACV,CAAC;IACD,IAAI,EAAE;QACJ,KAAK,EAAE;YACL,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,OAAO;YACd,QAAQ,EAAE,IAAI;YACd,UAAU,EAAE,IAAI;YAChB,SAAS,EAAE,KAAK;YAChB,OAAO,EAAE,MAAM;YACf,QAAQ,EAAE,KAAK;YACf,QAAQ,EAAE,qBAAqB;YAC/B,QAAQ,EAAE,oCAAoC;YAC9C,WAAW,EAAE,IAAI;YACjB,qBAAqB,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;SACxE;QACD,KAAK,EAAE;YACL,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,OAAO;YACd,WAAW,EAAE,sBAAsB;YACnC,QAAQ,EAAE,IAAI;YACd,SAAS,EAAE,IAAI;YACf,QAAQ,EACN,iFAAiF;SACpF;KACF;IACD,YAAY,EAAE,CAAC,QAAyB,EAAmB,EAAE;QAC3D,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAChC,OAAO;YACL,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,IAAI,EAAE,mBAAmB;YACzB,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE;YAC3C,KAAK,EAAE,QAAQ,CAAC,KAAK;SACtB,CAAC;IACJ,CAAC;IACD,QAAQ,EAAE,CAAC,QAAyB,EAAoB,EAAE;QACxD,MAAM,MAAM,GAA8B,EAAE,CAAC;QAE7C,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;YACpB,MAAM,CAAC,KAAK,GAAG,mBAAmB,CAAC;QACrC,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACpD,MAAM,CAAC,KAAK,GAAG,yBAAyB,CAAC;QAC3C,CAAC;QAED,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC;YACvC,MAAM;SACP,CAAC;IACJ,CAAC;IACD,QAAQ,EAAE,CAAC,QAAyB,EAAQ,EAAE;QAC5C,IAAI,QAAQ,CAAC,KAAK,IAAI,OAAO,QAAQ,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACzD,QAAQ,CAAC,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACzC,CAAC;IACH,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, COLORS, ValidationResult } from '../types';\nimport { Node, SetContactField } from '../../store/flow-definition';\n\nexport const set_contact_field: ActionConfig = {\n name: 'Update Field',\n color: COLORS.update,\n render: (_node: Node, action: SetContactField) => {\n return html`<div>\n Set <b>${action.field.name}</b> to <b>${action.value}</b>\n </div>`;\n },\n form: {\n field: {\n type: 'select',\n label: 'Field',\n required: true,\n searchable: true,\n clearable: false,\n nameKey: 'name',\n valueKey: 'key',\n endpoint: '/api/v2/fields.json',\n helpText: 'Select the contact field to update',\n allowCreate: true,\n createArbitraryOption: (input: string) => ({ key: input, name: input })\n },\n value: {\n type: 'text',\n label: 'Value',\n placeholder: 'Enter field value...',\n required: true,\n evaluated: true,\n helpText:\n 'The new value for the contact field. You can use expressions like @contact.name'\n }\n },\n fromFormData: (formData: SetContactField): SetContactField => {\n const field = formData.field[0];\n return {\n uuid: formData.uuid,\n type: 'set_contact_field',\n field: { name: field.name, key: field.key },\n value: formData.value\n };\n },\n validate: (formData: SetContactField): ValidationResult => {\n const errors: { [key: string]: string } = {};\n\n if (!formData.field) {\n errors.field = 'Field is required';\n }\n\n if (!formData.value || formData.value.trim() === '') {\n errors.value = 'Field value is required';\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n sanitize: (formData: SetContactField): void => {\n if (formData.value && typeof formData.value === 'string') {\n formData.value = formData.value.trim();\n }\n }\n};\n"]}
@@ -1,10 +1,78 @@
1
1
  import { html } from 'lit-html';
2
2
  import { COLORS } from '../types';
3
+ import { getStore } from '../../store/Store';
3
4
  export const set_contact_language = {
4
- name: 'Update Contact',
5
+ name: 'Update Language',
5
6
  color: COLORS.update,
6
7
  render: (_node, action) => {
7
- return html `<div>Set contact language to <b>${action.language}</b></div>`;
8
+ const languageNames = new Intl.DisplayNames(['en'], {
9
+ type: 'language'
10
+ });
11
+ return html `<div>Set to <b>${languageNames.of(action.language)}</b></div>`;
12
+ },
13
+ form: {
14
+ language: {
15
+ type: 'select',
16
+ label: 'Language',
17
+ required: true,
18
+ searchable: true,
19
+ clearable: false,
20
+ valueKey: 'value',
21
+ nameKey: 'name',
22
+ helpText: 'Select the language to set for the contact',
23
+ getDynamicOptions: () => {
24
+ const store = getStore();
25
+ const workspace = store === null || store === void 0 ? void 0 : store.getState().workspace;
26
+ if ((workspace === null || workspace === void 0 ? void 0 : workspace.languages) && Array.isArray(workspace.languages)) {
27
+ const languageNames = new Intl.DisplayNames(['en'], {
28
+ type: 'language'
29
+ });
30
+ return workspace.languages.map((languageCode) => ({
31
+ value: languageCode,
32
+ name: languageNames.of(languageCode) || languageCode
33
+ }));
34
+ }
35
+ return [];
36
+ }
37
+ }
38
+ },
39
+ toFormData: (action) => {
40
+ // Convert the language code back to the option object format expected by the form
41
+ if (action.language) {
42
+ const languageNames = new Intl.DisplayNames(['en'], {
43
+ type: 'language'
44
+ });
45
+ return {
46
+ language: [
47
+ {
48
+ value: action.language,
49
+ name: languageNames.of(action.language) || action.language
50
+ }
51
+ ],
52
+ uuid: action.uuid
53
+ };
54
+ }
55
+ return {
56
+ language: null,
57
+ uuid: action.uuid
58
+ };
59
+ },
60
+ fromFormData: (formData) => {
61
+ return {
62
+ uuid: formData.uuid,
63
+ type: 'set_contact_language',
64
+ language: formData.language[0].value
65
+ };
66
+ },
67
+ validate: (formData) => {
68
+ const errors = {};
69
+ if (!formData.language) {
70
+ errors.language = 'Language is required';
71
+ }
72
+ return {
73
+ valid: Object.keys(errors).length === 0,
74
+ errors
75
+ };
8
76
  }
9
77
  };
10
78
  //# sourceMappingURL=set_contact_language.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"set_contact_language.js","sourceRoot":"","sources":["../../../../src/flow/actions/set_contact_language.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,MAAM,EAAE,MAAM,UAAU,CAAC;AAGhD,MAAM,CAAC,MAAM,oBAAoB,GAAiB;IAChD,IAAI,EAAE,gBAAgB;IACtB,KAAK,EAAE,MAAM,CAAC,MAAM;IACpB,MAAM,EAAE,CAAC,KAAW,EAAE,MAA0B,EAAE,EAAE;QAClD,OAAO,IAAI,CAAA,mCAAmC,MAAM,CAAC,QAAQ,YAAY,CAAC;IAC5E,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, COLORS } from '../types';\nimport { Node, SetContactLanguage } from '../../store/flow-definition';\n\nexport const set_contact_language: ActionConfig = {\n name: 'Update Contact',\n color: COLORS.update,\n render: (_node: Node, action: SetContactLanguage) => {\n return html`<div>Set contact language to <b>${action.language}</b></div>`;\n }\n};\n"]}
1
+ {"version":3,"file":"set_contact_language.js","sourceRoot":"","sources":["../../../../src/flow/actions/set_contact_language.ts"],"names":[],"mappings":"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","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, COLORS, ValidationResult } from '../types';\nimport { Node, SetContactLanguage } from '../../store/flow-definition';\nimport { getStore } from '../../store/Store';\n\nexport const set_contact_language: ActionConfig = {\n name: 'Update Language',\n color: COLORS.update,\n render: (_node: Node, action: SetContactLanguage) => {\n const languageNames = new Intl.DisplayNames(['en'], {\n type: 'language'\n });\n return html`<div>Set to <b>${languageNames.of(action.language)}</b></div>`;\n },\n form: {\n language: {\n type: 'select',\n label: 'Language',\n required: true,\n searchable: true,\n clearable: false,\n valueKey: 'value',\n nameKey: 'name',\n helpText: 'Select the language to set for the contact',\n getDynamicOptions: () => {\n const store = getStore();\n const workspace = store?.getState().workspace;\n if (workspace?.languages && Array.isArray(workspace.languages)) {\n const languageNames = new Intl.DisplayNames(['en'], {\n type: 'language'\n });\n return workspace.languages.map((languageCode: string) => ({\n value: languageCode,\n name: languageNames.of(languageCode) || languageCode\n }));\n }\n return [];\n }\n }\n },\n toFormData: (action: SetContactLanguage) => {\n // Convert the language code back to the option object format expected by the form\n if (action.language) {\n const languageNames = new Intl.DisplayNames(['en'], {\n type: 'language'\n });\n return {\n language: [\n {\n value: action.language,\n name: languageNames.of(action.language) || action.language\n }\n ],\n uuid: action.uuid\n };\n }\n return {\n language: null,\n uuid: action.uuid\n };\n },\n fromFormData: (formData: any): SetContactLanguage => {\n return {\n uuid: formData.uuid,\n type: 'set_contact_language',\n language: formData.language[0].value\n };\n },\n\n validate: (formData: any): ValidationResult => {\n const errors: { [key: string]: string } = {};\n\n if (!formData.language) {\n errors.language = 'Language is required';\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n }\n};\n"]}
@@ -1,10 +1,35 @@
1
1
  import { html } from 'lit-html';
2
2
  import { COLORS } from '../types';
3
3
  export const set_contact_name = {
4
- name: 'Update Contact',
4
+ name: 'Update Name',
5
5
  color: COLORS.update,
6
6
  render: (_node, action) => {
7
- return html `<div>Set contact name to <b>${action.name}</b></div>`;
7
+ return html `<div>Set to <b>${action.name}</b></div>`;
8
+ },
9
+ form: {
10
+ name: {
11
+ type: 'text',
12
+ label: 'Name',
13
+ placeholder: 'Enter contact name...',
14
+ required: true,
15
+ evaluated: true,
16
+ helpText: 'The new name for the contact. You can use expressions like @contact.name'
17
+ }
18
+ },
19
+ validate: (formData) => {
20
+ const errors = {};
21
+ if (!formData.name || formData.name.trim() === '') {
22
+ errors.name = 'Name is required';
23
+ }
24
+ return {
25
+ valid: Object.keys(errors).length === 0,
26
+ errors
27
+ };
28
+ },
29
+ sanitize: (formData) => {
30
+ if (formData.name && typeof formData.name === 'string') {
31
+ formData.name = formData.name.trim();
32
+ }
8
33
  }
9
34
  };
10
35
  //# sourceMappingURL=set_contact_name.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"set_contact_name.js","sourceRoot":"","sources":["../../../../src/flow/actions/set_contact_name.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,MAAM,EAAE,MAAM,UAAU,CAAC;AAGhD,MAAM,CAAC,MAAM,gBAAgB,GAAiB;IAC5C,IAAI,EAAE,gBAAgB;IACtB,KAAK,EAAE,MAAM,CAAC,MAAM;IACpB,MAAM,EAAE,CAAC,KAAW,EAAE,MAAsB,EAAE,EAAE;QAC9C,OAAO,IAAI,CAAA,+BAA+B,MAAM,CAAC,IAAI,YAAY,CAAC;IACpE,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, COLORS } from '../types';\nimport { Node, SetContactName } from '../../store/flow-definition';\n\nexport const set_contact_name: ActionConfig = {\n name: 'Update Contact',\n color: COLORS.update,\n render: (_node: Node, action: SetContactName) => {\n return html`<div>Set contact name to <b>${action.name}</b></div>`;\n }\n};\n"]}
1
+ {"version":3,"file":"set_contact_name.js","sourceRoot":"","sources":["../../../../src/flow/actions/set_contact_name.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,MAAM,EAAoB,MAAM,UAAU,CAAC;AAGlE,MAAM,CAAC,MAAM,gBAAgB,GAAiB;IAC5C,IAAI,EAAE,aAAa;IACnB,KAAK,EAAE,MAAM,CAAC,MAAM;IACpB,MAAM,EAAE,CAAC,KAAW,EAAE,MAAsB,EAAE,EAAE;QAC9C,OAAO,IAAI,CAAA,kBAAkB,MAAM,CAAC,IAAI,YAAY,CAAC;IACvD,CAAC;IACD,IAAI,EAAE;QACJ,IAAI,EAAE;YACJ,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,MAAM;YACb,WAAW,EAAE,uBAAuB;YACpC,QAAQ,EAAE,IAAI;YACd,SAAS,EAAE,IAAI;YACf,QAAQ,EACN,0EAA0E;SAC7E;KACF;IACD,QAAQ,EAAE,CAAC,QAAwB,EAAoB,EAAE;QACvD,MAAM,MAAM,GAA8B,EAAE,CAAC;QAE7C,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAClD,MAAM,CAAC,IAAI,GAAG,kBAAkB,CAAC;QACnC,CAAC;QAED,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC;YACvC,MAAM;SACP,CAAC;IACJ,CAAC;IACD,QAAQ,EAAE,CAAC,QAAwB,EAAQ,EAAE;QAC3C,IAAI,QAAQ,CAAC,IAAI,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,QAAQ,CAAC,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACvC,CAAC;IACH,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, COLORS, ValidationResult } from '../types';\nimport { Node, SetContactName } from '../../store/flow-definition';\n\nexport const set_contact_name: ActionConfig = {\n name: 'Update Name',\n color: COLORS.update,\n render: (_node: Node, action: SetContactName) => {\n return html`<div>Set to <b>${action.name}</b></div>`;\n },\n form: {\n name: {\n type: 'text',\n label: 'Name',\n placeholder: 'Enter contact name...',\n required: true,\n evaluated: true,\n helpText:\n 'The new name for the contact. You can use expressions like @contact.name'\n }\n },\n validate: (formData: SetContactName): ValidationResult => {\n const errors: { [key: string]: string } = {};\n\n if (!formData.name || formData.name.trim() === '') {\n errors.name = 'Name is required';\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n sanitize: (formData: SetContactName): void => {\n if (formData.name && typeof formData.name === 'string') {\n formData.name = formData.name.trim();\n }\n }\n};\n"]}
@@ -1,10 +1,40 @@
1
1
  import { html } from 'lit-html';
2
2
  import { COLORS } from '../types';
3
+ import { titleCase } from '../../utils';
3
4
  export const set_contact_status = {
4
- name: 'Update Contact',
5
+ name: 'Update Status',
5
6
  color: COLORS.update,
6
7
  render: (_node, action) => {
7
- return html `<div>Set contact status to <b>${action.status}</b></div>`;
8
+ return html `<div>Set to <b>${titleCase(action.status)}</b></div>`;
9
+ },
10
+ form: {
11
+ status: {
12
+ type: 'select',
13
+ label: 'Status',
14
+ required: true,
15
+ searchable: false,
16
+ clearable: false,
17
+ options: [
18
+ { value: 'active', name: 'Active' },
19
+ { value: 'archived', name: 'Archived' },
20
+ { value: 'stopped', name: 'Stopped' },
21
+ { value: 'blocked', name: 'Blocked' }
22
+ ],
23
+ helpText: 'Select the status to set for the contact'
24
+ }
25
+ },
26
+ validate: (formData) => {
27
+ const errors = {};
28
+ if (!formData.status) {
29
+ errors.status = 'Status is required';
30
+ }
31
+ else if (!['active', 'archived', 'stopped', 'blocked'].includes(formData.status)) {
32
+ errors.status = 'Invalid status selected';
33
+ }
34
+ return {
35
+ valid: Object.keys(errors).length === 0,
36
+ errors
37
+ };
8
38
  }
9
39
  };
10
40
  //# sourceMappingURL=set_contact_status.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"set_contact_status.js","sourceRoot":"","sources":["../../../../src/flow/actions/set_contact_status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,MAAM,EAAE,MAAM,UAAU,CAAC;AAGhD,MAAM,CAAC,MAAM,kBAAkB,GAAiB;IAC9C,IAAI,EAAE,gBAAgB;IACtB,KAAK,EAAE,MAAM,CAAC,MAAM;IACpB,MAAM,EAAE,CAAC,KAAW,EAAE,MAAwB,EAAE,EAAE;QAChD,OAAO,IAAI,CAAA,iCAAiC,MAAM,CAAC,MAAM,YAAY,CAAC;IACxE,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, COLORS } from '../types';\nimport { Node, SetContactStatus } from '../../store/flow-definition';\n\nexport const set_contact_status: ActionConfig = {\n name: 'Update Contact',\n color: COLORS.update,\n render: (_node: Node, action: SetContactStatus) => {\n return html`<div>Set contact status to <b>${action.status}</b></div>`;\n }\n};\n"]}
1
+ {"version":3,"file":"set_contact_status.js","sourceRoot":"","sources":["../../../../src/flow/actions/set_contact_status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,MAAM,EAAoB,MAAM,UAAU,CAAC;AAElE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,MAAM,CAAC,MAAM,kBAAkB,GAAiB;IAC9C,IAAI,EAAE,eAAe;IACrB,KAAK,EAAE,MAAM,CAAC,MAAM;IACpB,MAAM,EAAE,CAAC,KAAW,EAAE,MAAwB,EAAE,EAAE;QAChD,OAAO,IAAI,CAAA,kBAAkB,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;IACpE,CAAC;IACD,IAAI,EAAE;QACJ,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,QAAQ;YACf,QAAQ,EAAE,IAAI;YACd,UAAU,EAAE,KAAK;YACjB,SAAS,EAAE,KAAK;YAChB,OAAO,EAAE;gBACP,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACnC,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE;gBACvC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE;gBACrC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE;aACtC;YACD,QAAQ,EAAE,0CAA0C;SACrD;KACF;IACD,QAAQ,EAAE,CAAC,QAA0B,EAAoB,EAAE;QACzD,MAAM,MAAM,GAA8B,EAAE,CAAC;QAE7C,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YACrB,MAAM,CAAC,MAAM,GAAG,oBAAoB,CAAC;QACvC,CAAC;aAAM,IACL,CAAC,CAAC,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EACvE,CAAC;YACD,MAAM,CAAC,MAAM,GAAG,yBAAyB,CAAC;QAC5C,CAAC;QAED,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC;YACvC,MAAM;SACP,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, COLORS, ValidationResult } from '../types';\nimport { Node, SetContactStatus } from '../../store/flow-definition';\nimport { titleCase } from '../../utils';\n\nexport const set_contact_status: ActionConfig = {\n name: 'Update Status',\n color: COLORS.update,\n render: (_node: Node, action: SetContactStatus) => {\n return html`<div>Set to <b>${titleCase(action.status)}</b></div>`;\n },\n form: {\n status: {\n type: 'select',\n label: 'Status',\n required: true,\n searchable: false,\n clearable: false,\n options: [\n { value: 'active', name: 'Active' },\n { value: 'archived', name: 'Archived' },\n { value: 'stopped', name: 'Stopped' },\n { value: 'blocked', name: 'Blocked' }\n ],\n helpText: 'Select the status to set for the contact'\n }\n },\n validate: (formData: SetContactStatus): ValidationResult => {\n const errors: { [key: string]: string } = {};\n\n if (!formData.status) {\n errors.status = 'Status is required';\n } else if (\n !['active', 'archived', 'stopped', 'blocked'].includes(formData.status)\n ) {\n errors.status = 'Invalid status selected';\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n }\n};\n"]}
@@ -5,7 +5,9 @@ export const set_run_result = {
5
5
  name: 'Save Flow Result',
6
6
  color: COLORS.save,
7
7
  render: (_node, action) => {
8
- return html `<div>Save ${action.value} as <b>${action.name}</b></div>`;
8
+ return html `<div>
9
+ Save <b>${action.value}</b> as <b>${action.name}</b>
10
+ </div>`;
9
11
  },
10
12
  form: {
11
13
  name: {
@@ -23,7 +25,15 @@ export const set_run_result = {
23
25
  },
24
26
  searchable: true,
25
27
  clearable: false,
26
- options: []
28
+ getDynamicOptions: () => {
29
+ const store = getStore();
30
+ return store
31
+ ? store
32
+ .getState()
33
+ .getFlowResults()
34
+ .map((r) => ({ value: r.name, name: r.name }))
35
+ : [];
36
+ }
27
37
  },
28
38
  value: {
29
39
  type: 'text',
@@ -43,17 +53,9 @@ export const set_run_result = {
43
53
  },
44
54
  layout: ['name', 'value', 'category'],
45
55
  toFormData: (action) => {
46
- // Get existing flow results to populate the select options
47
- const store = getStore();
48
- const flowResults = store ? store.getState().getFlowResults() : [];
49
- // Update the form configuration with dynamic options
50
- const config = set_run_result;
51
- if (config.form && config.form.name && config.form.name.type === 'select') {
52
- config.form.name.options = flowResults.map((result) => result.name);
53
- }
54
56
  return {
55
57
  uuid: action.uuid,
56
- name: action.name || '',
58
+ name: action.name ? [{ name: action.name, value: action.name }] : [],
57
59
  value: action.value || '',
58
60
  category: action.category || ''
59
61
  };
@@ -1 +1 @@
1
- {"version":3,"file":"set_run_result.js","sourceRoot":"","sources":["../../../../src/flow/actions/set_run_result.ts"],"names":[],"mappings":"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","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, COLORS } from '../types';\nimport { Node, SetRunResult } from '../../store/flow-definition';\nimport { getStore } from '../../store/Store';\n\nexport const set_run_result: ActionConfig = {\n name: 'Save Flow Result',\n color: COLORS.save,\n render: (_node: Node, action: SetRunResult) => {\n return html`<div>Save ${action.value} as <b>${action.name}</b></div>`;\n },\n form: {\n name: {\n type: 'select',\n label: 'Result Name',\n helpText: 'Select an existing result name or type a new one',\n required: true,\n placeholder: 'Select or enter result name...',\n createArbitraryOption: (input, options) => {\n const exists = options.some(\n (option: any) =>\n option.value.toLowerCase() === input.toLowerCase() ||\n option.name.toLowerCase() === input.toLowerCase()\n );\n return !exists && input.trim().length > 0\n ? { value: input, name: input }\n : null;\n },\n searchable: true,\n clearable: false,\n options: []\n },\n value: {\n type: 'text',\n label: 'Value',\n helpText: 'The value to save for this result (can use expressions)',\n required: false,\n evaluated: true,\n placeholder: 'Enter value...'\n },\n category: {\n type: 'text',\n label: 'Category',\n helpText: 'Optional category for this result',\n required: false,\n placeholder: 'Enter category...'\n }\n },\n layout: ['name', 'value', 'category'],\n toFormData: (action: SetRunResult) => {\n // Get existing flow results to populate the select options\n const store = getStore();\n const flowResults = store ? store.getState().getFlowResults() : [];\n\n // Update the form configuration with dynamic options\n const config = set_run_result;\n if (config.form && config.form.name && config.form.name.type === 'select') {\n (config.form.name as any).options = flowResults.map(\n (result) => result.name\n );\n }\n\n return {\n uuid: action.uuid,\n name: action.name || '',\n value: action.value || '',\n category: action.category || ''\n };\n },\n fromFormData: (formData: any): SetRunResult => {\n // Ensure name is a simple string, handling both direct values and select option objects\n let name = formData.name || '';\n if (Array.isArray(name) && name.length > 0) {\n // If it's an array (from multi-select), take the first item\n name = name[0];\n }\n if (typeof name === 'object' && name.value) {\n // If it's an option object, extract the value\n name = name.value;\n }\n if (typeof name === 'object' && name.name) {\n // If it's an option object with name property, extract it\n name = name.name;\n }\n\n return {\n uuid: formData.uuid,\n type: 'set_run_result',\n name: String(name), // Ensure it's always a string\n value: formData.value || '',\n category: formData.category || ''\n };\n }\n};\n"]}
1
+ {"version":3,"file":"set_run_result.js","sourceRoot":"","sources":["../../../../src/flow/actions/set_run_result.ts"],"names":[],"mappings":"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","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, COLORS } from '../types';\nimport { Node, SetRunResult } from '../../store/flow-definition';\nimport { getStore } from '../../store/Store';\n\nexport const set_run_result: ActionConfig = {\n name: 'Save Flow Result',\n color: COLORS.save,\n render: (_node: Node, action: SetRunResult) => {\n return html`<div>\n Save <b>${action.value}</b> as <b>${action.name}</b>\n </div>`;\n },\n form: {\n name: {\n type: 'select',\n label: 'Result Name',\n helpText: 'Select an existing result name or type a new one',\n required: true,\n placeholder: 'Select or enter result name...',\n createArbitraryOption: (input, options) => {\n const exists = options.some(\n (option: any) =>\n option.value.toLowerCase() === input.toLowerCase() ||\n option.name.toLowerCase() === input.toLowerCase()\n );\n return !exists && input.trim().length > 0\n ? { value: input, name: input }\n : null;\n },\n searchable: true,\n clearable: false,\n getDynamicOptions: () => {\n const store = getStore();\n return store\n ? store\n .getState()\n .getFlowResults()\n .map((r) => ({ value: r.name, name: r.name }))\n : [];\n }\n },\n value: {\n type: 'text',\n label: 'Value',\n helpText: 'The value to save for this result (can use expressions)',\n required: false,\n evaluated: true,\n placeholder: 'Enter value...'\n },\n category: {\n type: 'text',\n label: 'Category',\n helpText: 'Optional category for this result',\n required: false,\n placeholder: 'Enter category...'\n }\n },\n layout: ['name', 'value', 'category'],\n toFormData: (action: SetRunResult) => {\n return {\n uuid: action.uuid,\n name: action.name ? [{ name: action.name, value: action.name }] : [],\n value: action.value || '',\n category: action.category || ''\n };\n },\n fromFormData: (formData: any): SetRunResult => {\n // Ensure name is a simple string, handling both direct values and select option objects\n let name = formData.name || '';\n if (Array.isArray(name) && name.length > 0) {\n // If it's an array (from multi-select), take the first item\n name = name[0];\n }\n if (typeof name === 'object' && name.value) {\n // If it's an option object, extract the value\n name = name.value;\n }\n if (typeof name === 'object' && name.name) {\n // If it's an option object with name property, extract it\n name = name.name;\n }\n\n return {\n uuid: formData.uuid,\n type: 'set_run_result',\n name: String(name), // Ensure it's always a string\n value: formData.value || '',\n category: formData.category || ''\n };\n }\n};\n"]}
@@ -34,10 +34,10 @@ export const split_by_expression = {
34
34
  label: 'Operator',
35
35
  required: true,
36
36
  options: [
37
- { value: 'contains', label: 'contains' },
38
- { value: 'equals', label: 'equals' },
39
- { value: 'starts_with', label: 'starts with' },
40
- { value: 'regex', label: 'regex' }
37
+ { value: 'contains', name: 'contains' },
38
+ { value: 'equals', name: 'equals' },
39
+ { value: 'starts_with', name: 'starts with' },
40
+ { value: 'regex', name: 'regex' }
41
41
  ]
42
42
  },
43
43
  operand: {
@@ -1 +1 @@
1
- {"version":3,"file":"split_by_expression_example.js","sourceRoot":"","sources":["../../../../src/flow/actions/split_by_expression_example.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,MAAM,EAAE,MAAM,UAAU,CAAC;AAEhD,qDAAqD;AACrD,MAAM,2BAA2B,GAAG,CAAC,OAAe,EAAU,EAAE;IAC9D,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IAExB,0DAA0D;IAC1D,OAAO,OAAO;SACX,WAAW,EAAE;SACb,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,uBAAuB;SACnD,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,kCAAkC;SACvD,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe;AAClC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAiB;IAC/C,IAAI,EAAE,qBAAqB;IAC3B,KAAK,EAAE,MAAM,CAAC,KAAK;IACnB,IAAI,EAAE;QACJ,OAAO,EAAE;YACP,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,UAAU;YACjB,QAAQ,EAAE,IAAI;YACd,SAAS,EAAE,IAAI;YACf,WAAW,EAAE,8BAA8B;SAC5C;QACD,KAAK,EAAE;YACL,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,OAAO;YACd,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,CAAC;YACX,SAAS,EAAE,MAAM;YACjB,UAAU,EAAE;gBACV,QAAQ,EAAE;oBACR,IAAI,EAAE,QAAQ;oBACd,KAAK,EAAE,UAAU;oBACjB,QAAQ,EAAE,IAAI;oBACd,OAAO,EAAE;wBACP,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE;wBACxC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;wBACpC,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,EAAE;wBAC9C,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;qBACnC;iBACF;gBACD,OAAO,EAAE;oBACP,IAAI,EAAE,MAAM;oBACZ,KAAK,EAAE,OAAO;oBACd,QAAQ,EAAE,IAAI;oBACd,SAAS,EAAE,IAAI;oBACf,WAAW,EAAE,0BAA0B;iBACxC;gBACD,QAAQ,EAAE;oBACR,IAAI,EAAE,MAAM;oBACZ,KAAK,EAAE,UAAU;oBACjB,QAAQ,EAAE,IAAI;oBACd,WAAW,EAAE,6BAA6B;iBAC3C;aACF;YACD,mCAAmC;YACnC,YAAY,EAAE,CACZ,SAAiB,EACjB,KAAa,EACb,KAAU,EACV,QAAe,EACf,EAAE;gBACF,MAAM,YAAY,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC;gBACnC,MAAM,IAAI,GAAG,EAAE,GAAG,YAAY,CAAC,SAAS,CAAC,EAAE,CAAC;gBAE5C,2BAA2B;gBAC3B,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;gBAEpB,mEAAmE;gBACnE,IACE,KAAK,KAAK,SAAS;oBACnB,CAAC,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,EAC/C,CAAC;oBACD,IAAI,CAAC,QAAQ,GAAG,2BAA2B,CAAC,KAAK,CAAC,CAAC;gBACrD,CAAC;gBAED,YAAY,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;gBAC/B,OAAO,YAAY,CAAC;YACtB,CAAC;SACF;KACF;IACD,MAAM,EAAE,CAAC,KAAU,EAAE,MAAW,EAAE,EAAE;QAClC,OAAO,IAAI,CAAA,QAAQ,MAAM,CAAC,OAAO,IAAI,qBAAqB,QAAQ,CAAC;IACrE,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, COLORS } from '../types';\n\n// utility function to generate category from operand\nconst generateCategoryFromOperand = (operand: string): string => {\n if (!operand) return '';\n\n // clean up the operand to make a reasonable category name\n return operand\n .toLowerCase()\n .replace(/[^a-z0-9\\s]/g, '') // remove special chars\n .replace(/\\s+/g, '_') // replace spaces with underscores\n .slice(0, 20); // limit length\n};\n\nexport const split_by_expression: ActionConfig = {\n name: 'Split by Expression',\n color: COLORS.split,\n form: {\n operand: {\n type: 'text',\n label: 'Split by',\n required: true,\n evaluated: true,\n placeholder: 'Enter expression to evaluate'\n },\n rules: {\n type: 'array',\n label: 'Rules',\n sortable: true,\n minItems: 1,\n itemLabel: 'Rule',\n itemConfig: {\n operator: {\n type: 'select',\n label: 'Operator',\n required: true,\n options: [\n { value: 'contains', label: 'contains' },\n { value: 'equals', label: 'equals' },\n { value: 'starts_with', label: 'starts with' },\n { value: 'regex', label: 'regex' }\n ]\n },\n operand: {\n type: 'text',\n label: 'Value',\n required: true,\n evaluated: true,\n placeholder: 'Value to compare against'\n },\n category: {\n type: 'text',\n label: 'Category',\n required: true,\n placeholder: 'Category name for this rule'\n }\n },\n // handle changes at the item level\n onItemChange: (\n itemIndex: number,\n field: string,\n value: any,\n allItems: any[]\n ) => {\n const updatedItems = [...allItems];\n const item = { ...updatedItems[itemIndex] };\n\n // update the changed field\n item[field] = value;\n\n // if operand changed and category is empty, auto-generate category\n if (\n field === 'operand' &&\n (!item.category || item.category.trim() === '')\n ) {\n item.category = generateCategoryFromOperand(value);\n }\n\n updatedItems[itemIndex] = item;\n return updatedItems;\n }\n }\n },\n render: (_node: any, action: any) => {\n return html`<div>${action.operand || 'Split by expression'}</div>`;\n }\n};\n"]}
1
+ {"version":3,"file":"split_by_expression_example.js","sourceRoot":"","sources":["../../../../src/flow/actions/split_by_expression_example.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAgB,MAAM,EAAE,MAAM,UAAU,CAAC;AAEhD,qDAAqD;AACrD,MAAM,2BAA2B,GAAG,CAAC,OAAe,EAAU,EAAE;IAC9D,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IAExB,0DAA0D;IAC1D,OAAO,OAAO;SACX,WAAW,EAAE;SACb,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,uBAAuB;SACnD,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,kCAAkC;SACvD,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe;AAClC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAiB;IAC/C,IAAI,EAAE,qBAAqB;IAC3B,KAAK,EAAE,MAAM,CAAC,KAAK;IACnB,IAAI,EAAE;QACJ,OAAO,EAAE;YACP,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,UAAU;YACjB,QAAQ,EAAE,IAAI;YACd,SAAS,EAAE,IAAI;YACf,WAAW,EAAE,8BAA8B;SAC5C;QACD,KAAK,EAAE;YACL,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,OAAO;YACd,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,CAAC;YACX,SAAS,EAAE,MAAM;YACjB,UAAU,EAAE;gBACV,QAAQ,EAAE;oBACR,IAAI,EAAE,QAAQ;oBACd,KAAK,EAAE,UAAU;oBACjB,QAAQ,EAAE,IAAI;oBACd,OAAO,EAAE;wBACP,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE;wBACvC,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE;wBACnC,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,aAAa,EAAE;wBAC7C,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE;qBAClC;iBACF;gBACD,OAAO,EAAE;oBACP,IAAI,EAAE,MAAM;oBACZ,KAAK,EAAE,OAAO;oBACd,QAAQ,EAAE,IAAI;oBACd,SAAS,EAAE,IAAI;oBACf,WAAW,EAAE,0BAA0B;iBACxC;gBACD,QAAQ,EAAE;oBACR,IAAI,EAAE,MAAM;oBACZ,KAAK,EAAE,UAAU;oBACjB,QAAQ,EAAE,IAAI;oBACd,WAAW,EAAE,6BAA6B;iBAC3C;aACF;YACD,mCAAmC;YACnC,YAAY,EAAE,CACZ,SAAiB,EACjB,KAAa,EACb,KAAU,EACV,QAAe,EACf,EAAE;gBACF,MAAM,YAAY,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC;gBACnC,MAAM,IAAI,GAAG,EAAE,GAAG,YAAY,CAAC,SAAS,CAAC,EAAE,CAAC;gBAE5C,2BAA2B;gBAC3B,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;gBAEpB,mEAAmE;gBACnE,IACE,KAAK,KAAK,SAAS;oBACnB,CAAC,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,EAC/C,CAAC;oBACD,IAAI,CAAC,QAAQ,GAAG,2BAA2B,CAAC,KAAK,CAAC,CAAC;gBACrD,CAAC;gBAED,YAAY,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;gBAC/B,OAAO,YAAY,CAAC;YACtB,CAAC;SACF;KACF;IACD,MAAM,EAAE,CAAC,KAAU,EAAE,MAAW,EAAE,EAAE;QAClC,OAAO,IAAI,CAAA,QAAQ,MAAM,CAAC,OAAO,IAAI,qBAAqB,QAAQ,CAAC;IACrE,CAAC;CACF,CAAC","sourcesContent":["import { html } from 'lit-html';\nimport { ActionConfig, COLORS } from '../types';\n\n// utility function to generate category from operand\nconst generateCategoryFromOperand = (operand: string): string => {\n if (!operand) return '';\n\n // clean up the operand to make a reasonable category name\n return operand\n .toLowerCase()\n .replace(/[^a-z0-9\\s]/g, '') // remove special chars\n .replace(/\\s+/g, '_') // replace spaces with underscores\n .slice(0, 20); // limit length\n};\n\nexport const split_by_expression: ActionConfig = {\n name: 'Split by Expression',\n color: COLORS.split,\n form: {\n operand: {\n type: 'text',\n label: 'Split by',\n required: true,\n evaluated: true,\n placeholder: 'Enter expression to evaluate'\n },\n rules: {\n type: 'array',\n label: 'Rules',\n sortable: true,\n minItems: 1,\n itemLabel: 'Rule',\n itemConfig: {\n operator: {\n type: 'select',\n label: 'Operator',\n required: true,\n options: [\n { value: 'contains', name: 'contains' },\n { value: 'equals', name: 'equals' },\n { value: 'starts_with', name: 'starts with' },\n { value: 'regex', name: 'regex' }\n ]\n },\n operand: {\n type: 'text',\n label: 'Value',\n required: true,\n evaluated: true,\n placeholder: 'Value to compare against'\n },\n category: {\n type: 'text',\n label: 'Category',\n required: true,\n placeholder: 'Category name for this rule'\n }\n },\n // handle changes at the item level\n onItemChange: (\n itemIndex: number,\n field: string,\n value: any,\n allItems: any[]\n ) => {\n const updatedItems = [...allItems];\n const item = { ...updatedItems[itemIndex] };\n\n // update the changed field\n item[field] = value;\n\n // if operand changed and category is empty, auto-generate category\n if (\n field === 'operand' &&\n (!item.category || item.category.trim() === '')\n ) {\n item.category = generateCategoryFromOperand(value);\n }\n\n updatedItems[itemIndex] = item;\n return updatedItems;\n }\n }\n },\n render: (_node: any, action: any) => {\n return html`<div>${action.operand || 'Split by expression'}</div>`;\n }\n};\n"]}
@@ -0,0 +1,2 @@
1
+ // No unified contact form exports - each action has its own form configuration
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/flow/forms/index.ts"],"names":[],"mappings":"AAAA,+EAA+E","sourcesContent":["// No unified contact form exports - each action has its own form configuration\n"]}