@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
@@ -0,0 +1,152 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.FirstResponseLatencyTracker = void 0;
7
+ var _TelemetryConstants = require("../common/telemetry/TelemetryConstants");
8
+ var _TelemetryHelper = require("../common/telemetry/TelemetryHelper");
9
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
10
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
11
+ function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
12
+ class FirstResponseLatencyTracker {
13
+ constructor() {
14
+ _defineProperty(this, "isABotConversation", false);
15
+ _defineProperty(this, "isStarted", false);
16
+ _defineProperty(this, "isEnded", false);
17
+ _defineProperty(this, "startTrackingMessage", void 0);
18
+ _defineProperty(this, "stopTrackingMessage", void 0);
19
+ // this is a workaround to ensure in reload we track effectively the messages
20
+ // we do have a mechanism in place to prevent log agent messages.
21
+ this.isABotConversation = true;
22
+ }
23
+ createTrackingMessage(payload, type) {
24
+ return {
25
+ Id: payload.Id,
26
+ role: payload.role,
27
+ timestamp: payload === null || payload === void 0 ? void 0 : payload.timestamp,
28
+ tags: payload.tags,
29
+ messageType: payload.messageType,
30
+ text: payload.text,
31
+ type: type,
32
+ checkTime: new Date().getTime()
33
+ };
34
+ }
35
+
36
+ // Tracking Functions
37
+ startTracking(payload) {
38
+ // this prevents to initiate tracking for multiple incoming messages
39
+ if (this.isStarted) {
40
+ return;
41
+ }
42
+ // this is to ensure we track only messages where bot is engaged
43
+ if (!this.isABotConversation) {
44
+ return;
45
+ }
46
+
47
+ // control of states to prevent clashing of messages
48
+ this.isStarted = true;
49
+ this.isEnded = false;
50
+
51
+ // The idea of using types is to enrich telemetry data
52
+ this.startTrackingMessage = this.createTrackingMessage(payload, "userMessage");
53
+ }
54
+ handleAgentMessage(payload) {
55
+ var _payload$tags;
56
+ // this tag so far is only present in agent messages
57
+ if (payload !== null && payload !== void 0 && (_payload$tags = payload.tags) !== null && _payload$tags !== void 0 && _payload$tags.includes("public")) {
58
+ this.deregister();
59
+ }
60
+ }
61
+ stopTracking(payload) {
62
+ var _this$stopTrackingMes, _this$startTrackingMe;
63
+ // this prevents execution for multiple incoming messages from the bot.
64
+ if (this.isEnded && !this.isStarted) {
65
+ return;
66
+ }
67
+
68
+ // control of states to prevent clashing of messages
69
+ this.isEnded = true;
70
+ this.isStarted = false;
71
+
72
+ // The idea of using types is to enrich telemetry data
73
+ this.stopTrackingMessage = this.createTrackingMessage(payload, "botMessage");
74
+ // calculating elapsed time
75
+ const elapsedTime = (((_this$stopTrackingMes = this.stopTrackingMessage) === null || _this$stopTrackingMes === void 0 ? void 0 : _this$stopTrackingMes.checkTime) ?? 0) - (((_this$startTrackingMe = this.startTrackingMessage) === null || _this$startTrackingMe === void 0 ? void 0 : _this$startTrackingMe.checkTime) ?? 0);
76
+ _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.INFO, {
77
+ Event: _TelemetryConstants.TelemetryEvent.MessageLapTrack,
78
+ Description: "First response latency tracking",
79
+ CustomProperties: {
80
+ elapsedTime,
81
+ userMessage: this.startTrackingMessage,
82
+ botMessage: this.stopTrackingMessage
83
+ }
84
+ });
85
+ }
86
+
87
+ // mechanism to ensure we track only allowed conversations
88
+ isMessageFromValidSender(payload) {
89
+ var _payload$tags2;
90
+ // agent scenario
91
+ if (payload !== null && payload !== void 0 && (_payload$tags2 = payload.tags) !== null && _payload$tags2 !== void 0 && _payload$tags2.includes("public")) {
92
+ this.handleAgentMessage(payload);
93
+ return false;
94
+ }
95
+ return true;
96
+ }
97
+ startClock(payload) {
98
+ try {
99
+ if (!payload || !payload.Id) {
100
+ throw new Error("Invalid payload");
101
+ }
102
+ // in the case of a reload, tracker will be paused, until last history message is received
103
+ // this is because we dont have a way to identidy send messages as part of the history
104
+ //if (this.inPause) return;
105
+ this.startTracking(payload);
106
+ } catch (e) {
107
+ _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.ERROR, {
108
+ Event: _TelemetryConstants.TelemetryEvent.MessageStartLapTrackError,
109
+ Description: "Error while starting the clock",
110
+ ExceptionDetails: e,
111
+ CustomProperties: {
112
+ payload: payload
113
+ }
114
+ });
115
+ }
116
+ }
117
+ stopClock(payload) {
118
+ try {
119
+ if (!payload || !payload.Id) {
120
+ throw new Error("Invalid payload");
121
+ }
122
+ if (!this.isMessageFromValidSender(payload)) return;
123
+ if (this.isABotConversation && this.isStarted) {
124
+ this.stopTracking(payload);
125
+ }
126
+ } catch (e) {
127
+ console.error("FRL : error while trying to stop the tracker", e);
128
+ _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.ERROR, {
129
+ Event: _TelemetryConstants.TelemetryEvent.MessageStopLapTrackError,
130
+ Description: "Error while stopping the clock",
131
+ ExceptionDetails: e,
132
+ CustomProperties: {
133
+ payload: payload
134
+ }
135
+ });
136
+ //reset state
137
+ this.startTrackingMessage = undefined;
138
+ this.stopTrackingMessage = undefined;
139
+ this.isStarted = false;
140
+ this.isEnded = false;
141
+ }
142
+ }
143
+ deregister() {
144
+ // Reset State
145
+ this.isABotConversation = false;
146
+ this.isStarted = false;
147
+ this.isEnded = false;
148
+ this.startTrackingMessage = undefined;
149
+ this.stopTrackingMessage = undefined;
150
+ }
151
+ }
152
+ exports.FirstResponseLatencyTracker = FirstResponseLatencyTracker;
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.polyfillMessagePayloadForEvent = exports.isHistoryMessage = exports.getScenarioType = exports.buildMessagePayload = void 0;
7
+ var _Constants = require("./Constants");
8
+ var _Constants2 = require("../common/Constants");
9
+ const isHistoryMessage = (activity, startTime) => {
10
+ try {
11
+ if ((activity === null || activity === void 0 ? void 0 : activity.type) === _Constants2.Constants.message) {
12
+ var _activity$channelData, _activity$channelData2;
13
+ // this is an old piece of code, probably no longer relevant
14
+ if (activity !== null && activity !== void 0 && (_activity$channelData = activity.channelData) !== null && _activity$channelData !== void 0 && (_activity$channelData2 = _activity$channelData.tags) !== null && _activity$channelData2 !== void 0 && _activity$channelData2.includes(_Constants2.Constants.historyMessageTag)) return true;
15
+
16
+ // Id is an epoch time in milliseconds , in utc format, for some reason is in a string format
17
+ if (activity !== null && activity !== void 0 && activity.id) {
18
+ /// activity.id is an string that contains epoch time in milliseconds
19
+ const activityId = parseInt(activity === null || activity === void 0 ? void 0 : activity.id);
20
+
21
+ // if the activity id is not a number, we default to new message
22
+ if (isNaN(activityId)) {
23
+ return false;
24
+ }
25
+
26
+ // if the activity id is less than the start time, it means that the message is a history message
27
+ if (activityId < startTime) {
28
+ return true;
29
+ }
30
+ }
31
+ // anything else will be considered a new message
32
+ return false;
33
+ }
34
+ } catch (e) {
35
+ // if there is an error in parsing the activity id, we will consider it a new message
36
+ console.error("Error in parsing activity id: ", e);
37
+ }
38
+ return false;
39
+ };
40
+ exports.isHistoryMessage = isHistoryMessage;
41
+ const buildMessagePayload = (activity, userId) => {
42
+ var _text, _text2, _activity$channelData3, _activity$from;
43
+ return {
44
+ // To identify hidden contents vs empty content
45
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
46
+ 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)*` : "",
47
+ type: activity === null || activity === void 0 ? void 0 : activity.type,
48
+ timestamp: activity === null || activity === void 0 ? void 0 : activity.timestamp,
49
+ userId: userId,
50
+ tags: activity === null || activity === void 0 ? void 0 : (_activity$channelData3 = activity.channelData) === null || _activity$channelData3 === void 0 ? void 0 : _activity$channelData3.tags,
51
+ messageType: "",
52
+ Id: activity === null || activity === void 0 ? void 0 : activity.id,
53
+ role: activity === null || activity === void 0 ? void 0 : (_activity$from = activity.from) === null || _activity$from === void 0 ? void 0 : _activity$from.role,
54
+ isChatComplete: false
55
+ };
56
+ };
57
+ exports.buildMessagePayload = buildMessagePayload;
58
+ const polyfillMessagePayloadForEvent = (activity, payload, conversationId) => {
59
+ var _activity$conversatio, _attachments, _activity$from2;
60
+ return {
61
+ ...payload,
62
+ channelData: activity === null || activity === void 0 ? void 0 : activity.channelData,
63
+ chatId: activity === null || activity === void 0 ? void 0 : (_activity$conversatio = activity.conversation) === null || _activity$conversatio === void 0 ? void 0 : _activity$conversatio.id,
64
+ conversationId: conversationId,
65
+ Id: activity === null || activity === void 0 ? void 0 : activity.id,
66
+ isChatComplete: false,
67
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
68
+ text: activity === null || activity === void 0 ? void 0 : activity.text,
69
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
70
+ 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 : [],
71
+ role: activity === null || activity === void 0 ? void 0 : (_activity$from2 = activity.from) === null || _activity$from2 === void 0 ? void 0 : _activity$from2.role
72
+ };
73
+ };
74
+ exports.polyfillMessagePayloadForEvent = polyfillMessagePayloadForEvent;
75
+ const getScenarioType = activity => {
76
+ var _activity$from3, _activity$channelData4, _activity$channelData5;
77
+ if ((activity === null || activity === void 0 ? void 0 : (_activity$from3 = activity.from) === null || _activity$from3 === void 0 ? void 0 : _activity$from3.role) === _Constants2.Constants.userMessageTag) {
78
+ return _Constants.ScenarioType.UserSendMessageStrategy;
79
+ }
80
+ if (activity !== null && activity !== void 0 && (_activity$channelData4 = activity.channelData) !== null && _activity$channelData4 !== void 0 && (_activity$channelData5 = _activity$channelData4.tags) !== null && _activity$channelData5 !== void 0 && _activity$channelData5.includes(_Constants2.Constants.systemMessageTag)) {
81
+ return _Constants.ScenarioType.SystemMessageStrategy;
82
+ }
83
+ return _Constants.ScenarioType.ReceivedMessageStrategy;
84
+ };
85
+ exports.getScenarioType = getScenarioType;
@@ -173,7 +173,7 @@ class TranscriptHTMLBuilder {
173
173
  <script>
174
174
  class Translator {
175
175
  static convertTranscriptMessageToActivity(message) {
176
- const {created, OriginalMessageId, id, isControlMessage, content, tags, from, attachments, amsMetadata, amsReferences} = message;
176
+ const {created, OriginalMessageId, id, isControlMessage, content, tags, from, attachments, amsMetadata, amsReferences, amsreferences} = message;
177
177
 
178
178
  //it's required to convert the id to a number, otherwise the webchat will not render the messages in the correct order
179
179
  // if the OrginalMessageId is not present, we can use the id as the sequence id, which is always present.
@@ -220,7 +220,7 @@ class TranscriptHTMLBuilder {
220
220
  }
221
221
 
222
222
  // Attachments
223
- if (amsReferences && amsMetadata) {
223
+ if ((amsReferences || amsreferences) && amsMetadata) {
224
224
  const metadata = JSON.parse(amsMetadata);
225
225
  const { fileName } = metadata[0];
226
226
  const text = \`${this.attachmentMessage}\${fileName}\`;
@@ -244,7 +244,7 @@ class TranscriptHTMLBuilder {
244
244
  // Message
245
245
  if (content) {
246
246
  // Adaptive card formatting
247
- if (content.includes('"text"') && content.includes('"attachments"') && content.includes('"suggestedActions"')) {
247
+ if (content.includes('"attachments"') || content.includes('"suggestedActions"')) {
248
248
  try {
249
249
  const partialActivity = JSON.parse(content);
250
250
  return {
@@ -683,7 +683,7 @@ const createChatTranscript = async function (transcript, facadeChatSDK) {
683
683
  messages = await Promise.all(transcriptMessages.map(async message => {
684
684
  // eslint-disable-line @typescript-eslint/no-explicit-any
685
685
  const {
686
- amsReferences,
686
+ amsReferences = message.amsreferences,
687
687
  amsMetadata
688
688
  } = message;
689
689
  if (amsReferences && amsMetadata) {
@@ -5,102 +5,116 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.createOnNewAdapterActivityHandler = void 0;
7
7
  var _TelemetryConstants = require("../common/telemetry/TelemetryConstants");
8
+ var _Constants = require("../firstresponselatency/Constants");
9
+ var _util = require("../firstresponselatency/util");
8
10
  var _omnichannelChatComponents = require("@microsoft/omnichannel-chat-components");
9
- var _Constants = require("../common/Constants");
11
+ var _Constants2 = require("../common/Constants");
12
+ var _FirstResponseLatencyTracker = require("../firstresponselatency/FirstResponseLatencyTracker");
10
13
  var _TelemetryHelper = require("../common/telemetry/TelemetryHelper");
11
14
  var _TelemetryManager = require("../common/telemetry/TelemetryManager");
12
15
  const createOnNewAdapterActivityHandler = (chatId, userId) => {
16
+ // Hooking the message tracker in the listener, a bit invasive but easier to control.
17
+ const firstResponseLatencyTracker = new _FirstResponseLatencyTracker.FirstResponseLatencyTracker();
18
+ // epoch time in utc for when start to listen.
19
+ // 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.
20
+ // 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
21
+ const startTime = new Date().getTime();
22
+ let isHistoryMessageReceivedEventRaised = false;
13
23
  const onNewAdapterActivityHandler = activity => {
14
- var _activity$channelData, _activity$channelData2, _activity$channelData3;
15
- const isActivityMessage = (activity === null || activity === void 0 ? void 0 : activity.type) === _Constants.Constants.message;
16
- 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.Constants.historyMessageTag)) || (activity === null || activity === void 0 ? void 0 : (_activity$channelData3 = activity.channelData) === null || _activity$channelData3 === void 0 ? void 0 : _activity$channelData3.fromList));
17
- raiseMessageEvent(activity, isHistoryMessage);
24
+ raiseMessageEvent(activity);
18
25
  };
19
- let isHistoryMessageReceivedEventRasied = false;
20
- const raiseMessageEvent = (activity, isHistoryMessage) => {
26
+ const userSendMessageStrategy = activity => {
27
+ var _TelemetryManager$Int;
28
+ const payload = (0, _util.buildMessagePayload)(activity, userId);
21
29
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
- const polyfillMessagePayloadForEvent = payload => {
23
- var _activity$conversatio, _TelemetryManager$Int, _attachments;
24
- return {
25
- ...payload,
26
- channelData: activity === null || activity === void 0 ? void 0 : activity.channelData,
27
- chatId: activity === null || activity === void 0 ? void 0 : (_activity$conversatio = activity.conversation) === null || _activity$conversatio === void 0 ? void 0 : _activity$conversatio.id,
28
- conversationId: (_TelemetryManager$Int = _TelemetryManager.TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int === void 0 ? void 0 : _TelemetryManager$Int.conversationId,
29
- id: activity === null || activity === void 0 ? void 0 : activity.id,
30
- isChatComplete: false,
31
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
32
- text: activity === null || activity === void 0 ? void 0 : activity.text,
33
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
34
- 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 : []
35
- };
30
+ payload.messageType = _Constants2.Constants.userMessageTag;
31
+ const newMessageSentEvent = {
32
+ eventName: _TelemetryConstants.BroadcastEvent.NewMessageSent,
33
+ payload: (0, _util.polyfillMessagePayloadForEvent)(activity, payload, (_TelemetryManager$Int = _TelemetryManager.TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int === void 0 ? void 0 : _TelemetryManager$Int.conversationId)
36
34
  };
37
- if ((activity === null || activity === void 0 ? void 0 : activity.type) === _Constants.Constants.message) {
38
- var _text, _text2, _activity$channelData4, _activity$from;
39
- const payload = {
40
- // To identify hidden contents vs empty content
41
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
42
- 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)*` : "",
43
- type: activity === null || activity === void 0 ? void 0 : activity.type,
44
- timestamp: activity === null || activity === void 0 ? void 0 : activity.timestamp,
45
- userId: userId,
46
- tags: activity === null || activity === void 0 ? void 0 : (_activity$channelData4 = activity.channelData) === null || _activity$channelData4 === void 0 ? void 0 : _activity$channelData4.tags,
47
- messageType: ""
48
- };
49
- if ((activity === null || activity === void 0 ? void 0 : (_activity$from = activity.from) === null || _activity$from === void 0 ? void 0 : _activity$from.role) === _Constants.Constants.userMessageTag) {
50
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
51
- payload.messageType = _Constants.Constants.userMessageTag;
52
- const newMessageSentEvent = {
53
- eventName: _TelemetryConstants.BroadcastEvent.NewMessageSent,
54
- payload: polyfillMessagePayloadForEvent(payload)
55
- };
56
- _omnichannelChatComponents.BroadcastService.postMessage(newMessageSentEvent);
57
- _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.INFO, {
58
- Event: _TelemetryConstants.TelemetryEvent.MessageSent,
59
- Description: "New message sent"
60
- });
61
- } else {
62
- var _activity$channelData5, _activity$channelData6;
63
- 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.Constants.systemMessageTag)) {
64
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
65
- payload.messageType = _Constants.Constants.systemMessageTag;
66
- _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.INFO, {
67
- Event: _TelemetryConstants.TelemetryEvent.SystemMessageReceived,
68
- Description: "System message received"
69
- });
70
- } else {
71
- var _activity$channelData7, _activity$channelData8, _activity$channelData9;
72
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
73
- const messageHasNoText = !(activity !== null && activity !== void 0 && activity.text);
74
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
75
- 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;
76
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
77
- const messageHasNoAttachments = !(activity !== null && activity !== void 0 && activity.attachments) || (activity === null || activity === void 0 ? void 0 : activity.attachments.length) === 0;
78
- if (messageHasNoTags && messageHasNoText && messageHasNoAttachments) {
79
- return;
80
- }
81
- payload.messageType = _Constants.Constants.userMessageTag;
82
- }
83
- const newMessageReceivedEvent = {
84
- eventName: isHistoryMessage ? _TelemetryConstants.BroadcastEvent.HistoryMessageReceived : _TelemetryConstants.BroadcastEvent.NewMessageReceived,
85
- payload: polyfillMessagePayloadForEvent(payload)
86
- };
87
- _omnichannelChatComponents.BroadcastService.postMessage(newMessageReceivedEvent);
88
- if (!isHistoryMessage) {
89
- _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.INFO, {
90
- Event: _TelemetryConstants.TelemetryEvent.MessageReceived,
91
- Description: "New message received",
92
- CustomProperties: payload
93
- });
94
- } else {
95
- if (!isHistoryMessageReceivedEventRasied) {
96
- isHistoryMessageReceivedEventRasied = true;
97
- _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.INFO, {
98
- Event: _TelemetryConstants.TelemetryEvent.RehydrateMessageReceived,
99
- Description: "History message received",
100
- CustomProperties: payload
101
- });
102
- }
103
- }
35
+ _omnichannelChatComponents.BroadcastService.postMessage(newMessageSentEvent);
36
+ if (!(0, _util.isHistoryMessage)(activity, startTime)) {
37
+ firstResponseLatencyTracker.startClock(payload);
38
+ }
39
+ _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.INFO, {
40
+ Event: _TelemetryConstants.TelemetryEvent.MessageSent,
41
+ Description: "New message sent"
42
+ });
43
+ };
44
+ const systemMessageStrategy = activity => {
45
+ const payload = (0, _util.buildMessagePayload)(activity, userId);
46
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
47
+ payload.messageType = _Constants2.Constants.systemMessageTag;
48
+ _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.INFO, {
49
+ Event: _TelemetryConstants.TelemetryEvent.SystemMessageReceived,
50
+ Description: "System message received"
51
+ });
52
+ };
53
+ const historyMessageStrategy = payload => {
54
+ const newMessageReceivedEvent = {
55
+ eventName: _TelemetryConstants.BroadcastEvent.HistoryMessageReceived,
56
+ payload: payload
57
+ };
58
+ _omnichannelChatComponents.BroadcastService.postMessage(newMessageReceivedEvent);
59
+ if (!isHistoryMessageReceivedEventRaised) {
60
+ // this is needed for reload scenarios, it helps to identify the last message received before the reload
61
+ isHistoryMessageReceivedEventRaised = true;
62
+ _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.INFO, {
63
+ Event: _TelemetryConstants.TelemetryEvent.RehydrateMessageReceived,
64
+ Description: "History message received",
65
+ CustomProperties: payload
66
+ });
67
+ }
68
+ };
69
+ const isValidMessage = activity => {
70
+ var _activity$channelData, _activity$channelData2, _activity$channelData3;
71
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
72
+ const messageHasNoText = !(activity !== null && activity !== void 0 && activity.text);
73
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
74
+ 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;
75
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
76
+ const messageHasNoAttachments = !(activity !== null && activity !== void 0 && activity.attachments) || (activity === null || activity === void 0 ? void 0 : activity.attachments.length) === 0;
77
+ if (messageHasNoTags && messageHasNoText && messageHasNoAttachments) {
78
+ return false;
79
+ }
80
+ return true;
81
+ };
82
+ const receivedMessageStrategy = activity => {
83
+ var _TelemetryManager$Int3;
84
+ if (!isValidMessage(activity)) return;
85
+ const isHistoryMessageReceived = (0, _util.isHistoryMessage)(activity, startTime);
86
+ const payload = (0, _util.buildMessagePayload)(activity, userId);
87
+ payload.messageType = _Constants2.Constants.userMessageTag;
88
+ if (isHistoryMessageReceived) {
89
+ var _TelemetryManager$Int2;
90
+ historyMessageStrategy((0, _util.polyfillMessagePayloadForEvent)(activity, payload, (_TelemetryManager$Int2 = _TelemetryManager.TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int2 === void 0 ? void 0 : _TelemetryManager$Int2.conversationId));
91
+ return;
92
+ }
93
+ firstResponseLatencyTracker.stopClock(payload);
94
+ const newMessageReceivedEvent = {
95
+ eventName: _TelemetryConstants.BroadcastEvent.NewMessageReceived,
96
+ payload: (0, _util.polyfillMessagePayloadForEvent)(activity, payload, (_TelemetryManager$Int3 = _TelemetryManager.TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int3 === void 0 ? void 0 : _TelemetryManager$Int3.conversationId)
97
+ };
98
+ _omnichannelChatComponents.BroadcastService.postMessage(newMessageReceivedEvent);
99
+ _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.INFO, {
100
+ Event: _TelemetryConstants.TelemetryEvent.MessageReceived,
101
+ Description: "New message received",
102
+ CustomProperties: payload
103
+ });
104
+ };
105
+ const raiseMessageEvent = activity => {
106
+ if ((activity === null || activity === void 0 ? void 0 : activity.type) === _Constants2.Constants.message) {
107
+ const scenarioType = (0, _util.getScenarioType)(activity);
108
+ switch (scenarioType) {
109
+ case _Constants.ScenarioType.UserSendMessageStrategy:
110
+ userSendMessageStrategy(activity);
111
+ break;
112
+ case _Constants.ScenarioType.SystemMessageStrategy:
113
+ systemMessageStrategy(activity);
114
+ break;
115
+ case _Constants.ScenarioType.ReceivedMessageStrategy:
116
+ receivedMessageStrategy(activity);
117
+ break;
104
118
  }
105
119
  }
106
120
  };
@@ -199,6 +199,9 @@ export let TelemetryEvent;
199
199
  TelemetryEvent["ReconnectChatMinimize"] = "ReconnectChatMinimize";
200
200
  TelemetryEvent["MessageSent"] = "MessageSent";
201
201
  TelemetryEvent["MessageReceived"] = "MessageReceived";
202
+ TelemetryEvent["MessageLapTrack"] = "MessageLapTrack";
203
+ TelemetryEvent["MessageStartLapTrackError"] = "MessageStartLapTrackError";
204
+ TelemetryEvent["MessageStopLapTrackError"] = "MessageStopLapTrackError";
202
205
  TelemetryEvent["SystemMessageReceived"] = "SystemMessageReceived";
203
206
  TelemetryEvent["RehydrateMessageReceived"] = "RehydrateMessageReceived";
204
207
  TelemetryEvent["CustomContextReceived"] = "CustomContextReceived";
@@ -213,6 +216,8 @@ export let TelemetryEvent;
213
216
  TelemetryEvent["PostChatContextCallFailed"] = "PostChatContextCallFailed";
214
217
  TelemetryEvent["PostChatSurveyLoadingPaneLoaded"] = "PostChatSurveyLoadingPaneLoaded";
215
218
  TelemetryEvent["PostChatSurveyLoaded"] = "PostChatSurveyLoaded";
219
+ TelemetryEvent["PostChatSurveyUrlValidationCompleted"] = "PostChatSurveyUrlValidationCompleted";
220
+ TelemetryEvent["PostChatSurveyUrlValidationFailed"] = "PostChatSurveyUrlValidationFailed";
216
221
  TelemetryEvent["ChatDisconnectThreadEventReceived"] = "ChatDisconnectThreadEventReceived";
217
222
  TelemetryEvent["HiddenAdaptiveCardMessageReceived"] = "HiddenAdaptiveCardMessageReceived";
218
223
  TelemetryEvent["EndingAdapterAfterDisconnectionError"] = "EndingAdapterAfterDisconnectionError";
@@ -11,7 +11,7 @@ import { defaultOutOfOfficeChatButtonStyleProps } from "./common/styleProps/defa
11
11
  import useChatContextStore from "../../hooks/useChatContextStore";
12
12
  let uiTimer;
13
13
  export const ChatButtonStateful = props => {
14
- var _state$domainStates$l, _state$domainStates$l2, _buttonProps$controlP, _props$buttonProps, _props$buttonProps$co, _props$buttonProps2, _props$buttonProps2$c, _props$buttonProps3, _props$buttonProps3$c;
14
+ var _buttonProps$controlP, _props$buttonProps, _props$buttonProps$co, _props$buttonProps2, _props$buttonProps2$c, _props$buttonProps3, _props$buttonProps3$c;
15
15
  // this is to ensure the telemetry is set only once and start the load timer
16
16
  useEffect(() => {
17
17
  uiTimer = createTimer();
@@ -28,7 +28,8 @@ export const ChatButtonStateful = props => {
28
28
  startChat
29
29
  } = props;
30
30
  //Setting OutOfOperatingHours Flag
31
- const [outOfOperatingHours, setOutOfOperatingHours] = useState(((_state$domainStates$l = state.domainStates.liveChatConfig) === null || _state$domainStates$l === void 0 ? void 0 : (_state$domainStates$l2 = _state$domainStates$l.LiveWSAndLiveChatEngJoin) === null || _state$domainStates$l2 === void 0 ? void 0 : _state$domainStates$l2.OutOfOperatingHours) === "True");
31
+ //Setting OutOfOperatingHours Flag - to string conversion to normalize the value (could be boolean from other states or string directly from config)
32
+ const [outOfOperatingHours, setOutOfOperatingHours] = useState(state.appStates.outsideOperatingHours);
32
33
  const ref = useRef(() => {
33
34
  return;
34
35
  });
@@ -87,9 +88,7 @@ export const ChatButtonStateful = props => {
87
88
  ...(outOfOfficeButtonProps === null || outOfOfficeButtonProps === void 0 ? void 0 : outOfOfficeButtonProps.controlProps)
88
89
  };
89
90
  useEffect(() => {
90
- if (state.appStates.outsideOperatingHours) {
91
- setOutOfOperatingHours(true);
92
- }
91
+ setOutOfOperatingHours(state.appStates.outsideOperatingHours);
93
92
  TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
94
93
  Event: TelemetryEvent.LCWChatButtonShow,
95
94
  ElapsedTimeInMilliseconds: TelemetryTimers.LcwLoadToChatButtonTimer.milliSecondsElapsed
@@ -12,7 +12,7 @@ import useChatAdapterStore from "../../hooks/useChatAdapterStore";
12
12
  import useChatContextStore from "../../hooks/useChatContextStore";
13
13
  let uiTimer;
14
14
  export const HeaderStateful = props => {
15
- var _state$domainStates$l, _state$domainStates$l2, _state$domainStates, _headerProps$controlP, _headerProps$controlP2, _headerProps$controlP3, _outOfOfficeHeaderPro, _state$domainStates3;
15
+ var _state$domainStates, _headerProps$controlP, _headerProps$controlP2, _headerProps$controlP3, _outOfOfficeHeaderPro, _state$domainStates3;
16
16
  useEffect(() => {
17
17
  uiTimer = createTimer();
18
18
  TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
@@ -28,7 +28,7 @@ export const HeaderStateful = props => {
28
28
  endChat
29
29
  } = props;
30
30
  //Setting OutOfOperatingHours Flag
31
- const [outOfOperatingHours, setOutOfOperatingHours] = useState(((_state$domainStates$l = state.domainStates.liveChatConfig) === null || _state$domainStates$l === void 0 ? void 0 : (_state$domainStates$l2 = _state$domainStates$l.LiveWSAndLiveChatEngJoin) === null || _state$domainStates$l2 === void 0 ? void 0 : _state$domainStates$l2.OutOfOperatingHours) === "True");
31
+ const [outOfOperatingHours, setOutOfOperatingHours] = useState(state.appStates.outsideOperatingHours);
32
32
  const outOfOfficeStyleProps = Object.assign({}, defaultOutOfOfficeHeaderStyleProps, outOfOfficeHeaderProps === null || outOfOfficeHeaderProps === void 0 ? void 0 : outOfOfficeHeaderProps.styleProps);
33
33
 
34
34
  // For some reason state object is not getting updated values in this component
@@ -100,9 +100,7 @@ export const HeaderStateful = props => {
100
100
  hideCloseButton: state.appStates.conversationState === ConversationState.OutOfOffice || (outOfOfficeHeaderProps === null || outOfOfficeHeaderProps === void 0 ? void 0 : (_outOfOfficeHeaderPro = outOfOfficeHeaderProps.controlProps) === null || _outOfOfficeHeaderPro === void 0 ? void 0 : _outOfOfficeHeaderPro.hideCloseButton)
101
101
  };
102
102
  useEffect(() => {
103
- if (state.appStates.outsideOperatingHours) {
104
- setOutOfOperatingHours(true);
105
- }
103
+ setOutOfOperatingHours(state.appStates.outsideOperatingHours);
106
104
  }, []);
107
105
  useEffect(() => {
108
106
  var _state$domainStates2;
@@ -6,6 +6,7 @@ function _toPrimitive(input, hint) { if (typeof input !== "object" || input ===
6
6
  import { BroadcastService } from "@microsoft/omnichannel-chat-components";
7
7
  import { BroadcastEvent, LogLevel, TelemetryEvent } from "../../../../common/telemetry/TelemetryConstants";
8
8
  import { TelemetryHelper } from "../../../../common/telemetry/TelemetryHelper";
9
+ import { TelemetryManager } from "../../../../common/telemetry/TelemetryManager";
9
10
  const supportedSignInCardContentTypes = ["application/vnd.microsoft.card.signin", "application/vnd.microsoft.card.oauth"];
10
11
  const botOauthUrlRegex = /[\S]+.botframework.com\/api\/oauth\/signin\?signin=([\S]+)/;
11
12
  const delay = t => new Promise(resolve => setTimeout(resolve, t));
@@ -83,6 +84,7 @@ export class BotAuthActivitySubscriber {
83
84
  return (activity === null || activity === void 0 ? void 0 : (_activity$attachments = activity.attachments) === null || _activity$attachments === void 0 ? void 0 : _activity$attachments.length) > 0 && activity.attachments[0] && supportedSignInCardContentTypes.indexOf(activity.attachments[0].contentType) >= 0;
84
85
  }
85
86
  async apply(activity) {
87
+ var _TelemetryManager$Int;
86
88
  this.observer.next(false); // Hides card
87
89
  const attachment = activity.attachments[0];
88
90
  const signInUrl = attachment.content.buttons[0].value;
@@ -102,7 +104,8 @@ export class BotAuthActivitySubscriber {
102
104
  const event = {
103
105
  eventName: BroadcastEvent.SigninCardReceived,
104
106
  payload: {
105
- sasUrl
107
+ sasUrl,
108
+ conversationId: (_TelemetryManager$Int = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int === void 0 ? void 0 : _TelemetryManager$Int.conversationId
106
109
  }
107
110
  };
108
111
  if (!sasUrl) {
@@ -6,7 +6,7 @@ import { defaultMiddlewareLocalizedTexts } from "../../webchatcontainerstateful/
6
6
 
7
7
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
8
  const handleChatDisconnect = (props, state, setWebChatStyles) => {
9
- var _state$appStates, _state$domainStates, _state$domainStates$m, _props$webChatContain, _props$webChatContain2;
9
+ var _state$appStates, _state$domainStates, _state$domainStates$m, _props$webChatContain, _props$webChatContain2, _props$webChatContain3, _props$webChatContain4;
10
10
  const chatDisconnectState = state === null || state === void 0 ? void 0 : (_state$appStates = state.appStates) === null || _state$appStates === void 0 ? void 0 : _state$appStates.chatDisconnectEventReceived;
11
11
  const chatDisconnectMessage = (state === null || state === void 0 ? void 0 : (_state$domainStates = state.domainStates) === null || _state$domainStates === void 0 ? void 0 : (_state$domainStates$m = _state$domainStates.middlewareLocalizedTexts) === null || _state$domainStates$m === void 0 ? void 0 : _state$domainStates$m.MIDDLEWARE_BANNER_CHAT_DISCONNECT) ?? defaultMiddlewareLocalizedTexts.MIDDLEWARE_BANNER_CHAT_DISCONNECT;
12
12
  const hideSendBoxOnConversationEnd = props === null || props === void 0 ? void 0 : (_props$webChatContain = props.webChatContainerProps) === null || _props$webChatContain === void 0 ? void 0 : (_props$webChatContain2 = _props$webChatContain.renderingMiddlewareProps) === null || _props$webChatContain2 === void 0 ? void 0 : _props$webChatContain2.hideSendboxOnConversationEnd;
@@ -27,6 +27,8 @@ const handleChatDisconnect = (props, state, setWebChatStyles) => {
27
27
  });
28
28
  break;
29
29
  case false:
30
+ // this means customer on purpose wants to hide the send box, we should not override it
31
+ if ((props === null || props === void 0 ? void 0 : (_props$webChatContain3 = props.webChatContainerProps) === null || _props$webChatContain3 === void 0 ? void 0 : (_props$webChatContain4 = _props$webChatContain3.webChatStyles) === null || _props$webChatContain4 === void 0 ? void 0 : _props$webChatContain4.hideSendBox) === true) return;
30
32
  if (hideSendBoxOnConversationEnd !== false) {
31
33
  setWebChatStyles(styles => {
32
34
  return {