@servicetitan/titan-chat-ui 1.1.2 → 2.0.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 +12 -0
- package/dist/components/chat/__tests-cy__/chat-messages.test.js +69 -1
- package/dist/components/chat/__tests-cy__/chat-messages.test.js.map +1 -1
- package/dist/components/chat/chat-input.js +2 -2
- package/dist/components/chat/chat-input.js.map +1 -1
- package/dist/components/chat/chat-log.d.ts +8 -0
- package/dist/components/chat/chat-log.d.ts.map +1 -0
- package/dist/components/chat/chat-log.js +15 -0
- package/dist/components/chat/chat-log.js.map +1 -0
- package/dist/components/chat/chat-message-template-agent.d.ts.map +1 -1
- package/dist/components/chat/chat-message-template-agent.js +2 -2
- package/dist/components/chat/chat-message-template-agent.js.map +1 -1
- package/dist/components/chat/chat-message-template-user.js +2 -2
- package/dist/components/chat/chat-message-template-user.js.map +1 -1
- package/dist/components/chat/chat-message.d.ts +1 -5
- package/dist/components/chat/chat-message.d.ts.map +1 -1
- package/dist/components/chat/chat-message.js +4 -4
- package/dist/components/chat/chat-message.js.map +1 -1
- package/dist/components/chat/chat-messages.d.ts +3 -0
- package/dist/components/chat/chat-messages.d.ts.map +1 -1
- package/dist/components/chat/chat-messages.js +35 -7
- package/dist/components/chat/chat-messages.js.map +1 -1
- package/dist/components/chat/chat.d.ts.map +1 -1
- package/dist/components/chat/chat.js +3 -1
- package/dist/components/chat/chat.js.map +1 -1
- package/dist/components/messages/__tests-cy__/message-agent.test.js +1 -1
- package/dist/components/messages/__tests-cy__/message-agent.test.js.map +1 -1
- package/dist/components/messages/message-agent.d.ts +1 -0
- package/dist/components/messages/message-agent.d.ts.map +1 -1
- package/dist/components/messages/message-agent.js +2 -4
- package/dist/components/messages/message-agent.js.map +1 -1
- package/dist/components/messages/message-agent.module.less +29 -37
- package/dist/components/messages/message-footer.d.ts +1 -1
- package/dist/components/messages/message-footer.d.ts.map +1 -1
- package/dist/components/messages/message-footer.js +1 -1
- package/dist/components/messages/message-footer.js.map +1 -1
- package/dist/components/messages/message-user.js +2 -2
- package/dist/components/messages/message-user.js.map +1 -1
- package/dist/components/messages/message-user.module.less +3 -6
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/models/chat-customizations.d.ts +14 -6
- package/dist/models/chat-customizations.d.ts.map +1 -1
- package/dist/models/support-chat.d.ts +4 -4
- package/dist/models/support-chat.d.ts.map +1 -1
- package/dist/models/support-chat.js +18 -0
- package/dist/models/support-chat.js.map +1 -1
- package/dist/stores/__mocks-cy__/chat-ui.store.mock.d.ts +6 -1
- package/dist/stores/__mocks-cy__/chat-ui.store.mock.d.ts.map +1 -1
- package/dist/stores/__mocks-cy__/chat-ui.store.mock.js +30 -0
- package/dist/stores/__mocks-cy__/chat-ui.store.mock.js.map +1 -1
- package/dist/stores/__tests__/chat-input.store.test.d.ts +2 -0
- package/dist/stores/__tests__/chat-input.store.test.d.ts.map +1 -0
- package/dist/stores/__tests__/chat-input.store.test.js +32 -0
- package/dist/stores/__tests__/chat-input.store.test.js.map +1 -0
- package/dist/stores/chat-ui.store.d.ts +19 -10
- package/dist/stores/chat-ui.store.d.ts.map +1 -1
- package/dist/stores/chat-ui.store.js +47 -48
- package/dist/stores/chat-ui.store.js.map +1 -1
- package/dist/utils/test-utils.d.ts +5 -0
- package/dist/utils/test-utils.d.ts.map +1 -0
- package/dist/utils/test-utils.js +17 -0
- package/dist/utils/test-utils.js.map +1 -0
- package/package.json +2 -2
- package/src/components/chat/__tests-cy__/chat-messages.test.tsx +78 -1
- package/src/components/chat/chat-input.tsx +4 -4
- package/src/components/chat/chat-log.tsx +29 -0
- package/src/components/chat/chat-message-template-agent.tsx +7 -3
- package/src/components/chat/chat-message-template-user.tsx +3 -3
- package/src/components/chat/chat-message.tsx +58 -52
- package/src/components/chat/chat-messages.tsx +55 -11
- package/src/components/chat/chat.tsx +14 -8
- package/src/components/messages/__tests-cy__/message-agent.test.tsx +1 -1
- package/src/components/messages/message-agent.module.less +29 -37
- package/src/components/messages/message-agent.module.less.d.ts +0 -1
- package/src/components/messages/message-agent.tsx +4 -4
- package/src/components/messages/message-footer.tsx +4 -3
- package/src/components/messages/message-user.module.less +3 -6
- package/src/components/messages/message-user.tsx +5 -5
- package/src/index.ts +3 -0
- package/src/models/chat-customizations.ts +17 -6
- package/src/models/support-chat.ts +22 -10
- package/src/stores/__mocks-cy__/chat-ui.store.mock.ts +6 -0
- package/src/stores/__tests__/chat-input.store.test.ts +39 -0
- package/src/stores/chat-ui.store.ts +54 -55
- package/src/utils/test-utils.ts +22 -0
- package/tsconfig.json +1 -2
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -13,7 +13,6 @@ import {
|
|
|
13
13
|
ChatMessageModelFile,
|
|
14
14
|
ChatMessageModelText,
|
|
15
15
|
ChatMessageModelTimeout,
|
|
16
|
-
ChatMessageModelType,
|
|
17
16
|
ChatMessageModelWelcome,
|
|
18
17
|
ChatMessageState,
|
|
19
18
|
ChatParticipantIcon,
|
|
@@ -29,12 +28,15 @@ export enum ChatUiEvent {
|
|
|
29
28
|
eventRun = 'eventRun',
|
|
30
29
|
eventDestroy = 'eventDestroy',
|
|
31
30
|
eventRestart = 'eventRestart',
|
|
31
|
+
eventCancel = 'eventCancel',
|
|
32
|
+
eventEndChat = 'eventEndChat',
|
|
32
33
|
eventRecover = 'eventRecover',
|
|
33
34
|
eventChasitorTyping = 'eventChasitorTyping',
|
|
34
35
|
eventTimerRestart = 'eventTimerRestart',
|
|
35
36
|
eventMessageSend = 'eventMessageSend',
|
|
36
|
-
eventMessageSendFile = 'eventMessageSendFile',
|
|
37
37
|
eventMessageSendRetry = 'eventMessageSendRetry',
|
|
38
|
+
eventMessageSendFile = 'eventMessageSendFile',
|
|
39
|
+
eventMessageSendFileRetry = 'eventMessageSendFileRetry',
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
export type ChatUiEventListener<T = void> = (
|
|
@@ -82,6 +84,8 @@ export interface IChatUiStore<T extends ChatCustomizations = ChatCustomizations>
|
|
|
82
84
|
setError<T = any>(message: string, options?: ChatErrorOptions<T>): void;
|
|
83
85
|
setStatus(status: ChatRunState): void;
|
|
84
86
|
resetError(runState: ChatRunState): void;
|
|
87
|
+
reset(resetStatus?: boolean): void;
|
|
88
|
+
resetFile(): void;
|
|
85
89
|
|
|
86
90
|
triggerScroll(): void;
|
|
87
91
|
configure(configuration?: ChatConfiguration): void;
|
|
@@ -90,6 +94,9 @@ export interface IChatUiStore<T extends ChatCustomizations = ChatCustomizations>
|
|
|
90
94
|
destroy(): Promise<void>;
|
|
91
95
|
chasitorTyping(isTyping: boolean): Promise<void>;
|
|
92
96
|
restartTimers(): Promise<void>;
|
|
97
|
+
restart(): Promise<void>;
|
|
98
|
+
cancelChat(): Promise<void>;
|
|
99
|
+
endChat(endReason?: ChatEndReason): Promise<void>;
|
|
93
100
|
sendMessageText(messageText: string): Promise<void>;
|
|
94
101
|
sendMessageRetry(message: ChatMessageModelBase): Promise<void>;
|
|
95
102
|
addMessage(isAgent: boolean, message: string, data?: any): void;
|
|
@@ -306,24 +313,21 @@ export class ChatUiStore<T extends ChatCustomizations> implements IChatUiStore<T
|
|
|
306
313
|
await this.emitAsync(ChatUiEvent.eventDestroy);
|
|
307
314
|
}
|
|
308
315
|
|
|
309
|
-
restart() {
|
|
316
|
+
async restart() {
|
|
310
317
|
this.reset();
|
|
311
|
-
this.
|
|
318
|
+
await this.emitAsync(ChatUiEvent.eventRestart);
|
|
312
319
|
}
|
|
313
320
|
|
|
314
|
-
cancelChat() {
|
|
315
|
-
this.
|
|
321
|
+
async cancelChat() {
|
|
322
|
+
await this.emitAsync(ChatUiEvent.eventCancel);
|
|
316
323
|
}
|
|
317
324
|
|
|
318
|
-
endChat() {
|
|
319
|
-
this.
|
|
325
|
+
async endChat(endReason?: ChatEndReason) {
|
|
326
|
+
await this.emitAsync(ChatUiEvent.eventEndChat, endReason);
|
|
320
327
|
}
|
|
321
328
|
|
|
322
329
|
async chasitorTyping(isTyping: boolean) {
|
|
323
|
-
await this.emitAsync(
|
|
324
|
-
ChatUiEvent.eventChasitorTyping,
|
|
325
|
-
isTyping ? 'chasitorTyping' : 'chasitorNotTyping'
|
|
326
|
-
);
|
|
330
|
+
await this.emitAsync(ChatUiEvent.eventChasitorTyping, isTyping);
|
|
327
331
|
}
|
|
328
332
|
|
|
329
333
|
@action
|
|
@@ -358,10 +362,10 @@ export class ChatUiStore<T extends ChatCustomizations> implements IChatUiStore<T
|
|
|
358
362
|
}
|
|
359
363
|
|
|
360
364
|
@action
|
|
361
|
-
sendMessageFileRetry(messageModel: ChatMessageModelFile) {
|
|
365
|
+
async sendMessageFileRetry(messageModel: ChatMessageModelFile) {
|
|
362
366
|
this.resetError(ChatRunState.Started);
|
|
363
367
|
this.setMessageState(messageModel, ChatMessageState.Delivering);
|
|
364
|
-
this.
|
|
368
|
+
await this.emitAsync(ChatUiEvent.eventMessageSendFileRetry, messageModel);
|
|
365
369
|
}
|
|
366
370
|
|
|
367
371
|
getParticipant(participantKey: symbol): ChatParticipantModel {
|
|
@@ -431,6 +435,26 @@ export class ChatUiStore<T extends ChatCustomizations> implements IChatUiStore<T
|
|
|
431
435
|
}
|
|
432
436
|
}
|
|
433
437
|
|
|
438
|
+
@action
|
|
439
|
+
resetFile() {
|
|
440
|
+
this.currentFileMessage = undefined;
|
|
441
|
+
this.file = undefined;
|
|
442
|
+
this.isFilePickerEnabled = false;
|
|
443
|
+
this.triggerScroll();
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
@action
|
|
447
|
+
reset(resetStatus = true) {
|
|
448
|
+
this.setMessages([]);
|
|
449
|
+
if (resetStatus) {
|
|
450
|
+
this.status = ChatRunState.Offline;
|
|
451
|
+
}
|
|
452
|
+
this.error = undefined;
|
|
453
|
+
this.isAgentTyping = false;
|
|
454
|
+
this.endReason = undefined;
|
|
455
|
+
this.resetFile();
|
|
456
|
+
}
|
|
457
|
+
|
|
434
458
|
getLastFailedMessages() {
|
|
435
459
|
const result: ChatMessageModelText[] = [];
|
|
436
460
|
for (let i = this.messages.length - 1; i >= 0; i--) {
|
|
@@ -453,26 +477,6 @@ export class ChatUiStore<T extends ChatCustomizations> implements IChatUiStore<T
|
|
|
453
477
|
}, 0);
|
|
454
478
|
}
|
|
455
479
|
|
|
456
|
-
@action
|
|
457
|
-
protected reset(resetStatus = true) {
|
|
458
|
-
this.setMessages([]);
|
|
459
|
-
if (resetStatus) {
|
|
460
|
-
this.status = ChatRunState.Offline;
|
|
461
|
-
}
|
|
462
|
-
this.error = undefined;
|
|
463
|
-
this.isAgentTyping = false;
|
|
464
|
-
this.endReason = undefined;
|
|
465
|
-
this.resetFile();
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
@action
|
|
469
|
-
protected resetFile() {
|
|
470
|
-
this.currentFileMessage = undefined;
|
|
471
|
-
this.file = undefined;
|
|
472
|
-
this.isFilePickerEnabled = false;
|
|
473
|
-
this.triggerScroll();
|
|
474
|
-
}
|
|
475
|
-
|
|
476
480
|
protected async emitAsync<T>(event: string, ...args: unknown[]) {
|
|
477
481
|
if (!this.eventEmitter.listenerCount(event)) {
|
|
478
482
|
return Promise.resolve();
|
|
@@ -482,23 +486,14 @@ export class ChatUiStore<T extends ChatCustomizations> implements IChatUiStore<T
|
|
|
482
486
|
});
|
|
483
487
|
}
|
|
484
488
|
|
|
485
|
-
|
|
486
|
-
if (message.trim() === '') {
|
|
487
|
-
return;
|
|
488
|
-
}
|
|
489
|
-
const messageModel = this.addMessage(false, message);
|
|
490
|
-
await this.emitAsync(ChatUiEvent.eventMessageSend, messageModel);
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
private addMessageInternal<T extends ChatMessageModelBase>(
|
|
489
|
+
protected addMessageInternal<T extends ChatMessageModelBase>(
|
|
494
490
|
message: Omit<T, 'id' | 'timestamp'>
|
|
495
491
|
): T {
|
|
496
492
|
if (message.type === 'timeout') {
|
|
497
493
|
this.removeMessageByType('timeout'); // Remove previous timeout messages
|
|
498
494
|
} else {
|
|
499
|
-
this.restartTimers();
|
|
495
|
+
this.restartTimers().then(() => {});
|
|
500
496
|
}
|
|
501
|
-
this.removeAskSupportButtons();
|
|
502
497
|
const newMessage = this.createMessage<T>(message);
|
|
503
498
|
this.setMessages([...this.messages, newMessage]);
|
|
504
499
|
if (message.participant.isAgent) {
|
|
@@ -507,6 +502,20 @@ export class ChatUiStore<T extends ChatCustomizations> implements IChatUiStore<T
|
|
|
507
502
|
return newMessage;
|
|
508
503
|
}
|
|
509
504
|
|
|
505
|
+
protected removeMessageByType(type: string) {
|
|
506
|
+
if (this.messages.some(m => m.type === type)) {
|
|
507
|
+
this.setMessages(this.messages.filter(m => m.type !== type));
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
private async sendMessageTextInternal(message: string) {
|
|
512
|
+
if (message.trim() === '') {
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
const messageModel = this.addMessage(false, message);
|
|
516
|
+
await this.emitAsync(ChatUiEvent.eventMessageSend, messageModel);
|
|
517
|
+
}
|
|
518
|
+
|
|
510
519
|
private createMessage<T extends ChatMessageModelBase>(rest: Omit<T, 'id' | 'timestamp'>) {
|
|
511
520
|
return {
|
|
512
521
|
id: nanoid(),
|
|
@@ -528,14 +537,4 @@ export class ChatUiStore<T extends ChatCustomizations> implements IChatUiStore<T
|
|
|
528
537
|
this.incomingMessageSoundPromise = undefined;
|
|
529
538
|
}
|
|
530
539
|
}
|
|
531
|
-
|
|
532
|
-
private removeMessageByType(type: ChatMessageModelType) {
|
|
533
|
-
if (this.messages.some(m => m.type === type)) {
|
|
534
|
-
this.setMessages(this.messages.filter(m => m.type !== type));
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
private removeAskSupportButtons() {
|
|
539
|
-
this.removeMessageByType('askSupportButtons');
|
|
540
|
-
}
|
|
541
540
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Container } from '@servicetitan/react-ioc';
|
|
2
|
+
|
|
3
|
+
type Newable<T> = new (...args: never[]) => T;
|
|
4
|
+
|
|
5
|
+
export const initTestContainer = (
|
|
6
|
+
serviceIdentifier: Newable<unknown> | Newable<unknown>[],
|
|
7
|
+
initDependenciesFn: (container: Container) => void
|
|
8
|
+
) => {
|
|
9
|
+
const rootContainer = new Container();
|
|
10
|
+
if (Array.isArray(serviceIdentifier)) {
|
|
11
|
+
serviceIdentifier.forEach(identifier => rootContainer.bind(identifier).toSelf());
|
|
12
|
+
} else {
|
|
13
|
+
rootContainer.bind(serviceIdentifier).toSelf();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return () => {
|
|
17
|
+
const container = new Container();
|
|
18
|
+
container.parent = rootContainer;
|
|
19
|
+
initDependenciesFn(container);
|
|
20
|
+
return container;
|
|
21
|
+
};
|
|
22
|
+
};
|