@nyaruka/temba-components 0.138.4 → 0.139.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 +15 -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 +816 -852
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/display/FloatingTab.js +23 -30
- package/out-tsc/src/display/FloatingTab.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 +6 -7
- package/out-tsc/src/flow/CanvasNode.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +152 -235
- package/out-tsc/src/flow/Editor.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/utils.js +138 -66
- package/out-tsc/src/flow/utils.js.map +1 -1
- package/out-tsc/src/interfaces.js +1 -0
- package/out-tsc/src/interfaces.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/ContactChat.js +18 -1
- 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 +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 +1 -0
- package/out-tsc/src/simulator/Simulator.js.map +1 -1
- 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 +221 -223
- 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/package.json +1 -1
- package/src/display/FloatingTab.ts +22 -31
- package/src/flow/CanvasMenu.ts +8 -3
- package/src/flow/CanvasNode.ts +6 -7
- package/src/flow/Editor.ts +184 -279
- package/src/flow/Plumber.ts +1011 -457
- package/src/flow/utils.ts +162 -84
- package/src/interfaces.ts +2 -1
- package/src/list/TicketList.ts +4 -1
- package/src/live/ContactChat.ts +19 -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 +1 -0
- package/test/temba-floating-tab.test.ts +4 -6
- package/test/temba-flow-collision.test.ts +225 -303
- 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/src/flow/utils.ts
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { html } from 'lit-html';
|
|
2
2
|
import { NamedObject, FlowPosition } from '../store/flow-definition';
|
|
3
3
|
|
|
4
|
+
const GRID_SIZE = 20;
|
|
5
|
+
|
|
6
|
+
export function snapToGrid(value: number): number {
|
|
7
|
+
const snapped = Math.round(value / GRID_SIZE) * GRID_SIZE;
|
|
8
|
+
return Math.max(snapped, 0);
|
|
9
|
+
}
|
|
10
|
+
|
|
4
11
|
/**
|
|
5
12
|
* Renders a single line item with optional icon
|
|
6
13
|
*/
|
|
@@ -264,110 +271,181 @@ export const detectCollisions = (
|
|
|
264
271
|
);
|
|
265
272
|
};
|
|
266
273
|
|
|
274
|
+
type Direction = 'down' | 'up' | 'right' | 'left';
|
|
275
|
+
|
|
276
|
+
const DIRECTIONS: Direction[] = ['down', 'up', 'right', 'left'];
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Creates a new NodeBounds at a different position
|
|
280
|
+
*/
|
|
281
|
+
const makeBoundsAt = (
|
|
282
|
+
original: NodeBounds,
|
|
283
|
+
left: number,
|
|
284
|
+
top: number
|
|
285
|
+
): NodeBounds => ({
|
|
286
|
+
...original,
|
|
287
|
+
left,
|
|
288
|
+
top,
|
|
289
|
+
right: left + original.width,
|
|
290
|
+
bottom: top + original.height
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Computes the minimum position needed to clear all fixed nodes in a given direction.
|
|
295
|
+
* Returns null if the direction is not viable (e.g., would require negative coordinates
|
|
296
|
+
* and still overlap).
|
|
297
|
+
*/
|
|
298
|
+
const computeDirectionalClearance = (
|
|
299
|
+
collider: NodeBounds,
|
|
300
|
+
fixedNodes: NodeBounds[],
|
|
301
|
+
direction: Direction
|
|
302
|
+
): { left: number; top: number } | null => {
|
|
303
|
+
switch (direction) {
|
|
304
|
+
case 'down': {
|
|
305
|
+
const maxBottom = Math.max(...fixedNodes.map((f) => f.bottom));
|
|
306
|
+
const newTop = snapToGrid(maxBottom + MIN_NODE_SPACING);
|
|
307
|
+
return { left: collider.left, top: newTop };
|
|
308
|
+
}
|
|
309
|
+
case 'up': {
|
|
310
|
+
const minTop = Math.min(...fixedNodes.map((f) => f.top));
|
|
311
|
+
const newTop = snapToGrid(minTop - collider.height - MIN_NODE_SPACING);
|
|
312
|
+
if (newTop < 0) return { left: collider.left, top: 0 };
|
|
313
|
+
return { left: collider.left, top: newTop };
|
|
314
|
+
}
|
|
315
|
+
case 'right': {
|
|
316
|
+
const maxRight = Math.max(...fixedNodes.map((f) => f.right));
|
|
317
|
+
const newLeft = snapToGrid(maxRight + MIN_NODE_SPACING);
|
|
318
|
+
return { left: newLeft, top: collider.top };
|
|
319
|
+
}
|
|
320
|
+
case 'left': {
|
|
321
|
+
const minLeft = Math.min(...fixedNodes.map((f) => f.left));
|
|
322
|
+
const newLeft = snapToGrid(minLeft - collider.width - MIN_NODE_SPACING);
|
|
323
|
+
if (newLeft < 0) return { left: 0, top: collider.top };
|
|
324
|
+
return { left: newLeft, top: collider.top };
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
|
|
267
329
|
/**
|
|
268
|
-
* Calculates
|
|
269
|
-
*
|
|
270
|
-
*
|
|
330
|
+
* Calculates new positions to resolve all collisions using multi-directional reflow.
|
|
331
|
+
*
|
|
332
|
+
* Sacred nodes (the ones just dropped/created) keep their positions. All other
|
|
333
|
+
* colliding nodes are moved in whichever direction requires the least displacement
|
|
334
|
+
* and causes the fewest cascading collisions.
|
|
271
335
|
*/
|
|
272
336
|
export const calculateReflowPositions = (
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
allBounds: NodeBounds[],
|
|
276
|
-
droppedBelowMidpoint: boolean = false
|
|
337
|
+
sacredNodeUuids: string[],
|
|
338
|
+
allBounds: NodeBounds[]
|
|
277
339
|
): Map<string, FlowPosition> => {
|
|
278
340
|
const newPositions = new Map<string, FlowPosition>();
|
|
341
|
+
const sacredSet = new Set(sacredNodeUuids);
|
|
279
342
|
|
|
280
|
-
//
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
if (collisions.length > 0) {
|
|
286
|
-
// Find the highest bottom position of all colliding nodes
|
|
287
|
-
const maxBottom = Math.max(...collisions.map((b) => b.bottom));
|
|
288
|
-
|
|
289
|
-
// Move the dropped node below all colliding nodes
|
|
290
|
-
const newTop = maxBottom + MIN_NODE_SPACING;
|
|
291
|
-
newPositions.set(movedNodeUuid, {
|
|
292
|
-
left: movedNodeBounds.left,
|
|
293
|
-
top: newTop
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
// Update the moved node bounds for further collision checks
|
|
297
|
-
movedNodeBounds = {
|
|
298
|
-
...movedNodeBounds,
|
|
299
|
-
top: newTop,
|
|
300
|
-
bottom: newTop + movedNodeBounds.height
|
|
301
|
-
};
|
|
302
|
-
}
|
|
343
|
+
// Mutable map of current bounds, updated as collisions are resolved
|
|
344
|
+
const currentBounds = new Map<string, NodeBounds>();
|
|
345
|
+
for (const b of allBounds) {
|
|
346
|
+
currentBounds.set(b.uuid, { ...b });
|
|
303
347
|
}
|
|
304
348
|
|
|
305
|
-
//
|
|
306
|
-
const
|
|
307
|
-
|
|
349
|
+
// Seed the queue with non-sacred nodes that overlap any sacred node
|
|
350
|
+
const queue: string[] = [];
|
|
351
|
+
const inQueue = new Set<string>();
|
|
352
|
+
|
|
353
|
+
for (const sacredUuid of sacredSet) {
|
|
354
|
+
const sacred = currentBounds.get(sacredUuid);
|
|
355
|
+
if (!sacred) continue;
|
|
356
|
+
for (const [uuid, bounds] of currentBounds) {
|
|
357
|
+
if (sacredSet.has(uuid) || inQueue.has(uuid)) continue;
|
|
358
|
+
if (nodesOverlap(sacred, bounds)) {
|
|
359
|
+
queue.push(uuid);
|
|
360
|
+
inQueue.add(uuid);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
308
364
|
|
|
309
|
-
|
|
310
|
-
let hasCollisions = true;
|
|
365
|
+
const resolved = new Set<string>();
|
|
311
366
|
let iterations = 0;
|
|
312
|
-
const maxIterations =
|
|
367
|
+
const maxIterations = 200;
|
|
313
368
|
|
|
314
|
-
while (
|
|
315
|
-
hasCollisions = false;
|
|
369
|
+
while (queue.length > 0 && iterations < maxIterations) {
|
|
316
370
|
iterations++;
|
|
371
|
+
const uuid = queue.shift()!;
|
|
317
372
|
|
|
318
|
-
|
|
319
|
-
for (const bounds of allBounds) {
|
|
320
|
-
if (processedNodes.has(bounds.uuid)) {
|
|
321
|
-
continue;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
// Use original bounds since we skip already processed nodes
|
|
325
|
-
const currentBounds = bounds;
|
|
373
|
+
if (resolved.has(uuid)) continue;
|
|
326
374
|
|
|
327
|
-
|
|
328
|
-
let collisionFound = false;
|
|
329
|
-
let maxCollisionBottom = 0;
|
|
375
|
+
const collider = currentBounds.get(uuid)!;
|
|
330
376
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
377
|
+
// Find all fixed nodes (sacred + already-resolved) that overlap this node
|
|
378
|
+
const fixedOverlaps: NodeBounds[] = [];
|
|
379
|
+
for (const [otherUuid, otherBounds] of currentBounds) {
|
|
380
|
+
if (otherUuid === uuid) continue;
|
|
381
|
+
if (sacredSet.has(otherUuid) || resolved.has(otherUuid)) {
|
|
382
|
+
if (nodesOverlap(collider, otherBounds)) {
|
|
383
|
+
fixedOverlaps.push(otherBounds);
|
|
384
|
+
}
|
|
338
385
|
}
|
|
386
|
+
}
|
|
339
387
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
388
|
+
if (fixedOverlaps.length === 0) continue;
|
|
389
|
+
|
|
390
|
+
// Try each direction, pick the one with least disruption
|
|
391
|
+
let bestPos: { left: number; top: number } | null = null;
|
|
392
|
+
let bestScore = Infinity;
|
|
393
|
+
|
|
394
|
+
for (const dir of DIRECTIONS) {
|
|
395
|
+
const candidate = computeDirectionalClearance(
|
|
396
|
+
collider,
|
|
397
|
+
fixedOverlaps,
|
|
398
|
+
dir
|
|
399
|
+
);
|
|
400
|
+
if (!candidate) continue;
|
|
401
|
+
|
|
402
|
+
const candidateBounds = makeBoundsAt(
|
|
403
|
+
collider,
|
|
404
|
+
candidate.left,
|
|
405
|
+
candidate.top
|
|
406
|
+
);
|
|
407
|
+
|
|
408
|
+
// Verify no overlap with any sacred or resolved node
|
|
409
|
+
let stillOverlaps = false;
|
|
410
|
+
let cascadeCount = 0;
|
|
411
|
+
for (const [otherUuid, otherBounds] of currentBounds) {
|
|
412
|
+
if (otherUuid === uuid) continue;
|
|
413
|
+
if (!nodesOverlap(candidateBounds, otherBounds)) continue;
|
|
414
|
+
|
|
415
|
+
if (sacredSet.has(otherUuid) || resolved.has(otherUuid)) {
|
|
416
|
+
stillOverlaps = true;
|
|
417
|
+
break;
|
|
359
418
|
}
|
|
419
|
+
cascadeCount++;
|
|
420
|
+
}
|
|
421
|
+
if (stillOverlaps) continue;
|
|
422
|
+
|
|
423
|
+
const distance =
|
|
424
|
+
Math.abs(candidate.left - collider.left) +
|
|
425
|
+
Math.abs(candidate.top - collider.top);
|
|
426
|
+
const score = cascadeCount * 10000 + distance;
|
|
427
|
+
|
|
428
|
+
if (score < bestScore) {
|
|
429
|
+
bestScore = score;
|
|
430
|
+
bestPos = candidate;
|
|
360
431
|
}
|
|
432
|
+
}
|
|
361
433
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
434
|
+
if (bestPos) {
|
|
435
|
+
newPositions.set(uuid, { left: bestPos.left, top: bestPos.top });
|
|
436
|
+
const newBounds = makeBoundsAt(collider, bestPos.left, bestPos.top);
|
|
437
|
+
currentBounds.set(uuid, newBounds);
|
|
438
|
+
resolved.add(uuid);
|
|
439
|
+
|
|
440
|
+
// Enqueue any new cascading collisions
|
|
441
|
+
for (const [otherUuid, otherBounds] of currentBounds) {
|
|
442
|
+
if (otherUuid === uuid) continue;
|
|
443
|
+
if (sacredSet.has(otherUuid) || resolved.has(otherUuid)) continue;
|
|
444
|
+
if (inQueue.has(otherUuid)) continue;
|
|
445
|
+
if (nodesOverlap(newBounds, otherBounds)) {
|
|
446
|
+
queue.push(otherUuid);
|
|
447
|
+
inQueue.add(otherUuid);
|
|
448
|
+
}
|
|
371
449
|
}
|
|
372
450
|
}
|
|
373
451
|
}
|
package/src/interfaces.ts
CHANGED
|
@@ -303,5 +303,6 @@ export enum CustomEventType {
|
|
|
303
303
|
NodeEditRequested = 'temba-node-edit-requested',
|
|
304
304
|
NodeSaved = 'temba-node-saved',
|
|
305
305
|
NodeEditCancelled = 'temba-node-edit-cancelled',
|
|
306
|
-
FollowSimulation = 'temba-follow-simulation'
|
|
306
|
+
FollowSimulation = 'temba-follow-simulation',
|
|
307
|
+
ContactClicked = 'temba-contact-clicked'
|
|
307
308
|
}
|
package/src/list/TicketList.ts
CHANGED
|
@@ -13,7 +13,10 @@ export class TicketList extends TembaList {
|
|
|
13
13
|
const lastActivity = this.items[0].ticket.last_activity_on;
|
|
14
14
|
const separator = this.endpoint.includes('?') ? '&' : '?';
|
|
15
15
|
return (
|
|
16
|
-
this.endpoint +
|
|
16
|
+
this.endpoint +
|
|
17
|
+
separator +
|
|
18
|
+
'after=' +
|
|
19
|
+
new Date(lastActivity).getTime() * 1000
|
|
17
20
|
);
|
|
18
21
|
}
|
|
19
22
|
return this.endpoint;
|
package/src/live/ContactChat.ts
CHANGED
|
@@ -271,6 +271,12 @@ export class ContactChat extends ContactStoreElement {
|
|
|
271
271
|
@property({ type: Boolean })
|
|
272
272
|
showInterrupt = false;
|
|
273
273
|
|
|
274
|
+
@property({ type: Boolean })
|
|
275
|
+
disableAssign = false;
|
|
276
|
+
|
|
277
|
+
@property({ type: Boolean })
|
|
278
|
+
disableReply = false;
|
|
279
|
+
|
|
274
280
|
@property({ type: String })
|
|
275
281
|
avatar = DEFAULT_AVATAR;
|
|
276
282
|
|
|
@@ -607,6 +613,14 @@ export class ContactChat extends ContactStoreElement {
|
|
|
607
613
|
return null;
|
|
608
614
|
} else {
|
|
609
615
|
if (!this.currentTicket.closed_on) {
|
|
616
|
+
// hide compose if agent can't reply to unassigned tickets
|
|
617
|
+
if (
|
|
618
|
+
this.disableReply &&
|
|
619
|
+
(!this.currentTicket.assignee ||
|
|
620
|
+
this.currentTicket.assignee.email !== this.agent)
|
|
621
|
+
) {
|
|
622
|
+
return null;
|
|
623
|
+
}
|
|
610
624
|
//chatbox for active contacts with an open ticket
|
|
611
625
|
return this.getCompose();
|
|
612
626
|
} else {
|
|
@@ -676,6 +690,10 @@ export class ContactChat extends ContactStoreElement {
|
|
|
676
690
|
}
|
|
677
691
|
|
|
678
692
|
public assignTicket(email: string) {
|
|
693
|
+
if (this.disableAssign) {
|
|
694
|
+
return;
|
|
695
|
+
}
|
|
696
|
+
|
|
679
697
|
// if its already assigned to use, it's a noop
|
|
680
698
|
if (
|
|
681
699
|
(this.currentTicket.assignee &&
|
|
@@ -803,7 +821,7 @@ export class ContactChat extends ContactStoreElement {
|
|
|
803
821
|
? [this.currentTicket.assignee]
|
|
804
822
|
: []}
|
|
805
823
|
@change=${this.handleAssignmentChanged}
|
|
806
|
-
?disabled=${ticketClosed}
|
|
824
|
+
?disabled=${ticketClosed || this.disableAssign}
|
|
807
825
|
></temba-user-select>
|
|
808
826
|
|
|
809
827
|
<temba-select
|
package/src/locales/es.ts
CHANGED
|
@@ -1,18 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
's8f02e3a18ffc083a': `Are not currently in a flow`,
|
|
15
|
-
's638236250662c6b3': `Have sent a message in the last`,
|
|
16
|
-
's4788ee206c4570c7': `Have not started this flow in the last 90 days`,
|
|
17
|
-
};
|
|
18
|
-
|
|
1
|
+
// Do not modify this file by hand!
|
|
2
|
+
// Re-generate this file by running lit-localize
|
|
3
|
+
|
|
4
|
+
/* eslint-disable no-irregular-whitespace */
|
|
5
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
6
|
+
|
|
7
|
+
export const templates = {
|
|
8
|
+
scf1453991c986b25: `Tab para completar, enter para seleccionar`,
|
|
9
|
+
s73b4d70c02f4b4e0: `No options`,
|
|
10
|
+
s8f02e3a18ffc083a: `Are not currently in a flow`,
|
|
11
|
+
s638236250662c6b3: `Have sent a message in the last`,
|
|
12
|
+
s4788ee206c4570c7: `Have not started this flow in the last 90 days`
|
|
13
|
+
};
|
package/src/locales/fr.ts
CHANGED
|
@@ -1,18 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
's8f02e3a18ffc083a': `Are not currently in a flow`,
|
|
15
|
-
's638236250662c6b3': `Have sent a message in the last`,
|
|
16
|
-
's4788ee206c4570c7': `Have not started this flow in the last 90 days`,
|
|
17
|
-
};
|
|
18
|
-
|
|
1
|
+
// Do not modify this file by hand!
|
|
2
|
+
// Re-generate this file by running lit-localize
|
|
3
|
+
|
|
4
|
+
/* eslint-disable no-irregular-whitespace */
|
|
5
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
6
|
+
|
|
7
|
+
export const templates = {
|
|
8
|
+
s73b4d70c02f4b4e0: `No options`,
|
|
9
|
+
scf1453991c986b25: `Tab to complete, enter to select`,
|
|
10
|
+
s8f02e3a18ffc083a: `Are not currently in a flow`,
|
|
11
|
+
s638236250662c6b3: `Have sent a message in the last`,
|
|
12
|
+
s4788ee206c4570c7: `Have not started this flow in the last 90 days`
|
|
13
|
+
};
|
|
@@ -10,18 +10,9 @@ export const sourceLocale = `en`;
|
|
|
10
10
|
* The other locale codes that this application is localized into. Sorted
|
|
11
11
|
* lexicographically.
|
|
12
12
|
*/
|
|
13
|
-
export const targetLocales = [
|
|
14
|
-
`es`,
|
|
15
|
-
`fr`,
|
|
16
|
-
`pt`,
|
|
17
|
-
] as const;
|
|
13
|
+
export const targetLocales = [`es`, `fr`, `pt`] as const;
|
|
18
14
|
|
|
19
15
|
/**
|
|
20
16
|
* All valid project locale codes. Sorted lexicographically.
|
|
21
17
|
*/
|
|
22
|
-
export const allLocales = [
|
|
23
|
-
`en`,
|
|
24
|
-
`es`,
|
|
25
|
-
`fr`,
|
|
26
|
-
`pt`,
|
|
27
|
-
] as const;
|
|
18
|
+
export const allLocales = [`en`, `es`, `fr`, `pt`] as const;
|
package/src/locales/pt.ts
CHANGED
|
@@ -1,18 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
's8f02e3a18ffc083a': `Are not currently in a flow`,
|
|
15
|
-
's638236250662c6b3': `Have sent a message in the last`,
|
|
16
|
-
's4788ee206c4570c7': `Have not started this flow in the last 90 days`,
|
|
17
|
-
};
|
|
18
|
-
|
|
1
|
+
// Do not modify this file by hand!
|
|
2
|
+
// Re-generate this file by running lit-localize
|
|
3
|
+
|
|
4
|
+
/* eslint-disable no-irregular-whitespace */
|
|
5
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
6
|
+
|
|
7
|
+
export const templates = {
|
|
8
|
+
s73b4d70c02f4b4e0: `No options`,
|
|
9
|
+
scf1453991c986b25: `Tab to complete, enter to select`,
|
|
10
|
+
s8f02e3a18ffc083a: `Are not currently in a flow`,
|
|
11
|
+
s638236250662c6b3: `Have sent a message in the last`,
|
|
12
|
+
s4788ee206c4570c7: `Have not started this flow in the last 90 days`
|
|
13
|
+
};
|
|
@@ -7,15 +7,13 @@ describe('temba-floating-tab', () => {
|
|
|
7
7
|
const tab = (await getComponent('temba-floating-tab', {
|
|
8
8
|
icon: 'phone',
|
|
9
9
|
label: 'Phone Simulator',
|
|
10
|
-
color: '#10b981'
|
|
11
|
-
top: 100
|
|
10
|
+
color: '#10b981'
|
|
12
11
|
})) as FloatingTab;
|
|
13
12
|
|
|
14
13
|
assert.instanceOf(tab, FloatingTab);
|
|
15
14
|
expect(tab.icon).to.equal('phone');
|
|
16
15
|
expect(tab.label).to.equal('Phone Simulator');
|
|
17
16
|
expect(tab.color).to.equal('#10b981');
|
|
18
|
-
expect(tab.top).to.equal(100);
|
|
19
17
|
expect(tab.hidden).to.equal(false);
|
|
20
18
|
|
|
21
19
|
await assertScreenshot('floating-tab/default', getClip(tab));
|
|
@@ -75,21 +73,21 @@ describe('temba-floating-tab', () => {
|
|
|
75
73
|
icon: 'phone',
|
|
76
74
|
label: 'Phone',
|
|
77
75
|
color: '#10b981',
|
|
78
|
-
|
|
76
|
+
order: 1
|
|
79
77
|
})) as FloatingTab;
|
|
80
78
|
|
|
81
79
|
const tab2 = (await getComponent('temba-floating-tab', {
|
|
82
80
|
icon: 'globe',
|
|
83
81
|
label: 'Translation',
|
|
84
82
|
color: '#6b7280',
|
|
85
|
-
|
|
83
|
+
order: 2
|
|
86
84
|
})) as FloatingTab;
|
|
87
85
|
|
|
88
86
|
const tab3 = (await getComponent('temba-floating-tab', {
|
|
89
87
|
icon: 'clock',
|
|
90
88
|
label: 'History',
|
|
91
89
|
color: '#8b5cf6',
|
|
92
|
-
|
|
90
|
+
order: 3
|
|
93
91
|
})) as FloatingTab;
|
|
94
92
|
|
|
95
93
|
await assertScreenshot('floating-tab/green', getClip(tab1));
|