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

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 (33) hide show
  1. package/lib/cjs/common/telemetry/TelemetryConstants.js +5 -0
  2. package/lib/cjs/components/livechatwidget/common/ActivitySubscriber/BotAuthActivitySubscriber.js +4 -1
  3. package/lib/cjs/components/livechatwidget/common/endChat.js +4 -18
  4. package/lib/cjs/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +14 -8
  5. package/lib/cjs/components/ooohpanestateful/OOOHPaneStateful.js +4 -0
  6. package/lib/cjs/components/postchatsurveypanestateful/PostChatSurveyPaneStateful.js +22 -6
  7. package/lib/cjs/components/postchatsurveypanestateful/common/isValidSurveyUrl.js +28 -0
  8. package/lib/cjs/contexts/common/LiveChatWidgetContextInitialState.js +4 -4
  9. package/lib/cjs/firstresponselatency/Constants.js +13 -0
  10. package/lib/cjs/firstresponselatency/FirstResponseLatencyTracker.js +152 -0
  11. package/lib/cjs/firstresponselatency/util.js +85 -0
  12. package/lib/cjs/plugins/createChatTranscript.js +4 -4
  13. package/lib/cjs/plugins/newMessageEventHandler.js +102 -88
  14. package/lib/esm/common/telemetry/TelemetryConstants.js +5 -0
  15. package/lib/esm/components/livechatwidget/common/ActivitySubscriber/BotAuthActivitySubscriber.js +4 -1
  16. package/lib/esm/components/livechatwidget/common/endChat.js +4 -18
  17. package/lib/esm/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +14 -8
  18. package/lib/esm/components/ooohpanestateful/OOOHPaneStateful.js +4 -0
  19. package/lib/esm/components/postchatsurveypanestateful/PostChatSurveyPaneStateful.js +22 -6
  20. package/lib/esm/components/postchatsurveypanestateful/common/isValidSurveyUrl.js +21 -0
  21. package/lib/esm/contexts/common/LiveChatWidgetContextInitialState.js +4 -4
  22. package/lib/esm/firstresponselatency/Constants.js +6 -0
  23. package/lib/esm/firstresponselatency/FirstResponseLatencyTracker.js +145 -0
  24. package/lib/esm/firstresponselatency/util.js +75 -0
  25. package/lib/esm/plugins/createChatTranscript.js +4 -4
  26. package/lib/esm/plugins/newMessageEventHandler.js +100 -86
  27. package/lib/types/common/telemetry/TelemetryConstants.d.ts +5 -0
  28. package/lib/types/components/postchatsurveypanestateful/common/isValidSurveyUrl.d.ts +2 -0
  29. package/lib/types/contexts/common/ILiveChatWidgetContext.d.ts +1 -1
  30. package/lib/types/firstresponselatency/Constants.d.ts +30 -0
  31. package/lib/types/firstresponselatency/FirstResponseLatencyTracker.d.ts +17 -0
  32. package/lib/types/firstresponselatency/util.d.ts +6 -0
  33. package/package.json +1 -1
@@ -205,6 +205,9 @@ exports.TelemetryEvent = TelemetryEvent;
205
205
  TelemetryEvent["ReconnectChatMinimize"] = "ReconnectChatMinimize";
206
206
  TelemetryEvent["MessageSent"] = "MessageSent";
207
207
  TelemetryEvent["MessageReceived"] = "MessageReceived";
208
+ TelemetryEvent["MessageLapTrack"] = "MessageLapTrack";
209
+ TelemetryEvent["MessageStartLapTrackError"] = "MessageStartLapTrackError";
210
+ TelemetryEvent["MessageStopLapTrackError"] = "MessageStopLapTrackError";
208
211
  TelemetryEvent["SystemMessageReceived"] = "SystemMessageReceived";
209
212
  TelemetryEvent["RehydrateMessageReceived"] = "RehydrateMessageReceived";
210
213
  TelemetryEvent["CustomContextReceived"] = "CustomContextReceived";
