@nyaruka/temba-components 0.109.1 → 0.110.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 +19 -2
- package/dist/static/svg/index.svg +1 -1
- package/dist/temba-components.js +362 -355
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/compose/Compose.js +62 -106
- package/out-tsc/src/compose/Compose.js.map +1 -1
- package/out-tsc/src/contacts/ContactChat.js +64 -59
- package/out-tsc/src/contacts/ContactChat.js.map +1 -1
- package/out-tsc/src/vectoricon/index.js +1 -2
- package/out-tsc/src/vectoricon/index.js.map +1 -1
- package/out-tsc/test/temba-compose.test.js +24 -440
- package/out-tsc/test/temba-compose.test.js.map +1 -1
- package/out-tsc/test/temba-contact-chat.test.js +30 -167
- package/out-tsc/test/temba-contact-chat.test.js.map +1 -1
- package/package.json +1 -1
- package/screenshots/truth/compose/attachments-tab.png +0 -0
- package/screenshots/truth/compose/attachments-with-failures.png +0 -0
- package/screenshots/truth/compose/attachments-with-files-and-failures.png +0 -0
- package/screenshots/truth/compose/attachments-with-files-focused.png +0 -0
- package/screenshots/truth/compose/attachments-with-files.png +0 -0
- package/screenshots/truth/compose/intial-text.png +0 -0
- package/screenshots/truth/compose/no-counter.png +0 -0
- package/screenshots/truth/compose/wraps-text-and-spaces.png +0 -0
- package/screenshots/truth/compose/wraps-text-and-url.png +0 -0
- package/screenshots/truth/compose/wraps-text-no-spaces.png +0 -0
- package/screenshots/truth/contacts/chat-failure.png +0 -0
- package/src/compose/Compose.ts +69 -103
- package/src/contacts/ContactChat.ts +69 -70
- package/src/untyped.d.ts +1 -1
- package/src/vectoricon/index.ts +1 -2
- package/static/svg/index.svg +1 -1
- package/test/temba-compose.test.ts +29 -590
- package/test/temba-contact-chat.test.ts +30 -263
- package/web-test-runner.config.mjs +1 -0
- package/screenshots/truth/compose/attachments-and-send-button.png +0 -0
- package/screenshots/truth/compose/attachments-no-send-button.png +0 -0
- package/screenshots/truth/compose/attachments-with-all-files-and-click-send.png +0 -0
- package/screenshots/truth/compose/attachments-with-all-files.png +0 -0
- package/screenshots/truth/compose/attachments-with-failure-files.png +0 -0
- package/screenshots/truth/compose/attachments-with-success-files-and-click-send.png +0 -0
- package/screenshots/truth/compose/attachments-with-success-files.png +0 -0
- package/screenshots/truth/compose/chatbox-attachments-counter-and-send-button.png +0 -0
- package/screenshots/truth/compose/chatbox-attachments-counter-no-send-button.png +0 -0
- package/screenshots/truth/compose/chatbox-attachments-no-counter-and-send-button.png +0 -0
- package/screenshots/truth/compose/chatbox-attachments-no-counter-no-send-button.png +0 -0
- package/screenshots/truth/compose/chatbox-counter-and-send-button.png +0 -0
- package/screenshots/truth/compose/chatbox-counter-no-send-button.png +0 -0
- package/screenshots/truth/compose/chatbox-no-counter-and-send-button.png +0 -0
- package/screenshots/truth/compose/chatbox-no-counter-no-send-button.png +0 -0
- package/screenshots/truth/compose/chatbox-no-text-attachments-with-all-files-and-click-send.png +0 -0
- package/screenshots/truth/compose/chatbox-no-text-attachments-with-all-files.png +0 -0
- package/screenshots/truth/compose/chatbox-no-text-attachments-with-failure-files.png +0 -0
- package/screenshots/truth/compose/chatbox-no-text-attachments-with-success-files-and-click-send.png +0 -0
- package/screenshots/truth/compose/chatbox-no-text-attachments-with-success-files.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-and-click-send.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-and-hit-enter.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-and-spaces.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-and-url.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-attachments-no-files-and-click-send.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-attachments-no-files-and-hit-enter.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-attachments-no-files.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-attachments-with-all-files-and-click-send.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-attachments-with-all-files-and-hit-enter.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-attachments-with-all-files.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-attachments-with-failure-files.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-attachments-with-success-files-and-click-send.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-attachments-with-success-files-and-hit-enter.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-attachments-with-success-files.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text-no-spaces.png +0 -0
- package/screenshots/truth/compose/chatbox-with-text.png +0 -0
- package/screenshots/truth/contacts/compose-attachments-no-text-failure.png +0 -0
- package/screenshots/truth/contacts/compose-text-and-attachments-failure-attachments.png +0 -0
- package/screenshots/truth/contacts/compose-text-and-attachments-failure-generic.png +0 -0
- package/screenshots/truth/contacts/compose-text-and-attachments-failure-text-and-attachments.png +0 -0
- package/screenshots/truth/contacts/compose-text-and-attachments-failure-text.png +0 -0
- package/screenshots/truth/contacts/compose-text-no-attachments-failure.png +0 -0
- package/screenshots/truth/contacts/compose-text-no-attachments-success.png +0 -0
- package/static/svg/work/traced/folder-shield.svg +0 -1
- package/static/svg/work/used/folder-shield.svg +0 -3
- /package/screenshots/truth/contacts/{compose-attachments-no-text-success.png → chat-for-active-contact.png} +0 -0
- /package/screenshots/truth/contacts/{contact-archived-hide-chatbox.png → chat-for-archived-contact.png} +0 -0
- /package/screenshots/truth/contacts/{contact-blocked-hide-chatbox.png → chat-for-blocked-contact.png} +0 -0
- /package/screenshots/truth/contacts/{contact-stopped-hide-chatbox.png → chat-for-stopped-contact.png} +0 -0
- /package/screenshots/truth/contacts/{compose-text-and-attachments-success.png → chat-sends-attachments-only.png} +0 -0
- /package/screenshots/truth/contacts/{contact-active-default.png → chat-sends-text-and-attachments.png} +0 -0
- /package/screenshots/truth/contacts/{contact-active-show-chatbox.png → chat-sends-text-only.png} +0 -0
package/src/compose/Compose.ts
CHANGED
|
@@ -11,6 +11,15 @@ import { Tab } from '../tabpane/Tab';
|
|
|
11
11
|
import { TextInput } from '../textinput/TextInput';
|
|
12
12
|
import { ShortcutList } from '../list/ShortcutList';
|
|
13
13
|
|
|
14
|
+
export interface ComposeValue {
|
|
15
|
+
text: string;
|
|
16
|
+
attachments: { uuid: string }[];
|
|
17
|
+
quick_replies: string[];
|
|
18
|
+
optin: string;
|
|
19
|
+
template: string;
|
|
20
|
+
variables: string[];
|
|
21
|
+
}
|
|
22
|
+
|
|
14
23
|
export class Compose extends FormElement {
|
|
15
24
|
static get styles() {
|
|
16
25
|
return css`
|
|
@@ -81,11 +90,6 @@ export class Compose extends FormElement {
|
|
|
81
90
|
--temba-charcount-summary-bottom: 105px;
|
|
82
91
|
}
|
|
83
92
|
|
|
84
|
-
temba-button {
|
|
85
|
-
--button-y: 1px;
|
|
86
|
-
--button-x: 12px;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
93
|
.send-error {
|
|
90
94
|
color: rgba(250, 0, 0, 0.75);
|
|
91
95
|
font-size: var(--help-text-size);
|
|
@@ -108,10 +112,6 @@ export class Compose extends FormElement {
|
|
|
108
112
|
margin: 0.5em;
|
|
109
113
|
}
|
|
110
114
|
|
|
111
|
-
#send-button {
|
|
112
|
-
margin: 0.3em;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
115
|
temba-tabs {
|
|
116
116
|
--focused-tab-color: #f4f4f4;
|
|
117
117
|
min-height: var(--compose-min-height, 13.5em);
|
|
@@ -179,9 +179,6 @@ export class Compose extends FormElement {
|
|
|
179
179
|
@property({ type: Boolean })
|
|
180
180
|
completion: boolean;
|
|
181
181
|
|
|
182
|
-
@property({ type: Boolean })
|
|
183
|
-
chatbox: boolean;
|
|
184
|
-
|
|
185
182
|
@property({ type: Boolean })
|
|
186
183
|
attachments: boolean;
|
|
187
184
|
|
|
@@ -198,10 +195,10 @@ export class Compose extends FormElement {
|
|
|
198
195
|
counter: boolean;
|
|
199
196
|
|
|
200
197
|
@property({ type: Boolean })
|
|
201
|
-
|
|
198
|
+
autogrow: boolean;
|
|
202
199
|
|
|
203
200
|
@property({ type: Boolean })
|
|
204
|
-
|
|
201
|
+
shortcuts: boolean;
|
|
205
202
|
|
|
206
203
|
@property({ type: String })
|
|
207
204
|
currentText = '';
|
|
@@ -249,14 +246,8 @@ export class Compose extends FormElement {
|
|
|
249
246
|
@property({ type: String })
|
|
250
247
|
templateEndpoint = '/api/internal/templates.json';
|
|
251
248
|
|
|
252
|
-
@property({ type: String })
|
|
253
|
-
buttonName = 'Send';
|
|
254
|
-
|
|
255
249
|
@property({ type: Boolean, attribute: false })
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
@property({ type: String, attribute: false })
|
|
259
|
-
buttonError = '';
|
|
250
|
+
empty = true;
|
|
260
251
|
|
|
261
252
|
@property({ type: Boolean, attribute: 'widget_only' })
|
|
262
253
|
widgetOnly: boolean;
|
|
@@ -371,7 +362,7 @@ export class Compose extends FormElement {
|
|
|
371
362
|
changes.has('currentTemplate') ||
|
|
372
363
|
changes.has('variables')
|
|
373
364
|
) {
|
|
374
|
-
this.
|
|
365
|
+
this.checkIfEmpty();
|
|
375
366
|
|
|
376
367
|
const trimmed = this.currentText ? this.currentText.trim() : '';
|
|
377
368
|
if (
|
|
@@ -405,15 +396,11 @@ export class Compose extends FormElement {
|
|
|
405
396
|
}
|
|
406
397
|
|
|
407
398
|
private setFocusOnChatbox(): void {
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
window.setTimeout(() => {
|
|
414
|
-
completion.focus();
|
|
415
|
-
}, 0);
|
|
416
|
-
}
|
|
399
|
+
const completion = this.shadowRoot.querySelector('.chatbox') as Completion;
|
|
400
|
+
if (completion) {
|
|
401
|
+
window.setTimeout(() => {
|
|
402
|
+
completion.focus();
|
|
403
|
+
}, 0);
|
|
417
404
|
}
|
|
418
405
|
}
|
|
419
406
|
|
|
@@ -425,7 +412,6 @@ export class Compose extends FormElement {
|
|
|
425
412
|
this.currentText = '';
|
|
426
413
|
this.currentQuickReplies = [];
|
|
427
414
|
this.currentAttachments = [];
|
|
428
|
-
this.buttonError = '';
|
|
429
415
|
this.resetTabs();
|
|
430
416
|
}
|
|
431
417
|
|
|
@@ -463,28 +449,16 @@ export class Compose extends FormElement {
|
|
|
463
449
|
}
|
|
464
450
|
}
|
|
465
451
|
|
|
466
|
-
public
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
} else if (this.chatbox) {
|
|
474
|
-
this.buttonDisabled = chatboxEmpty;
|
|
475
|
-
} else if (this.attachments) {
|
|
476
|
-
this.buttonDisabled = attachmentsEmpty;
|
|
477
|
-
} else {
|
|
478
|
-
this.buttonDisabled = true;
|
|
479
|
-
}
|
|
452
|
+
public checkIfEmpty() {
|
|
453
|
+
const chatboxEmpty = this.currentText.trim().length === 0;
|
|
454
|
+
const attachmentsEmpty = this.currentAttachments.length === 0;
|
|
455
|
+
if (this.attachments) {
|
|
456
|
+
this.empty = chatboxEmpty && attachmentsEmpty;
|
|
457
|
+
} else {
|
|
458
|
+
this.empty = chatboxEmpty;
|
|
480
459
|
}
|
|
481
460
|
}
|
|
482
461
|
|
|
483
|
-
private handleSendClick(evt: Event) {
|
|
484
|
-
evt.stopPropagation();
|
|
485
|
-
this.handleSend();
|
|
486
|
-
}
|
|
487
|
-
|
|
488
462
|
private getCurrentLine(): { text: string; index: number } {
|
|
489
463
|
const chatbox = this.shadowRoot.querySelector('.chatbox') as Completion;
|
|
490
464
|
|
|
@@ -535,28 +509,26 @@ export class Compose extends FormElement {
|
|
|
535
509
|
}
|
|
536
510
|
}
|
|
537
511
|
|
|
538
|
-
if (
|
|
539
|
-
if (evt.
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
this.handleSend();
|
|
546
|
-
}
|
|
547
|
-
} else {
|
|
548
|
-
this.handleSend();
|
|
512
|
+
if (evt.key === 'Enter') {
|
|
513
|
+
if (!evt.shiftKey) {
|
|
514
|
+
evt.preventDefault();
|
|
515
|
+
if (this.completion) {
|
|
516
|
+
const chat = evt.target as Completion;
|
|
517
|
+
if (!chat.hasVisibleOptions()) {
|
|
518
|
+
this.triggerSend();
|
|
549
519
|
}
|
|
520
|
+
} else {
|
|
521
|
+
this.triggerSend();
|
|
550
522
|
}
|
|
551
523
|
}
|
|
552
524
|
}
|
|
553
525
|
}
|
|
554
526
|
|
|
555
|
-
|
|
556
|
-
if (!this.
|
|
557
|
-
this.
|
|
558
|
-
|
|
559
|
-
|
|
527
|
+
public triggerSend() {
|
|
528
|
+
if (!this.empty) {
|
|
529
|
+
this.fireCustomEvent(CustomEventType.Submitted, {
|
|
530
|
+
langValues: this.langValues
|
|
531
|
+
});
|
|
560
532
|
}
|
|
561
533
|
}
|
|
562
534
|
|
|
@@ -569,6 +541,10 @@ export class Compose extends FormElement {
|
|
|
569
541
|
(this.shadowRoot.querySelector('temba-tabs') as TabPane).index = 0;
|
|
570
542
|
}
|
|
571
543
|
|
|
544
|
+
public getTabs(): TabPane {
|
|
545
|
+
return this.shadowRoot.querySelector('temba-tabs') as TabPane;
|
|
546
|
+
}
|
|
547
|
+
|
|
572
548
|
public render(): TemplateResult {
|
|
573
549
|
return html`
|
|
574
550
|
<temba-field
|
|
@@ -757,13 +733,19 @@ export class Compose extends FormElement {
|
|
|
757
733
|
borderColor="#ebdf6f"
|
|
758
734
|
></temba-tab-->
|
|
759
735
|
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
736
|
+
${this.shortcuts
|
|
737
|
+
? html`<temba-tab
|
|
738
|
+
name="Shortcuts"
|
|
739
|
+
icon="shortcut"
|
|
740
|
+
selectionBackground="#fff"
|
|
741
|
+
>
|
|
742
|
+
<div class="shortcut-wrapper">
|
|
743
|
+
<temba-shortcuts
|
|
744
|
+
@temba-selection=${this.handleShortcutSelection}
|
|
745
|
+
></temba-shortcuts>
|
|
746
|
+
</div>
|
|
747
|
+
</temba-tab>`
|
|
748
|
+
: null}
|
|
767
749
|
|
|
768
750
|
<div slot="tab-right" class="top-right">
|
|
769
751
|
${this.counter ? this.getCounter() : null}
|
|
@@ -773,24 +755,19 @@ export class Compose extends FormElement {
|
|
|
773
755
|
slot="pane-bottom"
|
|
774
756
|
class="pane-bottom ${this.hasPendingText ? 'pending' : ''}"
|
|
775
757
|
>
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
</temba-completion>`
|
|
790
|
-
: null}
|
|
791
|
-
${this.buttonError
|
|
792
|
-
? html`<div class="send-error">${this.buttonError}</div>`
|
|
793
|
-
: null}
|
|
758
|
+
<temba-completion
|
|
759
|
+
class="chatbox"
|
|
760
|
+
.value=${this.initialText}
|
|
761
|
+
gsm
|
|
762
|
+
textarea
|
|
763
|
+
?disableCompletion=${!this.completion}
|
|
764
|
+
?autogrow=${this.autogrow}
|
|
765
|
+
maxlength=${this.maxLength}
|
|
766
|
+
@change=${this.handleChatboxChange}
|
|
767
|
+
@keydown=${this.handleKeyDown}
|
|
768
|
+
placeholder="Write something here"
|
|
769
|
+
>
|
|
770
|
+
</temba-completion>
|
|
794
771
|
</div>
|
|
795
772
|
</temba-tabs>
|
|
796
773
|
`;
|
|
@@ -801,15 +778,4 @@ export class Compose extends FormElement {
|
|
|
801
778
|
.text="${this.currentText}"
|
|
802
779
|
></temba-charcount>`;
|
|
803
780
|
}
|
|
804
|
-
|
|
805
|
-
private getButton(): TemplateResult {
|
|
806
|
-
return html`<temba-icon
|
|
807
|
-
tabindex="1"
|
|
808
|
-
class="send-icon"
|
|
809
|
-
name="send"
|
|
810
|
-
size="1"
|
|
811
|
-
clickable
|
|
812
|
-
@click=${this.handleSendClick}
|
|
813
|
-
></temba-icon>`;
|
|
814
|
-
}
|
|
815
781
|
}
|
|
@@ -4,7 +4,7 @@ import { property } from 'lit/decorators.js';
|
|
|
4
4
|
import { Contact, CustomEventType, Ticket } from '../interfaces';
|
|
5
5
|
import { oxford, oxfordFn, postJSON } from '../utils';
|
|
6
6
|
import { ContactStoreElement } from './ContactStoreElement';
|
|
7
|
-
import { Compose } from '../compose/Compose';
|
|
7
|
+
import { Compose, ComposeValue } from '../compose/Compose';
|
|
8
8
|
import { fetchContactHistory, getDisplayName } from './helpers';
|
|
9
9
|
import {
|
|
10
10
|
AirtimeTransferredEvent,
|
|
@@ -319,6 +319,20 @@ export class ContactChat extends ContactStoreElement {
|
|
|
319
319
|
border-top-right-radius: 0;
|
|
320
320
|
border-top-left-radius: 0;
|
|
321
321
|
}
|
|
322
|
+
|
|
323
|
+
.error-gutter {
|
|
324
|
+
display: flex;
|
|
325
|
+
padding: 0.5em 1em;
|
|
326
|
+
background: #f9f9f9;
|
|
327
|
+
item-align: center;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
.error-message {
|
|
331
|
+
color: var(--color-error);
|
|
332
|
+
padding-right: 1em;
|
|
333
|
+
flex-grow: 1;
|
|
334
|
+
align-self: center;
|
|
335
|
+
}
|
|
322
336
|
`;
|
|
323
337
|
}
|
|
324
338
|
|
|
@@ -349,6 +363,9 @@ export class ContactChat extends ContactStoreElement {
|
|
|
349
363
|
@property({ type: String })
|
|
350
364
|
avatar = DEFAULT_AVATAR;
|
|
351
365
|
|
|
366
|
+
@property({ type: String })
|
|
367
|
+
errorMessage: string;
|
|
368
|
+
|
|
352
369
|
// http promise to monitor for completeness
|
|
353
370
|
public httpComplete: Promise<void>;
|
|
354
371
|
private chat: Chat;
|
|
@@ -408,81 +425,55 @@ export class ContactChat extends ContactStoreElement {
|
|
|
408
425
|
this.newestEventTime = null;
|
|
409
426
|
this.refreshId = null;
|
|
410
427
|
this.polling = false;
|
|
428
|
+
this.errorMessage = null;
|
|
411
429
|
}
|
|
412
430
|
|
|
413
431
|
public refresh() {
|
|
414
432
|
this.checkForNewMessages();
|
|
415
433
|
}
|
|
416
434
|
|
|
435
|
+
private handleRetry() {
|
|
436
|
+
const compose = this.shadowRoot.querySelector('temba-compose') as Compose;
|
|
437
|
+
compose.triggerSend();
|
|
438
|
+
}
|
|
439
|
+
|
|
417
440
|
private handleSend(evt: CustomEvent) {
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
contact: this.currentContact.uuid
|
|
422
|
-
};
|
|
423
|
-
const compose = evt.currentTarget as Compose;
|
|
424
|
-
if (compose) {
|
|
425
|
-
const text = compose.currentText;
|
|
426
|
-
if (text && text.length > 0) {
|
|
427
|
-
payload['text'] = text;
|
|
428
|
-
}
|
|
429
|
-
const attachments = compose.currentAttachments;
|
|
430
|
-
if (attachments && attachments.length > 0) {
|
|
431
|
-
const attachment_uuids = attachments.map(
|
|
432
|
-
(attachment) => attachment.uuid
|
|
433
|
-
);
|
|
434
|
-
payload['attachments'] = attachment_uuids;
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
if (this.currentTicket) {
|
|
438
|
-
payload['ticket'] = this.currentTicket.uuid;
|
|
439
|
-
}
|
|
441
|
+
this.errorMessage = null;
|
|
442
|
+
const composeEle = evt.currentTarget as Compose;
|
|
443
|
+
const compose = evt.detail.langValues['und'] as ComposeValue;
|
|
440
444
|
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
'Ensure this field has no more than',
|
|
458
|
-
'Maximum allowed text is'
|
|
459
|
-
);
|
|
460
|
-
compose.buttonError = textError;
|
|
461
|
-
} else if (
|
|
462
|
-
response.json.attachments &&
|
|
463
|
-
response.json.attachments.length > 0 &&
|
|
464
|
-
response.json.attachments[0].length > 0
|
|
465
|
-
) {
|
|
466
|
-
let attachmentError = response.json.attachments[0];
|
|
467
|
-
attachmentError = attachmentError
|
|
468
|
-
.replace(
|
|
469
|
-
'Ensure this field has no more than',
|
|
470
|
-
'Maximum allowed attachments is'
|
|
471
|
-
)
|
|
472
|
-
.replace('elements', 'files');
|
|
473
|
-
compose.buttonError = attachmentError;
|
|
474
|
-
} else {
|
|
475
|
-
compose.buttonError = genericError;
|
|
476
|
-
}
|
|
477
|
-
} else {
|
|
478
|
-
compose.buttonError = genericError;
|
|
479
|
-
}
|
|
480
|
-
})
|
|
481
|
-
.catch((error) => {
|
|
482
|
-
console.error(error);
|
|
483
|
-
compose.buttonError = genericError;
|
|
484
|
-
});
|
|
445
|
+
const payload = {
|
|
446
|
+
contact: this.currentContact.uuid
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
const text = compose.text;
|
|
450
|
+
if (text && text.length > 0) {
|
|
451
|
+
payload['text'] = text;
|
|
452
|
+
}
|
|
453
|
+
const attachments = compose.attachments;
|
|
454
|
+
if (attachments && attachments.length > 0) {
|
|
455
|
+
const attachment_uuids = attachments.map((attachment) => attachment.uuid);
|
|
456
|
+
payload['attachments'] = attachment_uuids;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
if (this.currentTicket) {
|
|
460
|
+
payload['ticket'] = this.currentTicket.uuid;
|
|
485
461
|
}
|
|
462
|
+
|
|
463
|
+
const genericError = 'Send failed, please try again.';
|
|
464
|
+
postJSON(`/api/v2/messages.json`, payload)
|
|
465
|
+
.then((response) => {
|
|
466
|
+
if (response.status < 400) {
|
|
467
|
+
this.checkForNewMessages();
|
|
468
|
+
composeEle.reset();
|
|
469
|
+
this.fireCustomEvent(CustomEventType.MessageSent, { msg: payload });
|
|
470
|
+
} else {
|
|
471
|
+
this.errorMessage = genericError;
|
|
472
|
+
}
|
|
473
|
+
})
|
|
474
|
+
.catch(() => {
|
|
475
|
+
this.errorMessage = genericError;
|
|
476
|
+
});
|
|
486
477
|
}
|
|
487
478
|
|
|
488
479
|
public render(): TemplateResult {
|
|
@@ -881,14 +872,22 @@ export class ContactChat extends ContactStoreElement {
|
|
|
881
872
|
return html`<div class="border"></div>
|
|
882
873
|
<div class="compose">
|
|
883
874
|
<temba-compose
|
|
884
|
-
chatbox
|
|
885
875
|
attachments
|
|
886
876
|
counter
|
|
887
|
-
button
|
|
888
877
|
autogrow
|
|
889
|
-
|
|
878
|
+
shortcuts
|
|
879
|
+
@temba-submitted=${this.handleSend.bind(this)}
|
|
890
880
|
>
|
|
891
881
|
</temba-compose>
|
|
882
|
+
${this.errorMessage
|
|
883
|
+
? html` <div class="error-gutter">
|
|
884
|
+
<div class="error-message">${this.errorMessage}</div>
|
|
885
|
+
<temba-button
|
|
886
|
+
name="Retry"
|
|
887
|
+
@click=${this.handleRetry}
|
|
888
|
+
></temba-button>
|
|
889
|
+
</div>`
|
|
890
|
+
: null}
|
|
892
891
|
</div>`;
|
|
893
892
|
}
|
|
894
893
|
}
|
package/src/untyped.d.ts
CHANGED
package/src/vectoricon/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-duplicate-enum-values */
|
|
2
2
|
// for cache busting we dynamically generate a fingerprint, use yarn svg to update
|
|
3
|
-
export const SVG_FINGERPRINT = '
|
|
3
|
+
export const SVG_FINGERPRINT = 'f3e1cdc8bc9f2e47455a9ef0f7fe4baf';
|
|
4
4
|
|
|
5
5
|
// only icons below are included in the sprite sheet
|
|
6
6
|
export enum Icon {
|
|
@@ -154,7 +154,6 @@ export enum Icon {
|
|
|
154
154
|
staff = 'hard-drive',
|
|
155
155
|
submit = 'check',
|
|
156
156
|
success = 'check',
|
|
157
|
-
team = 'folder-shield',
|
|
158
157
|
template_approved = 'check-circle',
|
|
159
158
|
template_pending = 'hourglass-01',
|
|
160
159
|
template_rejected = 'alert-circle',
|