@microsoft/omnichannel-chat-widget 1.6.3-main.e6221d5 → 1.6.4-main.0fc902c

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 (39) hide show
  1. package/lib/cjs/common/telemetry/TelemetryConstants.js +1 -0
  2. package/lib/cjs/common/utils.js +9 -4
  3. package/lib/cjs/components/emailtranscriptpanestateful/EmailTranscriptPaneStateful.js +29 -24
  4. package/lib/cjs/components/footerstateful/downloadtranscriptstateful/DownloadTranscriptStateful.js +12 -6
  5. package/lib/cjs/components/livechatwidget/common/authHelper.js +4 -1
  6. package/lib/cjs/components/livechatwidget/common/endChat.js +9 -30
  7. package/lib/cjs/components/livechatwidget/common/initWebChatComposer.js +1 -1
  8. package/lib/cjs/components/livechatwidget/common/reconnectChatHelper.js +13 -3
  9. package/lib/cjs/components/livechatwidget/common/startChat.js +35 -19
  10. package/lib/cjs/components/livechatwidget/common/startChatErrorHandler.js +5 -0
  11. package/lib/cjs/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +27 -20
  12. package/lib/cjs/components/webchatcontainerstateful/WebChatContainerStateful.js +8 -4
  13. package/lib/cjs/components/webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts.js +1 -1
  14. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activityMiddleware.js +5 -6
  15. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/defaultStyles/defaultAttachmentDownloadIconStyles.js +1 -1
  16. package/lib/cjs/contexts/common/LiveChatWidgetContextInitialState.js +10 -0
  17. package/lib/cjs/contexts/createReducer.js +1 -1
  18. package/lib/esm/common/telemetry/TelemetryConstants.js +1 -0
  19. package/lib/esm/common/utils.js +9 -4
  20. package/lib/esm/components/emailtranscriptpanestateful/EmailTranscriptPaneStateful.js +30 -25
  21. package/lib/esm/components/footerstateful/downloadtranscriptstateful/DownloadTranscriptStateful.js +12 -6
  22. package/lib/esm/components/livechatwidget/common/authHelper.js +4 -1
  23. package/lib/esm/components/livechatwidget/common/endChat.js +10 -31
  24. package/lib/esm/components/livechatwidget/common/initWebChatComposer.js +1 -1
  25. package/lib/esm/components/livechatwidget/common/reconnectChatHelper.js +15 -4
  26. package/lib/esm/components/livechatwidget/common/startChat.js +35 -19
  27. package/lib/esm/components/livechatwidget/common/startChatErrorHandler.js +5 -0
  28. package/lib/esm/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +27 -20
  29. package/lib/esm/components/webchatcontainerstateful/WebChatContainerStateful.js +8 -4
  30. package/lib/esm/components/webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts.js +1 -1
  31. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activityMiddleware.js +5 -6
  32. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/defaultStyles/defaultAttachmentDownloadIconStyles.js +1 -1
  33. package/lib/esm/contexts/common/LiveChatWidgetContextInitialState.js +10 -0
  34. package/lib/esm/contexts/createReducer.js +1 -1
  35. package/lib/types/common/telemetry/TelemetryConstants.d.ts +2 -1
  36. package/lib/types/common/utils.d.ts +1 -1
  37. package/lib/types/components/livechatwidget/common/reconnectChatHelper.d.ts +1 -1
  38. package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activityMiddleware.d.ts +1 -1
  39. package/package.json +6 -4
@@ -24,9 +24,8 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
24
24
  ******/
25
25
 
26
26
  const loggedSystemMessages = new Array();
