@nyaruka/temba-components 0.133.0 → 0.134.1
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 +17 -0
- package/demo/components/webchat/example.html +1 -1
- 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 +307 -259
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/display/Chat.js +223 -90
- package/out-tsc/src/display/Chat.js.map +1 -1
- package/out-tsc/src/display/TembaUser.js +3 -3
- package/out-tsc/src/display/TembaUser.js.map +1 -1
- package/out-tsc/src/events.js.map +1 -1
- package/out-tsc/src/flow/CanvasNode.js +8 -0
- package/out-tsc/src/flow/CanvasNode.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +117 -28
- package/out-tsc/src/flow/Editor.js.map +1 -1
- package/out-tsc/src/flow/utils.js +141 -0
- package/out-tsc/src/flow/utils.js.map +1 -1
- package/out-tsc/src/interfaces.js.map +1 -1
- package/out-tsc/src/live/ContactChat.js +122 -170
- 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/store/AppState.js +3 -0
- package/out-tsc/src/store/AppState.js.map +1 -1
- package/out-tsc/src/store/Store.js +5 -5
- package/out-tsc/src/store/Store.js.map +1 -1
- package/out-tsc/src/webchat/WebChat.js +22 -9
- package/out-tsc/src/webchat/WebChat.js.map +1 -1
- package/out-tsc/test/actions/send_broadcast.test.js +9 -4
- package/out-tsc/test/actions/send_broadcast.test.js.map +1 -1
- package/out-tsc/test/temba-flow-collision.test.js +673 -0
- package/out-tsc/test/temba-flow-collision.test.js.map +1 -0
- package/out-tsc/test/temba-flow-editor-node.test.js +128 -42
- package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
- package/package.json +1 -1
- package/screenshots/truth/contacts/chat-failure.png +0 -0
- package/screenshots/truth/contacts/chat-for-archived-contact.png +0 -0
- package/screenshots/truth/contacts/chat-for-blocked-contact.png +0 -0
- package/screenshots/truth/contacts/chat-for-stopped-contact.png +0 -0
- package/screenshots/truth/contacts/chat-sends-attachments-only.png +0 -0
- package/screenshots/truth/contacts/chat-sends-text-and-attachments.png +0 -0
- package/screenshots/truth/contacts/chat-sends-text-only.png +0 -0
- package/src/display/Chat.ts +303 -129
- package/src/display/TembaUser.ts +3 -2
- package/src/events.ts +11 -8
- package/src/flow/CanvasNode.ts +10 -0
- package/src/flow/Editor.ts +156 -28
- package/src/flow/utils.ts +207 -1
- package/src/interfaces.ts +7 -0
- package/src/live/ContactChat.ts +129 -180
- 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/store/AppState.ts +2 -0
- package/src/store/Store.ts +5 -5
- package/src/webchat/WebChat.ts +24 -10
- package/test/actions/send_broadcast.test.ts +2 -1
- package/test/temba-flow-collision.test.ts +833 -0
- package/test/temba-flow-editor-node.test.ts +142 -47
package/src/live/ContactChat.ts
CHANGED
|
@@ -24,12 +24,10 @@ import {
|
|
|
24
24
|
CallEvent,
|
|
25
25
|
ChannelEvent,
|
|
26
26
|
ChatStartedEvent,
|
|
27
|
-
ContactEvent,
|
|
28
27
|
ContactGroupsEvent,
|
|
29
28
|
ContactHistoryPage,
|
|
30
29
|
ContactLanguageChangedEvent,
|
|
31
30
|
ContactStatusChangedEvent,
|
|
32
|
-
MsgEvent,
|
|
33
31
|
NameChangedEvent,
|
|
34
32
|
OptInEvent,
|
|
35
33
|
RunEvent,
|
|
@@ -37,11 +35,10 @@ import {
|
|
|
37
35
|
UpdateFieldEvent,
|
|
38
36
|
URNsChangedEvent
|
|
39
37
|
} from '../events';
|
|
40
|
-
import { Chat,
|
|
38
|
+
import { Chat, MessageType, ContactEvent } from '../display/Chat';
|
|
41
39
|
import { DEFAULT_AVATAR } from '../webchat/assets';
|
|
42
40
|
import { UserSelect } from '../form/select/UserSelect';
|
|
43
41
|
import { Select } from '../form/select/Select';
|
|
44
|
-
import { Store } from '../store/Store';
|
|
45
42
|
|
|
46
43
|
/*
|
|
47
44
|
export const SCROLL_THRESHOLD = 100;
|
|
@@ -176,17 +173,41 @@ export const renderTicketAction = (
|
|
|
176
173
|
): TemplateResult => {
|
|
177
174
|
const ticketUUID = event.ticket?.uuid || event.ticket_uuid;
|
|
178
175
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
176
|
+
const actionNote = event.note
|
|
177
|
+
? html`<div
|
|
178
|
+
style="width:85%; background: #fffac3; padding: 1em;margin-bottom: 1em 0; border: 1px solid #ffe97f;border-radius: var(--curvature);"
|
|
179
|
+
>
|
|
180
|
+
<div style="color: #8e830fff; font-size: 1em;margin-bottom:0.25em">
|
|
181
|
+
<strong>${event._user ? event._user.name : 'Someone'}</strong> added a
|
|
182
|
+
note
|
|
183
|
+
<temba-date
|
|
184
|
+
value=${event.created_on.toISOString()}
|
|
185
|
+
display="relative"
|
|
186
|
+
></temba-date>
|
|
187
|
+
</div>
|
|
188
|
+
${event.note}
|
|
189
|
+
</div>`
|
|
190
|
+
: null;
|
|
191
|
+
|
|
192
|
+
if (action === 'noted') {
|
|
193
|
+
return html`${actionNote}`;
|
|
184
194
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
195
|
+
|
|
196
|
+
const description = event._user
|
|
197
|
+
? html`<div>
|
|
198
|
+
<strong>${event._user.name}</strong> ${action} a
|
|
199
|
+
<strong><a href="/ticket/all/closed/${ticketUUID}/">ticket</a></strong>
|
|
200
|
+
</div>`
|
|
201
|
+
: html`<div>
|
|
202
|
+
A
|
|
203
|
+
<strong><a href="/ticket/all/closed/${ticketUUID}/">ticket</a></strong>
|
|
204
|
+
was <strong>${action}</strong>
|
|
205
|
+
</div>`;
|
|
206
|
+
|
|
207
|
+
return html`<div style="${actionNote ? 'margin-bottom: 1em;' : ''}">
|
|
208
|
+
${description}
|
|
209
|
+
</div>
|
|
210
|
+
${actionNote}`;
|
|
190
211
|
};
|
|
191
212
|
|
|
192
213
|
export const renderTicketAssigneeChanged = (
|
|
@@ -572,9 +593,16 @@ export class ContactChat extends ContactStoreElement {
|
|
|
572
593
|
this.currentContact = this.data;
|
|
573
594
|
}
|
|
574
595
|
|
|
575
|
-
if (changedProperties.has('currentContact')) {
|
|
596
|
+
if (changedProperties.has('currentContact') && this.currentContact) {
|
|
576
597
|
this.chat = this.shadowRoot.querySelector('temba-chat');
|
|
577
|
-
|
|
598
|
+
if (
|
|
599
|
+
this.currentContact.uuid !==
|
|
600
|
+
changedProperties.get('currentContact')?.uuid
|
|
601
|
+
) {
|
|
602
|
+
this.reset();
|
|
603
|
+
} else {
|
|
604
|
+
setTimeout(() => this.checkForNewMessages(), 500);
|
|
605
|
+
}
|
|
578
606
|
this.fetchPreviousMessages();
|
|
579
607
|
}
|
|
580
608
|
}
|
|
@@ -637,8 +665,9 @@ export class ContactChat extends ContactStoreElement {
|
|
|
637
665
|
postJSON(`/contact/chat/${this.currentContact.uuid}/`, payload)
|
|
638
666
|
.then((response) => {
|
|
639
667
|
if (response.status < 400) {
|
|
640
|
-
const
|
|
641
|
-
|
|
668
|
+
const event = response.json.event;
|
|
669
|
+
event.created_on = new Date(event.created_on);
|
|
670
|
+
this.chat.addMessages([event], null, true);
|
|
642
671
|
// reset polling interval to 2 seconds after sending a message
|
|
643
672
|
this.pollingInterval = 2000;
|
|
644
673
|
this.checkForNewMessages();
|
|
@@ -682,185 +711,136 @@ export class ContactChat extends ContactStoreElement {
|
|
|
682
711
|
}, this.pollingInterval);
|
|
683
712
|
}
|
|
684
713
|
|
|
685
|
-
public
|
|
686
|
-
let message = null;
|
|
714
|
+
public prerender(event: ContactEvent) {
|
|
687
715
|
switch (event.type) {
|
|
688
716
|
case Events.AIRTIME_TRANSFERRED:
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
717
|
+
event._rendered = {
|
|
718
|
+
html: renderAirtimeTransferredEvent(event as AirtimeTransferredEvent),
|
|
719
|
+
type: MessageType.Inline
|
|
692
720
|
};
|
|
693
721
|
break;
|
|
694
722
|
case Events.CALL_CREATED:
|
|
695
723
|
case Events.CALL_MISSED:
|
|
696
724
|
case Events.CALL_RECEIVED:
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
725
|
+
event._rendered = {
|
|
726
|
+
html: renderCallEvent(event as CallEvent),
|
|
727
|
+
type: MessageType.Inline
|
|
700
728
|
};
|
|
701
729
|
break;
|
|
702
730
|
case Events.CHAT_STARTED:
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
731
|
+
event._rendered = {
|
|
732
|
+
html: renderChatStartedEvent(event as ChatStartedEvent),
|
|
733
|
+
type: MessageType.Inline
|
|
706
734
|
};
|
|
707
735
|
break;
|
|
708
736
|
case Events.CONTACT_FIELD_CHANGED:
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
737
|
+
event._rendered = {
|
|
738
|
+
html: renderUpdateEvent(event as UpdateFieldEvent),
|
|
739
|
+
type: MessageType.Inline
|
|
712
740
|
};
|
|
713
741
|
break;
|
|
714
742
|
case Events.CONTACT_GROUPS_CHANGED:
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
743
|
+
event._rendered = {
|
|
744
|
+
html: renderContactGroupsEvent(event as ContactGroupsEvent),
|
|
745
|
+
type: MessageType.Inline
|
|
718
746
|
};
|
|
719
747
|
break;
|
|
720
748
|
case Events.CONTACT_LANGUAGE_CHANGED:
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
text: renderContactLanguageChangedEvent(
|
|
749
|
+
event._rendered = {
|
|
750
|
+
html: renderContactLanguageChangedEvent(
|
|
724
751
|
event as ContactLanguageChangedEvent
|
|
725
|
-
)
|
|
752
|
+
),
|
|
753
|
+
type: MessageType.Inline
|
|
726
754
|
};
|
|
727
755
|
break;
|
|
728
756
|
case Events.CONTACT_NAME_CHANGED:
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
757
|
+
event._rendered = {
|
|
758
|
+
html: renderNameChanged(event as NameChangedEvent),
|
|
759
|
+
type: MessageType.Inline
|
|
732
760
|
};
|
|
733
761
|
break;
|
|
734
762
|
case Events.CONTACT_STATUS_CHANGED:
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
text: renderContactStatusChangedEvent(
|
|
763
|
+
event._rendered = {
|
|
764
|
+
html: renderContactStatusChangedEvent(
|
|
738
765
|
event as ContactStatusChangedEvent
|
|
739
|
-
)
|
|
766
|
+
),
|
|
767
|
+
type: MessageType.Inline
|
|
740
768
|
};
|
|
741
769
|
break;
|
|
742
770
|
case Events.CONTACT_URNS_CHANGED:
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
771
|
+
event._rendered = {
|
|
772
|
+
html: renderContactURNsChanged(event as URNsChangedEvent),
|
|
773
|
+
type: MessageType.Inline
|
|
746
774
|
};
|
|
747
775
|
break;
|
|
748
776
|
case Events.OPTIN_REQUESTED:
|
|
749
777
|
case Events.OPTIN_STARTED:
|
|
750
778
|
case Events.OPTIN_STOPPED:
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
779
|
+
event._rendered = {
|
|
780
|
+
html: renderOptInEvent(event as OptInEvent),
|
|
781
|
+
type: MessageType.Inline
|
|
754
782
|
};
|
|
755
783
|
break;
|
|
756
784
|
case Events.RUN_STARTED:
|
|
757
785
|
case Events.RUN_ENDED:
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
786
|
+
event._rendered = {
|
|
787
|
+
html: renderRunEvent(event as RunEvent),
|
|
788
|
+
type: MessageType.Inline
|
|
761
789
|
};
|
|
762
790
|
break;
|
|
763
791
|
case Events.TICKET_ASSIGNEE_CHANGED:
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
792
|
+
event._rendered = {
|
|
793
|
+
html: renderTicketAssigneeChanged(event as TicketEvent),
|
|
794
|
+
type: MessageType.Inline
|
|
767
795
|
};
|
|
768
796
|
break;
|
|
769
797
|
case Events.TICKET_CLOSED:
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
798
|
+
event._rendered = {
|
|
799
|
+
html: renderTicketAction(event as TicketEvent, 'closed'),
|
|
800
|
+
type: MessageType.Inline
|
|
773
801
|
};
|
|
774
802
|
break;
|
|
775
803
|
case Events.TICKET_OPENED:
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
804
|
+
event._rendered = {
|
|
805
|
+
html: renderTicketAction(event as TicketEvent, 'opened'),
|
|
806
|
+
type: MessageType.Inline
|
|
807
|
+
};
|
|
808
|
+
break;
|
|
809
|
+
case Events.TICKET_NOTE_ADDED:
|
|
810
|
+
event._rendered = {
|
|
811
|
+
html: renderTicketAction(event as TicketEvent, 'noted'),
|
|
812
|
+
type: MessageType.Inline
|
|
779
813
|
};
|
|
780
814
|
break;
|
|
781
815
|
case Events.TICKET_REOPENED:
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
816
|
+
event._rendered = {
|
|
817
|
+
html: renderTicketAction(event as TicketEvent, 'reopened'),
|
|
818
|
+
type: MessageType.Inline
|
|
785
819
|
};
|
|
786
820
|
break;
|
|
787
821
|
case Events.TICKET_TOPIC_CHANGED:
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
text: html`<div>
|
|
822
|
+
event._rendered = {
|
|
823
|
+
html: html`<div>
|
|
791
824
|
Topic changed to
|
|
792
825
|
<strong>${(event as TicketEvent).topic.name}</strong>
|
|
793
|
-
</div
|
|
826
|
+
</div>`,
|
|
827
|
+
type: MessageType.Inline
|
|
794
828
|
};
|
|
795
829
|
break;
|
|
796
830
|
case Events.CHANNEL_EVENT: // deprecated
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
831
|
+
event._rendered = {
|
|
832
|
+
html: renderChannelEvent(event as ChannelEvent),
|
|
833
|
+
type: MessageType.Inline
|
|
800
834
|
};
|
|
801
835
|
break;
|
|
802
836
|
default:
|
|
803
837
|
console.error('Unknown event type', event);
|
|
804
838
|
}
|
|
805
|
-
|
|
806
|
-
if (message) {
|
|
807
|
-
message.id = event.uuid;
|
|
808
|
-
message.date = new Date(event.created_on);
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
return message;
|
|
812
839
|
}
|
|
813
840
|
|
|
814
|
-
private
|
|
815
|
-
if (event.type === 'msg_received') {
|
|
816
|
-
return {
|
|
817
|
-
name: this.currentContact.name
|
|
818
|
-
};
|
|
819
|
-
} else if (event._user) {
|
|
820
|
-
return event._user;
|
|
821
|
-
}
|
|
822
|
-
return null;
|
|
823
|
-
}
|
|
824
|
-
|
|
825
|
-
private createChatForMessageEvent(msgEvent: MsgEvent): any {
|
|
826
|
-
return {
|
|
827
|
-
id: msgEvent.uuid,
|
|
828
|
-
type: msgEvent.type === 'msg_received' ? 'msg_in' : 'msg_out',
|
|
829
|
-
user: this.getUserForEvent(msgEvent),
|
|
830
|
-
date: new Date(msgEvent.created_on),
|
|
831
|
-
attachments: msgEvent.msg.attachments,
|
|
832
|
-
text: msgEvent.msg.text,
|
|
833
|
-
sendError:
|
|
834
|
-
msgEvent._status &&
|
|
835
|
-
(msgEvent._status.status === 'errored' ||
|
|
836
|
-
msgEvent._status.status === 'failed'),
|
|
837
|
-
popup: html`<div
|
|
838
|
-
style="display: flex; flex-direction: row; align-items:center; justify-content: space-between;font-size:0.9em;line-height:1em;min-width:10em"
|
|
839
|
-
>
|
|
840
|
-
<div style="justify-content:left;text-align:left">
|
|
841
|
-
<temba-date
|
|
842
|
-
value=${msgEvent.created_on}
|
|
843
|
-
display="duration"
|
|
844
|
-
></temba-date>
|
|
845
|
-
|
|
846
|
-
${msgEvent.optin
|
|
847
|
-
? html`<div style="font-size:0.9em;color:#aaa">
|
|
848
|
-
${msgEvent.optin.name}
|
|
849
|
-
</div>`
|
|
850
|
-
: null}
|
|
851
|
-
</div>
|
|
852
|
-
${msgEvent._logs_url
|
|
853
|
-
? html`<a style="margin-left:0.5em" href="${msgEvent._logs_url}"
|
|
854
|
-
><temba-icon name="log"></temba-icon
|
|
855
|
-
></a>`
|
|
856
|
-
: null}
|
|
857
|
-
</div> `
|
|
858
|
-
};
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
private createMessages(page: ContactHistoryPage): ChatEvent[] {
|
|
841
|
+
private createMessages(page: ContactHistoryPage): ContactEvent[] {
|
|
862
842
|
if (page.events) {
|
|
863
|
-
|
|
843
|
+
const messages: ContactEvent[] = [];
|
|
864
844
|
page.events.forEach((event) => {
|
|
865
845
|
// track the UUID of the newest event for polling
|
|
866
846
|
if (
|
|
@@ -870,46 +850,25 @@ export class ContactChat extends ContactStoreElement {
|
|
|
870
850
|
this.afterUUID = event.uuid;
|
|
871
851
|
}
|
|
872
852
|
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
messages.push({
|
|
876
|
-
type: MessageType.Note,
|
|
877
|
-
id: event.created_on + event.type,
|
|
878
|
-
user: this.getUserForEvent(ticketEvent),
|
|
879
|
-
date: new Date(ticketEvent.created_on),
|
|
880
|
-
text: ticketEvent.note
|
|
881
|
-
});
|
|
882
|
-
} else if (event.type === 'ticket_opened') {
|
|
883
|
-
// ticket open events can have a note attached
|
|
884
|
-
const ticketEvent = event as TicketEvent;
|
|
885
|
-
messages.push({
|
|
886
|
-
type: MessageType.Note,
|
|
887
|
-
id: event.created_on + event.type + '_note',
|
|
888
|
-
user: this.getUserForEvent(ticketEvent),
|
|
889
|
-
date: new Date(ticketEvent.created_on),
|
|
890
|
-
text: ticketEvent.note
|
|
891
|
-
});
|
|
853
|
+
// convert to dates
|
|
854
|
+
event.created_on = new Date(event.created_on);
|
|
892
855
|
|
|
893
|
-
|
|
894
|
-
messages.push(this.getEventMessage(event));
|
|
895
|
-
} else if (
|
|
856
|
+
if (
|
|
896
857
|
event.type === 'msg_created' ||
|
|
897
858
|
event.type === 'msg_received' ||
|
|
898
859
|
event.type === 'ivr_created'
|
|
899
860
|
) {
|
|
900
|
-
|
|
901
|
-
messages.push(this.createChatForMessageEvent(msgEvent));
|
|
861
|
+
messages.push(event);
|
|
902
862
|
} else {
|
|
903
|
-
|
|
904
|
-
if (
|
|
905
|
-
messages.push(
|
|
863
|
+
this.prerender(event);
|
|
864
|
+
if (event._rendered) {
|
|
865
|
+
messages.push(event);
|
|
906
866
|
}
|
|
907
867
|
}
|
|
908
868
|
});
|
|
909
869
|
|
|
910
870
|
// remove any messages we don't recognize
|
|
911
|
-
|
|
912
|
-
return messages as ChatEvent[];
|
|
871
|
+
return messages.filter((msg) => !!msg);
|
|
913
872
|
}
|
|
914
873
|
return [];
|
|
915
874
|
}
|
|
@@ -921,7 +880,6 @@ export class ContactChat extends ContactStoreElement {
|
|
|
921
880
|
}
|
|
922
881
|
|
|
923
882
|
const chat = this.chat;
|
|
924
|
-
const contactChat = this;
|
|
925
883
|
if (this.currentContact && this.afterUUID) {
|
|
926
884
|
this.polling = true;
|
|
927
885
|
this.lastFetchTime = Date.now();
|
|
@@ -938,13 +896,10 @@ export class ContactChat extends ContactStoreElement {
|
|
|
938
896
|
null,
|
|
939
897
|
this.afterUUID
|
|
940
898
|
).then((page: ContactHistoryPage) => {
|
|
899
|
+
const messages = this.createMessages(page);
|
|
900
|
+
messages.reverse();
|
|
941
901
|
if (fetchContact === this.currentContact.uuid) {
|
|
942
|
-
const messages = this.createMessages(page);
|
|
943
902
|
const hasNewEvents = messages.length > 0;
|
|
944
|
-
if (messages.length === 0) {
|
|
945
|
-
contactChat.blockFetching = true;
|
|
946
|
-
}
|
|
947
|
-
messages.reverse();
|
|
948
903
|
chat.addMessages(messages, null, true);
|
|
949
904
|
this.polling = false;
|
|
950
905
|
this.scheduleRefresh(hasNewEvents);
|
|
@@ -1115,15 +1070,13 @@ export class ContactChat extends ContactStoreElement {
|
|
|
1115
1070
|
if (this.currentTicket) {
|
|
1116
1071
|
fetchResults(`/api/v2/tickets.json?uuid=${this.currentTicket.uuid}`).then(
|
|
1117
1072
|
(values) => {
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
}
|
|
1126
|
-
});
|
|
1073
|
+
if (values.length > 0) {
|
|
1074
|
+
this.fireCustomEvent(CustomEventType.TicketUpdated, {
|
|
1075
|
+
ticket: values[0],
|
|
1076
|
+
previous: this.currentTicket
|
|
1077
|
+
});
|
|
1078
|
+
this.currentTicket = values[0];
|
|
1079
|
+
}
|
|
1127
1080
|
}
|
|
1128
1081
|
);
|
|
1129
1082
|
}
|
|
@@ -1170,6 +1123,7 @@ export class ContactChat extends ContactStoreElement {
|
|
|
1170
1123
|
@temba-fetch-complete=${this.fetchComplete}
|
|
1171
1124
|
avatar=${this.avatar}
|
|
1172
1125
|
agent
|
|
1126
|
+
?hasFooter=${inFlow}
|
|
1173
1127
|
>
|
|
1174
1128
|
${inFlow
|
|
1175
1129
|
? html`
|
|
@@ -1294,8 +1248,6 @@ export const fetchContactHistory = (
|
|
|
1294
1248
|
url += (url.includes('?') ? '&' : '?') + params.join('&');
|
|
1295
1249
|
}
|
|
1296
1250
|
|
|
1297
|
-
const store = document.querySelector('temba-store') as Store;
|
|
1298
|
-
|
|
1299
1251
|
getUrl(url, controller)
|
|
1300
1252
|
.then((response: WebResponse) => {
|
|
1301
1253
|
// on success, remove our abort controller
|
|
@@ -1305,10 +1257,7 @@ export const fetchContactHistory = (
|
|
|
1305
1257
|
}
|
|
1306
1258
|
);
|
|
1307
1259
|
|
|
1308
|
-
|
|
1309
|
-
store.resolveUsers(page.events, ['created_by']).then(() => {
|
|
1310
|
-
resolve(page);
|
|
1311
|
-
});
|
|
1260
|
+
resolve(response.json as ContactHistoryPage);
|
|
1312
1261
|
})
|
|
1313
1262
|
.catch(() => {
|
|
1314
1263
|
// canceled
|
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
|
+
};
|
package/src/store/AppState.ts
CHANGED
|
@@ -290,6 +290,8 @@ export const zustand = createStore<AppState>()(
|
|
|
290
290
|
destinations.every((dest) => dest === destinations[0])
|
|
291
291
|
) {
|
|
292
292
|
const targetDestination = destinations[0];
|
|
293
|
+
// Don't reroute if the target is also being removed
|
|
294
|
+
if (uuids.includes(targetDestination)) return;
|
|
293
295
|
|
|
294
296
|
// Find all nodes with exits pointing to the node being removed
|
|
295
297
|
draft.nodes.forEach((node) => {
|
package/src/store/Store.ts
CHANGED
|
@@ -506,7 +506,7 @@ export class Store extends RapidElement {
|
|
|
506
506
|
|
|
507
507
|
public resolveUsers(items: any, keys: string[]): Promise<void> {
|
|
508
508
|
return new Promise<void>((resolve) => {
|
|
509
|
-
const
|
|
509
|
+
const uuids = new Set<string>();
|
|
510
510
|
|
|
511
511
|
// keys are dot notation paths to user fields
|
|
512
512
|
items.forEach((item) => {
|
|
@@ -519,17 +519,17 @@ export class Store extends RapidElement {
|
|
|
519
519
|
break;
|
|
520
520
|
}
|
|
521
521
|
}
|
|
522
|
-
if (value && value.
|
|
523
|
-
|
|
522
|
+
if (value && value.uuid) {
|
|
523
|
+
uuids.add(value.uuid);
|
|
524
524
|
}
|
|
525
525
|
});
|
|
526
526
|
});
|
|
527
527
|
|
|
528
528
|
const promises = [];
|
|
529
529
|
// we don't want to fetch all users at once so we can benefit from caching
|
|
530
|
-
|
|
530
|
+
uuids.forEach((uuid) => {
|
|
531
531
|
promises.push(
|
|
532
|
-
this.getUrl(`/api/v2/users.json?
|
|
532
|
+
this.getUrl(`/api/v2/users.json?uuid=${encodeURIComponent(uuid)}`, {
|
|
533
533
|
force: true
|
|
534
534
|
})
|
|
535
535
|
);
|