@microsoft/omnichannel-chat-widget 1.7.4-main.9d63968 → 1.7.4-main.9edefc7

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 (20) hide show
  1. package/lib/cjs/common/telemetry/TelemetryConstants.js +1 -0
  2. package/lib/cjs/components/footerstateful/FooterStateful.js +12 -9
  3. package/lib/cjs/components/headerstateful/HeaderStateful.js +4 -0
  4. package/lib/cjs/components/livechatwidget/common/endChat.js +20 -9
  5. package/lib/cjs/components/livechatwidget/common/initWebChatComposer.js +8 -4
  6. package/lib/cjs/components/livechatwidget/common/startChat.js +6 -0
  7. package/lib/cjs/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +20 -1
  8. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activityMiddleware.js +2 -1
  9. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/notification/NotificationHandler.js +8 -0
  10. package/lib/esm/common/telemetry/TelemetryConstants.js +1 -0
  11. package/lib/esm/components/footerstateful/FooterStateful.js +12 -9
  12. package/lib/esm/components/headerstateful/HeaderStateful.js +4 -0
  13. package/lib/esm/components/livechatwidget/common/endChat.js +20 -9
  14. package/lib/esm/components/livechatwidget/common/initWebChatComposer.js +8 -4
  15. package/lib/esm/components/livechatwidget/common/startChat.js +6 -0
  16. package/lib/esm/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +20 -1
  17. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activityMiddleware.js +2 -1
  18. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/notification/NotificationHandler.js +8 -0
  19. package/lib/types/common/telemetry/TelemetryConstants.d.ts +2 -1
  20. package/package.json +4 -2
@@ -65,6 +65,7 @@ exports.BroadcastEvent = BroadcastEvent;
65
65
  BroadcastEvent["UpdateConversationDataForTelemetry"] = "UpdateConversationDataForTelemetry";
66
66
  BroadcastEvent["ContactIdNotFound"] = "ContactIdNotFound";
67
67
  BroadcastEvent["SyncMinimize"] = "SyncMinimize";
68
+ BroadcastEvent["OnWidgetError"] = "OnWidgetError";
68
69
  })(BroadcastEvent || (exports.BroadcastEvent = BroadcastEvent = {}));
69
70
  let TelemetryEvent;
70
71
  exports.TelemetryEvent = TelemetryEvent;
@@ -17,12 +17,13 @@ var _TelemetryHelper = require("../../common/telemetry/TelemetryHelper");
17
17
  var _DownloadTranscriptStateful = require("./downloadtranscriptstateful/DownloadTranscriptStateful");
18
18
  var _useChatContextStore = _interopRequireDefault(require("../../hooks/useChatContextStore"));
19
19
  var _useChatSDKStore = _interopRequireDefault(require("../../hooks/useChatSDKStore"));
20
+ var _ConversationState = require("../../contexts/common/ConversationState");
20
21
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21
22
  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); }
22
23
  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; }
23
24
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
24
25
  const FooterStateful = props => {
25
- var _footerProps$controlP3, _footerProps$controlP6;
26
+ var _footerProps$controlP3;
26
27
  const [state, dispatch] = (0, _useChatContextStore.default)();
27
28
  // hideFooterDisplay - the purpose of this is to keep the footer always "active",
28
29
  // but hide it visually in certain states (e.g., loading state) and show in some other states (e.g. active state).
@@ -90,21 +91,23 @@ const FooterStateful = props => {
90
91
  }
91
92
  };