27
-
28
27
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
29
- const handleSystemMessage = (next, args, card, systemMessageStyleProps) => {
28
+ const handleSystemMessage = (next, args, card, renderMarkdown, systemMessageStyleProps) => {
30
29
  var _card$activity, _card$activity$channe, _card$activity$channe2, _card$activity2, _card$activity2$chann, _card$activity3, _card$activity3$chann, _card$activity3$chann2, _card$activity4, _card$activity4$chann, _card$activity5, _card$activity5$chann, _card$nextVisibleActi, _card$nextVisibleActi2, _card$activity6, _card$activity6$chann, _card$activity7, _card$nextVisibleActi3, _card$activity8;
31
30
  const systemMessageStyles = {
32
31
  ..._defaultSystemMessageStyles.defaultSystemMessageStyles,
@@ -49,14 +48,14 @@ const handleSystemMessage = (next, args, card, systemMessageStyleProps) => {
49
48
  if ((_card$activity5 = card.activity) !== null && _card$activity5 !== void 0 && (_card$activity5$chann = _card$activity5.channelData) !== null && _card$activity5$chann !== void 0 && _card$activity5$chann.clientmessageid && ((_card$nextVisibleActi = card.nextVisibleActivity) === null || _card$nextVisibleActi === void 0 ? void 0 : (_card$nextVisibleActi2 = _card$nextVisibleActi.channelData) === null || _card$nextVisibleActi2 === void 0 ? void 0 : _card$nextVisibleActi2.clientmessageid) === ((_card$activity6 = card.activity) === null || _card$activity6 === void 0 ? void 0 : (_card$activity6$chann = _card$activity6.channelData) === null || _card$activity6$chann === void 0 ? void 0 : _card$activity6$chann.clientmessageid) || (_card$activity7 = card.activity) !== null && _card$activity7 !== void 0 && _card$activity7.messageid && ((_card$nextVisibleActi3 = card.nextVisibleActivity) === null || _card$nextVisibleActi3 === void 0 ? void 0 : _card$nextVisibleActi3.messageid) === ((_card$activity8 = card.activity) === null || _card$activity8 === void 0 ? void 0 : _card$activity8.messageid)) {
50
49
  return () => false;
51
50
  }
52
-
51
+ card.activity.text = renderMarkdown(card.activity.text);
53
52
  // eslint-disable-next-line react/display-name
54
53
  return () => /*#__PURE__*/_react.default.createElement("div", {
55
54
  key: card.activity.id,
56
55
  style: systemMessageStyles,
57
56
  "aria-hidden": "false",
58
57
  dangerouslySetInnerHTML: {
59
- __html: (0, _utils.escapeHtml)(card.activity.text)
58
+ __html: card.activity.text
60
59
  }
61
60
  });
62
61
  };
@@ -72,7 +71,7 @@ const isDataTagsPresent = card => {
72
71
  };
73
72
 
74
73
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
75
- const createActivityMiddleware = (systemMessageStyleProps, userMessageStyleProps) => () => next => function () {
74
+ const createActivityMiddleware = (renderMarkdown, systemMessageStyleProps, userMessageStyleProps) => () => next => function () {
76
75
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
77
76
  args[_key] = arguments[_key];
78
77
  }
@@ -86,7 +85,7 @@ const createActivityMiddleware = (systemMessageStyleProps, userMessageStyleProps
86
85
  return () => false;
87
86
  }
88
87
  if (isTagIncluded(card, _Constants.Constants.systemMessageTag)) {
89
- return handleSystemMessage(next, args, card, systemMessageStyleProps);
88
+ return handleSystemMessage(next, args, card, renderMarkdown, systemMessageStyleProps);
90
89
  } else if (card.activity.text && card.activity.type === _DirectLineActivityType.DirectLineActivityType.Message) {
91
90
  if (!card.activity.channelData.isHtmlEncoded && card.activity.channelId === _Constants.Constants.webchatChannelId) {
92
91
  card.activity.text = (0, _utils.escapeHtml)(card.activity.text);
@@ -9,6 +9,6 @@ const defaultAttachmentDownloadIconStyles = {
9
9
  width: "12px",
10
10
  marginLeft: "auto !important",
11
11
  padding: "2px !important",
12
- fill: "#000000 !important"
12
+ fill: "#000000"
13
13
  };
14
14
  exports.defaultAttachmentDownloadIconStyles = defaultAttachmentDownloadIconStyles;
@@ -18,6 +18,16 @@ const getLiveChatWidgetContextInitialState = props => {
18
18
  const initialState = (0, _defaultClientDataStoreProvider.defaultClientDataStoreProvider)(cacheTtlInMins, storageType).getData(widgetCacheId);
19
19
  if (!(0, _utils.isNullOrUndefined)(initialState)) {
20
20
  const initialStateFromCache = JSON.parse(initialState);
21
+
22
+ /*
23
+ * this step is needed to avoid the pre-chat pane to be injected in the DOM when the widget is reloaded, because wont be visible
24
+ * and it will be blocking all elements behind it
25
+ * as part of the flow, the pre-chat will be detected and then it will be displayed properly
26
+ * this case is only and only for pre-chat pane.
27
+ * **/
28
+ if (initialStateFromCache.appStates.conversationState === _ConversationState.ConversationState.Prechat) {
29
+ initialStateFromCache.appStates.conversationState = _ConversationState.ConversationState.Closed;
30
+ }
21
31
  return initialStateFromCache;
22
32
  }
23
33
  const LiveChatWidgetContextInitialState = {
@@ -89,7 +89,7 @@ const reducer = (state, action) => {
89
89
  inMemory = {
90
90
  ...inMemory,
91
91
  appStates: {
92
- ...state.appStates,
92
+ ...inMemory.appStates,
93
93
  isMinimized: action.payload
94
94
  }
95
95
  };
@@ -59,6 +59,7 @@ export let BroadcastEvent;
59
59
  BroadcastEvent["UpdateSessionDataForTelemetry"] = "UpdateSessionDataForTelemetry";
60
60
  BroadcastEvent["UpdateConversationDataForTelemetry"] = "UpdateConversationDataForTelemetry";
61
61
  BroadcastEvent["ContactIdNotFound"] = "ContactIdNotFound";
62
+ BroadcastEvent["SyncMinimize"] = "SyncMinimize";
62
63
  })(BroadcastEvent || (BroadcastEvent = {}));
63
64
  export let TelemetryEvent;
64
65
  (function (TelemetryEvent) {
@@ -351,15 +351,20 @@ export const debounceLeading = function (fn) {
351
351
  };
352
352
 
353
353
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
354
- export const getConversationDetailsCall = async chatSDK => {
355
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
356
- let conversationDetails = undefined;
354
+ export const getConversationDetailsCall = async function (chatSDK) {
355
+ let liveChatContext = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
356
+ let conversationDetails = undefined; // eslint-disable-line @typescript-eslint/no-explicit-any
357
+ const optionalParams = {}; // eslint-disable-line @typescript-eslint/no-explicit-any
358
+
359
+ if (liveChatContext !== null && liveChatContext !== void 0 && liveChatContext.requestId && liveChatContext !== null && liveChatContext !== void 0 && liveChatContext.chatToken) {
360
+ optionalParams.liveChatContext = liveChatContext;
361
+ }
357
362
  try {
358
363
  TelemetryHelper.logSDKEvent(LogLevel.INFO, {
359
364
  Event: TelemetryEvent.GetConversationDetailsCallStarted,
360
365
  Description: "Conversation details call started"
361
366
  });
362
- conversationDetails = await chatSDK.getConversationDetails();
367
+ conversationDetails = await chatSDK.getConversationDetails(optionalParams);
363
368
  } catch (error) {
364
369
  checkContactIdError(error);
365
370
  TelemetryHelper.logSDKEvent(LogLevel.ERROR, {
@@ -1,5 +1,5 @@
1
1
  import { LogLevel, TelemetryEvent } from "../../common/telemetry/TelemetryConstants";
2
- import React, { useEffect, useState } from "react";
2
+ import React, { useCallback, useEffect, useState } from "react";
3
3
  import { findAllFocusableElement, findParentFocusableElementsWithoutChildContainer, formatTemplateString, preventFocusToMoveOutOfElement, setFocusOnElement, setFocusOnSendBox, setTabIndices } from "../../common/utils";
4
4
  import { DimLayer } from "../dimlayer/DimLayer";
5
5
  import { InputValidationPane } from "@microsoft/omnichannel-chat-components";
@@ -36,33 +36,38 @@ export const EmailTranscriptPaneStateful = props => {
36
36
  });
37
37
  setTabIndices(elements, initialTabIndexMap, true);
38
38
  };
39
+ const onSend = useCallback(async email => {
40
+ var _state$domainStates;
41
+ const liveChatContext = state === null || state === void 0 ? void 0 : (_state$domainStates = state.domainStates) === null || _state$domainStates === void 0 ? void 0 : _state$domainStates.liveChatContext;
42
+ closeEmailTranscriptPane();
43
+ const chatTranscriptBody = {
44
+ emailAddress: email,
45
+ attachmentMessage: (props === null || props === void 0 ? void 0 : props.attachmentMessage) ?? "The following attachment was uploaded during the conversation:"
46
+ };
47
+ try {
48
+ await (chatSDK === null || chatSDK === void 0 ? void 0 : chatSDK.emailLiveChatTranscript(chatTranscriptBody, {
49
+ liveChatContext
50
+ }));
51
+ NotificationHandler.notifySuccess(NotificationScenarios.EmailAddressSaved, defaultMiddlewareLocalizedTexts === null || defaultMiddlewareLocalizedTexts === void 0 ? void 0 : defaultMiddlewareLocalizedTexts.MIDDLEWARE_BANNER_FILE_EMAIL_ADDRESS_RECORDED_SUCCESS);
52
+ TelemetryHelper.logActionEvent(LogLevel.INFO, {
53
+ Event: TelemetryEvent.EmailTranscriptSent,
54
+ Description: "Transcript sent to email successfully."
55
+ });
56
+ } catch (ex) {
57
+ TelemetryHelper.logActionEvent(LogLevel.ERROR, {
58
+ Event: TelemetryEvent.EmailTranscriptFailed,
59
+ ExceptionDetails: {
60
+ exception: ex
61
+ }
62
+ });
63
+ const message = formatTemplateString(defaultMiddlewareLocalizedTexts.MIDDLEWARE_BANNER_FILE_EMAIL_ADDRESS_RECORDED_ERROR, [email]);
64
+ NotificationHandler.notifyError(NotificationScenarios.EmailTranscriptError, (props === null || props === void 0 ? void 0 : props.bannerMessageOnError) ?? message);
65
+ }
66
+ }, [props.attachmentMessage, props.bannerMessageOnError, chatSDK, state.domainStates.liveChatContext]);
39
67
  const controlProps = {
40
68
  id: "oclcw-emailTranscriptDialogContainer",
41
69
  dir: state.domainStates.globalDir,
42
- onSend: async email => {
43
- closeEmailTranscriptPane();
44
- const chatTranscriptBody = {
45
- emailAddress: email,
46
- attachmentMessage: (props === null || props === void 0 ? void 0 : props.attachmentMessage) ?? "The following attachment was uploaded during the conversation:"
47
- };
48
- try {
49
- await (chatSDK === null || chatSDK === void 0 ? void 0 : chatSDK.emailLiveChatTranscript(chatTranscriptBody));
50
- NotificationHandler.notifySuccess(NotificationScenarios.EmailAddressSaved, defaultMiddlewareLocalizedTexts === null || defaultMiddlewareLocalizedTexts === void 0 ? void 0 : defaultMiddlewareLocalizedTexts.MIDDLEWARE_BANNER_FILE_EMAIL_ADDRESS_RECORDED_SUCCESS);
51
- TelemetryHelper.logActionEvent(LogLevel.INFO, {
52
- Event: TelemetryEvent.EmailTranscriptSent,
53
- Description: "Transcript sent to email successfully."
54
- });
55
- } catch (ex) {
56
- TelemetryHelper.logActionEvent(LogLevel.ERROR, {
57
- Event: TelemetryEvent.EmailTranscriptFailed,
58
- ExceptionDetails: {
59
- exception: ex
60
- }
61
- });
62
- const message = formatTemplateString(defaultMiddlewareLocalizedTexts.MIDDLEWARE_BANNER_FILE_EMAIL_ADDRESS_RECORDED_ERROR, [email]);
63
- NotificationHandler.notifyError(NotificationScenarios.EmailTranscriptError, (props === null || props === void 0 ? void 0 : props.bannerMessageOnError) ?? message);
64
- }
65
- },
70
+ onSend,
66
71
  onCancel: () => {
67
72
  TelemetryHelper.logActionEvent(LogLevel.INFO, {
68
73
  Event: TelemetryEvent.EmailTranscriptCancelButtonClicked,
@@ -6,6 +6,8 @@ import { LogLevel, TelemetryEvent } from "../../../common/telemetry/TelemetryCon
6
6
  import createChatTranscript from "../../../plugins/createChatTranscript";
7
7
  import DOMPurify from "dompurify";
8
8
  import { createFileAndDownload, isNullOrUndefined } from "../../../common/utils";
9
+ import { executeReducer } from "../../../contexts/createReducer";
10
+ import { LiveChatWidgetActionType } from "../../../contexts/common/LiveChatWidgetActionType";
9
11
  const processDisplayName = displayName => {
10
12
  // if displayname matches "teamsvisitor:<some alphanumeric string>", we replace it with "Customer"
11
13
  const displayNameRegex = ".+:.+";
@@ -157,12 +159,16 @@ const beautifyChatTranscripts = (chatTranscripts, renderMarkDown, attachmentMess
157
159
 
158
160
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
159
161
  export const downloadTranscript = async (chatSDK, downloadTranscriptProps, state) => {
160
- var _state$domainStates, _state$domainStates2, _state$domainStates2$;
161
- // Need to keep existing request id for scenarios when trnascript is downloaded after endchat
162
- const liveChatContext = {
163
- chatToken: state === null || state === void 0 ? void 0 : (_state$domainStates = state.domainStates) === null || _state$domainStates === void 0 ? void 0 : _state$domainStates.chatToken,
164
- requestId: state === null || state === void 0 ? void 0 : (_state$domainStates2 = state.domainStates) === null || _state$domainStates2 === void 0 ? void 0 : (_state$domainStates2$ = _state$domainStates2.chatToken) === null || _state$domainStates2$ === void 0 ? void 0 : _state$domainStates2$.requestId
165
- };
162
+ var _state$domainStates;
163
+ // Need to keep existing live chat context for scenarios when transcript is downloaded after endchat
164
+ let liveChatContext = state === null || state === void 0 ? void 0 : (_state$domainStates = state.domainStates) === null || _state$domainStates === void 0 ? void 0 : _state$domainStates.liveChatContext;
165
+ if (!liveChatContext) {
166
+ const inMemoryState = executeReducer(state, {
167
+ type: LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
168
+ payload: null
169
+ });
170
+ liveChatContext = inMemoryState.domainStates.liveChatContext;
171
+ }
166
172
  let data = await (chatSDK === null || chatSDK === void 0 ? void 0 : chatSDK.getLiveChatTranscript({
167
173
  liveChatContext
168
174
  }));
@@ -1,6 +1,7 @@
1
1
  import { LogLevel, TelemetryEvent } from "../../../common/telemetry/TelemetryConstants";
2
2
  import { TelemetryHelper } from "../../../common/telemetry/TelemetryHelper";
3
3
  import { isNullOrEmptyString } from "../../../common/utils";
4
+ import { WidgetLoadCustomErrorString } from "../../../common/Constants";
4
5
  const getAuthClientFunction = chatConfig => {
5
6
  let authClientFunction = undefined;
6
7
  if (chatConfig !== null && chatConfig !== void 0 && chatConfig.LiveChatConfigAuthSettings) {
@@ -25,10 +26,12 @@ const handleAuthentication = async (chatSDK, chatConfig, getAuthToken) => {
25
26
  });
26
27
  return true;
27
28
  } else {
29
+ // instead of returning false, it's more appropiate to thrown an error to force error handling on the caller side
30
+ // this will help to avoid the error to be ignored and the chat to be started
28
31
  TelemetryHelper.logActionEvent(LogLevel.ERROR, {
29
32
  Event: TelemetryEvent.ReceivedNullOrEmptyToken
30
33
  });
31
- return false;
34
+ throw new Error(WidgetLoadCustomErrorString.AuthenticationFailedErrorString);
32
35
  }
33
36
  }
34
37
  return false;
@@ -1,6 +1,6 @@
1
1
  import { ConfirmationState, Constants, ConversationEndEntity, ParticipantType, PrepareEndChatDescriptionConstants } from "../../../common/Constants";
2
2
  import { LogLevel, TelemetryEvent } from "../../../common/telemetry/TelemetryConstants";
3
- import { getAuthClientFunction, handleAuthentication } from "./authHelper";
3
+ import { handleAuthentication } from "./authHelper";
4
4
  import { getConversationDetailsCall, getWidgetEndChatEventName } from "../../../common/utils";
5
5
  import { getPostChatContext, initiatePostChat } from "./renderSurveyHelpers";
6
6
  import { BroadcastService } from "@microsoft/omnichannel-chat-components";
@@ -113,7 +113,7 @@ const endChat = async (props, chatSDK, state, dispatch, setAdapter, setWebChatSt
113
113
  Event: TelemetryEvent.EndChatSDKCall
114
114
  });
115
115
  //Get auth token again if chat continued for longer time, otherwise gets 401 error
116
- await handleAuthenticationIfEnabled(props, chatSDK);
116
+ await handleAuthentication(chatSDK, props.chatConfig, props.getAuthToken);
117
117
  await (chatSDK === null || chatSDK === void 0 ? void 0 : chatSDK.endChat());
118
118
  } catch (ex) {
119
119
  TelemetryHelper.logSDKEvent(LogLevel.ERROR, {
@@ -192,10 +192,6 @@ export const callingStateCleanUp = dispatch => {
192
192
  };
193
193
  export const endChatStateCleanUp = dispatch => {
194
194
  // Need to clear these states immediately when chat ended from OC.
195
- dispatch({
196
- type: LiveChatWidgetActionType.SET_LIVE_CHAT_CONTEXT,
197
- payload: undefined
198
- });
199
195
  dispatch({
200
196
  type: LiveChatWidgetActionType.SET_RECONNECT_ID,
201
197
  payload: undefined
@@ -239,6 +235,12 @@ export const closeChatStateCleanUp = dispatch => {
239
235
  proactiveChatInNewWindow: false
240
236
  }
241
237
  });
238
+
239
+ // Clear live chat context only if chat widget is fully closed to support transcript calls after sessionclose is called
240
+ dispatch({
241
+ type: LiveChatWidgetActionType.SET_LIVE_CHAT_CONTEXT,
242
+ payload: undefined
243
+ });
242
244
  };
243
245
 
244
246
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -296,27 +298,6 @@ const closeChatWidget = (dispatch, props, state) => {
296
298
  });
297
299
  };
298
300
 
299
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
300
- const handleAuthenticationIfEnabled = async (props, chatSDK) => {
301
- //Unable to end chat if token has expired
302
- if (props.getAuthToken) {
303
- const authClientFunction = getAuthClientFunction(props.chatConfig);
304
- if (props.getAuthToken && authClientFunction) {
305
- // set auth token to chat sdk before end chat
306
- const authSuccess = await handleAuthentication(chatSDK, props.chatConfig, props.getAuthToken);
307
- if (!authSuccess) {
308
- TelemetryHelper.logActionEvent(LogLevel.ERROR, {
309
- Event: TelemetryEvent.GetAuthTokenFailed,
310
- ExceptionDetails: {
311
- exception: "Unable to get auth token during end chat"
312
- }
313
- });
314
- throw new Error("handleAuthenticationIfEnabled:Failed to get authentication token");
315
- }
316
- }
317
- }
318
- };
319
-
320
301
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
321
302
  const chatTokenCleanUp = async dispatch => {
322
303
  //Just do cleanup here
@@ -324,10 +305,8 @@ const chatTokenCleanUp = async dispatch => {
324
305
  type: LiveChatWidgetActionType.SET_CHAT_TOKEN,
325
306
  payload: undefined
326
307
  });
327
- dispatch({
328
- type: LiveChatWidgetActionType.SET_LIVE_CHAT_CONTEXT,
329
- payload: undefined
330
- });
308
+
309
+ // Need to keep liveChatContext until chat is fully closed to for transcript download/email
331
310
  };
332
311
 
333
312
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -116,7 +116,7 @@ export const initWebChatComposer = (props, state, dispatch, chatSDK, endChat) =>
116
116
  dir: state.domainStates.globalDir,
117
117
  locale: changeLanguageCodeFormatForWebChat(getLocaleStringFromId((_state$domainStates$l4 = state.domainStates.liveChatConfig) === null || _state$domainStates$l4 === void 0 ? void 0 : (_state$domainStates$l5 = _state$domainStates$l4.ChatWidgetLanguage) === null || _state$domainStates$l5 === void 0 ? void 0 : _state$domainStates$l5.msdyn_localeid)),
118
118
  store: webChatStore,
119
- activityMiddleware: (_props$webChatContain9 = props.webChatContainerProps) !== null && _props$webChatContain9 !== void 0 && (_props$webChatContain10 = _props$webChatContain9.renderingMiddlewareProps) !== null && _props$webChatContain10 !== void 0 && _props$webChatContain10.disableActivityMiddleware ? undefined : createActivityMiddleware((_state$domainStates$r = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r === void 0 ? void 0 : _state$domainStates$r.systemMessageStyleProps, (_state$domainStates$r2 = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r2 === void 0 ? void 0 : _state$domainStates$r2.userMessageStyleProps),
119
+ activityMiddleware: (_props$webChatContain9 = props.webChatContainerProps) !== null && _props$webChatContain9 !== void 0 && (_props$webChatContain10 = _props$webChatContain9.renderingMiddlewareProps) !== null && _props$webChatContain10 !== void 0 && _props$webChatContain10.disableActivityMiddleware ? undefined : createActivityMiddleware(renderMarkdown, (_state$domainStates$r = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r === void 0 ? void 0 : _state$domainStates$r.systemMessageStyleProps, (_state$domainStates$r2 = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r2 === void 0 ? void 0 : _state$domainStates$r2.userMessageStyleProps),
120
120
  attachmentMiddleware: (_props$webChatContain11 = props.webChatContainerProps) !== null && _props$webChatContain11 !== void 0 && (_props$webChatContain12 = _props$webChatContain11.renderingMiddlewareProps) !== null && _props$webChatContain12 !== void 0 && _props$webChatContain12.disableAttachmentMiddleware ? undefined : createAttachmentMiddleware(((_state$domainStates$r3 = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r3 === void 0 ? void 0 : (_state$domainStates$r4 = _state$domainStates$r3.attachmentProps) === null || _state$domainStates$r4 === void 0 ? void 0 : _state$domainStates$r4.enableInlinePlaying) ?? defaultAttachmentProps.enableInlinePlaying),
121
121
  activityStatusMiddleware: (_props$webChatContain13 = props.webChatContainerProps) !== null && _props$webChatContain13 !== void 0 && (_props$webChatContain14 = _props$webChatContain13.renderingMiddlewareProps) !== null && _props$webChatContain14 !== void 0 && _props$webChatContain14.disableActivityStatusMiddleware ? undefined : (_defaultWebChatContai = defaultWebChatContainerStatefulProps.webChatProps) === null || _defaultWebChatContai === void 0 ? void 0 : _defaultWebChatContai.activityStatusMiddleware,
122
122
  toastMiddleware: (_props$webChatContain15 = props.webChatContainerProps) !== null && _props$webChatContain15 !== void 0 && (_props$webChatContain16 = _props$webChatContain15.renderingMiddlewareProps) !== null && _props$webChatContain16 !== void 0 && _props$webChatContain16.disableToastMiddleware ? undefined : createToastMiddleware(props.notificationPaneProps, endChat),
@@ -3,10 +3,12 @@ import { BroadcastEvent, LogLevel, TelemetryEvent } from "../../../common/teleme
3
3
  import { checkContactIdError, isNullOrEmptyString, isNullOrUndefined } from "../../../common/utils";
4
4
  import { handleAuthentication, removeAuthTokenProvider } from "./authHelper";
5
5
  import { BroadcastService } from "@microsoft/omnichannel-chat-components";
6
- import { ConversationMode } from "../../../common/Constants";
6
+ import { ConversationMode, WidgetLoadCustomErrorString } from "../../../common/Constants";
7
7
  import { ConversationState } from "../../../contexts/common/ConversationState";
8
8
  import { LiveChatWidgetActionType } from "../../../contexts/common/LiveChatWidgetActionType";
9
9
  import { TelemetryHelper } from "../../../common/telemetry/TelemetryHelper";
10
+ import { handleStartChatError } from "./startChatErrorHandler";
11
+
10
12
  // Return value: should start normal chat flow when reconnect is enabled
11
13
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
14
  const handleChatReconnect = async (chatSDK, props, dispatch, setAdapter, initStartChat, state) => {
@@ -15,7 +17,7 @@ const handleChatReconnect = async (chatSDK, props, dispatch, setAdapter, initSta
15
17
  const isAuthenticatedChat = (_props$chatConfig = props.chatConfig) !== null && _props$chatConfig !== void 0 && (_props$chatConfig$Liv = _props$chatConfig.LiveChatConfigAuthSettings) !== null && _props$chatConfig$Liv !== void 0 && _props$chatConfig$Liv.msdyn_javascriptclientfunction ? true : false;
16
18
 
17
19
  // Get chat reconnect context
18
- const reconnectChatContext = await getChatReconnectContext(chatSDK, props.chatConfig, props, isAuthenticatedChat);
20
+ const reconnectChatContext = await getChatReconnectContext(chatSDK, props.chatConfig, props, isAuthenticatedChat, dispatch);
19
21
 
20
22
  // Redirect if enabled
21
23
  if (reconnectChatContext !== null && reconnectChatContext !== void 0 && reconnectChatContext.redirectURL) {
@@ -50,7 +52,7 @@ const handleChatReconnect = async (chatSDK, props, dispatch, setAdapter, initSta
50
52
  };
51
53
 
52
54
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
53
- const getChatReconnectContext = async (chatSDK, chatConfig, props, isAuthenticatedChat) => {
55
+ const getChatReconnectContext = async (chatSDK, chatConfig, props, isAuthenticatedChat, dispatch) => {
54
56
  try {
55
57
  var _props$reconnectChatP4;
56
58
  TelemetryHelper.logSDKEvent(LogLevel.INFO, {
@@ -62,6 +64,7 @@ const getChatReconnectContext = async (chatSDK, chatConfig, props, isAuthenticat
62
64
  };
63
65
  // Get auth token for getting chat reconnect context
64
66
  if (isAuthenticatedChat) {
67
+ // handle authentication will throw error if auth token is not available, so no need to check for response
65
68
  await handleAuthentication(chatSDK, chatConfig, props.getAuthToken);
66
69
  }
67
70
  const reconnectChatContext = await (chatSDK === null || chatSDK === void 0 ? void 0 : chatSDK.getChatReconnectContext(chatReconnectOptionalParams));
@@ -71,7 +74,9 @@ const getChatReconnectContext = async (chatSDK, chatConfig, props, isAuthenticat
71
74
  removeAuthTokenProvider(chatSDK);
72
75
  }
73
76
  return reconnectChatContext;
74
- } catch (error) {
77
+ }
78
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
79
+ catch (error) {
75
80
  checkContactIdError(error);
76
81
  TelemetryHelper.logSDKEvent(LogLevel.ERROR, {
77
82
  Event: TelemetryEvent.GetChatReconnectContextSDKCallFailed,
@@ -79,6 +84,12 @@ const getChatReconnectContext = async (chatSDK, chatConfig, props, isAuthenticat
79
84
  exception: error
80
85
  }
81
86
  });
87
+
88
+ // when auth token is not available, propagate the error to stop the execution and ensure error pane is loaded
89
+ if ((error === null || error === void 0 ? void 0 : error.message) == WidgetLoadCustomErrorString.AuthenticationFailedErrorString) {
90
+ handleStartChatError(dispatch, chatSDK, props, new Error(WidgetLoadCustomErrorString.AuthenticationFailedErrorString), false);
91
+ throw error;
92
+ }
82
93
  }
83
94
  };
84
95
 
@@ -27,7 +27,6 @@ let popoutWidgetInstanceId;
27
27
  const prepareStartChat = async (props, chatSDK, state, dispatch, setAdapter) => {
28
28
  optionalParams = {}; //Resetting to ensure no stale values
29
29
  widgetInstanceId = getWidgetCacheIdfromProps(props);
30
-
31
30
  // reconnect > chat from cache
32
31
  if (isReconnectEnabled(props.chatConfig) === true && !isPersistentEnabled(props.chatConfig)) {
33
32
  const shouldStartChatNormally = await handleChatReconnect(chatSDK, props, dispatch, setAdapter, initStartChat, state);
@@ -77,6 +76,7 @@ const setPreChatAndInitiateChat = async (chatSDK, dispatch, setAdapter, isProact
77
76
  });
78
77
  return;
79
78
  } else {
79
+ var _state$appStates;
80
80
  dispatch({
81
81
  type: LiveChatWidgetActionType.SET_PRE_CHAT_SURVEY_RESPONSE,
82
82
  payload: preChatSurveyResponse
@@ -85,6 +85,24 @@ const setPreChatAndInitiateChat = async (chatSDK, dispatch, setAdapter, isProact
85
85
  type: LiveChatWidgetActionType.SET_CONVERSATION_STATE,
86
86
  payload: ConversationState.Prechat
87
87
  });
88
+
89
+ // If minimized, maximize the chat, if the state is missing, consider it as minimized
90
+ if ((state === null || state === void 0 ? void 0 : state.appStates.isMinimized) == undefined || (state === null || state === void 0 ? void 0 : (_state$appStates = state.appStates) === null || _state$appStates === void 0 ? void 0 : _state$appStates.isMinimized) === true) {
91
+ var _state$domainStates2, _state$domainStates2$, _state$domainStates3, _state$domainStates3$;
92
+ dispatch({
93
+ type: LiveChatWidgetActionType.SET_MINIMIZED,
94
+ payload: false
95
+ });
96
+
97
+ // this event will notify the upper layer to maximize the widget, an event missing during multi-tab scenario.
98
+ BroadcastService.postMessage({
99
+ eventName: BroadcastEvent.MaximizeChat,
100
+ payload: {
101
+ height: state === null || state === void 0 ? void 0 : (_state$domainStates2 = state.domainStates) === null || _state$domainStates2 === void 0 ? void 0 : (_state$domainStates2$ = _state$domainStates2.widgetSize) === null || _state$domainStates2$ === void 0 ? void 0 : _state$domainStates2$.height,
102
+ width: state === null || state === void 0 ? void 0 : (_state$domainStates3 = state.domainStates) === null || _state$domainStates3 === void 0 ? void 0 : (_state$domainStates3$ = _state$domainStates3.widgetSize) === null || _state$domainStates3$ === void 0 ? void 0 : _state$domainStates3$.width
103
+ }
104
+ });
105
+ }
88
106
  return;
89
107
  }
90
108
  }
@@ -110,9 +128,9 @@ const initStartChat = async (chatSDK, dispatch, setAdapter, state, props, params
110
128
  chatSDKStateCleanUp(chatSDK);
111
129
  }
112
130
  try {
113
- var _state$appStates, _newAdapter$activity$;
131
+ var _state$appStates2, _newAdapter$activity$;
114
132
  // Clear disconnect state on start chat
115
- (state === null || state === void 0 ? void 0 : (_state$appStates = state.appStates) === null || _state$appStates === void 0 ? void 0 : _state$appStates.chatDisconnectEventReceived) && dispatch({
133
+ (state === null || state === void 0 ? void 0 : (_state$appStates2 = state.appStates) === null || _state$appStates2 === void 0 ? void 0 : _state$appStates2.chatDisconnectEventReceived) && dispatch({
116
134
  type: LiveChatWidgetActionType.SET_CHAT_DISCONNECT_EVENT_RECEIVED,
117
135
  payload: false
118
136
  });
@@ -207,7 +225,6 @@ const initStartChat = async (chatSDK, dispatch, setAdapter, state, props, params
207
225
  payload: liveChatContext
208
226
  });
209
227
  logWidgetLoadComplete();
210
-
211
228
  // Set post chat context in state
212
229
  // Commenting this for now as post chat context is fetched during end chat
213
230
  await setPostChatContextAndLoadSurvey(chatSDK, dispatch);
@@ -224,9 +241,9 @@ const initStartChat = async (chatSDK, dispatch, setAdapter, state, props, params
224
241
 
225
242
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
226
243
  const canConnectToExistingChat = async (props, chatSDK, state, dispatch, setAdapter) => {
227
- var _state$appStates2, _persistedState$domai6, _persistedState$appSt;
244
+ var _state$appStates3, _persistedState$domai6, _persistedState$appSt;
228
245
  // By pass this function in case of popout chat
229
- if ((state === null || state === void 0 ? void 0 : (_state$appStates2 = state.appStates) === null || _state$appStates2 === void 0 ? void 0 : _state$appStates2.hideStartChatButton) === true) {
246
+ if ((state === null || state === void 0 ? void 0 : (_state$appStates3 = state.appStates) === null || _state$appStates3 === void 0 ? void 0 : _state$appStates3.hideStartChatButton) === true) {
230
247
  return false;
231
248
  }
232
249
  const persistedState = getStateFromCache(getWidgetCacheIdfromProps(props));
@@ -249,17 +266,17 @@ const canConnectToExistingChat = async (props, chatSDK, state, dispatch, setAdap
249
266
 
250
267
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
251
268
  const setCustomContextParams = async (state, props) => {
252
- var _props$chatConfig, _props$chatConfig$Liv, _state$domainStates2, _persistedState$domai8;
269
+ var _props$chatConfig, _props$chatConfig$Liv, _state$domainStates4, _persistedState$domai8;
253
270
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
254
271
  const isAuthenticatedChat = props !== null && props !== void 0 && (_props$chatConfig = props.chatConfig) !== null && _props$chatConfig !== void 0 && (_props$chatConfig$Liv = _props$chatConfig.LiveChatConfigAuthSettings) !== null && _props$chatConfig$Liv !== void 0 && _props$chatConfig$Liv.msdyn_javascriptclientfunction ? true : false;
255
272
  //Should not set custom context for auth chat
256
273
  if (isAuthenticatedChat) {
257
274
  return;
258
275
  }
259
- if (state !== null && state !== void 0 && (_state$domainStates2 = state.domainStates) !== null && _state$domainStates2 !== void 0 && _state$domainStates2.customContext) {
260
- var _state$domainStates3;
276
+ if (state !== null && state !== void 0 && (_state$domainStates4 = state.domainStates) !== null && _state$domainStates4 !== void 0 && _state$domainStates4.customContext) {
277
+ var _state$domainStates5;
261
278
  optionalParams = Object.assign({}, optionalParams, {
262
- customContext: JSON.parse(JSON.stringify(state === null || state === void 0 ? void 0 : (_state$domainStates3 = state.domainStates) === null || _state$domainStates3 === void 0 ? void 0 : _state$domainStates3.customContext))
279
+ customContext: JSON.parse(JSON.stringify(state === null || state === void 0 ? void 0 : (_state$domainStates5 = state.domainStates) === null || _state$domainStates5 === void 0 ? void 0 : _state$domainStates5.customContext))
263
280
  });
264
281
  return;
265
282
  }
@@ -307,12 +324,14 @@ const canStartPopoutChat = async props => {
307
324
 
308
325
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
309
326
  const checkIfConversationStillValid = async (chatSDK, dispatch, state) => {
310
- var _state$domainStates4, _state$domainStates4$;
311
- const requestIdFromCache = (_state$domainStates4 = state.domainStates) === null || _state$domainStates4 === void 0 ? void 0 : (_state$domainStates4$ = _state$domainStates4.liveChatContext) === null || _state$domainStates4$ === void 0 ? void 0 : _state$domainStates4$.requestId;
327
+ var _state$domainStates6, _state$domainStates6$, _state$domainStates7;
328
+ const requestIdFromCache = (_state$domainStates6 = state.domainStates) === null || _state$domainStates6 === void 0 ? void 0 : (_state$domainStates6$ = _state$domainStates6.liveChatContext) === null || _state$domainStates6$ === void 0 ? void 0 : _state$domainStates6$.requestId;
329
+ const liveChatContext = state === null || state === void 0 ? void 0 : (_state$domainStates7 = state.domainStates) === null || _state$domainStates7 === void 0 ? void 0 : _state$domainStates7.liveChatContext;
330
+
312
331
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
313
332
  let conversationDetails = undefined;
314
333
 
315
- //Preserve current requestId
334
+ // Preserve current requestId
316
335
  const currentRequestId = chatSDK.requestId ?? "";
317
336
  dispatch({
318
337
  type: LiveChatWidgetActionType.SET_INITIAL_CHAT_SDK_REQUEST_ID,
@@ -320,9 +339,8 @@ const checkIfConversationStillValid = async (chatSDK, dispatch, state) => {
320
339
  });
321
340
  try {
322
341
  chatSDK.requestId = requestIdFromCache;
323
- conversationDetails = await getConversationDetailsCall(chatSDK);
342
+ conversationDetails = await getConversationDetailsCall(chatSDK, liveChatContext);
324
343
  if (Object.keys(conversationDetails).length === 0) {
325
- chatSDK.requestId = currentRequestId;
326
344
  return false;
327
345
  }
328
346
  if (conversationDetails.state === LiveWorkItemState.Closed || conversationDetails.state === LiveWorkItemState.WrapUp) {
@@ -330,18 +348,16 @@ const checkIfConversationStillValid = async (chatSDK, dispatch, state) => {
330
348
  type: LiveChatWidgetActionType.SET_LIVE_CHAT_CONTEXT,
331
349
  payload: undefined
332
350
  });
333
- chatSDK.requestId = currentRequestId;
334
351
  return false;
335
352
  }
336
353
  return true;
337
- } catch (erorr) {
354
+ } catch (error) {
338
355
  TelemetryHelper.logActionEvent(LogLevel.ERROR, {
339
356
  Event: TelemetryEvent.GetConversationDetailsException,
340
357
  ExceptionDetails: {
341
- exception: `Conversation is not valid: ${erorr}`
358
+ exception: `Conversation is not valid: ${error}`
342
359
  }
343
360
  });
344
- chatSDK.requestId = currentRequestId;
345
361
  return false;
346
362
  }
347
363
  };
@@ -24,6 +24,11 @@ export const handleStartChatError = (dispatch, chatSDK, props, ex, isStartChatSu
24
24
  type: LiveChatWidgetActionType.SET_START_CHAT_FAILURE_TYPE,
25
25
  payload: StartChatFailureType.AuthSetupError
26
26
  });
27
+ // set conversation to error to enforce error UI pane
28
+ dispatch({
29
+ type: LiveChatWidgetActionType.SET_CONVERSATION_STATE,
30
+ payload: ConversationState.Error
31
+ });
27
32
  logWidgetLoadCompleteWithError(ex);
28
33
  }
29
34
  if (ex.message === WidgetLoadCustomErrorString.NetworkErrorString) {