@microsoft/omnichannel-chat-widget 1.7.8-main.2e1cc2b → 1.7.8-main.50111af

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 (100) hide show
  1. package/lib/cjs/common/Constants.js +57 -18
  2. package/lib/cjs/common/KeyCodes.js +6 -1
  3. package/lib/cjs/common/contextDataStore/DataStoreManager.js +6 -1
  4. package/lib/cjs/common/facades/FacadeChatSDK.js +385 -291
  5. package/lib/cjs/common/storage/default/defaultCacheManager.js +6 -3
  6. package/lib/cjs/common/telemetry/TelemetryConstants.js +139 -116
  7. package/lib/cjs/common/telemetry/TelemetryHelper.js +219 -181
  8. package/lib/cjs/common/telemetry/TelemetryManager.js +9 -2
  9. package/lib/cjs/components/chatbuttonstateful/ChatButtonStateful.js +4 -5
  10. package/lib/cjs/components/headerstateful/HeaderStateful.js +3 -5
  11. package/lib/cjs/components/livechatwidget/common/ActivityStreamHandler.js +32 -19
  12. package/lib/cjs/components/livechatwidget/common/ActivitySubscriber/BotAuthActivitySubscriber.js +71 -56
  13. package/lib/cjs/components/livechatwidget/common/ActivitySubscriber/DefaultActivitySubscriber.js +17 -8
  14. package/lib/cjs/components/livechatwidget/common/ActivitySubscriber/HiddenAdaptiveCardActivitySubscriber.js +65 -52
  15. package/lib/cjs/components/livechatwidget/common/ActivitySubscriber/PauseActivitySubscriber.js +31 -18
  16. package/lib/cjs/components/livechatwidget/common/ChatAdapterShim.js +14 -6
  17. package/lib/cjs/components/livechatwidget/common/Deferred.js +14 -6
  18. package/lib/cjs/components/livechatwidget/common/authHelper.js +15 -0
  19. package/lib/cjs/components/livechatwidget/common/chatDisconnectHelper.js +3 -1
  20. package/lib/cjs/components/livechatwidget/common/endChat.js +4 -18
  21. package/lib/cjs/components/livechatwidget/common/reconnectChatHelper.js +0 -5
  22. package/lib/cjs/components/livechatwidget/common/startChat.js +2 -23
  23. package/lib/cjs/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +17 -11
  24. package/lib/cjs/components/ooohpanestateful/OOOHPaneStateful.js +9 -3
  25. package/lib/cjs/components/postchatsurveypanestateful/PostChatSurveyPaneStateful.js +22 -6
  26. package/lib/cjs/components/postchatsurveypanestateful/common/isValidSurveyUrl.js +28 -0
  27. package/lib/cjs/components/webchatcontainerstateful/WebChatContainerStateful.js +4 -3
  28. package/lib/cjs/components/webchatcontainerstateful/common/DemoChatAdapter.js +88 -65
  29. package/lib/cjs/components/webchatcontainerstateful/common/DemoChatSDK.js +26 -7
  30. package/lib/cjs/components/webchatcontainerstateful/common/DesignerChatAdapter.js +49 -26
  31. package/lib/cjs/components/webchatcontainerstateful/common/DesignerChatSDK.js +57 -35
  32. package/lib/cjs/components/webchatcontainerstateful/common/mockadapter.js +62 -52
  33. package/lib/cjs/components/webchatcontainerstateful/common/mockchatsdk.js +95 -61
  34. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/BotMagicCodeStore.js +6 -1
  35. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/WebChatStoreLoader.js +6 -1
  36. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/markdownrenderers/HyperlinkTextOverrideRenderer.js +53 -39
  37. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/timestamps/DeliveredTimestamp.js +4 -0
  38. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/notification/NotificationHandler.js +88 -60
  39. package/lib/cjs/contexts/common/LiveChatWidgetContextInitialState.js +18 -6
  40. package/lib/cjs/firstresponselatency/Constants.js +13 -0
  41. package/lib/cjs/firstresponselatency/FirstMessageTrackerFromBot.js +118 -0
  42. package/lib/cjs/firstresponselatency/FirstResponseLatencyTracker.js +201 -0
  43. package/lib/cjs/firstresponselatency/util.js +98 -0
  44. package/lib/cjs/plugins/createChatTranscript.js +92 -62
  45. package/lib/cjs/plugins/newMessageEventHandler.js +102 -88
  46. package/lib/esm/common/Constants.js +57 -18
  47. package/lib/esm/common/KeyCodes.js +6 -1
  48. package/lib/esm/common/contextDataStore/DataStoreManager.js +6 -1
  49. package/lib/esm/common/facades/FacadeChatSDK.js +385 -291
  50. package/lib/esm/common/storage/default/defaultCacheManager.js +6 -1
  51. package/lib/esm/common/telemetry/TelemetryConstants.js +139 -116
  52. package/lib/esm/common/telemetry/TelemetryHelper.js +219 -181
  53. package/lib/esm/common/telemetry/TelemetryManager.js +9 -2
  54. package/lib/esm/components/chatbuttonstateful/ChatButtonStateful.js +4 -5
  55. package/lib/esm/components/headerstateful/HeaderStateful.js +3 -5
  56. package/lib/esm/components/livechatwidget/common/ActivityStreamHandler.js +32 -19
  57. package/lib/esm/components/livechatwidget/common/ActivitySubscriber/BotAuthActivitySubscriber.js +71 -56
  58. package/lib/esm/components/livechatwidget/common/ActivitySubscriber/DefaultActivitySubscriber.js +17 -8
  59. package/lib/esm/components/livechatwidget/common/ActivitySubscriber/HiddenAdaptiveCardActivitySubscriber.js +65 -52
  60. package/lib/esm/components/livechatwidget/common/ActivitySubscriber/PauseActivitySubscriber.js +31 -18
  61. package/lib/esm/components/livechatwidget/common/ChatAdapterShim.js +14 -6
  62. package/lib/esm/components/livechatwidget/common/Deferred.js +14 -6
  63. package/lib/esm/components/livechatwidget/common/authHelper.js +15 -0
  64. package/lib/esm/components/livechatwidget/common/chatDisconnectHelper.js +3 -1
  65. package/lib/esm/components/livechatwidget/common/endChat.js +4 -18
  66. package/lib/esm/components/livechatwidget/common/reconnectChatHelper.js +1 -6
  67. package/lib/esm/components/livechatwidget/common/startChat.js +3 -24
  68. package/lib/esm/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +17 -11
  69. package/lib/esm/components/ooohpanestateful/OOOHPaneStateful.js +9 -3
  70. package/lib/esm/components/postchatsurveypanestateful/PostChatSurveyPaneStateful.js +22 -6
  71. package/lib/esm/components/postchatsurveypanestateful/common/isValidSurveyUrl.js +21 -0
  72. package/lib/esm/components/webchatcontainerstateful/WebChatContainerStateful.js +4 -3
  73. package/lib/esm/components/webchatcontainerstateful/common/DemoChatAdapter.js +88 -65
  74. package/lib/esm/components/webchatcontainerstateful/common/DemoChatSDK.js +26 -7
  75. package/lib/esm/components/webchatcontainerstateful/common/DesignerChatAdapter.js +49 -26
  76. package/lib/esm/components/webchatcontainerstateful/common/DesignerChatSDK.js +57 -35
  77. package/lib/esm/components/webchatcontainerstateful/common/mockadapter.js +63 -52
  78. package/lib/esm/components/webchatcontainerstateful/common/mockchatsdk.js +95 -61
  79. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/BotMagicCodeStore.js +6 -1
  80. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/WebChatStoreLoader.js +6 -1
  81. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/markdownrenderers/HyperlinkTextOverrideRenderer.js +53 -39
  82. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/timestamps/DeliveredTimestamp.js +4 -0
  83. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/notification/NotificationHandler.js +88 -60
  84. package/lib/esm/contexts/common/LiveChatWidgetContextInitialState.js +18 -6
  85. package/lib/esm/firstresponselatency/Constants.js +6 -0
  86. package/lib/esm/firstresponselatency/FirstMessageTrackerFromBot.js +112 -0
  87. package/lib/esm/firstresponselatency/FirstResponseLatencyTracker.js +194 -0
  88. package/lib/esm/firstresponselatency/util.js +87 -0
  89. package/lib/esm/plugins/createChatTranscript.js +92 -62
  90. package/lib/esm/plugins/newMessageEventHandler.js +100 -86
  91. package/lib/types/common/facades/FacadeChatSDK.d.ts +1 -0
  92. package/lib/types/common/telemetry/TelemetryConstants.d.ts +10 -1
  93. package/lib/types/components/postchatsurveypanestateful/common/isValidSurveyUrl.d.ts +2 -0
  94. package/lib/types/components/webchatcontainerstateful/interfaces/IWebChatProps.d.ts +2 -2
  95. package/lib/types/contexts/common/ILiveChatWidgetContext.d.ts +1 -1
  96. package/lib/types/firstresponselatency/Constants.d.ts +30 -0
  97. package/lib/types/firstresponselatency/FirstMessageTrackerFromBot.d.ts +1 -0
  98. package/lib/types/firstresponselatency/FirstResponseLatencyTracker.d.ts +22 -0
  99. package/lib/types/firstresponselatency/util.d.ts +7 -0
  100. package/package.json +18 -6