92
93
  (0, _react.useEffect)(() => {
93
- if (state.appStates.isAudioMuted === null) {
94
- var _footerProps$controlP4, _footerProps$controlP5;
95
- dispatch({
96
- type: _LiveChatWidgetActionType.LiveChatWidgetActionType.SET_AUDIO_NOTIFICATION,
97
- payload: (footerProps === null || footerProps === void 0 ? void 0 : (_footerProps$controlP4 = footerProps.controlProps) === null || _footerProps$controlP4 === void 0 ? void 0 : (_footerProps$controlP5 = _footerProps$controlP4.audioNotificationButtonProps) === null || _footerProps$controlP5 === void 0 ? void 0 : _footerProps$controlP5.isAudioMuted) ?? false
98
- });
94
+ if (state.appStates.conversationState === _ConversationState.ConversationState.Active) {
95
+ if (state.appStates.isAudioMuted === null) {
96
+ var _footerProps$controlP4, _footerProps$controlP5, _footerProps$controlP6;
97
+ dispatch({
98
+ type: _LiveChatWidgetActionType.LiveChatWidgetActionType.SET_AUDIO_NOTIFICATION,
99
+ payload: footerProps !== null && footerProps !== void 0 && (_footerProps$controlP4 = footerProps.controlProps) !== null && _footerProps$controlP4 !== void 0 && _footerProps$controlP4.hideAudioNotificationButton ? true : (footerProps === null || footerProps === void 0 ? void 0 : (_footerProps$controlP5 = footerProps.controlProps) === null || _footerProps$controlP5 === void 0 ? void 0 : (_footerProps$controlP6 = _footerProps$controlP5.audioNotificationButtonProps) === null || _footerProps$controlP6 === void 0 ? void 0 : _footerProps$controlP6.isAudioMuted) ?? false
100
+ });
101
+ }
99
102
  }
100
- }, []);
103
+ }, [state.appStates.conversationState]);
101
104
  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, !hideFooterDisplay && /*#__PURE__*/_react.default.createElement(_omnichannelChatComponents.Footer, {
102
105
  componentOverrides: footerProps === null || footerProps === void 0 ? void 0 : footerProps.componentOverrides,
103
106
  controlProps: controlProps,
104
107
  styleProps: footerProps === null || footerProps === void 0 ? void 0 : footerProps.styleProps
105
108
  }), /*#__PURE__*/_react.default.createElement(_AudioNotificationStateful.default, {
106
109
  audioSrc: (audioNotificationProps === null || audioNotificationProps === void 0 ? void 0 : audioNotificationProps.audioSrc) ?? _Audios.NewMessageNotificationSoundBase64,
107
- isAudioMuted: state.appStates.isAudioMuted === null ? (footerProps === null || footerProps === void 0 ? void 0 : (_footerProps$controlP6 = footerProps.controlProps) === null || _footerProps$controlP6 === void 0 ? void 0 : _footerProps$controlP6.hideAudioNotificationButton) ?? false : state.appStates.isAudioMuted ?? false
110
+ isAudioMuted: state.appStates.isAudioMuted ?? false
108
111
  }));
109
112
  };
110
113
  exports.FooterStateful = FooterStateful;
@@ -88,6 +88,10 @@ const HeaderStateful = props => {
88
88
  text: "We're Offline"
89
89
  },
