@nyaruka/temba-components 0.131.2 → 0.131.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/demo/components/floating-tabs/example.html +400 -0
- package/demo/components/flow/index.html +1 -1
- package/demo/data/flows/sample-flow.json +41 -2
- package/demo/data/flows/voicemail.json +613 -0
- package/demo/index.html +6 -0
- package/dist/locales/es.js +5 -5
- package/dist/locales/es.js.map +1 -1
- package/dist/locales/fr.js +5 -5
- package/dist/locales/fr.js.map +1 -1
- package/dist/locales/locale-codes.js +11 -2
- package/dist/locales/locale-codes.js.map +1 -1
- package/dist/locales/pt.js +5 -5
- package/dist/locales/pt.js.map +1 -1
- package/dist/temba-components.js +1109 -535
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/display/FloatingTab.js +167 -0
- package/out-tsc/src/display/FloatingTab.js.map +1 -0
- package/out-tsc/src/display/ProgressBar.js +22 -2
- package/out-tsc/src/display/ProgressBar.js.map +1 -1
- package/out-tsc/src/events.js.map +1 -1
- package/out-tsc/src/flow/CanvasNode.js +165 -31
- package/out-tsc/src/flow/CanvasNode.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +857 -3
- package/out-tsc/src/flow/Editor.js.map +1 -1
- package/out-tsc/src/flow/NodeEditor.js +239 -19
- package/out-tsc/src/flow/NodeEditor.js.map +1 -1
- package/out-tsc/src/flow/NodeTypeSelector.js +44 -3
- package/out-tsc/src/flow/NodeTypeSelector.js.map +1 -1
- package/out-tsc/src/flow/StickyNote.js +12 -3
- package/out-tsc/src/flow/StickyNote.js.map +1 -1
- package/out-tsc/src/flow/actions/add_contact_groups.js +2 -1
- package/out-tsc/src/flow/actions/add_contact_groups.js.map +1 -1
- package/out-tsc/src/flow/actions/add_contact_urn.js +2 -1
- package/out-tsc/src/flow/actions/add_contact_urn.js.map +1 -1
- package/out-tsc/src/flow/actions/add_input_labels.js +2 -1
- package/out-tsc/src/flow/actions/add_input_labels.js.map +1 -1
- package/out-tsc/src/flow/actions/play_audio.js +2 -1
- package/out-tsc/src/flow/actions/play_audio.js.map +1 -1
- package/out-tsc/src/flow/actions/remove_contact_groups.js +2 -1
- package/out-tsc/src/flow/actions/remove_contact_groups.js.map +1 -1
- package/out-tsc/src/flow/actions/request_optin.js +1 -0
- package/out-tsc/src/flow/actions/request_optin.js.map +1 -1
- package/out-tsc/src/flow/actions/say_msg.js +2 -1
- package/out-tsc/src/flow/actions/say_msg.js.map +1 -1
- package/out-tsc/src/flow/actions/send_broadcast.js +2 -1
- package/out-tsc/src/flow/actions/send_broadcast.js.map +1 -1
- package/out-tsc/src/flow/actions/send_email.js +2 -1
- package/out-tsc/src/flow/actions/send_email.js.map +1 -1
- package/out-tsc/src/flow/actions/send_msg.js +93 -3
- package/out-tsc/src/flow/actions/send_msg.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_channel.js +2 -1
- package/out-tsc/src/flow/actions/set_contact_channel.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_field.js +2 -1
- package/out-tsc/src/flow/actions/set_contact_field.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_language.js +2 -1
- package/out-tsc/src/flow/actions/set_contact_language.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_name.js +2 -1
- package/out-tsc/src/flow/actions/set_contact_name.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_status.js +2 -1
- package/out-tsc/src/flow/actions/set_contact_status.js.map +1 -1
- package/out-tsc/src/flow/actions/set_run_result.js +2 -1
- package/out-tsc/src/flow/actions/set_run_result.js.map +1 -1
- package/out-tsc/src/flow/actions/start_session.js +2 -1
- package/out-tsc/src/flow/actions/start_session.js.map +1 -1
- package/out-tsc/src/flow/config.js +2 -10
- package/out-tsc/src/flow/config.js.map +1 -1
- package/out-tsc/src/flow/nodes/shared.js +54 -0
- package/out-tsc/src/flow/nodes/shared.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_airtime.js +9 -3
- package/out-tsc/src/flow/nodes/split_by_airtime.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_contact_field.js +8 -3
- package/out-tsc/src/flow/nodes/split_by_contact_field.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_expression.js +8 -3
- package/out-tsc/src/flow/nodes/split_by_expression.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_groups.js +8 -3
- package/out-tsc/src/flow/nodes/split_by_groups.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_intent.js +3 -2
- package/out-tsc/src/flow/nodes/split_by_intent.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_llm.js +9 -2
- package/out-tsc/src/flow/nodes/split_by_llm.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_llm_categorize.js +9 -2
- package/out-tsc/src/flow/nodes/split_by_llm_categorize.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_random.js +8 -2
- package/out-tsc/src/flow/nodes/split_by_random.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_resthook.js +8 -3
- package/out-tsc/src/flow/nodes/split_by_resthook.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_run_result.js +8 -3
- package/out-tsc/src/flow/nodes/split_by_run_result.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_scheme.js +8 -3
- package/out-tsc/src/flow/nodes/split_by_scheme.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_subflow.js +8 -2
- package/out-tsc/src/flow/nodes/split_by_subflow.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_ticket.js +8 -2
- package/out-tsc/src/flow/nodes/split_by_ticket.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_webhook.js +8 -2
- package/out-tsc/src/flow/nodes/split_by_webhook.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_digits.js +3 -2
- package/out-tsc/src/flow/nodes/wait_for_digits.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_menu.js +3 -2
- package/out-tsc/src/flow/nodes/wait_for_menu.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_response.js +8 -3
- package/out-tsc/src/flow/nodes/wait_for_response.js.map +1 -1
- package/out-tsc/src/flow/types.js +15 -0
- package/out-tsc/src/flow/types.js.map +1 -1
- package/out-tsc/src/layout/FloatingWindow.js +346 -0
- package/out-tsc/src/layout/FloatingWindow.js.map +1 -0
- package/out-tsc/src/live/ContactChat.js +3 -19
- package/out-tsc/src/live/ContactChat.js.map +1 -1
- package/out-tsc/src/locales/es.js +5 -5
- package/out-tsc/src/locales/es.js.map +1 -1
- package/out-tsc/src/locales/fr.js +5 -5
- package/out-tsc/src/locales/fr.js.map +1 -1
- package/out-tsc/src/locales/locale-codes.js +11 -2
- package/out-tsc/src/locales/locale-codes.js.map +1 -1
- package/out-tsc/src/locales/pt.js +5 -5
- package/out-tsc/src/locales/pt.js.map +1 -1
- package/out-tsc/src/store/AppState.js +67 -0
- package/out-tsc/src/store/AppState.js.map +1 -1
- package/out-tsc/temba-modules.js +4 -0
- package/out-tsc/temba-modules.js.map +1 -1
- package/out-tsc/test/temba-floating-tab.test.js +91 -0
- package/out-tsc/test/temba-floating-tab.test.js.map +1 -0
- package/out-tsc/test/temba-floating-window.test.js +301 -0
- package/out-tsc/test/temba-floating-window.test.js.map +1 -0
- package/out-tsc/test/temba-flow-editor-node.test.js +117 -0
- package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
- package/out-tsc/test/temba-localization.test.js +471 -0
- package/out-tsc/test/temba-localization.test.js.map +1 -0
- package/out-tsc/test/temba-node-type-selector.test.js +150 -0
- package/out-tsc/test/temba-node-type-selector.test.js.map +1 -1
- package/out-tsc/test/utils.test.js +18 -0
- package/out-tsc/test/utils.test.js.map +1 -1
- package/package.json +1 -1
- package/screenshots/truth/floating-tab/default.png +0 -0
- package/screenshots/truth/floating-tab/gray.png +0 -0
- package/screenshots/truth/floating-tab/green.png +0 -0
- package/screenshots/truth/floating-tab/hidden.png +0 -0
- package/screenshots/truth/floating-tab/hover.png +0 -0
- package/screenshots/truth/floating-tab/purple.png +0 -0
- package/screenshots/truth/floating-window/chromeless.png +0 -0
- package/screenshots/truth/floating-window/custom-size.png +0 -0
- package/screenshots/truth/floating-window/default.png +0 -0
- package/screenshots/truth/floating-window/with-header.png +0 -0
- package/screenshots/truth/node-type-selector/action-mode.png +0 -0
- package/screenshots/truth/node-type-selector/split-mode.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/feedback-categorization.png +0 -0
- package/src/display/FloatingTab.ts +174 -0
- package/src/display/ProgressBar.ts +22 -2
- package/src/events.ts +2 -4
- package/src/flow/CanvasNode.ts +190 -32
- package/src/flow/Editor.ts +1040 -3
- package/src/flow/NodeEditor.ts +317 -19
- package/src/flow/NodeTypeSelector.ts +47 -3
- package/src/flow/StickyNote.ts +12 -3
- package/src/flow/actions/add_contact_groups.ts +2 -1
- package/src/flow/actions/add_contact_urn.ts +3 -1
- package/src/flow/actions/add_input_labels.ts +2 -1
- package/src/flow/actions/play_audio.ts +2 -1
- package/src/flow/actions/remove_contact_groups.ts +3 -1
- package/src/flow/actions/request_optin.ts +1 -0
- package/src/flow/actions/say_msg.ts +2 -1
- package/src/flow/actions/send_broadcast.ts +2 -1
- package/src/flow/actions/send_email.ts +3 -1
- package/src/flow/actions/send_msg.ts +134 -3
- package/src/flow/actions/set_contact_channel.ts +2 -1
- package/src/flow/actions/set_contact_field.ts +2 -1
- package/src/flow/actions/set_contact_language.ts +3 -1
- package/src/flow/actions/set_contact_name.ts +2 -1
- package/src/flow/actions/set_contact_status.ts +2 -1
- package/src/flow/actions/set_run_result.ts +2 -1
- package/src/flow/actions/start_session.ts +3 -1
- package/src/flow/config.ts +2 -12
- package/src/flow/nodes/shared.ts +70 -1
- package/src/flow/nodes/split_by_airtime.ts +20 -3
- package/src/flow/nodes/split_by_contact_field.ts +13 -3
- package/src/flow/nodes/split_by_expression.ts +13 -3
- package/src/flow/nodes/split_by_groups.ts +13 -3
- package/src/flow/nodes/split_by_intent.ts +3 -2
- package/src/flow/nodes/split_by_llm.ts +19 -2
- package/src/flow/nodes/split_by_llm_categorize.ts +19 -2
- package/src/flow/nodes/split_by_random.ts +12 -2
- package/src/flow/nodes/split_by_resthook.ts +13 -3
- package/src/flow/nodes/split_by_run_result.ts +13 -3
- package/src/flow/nodes/split_by_scheme.ts +13 -3
- package/src/flow/nodes/split_by_subflow.ts +12 -2
- package/src/flow/nodes/split_by_ticket.ts +12 -2
- package/src/flow/nodes/split_by_webhook.ts +12 -2
- package/src/flow/nodes/wait_for_digits.ts +3 -2
- package/src/flow/nodes/wait_for_menu.ts +3 -2
- package/src/flow/nodes/wait_for_response.ts +13 -3
- package/src/flow/types.ts +47 -0
- package/src/layout/FloatingWindow.ts +386 -0
- package/src/live/ContactChat.ts +4 -19
- package/src/locales/es.ts +18 -13
- package/src/locales/fr.ts +18 -13
- package/src/locales/locale-codes.ts +11 -2
- package/src/locales/pt.ts +18 -13
- package/src/store/AppState.ts +104 -0
- package/static/api/llms.json +18 -0
- package/temba-modules.ts +4 -0
- package/test/temba-floating-tab.test.ts +110 -0
- package/test/temba-floating-window.test.ts +477 -0
- package/test/temba-flow-editor-node.test.ts +144 -0
- package/test/temba-localization.test.ts +611 -0
- package/test/temba-node-type-selector.test.ts +203 -0
- package/test/utils.test.ts +20 -0
- package/test-assets/contacts/history.json +5 -6
- package/test-assets/select/llms.json +2 -2
- package/web-dev-server.config.mjs +47 -1
- package/web-test-runner.config.mjs +0 -1
- package/out-tsc/src/flow/nodes/wait_for_audio.js +0 -7
- package/out-tsc/src/flow/nodes/wait_for_audio.js.map +0 -1
- package/out-tsc/src/flow/nodes/wait_for_image.js +0 -7
- package/out-tsc/src/flow/nodes/wait_for_image.js.map +0 -1
- package/out-tsc/src/flow/nodes/wait_for_location.js +0 -7
- package/out-tsc/src/flow/nodes/wait_for_location.js.map +0 -1
- package/out-tsc/src/flow/nodes/wait_for_video.js +0 -7
- package/out-tsc/src/flow/nodes/wait_for_video.js.map +0 -1
- package/src/flow/nodes/wait_for_audio.ts +0 -7
- package/src/flow/nodes/wait_for_image.ts +0 -7
- package/src/flow/nodes/wait_for_location.ts +0 -7
- package/src/flow/nodes/wait_for_video.ts +0 -7
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { html } from 'lit-html';
|
|
2
|
-
import { ActionConfig, ACTION_GROUPS } from '../types';
|
|
2
|
+
import { ActionConfig, ACTION_GROUPS, FlowTypes } from '../types';
|
|
3
3
|
import { Node, SayMsg } from '../../store/flow-definition';
|
|
4
4
|
|
|
5
5
|
export const say_msg: ActionConfig = {
|
|
6
6
|
name: 'Say Message',
|
|
7
7
|
group: ACTION_GROUPS.send,
|
|
8
|
+
flowTypes: [FlowTypes.VOICE],
|
|
8
9
|
render: (_node: Node, _action: SayMsg) => {
|
|
9
10
|
// This will need to be implemented based on the actual render logic
|
|
10
11
|
return html`<div>Say Message</div>`;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { html } from 'lit-html';
|
|
2
|
-
import { ActionConfig, ACTION_GROUPS, FormData } from '../types';
|
|
2
|
+
import { ActionConfig, ACTION_GROUPS, FormData, FlowTypes } from '../types';
|
|
3
3
|
import { Node, SendBroadcast } from '../../store/flow-definition';
|
|
4
4
|
import { renderStringList } from '../utils';
|
|
5
5
|
import { Icon } from '../../Icons';
|
|
@@ -7,6 +7,7 @@ import { Icon } from '../../Icons';
|
|
|
7
7
|
export const send_broadcast: ActionConfig = {
|
|
8
8
|
name: 'Send Broadcast',
|
|
9
9
|
group: ACTION_GROUPS.broadcast,
|
|
10
|
+
flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
|
|
10
11
|
render: (_node: Node, action: SendBroadcast) => {
|
|
11
12
|
const recipients = [
|
|
12
13
|
...(action.contacts || []).map((c) => c.name),
|
|
@@ -3,7 +3,8 @@ import {
|
|
|
3
3
|
ActionConfig,
|
|
4
4
|
ACTION_GROUPS,
|
|
5
5
|
FormData,
|
|
6
|
-
ValidationResult
|
|
6
|
+
ValidationResult,
|
|
7
|
+
FlowTypes
|
|
7
8
|
} from '../types';
|
|
8
9
|
import { Node, SendEmail } from '../../store/flow-definition';
|
|
9
10
|
import { renderStringList } from '../utils';
|
|
@@ -12,6 +13,7 @@ import { Icon } from '../../Icons';
|
|
|
12
13
|
export const send_email: ActionConfig = {
|
|
13
14
|
name: 'Send Email',
|
|
14
15
|
group: ACTION_GROUPS.broadcast,
|
|
16
|
+
flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
|
|
15
17
|
render: (_node: Node, action: SendEmail) => {
|
|
16
18
|
return html`<div>
|
|
17
19
|
<div>${renderStringList(action.addresses, Icon.email)}</div>
|
|
@@ -4,7 +4,8 @@ import {
|
|
|
4
4
|
ActionConfig,
|
|
5
5
|
ACTION_GROUPS,
|
|
6
6
|
FormData,
|
|
7
|
-
ValidationResult
|
|
7
|
+
ValidationResult,
|
|
8
|
+
FlowTypes
|
|
8
9
|
} from '../types';
|
|
9
10
|
import { Node, SendMsg } from '../../store/flow-definition';
|
|
10
11
|
import { titleCase } from '../../utils';
|
|
@@ -12,13 +13,14 @@ import { titleCase } from '../../utils';
|
|
|
12
13
|
export const send_msg: ActionConfig = {
|
|
13
14
|
name: 'Send Message',
|
|
14
15
|
group: ACTION_GROUPS.send,
|
|
16
|
+
flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
|
|
15
17
|
render: (_node: Node, action: SendMsg) => {
|
|
16
18
|
const text = action.text.replace(/\n/g, '<br>');
|
|
17
19
|
return html`
|
|
18
20
|
${unsafeHTML(text)}
|
|
19
|
-
${action.quick_replies?.length > 0
|
|
21
|
+
${(action.quick_replies || [])?.length > 0
|
|
20
22
|
? html`<div class="quick-replies">
|
|
21
|
-
${action.quick_replies.map((reply) => {
|
|
23
|
+
${(action.quick_replies || []).map((reply) => {
|
|
22
24
|
return html`<div class="quick-reply">${reply}</div>`;
|
|
23
25
|
})}
|
|
24
26
|
${action.template
|
|
@@ -225,5 +227,134 @@ export const send_msg: ActionConfig = {
|
|
|
225
227
|
valid: Object.keys(errors).length === 0,
|
|
226
228
|
errors
|
|
227
229
|
};
|
|
230
|
+
},
|
|
231
|
+
localizable: ['text', 'quick_replies', 'attachments'],
|
|
232
|
+
toLocalizationFormData: (
|
|
233
|
+
action: SendMsg,
|
|
234
|
+
localization: Record<string, any>
|
|
235
|
+
) => {
|
|
236
|
+
// Convert localized values to form data format
|
|
237
|
+
// Localized values are stored as arrays even for single values
|
|
238
|
+
const formData: FormData = {
|
|
239
|
+
uuid: action.uuid
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
// Handle text (single value, but stored as array in localization)
|
|
243
|
+
if (localization.text && Array.isArray(localization.text)) {
|
|
244
|
+
formData.text = localization.text[0] || '';
|
|
245
|
+
} else {
|
|
246
|
+
// Fall back to empty string if no localization
|
|
247
|
+
formData.text = '';
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Handle attachments (already an array)
|
|
251
|
+
if (localization.attachments && Array.isArray(localization.attachments)) {
|
|
252
|
+
formData.attachments = localization.attachments;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Handle quick_replies (already an array)
|
|
256
|
+
if (
|
|
257
|
+
localization.quick_replies &&
|
|
258
|
+
Array.isArray(localization.quick_replies)
|
|
259
|
+
) {
|
|
260
|
+
formData.quick_replies = localization.quick_replies.map((reply) => ({
|
|
261
|
+
name: reply,
|
|
262
|
+
value: reply
|
|
263
|
+
}));
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Extract runtime attachments from localized attachments
|
|
267
|
+
const runtimeAttachments: {
|
|
268
|
+
type: { name: string; value: string };
|
|
269
|
+
expression: string;
|
|
270
|
+
}[] = [];
|
|
271
|
+
const staticAttachments: string[] = [];
|
|
272
|
+
|
|
273
|
+
if (formData.attachments && Array.isArray(formData.attachments)) {
|
|
274
|
+
formData.attachments.forEach((attachment) => {
|
|
275
|
+
if (typeof attachment === 'string' && attachment.includes(':')) {
|
|
276
|
+
const colonIndex = attachment.indexOf(':');
|
|
277
|
+
const contentType = attachment.substring(0, colonIndex);
|
|
278
|
+
const value = attachment.substring(colonIndex + 1);
|
|
279
|
+
|
|
280
|
+
if (!contentType.includes('/')) {
|
|
281
|
+
runtimeAttachments.push({
|
|
282
|
+
type: { name: titleCase(contentType), value: contentType },
|
|
283
|
+
expression: value
|
|
284
|
+
});
|
|
285
|
+
} else {
|
|
286
|
+
staticAttachments.push(attachment);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
formData.attachments = staticAttachments;
|
|
293
|
+
formData.runtime_attachments = runtimeAttachments;
|
|
294
|
+
|
|
295
|
+
return formData;
|
|
296
|
+
},
|
|
297
|
+
fromLocalizationFormData: (formData: FormData, action: SendMsg) => {
|
|
298
|
+
// Convert form data to localization format
|
|
299
|
+
// All values must be stored as arrays
|
|
300
|
+
const localization: Record<string, any> = {};
|
|
301
|
+
|
|
302
|
+
// Handle text (store as single-element array)
|
|
303
|
+
// Only save if not empty and different from base action
|
|
304
|
+
if (formData.text && formData.text.trim() !== '') {
|
|
305
|
+
if (formData.text !== action.text) {
|
|
306
|
+
localization.text = [formData.text];
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Handle quick_replies (store as array)
|
|
311
|
+
const quickReplies = (formData.quick_replies || [])
|
|
312
|
+
.map((reply: any) =>
|
|
313
|
+
typeof reply === 'string' ? reply : reply.value || reply.name || reply
|
|
314
|
+
)
|
|
315
|
+
.filter((reply: string) => reply && reply.trim() !== '');
|
|
316
|
+
|
|
317
|
+
// Only save if there are quick replies and different from base action
|
|
318
|
+
if (quickReplies.length > 0) {
|
|
319
|
+
if (
|
|
320
|
+
JSON.stringify(quickReplies) !==
|
|
321
|
+
JSON.stringify(action.quick_replies || [])
|
|
322
|
+
) {
|
|
323
|
+
localization.quick_replies = quickReplies;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// Handle attachments (combine static and runtime attachments)
|
|
328
|
+
const staticAttachments = (formData.attachments || []).filter(
|
|
329
|
+
(att: string) => att && att.trim() !== ''
|
|
330
|
+
);
|
|
331
|
+
const runtimeAttachments = (formData.runtime_attachments || [])
|
|
332
|
+
.filter(
|
|
333
|
+
(item: {
|
|
334
|
+
type: [{ name: string; value: string }];
|
|
335
|
+
expression: string;
|
|
336
|
+
}) =>
|
|
337
|
+
item && item.type && item.expression && item.expression.trim() !== ''
|
|
338
|
+
)
|
|
339
|
+
.map(
|
|
340
|
+
(item: {
|
|
341
|
+
type: [{ name: string; value: string }];
|
|
342
|
+
expression: string;
|
|
343
|
+
}) => `${item.type[0].value}:${item.expression}`
|
|
344
|
+
);
|
|
345
|
+
|
|
346
|
+
const allAttachments = [...staticAttachments, ...runtimeAttachments];
|
|
347
|
+
|
|
348
|
+
// Only save if there are attachments and different from base action
|
|
349
|
+
if (allAttachments.length > 0) {
|
|
350
|
+
if (
|
|
351
|
+
JSON.stringify(allAttachments) !==
|
|
352
|
+
JSON.stringify(action.attachments || [])
|
|
353
|
+
) {
|
|
354
|
+
localization.attachments = allAttachments;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
return localization;
|
|
228
359
|
}
|
|
229
360
|
};
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { html } from 'lit-html';
|
|
2
|
-
import { ActionConfig, ACTION_GROUPS } from '../types';
|
|
2
|
+
import { ActionConfig, ACTION_GROUPS, FlowTypes } from '../types';
|
|
3
3
|
import { Node, SetContactChannel } from '../../store/flow-definition';
|
|
4
4
|
|
|
5
5
|
export const set_contact_channel: ActionConfig = {
|
|
6
6
|
name: 'Update Channel',
|
|
7
7
|
group: ACTION_GROUPS.contacts,
|
|
8
|
+
flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
|
|
8
9
|
render: (_node: Node, action: SetContactChannel) => {
|
|
9
10
|
return html`<div>Set to <strong>${action.channel.name}</strong></div>`;
|
|
10
11
|
},
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { html } from 'lit-html';
|
|
2
|
-
import { ActionConfig, ACTION_GROUPS, FormData } from '../types';
|
|
2
|
+
import { ActionConfig, ACTION_GROUPS, FormData, FlowTypes } from '../types';
|
|
3
3
|
import { Node, SetContactField } from '../../store/flow-definition';
|
|
4
4
|
|
|
5
5
|
export const set_contact_field: ActionConfig = {
|
|
6
6
|
name: 'Update Field',
|
|
7
7
|
group: ACTION_GROUPS.contacts,
|
|
8
|
+
flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
|
|
8
9
|
render: (_node: Node, action: SetContactField) => {
|
|
9
10
|
if (action.value) {
|
|
10
11
|
return html`<div>
|
|
@@ -3,7 +3,8 @@ import {
|
|
|
3
3
|
ActionConfig,
|
|
4
4
|
ACTION_GROUPS,
|
|
5
5
|
FormData,
|
|
6
|
-
ValidationResult
|
|
6
|
+
ValidationResult,
|
|
7
|
+
FlowTypes
|
|
7
8
|
} from '../types';
|
|
8
9
|
import { Node, SetContactLanguage } from '../../store/flow-definition';
|
|
9
10
|
import { getStore } from '../../store/Store';
|
|
@@ -11,6 +12,7 @@ import { getStore } from '../../store/Store';
|
|
|
11
12
|
export const set_contact_language: ActionConfig = {
|
|
12
13
|
name: 'Update Language',
|
|
13
14
|
group: ACTION_GROUPS.contacts,
|
|
15
|
+
flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
|
|
14
16
|
render: (_node: Node, action: SetContactLanguage) => {
|
|
15
17
|
const languageNames = new Intl.DisplayNames(['en'], {
|
|
16
18
|
type: 'language'
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { html } from 'lit-html';
|
|
2
|
-
import { ActionConfig, ACTION_GROUPS, FormData } from '../types';
|
|
2
|
+
import { ActionConfig, ACTION_GROUPS, FormData, FlowTypes } from '../types';
|
|
3
3
|
import { Node, SetContactName } from '../../store/flow-definition';
|
|
4
4
|
|
|
5
5
|
export const set_contact_name: ActionConfig = {
|
|
6
6
|
name: 'Update Name',
|
|
7
7
|
group: ACTION_GROUPS.contacts,
|
|
8
|
+
flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
|
|
8
9
|
render: (_node: Node, action: SetContactName) => {
|
|
9
10
|
return html`<div>Set to <strong>${action.name}</strong></div>`;
|
|
10
11
|
},
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { html } from 'lit-html';
|
|
2
|
-
import { ActionConfig, ACTION_GROUPS, FormData } from '../types';
|
|
2
|
+
import { ActionConfig, ACTION_GROUPS, FormData, FlowTypes } from '../types';
|
|
3
3
|
import { Node, SetContactStatus } from '../../store/flow-definition';
|
|
4
4
|
import { titleCase } from '../../utils';
|
|
5
5
|
|
|
6
6
|
export const set_contact_status: ActionConfig = {
|
|
7
7
|
name: 'Update Status',
|
|
8
8
|
group: ACTION_GROUPS.contacts,
|
|
9
|
+
flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
|
|
9
10
|
render: (_node: Node, action: SetContactStatus) => {
|
|
10
11
|
return html`<div>Set to <strong>${titleCase(action.status)}</strong></div>`;
|
|
11
12
|
},
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { html } from 'lit-html';
|
|
2
|
-
import { ActionConfig, ACTION_GROUPS, FormData } from '../types';
|
|
2
|
+
import { ActionConfig, ACTION_GROUPS, FormData, FlowTypes } from '../types';
|
|
3
3
|
import { Node, SetRunResult } from '../../store/flow-definition';
|
|
4
4
|
import { getStore } from '../../store/Store';
|
|
5
5
|
|
|
6
6
|
export const set_run_result: ActionConfig = {
|
|
7
7
|
name: 'Save Flow Result',
|
|
8
8
|
group: ACTION_GROUPS.save,
|
|
9
|
+
flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
|
|
9
10
|
render: (_node: Node, action: SetRunResult) => {
|
|
10
11
|
return html`<div>
|
|
11
12
|
Save <strong>${action.value}</strong> as <strong>${action.name}</strong>
|
|
@@ -3,7 +3,8 @@ import {
|
|
|
3
3
|
ActionConfig,
|
|
4
4
|
ACTION_GROUPS,
|
|
5
5
|
FormData,
|
|
6
|
-
ValidationResult
|
|
6
|
+
ValidationResult,
|
|
7
|
+
FlowTypes
|
|
7
8
|
} from '../types';
|
|
8
9
|
import { Node, StartSession } from '../../store/flow-definition';
|
|
9
10
|
import { renderNamedObjects } from '../utils';
|
|
@@ -11,6 +12,7 @@ import { renderNamedObjects } from '../utils';
|
|
|
11
12
|
export const start_session: ActionConfig = {
|
|
12
13
|
name: 'Start Flow',
|
|
13
14
|
group: ACTION_GROUPS.broadcast,
|
|
15
|
+
flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
|
|
14
16
|
render: (_node: Node, action: StartSession) => {
|
|
15
17
|
const hasGroups = action.groups && action.groups.length > 0;
|
|
16
18
|
const hasContacts = action.contacts && action.contacts.length > 0;
|
package/src/flow/config.ts
CHANGED
|
@@ -36,19 +36,16 @@ import { split_by_webhook } from './nodes/split_by_webhook';
|
|
|
36
36
|
import { split_by_resthook } from './nodes/split_by_resthook';
|
|
37
37
|
import { split_by_llm } from './nodes/split_by_llm';
|
|
38
38
|
import { split_by_llm_categorize } from './nodes/split_by_llm_categorize';
|
|
39
|
-
import { wait_for_audio } from './nodes/wait_for_audio';
|
|
40
39
|
import { wait_for_digits } from './nodes/wait_for_digits';
|
|
41
|
-
import { wait_for_image } from './nodes/wait_for_image';
|
|
42
|
-
import { wait_for_location } from './nodes/wait_for_location';
|
|
43
40
|
import { wait_for_menu } from './nodes/wait_for_menu';
|
|
44
41
|
import { wait_for_response } from './nodes/wait_for_response';
|
|
45
|
-
import { wait_for_video } from './nodes/wait_for_video';
|
|
46
42
|
|
|
47
43
|
export const ACTION_CONFIG: {
|
|
48
44
|
[key: string]: ActionConfig;
|
|
49
45
|
} = {
|
|
46
|
+
say_msg,
|
|
47
|
+
play_audio,
|
|
50
48
|
set_contact_field,
|
|
51
|
-
|
|
52
49
|
send_broadcast,
|
|
53
50
|
set_run_result,
|
|
54
51
|
send_msg,
|
|
@@ -60,8 +57,6 @@ export const ACTION_CONFIG: {
|
|
|
60
57
|
set_contact_channel,
|
|
61
58
|
set_contact_language,
|
|
62
59
|
set_contact_status,
|
|
63
|
-
say_msg,
|
|
64
|
-
play_audio,
|
|
65
60
|
add_contact_urn,
|
|
66
61
|
add_input_labels,
|
|
67
62
|
request_optin
|
|
@@ -71,7 +66,6 @@ export const NODE_CONFIG: {
|
|
|
71
66
|
[key: string]: NodeConfig;
|
|
72
67
|
} = {
|
|
73
68
|
execute_actions,
|
|
74
|
-
|
|
75
69
|
split_by_contact_field,
|
|
76
70
|
split_by_expression,
|
|
77
71
|
split_by_groups,
|
|
@@ -84,12 +78,8 @@ export const NODE_CONFIG: {
|
|
|
84
78
|
split_by_ticket,
|
|
85
79
|
split_by_webhook,
|
|
86
80
|
split_by_resthook,
|
|
87
|
-
wait_for_audio,
|
|
88
81
|
wait_for_digits,
|
|
89
|
-
wait_for_image,
|
|
90
|
-
wait_for_location,
|
|
91
82
|
wait_for_menu,
|
|
92
83
|
wait_for_response,
|
|
93
|
-
wait_for_video,
|
|
94
84
|
split_by_airtime
|
|
95
85
|
};
|
package/src/flow/nodes/shared.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { TextFieldConfig } from '../types';
|
|
1
|
+
import { FormData, TextFieldConfig } from '../types';
|
|
2
|
+
import { Node } from '../../store/flow-definition';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Shared result_name field configuration for router nodes.
|
|
@@ -16,3 +17,71 @@ export const resultNameField: TextFieldConfig = {
|
|
|
16
17
|
helpText: 'The name to use to reference this result in the flow',
|
|
17
18
|
optionalLink: 'Save result as...'
|
|
18
19
|
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Shared category localization functions for router nodes.
|
|
23
|
+
* These provide a consistent way to localize category names across all router types.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Converts a node's categories to localization form data.
|
|
28
|
+
* @param node - The node containing categories to localize
|
|
29
|
+
* @param localization - The existing localization data for this language
|
|
30
|
+
* @returns Form data with category UUIDs mapped to original and localized names
|
|
31
|
+
*/
|
|
32
|
+
export function categoriesToLocalizationFormData(
|
|
33
|
+
node: Node,
|
|
34
|
+
localization: Record<string, any>
|
|
35
|
+
): FormData {
|
|
36
|
+
const categories = node.router?.categories || [];
|
|
37
|
+
const localizationData: Record<string, any> = {};
|
|
38
|
+
|
|
39
|
+
categories.forEach((category: any) => {
|
|
40
|
+
const categoryUuid = category.uuid;
|
|
41
|
+
const categoryLocalization = localization[categoryUuid];
|
|
42
|
+
|
|
43
|
+
localizationData[categoryUuid] = {
|
|
44
|
+
originalName: category.name,
|
|
45
|
+
localizedName:
|
|
46
|
+
categoryLocalization && categoryLocalization.name
|
|
47
|
+
? Array.isArray(categoryLocalization.name)
|
|
48
|
+
? categoryLocalization.name[0] || ''
|
|
49
|
+
: categoryLocalization.name
|
|
50
|
+
: ''
|
|
51
|
+
};
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
categories: localizationData
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Converts localization form data back to the localization structure.
|
|
61
|
+
* @param formData - The form data containing category localizations
|
|
62
|
+
* @param _node - The original node (reserved for future validation)
|
|
63
|
+
* @returns Record mapping category UUIDs to their localization data
|
|
64
|
+
*/
|
|
65
|
+
export function localizationFormDataToCategories(
|
|
66
|
+
formData: FormData,
|
|
67
|
+
_node: Node
|
|
68
|
+
): Record<string, any> {
|
|
69
|
+
const localizationData: Record<string, any> = {};
|
|
70
|
+
|
|
71
|
+
if (formData.categories) {
|
|
72
|
+
Object.keys(formData.categories).forEach((categoryUuid) => {
|
|
73
|
+
const categoryData = formData.categories[categoryUuid];
|
|
74
|
+
const localizedName = categoryData.localizedName?.trim() || '';
|
|
75
|
+
const originalName = categoryData.originalName?.trim() || '';
|
|
76
|
+
|
|
77
|
+
// Only save if localized name is different from original and not empty
|
|
78
|
+
if (localizedName && localizedName !== originalName) {
|
|
79
|
+
localizationData[categoryUuid] = {
|
|
80
|
+
name: [localizedName]
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return localizationData;
|
|
87
|
+
}
|
|
@@ -1,14 +1,26 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
ACTION_GROUPS,
|
|
3
|
+
FormData,
|
|
4
|
+
NodeConfig,
|
|
5
|
+
FlowTypes,
|
|
6
|
+
Features
|
|
7
|
+
} from '../types';
|
|
2
8
|
import { TransferAirtime, Node } from '../../store/flow-definition';
|
|
3
9
|
import { generateUUID, createSuccessFailureRouter } from '../../utils';
|
|
4
10
|
import { html } from 'lit';
|
|
5
11
|
import { CURRENCY_OPTIONS, CURRENCIES } from '../currencies';
|
|
6
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
resultNameField,
|
|
14
|
+
categoriesToLocalizationFormData,
|
|
15
|
+
localizationFormDataToCategories
|
|
16
|
+
} from './shared';
|
|
7
17
|
|
|
8
18
|
export const split_by_airtime: NodeConfig = {
|
|
9
19
|
type: 'split_by_airtime',
|
|
10
20
|
name: 'Send Airtime',
|
|
11
21
|
group: ACTION_GROUPS.services,
|
|
22
|
+
flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
|
|
23
|
+
features: [Features.AIRTIME],
|
|
12
24
|
showAsAction: true,
|
|
13
25
|
form: {
|
|
14
26
|
amounts: {
|
|
@@ -238,5 +250,10 @@ export const split_by_airtime: NodeConfig = {
|
|
|
238
250
|
router: finalRouter,
|
|
239
251
|
exits: exits
|
|
240
252
|
};
|
|
241
|
-
}
|
|
253
|
+
},
|
|
254
|
+
|
|
255
|
+
// Localization support for categories
|
|
256
|
+
localizable: 'categories',
|
|
257
|
+
toLocalizationFormData: categoriesToLocalizationFormData,
|
|
258
|
+
fromLocalizationFormData: localizationFormDataToCategories
|
|
242
259
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SPLIT_GROUPS, FormData, NodeConfig } from '../types';
|
|
1
|
+
import { SPLIT_GROUPS, FormData, NodeConfig, FlowTypes } from '../types';
|
|
2
2
|
import { Node } from '../../store/flow-definition';
|
|
3
3
|
import { createRulesRouter } from '../../utils';
|
|
4
4
|
import {
|
|
@@ -6,7 +6,11 @@ import {
|
|
|
6
6
|
operatorsToSelectOptions,
|
|
7
7
|
getOperatorConfig
|
|
8
8
|
} from '../operators';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
resultNameField,
|
|
11
|
+
categoriesToLocalizationFormData,
|
|
12
|
+
localizationFormDataToCategories
|
|
13
|
+
} from './shared';
|
|
10
14
|
import {
|
|
11
15
|
createRulesArrayConfig,
|
|
12
16
|
extractUserRules,
|
|
@@ -44,6 +48,7 @@ export const split_by_contact_field: NodeConfig = {
|
|
|
44
48
|
type: 'split_by_contact_field',
|
|
45
49
|
name: 'Split by Contact Field',
|
|
46
50
|
group: SPLIT_GROUPS.split,
|
|
51
|
+
flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
|
|
47
52
|
dialogSize: 'large',
|
|
48
53
|
form: {
|
|
49
54
|
field: {
|
|
@@ -185,5 +190,10 @@ export const split_by_contact_field: NodeConfig = {
|
|
|
185
190
|
},
|
|
186
191
|
renderTitle: (node: Node, nodeUI?: any) => {
|
|
187
192
|
return html`<div>Split by ${nodeUI.config.operand.name}</div>`;
|
|
188
|
-
}
|
|
193
|
+
},
|
|
194
|
+
|
|
195
|
+
// Localization support for categories
|
|
196
|
+
localizable: 'categories',
|
|
197
|
+
toLocalizationFormData: categoriesToLocalizationFormData,
|
|
198
|
+
fromLocalizationFormData: localizationFormDataToCategories
|
|
189
199
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SPLIT_GROUPS, FormData, NodeConfig } from '../types';
|
|
1
|
+
import { SPLIT_GROUPS, FormData, NodeConfig, FlowTypes } from '../types';
|
|
2
2
|
import { Node } from '../../store/flow-definition';
|
|
3
3
|
import { createRulesRouter } from '../../utils';
|
|
4
4
|
import {
|
|
@@ -6,7 +6,11 @@ import {
|
|
|
6
6
|
operatorsToSelectOptions,
|
|
7
7
|
getOperatorConfig
|
|
8
8
|
} from '../operators';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
resultNameField,
|
|
11
|
+
categoriesToLocalizationFormData,
|
|
12
|
+
localizationFormDataToCategories
|
|
13
|
+
} from './shared';
|
|
10
14
|
import {
|
|
11
15
|
createRulesArrayConfig,
|
|
12
16
|
extractUserRules,
|
|
@@ -17,6 +21,7 @@ export const split_by_expression: NodeConfig = {
|
|
|
17
21
|
type: 'split_by_expression',
|
|
18
22
|
name: 'Split by Expression',
|
|
19
23
|
group: SPLIT_GROUPS.split,
|
|
24
|
+
flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
|
|
20
25
|
dialogSize: 'large',
|
|
21
26
|
form: {
|
|
22
27
|
operand: {
|
|
@@ -95,5 +100,10 @@ export const split_by_expression: NodeConfig = {
|
|
|
95
100
|
router: finalRouter,
|
|
96
101
|
exits: exits
|
|
97
102
|
};
|
|
98
|
-
}
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
// Localization support for categories
|
|
106
|
+
localizable: 'categories',
|
|
107
|
+
toLocalizationFormData: categoriesToLocalizationFormData,
|
|
108
|
+
fromLocalizationFormData: localizationFormDataToCategories
|
|
99
109
|
};
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import { SPLIT_GROUPS, FormData, NodeConfig } from '../types';
|
|
1
|
+
import { SPLIT_GROUPS, FormData, NodeConfig, FlowTypes } from '../types';
|
|
2
2
|
import { Node, Category, Exit, Case } from '../../store/flow-definition.d';
|
|
3
3
|
import { generateUUID } from '../../utils';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
resultNameField,
|
|
6
|
+
categoriesToLocalizationFormData,
|
|
7
|
+
localizationFormDataToCategories
|
|
8
|
+
} from './shared';
|
|
5
9
|
|
|
6
10
|
// Helper function to create a switch router with group cases
|
|
7
11
|
const createGroupRouter = (
|
|
@@ -94,6 +98,7 @@ export const split_by_groups: NodeConfig = {
|
|
|
94
98
|
type: 'split_by_groups',
|
|
95
99
|
name: 'Split by Group',
|
|
96
100
|
group: SPLIT_GROUPS.split,
|
|
101
|
+
flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
|
|
97
102
|
form: {
|
|
98
103
|
groups: {
|
|
99
104
|
type: 'select',
|
|
@@ -197,5 +202,10 @@ export const split_by_groups: NodeConfig = {
|
|
|
197
202
|
router: {
|
|
198
203
|
type: 'switch',
|
|
199
204
|
operand: '@contact.groups'
|
|
200
|
-
}
|
|
205
|
+
},
|
|
206
|
+
|
|
207
|
+
// Localization support for categories
|
|
208
|
+
localizable: 'categories',
|
|
209
|
+
toLocalizationFormData: categoriesToLocalizationFormData,
|
|
210
|
+
fromLocalizationFormData: localizationFormDataToCategories
|
|
201
211
|
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { NodeConfig, ACTION_GROUPS } from '../types';
|
|
1
|
+
import { NodeConfig, ACTION_GROUPS, FlowTypes } from '../types';
|
|
2
2
|
|
|
3
3
|
export const split_by_llm_categorize: NodeConfig = {
|
|
4
4
|
type: 'split_by_intent',
|
|
5
5
|
name: 'Call classifier',
|
|
6
|
-
group: ACTION_GROUPS.services
|
|
6
|
+
group: ACTION_GROUPS.services,
|
|
7
|
+
flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND]
|
|
7
8
|
};
|
|
@@ -1,12 +1,24 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
ACTION_GROUPS,
|
|
3
|
+
FormData,
|
|
4
|
+
NodeConfig,
|
|
5
|
+
FlowTypes,
|
|
6
|
+
Features
|
|
7
|
+
} from '../types';
|
|
2
8
|
import { CallLLM, Node } from '../../store/flow-definition';
|
|
3
9
|
import { generateUUID, createSuccessFailureRouter } from '../../utils';
|
|
4
10
|
import { html } from 'lit';
|
|
11
|
+
import {
|
|
12
|
+
categoriesToLocalizationFormData,
|
|
13
|
+
localizationFormDataToCategories
|
|
14
|
+
} from './shared';
|
|
5
15
|
|
|
6
16
|
export const split_by_llm: NodeConfig = {
|
|
7
17
|
type: 'split_by_llm',
|
|
8
18
|
name: 'Call AI',
|
|
9
19
|
group: ACTION_GROUPS.services,
|
|
20
|
+
flowTypes: [FlowTypes.VOICE, FlowTypes.MESSAGE, FlowTypes.BACKGROUND],
|
|
21
|
+
features: [Features.AI],
|
|
10
22
|
showAsAction: true,
|
|
11
23
|
render: (node: Node) => {
|
|
12
24
|
const callLlmAction = node.actions?.find(
|
|
@@ -117,5 +129,10 @@ export const split_by_llm: NodeConfig = {
|
|
|
117
129
|
router: router,
|
|
118
130
|
exits: exits
|
|
119
131
|
};
|
|
120
|
-
}
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
// Localization support for categories
|
|
135
|
+
localizable: 'categories',
|
|
136
|
+
toLocalizationFormData: categoriesToLocalizationFormData,
|
|
137
|
+
fromLocalizationFormData: localizationFormDataToCategories
|
|
121
138
|
};
|