@microsoft/omnichannel-chat-widget 1.7.8-main.9e74278 → 1.7.8-main.bd4de53

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.
Files changed (43) hide show
  1. package/lib/cjs/common/telemetry/TelemetryConstants.js +5 -0
  2. package/lib/cjs/components/chatbuttonstateful/ChatButtonStateful.js +4 -5
  3. package/lib/cjs/components/headerstateful/HeaderStateful.js +3 -5
  4. package/lib/cjs/components/livechatwidget/common/ActivitySubscriber/BotAuthActivitySubscriber.js +4 -1
  5. package/lib/cjs/components/livechatwidget/common/chatDisconnectHelper.js +3 -1
  6. package/lib/cjs/components/livechatwidget/common/endChat.js +4 -18
  7. package/lib/cjs/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +17 -11
  8. package/lib/cjs/components/ooohpanestateful/OOOHPaneStateful.js +9 -3
  9. package/lib/cjs/components/postchatsurveypanestateful/PostChatSurveyPaneStateful.js +22 -6
  10. package/lib/cjs/components/postchatsurveypanestateful/common/isValidSurveyUrl.js +28 -0
  11. package/lib/cjs/components/webchatcontainerstateful/WebChatContainerStateful.js +4 -3
  12. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/timestamps/DeliveredTimestamp.js +4 -0
  13. package/lib/cjs/contexts/common/LiveChatWidgetContextInitialState.js +18 -6
  14. package/lib/cjs/firstresponselatency/Constants.js +13 -0
  15. package/lib/cjs/firstresponselatency/FirstResponseLatencyTracker.js +152 -0
  16. package/lib/cjs/firstresponselatency/util.js +85 -0
  17. package/lib/cjs/plugins/createChatTranscript.js +4 -4
  18. package/lib/cjs/plugins/newMessageEventHandler.js +102 -88
  19. package/lib/esm/common/telemetry/TelemetryConstants.js +5 -0
  20. package/lib/esm/components/chatbuttonstateful/ChatButtonStateful.js +4 -5
  21. package/lib/esm/components/headerstateful/HeaderStateful.js +3 -5
  22. package/lib/esm/components/livechatwidget/common/ActivitySubscriber/BotAuthActivitySubscriber.js +4 -1
  23. package/lib/esm/components/livechatwidget/common/chatDisconnectHelper.js +3 -1
  24. package/lib/esm/components/livechatwidget/common/endChat.js +4 -18
  25. package/lib/esm/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +17 -11
  26. package/lib/esm/components/ooohpanestateful/OOOHPaneStateful.js +9 -3
  27. package/lib/esm/components/postchatsurveypanestateful/PostChatSurveyPaneStateful.js +22 -6
  28. package/lib/esm/components/postchatsurveypanestateful/common/isValidSurveyUrl.js +21 -0
  29. package/lib/esm/components/webchatcontainerstateful/WebChatContainerStateful.js +4 -3
  30. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/timestamps/DeliveredTimestamp.js +4 -0
  31. package/lib/esm/contexts/common/LiveChatWidgetContextInitialState.js +18 -6
  32. package/lib/esm/firstresponselatency/Constants.js +6 -0
  33. package/lib/esm/firstresponselatency/FirstResponseLatencyTracker.js +145 -0
  34. package/lib/esm/firstresponselatency/util.js +75 -0
  35. package/lib/esm/plugins/createChatTranscript.js +4 -4
  36. package/lib/esm/plugins/newMessageEventHandler.js +100 -86
  37. package/lib/types/common/telemetry/TelemetryConstants.d.ts +5 -0
  38. package/lib/types/components/postchatsurveypanestateful/common/isValidSurveyUrl.d.ts +2 -0
  39. package/lib/types/contexts/common/ILiveChatWidgetContext.d.ts +1 -1
  40. package/lib/types/firstresponselatency/Constants.d.ts +30 -0
  41. package/lib/types/firstresponselatency/FirstResponseLatencyTracker.d.ts +17 -0
  42. package/lib/types/firstresponselatency/util.d.ts +6 -0
  43. package/package.json +1 -1
@@ -1,100 +1,114 @@
1
1
  import { BroadcastEvent, LogLevel, TelemetryEvent } from "../common/telemetry/TelemetryConstants";
2
+ import { ScenarioType } from "../firstresponselatency/Constants";
3
+ import { buildMessagePayload, getScenarioType, isHistoryMessage, polyfillMessagePayloadForEvent } from "../firstresponselatency/util";
2
4
  import { BroadcastService } from "@microsoft/omnichannel-chat-components";