@@ -11,74 +11,102 @@ var _WebChatStoreLoader = require("../WebChatStoreLoader");
11
11
  var _utils = require("../../../../common/utils");
12
12
  var _omnichannelChatComponents = require("@microsoft/omnichannel-chat-components");
13
13
  var _TelemetryConstants = require("../../../../common/telemetry/TelemetryConstants");
14
- class NotificationHandler {
15
- static notify(id, level, message) {
16
- if (_WebChatStoreLoader.WebChatStoreLoader.store) {
17
- _WebChatStoreLoader.WebChatStoreLoader.store.dispatch({
18
- type: _WebChatActionType.WebChatActionType.WEB_CHAT_SET_NOTIFICATION,
19
- payload: {
20
- id,
21
- level,
22
- message
23
- }
24
- });
25
- NotificationHandler.setFocusOnNotificationCloseButton();
26
- }
14
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
15
+ function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
16
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
17
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
18
+ 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); }
19
+ let NotificationHandler = /*#__PURE__*/function () {
20
+ function NotificationHandler() {
21
+ _classCallCheck(this, NotificationHandler);
27
22
  }
28
- static dismissNotification(id) {
29
- if (_WebChatStoreLoader.WebChatStoreLoader.store) {
30
- _WebChatStoreLoader.WebChatStoreLoader.store.dispatch({
31
- type: _WebChatActionType.WebChatActionType.WEB_CHAT_DISMISS_NOTIFICATION,
23
+ _createClass(NotificationHandler, null, [{
24
+ key: "notify",
25
+ value: function notify(id, level, message) {
26
+ if (_WebChatStoreLoader.WebChatStoreLoader.store) {
27
+ _WebChatStoreLoader.WebChatStoreLoader.store.dispatch({
28
+ type: _WebChatActionType.WebChatActionType.WEB_CHAT_SET_NOTIFICATION,
29
+ payload: {
30
+ id,
31
+ level,
32
+ message
33
+ }
34
+ });
35
+ NotificationHandler.setFocusOnNotificationCloseButton();
36
+ }
37
+ }
38
+ }, {
39
+ key: "dismissNotification",
40
+ value: function dismissNotification(id) {
41
+ if (_WebChatStoreLoader.WebChatStoreLoader.store) {
42
+ _WebChatStoreLoader.WebChatStoreLoader.store.dispatch({
43
+ type: _WebChatActionType.WebChatActionType.WEB_CHAT_DISMISS_NOTIFICATION,
44
+ payload: {
45
+ id
46
+ }
47
+ });
48
+ }
49
+ }
50
+ }, {
51
+ key: "notifyError",
52
+ value: function notifyError(id, message) {
53
+ _omnichannelChatComponents.BroadcastService.postMessage({
54
+ eventName: _TelemetryConstants.BroadcastEvent.OnWidgetError,
32
55
  payload: {
33
- id
56
+ errorMessage: message
34
57
  }
35
58
  });
59
+ this.notify(id, _NotificationLevel.NotificationLevel.Error, message);
36
60
  }
37
- }
38
- static notifyError(id, message) {
39
- _omnichannelChatComponents.BroadcastService.postMessage({
40
- eventName: _TelemetryConstants.BroadcastEvent.OnWidgetError,
41
- payload: {
42
- errorMessage: message
61
+ }, {
62
+ key: "notifyWarning",
63
+ value: function notifyWarning(id, message) {
64
+ this.notify(id, _NotificationLevel.NotificationLevel.Warning, message);
65
+ }
66
+ }, {
67
+ key: "notifyInfo",
68
+ value: function notifyInfo(id, message) {
69
+ this.notify(id, _NotificationLevel.NotificationLevel.Info, message);
70
+ }
71
+ }, {
72
+ key: "notifySuccess",
73
+ value: function notifySuccess(id, message) {
74
+ this.notify(id, _NotificationLevel.NotificationLevel.Success, message);
75
+ }
76
+ }, {
77
+ key: "notifyWithLevel",
78
+ value: function notifyWithLevel(id, message, level) {
79
+ if (!level) {
80
+ this.notifyInfo(id, message);
81
+ } else {
82
+ this.notify(id, level, message);
43
83
  }
44
- });
45
- this.notify(id, _NotificationLevel.NotificationLevel.Error, message);
46
- }
47
- static notifyWarning(id, message) {
48
- this.notify(id, _NotificationLevel.NotificationLevel.Warning, message);
49
- }
50
- static notifyInfo(id, message) {
51
- this.notify(id, _NotificationLevel.NotificationLevel.Info, message);
52
- }
53
- static notifySuccess(id, message) {
54
- this.notify(id, _NotificationLevel.NotificationLevel.Success, message);
55
- }
56
- static notifyWithLevel(id, message, level) {
57
- if (!level) {
58
- this.notifyInfo(id, message);
59
- } else {
60
- this.notify(id, level, message);
61
84
  }
62
- }
63
85
 
64
- /* Bypass WebChat behavior and focus on banner close button */
65
- static setFocusOnNotificationCloseButton() {
66
- const expandButton = document.querySelector(`#${_Constants.HtmlIdNames.MSLiveChatWidget} .${_Constants.HtmlClassNames.webChatBannerExpandButton}`);
67
- if (expandButton) {
68
- expandButton.focus();
69
- return;
86
+ /* Bypass WebChat behavior and focus on banner close button */
87
+ }, {
88
+ key: "setFocusOnNotificationCloseButton",
89
+ value: function setFocusOnNotificationCloseButton() {
90
+ const expandButton = document.querySelector(`#${_Constants.HtmlIdNames.MSLiveChatWidget} .${_Constants.HtmlClassNames.webChatBannerExpandButton}`);
91
+ if (expandButton) {
92
+ expandButton.focus();
93
+ return;
94
+ }
95
+ const closeButton = document.querySelector(`#${_Constants.HtmlIdNames.MSLiveChatWidget} .${_Constants.HtmlClassNames.webChatBannerCloseButton}`);
96
+ if (closeButton) {
97
+ closeButton.focus();
98
+ NotificationHandler.registerOnCloseEvent(closeButton);
99
+ return;
100
+ }
70
101
  }
71
- const closeButton = document.querySelector(`#${_Constants.HtmlIdNames.MSLiveChatWidget} .${_Constants.HtmlClassNames.webChatBannerCloseButton}`);
72
- if (closeButton) {
73
- closeButton.focus();
74
- NotificationHandler.registerOnCloseEvent(closeButton);
75
- return;
102
+ }, {
103
+ key: "registerOnCloseEvent",
104
+ value: function registerOnCloseEvent(button) {
105
+ button.onclick = () => {
106
+ (0, _utils.setFocusOnSendBox)();
107
+ };
76
108
  }
77
- }
78
- static registerOnCloseEvent(button) {
79
- button.onclick = () => {
80
- (0, _utils.setFocusOnSendBox)();
81
- };
82
- }
83
- }
109
+ }]);
110
+ return NotificationHandler;
111
+ }();
84
112
  exports.NotificationHandler = NotificationHandler;
@@ -4,14 +4,18 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.getLiveChatWidgetContextInitialState = void 0;
7
- var _ConversationState = require("./ConversationState");
8
- var _defaultMiddlewareLocalizedTexts = require("../../components/webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts");
9
- var _utils = require("../../common/utils");
10
- var _defaultClientDataStoreProvider = require("../../common/storage/default/defaultClientDataStoreProvider");
11
7
  var _Constants = require("../../common/Constants");
8
+ var _utils = require("../../common/utils");
9
+ var _ConversationState = require("./ConversationState");
12
10
  var _StartChatFailureType = require("./StartChatFailureType");
11
+ var _defaultClientDataStoreProvider = require("../../common/storage/default/defaultClientDataStoreProvider");
12
+ var _defaultMiddlewareLocalizedTexts = require("../../components/webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts");
13
13
  const getLiveChatWidgetContextInitialState = props => {
14
14
  var _props$controlProps, _props$webChatContain;
15
+ const isOutsideOperatingHours = () => {
16
+ var _props$chatConfig, _props$chatConfig$Liv, _props$chatConfig$Liv2;
17
+ return ((_props$chatConfig = props.chatConfig) === null || _props$chatConfig === void 0 ? void 0 : (_props$chatConfig$Liv = _props$chatConfig.LiveWSAndLiveChatEngJoin) === null || _props$chatConfig$Liv === void 0 ? void 0 : (_props$chatConfig$Liv2 = _props$chatConfig$Liv.OutOfOperatingHours) === null || _props$chatConfig$Liv2 === void 0 ? void 0 : _props$chatConfig$Liv2.toString().toLowerCase()) === "true";
18
+ };
15
19
  const widgetCacheId = (0, _utils.getWidgetCacheIdfromProps)(props);
16
20
  const cacheTtlInMins = (props === null || props === void 0 ? void 0 : (_props$controlProps = props.controlProps) === null || _props$controlProps === void 0 ? void 0 : _props$controlProps.cacheTtlInMins) ?? _Constants.Constants.CacheTtlInMinutes;
17
21
  const storageType = (props === null || props === void 0 ? void 0 : props.useSessionStorage) === true ? _Constants.StorageType.sessionStorage : _Constants.StorageType.localStorage;
@@ -28,6 +32,14 @@ const getLiveChatWidgetContextInitialState = props => {
28
32
  if (initialStateFromCache.appStates.conversationState === _ConversationState.ConversationState.Prechat) {
29
33
  initialStateFromCache.appStates.conversationState = _ConversationState.ConversationState.Closed;
30
34
  }
35
+
36
+ // we are always setting the chatConfig from the props to avoid any issues with the cache
37
+ initialStateFromCache.domainStates.liveChatConfig = props.chatConfig;
38
+
39
+ // Cache the result of isOutsideOperatingHours() to ensure consistency
40
+ const outsideOperatingHours = isOutsideOperatingHours();
41
+ initialStateFromCache.appStates.outsideOperatingHours = outsideOperatingHours;
42
+ initialStateFromCache.appStates.conversationState = outsideOperatingHours ? _ConversationState.ConversationState.OutOfOffice : initialStateFromCache.appStates.conversationState;
31
43
  return initialStateFromCache;
32
44
  }
33
45
  const LiveChatWidgetContextInitialState = {
@@ -52,11 +64,11 @@ const getLiveChatWidgetContextInitialState = props => {
52
64
  startChatFailureType: _StartChatFailureType.StartChatFailureType.Generic
53
65
  },
54
66
  appStates: {
55
- conversationState: _ConversationState.ConversationState.Closed,
67
+ conversationState: isOutsideOperatingHours() ? _ConversationState.ConversationState.OutOfOffice : _ConversationState.ConversationState.Closed,
56
68
  isMinimized: undefined,
57
69
  previousElementIdOnFocusBeforeModalOpen: null,
58
70
  startChatFailed: false,
59
- outsideOperatingHours: false,
71
+ outsideOperatingHours: isOutsideOperatingHours(),
60
72
  preChatResponseEmail: "",
61
73
  isAudioMuted: null,
62
74
  newMessage: false,
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.ScenarioType = void 0;
7
+ let ScenarioType;
8
+ exports.ScenarioType = ScenarioType;
9
+ (function (ScenarioType) {
10
+ ScenarioType["UserSendMessageStrategy"] = "UserSendMessageStrategy";
11
+ ScenarioType["SystemMessageStrategy"] = "SystemMessageStrategy";
12
+ ScenarioType["ReceivedMessageStrategy"] = "ReceivedMessageStrategy";
13
+ })(ScenarioType || (exports.ScenarioType = ScenarioType = {}));
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createTrackingForFirstMessage = void 0;
7
+ var _TelemetryConstants = require("../common/telemetry/TelemetryConstants");
8
+ var _omnichannelChatComponents = require("@microsoft/omnichannel-chat-components");
9
+ var _TelemetryHelper = require("../common/telemetry/TelemetryHelper");
10
+ var _util = require("./util");
11
+ // This tracker is event based, this is since we are tracking events coming from different sources
12
+ // with different timeline, therefore this is a functional approach to track the events, instead of a class based approach
13
+ const createTrackingForFirstMessage = () => {
14
+ // Reset the tracking variables
15
+ let startTracking = false;
16
+ let stopTracking = false;
17
+ let startTime = 0;
18
+ let stopTime = 0;
19
+ let stopTrackingMessage;
20
+ let flag = false;
21
+ const isMessageFromValidSender = payload => {
22
+ var _payload$tags;
23
+ // agent scenario
24
+ if (payload !== null && payload !== void 0 && (_payload$tags = payload.tags) !== null && _payload$tags !== void 0 && _payload$tags.includes("public")) {
25
+ return false;
26
+ }
27
+ return true;
28
+ };
29
+ const widgetLoadListener = _omnichannelChatComponents.BroadcastService.getMessageByEventName(_TelemetryConstants.TelemetryEvent.WidgetLoadComplete).subscribe(() => {
30
+ if (startTracking) return;
31
+ startTracking = true;
32
+ startTime = new Date().getTime();
33
+ });
34
+ const newMessageListener = _omnichannelChatComponents.BroadcastService.getMessageByEventName(_TelemetryConstants.BroadcastEvent.NewMessageReceived).subscribe(message => {
35
+ const payload = message.payload;
36
+
37
+ // we only care for bot, so we need to check if the message is from the bot
38
+ // pending to add typing message indicator signal detection
39
+
40
+ if (isMessageFromValidSender(payload)) {
41
+ if (startTracking && !stopTracking) {
42
+ stopTime = new Date().getTime();
43
+ const elapsedTime = stopTime - startTime;
44
+ stopTracking = true;
45
+ stopTrackingMessage = (0, _util.createTrackingMessage)(payload, "botMessage");
46
+ notifyFMLTrackingCompleted();
47
+ _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.INFO, {
48
+ Event: _TelemetryConstants.TelemetryEvent.BotFirstMessageLapTrack,
49
+ Description: "First Message from Bot latency tracking",
50
+ CustomProperties: {
51
+ elapsedTime,
52
+ widgetLoadedAt: startTime,
53
+ botMessage: stopTrackingMessage
54
+ }
55
+ });
56
+ }
57
+ }
58
+
59
+ // this track only first message, if coming from the bot or not
60
+ // the only difference is that it logs only those from bot
61
+ disconnectListener();
62
+ });
63
+ const notifyFMLTrackingCompleted = () => {
64
+ ackListener();
65
+ // Retry sending until flag is true, but do not block the main thread
66
+ const interval = setInterval(() => {
67
+ if (flag) {
68
+ clearInterval(interval);
69
+ } else {
70
+ _omnichannelChatComponents.BroadcastService.postMessage({
71
+ eventName: _TelemetryConstants.BroadcastEvent.FMLTrackingCompleted,
72
+ payload: null
73
+ });
74
+ }
75
+ }, 100);
76
+ };
77
+ const ackListener = () => {
78
+ const listen = _omnichannelChatComponents.BroadcastService.getMessageByEventName(_TelemetryConstants.BroadcastEvent.FMLTrackingCompletedAck).subscribe(() => {
79
+ flag = true;
80
+ listen.unsubscribe();
81
+ });
82
+ };
83
+
84
+ // Rehydrate message is received when the widget is reloaded, this is to ensure that we are not tracking messages that are not part of the current conversation
85
+ // No need to keep listerning for tracking, enforcing disconnection for the listners
86
+ const rehydrateListener = _omnichannelChatComponents.BroadcastService.getMessageByEventName(_TelemetryConstants.TelemetryEvent.RehydrateMessageReceived).subscribe(() => {
87
+ startTracking = false;
88
+ stopTracking = false;
89
+ disconnectListener();
90
+ });
91
+
92
+ // Rehydrate message is received when the widget is reloaded, this is to ensure that we are not tracking messages that are not part of the current conversation
93
+ // No need to keep listerning for tracking, enforcing disconnection for the listners
94
+ const historyListener = _omnichannelChatComponents.BroadcastService.getMessageByEventName(_TelemetryConstants.BroadcastEvent.HistoryMessageReceived).subscribe(() => {
95
+ startTracking = false;
96
+ stopTracking = false;
97
+ disconnectListener();
98
+ });
99
+ const offlineNetworkListener = _omnichannelChatComponents.BroadcastService.getMessageByEventName(_TelemetryConstants.TelemetryEvent.NetworkDisconnected).subscribe(() => {
100
+ startTracking = false;
101
+ stopTracking = false;
102
+ disconnectListener();
103
+ _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.INFO, {
104
+ Event: _TelemetryConstants.TelemetryEvent.BotFirstMessageLapTrackError,
105
+ Description: "Tracker Stopped due to network disconnection"
106
+ });
107
+ });
108
+
109
+ // this is to ensure that we are not tracking messages that are not part of the current conversation
110
+ const disconnectListener = () => {
111
+ historyListener.unsubscribe();
112
+ rehydrateListener.unsubscribe();
113
+ newMessageListener.unsubscribe();
114
+ widgetLoadListener.unsubscribe();
115
+ offlineNetworkListener.unsubscribe();
116
+ };
117
+ };
118
+ exports.createTrackingForFirstMessage = createTrackingForFirstMessage;
@@ -0,0 +1,201 @@
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 _omnichannelChatComponents = require("@microsoft/omnichannel-chat-components");
9
+ var _TelemetryHelper = require("../common/telemetry/TelemetryHelper");
10
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
11
+ function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
12
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
13
+ 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; }
14
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
15
+ 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); }
16
+ let FirstResponseLatencyTracker = /*#__PURE__*/function () {
17
+ function FirstResponseLatencyTracker() {
18
+ _classCallCheck(this, FirstResponseLatencyTracker);
19
+ _defineProperty(this, "isABotConversation", false);
20
+ _defineProperty(this, "isStarted", false);
21
+ _defineProperty(this, "isEnded", false);
22
+ _defineProperty(this, "startTrackingMessage", void 0);
23
+ _defineProperty(this, "stopTrackingMessage", void 0);
24
+ _defineProperty(this, "isReady", false);
25
+ _defineProperty(this, "offlineNetworkListener", _omnichannelChatComponents.BroadcastService.getMessageByEventName(_TelemetryConstants.TelemetryEvent.NetworkDisconnected).subscribe(() => {
26
+ this.isStarted = false;
27
+ this.isEnded = false;
28
+ _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.INFO, {
29
+ Event: _TelemetryConstants.TelemetryEvent.MessageStopLapTrackError,
30
+ Description: "Tracker Stopped due to network disconnection"
31
+ });
32
+ }));
33
+ _defineProperty(this, "fmltrackingListener", _omnichannelChatComponents.BroadcastService.getMessageByEventName(_TelemetryConstants.BroadcastEvent.FMLTrackingCompleted).subscribe(() => {
34
+ this.isReady = true;
35
+ _omnichannelChatComponents.BroadcastService.postMessage({
36
+ eventName: _TelemetryConstants.BroadcastEvent.FMLTrackingCompletedAck,
37
+ payload: null
38
+ });
39
+ }));
40
+ // Rehydrate message is received when the widget is reloaded, this is to ensure that we are not tracking messages that are not part of the current conversation
41
+ // No need to keep listerning for tracking, enforcing disconnection for the listners
42
+ _defineProperty(this, "rehydrateListener", _omnichannelChatComponents.BroadcastService.getMessageByEventName(_TelemetryConstants.TelemetryEvent.RehydrateMessageReceived).subscribe(() => {
43
+ this.isReady = true;
44
+ }));
45
+ // Rehydrate message is received when the widget is reloaded, this is to ensure that we are not tracking messages that are not part of the current conversation
46
+ // No need to keep listerning for tracking, enforcing disconnection for the listners
47
+ _defineProperty(this, "historyListener", _omnichannelChatComponents.BroadcastService.getMessageByEventName(_TelemetryConstants.BroadcastEvent.HistoryMessageReceived).subscribe(() => {
48
+ this.isReady = true;
49
+ }));
50
+ // this is a workaround to ensure in reload we track effectively the messages
51
+ // we do have a mechanism in place to prevent log agent messages.
52
+ this.isABotConversation = true;
53
+ }
54
+ _createClass(FirstResponseLatencyTracker, [{
55
+ key: "createTrackingMessage",
56
+ value: function createTrackingMessage(payload, type) {
57
+ return {
58
+ Id: payload.Id,
59
+ role: payload.role,
60
+ timestamp: payload === null || payload === void 0 ? void 0 : payload.timestamp,
61
+ tags: payload.tags,
62
+ messageType: payload.messageType,
63
+ text: payload.text,
64
+ type: type,
65
+ checkTime: new Date().getTime()
66
+ };
67
+ }
68
+
69
+ // Tracking Functions
70
+ }, {
71
+ key: "startTracking",
72
+ value: function startTracking(payload) {
73
+ if (!this.isReady) return;
74
+ // this prevents to initiate tracking for multiple incoming messages
75
+ if (this.isStarted) {
76
+ return;
77
+ }
78
+ // this is to ensure we track only messages where bot is engaged
79
+ if (!this.isABotConversation) {
80
+ return;
81
+ }
82
+ // control of states to prevent clashing of messages
83
+ this.isStarted = true;
84
+ this.isEnded = false;
85
+ // The idea of using types is to enrich telemetry data
86
+ this.startTrackingMessage = this.createTrackingMessage(payload, "userMessage");
87
+ }
88
+ }, {
89
+ key: "handleAgentMessage",
90
+ value: function handleAgentMessage(payload) {
91
+ var _payload$tags;
92
+ // this tag so far is only present in agent messages
93
+ if (payload !== null && payload !== void 0 && (_payload$tags = payload.tags) !== null && _payload$tags !== void 0 && _payload$tags.includes("public")) {
94
+ this.deregister();
95
+ }
96
+ }
97
+ }, {
98
+ key: "stopTracking",
99
+ value: function stopTracking(payload) {
100
+ var _this$stopTrackingMes, _this$startTrackingMe;
101
+ // this prevents execution for multiple incoming messages from the bot.
102
+ if (this.isEnded && !this.isStarted) {
103
+ return;
104
+ }
105
+
106
+ // control of states to prevent clashing of messages
107
+ this.isEnded = true;
108
+ this.isStarted = false;
109
+
110
+ // The idea of using types is to enrich telemetry data
111
+ this.stopTrackingMessage = this.createTrackingMessage(payload, "botMessage");
112
+ // calculating elapsed time
113
+ 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);
114
+ _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.INFO, {
115
+ Event: _TelemetryConstants.TelemetryEvent.MessageLapTrack,
116
+ Description: "First response latency tracking",
117
+ CustomProperties: {
118
+ elapsedTime,
119
+ userMessage: this.startTrackingMessage,
120
+ botMessage: this.stopTrackingMessage
121
+ }
122
+ });
123
+ }
124
+
125
+ // mechanism to ensure we track only allowed conversations
126
+ }, {
127
+ key: "isMessageFromValidSender",
128
+ value: function isMessageFromValidSender(payload) {
129
+ var _payload$tags2;
130
+ // agent scenario
131
+ if (payload !== null && payload !== void 0 && (_payload$tags2 = payload.tags) !== null && _payload$tags2 !== void 0 && _payload$tags2.includes("public")) {
132
+ this.handleAgentMessage(payload);
133
+ return false;
134
+ }
135
+ return true;
136
+ }
137
+ }, {
138
+ key: "startClock",
139
+ value: function startClock(payload) {
140
+ try {
141
+ if (!payload || !payload.Id) {
142
+ throw new Error("Invalid payload");
143
+ }
144
+ this.startTracking(payload);
145
+ } catch (e) {
146
+ _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.ERROR, {
147
+ Event: _TelemetryConstants.TelemetryEvent.MessageStartLapTrackError,
148
+ Description: "Error while starting the clock",
149
+ ExceptionDetails: e,
150
+ CustomProperties: {
151
+ payload: payload
152
+ }
153
+ });
154
+ }
155
+ }
156
+ }, {
157
+ key: "stopClock",
158
+ value: function stopClock(payload) {
159
+ try {
160
+ if (!payload || !payload.Id) {
161
+ throw new Error("Invalid payload");
162
+ }
163
+ if (!this.isMessageFromValidSender(payload)) return;
164
+ if (this.isABotConversation && this.isStarted) {
165
+ this.stopTracking(payload);
166
+ }
167
+ } catch (e) {
168
+ console.error("FRL : error while trying to stop the tracker", e);
169
+ _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.ERROR, {
170
+ Event: _TelemetryConstants.TelemetryEvent.MessageStopLapTrackError,
171
+ Description: "Error while stopping the clock",
172
+ ExceptionDetails: e,
173
+ CustomProperties: {
174
+ payload: payload
175
+ }
176
+ });
177
+ //reset state
178
+ this.startTrackingMessage = undefined;
179
+ this.stopTrackingMessage = undefined;
180
+ this.isStarted = false;
181
+ this.isEnded = false;
182
+ }
183
+ }
184
+ }, {
185
+ key: "deregister",
186
+ value: function deregister() {
187
+ // Reset State
188
+ this.isABotConversation = false;
189
+ this.isStarted = false;
190
+ this.isEnded = false;
191
+ this.startTrackingMessage = undefined;
192
+ this.stopTrackingMessage = undefined;
193
+ this.offlineNetworkListener.unsubscribe();
194
+ this.fmltrackingListener.unsubscribe();
195
+ this.rehydrateListener.unsubscribe();
196
+ this.historyListener.unsubscribe();
197
+ }
198
+ }]);
199
+ return FirstResponseLatencyTracker;
200
+ }();
201
+ exports.FirstResponseLatencyTracker = FirstResponseLatencyTracker;
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.polyfillMessagePayloadForEvent = exports.isHistoryMessage = exports.getScenarioType = exports.createTrackingMessage = 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;
86
+ const createTrackingMessage = (payload, type) => {
87
+ return {
88
+ Id: payload.Id,
89
+ role: payload.role,
90
+ timestamp: payload === null || payload === void 0 ? void 0 : payload.timestamp,
91
+ tags: payload.tags,
92
+ messageType: payload.messageType,
93
+ text: payload.text,
94
+ type: type,
95
+ checkTime: new Date().getTime()
96
+ };
97
+ };
98
+ exports.createTrackingMessage = createTrackingMessage;