@nyaruka/temba-components 0.137.0 → 0.138.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/CHANGELOG.md +9 -0
- package/dist/temba-components.js +392 -258
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/display/FloatingTab.js +2 -2
- package/out-tsc/src/display/FloatingTab.js.map +1 -1
- package/out-tsc/src/flow/CanvasNode.js +45 -24
- package/out-tsc/src/flow/CanvasNode.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +305 -16
- package/out-tsc/src/flow/Editor.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/simulator/Simulator.js +11 -4
- package/out-tsc/src/simulator/Simulator.js.map +1 -1
- package/out-tsc/src/store/AppState.js +12 -2
- package/out-tsc/src/store/AppState.js.map +1 -1
- package/out-tsc/test/temba-flow-editor-node.test.js +2 -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/package.json +1 -1
- package/src/display/FloatingTab.ts +2 -2
- package/src/flow/CanvasNode.ts +54 -29
- package/src/flow/Editor.ts +357 -17
- package/src/flow/Plumber.ts +123 -69
- package/src/simulator/Simulator.ts +11 -5
- package/src/store/AppState.ts +13 -2
- package/test/temba-flow-editor-node.test.ts +2 -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
|
@@ -3,11 +3,11 @@ import { html } from 'lit-html';
|
|
|
3
3
|
import { css, unsafeCSS } from 'lit';
|
|
4
4
|
import { property, state } from 'lit/decorators.js';
|
|
5
5
|
import { getStore } from '../store/Store';
|
|
6
|
-
import { fromStore, zustand } from '../store/AppState';
|
|
6
|
+
import { fromStore, zustand, FLOW_SPEC_VERSION } from '../store/AppState';
|
|
7
7
|
import { RapidElement } from '../RapidElement';
|
|
8
8
|
import { repeat } from 'lit-html/directives/repeat.js';
|
|
9
9
|
import { CustomEventType } from '../interfaces';
|
|
10
|
-
import { generateUUID, postJSON } from '../utils';
|
|
10
|
+
import { generateUUID, postJSON, fetchResults, getClasses } from '../utils';
|
|
11
11
|
import { ACTION_CONFIG, NODE_CONFIG } from './config';
|
|
12
12
|
import { ACTION_GROUP_METADATA } from './types';
|
|
13
13
|
import { Plumber } from './Plumber';
|
|
@@ -110,6 +110,29 @@ export class Editor extends RapidElement {
|
|
|
110
110
|
transition: none !important;
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
#canvas.viewing-revision {
|
|
114
|
+
pointer-events: none;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
#canvas.read-only svg {
|
|
118
|
+
pointer-events: none;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
#grid.viewing-revision {
|
|
122
|
+
background-color: #fff9fc;
|
|
123
|
+
background-image: radial-gradient(
|
|
124
|
+
circle,
|
|
125
|
+
rgba(166, 38, 164, 0.2) 1px,
|
|
126
|
+
transparent 1px
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
#grid.viewing-revision temba-flow-node,
|
|
131
|
+
#grid.viewing-revision svg.jtk-connector,
|
|
132
|
+
#grid.viewing-revision .activity-overlay {
|
|
133
|
+
opacity: 0.5;
|
|
134
|
+
}
|
|
135
|
+
|
|
113
136
|
body .jtk-endpoint {
|
|
114
137
|
width: initial;
|
|
115
138
|
height: initial;
|
|
@@ -164,12 +187,28 @@ export class Editor extends RapidElement {
|
|
|
164
187
|
stroke-width: 3px;
|
|
165
188
|
}
|
|
166
189
|
|
|
190
|
+
body #canvas.read-only-connections svg.jtk-connector.jtk-hover path {
|
|
191
|
+
stroke: var(--color-connectors) !important;
|
|
192
|
+
}
|
|
193
|
+
|
|
167
194
|
body .plumb-connector.jtk-hover .plumb-arrow {
|
|
168
195
|
fill: var(--color-success) !important;
|
|
169
196
|
stroke-width: 0px;
|
|
170
197
|
z-index: 10;
|
|
171
198
|
}
|
|
172
199
|
|
|
200
|
+
body
|
|
201
|
+
#canvas.read-only-connections
|
|
202
|
+
.plumb-connector.jtk-hover
|
|
203
|
+
.plumb-arrow {
|
|
204
|
+
fill: var(--color-connectors) !important;
|
|
205
|
+
ponter-events: none;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
body #canvas.read-only-connections svg {
|
|
209
|
+
pointer-events: none;
|
|
210
|
+
}
|
|
211
|
+
|
|
173
212
|
/* Activity overlays on connections */
|
|
174
213
|
.jtk-overlay.activity-overlay {
|
|
175
214
|
background: #f3f3f3;
|
|
@@ -458,6 +497,18 @@ export class Editor extends RapidElement {
|
|
|
458
497
|
width: 100%;
|
|
459
498
|
}
|
|
460
499
|
|
|
500
|
+
.revert-button {
|
|
501
|
+
background: var(--color-primary-dark);
|
|
502
|
+
border: none;
|
|
503
|
+
color: #fff;
|
|
504
|
+
padding: 6px 10px;
|
|
505
|
+
border-radius: var(--curvature);
|
|
506
|
+
font-size: 11px;
|
|
507
|
+
font-weight: 600;
|
|
508
|
+
cursor: pointer;
|
|
509
|
+
transition: opacity 0.2s ease;
|
|
510
|
+
}
|
|
511
|
+
|
|
461
512
|
.auto-translate-button {
|
|
462
513
|
background: var(--color-primary-dark);
|
|
463
514
|
border: none;
|
|
@@ -544,6 +595,11 @@ export class Editor extends RapidElement {
|
|
|
544
595
|
this.autoTranslating = false;
|
|
545
596
|
this.autoTranslateModel = null;
|
|
546
597
|
this.autoTranslateError = null;
|
|
598
|
+
this.revisionsWindowHidden = true;
|
|
599
|
+
this.revisions = [];
|
|
600
|
+
this.viewingRevision = null;
|
|
601
|
+
this.isLoadingRevisions = false;
|
|
602
|
+
this.preRevertState = null;
|
|
547
603
|
this.translationCache = new Map();
|
|
548
604
|
// NodeEditor state - handles both node and action editing
|
|
549
605
|
this.editingNode = null;
|
|
@@ -693,10 +749,11 @@ export class Editor extends RapidElement {
|
|
|
693
749
|
}
|
|
694
750
|
}, SAVE_QUIET_TIME);
|
|
695
751
|
}
|
|
696
|
-
saveChanges() {
|
|
752
|
+
saveChanges(definitionOverride) {
|
|
753
|
+
const definition = definitionOverride || this.definition;
|
|
697
754
|
// post the flow definition to the server
|
|
698
|
-
getStore()
|
|
699
|
-
.postJSON(`/flow/revisions/${this.flow}/`,
|
|
755
|
+
return getStore()
|
|
756
|
+
.postJSON(`/flow/revisions/${this.flow}/`, definition)
|
|
700
757
|
.then((response) => {
|
|
701
758
|
var _b;
|
|
702
759
|
// Update flow info and revision with the response data
|
|
@@ -708,6 +765,10 @@ export class Editor extends RapidElement {
|
|
|
708
765
|
if (((_b = response.json.revision) === null || _b === void 0 ? void 0 : _b.revision) !== undefined) {
|
|
709
766
|
state.setRevision(response.json.revision.revision);
|
|
710
767
|
}
|
|
768
|
+
// if the revisions window is open, refresh the list
|
|
769
|
+
if (!this.revisionsWindowHidden) {
|
|
770
|
+
this.fetchRevisions();
|
|
771
|
+
}
|
|
711
772
|
}
|
|
712
773
|
})
|
|
713
774
|
.catch((error) => {
|
|
@@ -751,7 +812,7 @@ export class Editor extends RapidElement {
|
|
|
751
812
|
clearTimeout(this.activityTimer);
|
|
752
813
|
}
|
|
753
814
|
this.activityTimer = window.setTimeout(() => {
|
|
754
|
-
this.fetchActivityData();
|
|
815
|
+
// this.fetchActivityData();
|
|
755
816
|
}, this.activityInterval);
|
|
756
817
|
});
|
|
757
818
|
}
|
|
@@ -832,6 +893,8 @@ export class Editor extends RapidElement {
|
|
|
832
893
|
// ignore right clicks
|
|
833
894
|
if (event.button !== 0)
|
|
834
895
|
return;
|
|
896
|
+
if (this.isReadOnly())
|
|
897
|
+
return;
|
|
835
898
|
const element = event.currentTarget;
|
|
836
899
|
// Only start dragging if clicking on the element itself, not on exits or other interactive elements
|
|
837
900
|
const target = event.target;
|
|
@@ -893,6 +956,8 @@ export class Editor extends RapidElement {
|
|
|
893
956
|
}
|
|
894
957
|
handleCanvasMouseDown(event) {
|
|
895
958
|
var _b;
|
|
959
|
+
if (this.isReadOnly())
|
|
960
|
+
return;
|
|
896
961
|
const target = event.target;
|
|
897
962
|
if (target.id === 'canvas' || target.id === 'grid') {
|
|
898
963
|
// Ignore clicks on exits
|
|
@@ -954,6 +1019,7 @@ export class Editor extends RapidElement {
|
|
|
954
1019
|
// Clean up jsPlumb connections for nodes before removing them
|
|
955
1020
|
uuids.forEach((uuid) => {
|
|
956
1021
|
this.plumber.removeNodeConnections(uuid);
|
|
1022
|
+
this.plumber.removeAllEndpoints(uuid);
|
|
957
1023
|
});
|
|
958
1024
|
// Now remove them from the definition
|
|
959
1025
|
if (uuids.length > 0 && this.plumber) {
|
|
@@ -1372,6 +1438,10 @@ export class Editor extends RapidElement {
|
|
|
1372
1438
|
store.getState().expandCanvas(maxWidth, maxHeight);
|
|
1373
1439
|
}
|
|
1374
1440
|
handleCanvasContextMenu(event) {
|
|
1441
|
+
if (this.isReadOnly()) {
|
|
1442
|
+
event.preventDefault();
|
|
1443
|
+
return;
|
|
1444
|
+
}
|
|
1375
1445
|
// Check if we right-clicked on empty canvas space
|
|
1376
1446
|
const target = event.target;
|
|
1377
1447
|
if (target.id !== 'canvas') {
|
|
@@ -2048,6 +2118,7 @@ export class Editor extends RapidElement {
|
|
|
2048
2118
|
return;
|
|
2049
2119
|
}
|
|
2050
2120
|
this.localizationWindowHidden = false;
|
|
2121
|
+
this.revisionsWindowHidden = true;
|
|
2051
2122
|
const alreadySelected = languages.some((lang) => lang.code === this.languageCode);
|
|
2052
2123
|
if (!alreadySelected) {
|
|
2053
2124
|
this.handleLanguageChange(languages[0].code);
|
|
@@ -2255,6 +2326,199 @@ export class Editor extends RapidElement {
|
|
|
2255
2326
|
}
|
|
2256
2327
|
this.autoTranslating = false;
|
|
2257
2328
|
}
|
|
2329
|
+
handleRevisionsTabClick() {
|
|
2330
|
+
if (this.revisionsWindowHidden) {
|
|
2331
|
+
this.fetchRevisions();
|
|
2332
|
+
this.revisionsWindowHidden = false;
|
|
2333
|
+
this.localizationWindowHidden = true; // Close other window
|
|
2334
|
+
}
|
|
2335
|
+
}
|
|
2336
|
+
handleRevisionsWindowClosed() {
|
|
2337
|
+
this.resetRevisionsScroll();
|
|
2338
|
+
this.revisionsWindowHidden = true;
|
|
2339
|
+
if (this.viewingRevision) {
|
|
2340
|
+
this.handleCancelRevisionView();
|
|
2341
|
+
}
|
|
2342
|
+
}
|
|
2343
|
+
resetRevisionsScroll() {
|
|
2344
|
+
var _b;
|
|
2345
|
+
const list = (_b = this.querySelector('#revisions-window').shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('.body');
|
|
2346
|
+
if (list) {
|
|
2347
|
+
list.scrollTop = 0;
|
|
2348
|
+
}
|
|
2349
|
+
}
|
|
2350
|
+
async fetchRevisions() {
|
|
2351
|
+
this.isLoadingRevisions = true;
|
|
2352
|
+
try {
|
|
2353
|
+
const results = await fetchResults(`/flow/revisions/${this.flow}/?version=${FLOW_SPEC_VERSION}`);
|
|
2354
|
+
this.revisions = results.slice(1);
|
|
2355
|
+
}
|
|
2356
|
+
catch (e) {
|
|
2357
|
+
console.error('Error fetching revisions', e);
|
|
2358
|
+
}
|
|
2359
|
+
finally {
|
|
2360
|
+
this.isLoadingRevisions = false;
|
|
2361
|
+
}
|
|
2362
|
+
}
|
|
2363
|
+
async handleRevisionClick(revision) {
|
|
2364
|
+
var _b, _c;
|
|
2365
|
+
if (((_b = this.viewingRevision) === null || _b === void 0 ? void 0 : _b.id) === revision.id) {
|
|
2366
|
+
return;
|
|
2367
|
+
}
|
|
2368
|
+
if (!this.viewingRevision) {
|
|
2369
|
+
// Save current state first
|
|
2370
|
+
this.preRevertState = {
|
|
2371
|
+
definition: this.definition,
|
|
2372
|
+
dirtyDate: this.dirtyDate
|
|
2373
|
+
};
|
|
2374
|
+
}
|
|
2375
|
+
this.viewingRevision = revision;
|
|
2376
|
+
this.isLoadingRevisions = true;
|
|
2377
|
+
(_c = this.plumber) === null || _c === void 0 ? void 0 : _c.reset();
|
|
2378
|
+
try {
|
|
2379
|
+
await getStore()
|
|
2380
|
+
.getState()
|
|
2381
|
+
.fetchRevision(`/flow/revisions/${this.flow}`, revision.id.toString());
|
|
2382
|
+
}
|
|
2383
|
+
catch (e) {
|
|
2384
|
+
console.error('Error fetching revision details', e);
|
|
2385
|
+
this.handleCancelRevisionView();
|
|
2386
|
+
}
|
|
2387
|
+
finally {
|
|
2388
|
+
this.isLoadingRevisions = false;
|
|
2389
|
+
}
|
|
2390
|
+
}
|
|
2391
|
+
handleCancelRevisionView() {
|
|
2392
|
+
var _b;
|
|
2393
|
+
(_b = this.plumber) === null || _b === void 0 ? void 0 : _b.reset();
|
|
2394
|
+
if (this.preRevertState) {
|
|
2395
|
+
const currentInfo = getStore().getState().flowInfo;
|
|
2396
|
+
getStore().getState().setFlowContents({
|
|
2397
|
+
definition: this.preRevertState.definition,
|
|
2398
|
+
info: currentInfo
|
|
2399
|
+
});
|
|
2400
|
+
if (this.preRevertState.dirtyDate) {
|
|
2401
|
+
getStore().getState().setDirtyDate(this.preRevertState.dirtyDate);
|
|
2402
|
+
}
|
|
2403
|
+
}
|
|
2404
|
+
else {
|
|
2405
|
+
// Fallback if no pre-revert definition
|
|
2406
|
+
getStore().getState().fetchRevision(`/flow/revisions/${this.flow}`);
|
|
2407
|
+
}
|
|
2408
|
+
this.viewingRevision = null;
|
|
2409
|
+
this.preRevertState = null;
|
|
2410
|
+
}
|
|
2411
|
+
async handleRevertClick() {
|
|
2412
|
+
var _b;
|
|
2413
|
+
if (!this.viewingRevision || !this.preRevertState)
|
|
2414
|
+
return;
|
|
2415
|
+
(_b = this.plumber) === null || _b === void 0 ? void 0 : _b.reset();
|
|
2416
|
+
// Use the content of the viewing revision (this.definition)
|
|
2417
|
+
// but the revision number of the current head (preRevertState)
|
|
2418
|
+
// so the server accepts it as a valid update
|
|
2419
|
+
const definitionToSave = {
|
|
2420
|
+
...this.definition,
|
|
2421
|
+
revision: this.preRevertState.definition.revision
|
|
2422
|
+
};
|
|
2423
|
+
await this.saveChanges(definitionToSave);
|
|
2424
|
+
this.viewingRevision = null;
|
|
2425
|
+
this.preRevertState = null;
|
|
2426
|
+
this.revisionsWindowHidden = true;
|
|
2427
|
+
const revisionsWindow = document.getElementById('revisions-window');
|
|
2428
|
+
revisionsWindow.handleClose();
|
|
2429
|
+
// Refresh revisions list to show the new one
|
|
2430
|
+
this.fetchRevisions();
|
|
2431
|
+
// Fetch the latest version of the flow to ensure the store is up to date
|
|
2432
|
+
getStore().getState().fetchRevision(`/flow/revisions/${this.flow}`);
|
|
2433
|
+
}
|
|
2434
|
+
renderRevisionsTab() {
|
|
2435
|
+
return html `
|
|
2436
|
+
<temba-floating-tab
|
|
2437
|
+
id="revisions-tab"
|
|
2438
|
+
icon="revisions"
|
|
2439
|
+
label="Revisions"
|
|
2440
|
+
color="rgb(142, 94, 167)"
|
|
2441
|
+
top="105"
|
|
2442
|
+
.hidden=${!this.revisionsWindowHidden && this.localizationWindowHidden}
|
|
2443
|
+
@temba-button-clicked=${this.handleRevisionsTabClick}
|
|
2444
|
+
></temba-floating-tab>
|
|
2445
|
+
`;
|
|
2446
|
+
}
|
|
2447
|
+
renderRevisionsWindow() {
|
|
2448
|
+
return html `
|
|
2449
|
+
<temba-floating-window
|
|
2450
|
+
id="revisions-window"
|
|
2451
|
+
header="Revisions"
|
|
2452
|
+
.width=${360}
|
|
2453
|
+
.maxHeight=${600}
|
|
2454
|
+
.top=${75}
|
|
2455
|
+
color="rgb(142, 94, 167)"
|
|
2456
|
+
.hidden=${this.revisionsWindowHidden}
|
|
2457
|
+
@temba-dialog-hidden=${this.handleRevisionsWindowClosed}
|
|
2458
|
+
>
|
|
2459
|
+
<div class="localization-window-content">
|
|
2460
|
+
<div
|
|
2461
|
+
class="revisions-list"
|
|
2462
|
+
style="display:flex; flex-direction:column; gap:8px; overflow-y:auto; padding-bottom:10px;"
|
|
2463
|
+
>
|
|
2464
|
+
${this.isLoadingRevisions && !this.revisions.length
|
|
2465
|
+
? html `<temba-loading></temba-loading>`
|
|
2466
|
+
: this.revisions.map((rev) => {
|
|
2467
|
+
var _b;
|
|
2468
|
+
const isSelected = ((_b = this.viewingRevision) === null || _b === void 0 ? void 0 : _b.id) === rev.id;
|
|
2469
|
+
return html `
|
|
2470
|
+
<div
|
|
2471
|
+
class="revision-item ${isSelected ? 'selected' : ''}"
|
|
2472
|
+
style="padding:8px; border-radius:4px; cursor:pointer; background:${isSelected
|
|
2473
|
+
? '#f0f6ff' // Light blue bg for selected
|
|
2474
|
+
: '#f9fafb'}; border:1px solid ${isSelected ? '#a4cafe' : '#e5e7eb'}; transition: all 0.2s ease;"
|
|
2475
|
+
@click=${() => this.handleRevisionClick(rev)}
|
|
2476
|
+
>
|
|
2477
|
+
<div
|
|
2478
|
+
style="display:flex; justify-content:space-between; align-items:center;"
|
|
2479
|
+
>
|
|
2480
|
+
<div
|
|
2481
|
+
class="revision-header"
|
|
2482
|
+
style="margin-bottom: 2px;"
|
|
2483
|
+
>
|
|
2484
|
+
<div
|
|
2485
|
+
style="font-weight:600; font-size:13px; color:#111827;"
|
|
2486
|
+
>
|
|
2487
|
+
<temba-date value=${rev.created_on} display="duration"></temba-date>
|
|
2488
|
+
|
|
2489
|
+
</div>
|
|
2490
|
+
<div style="font-size:11px; color:#6b7280;">
|
|
2491
|
+
${rev.user.name || rev.user.username}
|
|
2492
|
+
</div>
|
|
2493
|
+
</div>
|
|
2494
|
+
${isSelected
|
|
2495
|
+
? html `<button
|
|
2496
|
+
class="revert-button"
|
|
2497
|
+
@click=${this.handleRevertClick}
|
|
2498
|
+
>
|
|
2499
|
+
Revert
|
|
2500
|
+
</button>`
|
|
2501
|
+
: html ``}
|
|
2502
|
+
|
|
2503
|
+
</button>
|
|
2504
|
+
</div>
|
|
2505
|
+
|
|
2506
|
+
${rev.comment
|
|
2507
|
+
? html `<div
|
|
2508
|
+
style="font-size:12px; color:#4b5563; margin-top:4px;"
|
|
2509
|
+
>
|
|
2510
|
+
${rev.comment}
|
|
2511
|
+
</div>`
|
|
2512
|
+
: ''}
|
|
2513
|
+
|
|
2514
|
+
</div>
|
|
2515
|
+
`;
|
|
2516
|
+
})}
|
|
2517
|
+
</div>
|
|
2518
|
+
</div>
|
|
2519
|
+
</temba-floating-window>
|
|
2520
|
+
`;
|
|
2521
|
+
}
|
|
2258
2522
|
renderLocalizationWindow() {
|
|
2259
2523
|
var _b, _c, _d;
|
|
2260
2524
|
const languages = this.getLocalizationLanguages();
|
|
@@ -2481,6 +2745,9 @@ export class Editor extends RapidElement {
|
|
|
2481
2745
|
behavior: 'smooth'
|
|
2482
2746
|
});
|
|
2483
2747
|
}
|
|
2748
|
+
isReadOnly() {
|
|
2749
|
+
return this.viewingRevision !== null || this.isTranslating;
|
|
2750
|
+
}
|
|
2484
2751
|
render() {
|
|
2485
2752
|
var _b, _c;
|
|
2486
2753
|
// we have to embed our own style since we are in light DOM
|
|
@@ -2489,17 +2756,24 @@ export class Editor extends RapidElement {
|
|
|
2489
2756
|
${unsafeCSS(CanvasNode.styles.cssText)}
|
|
2490
2757
|
</style>`;
|
|
2491
2758
|
const stickies = ((_c = (_b = this.definition) === null || _b === void 0 ? void 0 : _b._ui) === null || _c === void 0 ? void 0 : _c.stickies) || {};
|
|
2492
|
-
return html `${style} ${this.
|
|
2493
|
-
${this.renderAutoTranslateDialog()}
|
|
2759
|
+
return html `${style} ${this.renderRevisionsWindow()}
|
|
2760
|
+
${this.renderLocalizationWindow()} ${this.renderAutoTranslateDialog()}
|
|
2494
2761
|
<div id="editor">
|
|
2495
2762
|
<div
|
|
2496
2763
|
id="grid"
|
|
2764
|
+
class="${this.viewingRevision ? 'viewing-revision' : ''}"
|
|
2497
2765
|
style="min-width:100%;width:${this.canvasSize.width}px; height:${this
|
|
2498
2766
|
.canvasSize.height}px"
|
|
2499
2767
|
>
|
|
2500
|
-
<div
|
|
2768
|
+
<div
|
|
2769
|
+
id="canvas"
|
|
2770
|
+
class="${getClasses({
|
|
2771
|
+
'viewing-revision': !!this.viewingRevision,
|
|
2772
|
+
'read-only-connections': !!this.viewingRevision || this.isTranslating
|
|
2773
|
+
})}"
|
|
2774
|
+
>
|
|
2501
2775
|
${this.definition
|
|
2502
|
-
? repeat(this.definition.nodes, (node) => node.uuid, (node
|
|
2776
|
+
? repeat([...this.definition.nodes].sort((a, b) => a.uuid.localeCompare(b.uuid)), (node) => node.uuid, (node) => {
|
|
2503
2777
|
var _b, _c, _d;
|
|
2504
2778
|
const position = ((_c = (_b = this.definition._ui) === null || _b === void 0 ? void 0 : _b.nodes[node.uuid]) === null || _c === void 0 ? void 0 : _c.position) || {
|
|
2505
2779
|
left: 0,
|
|
@@ -2509,7 +2783,8 @@ export class Editor extends RapidElement {
|
|
|
2509
2783
|
((_d = this.currentDragItem) === null || _d === void 0 ? void 0 : _d.uuid) === node.uuid;
|
|
2510
2784
|
const selected = this.selectedItems.has(node.uuid);
|
|
2511
2785
|
// first node is the flow start (nodes are sorted by position)
|
|
2512
|
-
const isFlowStart =
|
|
2786
|
+
const isFlowStart = this.definition.nodes.length > 0 &&
|
|
2787
|
+
this.definition.nodes[0].uuid === node.uuid;
|
|
2513
2788
|
return html `<temba-flow-node
|
|
2514
2789
|
class="draggable ${dragging ? 'dragging' : ''} ${selected
|
|
2515
2790
|
? 'selected'
|
|
@@ -2561,11 +2836,13 @@ export class Editor extends RapidElement {
|
|
|
2561
2836
|
: ''}
|
|
2562
2837
|
|
|
2563
2838
|
<temba-canvas-menu></temba-canvas-menu>
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2839
|
+
${!this.viewingRevision
|
|
2840
|
+
? html `<temba-node-type-selector
|
|
2841
|
+
.flowType=${this.flowType}
|
|
2842
|
+
.features=${this.features}
|
|
2843
|
+
></temba-node-type-selector>`
|
|
2844
|
+
: ''}
|
|
2845
|
+
${this.renderRevisionsTab()} ${this.renderLocalizationTab()} `;
|
|
2569
2846
|
}
|
|
2570
2847
|
}
|
|
2571
2848
|
__decorate([
|
|
@@ -2652,6 +2929,18 @@ __decorate([
|
|
|
2652
2929
|
__decorate([
|
|
2653
2930
|
state()
|
|
2654
2931
|
], Editor.prototype, "autoTranslateError", void 0);
|
|
2932
|
+
__decorate([
|
|
2933
|
+
state()
|
|
2934
|
+
], Editor.prototype, "revisionsWindowHidden", void 0);
|
|
2935
|
+
__decorate([
|
|
2936
|
+
state()
|
|
2937
|
+
], Editor.prototype, "revisions", void 0);
|
|
2938
|
+
__decorate([
|
|
2939
|
+
state()
|
|
2940
|
+
], Editor.prototype, "viewingRevision", void 0);
|
|
2941
|
+
__decorate([
|
|
2942
|
+
state()
|
|
2943
|
+
], Editor.prototype, "isLoadingRevisions", void 0);
|
|
2655
2944
|
__decorate([
|
|
2656
2945
|
state()
|
|
2657
2946
|
], Editor.prototype, "editingNode", void 0);
|