3
5
  import { Constants } from "../common/Constants";
6
+ import { FirstResponseLatencyTracker } from "../firstresponselatency/FirstResponseLatencyTracker";
4
7
  import { TelemetryHelper } from "../common/telemetry/TelemetryHelper";
5
8
  import { TelemetryManager } from "../common/telemetry/TelemetryManager";
6
9
  export const createOnNewAdapterActivityHandler = (chatId, userId) => {
10
+ // Hooking the message tracker in the listener, a bit invasive but easier to control.
11
+ const firstResponseLatencyTracker = new FirstResponseLatencyTracker();
12
+ // epoch time in utc for when start to listen.
13
+ // We dont longer have a mechanism to know if a message is history or new, so any message older than the time we start listening will be considered a history message.
14
+ // this is a workaround for the fact that we dont have a way to identify if a message is history or new, and it will provide consistency across different scenarios
15
+ const startTime = new Date().getTime();
16
+ let isHistoryMessageReceivedEventRaised = false;
7
17
  const onNewAdapterActivityHandler = activity => {
8
- var _activity$channelData, _activity$channelData2, _activity$channelData3;
9
- const isActivityMessage = (activity === null || activity === void 0 ? void 0 : activity.type) === Constants.message;
10
- const isHistoryMessage = isActivityMessage && ((activity === null || activity === void 0 ? void 0 : (_activity$channelData = activity.channelData) === null || _activity$channelData === void 0 ? void 0 : (_activity$channelData2 = _activity$channelData.tags) === null || _activity$channelData2 === void 0 ? void 0 : _activity$channelData2.includes(Constants.historyMessageTag)) || (activity === null || activity === void 0 ? void 0 : (_activity$channelData3 = activity.channelData) === null || _activity$channelData3 === void 0 ? void 0 : _activity$channelData3.fromList));
11
- raiseMessageEvent(activity, isHistoryMessage);
18
+ raiseMessageEvent(activity);
12
19
  };
13
- let isHistoryMessageReceivedEventRasied = false;
14
- const raiseMessageEvent = (activity, isHistoryMessage) => {
20
+ const userSendMessageStrategy = activity => {
21
+ var _TelemetryManager$Int;
22
+ const payload = buildMessagePayload(activity, userId);
15
23
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
16
- const polyfillMessagePayloadForEvent = payload => {
17
- var _activity$conversatio, _TelemetryManager$Int, _attachments;
18
- return {
19
- ...payload,
20
- channelData: activity === null || activity === void 0 ? void 0 : activity.channelData,
21
- chatId: activity === null || activity === void 0 ? void 0 : (_activity$conversatio = activity.conversation) === null || _activity$conversatio === void 0 ? void 0 : _activity$conversatio.id,
22
- conversationId: (_TelemetryManager$Int = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int === void 0 ? void 0 : _TelemetryManager$Int.conversationId,
23
- id: activity === null || activity === void 0 ? void 0 : activity.id,
24
- isChatComplete: false,
25
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
- text: activity === null || activity === void 0 ? void 0 : activity.text,
27
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
- attachment: (activity === null || activity === void 0 ? void 0 : (_attachments = activity.attachments) === null || _attachments === void 0 ? void 0 : _attachments.length) >= 1 ? activity === null || activity === void 0 ? void 0 : activity.attachments : []
29
- };
24
+ payload.messageType = Constants.userMessageTag;
25
+ const newMessageSentEvent = {
26
+ eventName: BroadcastEvent.NewMessageSent,
27
+ payload: polyfillMessagePayloadForEvent(activity, payload, (_TelemetryManager$Int = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int === void 0 ? void 0 : _TelemetryManager$Int.conversationId)
30
28
  };
29
+ BroadcastService.postMessage(newMessageSentEvent);
30
+ if (!isHistoryMessage(activity, startTime)) {
31
+ firstResponseLatencyTracker.startClock(payload);
32
+ }
33
+ TelemetryHelper.logActionEvent(LogLevel.INFO, {
34
+ Event: TelemetryEvent.MessageSent,
35
+ Description: "New message sent"
36
+ });
37
+ };
38
+ const systemMessageStrategy = activity => {
39
+ const payload = buildMessagePayload(activity, userId);
40
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
41
+ payload.messageType = Constants.systemMessageTag;
42
+ TelemetryHelper.logActionEvent(LogLevel.INFO, {
43
+ Event: TelemetryEvent.SystemMessageReceived,
44
+ Description: "System message received"
45
+ });
46
+ };
47
+ const historyMessageStrategy = payload => {
48
+ const newMessageReceivedEvent = {
49
+ eventName: BroadcastEvent.HistoryMessageReceived,
50
+ payload: payload
51
+ };
52
+ BroadcastService.postMessage(newMessageReceivedEvent);
53
+ if (!isHistoryMessageReceivedEventRaised) {
54
+ // this is needed for reload scenarios, it helps to identify the last message received before the reload
55
+ isHistoryMessageReceivedEventRaised = true;
56
+ TelemetryHelper.logActionEvent(LogLevel.INFO, {
57
+ Event: TelemetryEvent.RehydrateMessageReceived,
58
+ Description: "History message received",
59
+ CustomProperties: payload
60
+ });
61
+ }
62
+ };
63
+ const isValidMessage = activity => {
64
+ var _activity$channelData, _activity$channelData2, _activity$channelData3;
65
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
66
+ const messageHasNoText = !(activity !== null && activity !== void 0 && activity.text);
67
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
68
+ const messageHasNoTags = !(activity !== null && activity !== void 0 && activity.channelData) || !(activity !== null && activity !== void 0 && (_activity$channelData = activity.channelData) !== null && _activity$channelData !== void 0 && _activity$channelData.tags) || (activity === null || activity === void 0 ? void 0 : (_activity$channelData2 = activity.channelData) === null || _activity$channelData2 === void 0 ? void 0 : (_activity$channelData3 = _activity$channelData2.tags) === null || _activity$channelData3 === void 0 ? void 0 : _activity$channelData3.length) === 0;
69
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
70
+ const messageHasNoAttachments = !(activity !== null && activity !== void 0 && activity.attachments) || (activity === null || activity === void 0 ? void 0 : activity.attachments.length) === 0;
71
+ if (messageHasNoTags && messageHasNoText && messageHasNoAttachments) {
72
+ return false;
73
+ }
74
+ return true;
75
+ };
76
+ const receivedMessageStrategy = activity => {
77
+ var _TelemetryManager$Int3;
78
+ if (!isValidMessage(activity)) return;
79
+ const isHistoryMessageReceived = isHistoryMessage(activity, startTime);
80
+ const payload = buildMessagePayload(activity, userId);
81
+ payload.messageType = Constants.userMessageTag;
82
+ if (isHistoryMessageReceived) {
83
+ var _TelemetryManager$Int2;
84
+ historyMessageStrategy(polyfillMessagePayloadForEvent(activity, payload, (_TelemetryManager$Int2 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int2 === void 0 ? void 0 : _TelemetryManager$Int2.conversationId));
85
+ return;
86
+ }
87
+ firstResponseLatencyTracker.stopClock(payload);
88
+ const newMessageReceivedEvent = {
89
+ eventName: BroadcastEvent.NewMessageReceived,
90
+ payload: polyfillMessagePayloadForEvent(activity, payload, (_TelemetryManager$Int3 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int3 === void 0 ? void 0 : _TelemetryManager$Int3.conversationId)
91
+ };
92
+ BroadcastService.postMessage(newMessageReceivedEvent);
93
+ TelemetryHelper.logActionEvent(LogLevel.INFO, {
94
+ Event: TelemetryEvent.MessageReceived,
95
+ Description: "New message received",
96
+ CustomProperties: payload
97
+ });
98
+ };
99
+ const raiseMessageEvent = activity => {
31
100
  if ((activity === null || activity === void 0 ? void 0 : activity.type) === Constants.message) {
32
- var _text, _text2, _activity$channelData4, _activity$from;
33
- const payload = {
34
- // To identify hidden contents vs empty content
35
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
- text: (activity === null || activity === void 0 ? void 0 : (_text = activity.text) === null || _text === void 0 ? void 0 : _text.length) >= 1 ? `*contents hidden (${activity === null || activity === void 0 ? void 0 : (_text2 = activity.text) === null || _text2 === void 0 ? void 0 : _text2.length} chars)*` : "",
37
- type: activity === null || activity === void 0 ? void 0 : activity.type,
38
- timestamp: activity === null || activity === void 0 ? void 0 : activity.timestamp,
39
- userId: userId,
40
- tags: activity === null || activity === void 0 ? void 0 : (_activity$channelData4 = activity.channelData) === null || _activity$channelData4 === void 0 ? void 0 : _activity$channelData4.tags,
41
- messageType: ""
42
- };
43
- if ((activity === null || activity === void 0 ? void 0 : (_activity$from = activity.from) === null || _activity$from === void 0 ? void 0 : _activity$from.role) === Constants.userMessageTag) {
44
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
45
- payload.messageType = Constants.userMessageTag;
46
- const newMessageSentEvent = {
47
- eventName: BroadcastEvent.NewMessageSent,
48
- payload: polyfillMessagePayloadForEvent(payload)
49
- };
50
- BroadcastService.postMessage(newMessageSentEvent);
51
- TelemetryHelper.logActionEvent(LogLevel.INFO, {
52
- Event: TelemetryEvent.MessageSent,
53
- Description: "New message sent"
54
- });
55
- } else {
56
- var _activity$channelData5, _activity$channelData6;
57
- if (activity !== null && activity !== void 0 && (_activity$channelData5 = activity.channelData) !== null && _activity$channelData5 !== void 0 && (_activity$channelData6 = _activity$channelData5.tags) !== null && _activity$channelData6 !== void 0 && _activity$channelData6.includes(Constants.systemMessageTag)) {
58
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
59
- payload.messageType = Constants.systemMessageTag;
60
- TelemetryHelper.logActionEvent(LogLevel.INFO, {
61
- Event: TelemetryEvent.SystemMessageReceived,
62
- Description: "System message received"
63
- });
64
- } else {
65
- var _activity$channelData7, _activity$channelData8, _activity$channelData9;
66
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
67
- const messageHasNoText = !(activity !== null && activity !== void 0 && activity.text);
68
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
69
- const messageHasNoTags = !(activity !== null && activity !== void 0 && activity.channelData) || !(activity !== null && activity !== void 0 && (_activity$channelData7 = activity.channelData) !== null && _activity$channelData7 !== void 0 && _activity$channelData7.tags) || (activity === null || activity === void 0 ? void 0 : (_activity$channelData8 = activity.channelData) === null || _activity$channelData8 === void 0 ? void 0 : (_activity$channelData9 = _activity$channelData8.tags) === null || _activity$channelData9 === void 0 ? void 0 : _activity$channelData9.length) === 0;
70
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
71
- const messageHasNoAttachments = !(activity !== null && activity !== void 0 && activity.attachments) || (activity === null || activity === void 0 ? void 0 : activity.attachments.length) === 0;
72
- if (messageHasNoTags && messageHasNoText && messageHasNoAttachments) {
73
- return;
74
- }
75
- payload.messageType = Constants.userMessageTag;
76
- }
77
- const newMessageReceivedEvent = {
78
- eventName: isHistoryMessage ? BroadcastEvent.HistoryMessageReceived : BroadcastEvent.NewMessageReceived,
79
- payload: polyfillMessagePayloadForEvent(payload)
80
- };
81
- BroadcastService.postMessage(newMessageReceivedEvent);
82
- if (!isHistoryMessage) {
83
- TelemetryHelper.logActionEvent(LogLevel.INFO, {
84
- Event: TelemetryEvent.MessageReceived,
85
- Description: "New message received",
86
- CustomProperties: payload
87
- });
88
- } else {
89
- if (!isHistoryMessageReceivedEventRasied) {
90
- isHistoryMessageReceivedEventRasied = true;
91
- TelemetryHelper.logActionEvent(LogLevel.INFO, {
92
- Event: TelemetryEvent.RehydrateMessageReceived,
93
- Description: "History message received",
94
- CustomProperties: payload
95
- });
96
- }
97
- }
101
+ const scenarioType = getScenarioType(activity);
102
+ switch (scenarioType) {
103
+ case ScenarioType.UserSendMessageStrategy:
104
+ userSendMessageStrategy(activity);
105
+ break;
106
+ case ScenarioType.SystemMessageStrategy:
107
+ systemMessageStrategy(activity);
108
+ break;
109
+ case ScenarioType.ReceivedMessageStrategy:
110
+ receivedMessageStrategy(activity);
111
+ break;
98
112
  }
99
113
  }
100
114
  };
@@ -192,6 +192,9 @@ export declare enum TelemetryEvent {
192
192
  ReconnectChatMinimize = "ReconnectChatMinimize",
193
193
  MessageSent = "MessageSent",
194
194
  MessageReceived = "MessageReceived",
195
+ MessageLapTrack = "MessageLapTrack",
196
+ MessageStartLapTrackError = "MessageStartLapTrackError",
197
+ MessageStopLapTrackError = "MessageStopLapTrackError",
195
198
  SystemMessageReceived = "SystemMessageReceived",
196
199
  RehydrateMessageReceived = "RehydrateMessageReceived",
197
200
  CustomContextReceived = "CustomContextReceived",
@@ -206,6 +209,8 @@ export declare enum TelemetryEvent {
206
209
  PostChatContextCallFailed = "PostChatContextCallFailed",
207
210
  PostChatSurveyLoadingPaneLoaded = "PostChatSurveyLoadingPaneLoaded",
208
211
  PostChatSurveyLoaded = "PostChatSurveyLoaded",
212
+ PostChatSurveyUrlValidationCompleted = "PostChatSurveyUrlValidationCompleted",
213
+ PostChatSurveyUrlValidationFailed = "PostChatSurveyUrlValidationFailed",
209
214
  ChatDisconnectThreadEventReceived = "ChatDisconnectThreadEventReceived",
210
215
  HiddenAdaptiveCardMessageReceived = "HiddenAdaptiveCardMessageReceived",
211
216
  EndingAdapterAfterDisconnectionError = "EndingAdapterAfterDisconnectionError",
@@ -0,0 +1,2 @@
1
+ declare const isValidSurveyUrl: (url: string) => boolean;
2
+ export default isValidSurveyUrl;
@@ -1,9 +1,9 @@
1
+ import { ConfirmationState, ConversationEndEntity, ParticipantType } from "../../common/Constants";
1
2
  import ChatConfig from "@microsoft/omnichannel-chat-sdk/lib/core/ChatConfig";
2
3
  import { ConversationState } from "./ConversationState";
3
4
  import { IInternalTelemetryData } from "../../common/telemetry/interfaces/IInternalTelemetryData";
4
5
  import { ILiveChatWidgetLocalizedTexts } from "./ILiveChatWidgetLocalizedTexts";
5
6
  import { IRenderingMiddlewareProps } from "../../components/webchatcontainerstateful/interfaces/IRenderingMiddlewareProps";
6
- import { ConfirmationState, ConversationEndEntity, ParticipantType } from "../../common/Constants";
7
7
  import { StartChatFailureType } from "./StartChatFailureType";
8
8
  export interface ILiveChatWidgetContext {
9
9
  domainStates: {
@@ -0,0 +1,30 @@
1
+ export declare enum ScenarioType {
2
+ UserSendMessageStrategy = "UserSendMessageStrategy",
3
+ SystemMessageStrategy = "SystemMessageStrategy",
4
+ ReceivedMessageStrategy = "ReceivedMessageStrategy"
5
+ }
6
+ export type MessagePayload = {
7
+ text: string;
8
+ type: string;
9
+ timestamp?: string | undefined;
10
+ userId: string;
11
+ tags: string[];
12
+ messageType: string;
13
+ Id: string | undefined;
14
+ role: string | undefined;
15
+ channelData?: any;
16
+ chatId?: string;
17
+ conversationId?: string;
18
+ isChatComplete: boolean;
19
+ attachment?: any[];
20
+ };
21
+ export type TrackingMessage = {
22
+ Id: string | undefined;
23
+ role: string | undefined;
24
+ timestamp: string | undefined;
25
+ tags: string[];
26
+ messageType: string;
27
+ text: string;
28
+ checkTime?: number;
29
+ type: string;
30
+ };
@@ -0,0 +1,17 @@
1
+ import { MessagePayload } from "./Constants";
2
+ export declare class FirstResponseLatencyTracker {
3
+ private isABotConversation;
4
+ private isStarted;
5
+ private isEnded;
6
+ private startTrackingMessage?;
7
+ private stopTrackingMessage?;
8
+ constructor();
9
+ private createTrackingMessage;
10
+ private startTracking;
11
+ private handleAgentMessage;
12
+ private stopTracking;
13
+ private isMessageFromValidSender;
14
+ startClock(payload: MessagePayload): void;
15
+ stopClock(payload: MessagePayload): void;
16
+ private deregister;
17
+ }
@@ -0,0 +1,6 @@
1
+ import { MessagePayload, ScenarioType } from "./Constants";
2
+ import { IActivity } from "botframework-directlinejs";
3
+ export declare const isHistoryMessage: (activity: IActivity, startTime: number) => boolean;
4
+ export declare const buildMessagePayload: (activity: IActivity, userId: string) => MessagePayload;
5
+ export declare const polyfillMessagePayloadForEvent: (activity: IActivity, payload: MessagePayload, conversationId?: string) => MessagePayload;
6
+ export declare const getScenarioType: (activity: IActivity) => ScenarioType;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microsoft/omnichannel-chat-widget",
3
- "version": "1.7.8-main.9e74278",
3
+ "version": "1.7.8-main.bd4de53",
4
4
  "description": "Microsoft Omnichannel Chat Widget",
5
5
  "main": "lib/cjs/index.js",
6
6
  "types": "lib/types/index.d.ts",