@nyaruka/temba-components 0.137.0 → 0.138.4
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 +0 -9
- package/.devcontainer/devcontainer.json +8 -3
- package/.github/workflows/build.yml +6 -1
- package/.github/workflows/cla.yml +1 -1
- package/.github/workflows/publish.yml +6 -1
- package/CHANGELOG.md +42 -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 +445 -278
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/display/FloatingTab.js +16 -8
- package/out-tsc/src/display/FloatingTab.js.map +1 -1
- package/out-tsc/src/flow/CanvasMenu.js +33 -15
- package/out-tsc/src/flow/CanvasMenu.js.map +1 -1
- package/out-tsc/src/flow/CanvasNode.js +49 -24
- package/out-tsc/src/flow/CanvasNode.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +583 -70
- package/out-tsc/src/flow/Editor.js.map +1 -1
- package/out-tsc/src/flow/NodeTypeSelector.js +13 -11
- package/out-tsc/src/flow/NodeTypeSelector.js.map +1 -1
- package/out-tsc/src/flow/Plumber.js +110 -64
- package/out-tsc/src/flow/Plumber.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_field.js +5 -1
- package/out-tsc/src/flow/actions/set_contact_field.js.map +1 -1
- package/out-tsc/src/list/RunList.js +2 -1
- package/out-tsc/src/list/RunList.js.map +1 -1
- package/out-tsc/src/list/TicketList.js +2 -1
- package/out-tsc/src/list/TicketList.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/simulator/Simulator.js +11 -4
- package/out-tsc/src/simulator/Simulator.js.map +1 -1
- package/out-tsc/src/store/AppState.js +17 -2
- package/out-tsc/src/store/AppState.js.map +1 -1
- package/out-tsc/test/temba-contact-fields.test.js +3 -3
- package/out-tsc/test/temba-contact-fields.test.js.map +1 -1
- package/out-tsc/test/temba-flow-editor-node.test.js +3 -1
- package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
- package/out-tsc/test/temba-flow-editor-revisions.test.js +106 -0
- package/out-tsc/test/temba-flow-editor-revisions.test.js.map +1 -0
- package/out-tsc/test/temba-flow-editor.test.js +14 -10
- package/out-tsc/test/temba-flow-editor.test.js.map +1 -1
- package/out-tsc/test/temba-flow-plumber-connections.test.js +7 -1
- package/out-tsc/test/temba-flow-plumber-connections.test.js.map +1 -1
- package/out-tsc/test/temba-flow-plumber.test.js +6 -0
- package/out-tsc/test/temba-flow-plumber.test.js.map +1 -1
- package/out-tsc/test/temba-select.test.js +1 -0
- package/out-tsc/test/temba-select.test.js.map +1 -1
- package/package.json +1 -1
- package/screenshots/truth/floating-tab/gray.png +0 -0
- package/screenshots/truth/floating-tab/green.png +0 -0
- package/screenshots/truth/floating-tab/purple.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/src/display/FloatingTab.ts +18 -8
- package/src/flow/CanvasMenu.ts +38 -16
- package/src/flow/CanvasNode.ts +62 -29
- package/src/flow/Editor.ts +699 -74
- package/src/flow/NodeTypeSelector.ts +13 -11
- package/src/flow/Plumber.ts +123 -69
- package/src/flow/actions/set_contact_field.ts +5 -1
- package/src/list/RunList.ts +2 -1
- package/src/list/TicketList.ts +2 -1
- 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/simulator/Simulator.ts +11 -5
- package/src/store/AppState.ts +18 -2
- package/test/temba-contact-fields.test.ts +8 -3
- package/test/temba-flow-editor-node.test.ts +3 -1
- package/test/temba-flow-editor-revisions.test.ts +134 -0
- package/test/temba-flow-editor.test.ts +16 -10
- package/test/temba-flow-plumber-connections.test.ts +7 -1
- package/test/temba-flow-plumber.test.ts +6 -0
- package/test/temba-select.test.ts +1 -0
package/src/flow/CanvasNode.ts
CHANGED
|
@@ -33,6 +33,9 @@ export class CanvasNode extends RapidElement {
|
|
|
33
33
|
@fromStore(zustand, (state: AppState) => state.languageCode)
|
|
34
34
|
private languageCode!: string;
|
|
35
35
|
|
|
36
|
+
@fromStore(zustand, (state: AppState) => state.viewingRevision)
|
|
37
|
+
private viewingRevision!: boolean;
|
|
38
|
+
|
|
36
39
|
@fromStore(zustand, (state: AppState) => state.flowDefinition)
|
|
37
40
|
private flowDefinition!: any;
|
|
38
41
|
|
|
@@ -49,6 +52,8 @@ export class CanvasNode extends RapidElement {
|
|
|
49
52
|
// Track exits that are in "removing" state
|
|
50
53
|
private exitRemovalTimeouts: Map<string, number> = new Map();
|
|
51
54
|
|
|
55
|
+
private connectionTimeout: number | null = null;
|
|
56
|
+
|
|
52
57
|
// Set of exit UUIDs that are in the removing state
|
|
53
58
|
private exitRemovingState: Set<string> = new Set();
|
|
54
59
|
|
|
@@ -91,11 +96,8 @@ export class CanvasNode extends RapidElement {
|
|
|
91
96
|
box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
|
|
92
97
|
min-width: 200px;
|
|
93
98
|
border-radius: var(--curvature);
|
|
94
|
-
|
|
95
99
|
color: #333;
|
|
96
|
-
cursor: move;
|
|
97
100
|
user-select: none;
|
|
98
|
-
|
|
99
101
|
}
|
|
100
102
|
|
|
101
103
|
/* Flow start indicator */
|
|
@@ -178,7 +180,7 @@ export class CanvasNode extends RapidElement {
|
|
|
178
180
|
opacity: 1;
|
|
179
181
|
}
|
|
180
182
|
|
|
181
|
-
.
|
|
183
|
+
.read-only-hidden {
|
|
182
184
|
visibility: hidden !important;
|
|
183
185
|
pointer-events: none !important;
|
|
184
186
|
}
|
|
@@ -373,6 +375,12 @@ export class CanvasNode extends RapidElement {
|
|
|
373
375
|
.exit.connected:hover {
|
|
374
376
|
background-color: var(--color-connectors, #e6e6e6);
|
|
375
377
|
}
|
|
378
|
+
|
|
379
|
+
.exit.connected.read-only, .exit.connected.read-only:hover {
|
|
380
|
+
background-color: #fff;
|
|
381
|
+
pointer-events: none !important;
|
|
382
|
+
cursor: default;
|
|
383
|
+
}
|
|
376
384
|
|
|
377
385
|
.exit.removing, .exit.removing:hover {
|
|
378
386
|
background-color: var(--color-error);
|
|
@@ -530,23 +538,31 @@ export class CanvasNode extends RapidElement {
|
|
|
530
538
|
if (changes.has('node')) {
|
|
531
539
|
// Only proceed if plumber is available (for tests that don't set it up)
|
|
532
540
|
if (this.plumber) {
|
|
533
|
-
|
|
541
|
+
if (this.connectionTimeout) {
|
|
542
|
+
clearTimeout(this.connectionTimeout);
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
// Pass exit IDs explicitly to avoid DOM querying dependency
|
|
546
|
+
const exitIds = this.node.exits.map((e) => e.uuid);
|
|
547
|
+
this.plumber.removeNodeConnections(this.node.uuid, exitIds);
|
|
548
|
+
|
|
534
549
|
// make our initial connections
|
|
535
|
-
for
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
// so make our source endpoint
|
|
550
|
+
// We use setTimeout to allow for DOM updates to complete before querying for exits
|
|
551
|
+
this.connectionTimeout = window.setTimeout(() => {
|
|
552
|
+
for (const exit of this.node.exits) {
|
|
539
553
|
this.plumber.makeSource(exit.uuid);
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
554
|
+
if (exit.destination_uuid) {
|
|
555
|
+
this.plumber.connectIds(
|
|
556
|
+
this.node.uuid,
|
|
557
|
+
exit.uuid,
|
|
558
|
+
exit.destination_uuid
|
|
559
|
+
);
|
|
560
|
+
}
|
|
546
561
|
}
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
562
|
+
// Note: revalidation is handled by plumber's processPendingConnections which calls repaintEverything
|
|
563
|
+
this.connectionTimeout = null;
|
|
564
|
+
this.plumber.revalidate([this.node.uuid]);
|
|
565
|
+
}, 0);
|
|
550
566
|
}
|
|
551
567
|
|
|
552
568
|
const ele = this.parentElement;
|
|
@@ -564,6 +580,15 @@ export class CanvasNode extends RapidElement {
|
|
|
564
580
|
}
|
|
565
581
|
|
|
566
582
|
disconnectedCallback() {
|
|
583
|
+
// Force cleanup of connections for this node
|
|
584
|
+
if (this.plumber && this.node) {
|
|
585
|
+
if (this.connectionTimeout) {
|
|
586
|
+
clearTimeout(this.connectionTimeout);
|
|
587
|
+
this.connectionTimeout = null;
|
|
588
|
+
}
|
|
589
|
+
this.plumber.forgetNode(this.node.uuid);
|
|
590
|
+
}
|
|
591
|
+
|
|
567
592
|
// Remove the event listener when the component is removed
|
|
568
593
|
super.disconnectedCallback();
|
|
569
594
|
|
|
@@ -604,12 +629,19 @@ export class CanvasNode extends RapidElement {
|
|
|
604
629
|
// Clear the removing state
|
|
605
630
|
this.exitRemovingState.clear();
|
|
606
631
|
this.actionRemovingState.clear();
|
|
632
|
+
|
|
633
|
+
// only proceed if plumber is available (for tests that don't set it up)
|
|
634
|
+
if (this.plumber) {
|
|
635
|
+
this.plumber.removeNodeConnections(
|
|
636
|
+
this.node.uuid,
|
|
637
|
+
this.node.exits.map((e) => e.uuid)
|
|
638
|
+
);
|
|
639
|
+
}
|
|
607
640
|
}
|
|
608
641
|
|
|
609
642
|
private handleExitClick(event: MouseEvent, exit: Exit) {
|
|
610
643
|
event.preventDefault();
|
|
611
644
|
event.stopPropagation();
|
|
612
|
-
|
|
613
645
|
const exitId = exit.uuid;
|
|
614
646
|
|
|
615
647
|
// If exit is not connected, do nothing
|
|
@@ -1282,23 +1314,19 @@ export class CanvasNode extends RapidElement {
|
|
|
1282
1314
|
return html`<div class="cn-title" style="background:${color}">
|
|
1283
1315
|
${this.ui?.type === 'execute_actions'
|
|
1284
1316
|
? html`<temba-icon
|
|
1285
|
-
class="drag-handle ${this.
|
|
1286
|
-
? 'translating-hidden'
|
|
1287
|
-
: ''}"
|
|
1317
|
+
class="drag-handle ${this.isReadOnly() ? 'read-only-hidden' : ''}"
|
|
1288
1318
|
name="sort"
|
|
1289
1319
|
></temba-icon>`
|
|
1290
1320
|
: this.node?.actions?.length > 1
|
|
1291
1321
|
? html`<temba-icon
|
|
1292
|
-
class="drag-handle ${this.
|
|
1293
|
-
? 'translating-hidden'
|
|
1294
|
-
: ''}"
|
|
1322
|
+
class="drag-handle ${this.isReadOnly() ? 'read-only-hidden' : ''}"
|
|
1295
1323
|
name="sort"
|
|
1296
1324
|
></temba-icon>`
|
|
1297
1325
|
: html`<div class="title-spacer"></div>`}
|
|
1298
1326
|
|
|
1299
1327
|
<div class="name">${isRemoving ? 'Remove?' : config.name}</div>
|
|
1300
1328
|
<div
|
|
1301
|
-
class="remove-button ${this.
|
|
1329
|
+
class="remove-button ${this.isReadOnly() ? 'read-only-hidden' : ''}"
|
|
1302
1330
|
@click=${(e: MouseEvent) =>
|
|
1303
1331
|
this.handleActionRemoveClick(e, action, index)}
|
|
1304
1332
|
title="Remove action"
|
|
@@ -1332,7 +1360,7 @@ export class CanvasNode extends RapidElement {
|
|
|
1332
1360
|
: html`${config.name}`}
|
|
1333
1361
|
</div>
|
|
1334
1362
|
<div
|
|
1335
|
-
class="remove-button ${this.
|
|
1363
|
+
class="remove-button ${this.isReadOnly() ? 'read-only-hidden' : ''}"
|
|
1336
1364
|
@click=${(e: MouseEvent) => this.handleNodeRemoveClick(e)}
|
|
1337
1365
|
title="Remove node"
|
|
1338
1366
|
>
|
|
@@ -1571,13 +1599,18 @@ export class CanvasNode extends RapidElement {
|
|
|
1571
1599
|
class=${getClasses({
|
|
1572
1600
|
exit: true,
|
|
1573
1601
|
connected: !!exit.destination_uuid,
|
|
1574
|
-
removing: this.exitRemovingState.has(exit.uuid)
|
|
1602
|
+
removing: this.exitRemovingState.has(exit.uuid),
|
|
1603
|
+
'read-only': this.isReadOnly()
|
|
1575
1604
|
})}
|
|
1576
1605
|
@click=${(e: MouseEvent) => this.handleExitClick(e, exit)}
|
|
1577
1606
|
></div>
|
|
1578
1607
|
</div>`;
|
|
1579
1608
|
}
|
|
1580
1609
|
|
|
1610
|
+
private isReadOnly(): boolean {
|
|
1611
|
+
return this.viewingRevision || this.isTranslating;
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1581
1614
|
public render() {
|
|
1582
1615
|
if (!this.node || !this.ui) {
|
|
1583
1616
|
return html`<div class="node">Loading...</div>`;
|
|
@@ -1666,7 +1699,7 @@ export class CanvasNode extends RapidElement {
|
|
|
1666
1699
|
(exit) => this.renderExit(exit)
|
|
1667
1700
|
)}
|
|
1668
1701
|
</div>`}
|
|
1669
|
-
${this.ui.type === 'execute_actions' && !this.
|
|
1702
|
+
${this.ui.type === 'execute_actions' && !this.isReadOnly()
|
|
1670
1703
|
? html`<div
|
|
1671
1704
|
class="add-action-button"
|
|
1672
1705
|
@click=${(e: MouseEvent) => this.handleAddActionClick(e)}
|