@@ -219,6 +222,8 @@ exports.TelemetryEvent = TelemetryEvent;
219
222
  TelemetryEvent["PostChatContextCallFailed"] = "PostChatContextCallFailed";
220
223
  TelemetryEvent["PostChatSurveyLoadingPaneLoaded"] = "PostChatSurveyLoadingPaneLoaded";
221
224
  TelemetryEvent["PostChatSurveyLoaded"] = "PostChatSurveyLoaded";
225
+ TelemetryEvent["PostChatSurveyUrlValidationCompleted"] = "PostChatSurveyUrlValidationCompleted";
226
+ TelemetryEvent["PostChatSurveyUrlValidationFailed"] = "PostChatSurveyUrlValidationFailed";
222
227
  TelemetryEvent["ChatDisconnectThreadEventReceived"] = "ChatDisconnectThreadEventReceived";
223
228
  TelemetryEvent["HiddenAdaptiveCardMessageReceived"] = "HiddenAdaptiveCardMessageReceived";
224
229
  TelemetryEvent["EndingAdapterAfterDisconnectionError"] = "EndingAdapterAfterDisconnectionError";
@@ -7,6 +7,7 @@ exports.BotAuthActivitySubscriber = void 0;
7
7
  var _omnichannelChatComponents = require("@microsoft/omnichannel-chat-components");
8
8
  var _TelemetryConstants = require("../../../../common/telemetry/TelemetryConstants");
9
9
  var _TelemetryHelper = require("../../../../common/telemetry/TelemetryHelper");
10
+ var _TelemetryManager = require("../../../../common/telemetry/TelemetryManager");
10
11
  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; }
11
12
  function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
12
13
  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); }
@@ -87,6 +88,7 @@ class BotAuthActivitySubscriber {
87
88
  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;
88
89
  }
89
90
  async apply(activity) {
91
+ var _TelemetryManager$Int;
90
92
  this.observer.next(false); // Hides card
91
93
  const attachment = activity.attachments[0];
92
94
  const signInUrl = attachment.content.buttons[0].value;
@@ -106,7 +108,8 @@ class BotAuthActivitySubscriber {
106
108
  const event = {
107
109
  eventName: _TelemetryConstants.BroadcastEvent.SigninCardReceived,
108
110
  payload: {
109
- sasUrl
111
+ sasUrl,
112
+ conversationId: (_TelemetryManager$Int = _TelemetryManager.TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int === void 0 ? void 0 : _TelemetryManager$Int.conversationId
110
113
  }
111
114
  };
112
115
  if (!sasUrl) {
@@ -209,7 +209,7 @@ const endChat = async (props, facadeChatSDK, state, dispatch, setAdapter, setWeb
209
209
  payload: undefined
210
210
  });
211
211
  // Always allow to close the chat for embedded mode irrespective of end chat errors
212
- closeChatWidget(dispatch, props, state);
212
+ closeChatWidget(dispatch);
213
213
  facadeChatSDK.destroy();
214
214
  }
215
215
  }
@@ -339,21 +339,7 @@ const endVoiceVideoCallIfOngoing = async (facadeChatSDK, dispatch) => {
339
339
  }
340
340
  };
341
341
  exports.endVoiceVideoCallIfOngoing = endVoiceVideoCallIfOngoing;
