@nyaruka/temba-components 0.138.6 → 0.140.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/cla.yml +1 -1
- package/.github/workflows/copilot-setup-steps.yml +6 -1
- package/CHANGELOG.md +26 -0
- package/demo/data/flows/sample-flow.json +24 -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 +2 -11
- 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 +1112 -882
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/display/Chat.js +10 -7
- package/out-tsc/src/display/Chat.js.map +1 -1
- package/out-tsc/src/display/Dropdown.js +3 -1
- package/out-tsc/src/display/Dropdown.js.map +1 -1
- package/out-tsc/src/display/FloatingTab.js +25 -32
- package/out-tsc/src/display/FloatingTab.js.map +1 -1
- package/out-tsc/src/display/Thumbnail.js +163 -5
- package/out-tsc/src/display/Thumbnail.js.map +1 -1
- package/out-tsc/src/flow/CanvasMenu.js +5 -3
- package/out-tsc/src/flow/CanvasMenu.js.map +1 -1
- package/out-tsc/src/flow/CanvasNode.js +70 -29
- package/out-tsc/src/flow/CanvasNode.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +290 -239
- package/out-tsc/src/flow/Editor.js.map +1 -1
- package/out-tsc/src/flow/NodeEditor.js +118 -10
- package/out-tsc/src/flow/NodeEditor.js.map +1 -1
- package/out-tsc/src/flow/Plumber.js +757 -403
- package/out-tsc/src/flow/Plumber.js.map +1 -1
- package/out-tsc/src/flow/StickyNote.js +13 -4
- package/out-tsc/src/flow/StickyNote.js.map +1 -1
- package/out-tsc/src/flow/actions/audio-player.js +112 -0
- package/out-tsc/src/flow/actions/audio-player.js.map +1 -0
- package/out-tsc/src/flow/actions/enter_flow.js +43 -0
- package/out-tsc/src/flow/actions/enter_flow.js.map +1 -0
- package/out-tsc/src/flow/actions/play_audio.js +57 -4
- package/out-tsc/src/flow/actions/play_audio.js.map +1 -1
- package/out-tsc/src/flow/actions/say_msg.js +86 -3
- package/out-tsc/src/flow/actions/say_msg.js.map +1 -1
- package/out-tsc/src/flow/config.js +11 -3
- package/out-tsc/src/flow/config.js.map +1 -1
- package/out-tsc/src/flow/nodes/shared-rules.js +1 -1
- package/out-tsc/src/flow/nodes/shared-rules.js.map +1 -1
- package/out-tsc/src/flow/nodes/terminal.js +7 -0
- package/out-tsc/src/flow/nodes/terminal.js.map +1 -0
- package/out-tsc/src/flow/nodes/wait_for_audio.js +77 -0
- package/out-tsc/src/flow/nodes/wait_for_audio.js.map +1 -0
- package/out-tsc/src/flow/nodes/wait_for_dial.js +151 -0
- package/out-tsc/src/flow/nodes/wait_for_dial.js.map +1 -0
- package/out-tsc/src/flow/nodes/wait_for_digits.js +61 -1
- package/out-tsc/src/flow/nodes/wait_for_digits.js.map +1 -1
- package/out-tsc/src/flow/nodes/wait_for_menu.js +173 -2
- package/out-tsc/src/flow/nodes/wait_for_menu.js.map +1 -1
- package/out-tsc/src/flow/operators.js +21 -5
- package/out-tsc/src/flow/operators.js.map +1 -1
- package/out-tsc/src/flow/types.js.map +1 -1
- package/out-tsc/src/flow/utils.js +213 -65
- package/out-tsc/src/flow/utils.js.map +1 -1
- package/out-tsc/src/form/ArrayEditor.js +4 -2
- package/out-tsc/src/form/ArrayEditor.js.map +1 -1
- package/out-tsc/src/form/FieldRenderer.js +49 -0
- package/out-tsc/src/form/FieldRenderer.js.map +1 -1
- package/out-tsc/src/interfaces.js +2 -0
- package/out-tsc/src/interfaces.js.map +1 -1
- package/out-tsc/src/layout/Dialog.js +52 -7
- package/out-tsc/src/layout/Dialog.js.map +1 -1
- package/out-tsc/src/list/TicketList.js +4 -1
- package/out-tsc/src/list/TicketList.js.map +1 -1
- package/out-tsc/src/live/TembaChart.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 +2 -11
- 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/simulator/Simulator.js +10 -3
- package/out-tsc/src/simulator/Simulator.js.map +1 -1
- package/out-tsc/src/store/AppState.js +89 -3
- package/out-tsc/src/store/AppState.js.map +1 -1
- package/out-tsc/test/actions/play_audio.test.js +118 -0
- package/out-tsc/test/actions/play_audio.test.js.map +1 -0
- package/out-tsc/test/actions/say_msg.test.js +158 -0
- package/out-tsc/test/actions/say_msg.test.js.map +1 -0
- package/out-tsc/test/nodes/wait_for_audio.test.js +156 -0
- package/out-tsc/test/nodes/wait_for_audio.test.js.map +1 -0
- package/out-tsc/test/nodes/wait_for_dial.test.js +336 -0
- package/out-tsc/test/nodes/wait_for_dial.test.js.map +1 -0
- package/out-tsc/test/nodes/wait_for_digits.test.js +198 -84
- package/out-tsc/test/nodes/wait_for_digits.test.js.map +1 -1
- package/out-tsc/test/nodes/wait_for_menu.test.js +340 -0
- package/out-tsc/test/nodes/wait_for_menu.test.js.map +1 -0
- package/out-tsc/test/temba-floating-tab.test.js +4 -6
- package/out-tsc/test/temba-floating-tab.test.js.map +1 -1
- package/out-tsc/test/temba-flow-collision.test.js +473 -220
- package/out-tsc/test/temba-flow-collision.test.js.map +1 -1
- package/out-tsc/test/temba-flow-editor.test.js +0 -2
- package/out-tsc/test/temba-flow-editor.test.js.map +1 -1
- package/out-tsc/test/temba-flow-plumber-connections.test.js +83 -84
- package/out-tsc/test/temba-flow-plumber-connections.test.js.map +1 -1
- package/out-tsc/test/temba-flow-plumber.test.js +102 -93
- package/out-tsc/test/temba-flow-plumber.test.js.map +1 -1
- package/out-tsc/test/temba-node-type-selector.test.js +6 -6
- package/out-tsc/test/temba-node-type-selector.test.js.map +1 -1
- package/package.json +1 -1
- package/screenshots/truth/actions/play_audio/editor/expression-url.png +0 -0
- package/screenshots/truth/actions/play_audio/editor/static-url.png +0 -0
- package/screenshots/truth/actions/play_audio/render/expression-url.png +0 -0
- package/screenshots/truth/actions/play_audio/render/static-url.png +0 -0
- package/screenshots/truth/actions/say_msg/editor/multiline-text.png +0 -0
- package/screenshots/truth/actions/say_msg/editor/simple-text.png +0 -0
- package/screenshots/truth/actions/say_msg/editor/text-with-audio-url.png +0 -0
- package/screenshots/truth/actions/say_msg/render/multiline-text.png +0 -0
- package/screenshots/truth/actions/say_msg/render/simple-text.png +0 -0
- package/screenshots/truth/actions/say_msg/render/text-with-audio-url.png +0 -0
- package/screenshots/truth/editor/router.png +0 -0
- package/screenshots/truth/editor/wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_audio/editor/basic-audio-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_audio/render/basic-audio-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_dial/editor/basic-dial.png +0 -0
- package/screenshots/truth/nodes/wait_for_dial/editor/dial-with-limits.png +0 -0
- package/screenshots/truth/nodes/wait_for_dial/render/basic-dial.png +0 -0
- package/screenshots/truth/nodes/wait_for_dial/render/dial-with-limits.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/digits-with-rules.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/digits-with-rules.png +0 -0
- package/screenshots/truth/nodes/wait_for_menu/editor/menu-with-digits.png +0 -0
- package/screenshots/truth/nodes/wait_for_menu/render/menu-with-digits.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/basic-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/custom-result-name.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/no-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/short-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/basic-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/custom-result-name.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/no-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/render/short-timeout.png +0 -0
- package/src/display/Chat.ts +13 -7
- package/src/display/Dropdown.ts +3 -1
- package/src/display/FloatingTab.ts +24 -33
- package/src/display/Thumbnail.ts +162 -2
- package/src/flow/CanvasMenu.ts +8 -3
- package/src/flow/CanvasNode.ts +75 -30
- package/src/flow/Editor.ts +336 -288
- package/src/flow/NodeEditor.ts +137 -9
- package/src/flow/Plumber.ts +1011 -457
- package/src/flow/StickyNote.ts +14 -4
- package/src/flow/actions/audio-player.ts +127 -0
- package/src/flow/actions/enter_flow.ts +44 -0
- package/src/flow/actions/play_audio.ts +64 -5
- package/src/flow/actions/say_msg.ts +94 -4
- package/src/flow/config.ts +11 -3
- package/src/flow/nodes/shared-rules.ts +1 -1
- package/src/flow/nodes/terminal.ts +9 -0
- package/src/flow/nodes/wait_for_audio.ts +88 -0
- package/src/flow/nodes/wait_for_dial.ts +176 -0
- package/src/flow/nodes/wait_for_digits.ts +86 -2
- package/src/flow/nodes/wait_for_menu.ts +209 -3
- package/src/flow/operators.ts +23 -5
- package/src/flow/types.ts +23 -1
- package/src/flow/utils.ts +238 -81
- package/src/form/ArrayEditor.ts +4 -2
- package/src/form/FieldRenderer.ts +64 -1
- package/src/interfaces.ts +3 -1
- package/src/layout/Dialog.ts +53 -7
- package/src/list/TicketList.ts +4 -1
- package/src/live/TembaChart.ts +1 -1
- package/src/locales/es.ts +13 -18
- package/src/locales/fr.ts +13 -18
- package/src/locales/locale-codes.ts +2 -11
- package/src/locales/pt.ts +13 -18
- package/src/simulator/Simulator.ts +13 -3
- package/src/store/AppState.ts +105 -1
- package/src/store/flow-definition.d.ts +2 -0
- package/test/actions/play_audio.test.ts +155 -0
- package/test/actions/say_msg.test.ts +196 -0
- package/test/nodes/wait_for_audio.test.ts +182 -0
- package/test/nodes/wait_for_dial.test.ts +382 -0
- package/test/nodes/wait_for_digits.test.ts +233 -109
- package/test/nodes/wait_for_menu.test.ts +383 -0
- package/test/temba-floating-tab.test.ts +4 -6
- package/test/temba-flow-collision.test.ts +495 -293
- package/test/temba-flow-editor.test.ts +0 -2
- package/test/temba-flow-plumber-connections.test.ts +97 -97
- package/test/temba-flow-plumber.test.ts +116 -103
- package/test/temba-node-type-selector.test.ts +6 -6
- 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/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/src/flow/NodeEditor.ts
CHANGED
|
@@ -20,9 +20,10 @@ import {
|
|
|
20
20
|
} from './types';
|
|
21
21
|
import { CustomEventType } from '../interfaces';
|
|
22
22
|
import { generateUUID } from '../utils';
|
|
23
|
+
import { formatIssueMessage } from './utils';
|
|
23
24
|
import { FieldRenderer } from '../form/FieldRenderer';
|
|
24
25
|
import { renderMarkdownInline } from '../markdown';
|
|
25
|
-
import { AppState, fromStore, zustand } from '../store/AppState';
|
|
26
|
+
import { AppState, FlowIssue, fromStore, zustand } from '../store/AppState';
|
|
26
27
|
import { getStore } from '../store/Store';
|
|
27
28
|
|
|
28
29
|
export class NodeEditor extends RapidElement {
|
|
@@ -55,6 +56,19 @@ export class NodeEditor extends RapidElement {
|
|
|
55
56
|
margin-top: 15px;
|
|
56
57
|
}
|
|
57
58
|
|
|
59
|
+
.issue-warning {
|
|
60
|
+
display: flex;
|
|
61
|
+
align-items: center;
|
|
62
|
+
gap: 8px;
|
|
63
|
+
color: var(--color-error, tomato);
|
|
64
|
+
font-size: 13px;
|
|
65
|
+
cursor: pointer;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.issue-warning:hover .issue-text {
|
|
69
|
+
text-decoration: underline;
|
|
70
|
+
}
|
|
71
|
+
|
|
58
72
|
.form-actions {
|
|
59
73
|
display: flex;
|
|
60
74
|
gap: 10px;
|
|
@@ -112,12 +126,29 @@ export class NodeEditor extends RapidElement {
|
|
|
112
126
|
color: var(--color-label, #777);
|
|
113
127
|
}
|
|
114
128
|
|
|
129
|
+
.form-row-inline-label {
|
|
130
|
+
font-size: 20px;
|
|
131
|
+
font-weight: 300;
|
|
132
|
+
color: #ccc;
|
|
133
|
+
min-width: 20px;
|
|
134
|
+
text-align: center;
|
|
135
|
+
display: flex;
|
|
136
|
+
align-items: center;
|
|
137
|
+
justify-content: center;
|
|
138
|
+
user-select: none;
|
|
139
|
+
}
|
|
140
|
+
|
|
115
141
|
.form-row-help {
|
|
116
142
|
font-size: 12px;
|
|
117
143
|
color: #666;
|
|
118
144
|
margin-top: 6px;
|
|
119
145
|
}
|
|
120
146
|
|
|
147
|
+
.form-text {
|
|
148
|
+
color: #666;
|
|
149
|
+
font-size: 13px;
|
|
150
|
+
}
|
|
151
|
+
|
|
121
152
|
.form-group {
|
|
122
153
|
border: 1px solid #e0e0e0;
|
|
123
154
|
border-radius: 6px;
|
|
@@ -381,6 +412,9 @@ export class NodeEditor extends RapidElement {
|
|
|
381
412
|
@property({ type: Object })
|
|
382
413
|
nodeUI?: NodeUI;
|
|
383
414
|
|
|
415
|
+
@property({ attribute: false })
|
|
416
|
+
dialogOrigin?: { x: number; y: number };
|
|
417
|
+
|
|
384
418
|
@property({ type: Boolean })
|
|
385
419
|
isOpen: boolean = false;
|
|
386
420
|
|
|
@@ -411,6 +445,12 @@ export class NodeEditor extends RapidElement {
|
|
|
411
445
|
@fromStore(zustand, (state: AppState) => state.flowDefinition)
|
|
412
446
|
private flowDefinition!: FlowDefinition;
|
|
413
447
|
|
|
448
|
+
@fromStore(zustand, (state: AppState) => state.issuesByNode)
|
|
449
|
+
private issuesByNode!: Map<string, FlowIssue[]>;
|
|
450
|
+
|
|
451
|
+
@fromStore(zustand, (state: AppState) => state.issuesByAction)
|
|
452
|
+
private issuesByAction!: Map<string, FlowIssue[]>;
|
|
453
|
+
|
|
414
454
|
connectedCallback(): void {
|
|
415
455
|
super.connectedCallback();
|
|
416
456
|
this.initializeFormData();
|
|
@@ -447,7 +487,13 @@ export class NodeEditor extends RapidElement {
|
|
|
447
487
|
private initializeFormData(): void {
|
|
448
488
|
const nodeConfig = this.getNodeConfig();
|
|
449
489
|
|
|
450
|
-
|
|
490
|
+
// Temporary: terminal nodes defer to action configs, same as execute_actions
|
|
491
|
+
if (
|
|
492
|
+
(!nodeConfig ||
|
|
493
|
+
nodeConfig.type === 'execute_actions' ||
|
|
494
|
+
nodeConfig.type === 'terminal') &&
|
|
495
|
+
this.action
|
|
496
|
+
) {
|
|
451
497
|
// Action editing mode - use action config
|
|
452
498
|
const actionConfig = ACTION_CONFIG[this.action.type];
|
|
453
499
|
|
|
@@ -597,8 +643,13 @@ export class NodeEditor extends RapidElement {
|
|
|
597
643
|
if (this.node && this.nodeUI) {
|
|
598
644
|
const nodeConfig = this.getNodeConfig();
|
|
599
645
|
|
|
600
|
-
//
|
|
601
|
-
|
|
646
|
+
// Temporary: terminal nodes defer to action configs for editing, same as execute_actions
|
|
647
|
+
// For execute_actions/terminal nodes, defer to action editing if an action is selected
|
|
648
|
+
if (
|
|
649
|
+
(this.nodeUI.type === 'execute_actions' ||
|
|
650
|
+
this.nodeUI.type === ('terminal' as any)) &&
|
|
651
|
+
this.action
|
|
652
|
+
) {
|
|
602
653
|
return ACTION_CONFIG[this.action.type] || null;
|
|
603
654
|
}
|
|
604
655
|
|
|
@@ -1462,6 +1513,11 @@ export class NodeEditor extends RapidElement {
|
|
|
1462
1513
|
} else if (fieldName && config.type === 'message-editor') {
|
|
1463
1514
|
// Special handling for message editor
|
|
1464
1515
|
this.handleMessageEditorChange(fieldName, e);
|
|
1516
|
+
} else if (fieldName && config.type === 'media') {
|
|
1517
|
+
// Extract URL from media picker's attachment
|
|
1518
|
+
const picker = e.target as any;
|
|
1519
|
+
const url = picker.attachments?.[0]?.url || '';
|
|
1520
|
+
this.handleNewFieldChange(fieldName, url);
|
|
1465
1521
|
} else {
|
|
1466
1522
|
// Default handling for most field types
|
|
1467
1523
|
this.handleFormFieldChange(fieldName, e);
|
|
@@ -1575,6 +1631,12 @@ export class NodeEditor extends RapidElement {
|
|
|
1575
1631
|
case 'group':
|
|
1576
1632
|
return this.renderGroup(item, config, renderedFields);
|
|
1577
1633
|
|
|
1634
|
+
case 'spacer':
|
|
1635
|
+
return html``;
|
|
1636
|
+
|
|
1637
|
+
case 'text':
|
|
1638
|
+
return html`<div class="form-text">${item.text}</div>`;
|
|
1639
|
+
|
|
1578
1640
|
default:
|
|
1579
1641
|
return html``;
|
|
1580
1642
|
}
|
|
@@ -1585,7 +1647,14 @@ export class NodeEditor extends RapidElement {
|
|
|
1585
1647
|
config: ActionConfig | NodeConfig,
|
|
1586
1648
|
renderedFields: Set<string>
|
|
1587
1649
|
): TemplateResult {
|
|
1588
|
-
const {
|
|
1650
|
+
const {
|
|
1651
|
+
items,
|
|
1652
|
+
gap = '1rem',
|
|
1653
|
+
label,
|
|
1654
|
+
helpText,
|
|
1655
|
+
inlineLabels,
|
|
1656
|
+
marginBottom
|
|
1657
|
+
} = rowConfig;
|
|
1589
1658
|
|
|
1590
1659
|
// Collect all fields from this row for width calculations
|
|
1591
1660
|
const fieldsInRow = this.collectFieldsFromItems(items);
|
|
@@ -1619,8 +1688,18 @@ export class NodeEditor extends RapidElement {
|
|
|
1619
1688
|
});
|
|
1620
1689
|
|
|
1621
1690
|
const rowContent = html`
|
|
1622
|
-
<div
|
|
1691
|
+
<div
|
|
1692
|
+
class="form-row"
|
|
1693
|
+
style="display: flex; gap: ${gap};${marginBottom
|
|
1694
|
+
? ` margin-bottom: ${marginBottom};`
|
|
1695
|
+
: ''}"
|
|
1696
|
+
>
|
|
1623
1697
|
${items.map((item) => {
|
|
1698
|
+
// Spacer items render as empty flex children
|
|
1699
|
+
if (typeof item !== 'string' && item.type === 'spacer') {
|
|
1700
|
+
return html`<div style="flex: 1 1 0;"></div>`;
|
|
1701
|
+
}
|
|
1702
|
+
|
|
1624
1703
|
// Get the field name from the item
|
|
1625
1704
|
const fieldName =
|
|
1626
1705
|
typeof item === 'string'
|
|
@@ -1641,10 +1720,22 @@ export class NodeEditor extends RapidElement {
|
|
|
1641
1720
|
renderedFields
|
|
1642
1721
|
);
|
|
1643
1722
|
|
|
1723
|
+
// When inlineLabels is provided, render the label inline to the left
|
|
1724
|
+
const inlineLabel =
|
|
1725
|
+
inlineLabels && fieldName ? inlineLabels[fieldName] : null;
|
|
1726
|
+
|
|
1644
1727
|
// Wrap in a div with flex style if we have a flex style
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1728
|
+
if (flexStyle) {
|
|
1729
|
+
return inlineLabel
|
|
1730
|
+
? html`<div
|
|
1731
|
+
style="${flexStyle} display: flex; align-items: center; gap: 0.35rem;"
|
|
1732
|
+
>
|
|
1733
|
+
<span class="form-row-inline-label">${inlineLabel}</span>
|
|
1734
|
+
<div style="flex: 1 1 0; min-width: 0;">${itemContent}</div>
|
|
1735
|
+
</div>`
|
|
1736
|
+
: html`<div style="${flexStyle}">${itemContent}</div>`;
|
|
1737
|
+
}
|
|
1738
|
+
return itemContent;
|
|
1648
1739
|
})}
|
|
1649
1740
|
</div>
|
|
1650
1741
|
`;
|
|
@@ -2038,6 +2129,40 @@ export class NodeEditor extends RapidElement {
|
|
|
2038
2129
|
`;
|
|
2039
2130
|
}
|
|
2040
2131
|
|
|
2132
|
+
private handleIssueClick(issue: FlowIssue): void {
|
|
2133
|
+
this.fireCustomEvent(CustomEventType.ShowIssue, { issue });
|
|
2134
|
+
}
|
|
2135
|
+
|
|
2136
|
+
private renderIssueWarnings(): TemplateResult | string {
|
|
2137
|
+
const issues: FlowIssue[] = [];
|
|
2138
|
+
|
|
2139
|
+
// Check for action-level issues
|
|
2140
|
+
if (this.action && this.issuesByAction?.has(this.action.uuid)) {
|
|
2141
|
+
issues.push(...this.issuesByAction.get(this.action.uuid));
|
|
2142
|
+
}
|
|
2143
|
+
|
|
2144
|
+
// Check for node-level issues (issues without action_uuid)
|
|
2145
|
+
if (this.node && this.issuesByNode?.has(this.node.uuid)) {
|
|
2146
|
+
issues.push(...this.issuesByNode.get(this.node.uuid));
|
|
2147
|
+
}
|
|
2148
|
+
|
|
2149
|
+
if (issues.length === 0) return '';
|
|
2150
|
+
|
|
2151
|
+
return html`
|
|
2152
|
+
${issues.map(
|
|
2153
|
+
(issue) => html`
|
|
2154
|
+
<div
|
|
2155
|
+
class="issue-warning"
|
|
2156
|
+
@click=${() => this.handleIssueClick(issue)}
|
|
2157
|
+
>
|
|
2158
|
+
<temba-icon name="alert_warning" size="1.2"></temba-icon>
|
|
2159
|
+
<span class="issue-text">${formatIssueMessage(issue)}</span>
|
|
2160
|
+
</div>
|
|
2161
|
+
`
|
|
2162
|
+
)}
|
|
2163
|
+
`;
|
|
2164
|
+
}
|
|
2165
|
+
|
|
2041
2166
|
render(): TemplateResult {
|
|
2042
2167
|
if (!this.isOpen) {
|
|
2043
2168
|
return html``;
|
|
@@ -2061,6 +2186,8 @@ export class NodeEditor extends RapidElement {
|
|
|
2061
2186
|
<temba-dialog
|
|
2062
2187
|
header="${header}"
|
|
2063
2188
|
.open="${this.isOpen}"
|
|
2189
|
+
.originX=${this.dialogOrigin?.x ?? null}
|
|
2190
|
+
.originY=${this.dialogOrigin?.y ?? null}
|
|
2064
2191
|
@temba-button-clicked=${this.handleDialogButtonClick}
|
|
2065
2192
|
primaryButtonName="Save"
|
|
2066
2193
|
cancelButtonName="Cancel"
|
|
@@ -2072,6 +2199,7 @@ export class NodeEditor extends RapidElement {
|
|
|
2072
2199
|
${this.getNodeConfig()?.router?.configurable
|
|
2073
2200
|
? this.renderRouterSection()
|
|
2074
2201
|
: null}
|
|
2202
|
+
${this.renderIssueWarnings()}
|
|
2075
2203
|
</div>
|
|
2076
2204
|
|
|
2077
2205
|
<div slot="gutter">${this.renderGutter()}</div>
|