@nyaruka/temba-components 0.129.7 → 0.129.9
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/.devcontainer/Dockerfile +11 -4
- package/.devcontainer/devcontainer.json +3 -2
- package/.github/workflows/build.yml +4 -14
- package/CHANGELOG.md +29 -0
- package/demo/components/flow/example.html +1 -1
- package/demo/components/message-editor/example.html +125 -0
- package/demo/components/textinput/completion.html +1 -0
- package/demo/data/flows/food-order.json +12 -21
- package/demo/data/flows/sample-flow.json +210 -104
- package/dist/temba-components.js +715 -364
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/display/Thumbnail.js +2 -1
- package/out-tsc/src/display/Thumbnail.js.map +1 -1
- package/out-tsc/src/events.js.map +1 -1
- package/out-tsc/src/excellent/helpers.js +2 -2
- package/out-tsc/src/excellent/helpers.js.map +1 -1
- package/out-tsc/src/flow/CanvasNode.js +25 -7
- package/out-tsc/src/flow/CanvasNode.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +11 -1
- package/out-tsc/src/flow/Editor.js.map +1 -1
- package/out-tsc/src/flow/NodeEditor.js +342 -276
- package/out-tsc/src/flow/NodeEditor.js.map +1 -1
- package/out-tsc/src/flow/actions/add_input_labels.js +40 -0
- package/out-tsc/src/flow/actions/add_input_labels.js.map +1 -1
- package/out-tsc/src/flow/actions/call_llm.js +56 -3
- package/out-tsc/src/flow/actions/call_llm.js.map +1 -1
- package/out-tsc/src/flow/actions/call_webhook.js +26 -17
- package/out-tsc/src/flow/actions/call_webhook.js.map +1 -1
- package/out-tsc/src/flow/actions/open_ticket.js +65 -3
- package/out-tsc/src/flow/actions/open_ticket.js.map +1 -1
- package/out-tsc/src/flow/actions/send_msg.js +147 -6
- package/out-tsc/src/flow/actions/send_msg.js.map +1 -1
- package/out-tsc/src/flow/actions/set_run_result.js +75 -0
- package/out-tsc/src/flow/actions/set_run_result.js.map +1 -1
- package/out-tsc/src/flow/config.js +4 -0
- package/out-tsc/src/flow/config.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_llm_categorize.js +227 -0
- package/out-tsc/src/flow/nodes/split_by_llm_categorize.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_ticket.js +18 -0
- package/out-tsc/src/flow/nodes/split_by_ticket.js.map +1 -0
- package/out-tsc/src/flow/nodes/wait_for_response.js +27 -1
- package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -1
- package/out-tsc/src/flow/types.js +0 -65
- package/out-tsc/src/flow/types.js.map +1 -1
- package/out-tsc/src/form/ArrayEditor.js +87 -57
- package/out-tsc/src/form/ArrayEditor.js.map +1 -1
- package/out-tsc/src/form/BaseListEditor.js +19 -4
- package/out-tsc/src/form/BaseListEditor.js.map +1 -1
- package/out-tsc/src/form/FieldRenderer.js +305 -0
- package/out-tsc/src/form/FieldRenderer.js.map +1 -0
- package/out-tsc/src/form/FormField.js +4 -4
- package/out-tsc/src/form/FormField.js.map +1 -1
- package/out-tsc/src/form/KeyValueEditor.js +1 -1
- package/out-tsc/src/form/KeyValueEditor.js.map +1 -1
- package/out-tsc/src/form/MediaPicker.js +13 -1
- package/out-tsc/src/form/MediaPicker.js.map +1 -1
- package/out-tsc/src/form/MessageEditor.js +422 -0
- package/out-tsc/src/form/MessageEditor.js.map +1 -0
- package/out-tsc/src/form/TextInput.js +13 -6
- package/out-tsc/src/form/TextInput.js.map +1 -1
- package/out-tsc/src/form/select/Select.js +52 -24
- package/out-tsc/src/form/select/Select.js.map +1 -1
- package/out-tsc/src/live/ContactChat.js +66 -15
- package/out-tsc/src/live/ContactChat.js.map +1 -1
- package/out-tsc/src/markdown.js +13 -11
- package/out-tsc/src/markdown.js.map +1 -1
- package/out-tsc/temba-modules.js +2 -0
- package/out-tsc/temba-modules.js.map +1 -1
- package/out-tsc/test/ActionHelper.js +2 -0
- package/out-tsc/test/ActionHelper.js.map +1 -1
- package/out-tsc/test/NodeHelper.js +148 -0
- package/out-tsc/test/NodeHelper.js.map +1 -0
- package/out-tsc/test/actions/call_llm.test.js +103 -0
- package/out-tsc/test/actions/call_llm.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_llm_categorize.test.js +532 -0
- package/out-tsc/test/nodes/split_by_llm_categorize.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_random.test.js +150 -0
- package/out-tsc/test/nodes/split_by_random.test.js.map +1 -0
- package/out-tsc/test/nodes/wait_for_digits.test.js +150 -0
- package/out-tsc/test/nodes/wait_for_digits.test.js.map +1 -0
- package/out-tsc/test/nodes/wait_for_response.test.js +171 -0
- package/out-tsc/test/nodes/wait_for_response.test.js.map +1 -0
- package/out-tsc/test/temba-add-input-labels.test.js +70 -0
- package/out-tsc/test/temba-add-input-labels.test.js.map +1 -0
- package/out-tsc/test/temba-field-config.test.js +4 -2
- package/out-tsc/test/temba-field-config.test.js.map +1 -1
- package/out-tsc/test/temba-field-renderer.test.js +296 -0
- package/out-tsc/test/temba-field-renderer.test.js.map +1 -0
- package/out-tsc/test/temba-markdown.test.js +1 -1
- package/out-tsc/test/temba-markdown.test.js.map +1 -1
- package/out-tsc/test/temba-message-editor.test.js +194 -0
- package/out-tsc/test/temba-message-editor.test.js.map +1 -0
- package/out-tsc/test/temba-node-editor.test.js +471 -0
- package/out-tsc/test/temba-node-editor.test.js.map +1 -1
- package/out-tsc/test/temba-select.test.js +7 -4
- package/out-tsc/test/temba-select.test.js.map +1 -1
- package/out-tsc/test/temba-textinput.test.js +16 -0
- package/out-tsc/test/temba-textinput.test.js.map +1 -1
- package/out-tsc/test/temba-webchat.test.js +5 -1
- package/out-tsc/test/temba-webchat.test.js.map +1 -1
- package/out-tsc/test/utils.test.js +2 -8
- package/out-tsc/test/utils.test.js.map +1 -1
- package/package.json +7 -4
- 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/call_llm/editor/information-extraction.png +0 -0
- package/screenshots/truth/actions/call_llm/editor/sentiment-analysis.png +0 -0
- package/screenshots/truth/actions/call_llm/editor/summarization.png +0 -0
- package/screenshots/truth/actions/call_llm/editor/translation-task.png +0 -0
- package/screenshots/truth/actions/call_llm/render/information-extraction.png +0 -0
- package/screenshots/truth/actions/call_llm/render/sentiment-analysis.png +0 -0
- package/screenshots/truth/actions/call_llm/render/summarization.png +0 -0
- package/screenshots/truth/actions/call_llm/render/translation-task.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/cleanup-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/long-descriptive-group-names.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/many-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/multiple-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/remove-from-all-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/single-group.png +0 -0
- package/screenshots/truth/actions/send_email/editor/complex-business-email.png +0 -0
- package/screenshots/truth/actions/send_email/editor/empty-body.png +0 -0
- package/screenshots/truth/actions/send_email/editor/empty-subject.png +0 -0
- package/screenshots/truth/actions/send_email/editor/long-subject.png +0 -0
- package/screenshots/truth/actions/send_email/editor/multiline-body.png +0 -0
- package/screenshots/truth/actions/send_email/editor/multiple-recipients.png +0 -0
- package/screenshots/truth/actions/send_email/editor/simple-email.png +0 -0
- package/screenshots/truth/actions/send_email/editor/with-expressions.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/long-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/multiline-text-with-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/simple-text.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-with-linebreaks.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-with-many-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-with-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-without-quick-replies.png +0 -0
- package/screenshots/truth/editor/router.png +0 -0
- package/screenshots/truth/editor/send_msg.png +0 -0
- package/screenshots/truth/editor/set_contact_language.png +0 -0
- package/screenshots/truth/editor/set_contact_name.png +0 -0
- package/screenshots/truth/editor/set_run_result.png +0 -0
- package/screenshots/truth/editor/wait.png +0 -0
- package/screenshots/truth/field-renderer/checkbox-checked.png +0 -0
- package/screenshots/truth/field-renderer/checkbox-unchecked.png +0 -0
- package/screenshots/truth/field-renderer/checkbox-with-errors.png +0 -0
- package/screenshots/truth/field-renderer/context-comparison.png +0 -0
- package/screenshots/truth/field-renderer/key-value-with-label.png +0 -0
- package/screenshots/truth/field-renderer/message-editor-with-label.png +0 -0
- package/screenshots/truth/field-renderer/select-multi.png +0 -0
- package/screenshots/truth/field-renderer/select-no-label.png +0 -0
- package/screenshots/truth/field-renderer/select-with-label.png +0 -0
- package/screenshots/truth/field-renderer/text-evaluated.png +0 -0
- package/screenshots/truth/field-renderer/text-no-label.png +0 -0
- package/screenshots/truth/field-renderer/text-with-errors.png +0 -0
- package/screenshots/truth/field-renderer/text-with-label.png +0 -0
- package/screenshots/truth/field-renderer/textarea-evaluated.png +0 -0
- package/screenshots/truth/field-renderer/textarea-with-label.png +0 -0
- package/screenshots/truth/formfield/markdown-errors.png +0 -0
- package/screenshots/truth/formfield/no-errors.png +0 -0
- package/screenshots/truth/formfield/plain-text-errors.png +0 -0
- package/screenshots/truth/message-editor/autogrow-initial-content.png +0 -0
- package/screenshots/truth/message-editor/default.png +0 -0
- package/screenshots/truth/message-editor/drag-highlight.png +0 -0
- package/screenshots/truth/message-editor/filtered-attachments.png +0 -0
- package/screenshots/truth/message-editor/with-completion.png +0 -0
- package/screenshots/truth/message-editor/with-properties.png +0 -0
- package/screenshots/truth/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/omnibox/selected.png +0 -0
- package/screenshots/truth/select/functions.png +0 -0
- package/screenshots/truth/select/multi-with-endpoint.png +0 -0
- package/screenshots/truth/select/search-enabled.png +0 -0
- package/screenshots/truth/textinput/autogrow-initial.png +0 -0
- package/screenshots/truth/textinput/input-form.png +0 -0
- package/src/display/Thumbnail.ts +2 -1
- package/src/events.ts +13 -1
- package/src/excellent/helpers.ts +2 -2
- package/src/flow/CanvasNode.ts +22 -1
- package/src/flow/Editor.ts +12 -1
- package/src/flow/NodeEditor.ts +412 -354
- package/src/flow/actions/add_input_labels.ts +45 -0
- package/src/flow/actions/call_llm.ts +57 -3
- package/src/flow/actions/call_webhook.ts +28 -18
- package/src/flow/actions/open_ticket.ts +74 -3
- package/src/flow/actions/send_msg.ts +170 -6
- package/src/flow/actions/set_run_result.ts +83 -0
- package/src/flow/config.ts +4 -0
- package/src/flow/nodes/split_by_llm_categorize.ts +277 -0
- package/src/flow/nodes/split_by_ticket.ts +19 -0
- package/src/flow/nodes/wait_for_response.ts +28 -1
- package/src/flow/types.ts +46 -128
- package/src/form/ArrayEditor.ts +96 -66
- package/src/form/BaseListEditor.ts +22 -6
- package/src/form/FieldRenderer.ts +465 -0
- package/src/form/FormField.ts +4 -4
- package/src/form/KeyValueEditor.ts +1 -1
- package/src/form/MediaPicker.ts +13 -1
- package/src/form/MessageEditor.ts +449 -0
- package/src/form/TextInput.ts +16 -8
- package/src/form/select/Select.ts +55 -24
- package/src/live/ContactChat.ts +69 -19
- package/src/markdown.ts +19 -11
- package/src/store/flow-definition.d.ts +5 -2
- package/static/api/labels.json +31 -0
- package/static/api/topics.json +24 -9
- package/static/api/users.json +35 -16
- package/static/css/temba-components.css +5 -3
- package/static/mr/docs/en-us/editor.json +2588 -0
- package/stress-test.js +143 -0
- package/temba-modules.ts +2 -0
- package/test/ActionHelper.ts +2 -0
- package/test/NodeHelper.ts +184 -0
- package/test/actions/call_llm.test.ts +137 -0
- package/test/nodes/README.md +78 -0
- package/test/nodes/split_by_llm_categorize.test.ts +698 -0
- package/test/nodes/split_by_random.test.ts +177 -0
- package/test/nodes/wait_for_digits.test.ts +176 -0
- package/test/nodes/wait_for_response.test.ts +206 -0
- package/test/temba-add-input-labels.test.ts +87 -0
- package/test/temba-field-config.test.ts +4 -2
- package/test/temba-field-renderer.test.ts +482 -0
- package/test/temba-markdown.test.ts +1 -1
- package/test/temba-message-editor.test.ts +300 -0
- package/test/temba-node-editor.test.ts +590 -0
- package/test/temba-select.test.ts +7 -7
- package/test/temba-textinput.test.ts +26 -0
- package/test/temba-webchat.test.ts +6 -1
- package/test/utils.test.ts +2 -13
- package/test-assets/contacts/history.json +19 -0
- package/test-assets/select/llms.json +18 -0
- package/test-assets/style.css +2 -0
- package/web-dev-mock.mjs +523 -0
- package/web-dev-server.config.mjs +74 -6
- package/web-test-runner.config.mjs +9 -4
- package/test/temba-flow-editor.test.ts.backup +0 -563
- package/test/temba-utils-index.test.ts.backup +0 -1737
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { COLORS } from '../types';
|
|
2
|
+
import { generateUUID } from '../../utils';
|
|
3
|
+
import { html } from 'lit';
|
|
4
|
+
export const split_by_llm_categorize = {
|
|
5
|
+
type: 'split_by_llm_categorize',
|
|
6
|
+
name: 'Split by AI',
|
|
7
|
+
color: COLORS.call,
|
|
8
|
+
form: {
|
|
9
|
+
llm: {
|
|
10
|
+
type: 'select',
|
|
11
|
+
label: 'LLM',
|
|
12
|
+
helpText: 'Select the LLM to use for categorization',
|
|
13
|
+
required: true,
|
|
14
|
+
endpoint: '/test-assets/select/llms.json',
|
|
15
|
+
valueKey: 'uuid',
|
|
16
|
+
nameKey: 'name',
|
|
17
|
+
placeholder: 'Select an LLM...'
|
|
18
|
+
},
|
|
19
|
+
input: {
|
|
20
|
+
type: 'text',
|
|
21
|
+
label: 'Input',
|
|
22
|
+
helpText: 'The input to categorize (usually @input)',
|
|
23
|
+
required: true,
|
|
24
|
+
evaluated: true,
|
|
25
|
+
placeholder: '@input'
|
|
26
|
+
},
|
|
27
|
+
categories: {
|
|
28
|
+
type: 'array',
|
|
29
|
+
label: 'Categories',
|
|
30
|
+
helpText: 'Define the categories for classification',
|
|
31
|
+
required: true,
|
|
32
|
+
itemLabel: 'Category',
|
|
33
|
+
minItems: 1,
|
|
34
|
+
maxItems: 10,
|
|
35
|
+
isEmptyItem: (item) => {
|
|
36
|
+
return !item.name || item.name.trim() === '';
|
|
37
|
+
},
|
|
38
|
+
itemConfig: {
|
|
39
|
+
name: {
|
|
40
|
+
type: 'text',
|
|
41
|
+
placeholder: 'Category name',
|
|
42
|
+
required: true
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
layout: ['llm', 'input', 'categories'],
|
|
48
|
+
validate: (formData) => {
|
|
49
|
+
const errors = {};
|
|
50
|
+
// Check for duplicate category names
|
|
51
|
+
if (formData.categories && Array.isArray(formData.categories)) {
|
|
52
|
+
const categories = formData.categories.filter((item) => (item === null || item === void 0 ? void 0 : item.name) && item.name.trim() !== '');
|
|
53
|
+
// Find all categories that have duplicates (case-insensitive)
|
|
54
|
+
const duplicateCategories = [];
|
|
55
|
+
const lowerCaseMap = new Map();
|
|
56
|
+
// First pass: map lowercase names to all original cases
|
|
57
|
+
categories.forEach((category) => {
|
|
58
|
+
const lowerName = category.name.trim().toLowerCase();
|
|
59
|
+
if (!lowerCaseMap.has(lowerName)) {
|
|
60
|
+
lowerCaseMap.set(lowerName, []);
|
|
61
|
+
}
|
|
62
|
+
lowerCaseMap.get(lowerName).push(category.name.trim());
|
|
63
|
+
});
|
|
64
|
+
// Second pass: collect all names that appear more than once
|
|
65
|
+
lowerCaseMap.forEach((originalNames) => {
|
|
66
|
+
if (originalNames.length > 1) {
|
|
67
|
+
duplicateCategories.push(...originalNames);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
if (duplicateCategories.length > 0) {
|
|
71
|
+
const uniqueDuplicates = [...new Set(duplicateCategories)];
|
|
72
|
+
errors.categories = `Duplicate category names found: ${uniqueDuplicates.join(', ')}`;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
valid: Object.keys(errors).length === 0,
|
|
77
|
+
errors
|
|
78
|
+
};
|
|
79
|
+
},
|
|
80
|
+
render: (node) => {
|
|
81
|
+
var _a;
|
|
82
|
+
const callLlmAction = (_a = node.actions) === null || _a === void 0 ? void 0 : _a.find((action) => action.type === 'call_llm');
|
|
83
|
+
return html `
|
|
84
|
+
<div class="body">Categorize with ${callLlmAction.llm.name}</div>
|
|
85
|
+
`;
|
|
86
|
+
},
|
|
87
|
+
toFormData: (node) => {
|
|
88
|
+
var _a, _b, _c;
|
|
89
|
+
// Extract data from the existing node structure
|
|
90
|
+
const callLlmAction = (_a = node.actions) === null || _a === void 0 ? void 0 : _a.find((action) => action.type === 'call_llm');
|
|
91
|
+
const categories = ((_c = (_b = node.router) === null || _b === void 0 ? void 0 : _b.categories) === null || _c === void 0 ? void 0 : _c.filter((cat) => cat.name !== 'Other' && cat.name !== 'Failure').map((cat) => ({ name: cat.name }))) || [];
|
|
92
|
+
return {
|
|
93
|
+
uuid: node.uuid,
|
|
94
|
+
llm: (callLlmAction === null || callLlmAction === void 0 ? void 0 : callLlmAction.llm)
|
|
95
|
+
? [{ value: callLlmAction.llm.uuid, name: callLlmAction.llm.name }]
|
|
96
|
+
: [],
|
|
97
|
+
input: (callLlmAction === null || callLlmAction === void 0 ? void 0 : callLlmAction.input) || '@input',
|
|
98
|
+
categories: categories
|
|
99
|
+
};
|
|
100
|
+
},
|
|
101
|
+
fromFormData: (formData, originalNode) => {
|
|
102
|
+
var _a, _b, _c;
|
|
103
|
+
// Get LLM selection
|
|
104
|
+
const llmSelection = Array.isArray(formData.llm) && formData.llm.length > 0
|
|
105
|
+
? formData.llm[0]
|
|
106
|
+
: null;
|
|
107
|
+
// Get user categories
|
|
108
|
+
const userCategories = (formData.categories || [])
|
|
109
|
+
.filter((item) => { var _a; return (_a = item === null || item === void 0 ? void 0 : item.name) === null || _a === void 0 ? void 0 : _a.trim(); })
|
|
110
|
+
.map((item) => item.name.trim());
|
|
111
|
+
// Find existing call_llm action to preserve its UUID
|
|
112
|
+
const existingCallLlmAction = (_a = originalNode.actions) === null || _a === void 0 ? void 0 : _a.find((action) => action.type === 'call_llm');
|
|
113
|
+
const callLlmUuid = (existingCallLlmAction === null || existingCallLlmAction === void 0 ? void 0 : existingCallLlmAction.uuid) || generateUUID();
|
|
114
|
+
// Create call_llm action (using any type to match the example format)
|
|
115
|
+
const callLlmAction = {
|
|
116
|
+
type: 'call_llm',
|
|
117
|
+
uuid: callLlmUuid,
|
|
118
|
+
llm: llmSelection
|
|
119
|
+
? { uuid: llmSelection.value, name: llmSelection.name }
|
|
120
|
+
: { uuid: '', name: '' },
|
|
121
|
+
instructions: `@(prompt("categorize", slice(node.categories, 0, -2)))`,
|
|
122
|
+
input: formData.input || '@input',
|
|
123
|
+
output_local: '_llm_output'
|
|
124
|
+
};
|
|
125
|
+
// Create categories and exits
|
|
126
|
+
const categories = [];
|
|
127
|
+
const exits = [];
|
|
128
|
+
const cases = [];
|
|
129
|
+
// Get existing categories from original node for UUID preservation
|
|
130
|
+
const existingCategories = ((_b = originalNode.router) === null || _b === void 0 ? void 0 : _b.categories) || [];
|
|
131
|
+
const existingExits = originalNode.exits || [];
|
|
132
|
+
const existingCases = ((_c = originalNode.router) === null || _c === void 0 ? void 0 : _c.cases) || [];
|
|
133
|
+
// Add user categories
|
|
134
|
+
userCategories.forEach((categoryName) => {
|
|
135
|
+
// Check if this category already exists
|
|
136
|
+
const existingCategory = existingCategories.find((cat) => cat.name === categoryName);
|
|
137
|
+
const existingExit = existingCategory
|
|
138
|
+
? existingExits.find((exit) => exit.uuid === existingCategory.exit_uuid)
|
|
139
|
+
: null;
|
|
140
|
+
const existingCase = existingCategory
|
|
141
|
+
? existingCases.find((case_) => case_.category_uuid === existingCategory.uuid)
|
|
142
|
+
: null;
|
|
143
|
+
// Use existing UUIDs if category name hasn't changed, otherwise generate new ones
|
|
144
|
+
const categoryUuid = (existingCategory === null || existingCategory === void 0 ? void 0 : existingCategory.uuid) || generateUUID();
|
|
145
|
+
const exitUuid = (existingExit === null || existingExit === void 0 ? void 0 : existingExit.uuid) || generateUUID();
|
|
146
|
+
const caseUuid = (existingCase === null || existingCase === void 0 ? void 0 : existingCase.uuid) || generateUUID();
|
|
147
|
+
categories.push({
|
|
148
|
+
uuid: categoryUuid,
|
|
149
|
+
name: categoryName,
|
|
150
|
+
exit_uuid: exitUuid
|
|
151
|
+
});
|
|
152
|
+
exits.push({
|
|
153
|
+
uuid: exitUuid,
|
|
154
|
+
destination_uuid: (existingExit === null || existingExit === void 0 ? void 0 : existingExit.destination_uuid) || null
|
|
155
|
+
});
|
|
156
|
+
cases.push({
|
|
157
|
+
uuid: caseUuid,
|
|
158
|
+
type: 'has_only_text',
|
|
159
|
+
arguments: [categoryName],
|
|
160
|
+
category_uuid: categoryUuid
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
// Add "Other" category (default)
|
|
164
|
+
const existingOtherCategory = existingCategories.find((cat) => cat.name === 'Other');
|
|
165
|
+
const existingOtherExit = existingOtherCategory
|
|
166
|
+
? existingExits.find((exit) => exit.uuid === existingOtherCategory.exit_uuid)
|
|
167
|
+
: null;
|
|
168
|
+
const otherCategoryUuid = (existingOtherCategory === null || existingOtherCategory === void 0 ? void 0 : existingOtherCategory.uuid) || generateUUID();
|
|
169
|
+
const otherExitUuid = (existingOtherExit === null || existingOtherExit === void 0 ? void 0 : existingOtherExit.uuid) || generateUUID();
|
|
170
|
+
categories.push({
|
|
171
|
+
uuid: otherCategoryUuid,
|
|
172
|
+
name: 'Other',
|
|
173
|
+
exit_uuid: otherExitUuid
|
|
174
|
+
});
|
|
175
|
+
exits.push({
|
|
176
|
+
uuid: otherExitUuid,
|
|
177
|
+
destination_uuid: (existingOtherExit === null || existingOtherExit === void 0 ? void 0 : existingOtherExit.destination_uuid) || null
|
|
178
|
+
});
|
|
179
|
+
// Add "Failure" category
|
|
180
|
+
const existingFailureCategory = existingCategories.find((cat) => cat.name === 'Failure');
|
|
181
|
+
const existingFailureExit = existingFailureCategory
|
|
182
|
+
? existingExits.find((exit) => exit.uuid === existingFailureCategory.exit_uuid)
|
|
183
|
+
: null;
|
|
184
|
+
const existingFailureCase = existingFailureCategory
|
|
185
|
+
? existingCases.find((case_) => {
|
|
186
|
+
var _a;
|
|
187
|
+
return case_.category_uuid === existingFailureCategory.uuid &&
|
|
188
|
+
((_a = case_.arguments) === null || _a === void 0 ? void 0 : _a[0]) === '<ERROR>';
|
|
189
|
+
})
|
|
190
|
+
: null;
|
|
191
|
+
const failureCategoryUuid = (existingFailureCategory === null || existingFailureCategory === void 0 ? void 0 : existingFailureCategory.uuid) || generateUUID();
|
|
192
|
+
const failureExitUuid = (existingFailureExit === null || existingFailureExit === void 0 ? void 0 : existingFailureExit.uuid) || generateUUID();
|
|
193
|
+
const failureCaseUuid = (existingFailureCase === null || existingFailureCase === void 0 ? void 0 : existingFailureCase.uuid) || generateUUID();
|
|
194
|
+
categories.push({
|
|
195
|
+
uuid: failureCategoryUuid,
|
|
196
|
+
name: 'Failure',
|
|
197
|
+
exit_uuid: failureExitUuid
|
|
198
|
+
});
|
|
199
|
+
exits.push({
|
|
200
|
+
uuid: failureExitUuid,
|
|
201
|
+
destination_uuid: (existingFailureExit === null || existingFailureExit === void 0 ? void 0 : existingFailureExit.destination_uuid) || null
|
|
202
|
+
});
|
|
203
|
+
// Add failure case for <ERROR>
|
|
204
|
+
cases.push({
|
|
205
|
+
uuid: failureCaseUuid,
|
|
206
|
+
type: 'has_only_text',
|
|
207
|
+
arguments: ['<ERROR>'],
|
|
208
|
+
category_uuid: failureCategoryUuid
|
|
209
|
+
});
|
|
210
|
+
// Create the router
|
|
211
|
+
const router = {
|
|
212
|
+
type: 'switch',
|
|
213
|
+
categories: categories,
|
|
214
|
+
default_category_uuid: otherCategoryUuid,
|
|
215
|
+
operand: '@locals._llm_output',
|
|
216
|
+
cases: cases
|
|
217
|
+
};
|
|
218
|
+
// Return the complete node
|
|
219
|
+
return {
|
|
220
|
+
uuid: originalNode.uuid,
|
|
221
|
+
actions: [callLlmAction],
|
|
222
|
+
router: router,
|
|
223
|
+
exits: exits
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
//# sourceMappingURL=split_by_llm_categorize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"split_by_llm_categorize.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_llm_categorize.ts"],"names":[],"mappings":"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","sourcesContent":["import { COLORS, NodeConfig } from '../types';\nimport { Node } from '../../store/flow-definition';\nimport { generateUUID } from '../../utils';\nimport { html } from 'lit';\n\nexport const split_by_llm_categorize: NodeConfig = {\n type: 'split_by_llm_categorize',\n name: 'Split by AI',\n color: COLORS.call,\n form: {\n llm: {\n type: 'select',\n label: 'LLM',\n helpText: 'Select the LLM to use for categorization',\n required: true,\n endpoint: '/test-assets/select/llms.json',\n valueKey: 'uuid',\n nameKey: 'name',\n placeholder: 'Select an LLM...'\n },\n input: {\n type: 'text',\n label: 'Input',\n helpText: 'The input to categorize (usually @input)',\n required: true,\n evaluated: true,\n placeholder: '@input'\n },\n categories: {\n type: 'array',\n label: 'Categories',\n helpText: 'Define the categories for classification',\n required: true,\n itemLabel: 'Category',\n minItems: 1,\n maxItems: 10,\n isEmptyItem: (item: any) => {\n return !item.name || item.name.trim() === '';\n },\n itemConfig: {\n name: {\n type: 'text',\n placeholder: 'Category name',\n required: true\n }\n }\n }\n },\n layout: ['llm', 'input', 'categories'],\n validate: (formData: any) => {\n const errors: { [key: string]: string } = {};\n\n // Check for duplicate category names\n if (formData.categories && Array.isArray(formData.categories)) {\n const categories = formData.categories.filter(\n (item: any) => item?.name && item.name.trim() !== ''\n );\n\n // Find all categories that have duplicates (case-insensitive)\n const duplicateCategories = [];\n const lowerCaseMap = new Map();\n\n // First pass: map lowercase names to all original cases\n categories.forEach((category) => {\n const lowerName = category.name.trim().toLowerCase();\n if (!lowerCaseMap.has(lowerName)) {\n lowerCaseMap.set(lowerName, []);\n }\n lowerCaseMap.get(lowerName).push(category.name.trim());\n });\n\n // Second pass: collect all names that appear more than once\n lowerCaseMap.forEach((originalNames) => {\n if (originalNames.length > 1) {\n duplicateCategories.push(...originalNames);\n }\n });\n\n if (duplicateCategories.length > 0) {\n const uniqueDuplicates = [...new Set(duplicateCategories)];\n errors.categories = `Duplicate category names found: ${uniqueDuplicates.join(\n ', '\n )}`;\n }\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n render: (node: Node) => {\n const callLlmAction = node.actions?.find(\n (action) => action.type === 'call_llm'\n ) as any;\n return html`\n <div class=\"body\">Categorize with ${callLlmAction.llm.name}</div>\n `;\n },\n toFormData: (node: Node) => {\n // Extract data from the existing node structure\n const callLlmAction = node.actions?.find(\n (action) => action.type === 'call_llm'\n ) as any;\n const categories =\n node.router?.categories\n ?.filter((cat) => cat.name !== 'Other' && cat.name !== 'Failure')\n .map((cat) => ({ name: cat.name })) || [];\n\n return {\n uuid: node.uuid,\n llm: callLlmAction?.llm\n ? [{ value: callLlmAction.llm.uuid, name: callLlmAction.llm.name }]\n : [],\n input: callLlmAction?.input || '@input',\n categories: categories\n };\n },\n fromFormData: (formData: any, originalNode: Node): Node => {\n // Get LLM selection\n const llmSelection =\n Array.isArray(formData.llm) && formData.llm.length > 0\n ? formData.llm[0]\n : null;\n\n // Get user categories\n const userCategories = (formData.categories || [])\n .filter((item: any) => item?.name?.trim())\n .map((item: any) => item.name.trim());\n\n // Find existing call_llm action to preserve its UUID\n const existingCallLlmAction = originalNode.actions?.find(\n (action) => action.type === 'call_llm'\n );\n const callLlmUuid = existingCallLlmAction?.uuid || generateUUID();\n\n // Create call_llm action (using any type to match the example format)\n const callLlmAction: any = {\n type: 'call_llm',\n uuid: callLlmUuid,\n llm: llmSelection\n ? { uuid: llmSelection.value, name: llmSelection.name }\n : { uuid: '', name: '' },\n instructions: `@(prompt(\"categorize\", slice(node.categories, 0, -2)))`,\n input: formData.input || '@input',\n output_local: '_llm_output'\n };\n\n // Create categories and exits\n const categories = [];\n const exits = [];\n const cases = [];\n\n // Get existing categories from original node for UUID preservation\n const existingCategories = originalNode.router?.categories || [];\n const existingExits = originalNode.exits || [];\n const existingCases = originalNode.router?.cases || [];\n\n // Add user categories\n userCategories.forEach((categoryName: string) => {\n // Check if this category already exists\n const existingCategory = existingCategories.find(\n (cat) => cat.name === categoryName\n );\n const existingExit = existingCategory\n ? existingExits.find((exit) => exit.uuid === existingCategory.exit_uuid)\n : null;\n const existingCase = existingCategory\n ? existingCases.find(\n (case_) => case_.category_uuid === existingCategory.uuid\n )\n : null;\n\n // Use existing UUIDs if category name hasn't changed, otherwise generate new ones\n const categoryUuid = existingCategory?.uuid || generateUUID();\n const exitUuid = existingExit?.uuid || generateUUID();\n const caseUuid = existingCase?.uuid || generateUUID();\n\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 cases.push({\n uuid: caseUuid,\n type: 'has_only_text',\n arguments: [categoryName],\n category_uuid: categoryUuid\n });\n });\n\n // Add \"Other\" category (default)\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 otherCategoryUuid = existingOtherCategory?.uuid || generateUUID();\n const otherExitUuid = existingOtherExit?.uuid || generateUUID();\n\n categories.push({\n uuid: otherCategoryUuid,\n name: 'Other',\n exit_uuid: otherExitUuid\n });\n exits.push({\n uuid: otherExitUuid,\n destination_uuid: existingOtherExit?.destination_uuid || null\n });\n\n // Add \"Failure\" category\n const existingFailureCategory = existingCategories.find(\n (cat) => cat.name === 'Failure'\n );\n const existingFailureExit = existingFailureCategory\n ? existingExits.find(\n (exit) => exit.uuid === existingFailureCategory.exit_uuid\n )\n : null;\n const existingFailureCase = existingFailureCategory\n ? existingCases.find(\n (case_) =>\n case_.category_uuid === existingFailureCategory.uuid &&\n case_.arguments?.[0] === '<ERROR>'\n )\n : null;\n\n const failureCategoryUuid = existingFailureCategory?.uuid || generateUUID();\n const failureExitUuid = existingFailureExit?.uuid || generateUUID();\n const failureCaseUuid = existingFailureCase?.uuid || generateUUID();\n\n categories.push({\n uuid: failureCategoryUuid,\n name: 'Failure',\n exit_uuid: failureExitUuid\n });\n exits.push({\n uuid: failureExitUuid,\n destination_uuid: existingFailureExit?.destination_uuid || null\n });\n\n // Add failure case for <ERROR>\n cases.push({\n uuid: failureCaseUuid,\n type: 'has_only_text',\n arguments: ['<ERROR>'],\n category_uuid: failureCategoryUuid\n });\n\n // Create the router\n const router = {\n type: 'switch' as const,\n categories: categories,\n default_category_uuid: otherCategoryUuid,\n operand: '@locals._llm_output',\n cases: cases\n };\n\n // Return the complete node\n return {\n uuid: originalNode.uuid,\n actions: [callLlmAction],\n router: router,\n exits: exits\n };\n }\n};\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { open_ticket } from '../actions/open_ticket';
|
|
2
|
+
export const split_by_ticket = {
|
|
3
|
+
type: 'split_by_ticket',
|
|
4
|
+
action: open_ticket,
|
|
5
|
+
router: {
|
|
6
|
+
type: 'switch',
|
|
7
|
+
defaultCategory: 'Failure',
|
|
8
|
+
operand: '@locals._new_ticket',
|
|
9
|
+
rules: [
|
|
10
|
+
{
|
|
11
|
+
type: 'has_text',
|
|
12
|
+
arguments: [],
|
|
13
|
+
categoryName: 'Success'
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=split_by_ticket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"split_by_ticket.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_ticket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAGrD,MAAM,CAAC,MAAM,eAAe,GAAe;IACzC,IAAI,EAAE,iBAAiB;IACvB,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE;QACN,IAAI,EAAE,QAAQ;QACd,eAAe,EAAE,SAAS;QAC1B,OAAO,EAAE,qBAAqB;QAC9B,KAAK,EAAE;YACL;gBACE,IAAI,EAAE,UAAU;gBAChB,SAAS,EAAE,EAAE;gBACb,YAAY,EAAE,SAAS;aACxB;SACF;KACF;CACF,CAAC","sourcesContent":["import { open_ticket } from '../actions/open_ticket';\nimport { NodeConfig } from '../types';\n\nexport const split_by_ticket: NodeConfig = {\n type: 'split_by_ticket',\n action: open_ticket,\n router: {\n type: 'switch',\n defaultCategory: 'Failure',\n operand: '@locals._new_ticket',\n rules: [\n {\n type: 'has_text',\n arguments: [],\n categoryName: 'Success'\n }\n ]\n }\n};\n"]}
|
|
@@ -2,6 +2,32 @@ import { COLORS } from '../types';
|
|
|
2
2
|
export const wait_for_response = {
|
|
3
3
|
type: 'wait_for_response',
|
|
4
4
|
name: 'Wait for Response',
|
|
5
|
-
color: COLORS.wait
|
|
5
|
+
color: COLORS.wait,
|
|
6
|
+
form: {
|
|
7
|
+
result_name: {
|
|
8
|
+
type: 'text',
|
|
9
|
+
label: 'Result Name',
|
|
10
|
+
helpText: 'The name to save the response as',
|
|
11
|
+
placeholder: 'response'
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
layout: ['timeout', 'result_name'],
|
|
15
|
+
toFormData: (node) => {
|
|
16
|
+
var _a;
|
|
17
|
+
return {
|
|
18
|
+
uuid: node.uuid,
|
|
19
|
+
result_name: ((_a = node.router) === null || _a === void 0 ? void 0 : _a.result_name) || 'response'
|
|
20
|
+
};
|
|
21
|
+
},
|
|
22
|
+
fromFormData: (formData, originalNode) => {
|
|
23
|
+
const router = {
|
|
24
|
+
...originalNode.router,
|
|
25
|
+
result_name: formData.result_name || 'response'
|
|
26
|
+
};
|
|
27
|
+
return {
|
|
28
|
+
...originalNode,
|
|
29
|
+
router
|
|
30
|
+
};
|
|
31
|
+
}
|
|
6
32
|
};
|
|
7
33
|
//# sourceMappingURL=wait_for_response.js.map
|
|
@@ -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;
|
|
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"]}
|
|
@@ -11,69 +11,4 @@ export const COLORS = {
|
|
|
11
11
|
add: '#309c42',
|
|
12
12
|
remove: '#e74c3c'
|
|
13
13
|
};
|
|
14
|
-
// Default property type mappings
|
|
15
|
-
export function getDefaultComponent(value) {
|
|
16
|
-
if (typeof value === 'boolean') {
|
|
17
|
-
return 'temba-checkbox';
|
|
18
|
-
}
|
|
19
|
-
if (typeof value === 'number') {
|
|
20
|
-
return 'temba-textinput';
|
|
21
|
-
}
|
|
22
|
-
if (Array.isArray(value)) {
|
|
23
|
-
return 'temba-select'; // For arrays, use multi-select
|
|
24
|
-
}
|
|
25
|
-
// Default to text input for strings and unknown types
|
|
26
|
-
return 'temba-textinput';
|
|
27
|
-
}
|
|
28
|
-
// Get component properties for default mappings with proper typing
|
|
29
|
-
export function getDefaultComponentProps(value) {
|
|
30
|
-
if (typeof value === 'boolean') {
|
|
31
|
-
return {
|
|
32
|
-
widget: { type: 'temba-checkbox' }
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
if (typeof value === 'number') {
|
|
36
|
-
return {
|
|
37
|
-
widget: {
|
|
38
|
-
type: 'temba-textinput',
|
|
39
|
-
attributes: { type: 'number' }
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
if (Array.isArray(value)) {
|
|
44
|
-
if (value.length > 0 && typeof value[0] === 'string') {
|
|
45
|
-
return {
|
|
46
|
-
widget: {
|
|
47
|
-
type: 'temba-select',
|
|
48
|
-
attributes: { multi: true, tags: true }
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
return {
|
|
53
|
-
widget: {
|
|
54
|
-
type: 'temba-select',
|
|
55
|
-
attributes: { multi: true }
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
return {
|
|
60
|
-
widget: { type: 'temba-textinput' }
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
// Type guard functions for working with WidgetConfig
|
|
64
|
-
export function isTextInputWidget(config) {
|
|
65
|
-
return config.type === 'temba-textinput';
|
|
66
|
-
}
|
|
67
|
-
export function isCompletionWidget(config) {
|
|
68
|
-
return config.type === 'temba-completion';
|
|
69
|
-
}
|
|
70
|
-
export function isSelectWidget(config) {
|
|
71
|
-
return config.type === 'temba-select';
|
|
72
|
-
}
|
|
73
|
-
export function isCheckboxWidget(config) {
|
|
74
|
-
return config.type === 'temba-checkbox';
|
|
75
|
-
}
|
|
76
|
-
export function isSliderWidget(config) {
|
|
77
|
-
return config.type === 'temba-slider';
|
|
78
|
-
}
|
|
79
14
|
//# sourceMappingURL=types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/flow/types.ts"],"names":[],"mappings":"AAiQA,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;AAEF,iCAAiC;AACjC,MAAM,UAAU,mBAAmB,CAAC,KAAU;IAC5C,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,cAAc,CAAC,CAAC,+BAA+B;IACxD,CAAC;IACD,sDAAsD;IACtD,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,wBAAwB,CAAC,KAAU;IACjD,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO;YACL,MAAM,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE;SACnC,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO;YACL,MAAM,EAAE;gBACN,IAAI,EAAE,iBAAiB;gBACvB,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;aAC/B;SACF,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;YACrD,OAAO;gBACL,MAAM,EAAE;oBACN,IAAI,EAAE,cAAc;oBACpB,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE;iBACxC;aACF,CAAC;QACJ,CAAC;QACD,OAAO;YACL,MAAM,EAAE;gBACN,IAAI,EAAE,cAAc;gBACpB,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE;aAC5B;SACF,CAAC;IACJ,CAAC;IACD,OAAO;QACL,MAAM,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE;KACpC,CAAC;AACJ,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,iBAAiB,CAC/B,MAAoB;IAEpB,OAAO,MAAM,CAAC,IAAI,KAAK,iBAAiB,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,MAAoB;IAEpB,OAAO,MAAM,CAAC,IAAI,KAAK,kBAAkB,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,MAAoB;IAEpB,OAAO,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,MAAoB;IAEpB,OAAO,MAAM,CAAC,IAAI,KAAK,gBAAgB,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,MAAoB;IAEpB,OAAO,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC;AACxC,CAAC","sourcesContent":["import { TemplateResult } from 'lit-html';\nimport { Action } 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\n// Widget configuration using discriminated union for type safety\nexport type WidgetConfig =\n | { type: 'temba-textinput'; attributes?: TextInputAttributes }\n | { type: 'temba-completion'; attributes?: CompletionAttributes }\n | { type: 'temba-select'; attributes?: SelectAttributes }\n | { type: 'temba-checkbox'; attributes?: CheckboxAttributes }\n | { type: 'temba-slider'; attributes?: SliderAttributes }\n | { type: string; attributes?: { [key: string]: any } }; // Generic fallback\n\n// Property configuration with the clean structure you want\nexport interface PropertyConfig {\n // Form field metadata\n label?: string;\n helpText?: string;\n required?: boolean;\n maxLength?: number;\n minLength?: number;\n pattern?: string;\n\n // Widget configuration\n widget: WidgetConfig;\n\n // Conditional behavior based on other field values\n conditions?: {\n // When to show this field\n visible?: (formData: any) => boolean;\n\n // When this field is disabled\n disabled?: (formData: any) => boolean;\n };\n}\n\nexport interface NodeConfig {\n type: string;\n name?: string;\n color?: string;\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: 'has_number_between' | 'has_string' | 'has_value' | 'has_not_value';\n arguments: string[];\n categoryName: string;\n }[];\n };\n properties?: { [key: string]: PropertyConfig };\n toFormData?: (node: any) => any;\n fromFormData?: (formData: any, originalNode: any) => any;\n}\n\n// New field configuration system for generic form generation\nexport interface BaseFieldConfig {\n label?: string;\n required?: boolean;\n evaluated?: boolean; // if this field supports expression evaluation\n dependsOn?: string[]; // fields this field depends on\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; // CSS max-width value (e.g., '200px', '50%', '10rem')\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}\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; label: string }[];\n multi?: 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}\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 onItemChange?: (\n itemIndex: number,\n field: string,\n value: any,\n allItems: any[]\n ) => any[];\n}\n\nexport interface CheckboxFieldConfig extends BaseFieldConfig {\n type: 'checkbox';\n size?: number;\n animateChange?: string;\n}\n\nexport type FieldConfig =\n | TextFieldConfig\n | TextareaFieldConfig\n | SelectFieldConfig\n | KeyValueFieldConfig\n | ArrayFieldConfig\n | CheckboxFieldConfig;\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; // initial state if collapsible\n helpText?: string;\n}\n\nexport type LayoutItem =\n | FieldItemConfig\n | RowLayoutConfig\n | GroupLayoutConfig\n | string; // string is shorthand for field\n\nexport interface ActionConfig {\n name: string;\n color: string;\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\n // Action editor configuration (legacy)\n // Form-level transformations\n toFormData?: (action: Action) => any;\n fromFormData?: (formData: any) => Action;\n\n validate?: (action: Action) => ValidationResult;\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\n// Default property type mappings\nexport function getDefaultComponent(value: any): WidgetConfig['type'] {\n if (typeof value === 'boolean') {\n return 'temba-checkbox';\n }\n if (typeof value === 'number') {\n return 'temba-textinput';\n }\n if (Array.isArray(value)) {\n return 'temba-select'; // For arrays, use multi-select\n }\n // Default to text input for strings and unknown types\n return 'temba-textinput';\n}\n\n// Get component properties for default mappings with proper typing\nexport function getDefaultComponentProps(value: any): PropertyConfig {\n if (typeof value === 'boolean') {\n return {\n widget: { type: 'temba-checkbox' }\n };\n }\n if (typeof value === 'number') {\n return {\n widget: {\n type: 'temba-textinput',\n attributes: { type: 'number' }\n }\n };\n }\n if (Array.isArray(value)) {\n if (value.length > 0 && typeof value[0] === 'string') {\n return {\n widget: {\n type: 'temba-select',\n attributes: { multi: true, tags: true }\n }\n };\n }\n return {\n widget: {\n type: 'temba-select',\n attributes: { multi: true }\n }\n };\n }\n return {\n widget: { type: 'temba-textinput' }\n };\n}\n\n// Type guard functions for working with WidgetConfig\nexport function isTextInputWidget(\n config: WidgetConfig\n): config is { type: 'temba-textinput'; attributes?: TextInputAttributes } {\n return config.type === 'temba-textinput';\n}\n\nexport function isCompletionWidget(\n config: WidgetConfig\n): config is { type: 'temba-completion'; attributes?: CompletionAttributes } {\n return config.type === 'temba-completion';\n}\n\nexport function isSelectWidget(\n config: WidgetConfig\n): config is { type: 'temba-select'; attributes?: SelectAttributes } {\n return config.type === 'temba-select';\n}\n\nexport function isCheckboxWidget(\n config: WidgetConfig\n): config is { type: 'temba-checkbox'; attributes?: CheckboxAttributes } {\n return config.type === 'temba-checkbox';\n}\n\nexport function isSliderWidget(\n config: WidgetConfig\n): config is { type: 'slider'; attributes?: SliderAttributes } {\n return config.type === 'temba-slider';\n}\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/flow/types.ts"],"names":[],"mappings":"AAiQA,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 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 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;\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\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}\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; label: 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?: 'small' | 'large';\n createArbitraryOption?: (input: string, options: any[]) => any;\n allowCreate?: boolean;\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 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}\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 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\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"]}
|