90
90
  onMinimizeClick: () => {
91
+ _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.INFO, {
92
+ Event: _TelemetryConstants.TelemetryEvent.HeaderMinimizeButtonClicked,
93
+ Description: "Header Minimize button clicked."
94
+ });
91
95
  dispatch({
92
96
  type: _LiveChatWidgetActionType.LiveChatWidgetActionType.SET_MINIMIZED,
93
97
  payload: true
@@ -4,8 +4,8 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.prepareEndChat = exports.endVoiceVideoCallIfOngoing = exports.endChatStateCleanUp = exports.endChat = exports.closeChatStateCleanUp = exports.chatSDKStateCleanUp = exports.callingStateCleanUp = void 0;
7
- var _Constants = require("../../../common/Constants");
8
7
  var _TelemetryConstants = require("../../../common/telemetry/TelemetryConstants");
8
+ var _Constants = require("../../../common/Constants");
9
9
  var _utils = require("../../../common/utils");
10
10
  var _renderSurveyHelpers = require("./renderSurveyHelpers");
11
11
  var _omnichannelChatComponents = require("@microsoft/omnichannel-chat-components");
@@ -60,6 +60,13 @@ const prepareEndChat = async (props, chatSDK, state, dispatch, setAdapter, setWe
60
60
  const postchatContext = (await (0, _renderSurveyHelpers.getPostChatContext)(chatSDK, state, dispatch)) ?? (state === null || state === void 0 ? void 0 : (_state$domainStates = state.domainStates) === null || _state$domainStates === void 0 ? void 0 : _state$domainStates.postChatContext);
61
61
  if (postchatContext === undefined) {
62
62
  var _state$appStates2;
63
+ _omnichannelChatComponents.BroadcastService.postMessage({
64
+ eventName: _TelemetryConstants.BroadcastEvent.OnWidgetError,
65
+ payload: {
66
+ errorMessage: "Widget did not display post chat survey as getPostChatContext returned undefined."
67
+ }
68
+ });
69
+
63
70
  // For Customer intiated conversations, just close chat widget
64
71
  if ((state === null || state === void 0 ? void 0 : (_state$appStates2 = state.appStates) === null || _state$appStates2 === void 0 ? void 0 : _state$appStates2.conversationEndedBy) === _Constants.ConversationEndEntity.Customer) {
65
72
  _TelemetryHelper.TelemetryHelper.logSDKEvent(_TelemetryConstants.LogLevel.INFO, {
@@ -133,21 +140,25 @@ const prepareEndChat = async (props, chatSDK, state, dispatch, setAdapter, setWe
133
140
  exports.prepareEndChat = prepareEndChat;
134
141
  const endChat = async (props, chatSDK, state, dispatch, setAdapter, setWebChatStyles, adapter, skipEndChatSDK, skipCloseChat, postMessageToOtherTab) => {
135
142
  if (!skipEndChatSDK && chatSDK.conversation) {
143
+ var _inMemoryState$appSta;
144
+ const inMemoryState = (0, _createReducer.executeReducer)(state, {
145
+ type: _LiveChatWidgetActionType.LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
146
+ payload: null
147
+ });
148
+ const endChatOptionalParameters = {
149
+ isSessionEnded: inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta = inMemoryState.appStates) === null || _inMemoryState$appSta === void 0 ? void 0 : _inMemoryState$appSta.chatDisconnectEventReceived
150
+ };
136
151
  try {
137
152
  _TelemetryHelper.TelemetryHelper.logSDKEvent(_TelemetryConstants.LogLevel.INFO, {
138
153
  Event: _TelemetryConstants.TelemetryEvent.EndChatSDKCall
139
154
  });
140
155
  //Get auth token again if chat continued for longer time, otherwise gets 401 error
141
156
  await (0, _authHelper.handleAuthentication)(chatSDK, props.chatConfig, props.getAuthToken);
142
- await (chatSDK === null || chatSDK === void 0 ? void 0 : chatSDK.endChat());
157
+ await (chatSDK === null || chatSDK === void 0 ? void 0 : chatSDK.endChat(endChatOptionalParameters));
143
158
  } catch (ex) {
144
- var _inMemoryState$appSta;
145
- const inMemoryState = (0, _createReducer.executeReducer)(state, {
146
- type: _LiveChatWidgetActionType.LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
147
- payload: null
148
- });
159
+ var _inMemoryState$appSta2;
149
160
  // if the chat was disconnected or ended by the agent, we don't want to log the error
150
- if (!(inMemoryState !== null && inMemoryState !== void 0 && (_inMemoryState$appSta = inMemoryState.appStates) !== null && _inMemoryState$appSta !== void 0 && _inMemoryState$appSta.chatDisconnectEventReceived)) {
161
+ if (!(inMemoryState !== null && inMemoryState !== void 0 && (_inMemoryState$appSta2 = inMemoryState.appStates) !== null && _inMemoryState$appSta2 !== void 0 && _inMemoryState$appSta2.chatDisconnectEventReceived)) {
151
162
  _TelemetryHelper.TelemetryHelper.logSDKEvent(_TelemetryConstants.LogLevel.ERROR, {
152
163
  Event: _TelemetryConstants.TelemetryEvent.EndChatSDKCallFailed,
153
164
  ExceptionDetails: {
@@ -164,7 +175,7 @@ const endChat = async (props, chatSDK, state, dispatch, setAdapter, setWebChatSt
164
175
  }
165
176
  postMessageToOtherTab = false;
166
177
  } finally {
167
- await endChatStateCleanUp(dispatch);
178
+ endChatStateCleanUp(dispatch);
168
179
  }
169
180
  }
170
181
  if (!skipCloseChat) {
@@ -7,6 +7,7 @@ exports.initWebChatComposer = void 0;
7
7
  var _Constants = require("../../../common/Constants");
8
8
  var _TelemetryConstants = require("../../../common/telemetry/TelemetryConstants");
9
9
  var _utils = require("../../../common/utils");
10
+ var _dompurify = _interopRequireDefault(require("dompurify"));
10
11
  var _HyperlinkTextOverrideRenderer = _interopRequireDefault(require("../../webchatcontainerstateful/webchatcontroller/markdownrenderers/HyperlinkTextOverrideRenderer"));
11
12
  var _LiveChatWidgetActionType = require("../../../contexts/common/LiveChatWidgetActionType");
12
13
  var _TelemetryHelper = require("../../../common/telemetry/TelemetryHelper");
@@ -22,8 +23,10 @@ var _conversationEndMiddleware = _interopRequireDefault(require("../../webchatco
22
23
  var _dataMaskingMiddleware = _interopRequireDefault(require("../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/dataMaskingMiddleware"));
23
24
  var _createMarkdown = require("./createMarkdown");
24
25
  var _maxMessageSizeValidator = _interopRequireDefault(require("../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/maxMessageSizeValidator"));
26
+ var _messageSequenceIdOverrideMiddleware = _interopRequireDefault(require("../../webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/messageSequenceIdOverrideMiddleware"));
25
27
  var _messageTimestampMiddleware = _interopRequireDefault(require("../../webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/messageTimestampMiddleware"));
26
28
  var _botframeworkWebchat = require("botframework-webchat");
29
+ var _toastMiddleware = _interopRequireDefault(require("../../webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/toastMiddleware"));
27
30
  var _WebChatLogger = require("../../webchatcontainerstateful/webchatcontroller/webchattelemetry/WebChatLogger");
28
31
  var _defaultAttachmentProps = require("../../webchatcontainerstateful/common/defaultProps/defaultAttachmentProps");
29
32
  var _defaultMiddlewareLocalizedTexts = require("../../webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts");
@@ -34,9 +37,6 @@ var _htmlPlayerMiddleware = _interopRequireDefault(require("../../webchatcontain
34
37
  var _htmlTextMiddleware = _interopRequireDefault(require("../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/htmlTextMiddleware"));
35
38
  var _preProcessingMiddleware = _interopRequireDefault(require("../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/preProcessingMiddleware"));
36
39
  var _sanitizationMiddleware = _interopRequireDefault(require("../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/sanitizationMiddleware"));
37
- var _dompurify = _interopRequireDefault(require("dompurify"));
38
- var _messageSequenceIdOverrideMiddleware = _interopRequireDefault(require("../../webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/messageSequenceIdOverrideMiddleware"));
39
- var _toastMiddleware = _interopRequireDefault(require("../../webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/toastMiddleware"));
40
40
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
41
41
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
42
42
  const initWebChatComposer = (props, state, dispatch, chatSDK, endChat) => {
@@ -106,7 +106,11 @@ const initWebChatComposer = (props, state, dispatch, chatSDK, endChat) => {
106
106
  markdownRenderers.forEach(renderer => {
107
107
  text = renderer.render(text);
108
108
  });
109
- text = _dompurify.default.sanitize(text);
109
+ const config = {
110
+ FORBID_TAGS: ["form", "button", "script", "div"],
111
+ FORBID_ATTR: ["action"]
112
+ };
113
+ text = _dompurify.default.sanitize(text, config);
110
114
  return text;
111
115
  };
112
116
  function postDomPurifyActivities() {
@@ -206,6 +206,12 @@ const initStartChat = async (chatSDK, dispatch, setAdapter, state, props, params
206
206
  exception: `Failed to setup startChat: ${error}`
207
207
  }
208
208
  });
209
+ _omnichannelChatComponents.BroadcastService.postMessage({
210
+ eventName: _TelemetryConstants.BroadcastEvent.OnWidgetError,
211
+ payload: {
212
+ errorMessage: error
213
+ }
214
+ });
209
215
  isStartChatSuccessful = false;
210
216
  throw error;
211
217
  }
@@ -155,6 +155,12 @@ const LiveChatWidgetStateful = props => {
155
155
  }
156
156
  return;
157
157
  }
158
+ _omnichannelChatComponents.BroadcastService.postMessage({
159
+ eventName: _TelemetryConstants.BroadcastEvent.OnWidgetError,
160
+ payload: {
161
+ errorMessage: "Chat found in cache but invalid as the conversation status is inactive."
162
+ }
163
+ });
158
164
  }
159
165
  if (isChatValid === false) {
160
166
  if (localState) {
@@ -274,6 +280,12 @@ const LiveChatWidgetStateful = props => {
274
280
  type: _LiveChatWidgetActionType.LiveChatWidgetActionType.SET_CONVERSATION_STATE,
275
281
  payload: _ConversationState.ConversationState.OutOfOffice
276
282
  });
283
+ _omnichannelChatComponents.BroadcastService.postMessage({
284
+ eventName: _TelemetryConstants.BroadcastEvent.OnWidgetError,
285
+ payload: {
286
+ errorMessage: "Out-of-office hours status is shown."
287
+ }
288
+ });
277
289
  return;
278
290
  }
279
291
  _omnichannelChatComponents.BroadcastService.postMessage({
@@ -365,9 +377,16 @@ const LiveChatWidgetStateful = props => {
365
377
  type: _LiveChatWidgetActionType.LiveChatWidgetActionType.SET_CHAT_DISCONNECT_EVENT_RECEIVED,
366
378
  payload: true
367
379
  });
380
+ const desc = "Chat disconnected due to timeout, user went offline or blocked the device (including closing laptop)";
368
381
  _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.INFO, {
369
382
  Event: _TelemetryConstants.TelemetryEvent.ChatDisconnectThreadEventReceived,
370
- Description: "Chat disconnected due to timeout, user went offline or blocked the device (including closing laptop)"
383
+ Description: desc
384
+ });
385
+ _omnichannelChatComponents.BroadcastService.postMessage({
386
+ eventName: _TelemetryConstants.BroadcastEvent.OnWidgetError,
387
+ payload: {
388
+ errorMessage: desc
389
+ }
371
390
  });
372
391
  }
373
392
  });
@@ -87,7 +87,8 @@ const createActivityMiddleware = (renderMarkdown, systemMessageStyleProps, userM
87
87
  }
88
88
  if (isTagIncluded(card, _Constants.Constants.systemMessageTag)) {
89
89
  return handleSystemMessage(next, args, card, renderMarkdown, systemMessageStyleProps);
90
- } else if (card.activity.text && card.activity.type === _DirectLineActivityType.DirectLineActivityType.Message) {
90
+ }
91
+ if (card.activity.text && card.activity.type === _DirectLineActivityType.DirectLineActivityType.Message) {
91
92
  if (!card.activity.channelData.isHtmlEncoded && card.activity.channelId === _Constants.Constants.webchatChannelId) {
92
93
  card.activity.text = (0, _utils.escapeHtml)(card.activity.text);
93
94
  card.activity.channelData.isHtmlEncoded = true;
@@ -9,6 +9,8 @@ var _NotificationLevel = require("../enums/NotificationLevel");
9
9
  var _WebChatActionType = require("../enums/WebChatActionType");
10
10
  var _WebChatStoreLoader = require("../WebChatStoreLoader");
11
11
  var _utils = require("../../../../common/utils");
12
+ var _omnichannelChatComponents = require("@microsoft/omnichannel-chat-components");
13
+ var _TelemetryConstants = require("../../../../common/telemetry/TelemetryConstants");
12
14
  class NotificationHandler {
13
15
  static notify(id, level, message) {
14
16
  if (_WebChatStoreLoader.WebChatStoreLoader.store) {
@@ -34,6 +36,12 @@ class NotificationHandler {
34
36
  }
35
37
  }
36
38
  static notifyError(id, message) {
39
+ _omnichannelChatComponents.BroadcastService.postMessage({
40
+ eventName: _TelemetryConstants.BroadcastEvent.OnWidgetError,
41
+ payload: {
42
+ errorMessage: message
43
+ }
44
+ });
37
45
  this.notify(id, _NotificationLevel.NotificationLevel.Error, message);
38
46
  }
39
47
  static notifyWarning(id, message) {
@@ -60,6 +60,7 @@ export let BroadcastEvent;
60
60
  BroadcastEvent["UpdateConversationDataForTelemetry"] = "UpdateConversationDataForTelemetry";
61
61
  BroadcastEvent["ContactIdNotFound"] = "ContactIdNotFound";
62
62
  BroadcastEvent["SyncMinimize"] = "SyncMinimize";
63
+ BroadcastEvent["OnWidgetError"] = "OnWidgetError";
63
64
  })(BroadcastEvent || (BroadcastEvent = {}));
64
65
  export let TelemetryEvent;
65
66
  (function (TelemetryEvent) {
@@ -11,10 +11,11 @@ import { TelemetryHelper } from "../../common/telemetry/TelemetryHelper";
11
11
  import { downloadTranscript } from "./downloadtranscriptstateful/DownloadTranscriptStateful";
12
12
  import useChatContextStore from "../../hooks/useChatContextStore";
13
13
  import useChatSDKStore from "../../hooks/useChatSDKStore";
14
+ import { ConversationState } from "../../contexts/common/ConversationState";
14
15
 
15
16
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
16
17
  export const FooterStateful = props => {
17
- var _footerProps$controlP3, _footerProps$controlP6;
18
+ var _footerProps$controlP3;
18
19
  const [state, dispatch] = useChatContextStore();
19
20
  // hideFooterDisplay - the purpose of this is to keep the footer always "active",
20
21
  // but hide it visually in certain states (e.g., loading state) and show in some other states (e.g. active state).
@@ -82,21 +83,23 @@ export const FooterStateful = props => {
82
83
  }
83
84
  };
84
85
  useEffect(() => {
85
- if (state.appStates.isAudioMuted === null) {
86
- var _footerProps$controlP4, _footerProps$controlP5;
87
- dispatch({
88
- type: LiveChatWidgetActionType.SET_AUDIO_NOTIFICATION,
89
- payload: (footerProps === null || footerProps === void 0 ? void 0 : (_footerProps$controlP4 = footerProps.controlProps) === null || _footerProps$controlP4 === void 0 ? void 0 : (_footerProps$controlP5 = _footerProps$controlP4.audioNotificationButtonProps) === null || _footerProps$controlP5 === void 0 ? void 0 : _footerProps$controlP5.isAudioMuted) ?? false
90
- });
86
+ if (state.appStates.conversationState === ConversationState.Active) {
87
+ if (state.appStates.isAudioMuted === null) {
88
+ var _footerProps$controlP4, _footerProps$controlP5, _footerProps$controlP6;
89
+ dispatch({
90
+ type: LiveChatWidgetActionType.SET_AUDIO_NOTIFICATION,
91
+ payload: footerProps !== null && footerProps !== void 0 && (_footerProps$controlP4 = footerProps.controlProps) !== null && _footerProps$controlP4 !== void 0 && _footerProps$controlP4.hideAudioNotificationButton ? true : (footerProps === null || footerProps === void 0 ? void 0 : (_footerProps$controlP5 = footerProps.controlProps) === null || _footerProps$controlP5 === void 0 ? void 0 : (_footerProps$controlP6 = _footerProps$controlP5.audioNotificationButtonProps) === null || _footerProps$controlP6 === void 0 ? void 0 : _footerProps$controlP6.isAudioMuted) ?? false
92
+ });
93
+ }
91
94
  }
92
- }, []);
95
+ }, [state.appStates.conversationState]);
93
96
  return /*#__PURE__*/React.createElement(React.Fragment, null, !hideFooterDisplay && /*#__PURE__*/React.createElement(Footer, {
94
97
  componentOverrides: footerProps === null || footerProps === void 0 ? void 0 : footerProps.componentOverrides,
95
98
  controlProps: controlProps,
96
99
  styleProps: footerProps === null || footerProps === void 0 ? void 0 : footerProps.styleProps
97
100
  }), /*#__PURE__*/React.createElement(AudioNotificationStateful, {
98
101
  audioSrc: (audioNotificationProps === null || audioNotificationProps === void 0 ? void 0 : audioNotificationProps.audioSrc) ?? NewMessageNotificationSoundBase64,
99
- isAudioMuted: state.appStates.isAudioMuted === null ? (footerProps === null || footerProps === void 0 ? void 0 : (_footerProps$controlP6 = footerProps.controlProps) === null || _footerProps$controlP6 === void 0 ? void 0 : _footerProps$controlP6.hideAudioNotificationButton) ?? false : state.appStates.isAudioMuted ?? false
102
+ isAudioMuted: state.appStates.isAudioMuted ?? false
100
103
  }));
101
104
  };
102
105
  export default FooterStateful;
@@ -79,6 +79,10 @@ export const HeaderStateful = props => {
79
79
  text: "We're Offline"
80
80
  },
81
81
  onMinimizeClick: () => {
82
+ TelemetryHelper.logActionEvent(LogLevel.INFO, {
83
+ Event: TelemetryEvent.HeaderMinimizeButtonClicked,
84
+ Description: "Header Minimize button clicked."
85
+ });
82
86
  dispatch({
83
87
  type: LiveChatWidgetActionType.SET_MINIMIZED,
84
88
  payload: true
@@ -1,5 +1,5 @@
1
+ import { BroadcastEvent, LogLevel, TelemetryEvent } from "../../../common/telemetry/TelemetryConstants";
1
2
  import { ConfirmationState, Constants, ConversationEndEntity, ParticipantType, PrepareEndChatDescriptionConstants } from "../../../common/Constants";
2
- import { LogLevel, TelemetryEvent } from "../../../common/telemetry/TelemetryConstants";
3
3
  import { getConversationDetailsCall, getWidgetEndChatEventName } from "../../../common/utils";
4
4
  import { getPostChatContext, initiatePostChat } from "./renderSurveyHelpers";
5
5
  import { BroadcastService } from "@microsoft/omnichannel-chat-components";
@@ -55,6 +55,13 @@ const prepareEndChat = async (props, chatSDK, state, dispatch, setAdapter, setWe
55
55
  const postchatContext = (await getPostChatContext(chatSDK, state, dispatch)) ?? (state === null || state === void 0 ? void 0 : (_state$domainStates = state.domainStates) === null || _state$domainStates === void 0 ? void 0 : _state$domainStates.postChatContext);
56
56
  if (postchatContext === undefined) {
57
57
  var _state$appStates2;
58
+ BroadcastService.postMessage({
59
+ eventName: BroadcastEvent.OnWidgetError,
60
+ payload: {
61
+ errorMessage: "Widget did not display post chat survey as getPostChatContext returned undefined."
62
+ }
63
+ });
64
+
58
65
  // For Customer intiated conversations, just close chat widget
59
66
  if ((state === null || state === void 0 ? void 0 : (_state$appStates2 = state.appStates) === null || _state$appStates2 === void 0 ? void 0 : _state$appStates2.conversationEndedBy) === ConversationEndEntity.Customer) {
60
67
  TelemetryHelper.logSDKEvent(LogLevel.INFO, {
@@ -127,21 +134,25 @@ const prepareEndChat = async (props, chatSDK, state, dispatch, setAdapter, setWe
127
134
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
128
135
  const endChat = async (props, chatSDK, state, dispatch, setAdapter, setWebChatStyles, adapter, skipEndChatSDK, skipCloseChat, postMessageToOtherTab) => {
129
136
  if (!skipEndChatSDK && chatSDK.conversation) {
137
+ var _inMemoryState$appSta;
138
+ const inMemoryState = executeReducer(state, {
139
+ type: LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
140
+ payload: null
141
+ });
142
+ const endChatOptionalParameters = {
143
+ isSessionEnded: inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta = inMemoryState.appStates) === null || _inMemoryState$appSta === void 0 ? void 0 : _inMemoryState$appSta.chatDisconnectEventReceived
144
+ };
130
145
  try {
131
146
  TelemetryHelper.logSDKEvent(LogLevel.INFO, {
132
147
  Event: TelemetryEvent.EndChatSDKCall
133
148
  });
134
149
  //Get auth token again if chat continued for longer time, otherwise gets 401 error
135
150
  await handleAuthentication(chatSDK, props.chatConfig, props.getAuthToken);
136
- await (chatSDK === null || chatSDK === void 0 ? void 0 : chatSDK.endChat());
151
+ await (chatSDK === null || chatSDK === void 0 ? void 0 : chatSDK.endChat(endChatOptionalParameters));
137
152
  } catch (ex) {
138
- var _inMemoryState$appSta;
139
- const inMemoryState = executeReducer(state, {
140
- type: LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
141
- payload: null
142
- });
153
+ var _inMemoryState$appSta2;
143
154
  // if the chat was disconnected or ended by the agent, we don't want to log the error
144
- if (!(inMemoryState !== null && inMemoryState !== void 0 && (_inMemoryState$appSta = inMemoryState.appStates) !== null && _inMemoryState$appSta !== void 0 && _inMemoryState$appSta.chatDisconnectEventReceived)) {
155
+ if (!(inMemoryState !== null && inMemoryState !== void 0 && (_inMemoryState$appSta2 = inMemoryState.appStates) !== null && _inMemoryState$appSta2 !== void 0 && _inMemoryState$appSta2.chatDisconnectEventReceived)) {
145
156
  TelemetryHelper.logSDKEvent(LogLevel.ERROR, {
146
157
  Event: TelemetryEvent.EndChatSDKCallFailed,
147
158
  ExceptionDetails: {
@@ -158,7 +169,7 @@ const endChat = async (props, chatSDK, state, dispatch, setAdapter, setWebChatSt
158
169
  }
159
170
  postMessageToOtherTab = false;
160
171
  } finally {
161
- await endChatStateCleanUp(dispatch);
172
+ endChatStateCleanUp(dispatch);
162
173
  }
163
174
  }
164
175
  if (!skipCloseChat) {
@@ -1,6 +1,7 @@
1
1
  import { ConversationEndEntity, ParticipantType } from "../../../common/Constants";
2
2
  import { LogLevel, TelemetryEvent } from "../../../common/telemetry/TelemetryConstants";
3
3
  import { changeLanguageCodeFormatForWebChat, getConversationDetailsCall } from "../../../common/utils";
4
+ import DOMPurify from "dompurify";
4
5
  import HyperlinkTextOverrideRenderer from "../../webchatcontainerstateful/webchatcontroller/markdownrenderers/HyperlinkTextOverrideRenderer";
5
6
  import { LiveChatWidgetActionType } from "../../../contexts/common/LiveChatWidgetActionType";
6
7
  import { TelemetryHelper } from "../../../common/telemetry/TelemetryHelper";
@@ -16,8 +17,10 @@ import createConversationEndMiddleware from "../../webchatcontainerstateful/webc
16
17
  import createDataMaskingMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/dataMaskingMiddleware";
17
18
  import { createMarkdown } from "./createMarkdown";
18
19
  import createMaxMessageSizeValidator from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/maxMessageSizeValidator";
20
+ import createMessageSequenceIdOverrideMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/messageSequenceIdOverrideMiddleware";
19
21
  import createMessageTimeStampMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/messageTimestampMiddleware";
20
22
  import { createStore } from "botframework-webchat";
23
+ import createToastMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/toastMiddleware";
21
24
  import { createWebChatTelemetry } from "../../webchatcontainerstateful/webchatcontroller/webchattelemetry/WebChatLogger";
22
25
  import { defaultAttachmentProps } from "../../webchatcontainerstateful/common/defaultProps/defaultAttachmentProps";
23
26
  import { defaultMiddlewareLocalizedTexts } from "../../webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts";
@@ -28,9 +31,6 @@ import htmlPlayerMiddleware from "../../webchatcontainerstateful/webchatcontroll
28
31
  import htmlTextMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/htmlTextMiddleware";
29
32
  import preProcessingMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/preProcessingMiddleware";
30
33
  import sanitizationMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/sanitizationMiddleware";
31
- import DOMPurify from "dompurify";
32
- import createMessageSequenceIdOverrideMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/messageSequenceIdOverrideMiddleware";
33
- import createToastMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/toastMiddleware";
34
34
 
35
35
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
36
  export const initWebChatComposer = (props, state, dispatch, chatSDK, endChat) => {
@@ -100,7 +100,11 @@ export const initWebChatComposer = (props, state, dispatch, chatSDK, endChat) =>
100
100
  markdownRenderers.forEach(renderer => {
101
101
  text = renderer.render(text);
102
102
  });
103
- text = DOMPurify.sanitize(text);
103
+ const config = {
104
+ FORBID_TAGS: ["form", "button", "script", "div"],
105
+ FORBID_ATTR: ["action"]
106
+ };
107
+ text = DOMPurify.sanitize(text, config);
104
108
  return text;
105
109
  };
106
110
  function postDomPurifyActivities() {
@@ -199,6 +199,12 @@ const initStartChat = async (chatSDK, dispatch, setAdapter, state, props, params
199
199
  exception: `Failed to setup startChat: ${error}`
200
200
  }
201
201
  });
202
+ BroadcastService.postMessage({
203
+ eventName: BroadcastEvent.OnWidgetError,
204
+ payload: {
205
+ errorMessage: error
206
+ }
207
+ });
202
208
  isStartChatSuccessful = false;
203
209
  throw error;
204
210
  }
@@ -147,6 +147,12 @@ export const LiveChatWidgetStateful = props => {
147
147
  }
148
148
  return;
149
149
  }
150
+ BroadcastService.postMessage({
151
+ eventName: BroadcastEvent.OnWidgetError,
152
+ payload: {
153
+ errorMessage: "Chat found in cache but invalid as the conversation status is inactive."
154
+ }
155
+ });
150
156
  }
151
157
  if (isChatValid === false) {
152
158
  if (localState) {
@@ -266,6 +272,12 @@ export const LiveChatWidgetStateful = props => {
266
272
  type: LiveChatWidgetActionType.SET_CONVERSATION_STATE,
267
273
  payload: ConversationState.OutOfOffice
268
274
  });
275
+ BroadcastService.postMessage({
276
+ eventName: BroadcastEvent.OnWidgetError,
277
+ payload: {
278
+ errorMessage: "Out-of-office hours status is shown."
279
+ }
280
+ });
269
281
  return;
270
282
  }
271
283
  BroadcastService.postMessage({
@@ -357,9 +369,16 @@ export const LiveChatWidgetStateful = props => {
357
369
  type: LiveChatWidgetActionType.SET_CHAT_DISCONNECT_EVENT_RECEIVED,
358
370
  payload: true
359
371
  });
372
+ const desc = "Chat disconnected due to timeout, user went offline or blocked the device (including closing laptop)";
360
373
  TelemetryHelper.logActionEvent(LogLevel.INFO, {
361
374
  Event: TelemetryEvent.ChatDisconnectThreadEventReceived,
362
- Description: "Chat disconnected due to timeout, user went offline or blocked the device (including closing laptop)"
375
+ Description: desc
376
+ });
377
+ BroadcastService.postMessage({
378
+ eventName: BroadcastEvent.OnWidgetError,
379
+ payload: {
380
+ errorMessage: desc
381
+ }
363
382
  });
364
383
  }
365
384
  });
@@ -80,7 +80,8 @@ export const createActivityMiddleware = (renderMarkdown, systemMessageStyleProps
80
80
  }
81
81
  if (isTagIncluded(card, Constants.systemMessageTag)) {
82
82
  return handleSystemMessage(next, args, card, renderMarkdown, systemMessageStyleProps);
83
- } else if (card.activity.text && card.activity.type === DirectLineActivityType.Message) {
83
+ }
84
+ if (card.activity.text && card.activity.type === DirectLineActivityType.Message) {
84
85
  if (!card.activity.channelData.isHtmlEncoded && card.activity.channelId === Constants.webchatChannelId) {
85
86
  card.activity.text = escapeHtml(card.activity.text);
86
87
  card.activity.channelData.isHtmlEncoded = true;
@@ -3,6 +3,8 @@ import { NotificationLevel } from "../enums/NotificationLevel";
3
3
  import { WebChatActionType } from "../enums/WebChatActionType";
4
4
  import { WebChatStoreLoader } from "../WebChatStoreLoader";
5
5
  import { setFocusOnSendBox } from "../../../../common/utils";
6
+ import { BroadcastService } from "@microsoft/omnichannel-chat-components";
7
+ import { BroadcastEvent } from "../../../../common/telemetry/TelemetryConstants";
6
8
  export class NotificationHandler {
7
9
  static notify(id, level, message) {
8
10
  if (WebChatStoreLoader.store) {
@@ -28,6 +30,12 @@ export class NotificationHandler {
28
30
  }
29
31
  }
30
32
  static notifyError(id, message) {
33
+ BroadcastService.postMessage({
34
+ eventName: BroadcastEvent.OnWidgetError,
35
+ payload: {
36
+ errorMessage: message
37
+ }
38
+ });
31
39
  this.notify(id, NotificationLevel.Error, message);
32
40
  }
33
41
  static notifyWarning(id, message) {
@@ -53,7 +53,8 @@ export declare enum BroadcastEvent {
53
53
  UpdateSessionDataForTelemetry = "UpdateSessionDataForTelemetry",
54
54
  UpdateConversationDataForTelemetry = "UpdateConversationDataForTelemetry",
55
55
  ContactIdNotFound = "ContactIdNotFound",
56
- SyncMinimize = "SyncMinimize"
56
+ SyncMinimize = "SyncMinimize",
57
+ OnWidgetError = "OnWidgetError"
57
58
  }
58
59
  export declare enum TelemetryEvent {
59
60
  CallAdded = "CallAdded",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microsoft/omnichannel-chat-widget",
3
- "version": "1.7.4-main.9d63968",
3
+ "version": "1.7.4-main.9edefc7",
4
4
  "description": "Microsoft Omnichannel Chat Widget",
5
5
  "main": "lib/cjs/index.js",
6
6
  "types": "lib/types/index.d.ts",
@@ -74,8 +74,10 @@
74
74
  "webpack-cli": "^4.9.2"
75
75
  },
76
76
  "dependencies": {
77
+ "@azure/core-tracing": "^1.2.0",
77
78
  "@microsoft/omnichannel-chat-components": "1.1.5",
78
- "@microsoft/omnichannel-chat-sdk": "^1.10.1",
79
+ "@microsoft/omnichannel-chat-sdk": "^1.10.2",
80
+ "@opentelemetry/api": "^1.9.0",
79
81
  "abort-controller-es5": "^2.0.1",
80
82
  "dompurify": "^2.5.4",
81
83
  "markdown-it": "^12.3.2",