342
- const closeChatWidget = (dispatch, props, state) => {
343
- var _state$appStates5;
344
- if (state !== null && state !== void 0 && (_state$appStates5 = state.appStates) !== null && _state$appStates5 !== void 0 && _state$appStates5.hideStartChatButton) {
345
- var _props$controlProps2, _props$controlProps3;
346
- // Only close chat if header is enabled for popout
347
- // TODO : This condition needs to be removed eventually when the filler UX is ready for popout, removing this condition would show a blank screen for OOB Widget
348
- if ((props === null || props === void 0 ? void 0 : (_props$controlProps2 = props.controlProps) === null || _props$controlProps2 === void 0 ? void 0 : _props$controlProps2.hideHeader) === undefined || (props === null || props === void 0 ? void 0 : (_props$controlProps3 = props.controlProps) === null || _props$controlProps3 === void 0 ? void 0 : _props$controlProps3.hideHeader) === false) {
349
- dispatch({
350
- type: _LiveChatWidgetActionType.LiveChatWidgetActionType.SET_CONVERSATION_STATE,
351
- payload: _ConversationState.ConversationState.Closed
352
- });
353
- }
354
- return;
355
- }
356
-
342
+ const closeChatWidget = dispatch => {
357
343
  // Embedded chat
358
344
  dispatch({
359
345
  type: _LiveChatWidgetActionType.LiveChatWidgetActionType.SET_CONVERSATION_STATE,
@@ -373,6 +359,6 @@ const chatTokenCleanUp = async dispatch => {
373
359
  };
374
360
 
375
361
  const getEndChatEventName = async (facadeChatSDK, props) => {
376
- var _facadeChatSDK$getCha2, _facadeChatSDK$getCha3, _facadeChatSDK$getCha4, _facadeChatSDK$getCha5, _props$controlProps4;
377
- return (0, _utils.getWidgetEndChatEventName)((_facadeChatSDK$getCha2 = facadeChatSDK.getChatSDK()) === null || _facadeChatSDK$getCha2 === void 0 ? void 0 : (_facadeChatSDK$getCha3 = _facadeChatSDK$getCha2.omnichannelConfig) === null || _facadeChatSDK$getCha3 === void 0 ? void 0 : _facadeChatSDK$getCha3.orgId, (_facadeChatSDK$getCha4 = facadeChatSDK.getChatSDK()) === null || _facadeChatSDK$getCha4 === void 0 ? void 0 : (_facadeChatSDK$getCha5 = _facadeChatSDK$getCha4.omnichannelConfig) === null || _facadeChatSDK$getCha5 === void 0 ? void 0 : _facadeChatSDK$getCha5.widgetId, (props === null || props === void 0 ? void 0 : (_props$controlProps4 = props.controlProps) === null || _props$controlProps4 === void 0 ? void 0 : _props$controlProps4.widgetInstanceId) ?? "");
362
+ var _facadeChatSDK$getCha2, _facadeChatSDK$getCha3, _facadeChatSDK$getCha4, _facadeChatSDK$getCha5, _props$controlProps2;
363
+ return (0, _utils.getWidgetEndChatEventName)((_facadeChatSDK$getCha2 = facadeChatSDK.getChatSDK()) === null || _facadeChatSDK$getCha2 === void 0 ? void 0 : (_facadeChatSDK$getCha3 = _facadeChatSDK$getCha2.omnichannelConfig) === null || _facadeChatSDK$getCha3 === void 0 ? void 0 : _facadeChatSDK$getCha3.orgId, (_facadeChatSDK$getCha4 = facadeChatSDK.getChatSDK()) === null || _facadeChatSDK$getCha4 === void 0 ? void 0 : (_facadeChatSDK$getCha5 = _facadeChatSDK$getCha4.omnichannelConfig) === null || _facadeChatSDK$getCha5 === void 0 ? void 0 : _facadeChatSDK$getCha5.widgetId, (props === null || props === void 0 ? void 0 : (_props$controlProps2 = props.controlProps) === null || _props$controlProps2 === void 0 ? void 0 : _props$controlProps2.widgetInstanceId) ?? "");
378
364
  };
@@ -417,7 +417,7 @@ const LiveChatWidgetStateful = props => {
417
417
 
418
418
  // Start chat from SDK Event
419
419
  _omnichannelChatComponents.BroadcastService.getMessageByEventName(_TelemetryConstants.BroadcastEvent.StartChat).subscribe(msg => {
420
- var _props$chatConfig5, _props$chatConfig5$Li, _props$chatConfig6, _props$chatConfig6$Li, _msg$payload5, _msg$payload6, _msg$payload7, _msg$payload9, _inMemoryState$appSta2, _inMemoryState$appSta3, _inMemoryState$appSta4, _inMemoryState$appSta5;
420
+ var _props$chatConfig5, _props$chatConfig5$Li, _props$chatConfig6, _props$chatConfig6$Li, _msg$payload5, _msg$payload6, _msg$payload7, _msg$payload9, _inMemoryState$appSta2, _inMemoryState$appSta3;
421
421
  // If chat is out of operating hours chat widget sets the conversation state to OutOfOffice.
422
422
  if (typeof (props === null || props === void 0 ? void 0 : (_props$chatConfig5 = props.chatConfig) === null || _props$chatConfig5 === void 0 ? void 0 : (_props$chatConfig5$Li = _props$chatConfig5.LiveWSAndLiveChatEngJoin) === null || _props$chatConfig5$Li === void 0 ? void 0 : _props$chatConfig5$Li.OutOfOperatingHours) === "string" && (props === null || props === void 0 ? void 0 : (_props$chatConfig6 = props.chatConfig) === null || _props$chatConfig6 === void 0 ? void 0 : (_props$chatConfig6$Li = _props$chatConfig6.LiveWSAndLiveChatEngJoin) === null || _props$chatConfig6$Li === void 0 ? void 0 : _props$chatConfig6$Li.OutOfOperatingHours.toLowerCase()) === "true") {
423
423
  (state === null || state === void 0 ? void 0 : state.appStates.isMinimized) && dispatch({
@@ -455,8 +455,14 @@ const LiveChatWidgetStateful = props => {
455
455
  });
456
456
  inMemoryState.domainStates.customContext = msg === null || msg === void 0 ? void 0 : (_msg$payload9 = msg.payload) === null || _msg$payload9 === void 0 ? void 0 : _msg$payload9.customContext;
457
457
 
458
- // Only initiate new chat if widget runtime state is one of the followings
459
- if (((_inMemoryState$appSta2 = inMemoryState.appStates) === null || _inMemoryState$appSta2 === void 0 ? void 0 : _inMemoryState$appSta2.conversationState) === _ConversationState.ConversationState.Closed || ((_inMemoryState$appSta3 = inMemoryState.appStates) === null || _inMemoryState$appSta3 === void 0 ? void 0 : _inMemoryState$appSta3.conversationState) === _ConversationState.ConversationState.InActive || ((_inMemoryState$appSta4 = inMemoryState.appStates) === null || _inMemoryState$appSta4 === void 0 ? void 0 : _inMemoryState$appSta4.conversationState) === _ConversationState.ConversationState.Postchat) {
458
+ /*
459
+ * If the conversation is in closed state then we start a new chat,
460
+ * else if the conversation is in active state then we maximize the chat
461
+ * If the conversation is in inactive or postchat state then we maximize the chat.
462
+ *
463
+ * To start a new chat, it needs to be called via the close button or close chat via SDK.
464
+ **/
465
+ if (((_inMemoryState$appSta2 = inMemoryState.appStates) === null || _inMemoryState$appSta2 === void 0 ? void 0 : _inMemoryState$appSta2.conversationState) === _ConversationState.ConversationState.Closed) {
460
466
  _omnichannelChatComponents.BroadcastService.postMessage({
461
467
  eventName: _TelemetryConstants.BroadcastEvent.ChatInitiated
462
468
  });
@@ -465,7 +471,7 @@ const LiveChatWidgetStateful = props => {
465
471
  }
466
472
 
467
473
  // If minimized, maximize the chat
468
- if ((inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta5 = inMemoryState.appStates) === null || _inMemoryState$appSta5 === void 0 ? void 0 : _inMemoryState$appSta5.isMinimized) === true) {
474
+ if ((inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta3 = inMemoryState.appStates) === null || _inMemoryState$appSta3 === void 0 ? void 0 : _inMemoryState$appSta3.isMinimized) === true) {
469
475
  var _inMemoryState$domain, _inMemoryState$domain2, _inMemoryState$domain3, _inMemoryState$domain4;
470
476
  dispatch({
471
477
  type: _LiveChatWidgetActionType.LiveChatWidgetActionType.SET_MINIMIZED,
@@ -593,12 +599,12 @@ const LiveChatWidgetStateful = props => {
593
599
  disablePolling: true
594
600
  });
595
601
  facadeChatSDK === null || facadeChatSDK === void 0 ? void 0 : facadeChatSDK.onAgentEndSession(event => {
596
- var _inMemoryState$appSta6;
602
+ var _inMemoryState$appSta4;
597
603
  const inMemoryState = (0, _createReducer.executeReducer)(state, {
598
604
  type: _LiveChatWidgetActionType.LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
599
605
  payload: null
600
606
  });
601
- if ("participantsRemoved" in event && (inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta6 = inMemoryState.appStates) === null || _inMemoryState$appSta6 === void 0 ? void 0 : _inMemoryState$appSta6.conversationState) === _ConversationState.ConversationState.Active) {
607
+ if ("participantsRemoved" in event && (inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta4 = inMemoryState.appStates) === null || _inMemoryState$appSta4 === void 0 ? void 0 : _inMemoryState$appSta4.conversationState) === _ConversationState.ConversationState.Active) {
602
608
  setWebChatStyles(styles => {
603
609
  return {
604
610
  ...styles,
@@ -741,13 +747,13 @@ const LiveChatWidgetStateful = props => {
741
747
 
742
748
  // Handle Chat disconnect cases
743
749
  (0, _react2.useEffect)(() => {
744
- var _inMemoryState$appSta7;
750
+ var _inMemoryState$appSta5;
745
751
  const inMemoryState = (0, _createReducer.executeReducer)(state, {
746
752
  type: _LiveChatWidgetActionType.LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
747
753
  payload: null
748
754
  });
749
755
  (0, _chatDisconnectHelper.handleChatDisconnect)(props, inMemoryState, setWebChatStyles);
750
- const chatDisconnectState = inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta7 = inMemoryState.appStates) === null || _inMemoryState$appSta7 === void 0 ? void 0 : _inMemoryState$appSta7.chatDisconnectEventReceived;
756
+ const chatDisconnectState = inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta5 = inMemoryState.appStates) === null || _inMemoryState$appSta5 === void 0 ? void 0 : _inMemoryState$appSta5.chatDisconnectEventReceived;
751
757
  if (chatDisconnectState && adapter) {
752
758
  try {
753
759
  adapter.end();
@@ -11,6 +11,7 @@ var _omnichannelChatComponents = require("@microsoft/omnichannel-chat-components
11
11
  var _TelemetryHelper = require("../../common/telemetry/TelemetryHelper");
12
12
  var _defaultgeneralOOOHPaneStyleProps = require("./common/defaultStyleProps/defaultgeneralOOOHPaneStyleProps");
13
13
  var _useChatContextStore = _interopRequireDefault(require("../../hooks/useChatContextStore"));
14
+ var _dompurify = _interopRequireDefault(require("dompurify"));
14
15
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
16
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
16
17
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
@@ -49,6 +50,9 @@ const OutOfOfficeHoursPaneStateful = props => {
49
50
  ElapsedTimeInMilliseconds: uiTimer.milliSecondsElapsed
50
51
  });
51
52
  }, []);
53
+ if (controlProps !== null && controlProps !== void 0 && controlProps.titleText) {
54
+ controlProps.titleText = _dompurify.default.sanitize(controlProps.titleText);
55
+ }
52
56
  return /*#__PURE__*/_react.default.createElement(_omnichannelChatComponents.OutOfOfficeHoursPane, {
53
57
  componentOverrides: props.componentOverrides,
54
58
  controlProps: controlProps,
@@ -14,17 +14,19 @@ var _TelemetryHelper = require("../../common/telemetry/TelemetryHelper");
14
14
  var _defaultgeneralPostChatSurveyPaneStyleProps = require("./common/defaultStyleProps/defaultgeneralPostChatSurveyPaneStyleProps");
15
15
  var _utils = require("../../common/utils");
16
16
  var _useChatContextStore = _interopRequireDefault(require("../../hooks/useChatContextStore"));
17
+ var _isValidSurveyUrl = _interopRequireDefault(require("./common/isValidSurveyUrl"));
17
18
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
18
19
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
19
20
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
20
21
  const generateSurveyInviteLink = function (surveyInviteLink, isEmbed, locale, compact) {
21
22
  let showMultiLingual = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
22
- const surveyLink = `${surveyInviteLink}
23
- &embed=${isEmbed.toString()}
24
- &compact=${compact.toString() ?? "true"}
25
- &lang=${locale ?? "en-us"}
26
- &showmultilingual=${showMultiLingual.toString() ?? "false"}`;
27
- return surveyLink;
23
+ const surveyLinkParams = new URLSearchParams({
24
+ embed: isEmbed.toString(),
25
+ compact: (compact ?? true).toString(),
26
+ lang: locale ?? "en-us",
27
+ showmultilingual: (showMultiLingual ?? false).toString()
28
+ });
29
+ return `${surveyInviteLink}&${surveyLinkParams.toString()}`;
28
30
  };
29
31
  const PostChatSurveyPaneStateful = props => {
30
32
  var _props$styleProps, _state$appStates, _props$controlProps;
@@ -54,6 +56,20 @@ const PostChatSurveyPaneStateful = props => {
54
56
  surveyURL: ((_props$controlProps = props.controlProps) === null || _props$controlProps === void 0 ? void 0 : _props$controlProps.surveyURL) ?? surveyInviteLink,
55
57
  ...props.controlProps
56
58
  };
59
+ if (controlProps.surveyURL) {
60
+ if (!(0, _isValidSurveyUrl.default)(controlProps.surveyURL)) {
61
+ _TelemetryHelper.TelemetryHelper.logLoadingEvent(_TelemetryConstants.LogLevel.ERROR, {
62
+ Event: _TelemetryConstants.TelemetryEvent.PostChatSurveyUrlValidationFailed,
63
+ Description: `${controlProps.surveyURL} is not a valid Survey URL`
64
+ });
65
+ controlProps.surveyURL = "";
66
+ } else {
67
+ _TelemetryHelper.TelemetryHelper.logLoadingEvent(_TelemetryConstants.LogLevel.INFO, {
68
+ Event: _TelemetryConstants.TelemetryEvent.PostChatSurveyUrlValidationCompleted,
69
+ Description: `${controlProps.surveyURL} is a valid Survey URL`
70
+ });
71
+ }
72
+ }
57
73
 
58
74
  // Move focus to the first button
59
75
  (0, _react.useEffect)(() => {
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _utils = require("../../../common/utils");
8
+ const validRootDomains = ["microsoft.com", "microsoft.us", "appsplatform.us", "powervirtualagents.cn"];
9
+ const isValidSurveyUrl = url => {
10
+ if ((0, _utils.isNullOrEmptyString)(url)) {
11
+ return false;
12
+ }
13
+ try {
14
+ const objectUrl = new URL(url);
15
+ if (!objectUrl.origin || objectUrl.origin === "null") {
16
+ return false;
17
+ }
18
+ const validDomain = validRootDomains.find(domain => objectUrl.origin.endsWith(domain));
19
+ if (validDomain) {
20
+ return true;
21
+ }
22
+ } catch (error) {
23
+ return false;
24
+ }
25
+ return false;
26
+ };
27
+ var _default = isValidSurveyUrl;
28
+ exports.default = _default;
@@ -4,12 +4,12 @@ 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
15
  const widgetCacheId = (0, _utils.getWidgetCacheIdfromProps)(props);
@@ -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,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) {