@microsoft/omnichannel-chat-widget 1.8.1-main.565f247 → 1.8.1-main.5ac9acf
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.
- package/lib/cjs/common/facades/FacadeChatSDK.js +49 -7
- package/lib/cjs/common/telemetry/TelemetryConstants.js +4 -0
- package/lib/cjs/common/telemetry/TelemetryManager.js +2 -2
- package/lib/cjs/common/utils/xssUtils.js +79 -0
- package/lib/cjs/common/utils.js +3 -0
- package/lib/cjs/components/confirmationpanestateful/ConfirmationPaneStateful.js +7 -3
- package/lib/cjs/components/errorboundary/ErrorBoundary.js +68 -0
- package/lib/cjs/components/livechatwidget/LiveChatWidget.js +15 -4
- package/lib/cjs/components/livechatwidget/common/liveChatConfigUtils.js +1 -1
- package/lib/cjs/components/livechatwidget/common/persistentChatHelper.js +12 -5
- package/lib/cjs/components/livechatwidget/common/reconnectChatHelper.js +4 -0
- package/lib/cjs/components/livechatwidget/common/startChat.js +2 -2
- package/lib/cjs/components/livechatwidget/common/startChatErrorHandler.js +55 -9
- package/lib/cjs/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +31 -19
- package/lib/cjs/components/ooohpanestateful/OOOHPaneStateful.js +23 -2
- package/lib/cjs/components/postchatsurveypanestateful/PostChatSurveyPaneStateful.js +14 -5
- package/lib/cjs/components/postchatsurveypanestateful/enums/CustomerVoiceEvents.js +1 -0
- package/lib/esm/common/facades/FacadeChatSDK.js +49 -7
- package/lib/esm/common/telemetry/TelemetryConstants.js +4 -0
- package/lib/esm/common/telemetry/TelemetryManager.js +2 -2
- package/lib/esm/common/utils/xssUtils.js +72 -0
- package/lib/esm/common/utils.js +3 -0
- package/lib/esm/components/confirmationpanestateful/ConfirmationPaneStateful.js +7 -3
- package/lib/esm/components/errorboundary/ErrorBoundary.js +59 -0
- package/lib/esm/components/livechatwidget/LiveChatWidget.js +16 -5
- package/lib/esm/components/livechatwidget/common/liveChatConfigUtils.js +1 -1
- package/lib/esm/components/livechatwidget/common/persistentChatHelper.js +12 -5
- package/lib/esm/components/livechatwidget/common/reconnectChatHelper.js +4 -0
- package/lib/esm/components/livechatwidget/common/startChat.js +2 -2
- package/lib/esm/components/livechatwidget/common/startChatErrorHandler.js +53 -8
- package/lib/esm/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +31 -19
- package/lib/esm/components/ooohpanestateful/OOOHPaneStateful.js +23 -2
- package/lib/esm/components/postchatsurveypanestateful/PostChatSurveyPaneStateful.js +14 -5
- package/lib/esm/components/postchatsurveypanestateful/enums/CustomerVoiceEvents.js +1 -0
- package/lib/types/common/facades/FacadeChatSDK.d.ts +1 -0
- package/lib/types/common/telemetry/TelemetryConstants.d.ts +4 -0
- package/lib/types/common/utils/xssUtils.d.ts +29 -0
- package/lib/types/components/errorboundary/ErrorBoundary.d.ts +14 -0
- package/lib/types/components/livechatwidget/common/liveChatConfigUtils.d.ts +1 -1
- package/lib/types/components/livechatwidget/common/persistentChatHelper.d.ts +2 -1
- package/lib/types/components/livechatwidget/common/startChatErrorHandler.d.ts +1 -0
- package/lib/types/components/postchatsurveypanestateful/enums/CustomerVoiceEvents.d.ts +2 -1
- package/lib/types/components/postchatsurveypanestateful/interfaces/IPostChatSurveyPaneStatefulProps.d.ts +1 -0
- package/package.json +2 -2
|
@@ -6,7 +6,7 @@ export const isPostChatSurveyEnabled = async facadeChatSDK => {
|
|
|
6
6
|
const postChatEnabled = (_chatConfig$LiveWSAnd = chatConfig.LiveWSAndLiveChatEngJoin) === null || _chatConfig$LiveWSAnd === void 0 ? void 0 : _chatConfig$LiveWSAnd.msdyn_postconversationsurveyenable.toString().toLowerCase();
|
|
7
7
|
return postChatEnabled === "true";
|
|
8
8
|
};
|
|
9
|
-
export const isPersistentChatEnabled =
|
|
9
|
+
export const isPersistentChatEnabled = conversationMode => {
|
|
10
10
|
if (isNullOrUndefined(conversationMode)) {
|
|
11
11
|
return false;
|
|
12
12
|
}
|
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
import { isPersistentChatEnabled } from "./liveChatConfigUtils";
|
|
2
2
|
|
|
3
3
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4
|
-
export const shouldSetPreChatIfPersistentChat = async (
|
|
5
|
-
const persistentEnabled =
|
|
4
|
+
export const shouldSetPreChatIfPersistentChat = async (facadeChatSDK, conversationMode, showPreChat) => {
|
|
5
|
+
const persistentEnabled = isPersistentChatEnabled(conversationMode);
|
|
6
6
|
let skipPreChat = false;
|
|
7
7
|
if (persistentEnabled) {
|
|
8
|
+
// Access private properties using type assertions
|
|
9
|
+
const chatSDK = facadeChatSDK.getChatSDK();
|
|
10
|
+
|
|
11
|
+
// Use type assertion to bypass private access restriction
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
13
|
+
const sdkAsAny = chatSDK;
|
|
14
|
+
// most likely this is not set , the facade will take care of it
|
|
8
15
|
const reconnectableChatsParams = {
|
|
9
|
-
authenticatedUserToken:
|
|
10
|
-
requestId:
|
|
16
|
+
authenticatedUserToken: sdkAsAny.authenticatedUserToken,
|
|
17
|
+
requestId: sdkAsAny.requestId
|
|
11
18
|
};
|
|
12
19
|
try {
|
|
13
|
-
const reconnectableChatsResponse = await
|
|
20
|
+
const reconnectableChatsResponse = await facadeChatSDK.getReconnectableChats(reconnectableChatsParams);
|
|
14
21
|
if (reconnectableChatsResponse && reconnectableChatsResponse.reconnectid) {
|
|
15
22
|
// Skip rendering prechat on existing persistent chat session
|
|
16
23
|
skipPreChat = true;
|
|
@@ -67,6 +67,10 @@ const getChatReconnectContext = async (facadeChatSDK, chatConfig, props, isAuthe
|
|
|
67
67
|
// AuthToken will be reset later at start chat
|
|
68
68
|
removeAuthTokenProvider(facadeChatSDK.getChatSDK());
|
|
69
69
|
}
|
|
70
|
+
TelemetryHelper.logSDKEvent(LogLevel.INFO, {
|
|
71
|
+
Event: TelemetryEvent.GetChatReconnectContextSDKCallSucceeded,
|
|
72
|
+
Description: "Reconnect context SDK call succeeded"
|
|
73
|
+
});
|
|
70
74
|
return reconnectChatContext;
|
|
71
75
|
}
|
|
72
76
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -69,7 +69,7 @@ const setPreChatAndInitiateChat = async (facadeChatSDK, dispatch, setAdapter, is
|
|
|
69
69
|
const parseToJson = false;
|
|
70
70
|
const preChatSurveyResponse = (props === null || props === void 0 ? void 0 : (_props$preChatSurveyP = props.preChatSurveyPaneProps) === null || _props$preChatSurveyP === void 0 ? void 0 : (_props$preChatSurveyP2 = _props$preChatSurveyP.controlProps) === null || _props$preChatSurveyP2 === void 0 ? void 0 : _props$preChatSurveyP2.payload) ?? (await facadeChatSDK.getPreChatSurvey(parseToJson));
|
|
71
71
|
let showPrechat = isProactiveChat ? preChatSurveyResponse && proactiveChatEnablePrechatState : preChatSurveyResponse && !(props !== null && props !== void 0 && (_props$controlProps = props.controlProps) !== null && _props$controlProps !== void 0 && _props$controlProps.hidePreChatSurveyPane);
|
|
72
|
-
showPrechat = await shouldSetPreChatIfPersistentChat(facadeChatSDK
|
|
72
|
+
showPrechat = await shouldSetPreChatIfPersistentChat(facadeChatSDK, state === null || state === void 0 ? void 0 : (_state$domainStates = state.domainStates) === null || _state$domainStates === void 0 ? void 0 : (_state$domainStates$l = _state$domainStates.liveChatConfig) === null || _state$domainStates$l === void 0 ? void 0 : (_state$domainStates$l2 = _state$domainStates$l.LiveWSAndLiveChatEngJoin) === null || _state$domainStates$l2 === void 0 ? void 0 : _state$domainStates$l2.msdyn_conversationmode, showPrechat);
|
|
73
73
|
if (showPrechat) {
|
|
74
74
|
var _state$domainStates2, _state$domainStates2$, _state$domainStates2$2, _state$domainStates2$3;
|
|
75
75
|
const isOutOfOperatingHours = (state === null || state === void 0 ? void 0 : (_state$domainStates2 = state.domainStates) === null || _state$domainStates2 === void 0 ? void 0 : (_state$domainStates2$ = _state$domainStates2.liveChatConfig) === null || _state$domainStates2$ === void 0 ? void 0 : (_state$domainStates2$2 = _state$domainStates2$.LiveWSAndLiveChatEngJoin) === null || _state$domainStates2$2 === void 0 ? void 0 : (_state$domainStates2$3 = _state$domainStates2$2.OutOfOperatingHours) === null || _state$domainStates2$3 === void 0 ? void 0 : _state$domainStates2$3.toString().toLowerCase()) === "true";
|
|
@@ -156,7 +156,7 @@ const setPreChatAndInitiateChat = async (facadeChatSDK, dispatch, setAdapter, is
|
|
|
156
156
|
const initStartChat = async (facadeChatSDK, dispatch, setAdapter, state, props, params, persistedState) => {
|
|
157
157
|
var _state$domainStates7, _state$domainStates7$, _state$domainStates7$2;
|
|
158
158
|
let isStartChatSuccessful = false;
|
|
159
|
-
const persistentChatEnabled =
|
|
159
|
+
const persistentChatEnabled = isPersistentChatEnabled(state === null || state === void 0 ? void 0 : (_state$domainStates7 = state.domainStates) === null || _state$domainStates7 === void 0 ? void 0 : (_state$domainStates7$ = _state$domainStates7.liveChatConfig) === null || _state$domainStates7$ === void 0 ? void 0 : (_state$domainStates7$2 = _state$domainStates7$.LiveWSAndLiveChatEngJoin) === null || _state$domainStates7$2 === void 0 ? void 0 : _state$domainStates7$2.msdyn_conversationmode);
|
|
160
160
|
if ((state === null || state === void 0 ? void 0 : state.appStates.conversationState) === ConversationState.Closed) {
|
|
161
161
|
// Preventive reset to avoid starting chat with previous requestId which could potentially cause problems
|
|
162
162
|
chatSDKStateCleanUp(facadeChatSDK.getChatSDK());
|
|
@@ -10,6 +10,11 @@ import { TelemetryHelper } from "../../../common/telemetry/TelemetryHelper";
|
|
|
10
10
|
import { TelemetryTimers } from "../../../common/telemetry/TelemetryManager";
|
|
11
11
|
import { getWidgetCacheIdfromProps } from "../../../common/utils";
|
|
12
12
|
|
|
13
|
+
// Helper function to check if error is authentication-related
|
|
14
|
+
const isAuthenticationError = errorMessage => {
|
|
15
|
+
return errorMessage === WidgetLoadCustomErrorString.AuthenticationFailedErrorString || errorMessage.startsWith("Authentication Setup Error:") || errorMessage.includes("Token validation failed") || errorMessage.includes("Authentication token");
|
|
16
|
+
};
|
|
17
|
+
|
|
13
18
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
14
19
|
export const handleStartChatError = (dispatch, facadeChatSDK, props, ex, isStartChatSuccessful) => {
|
|
15
20
|
var _props$controlProps;
|
|
@@ -18,19 +23,16 @@ export const handleStartChatError = (dispatch, facadeChatSDK, props, ex, isStart
|
|
|
18
23
|
return;
|
|
19
24
|
}
|
|
20
25
|
|
|
21
|
-
// Handle
|
|
22
|
-
if (ex.message
|
|
26
|
+
// Handle authentication-related errors
|
|
27
|
+
if (isAuthenticationError(ex.message)) {
|
|
23
28
|
dispatch({
|
|
24
29
|
type: LiveChatWidgetActionType.SET_START_CHAT_FAILURE_TYPE,
|
|
25
30
|
payload: StartChatFailureType.AuthSetupError
|
|
26
31
|
});
|
|
27
|
-
// set conversation to error to enforce error UI pane
|
|
28
|
-
dispatch({
|
|
29
|
-
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE,
|
|
30
|
-
payload: ConversationState.Error
|
|
31
|
-
});
|
|
32
32
|
logWidgetLoadCompleteWithError(ex);
|
|
33
|
+
// Don't return early - let the generic error handling logic handle hideErrorUIPane and telemetry
|
|
33
34
|
}
|
|
35
|
+
|
|
34
36
|
if (ex.message === WidgetLoadCustomErrorString.NetworkErrorString) {
|
|
35
37
|
logWidgetLoadCompleteWithError(ex);
|
|
36
38
|
}
|
|
@@ -53,8 +55,11 @@ export const handleStartChatError = (dispatch, facadeChatSDK, props, ex, isStart
|
|
|
53
55
|
case ChatSDKErrorName.UninitializedChatSDK:
|
|
54
56
|
handleUninitializedChatSDK(ex);
|
|
55
57
|
break;
|
|
56
|
-
// Handle the case indicating failure to retrieve an authenticated chat conversation
|
|
57
58
|
case ChatSDKErrorName.AuthenticatedChatConversationRetrievalFailure:
|
|
59
|
+
dispatch({
|
|
60
|
+
type: LiveChatWidgetActionType.SET_START_CHAT_FAILURE_TYPE,
|
|
61
|
+
payload: StartChatFailureType.Unauthorized
|
|
62
|
+
});
|
|
58
63
|
logWidgetLoadCompleteWithError(ex);
|
|
59
64
|
break;
|
|
60
65
|
case ChatSDKErrorName.InvalidConversation:
|
|
@@ -106,6 +111,9 @@ const logWidgetLoadFailed = ex => {
|
|
|
106
111
|
if (ex !== null && ex !== void 0 && ex.httpResponseStatusCode) {
|
|
107
112
|
exDetails.HttpResponseStatusCode = ex.httpResponseStatusCode;
|
|
108
113
|
}
|
|
114
|
+
if (ex !== null && ex !== void 0 && ex.exceptionDetails) {
|
|
115
|
+
exDetails.ChatSDKExceptionDetails = ex.exceptionDetails;
|
|
116
|
+
}
|
|
109
117
|
TelemetryHelper.logLoadingEventToAllTelemetry(LogLevel.ERROR, {
|
|
110
118
|
Event: TelemetryEvent.WidgetLoadFailed,
|
|
111
119
|
Description: "Widget load complete with error",
|
|
@@ -134,6 +142,9 @@ const logWidgetLoadCompleteWithError = ex => {
|
|
|
134
142
|
if (ex !== null && ex !== void 0 && ex.httpResponseStatusCode) {
|
|
135
143
|
exDetails.HttpResponseStatusCode = ex.httpResponseStatusCode;
|
|
136
144
|
}
|
|
145
|
+
if (ex !== null && ex !== void 0 && ex.exceptionDetails) {
|
|
146
|
+
exDetails.ChatSDKExceptionDetails = ex.exceptionDetails;
|
|
147
|
+
}
|
|
137
148
|
TelemetryHelper.logLoadingEventToAllTelemetry(LogLevel.ERROR, {
|
|
138
149
|
Event: TelemetryEvent.WidgetLoadFailed,
|
|
139
150
|
Description: "Widget load complete with error",
|
|
@@ -141,6 +152,34 @@ const logWidgetLoadCompleteWithError = ex => {
|
|
|
141
152
|
ElapsedTimeInMilliseconds: TelemetryTimers === null || TelemetryTimers === void 0 ? void 0 : (_TelemetryTimers$Widg3 = TelemetryTimers.WidgetLoadTimer) === null || _TelemetryTimers$Widg3 === void 0 ? void 0 : _TelemetryTimers$Widg3.milliSecondsElapsed
|
|
142
153
|
});
|
|
143
154
|
};
|
|
155
|
+
export const logWidgetLoadWithUnexpectedError = ex => {
|
|
156
|
+
var _TelemetryTimers$Widg4;
|
|
157
|
+
// eslint-disable-line @typescript-eslint/no-explicit-any
|
|
158
|
+
const details = {
|
|
159
|
+
message: (ex === null || ex === void 0 ? void 0 : ex.message) || "An unexpected error occurred",
|
|
160
|
+
stack: (ex === null || ex === void 0 ? void 0 : ex.stack) || "No stack trace available"
|
|
161
|
+
};
|
|
162
|
+
let additionalDetails = "";
|
|
163
|
+
try {
|
|
164
|
+
additionalDetails = JSON.stringify(details);
|
|
165
|
+
} catch (error) {
|
|
166
|
+
additionalDetails = "Failed to stringify error details";
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
170
|
+
const exDetails = {
|
|
171
|
+
Exception: `Widget load with unexpected error: ${additionalDetails}`
|
|
172
|
+
};
|
|
173
|
+
if (ex !== null && ex !== void 0 && ex.httpResponseStatusCode) {
|
|
174
|
+
exDetails.HttpResponseStatusCode = ex.httpResponseStatusCode;
|
|
175
|
+
}
|
|
176
|
+
TelemetryHelper.logLoadingEventToAllTelemetry(LogLevel.ERROR, {
|
|
177
|
+
Event: TelemetryEvent.WidgetLoadFailed,
|
|
178
|
+
Description: "Widget load with unexpected error",
|
|
179
|
+
ExceptionDetails: exDetails,
|
|
180
|
+
ElapsedTimeInMilliseconds: TelemetryTimers === null || TelemetryTimers === void 0 ? void 0 : (_TelemetryTimers$Widg4 = TelemetryTimers.WidgetLoadTimer) === null || _TelemetryTimers$Widg4 === void 0 ? void 0 : _TelemetryTimers$Widg4.milliSecondsElapsed
|
|
181
|
+
});
|
|
182
|
+
};
|
|
144
183
|
|
|
145
184
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
146
185
|
const forceEndChat = facadeChatSDK => {
|
|
@@ -193,6 +232,12 @@ const handleChatTokenRetrievalFailure = (dispatch, ex) => {
|
|
|
193
232
|
type: LiveChatWidgetActionType.SET_START_CHAT_FAILURE_TYPE,
|
|
194
233
|
payload: StartChatFailureType.Unauthorized
|
|
195
234
|
});
|
|
235
|
+
} else {
|
|
236
|
+
// For other authentication-related token retrieval failures, set as AuthSetupError
|
|
237
|
+
dispatch({
|
|
238
|
+
type: LiveChatWidgetActionType.SET_START_CHAT_FAILURE_TYPE,
|
|
239
|
+
payload: StartChatFailureType.AuthSetupError
|
|
240
|
+
});
|
|
196
241
|
}
|
|
197
242
|
logWidgetLoadCompleteWithError(ex);
|
|
198
243
|
}
|
|
@@ -48,7 +48,6 @@ import { initCallingSdk } from "../common/initCallingSdk";
|
|
|
48
48
|
import { initConfirmationPropsComposer } from "../common/initConfirmationPropsComposer";
|
|
49
49
|
import { initWebChatComposer } from "../common/initWebChatComposer";
|
|
50
50
|
import { registerBroadcastServiceForStorage } from "../../../common/storage/default/defaultCacheManager";
|
|
51
|
-
import { registerTelemetryLoggers } from "../common/registerTelemetryLoggers";
|
|
52
51
|
import { setPostChatContextAndLoadSurvey } from "../common/setPostChatContextAndLoadSurvey";
|
|
53
52
|
import { startProactiveChat } from "../common/startProactiveChat";
|
|
54
53
|
import useChatAdapterStore from "../../../hooks/useChatAdapterStore";
|
|
@@ -56,7 +55,7 @@ import useChatContextStore from "../../../hooks/useChatContextStore";
|
|
|
56
55
|
import useFacadeSDKStore from "../../../hooks/useFacadeChatSDKStore";
|
|
57
56
|
let uiTimer;
|
|
58
57
|
export const LiveChatWidgetStateful = props => {
|
|
59
|
-
var _props$webChatContain, _props$
|
|
58
|
+
var _props$webChatContain, _props$webChatContain2, _props$webChatContain3, _props$webChatContain4, _props$webChatContain5, _props$webChatContain6, _props$webChatContain7, _props$webChatContain8, _props$webChatContain9, _props$styleProps, _props$webChatContain10, _props$webChatContain11, _props$controlProps, _props$controlProps3, _state$appStates7, _props$webChatContain15, _state$appStates14, _props$webChatContain17, _props$webChatContain18, _props$controlProps12, _props$draggableChatW, _props$draggableChatW2, _props$draggableChatW3, _props$draggableChatW4, _props$draggableChatW5, _livechatProps$webCha, _livechatProps$styleP, _livechatProps$contro, _livechatProps$contro2, _livechatProps$compon, _livechatProps$contro3, _livechatProps$compon2, _livechatProps$contro4, _livechatProps$compon3, _livechatProps$contro5, _livechatProps$compon4, _livechatProps$contro6, _livechatProps$compon5, _livechatProps$contro7, _livechatProps$compon6, _livechatProps$contro8, _livechatProps$compon7, _livechatProps$contro9, _livechatProps$compon8, _livechatProps$contro10, _livechatProps$contro11, _livechatProps$compon9, _livechatProps$contro12, _livechatProps$compon10, _livechatProps$contro13, _livechatProps$compon11, _livechatProps$compon12, _livechatProps$compon13;
|
|
60
59
|
useEffect(() => {
|
|
61
60
|
uiTimer = createTimer();
|
|
62
61
|
TelemetryHelper.logLoadingEventToAllTelemetry(LogLevel.INFO, {
|
|
@@ -75,10 +74,13 @@ export const LiveChatWidgetStateful = props => {
|
|
|
75
74
|
const [facadeChatSDK] = useFacadeSDKStore();
|
|
76
75
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
77
76
|
const [voiceVideoCallingSDK, setVoiceVideoCallingSDK] = useState(undefined);
|
|
77
|
+
const [conversationId, setConversationId] = useState("");
|
|
78
78
|
const {
|
|
79
79
|
Composer
|
|
80
80
|
} = Components;
|
|
81
81
|
const canStartProactiveChat = useRef(true);
|
|
82
|
+
const bubbleBackground = ((_props$webChatContain2 = props.webChatContainerProps) === null || _props$webChatContain2 === void 0 ? void 0 : (_props$webChatContain3 = _props$webChatContain2.webChatStyles) === null || _props$webChatContain3 === void 0 ? void 0 : _props$webChatContain3.bubbleBackground) ?? ((_props$webChatContain4 = props.webChatContainerProps) === null || _props$webChatContain4 === void 0 ? void 0 : (_props$webChatContain5 = _props$webChatContain4.adaptiveCardStyles) === null || _props$webChatContain5 === void 0 ? void 0 : _props$webChatContain5.background) ?? defaultAdaptiveCardStyles.background;
|
|
83
|
+
const bubbleTextColor = ((_props$webChatContain6 = props.webChatContainerProps) === null || _props$webChatContain6 === void 0 ? void 0 : (_props$webChatContain7 = _props$webChatContain6.webChatStyles) === null || _props$webChatContain7 === void 0 ? void 0 : _props$webChatContain7.bubbleTextColor) ?? ((_props$webChatContain8 = props.webChatContainerProps) === null || _props$webChatContain8 === void 0 ? void 0 : (_props$webChatContain9 = _props$webChatContain8.adaptiveCardStyles) === null || _props$webChatContain9 === void 0 ? void 0 : _props$webChatContain9.color) ?? defaultAdaptiveCardStyles.color;
|
|
82
84
|
|
|
83
85
|
// Process general styles
|
|
84
86
|
const generalStyles = {
|
|
@@ -87,7 +89,7 @@ export const LiveChatWidgetStateful = props => {
|
|
|
87
89
|
|
|
88
90
|
//Scrollbar styles
|
|
89
91
|
const scrollbarProps = Object.assign({}, defaultScrollBarProps, props === null || props === void 0 ? void 0 : props.scrollBarProps);
|
|
90
|
-
const sendBoxTextArea = props === null || props === void 0 ? void 0 : (_props$
|
|
92
|
+
const sendBoxTextArea = props === null || props === void 0 ? void 0 : (_props$webChatContain10 = props.webChatContainerProps) === null || _props$webChatContain10 === void 0 ? void 0 : (_props$webChatContain11 = _props$webChatContain10.sendBoxTextBox) === null || _props$webChatContain11 === void 0 ? void 0 : _props$webChatContain11.textarea;
|
|
91
93
|
|
|
92
94
|
// In case the broadcast channel is already initialized elsewhere; One tab can only hold 1 instance
|
|
93
95
|
if ((props === null || props === void 0 ? void 0 : (_props$controlProps = props.controlProps) === null || _props$controlProps === void 0 ? void 0 : _props$controlProps.skipBroadcastChannelInit) !== true) {
|
|
@@ -220,7 +222,6 @@ export const LiveChatWidgetStateful = props => {
|
|
|
220
222
|
state.domainStates.confirmationPaneConfirmedOptionClicked = false;
|
|
221
223
|
state.domainStates.confirmationState = ConfirmationState.NotSet;
|
|
222
224
|
setupClientDataStore();
|
|
223
|
-
registerTelemetryLoggers(props, dispatch);
|
|
224
225
|
createInternetConnectionChangeHandler(state);
|
|
225
226
|
dispatch({
|
|
226
227
|
type: LiveChatWidgetActionType.SET_WIDGET_ELEMENT_ID,
|
|
@@ -570,6 +571,14 @@ export const LiveChatWidgetStateful = props => {
|
|
|
570
571
|
});
|
|
571
572
|
});
|
|
572
573
|
|
|
574
|
+
// Retrieve convId
|
|
575
|
+
BroadcastService.getMessageByEventName(BroadcastEvent.UpdateConversationDataForTelemetry).subscribe(msg => {
|
|
576
|
+
var _msg$payload11, _msg$payload11$liveWo;
|
|
577
|
+
if ((_msg$payload11 = msg.payload) !== null && _msg$payload11 !== void 0 && (_msg$payload11$liveWo = _msg$payload11.liveWorkItem) !== null && _msg$payload11$liveWo !== void 0 && _msg$payload11$liveWo.conversationId) {
|
|
578
|
+
setConversationId(msg.payload.liveWorkItem.conversationId);
|
|
579
|
+
}
|
|
580
|
+
});
|
|
581
|
+
|
|
573
582
|
// Check for TPC and log in telemetry if blocked
|
|
574
583
|
isCookieAllowed();
|
|
575
584
|
return () => {
|
|
@@ -616,8 +625,8 @@ export const LiveChatWidgetStateful = props => {
|
|
|
616
625
|
});
|
|
617
626
|
}
|
|
618
627
|
if (state.appStates.conversationState === ConversationState.InActive) {
|
|
619
|
-
var _props$
|
|
620
|
-
if ((props === null || props === void 0 ? void 0 : (_props$
|
|
628
|
+
var _props$webChatContain12, _props$webChatContain13;
|
|
629
|
+
if ((props === null || props === void 0 ? void 0 : (_props$webChatContain12 = props.webChatContainerProps) === null || _props$webChatContain12 === void 0 ? void 0 : (_props$webChatContain13 = _props$webChatContain12.renderingMiddlewareProps) === null || _props$webChatContain13 === void 0 ? void 0 : _props$webChatContain13.hideSendboxOnConversationEnd) !== false) {
|
|
621
630
|
setWebChatStyles(styles => {
|
|
622
631
|
return {
|
|
623
632
|
...styles,
|
|
@@ -661,12 +670,12 @@ export const LiveChatWidgetStateful = props => {
|
|
|
661
670
|
}
|
|
662
671
|
}, [state.appStates.unreadMessageCount]);
|
|
663
672
|
useEffect(() => {
|
|
664
|
-
var _props$
|
|
673
|
+
var _props$webChatContain14;
|
|
665
674
|
setWebChatStyles({
|
|
666
675
|
...webChatStyles,
|
|
667
|
-
...((_props$
|
|
676
|
+
...((_props$webChatContain14 = props.webChatContainerProps) === null || _props$webChatContain14 === void 0 ? void 0 : _props$webChatContain14.webChatStyles)
|
|
668
677
|
});
|
|
669
|
-
}, [(_props$
|
|
678
|
+
}, [(_props$webChatContain15 = props.webChatContainerProps) === null || _props$webChatContain15 === void 0 ? void 0 : _props$webChatContain15.webChatStyles]);
|
|
670
679
|
useEffect(() => {
|
|
671
680
|
//Confirmation pane dismissing through OK option, so proceed with end chat
|
|
672
681
|
if (state.domainStates.confirmationState === ConfirmationState.Ok) {
|
|
@@ -765,12 +774,12 @@ export const LiveChatWidgetStateful = props => {
|
|
|
765
774
|
|
|
766
775
|
// if props state gets updates we need to update the renderingMiddlewareProps in the state
|
|
767
776
|
useEffect(() => {
|
|
768
|
-
var _props$
|
|
777
|
+
var _props$webChatContain16;
|
|
769
778
|
dispatch({
|
|
770
779
|
type: LiveChatWidgetActionType.SET_RENDERING_MIDDLEWARE_PROPS,
|
|
771
|
-
payload: (_props$
|
|
780
|
+
payload: (_props$webChatContain16 = props.webChatContainerProps) === null || _props$webChatContain16 === void 0 ? void 0 : _props$webChatContain16.renderingMiddlewareProps
|
|
772
781
|
});
|
|
773
|
-
}, [(_props$
|
|
782
|
+
}, [(_props$webChatContain17 = props.webChatContainerProps) === null || _props$webChatContain17 === void 0 ? void 0 : _props$webChatContain17.renderingMiddlewareProps]);
|
|
774
783
|
useEffect(() => {
|
|
775
784
|
TelemetryHelper.logLoadingEventToAllTelemetry(LogLevel.INFO, {
|
|
776
785
|
Event: TelemetryEvent.UXLiveChatWidgetCompleted,
|
|
@@ -813,7 +822,7 @@ export const LiveChatWidgetStateful = props => {
|
|
|
813
822
|
const webChatProps = initWebChatComposer(props, state, dispatch, facadeChatSDK, endChatRelay);
|
|
814
823
|
const downloadTranscriptProps = createDownloadTranscriptProps(props.downloadTranscriptProps, {
|
|
815
824
|
...(defaultWebChatContainerStatefulProps === null || defaultWebChatContainerStatefulProps === void 0 ? void 0 : defaultWebChatContainerStatefulProps.webChatStyles),
|
|
816
|
-
...((_props$
|
|
825
|
+
...((_props$webChatContain18 = props.webChatContainerProps) === null || _props$webChatContain18 === void 0 ? void 0 : _props$webChatContain18.webChatStyles)
|
|
817
826
|
}, props.webChatContainerProps);
|
|
818
827
|
const livechatProps = {
|
|
819
828
|
...props,
|
|
@@ -839,6 +848,11 @@ export const LiveChatWidgetStateful = props => {
|
|
|
839
848
|
setOcUserAgent(facadeChatSDK.getChatSDK());
|
|
840
849
|
const directLine = ((_livechatProps$webCha = livechatProps.webChatContainerProps) === null || _livechatProps$webCha === void 0 ? void 0 : _livechatProps$webCha.directLine) ?? adapter ?? defaultWebChatContainerStatefulProps.directLine;
|
|
841
850
|
const userID = directLine.getState ? directLine === null || directLine === void 0 ? void 0 : directLine.getState("acs.userId") : "teamsvisitor";
|
|
851
|
+
const styleOptions = React.useMemo(() => ({
|
|
852
|
+
...webChatStyles,
|
|
853
|
+
bubbleBackground,
|
|
854
|
+
bubbleTextColor
|
|
855
|
+
}), [webChatStyles, bubbleBackground, bubbleTextColor]);
|
|
842
856
|
|
|
843
857
|
// WebChat's Composer can only be rendered if a directLine object is defined
|
|
844
858
|
return directLine && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("style", null, `
|
|
@@ -877,11 +891,7 @@ export const LiveChatWidgetStateful = props => {
|
|
|
877
891
|
}`}
|
|
878
892
|
`), /*#__PURE__*/React.createElement(DraggableChatWidget, chatWidgetDraggableConfig, /*#__PURE__*/React.createElement(Composer, _extends({}, webChatProps, {
|
|
879
893
|
userID: userID,
|
|
880
|
-
styleOptions:
|
|
881
|
-
...webChatStyles,
|
|
882
|
-
bubbleBackground: ((_props$webChatContain11 = props.webChatContainerProps) === null || _props$webChatContain11 === void 0 ? void 0 : (_props$webChatContain12 = _props$webChatContain11.webChatStyles) === null || _props$webChatContain12 === void 0 ? void 0 : _props$webChatContain12.bubbleBackground) ?? ((_props$webChatContain13 = props.webChatContainerProps) === null || _props$webChatContain13 === void 0 ? void 0 : (_props$webChatContain14 = _props$webChatContain13.adaptiveCardStyles) === null || _props$webChatContain14 === void 0 ? void 0 : _props$webChatContain14.background) ?? defaultAdaptiveCardStyles.background,
|
|
883
|
-
bubbleTextColor: ((_props$webChatContain15 = props.webChatContainerProps) === null || _props$webChatContain15 === void 0 ? void 0 : (_props$webChatContain16 = _props$webChatContain15.webChatStyles) === null || _props$webChatContain16 === void 0 ? void 0 : _props$webChatContain16.bubbleTextColor) ?? ((_props$webChatContain17 = props.webChatContainerProps) === null || _props$webChatContain17 === void 0 ? void 0 : (_props$webChatContain18 = _props$webChatContain17.adaptiveCardStyles) === null || _props$webChatContain18 === void 0 ? void 0 : _props$webChatContain18.color) ?? defaultAdaptiveCardStyles.color
|
|
884
|
-
},
|
|
894
|
+
styleOptions: styleOptions,
|
|
885
895
|
directLine: directLine
|
|
886
896
|
}), /*#__PURE__*/React.createElement(Stack, {
|
|
887
897
|
id: widgetElementId,
|
|
@@ -912,6 +922,8 @@ export const LiveChatWidgetStateful = props => {
|
|
|
912
922
|
}, livechatProps.callingContainerProps)), !((_livechatProps$contro11 = livechatProps.controlProps) !== null && _livechatProps$contro11 !== void 0 && _livechatProps$contro11.hideWebChatContainer) && shouldShowWebChatContainer(state) && (decodeComponentString((_livechatProps$compon9 = livechatProps.componentOverrides) === null || _livechatProps$compon9 === void 0 ? void 0 : _livechatProps$compon9.webChatContainer) || /*#__PURE__*/React.createElement(WebChatContainerStateful, livechatProps)), !((_livechatProps$contro12 = livechatProps.controlProps) !== null && _livechatProps$contro12 !== void 0 && _livechatProps$contro12.hideConfirmationPane) && shouldShowConfirmationPane(state) && (decodeComponentString((_livechatProps$compon10 = livechatProps.componentOverrides) === null || _livechatProps$compon10 === void 0 ? void 0 : _livechatProps$compon10.confirmationPane) || /*#__PURE__*/React.createElement(ConfirmationPaneStateful, _extends({}, confirmationPaneProps, {
|
|
913
923
|
setPostChatContext: setPostChatContextRelay,
|
|
914
924
|
prepareEndChat: prepareEndChatRelay
|
|
915
|
-
}))), !((_livechatProps$contro13 = livechatProps.controlProps) !== null && _livechatProps$contro13 !== void 0 && _livechatProps$contro13.hidePostChatLoadingPane) && shouldShowPostChatLoadingPane(state) && (decodeComponentString((_livechatProps$compon11 = livechatProps.componentOverrides) === null || _livechatProps$compon11 === void 0 ? void 0 : _livechatProps$compon11.postChatLoadingPane) || /*#__PURE__*/React.createElement(PostChatLoadingPaneStateful, livechatProps.postChatLoadingPaneProps)), shouldShowPostChatSurveyPane(state) && (decodeComponentString((_livechatProps$compon12 = livechatProps.componentOverrides) === null || _livechatProps$compon12 === void 0 ? void 0 : _livechatProps$compon12.postChatSurveyPane) || /*#__PURE__*/React.createElement(PostChatSurveyPaneStateful, _extends({}, livechatProps.postChatSurveyPaneProps, livechatProps.chatSDK
|
|
925
|
+
}))), !((_livechatProps$contro13 = livechatProps.controlProps) !== null && _livechatProps$contro13 !== void 0 && _livechatProps$contro13.hidePostChatLoadingPane) && shouldShowPostChatLoadingPane(state) && (decodeComponentString((_livechatProps$compon11 = livechatProps.componentOverrides) === null || _livechatProps$compon11 === void 0 ? void 0 : _livechatProps$compon11.postChatLoadingPane) || /*#__PURE__*/React.createElement(PostChatLoadingPaneStateful, livechatProps.postChatLoadingPaneProps)), shouldShowPostChatSurveyPane(state) && (decodeComponentString((_livechatProps$compon12 = livechatProps.componentOverrides) === null || _livechatProps$compon12 === void 0 ? void 0 : _livechatProps$compon12.postChatSurveyPane) || /*#__PURE__*/React.createElement(PostChatSurveyPaneStateful, _extends({}, livechatProps.postChatSurveyPaneProps, livechatProps.chatSDK, {
|
|
926
|
+
customerVoiceSurveyCorrelationId: conversationId
|
|
927
|
+
}))), createFooter(livechatProps, state), shouldShowEmailTranscriptPane(state) && (decodeComponentString((_livechatProps$compon13 = livechatProps.componentOverrides) === null || _livechatProps$compon13 === void 0 ? void 0 : _livechatProps$compon13.emailTranscriptPane) || /*#__PURE__*/React.createElement(EmailTranscriptPaneStateful, livechatProps.emailTranscriptPane))))));
|
|
916
928
|
};
|
|
917
929
|
export default LiveChatWidgetStateful;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { LogLevel, TelemetryEvent } from "../../common/telemetry/TelemetryConstants";
|
|
2
2
|
import React, { useEffect } from "react";
|
|
3
3
|
import { createTimer, findAllFocusableElement } from "../../common/utils";
|
|
4
|
-
import DOMPurify from "dompurify";
|
|
5
4
|
import { OutOfOfficeHoursPane } from "@microsoft/omnichannel-chat-components";
|
|
6
5
|
import { TelemetryHelper } from "../../common/telemetry/TelemetryHelper";
|
|
7
6
|
import { defaultGeneralStyleProps } from "./common/defaultStyleProps/defaultgeneralOOOHPaneStyleProps";
|
|
7
|
+
import { detectAndCleanXSS } from "../../common/utils/xssUtils";
|
|
8
8
|
import useChatContextStore from "../../hooks/useChatContextStore";
|
|
9
9
|
let uiTimer;
|
|
10
|
+
const OOOHPaneTitleText = "Thanks for contacting us. You have reached us outside of our operating hours. An agent will respond when we open.";
|
|
10
11
|
export const OutOfOfficeHoursPaneStateful = props => {
|
|
11
12
|
var _props$styleProps;
|
|
12
13
|
useEffect(() => {
|
|
@@ -45,8 +46,28 @@ export const OutOfOfficeHoursPaneStateful = props => {
|
|
|
45
46
|
ElapsedTimeInMilliseconds: uiTimer.milliSecondsElapsed
|
|
46
47
|
});
|
|
47
48
|
}, []);
|
|
49
|
+
|
|
50
|
+
// Enhanced titleText sanitization
|
|
48
51
|
if (controlProps !== null && controlProps !== void 0 && controlProps.titleText) {
|
|
49
|
-
|
|
52
|
+
const {
|
|
53
|
+
cleanText,
|
|
54
|
+
isXSSDetected
|
|
55
|
+
} = detectAndCleanXSS(controlProps.titleText);
|
|
56
|
+
if (!isXSSDetected) {
|
|
57
|
+
// replace with the sanitized text
|
|
58
|
+
controlProps.titleText = cleanText;
|
|
59
|
+
} else {
|
|
60
|
+
TelemetryHelper.logLoadingEventToAllTelemetry(LogLevel.WARN, {
|
|
61
|
+
Event: TelemetryEvent.XSSTextDetected,
|
|
62
|
+
Description: "Potential XSS attempt detected in titleText",
|
|
63
|
+
CustomProperties: {
|
|
64
|
+
originalText: controlProps.titleText.substring(0, 100),
|
|
65
|
+
// Log first 100 chars for analysis
|
|
66
|
+
cleanedText: cleanText.substring(0, 100)
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
controlProps.titleText = OOOHPaneTitleText;
|
|
70
|
+
}
|
|
50
71
|
}
|
|
51
72
|
return /*#__PURE__*/React.createElement(OutOfOfficeHoursPane, {
|
|
52
73
|
componentOverrides: props.componentOverrides,
|
|
@@ -9,13 +9,14 @@ import { defaultGeneralPostChatSurveyPaneStyleProps } from "./common/defaultStyl
|
|
|
9
9
|
import { findAllFocusableElement } from "../../common/utils";
|
|
10
10
|
import useChatContextStore from "../../hooks/useChatContextStore";
|
|
11
11
|
import isValidSurveyUrl from "./common/isValidSurveyUrl";
|
|
12
|
-
const generateSurveyInviteLink = function (surveyInviteLink, isEmbed, locale, compact) {
|
|
13
|
-
let showMultiLingual = arguments.length >
|
|
12
|
+
const generateSurveyInviteLink = function (surveyInviteLink, isEmbed, locale, compact, customerVoiceSurveyCorrelationId) {
|
|
13
|
+
let showMultiLingual = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false;
|
|
14
14
|
const surveyLinkParams = new URLSearchParams({
|
|
15
15
|
embed: isEmbed.toString(),
|
|
16
16
|
compact: (compact ?? true).toString(),
|
|
17
17
|
lang: locale ?? "en-us",
|
|
18
|
-
showmultilingual: (showMultiLingual ?? false).toString()
|
|
18
|
+
showmultilingual: (showMultiLingual ?? false).toString(),
|
|
19
|
+
cvResponsePageRequestId: customerVoiceSurveyCorrelationId
|
|
19
20
|
});
|
|
20
21
|
return `${surveyInviteLink}&${surveyLinkParams.toString()}`;
|
|
21
22
|
};
|
|
@@ -31,9 +32,9 @@ export const PostChatSurveyPaneStateful = props => {
|
|
|
31
32
|
// Bot survey enabled
|
|
32
33
|
state.appStates.postChatParticipantType === ParticipantType.Bot) {
|
|
33
34
|
// Only Bot has engaged
|
|
34
|
-
surveyInviteLink = generateSurveyInviteLink(state.domainStates.postChatContext.botSurveyInviteLink, surveyMode, state.domainStates.postChatContext.botFormsProLocale, props.isCustomerVoiceSurveyCompact ?? true);
|
|
35
|
+
surveyInviteLink = generateSurveyInviteLink(state.domainStates.postChatContext.botSurveyInviteLink, surveyMode, state.domainStates.postChatContext.botFormsProLocale, props.isCustomerVoiceSurveyCompact ?? true, props.customerVoiceSurveyCorrelationId || "");
|
|
35
36
|
} else {
|
|
36
|
-
surveyInviteLink = generateSurveyInviteLink(state.domainStates.postChatContext.surveyInviteLink, surveyMode, state.domainStates.postChatContext.formsProLocale, props.isCustomerVoiceSurveyCompact ?? true);
|
|
37
|
+
surveyInviteLink = generateSurveyInviteLink(state.domainStates.postChatContext.surveyInviteLink, surveyMode, state.domainStates.postChatContext.formsProLocale, props.isCustomerVoiceSurveyCompact ?? true, props.customerVoiceSurveyCorrelationId || "");
|
|
37
38
|
}
|
|
38
39
|
if (props.copilotSurveyContext) {
|
|
39
40
|
surveyInviteLink = `${surveyInviteLink}&mcs_additionalcontext=${JSON.stringify(props.copilotSurveyContext)}`;
|
|
@@ -96,6 +97,14 @@ export const PostChatSurveyPaneStateful = props => {
|
|
|
96
97
|
message: "Customer Voice form response error."
|
|
97
98
|
}
|
|
98
99
|
});
|
|
100
|
+
} else if (typeof data === "string" && data.startsWith(CustomerVoiceEvents.FormsError)) {
|
|
101
|
+
TelemetryHelper.logActionEventToAllTelemetry(LogLevel.ERROR, {
|
|
102
|
+
Event: TelemetryEvent.CustomerVoiceFormsError,
|
|
103
|
+
Description: "Customer Voice failed to load with forms error.",
|
|
104
|
+
ExceptionDetails: {
|
|
105
|
+
message: `Customer Voice forms error details: ${data}`
|
|
106
|
+
}
|
|
107
|
+
});
|
|
99
108
|
}
|
|
100
109
|
});
|
|
101
110
|
}, []);
|
|
@@ -3,4 +3,5 @@ export let CustomerVoiceEvents;
|
|
|
3
3
|
CustomerVoiceEvents["ResponsePageLoaded"] = "ResponsePageLoaded";
|
|
4
4
|
CustomerVoiceEvents["FormResponseSubmitted"] = "FormResponseSubmitted";
|
|
5
5
|
CustomerVoiceEvents["FormResponseError"] = "FormResponseError";
|
|
6
|
+
CustomerVoiceEvents["FormsError"] = "FormsError";
|
|
6
7
|
})(CustomerVoiceEvents || (CustomerVoiceEvents = {}));
|
|
@@ -72,4 +72,5 @@ export declare class FacadeChatSDK {
|
|
|
72
72
|
getVoiceVideoCalling(params?: VoiceVideoCallingOptionalParams): Promise<GetVoiceVideoCallingResponse>;
|
|
73
73
|
getPostChatSurveyContext(): Promise<PostChatContext>;
|
|
74
74
|
getAgentAvailability(optionalParams?: GetAgentAvailabilityOptionalParams): Promise<GetAgentAvailabilityResponse>;
|
|
75
|
+
getReconnectableChats(reconnectableChatsParams?: any): Promise<any>;
|
|
75
76
|
}
|
|
@@ -94,6 +94,8 @@ export declare enum TelemetryEvent {
|
|
|
94
94
|
DisconnectEndChatSDKCallFailed = "DisconnectEndChatSDKCallFailed",
|
|
95
95
|
GetChatReconnectContextSDKCallStarted = "GetChatReconnectContextSDKCallStarted",
|
|
96
96
|
GetChatReconnectContextSDKCallFailed = "GetChatReconnectContextSDKCallFailed",
|
|
97
|
+
CheckContactIdError = "checkContactIdError",
|
|
98
|
+
GetChatReconnectContextSDKCallSucceeded = "GetChatReconnectContextSDKCallSucceeded",
|
|
97
99
|
ParseAdaptiveCardFailed = "ParseAdaptiveCardFailed",
|
|
98
100
|
ClientDataStoreProviderFailed = "ClientDataStoreProviderFailed",
|
|
99
101
|
InMemoryDataStoreFailed = "InMemoryDataStoreFailed",
|
|
@@ -161,6 +163,7 @@ export declare enum TelemetryEvent {
|
|
|
161
163
|
CustomerVoiceResponsePageLoaded = "CustomerVoiceResponsePageLoaded",
|
|
162
164
|
CustomerVoiceFormResponseSubmitted = "CustomerVoiceFormResponseSubmitted",
|
|
163
165
|
CustomerVoiceFormResponseError = "CustomerVoiceFormResponseError",
|
|
166
|
+
CustomerVoiceFormsError = "CustomerVoiceFormsError",
|
|
164
167
|
BotAuthActivityEmptySasUrl = "BotAuthActivityEmptySasUrl",
|
|
165
168
|
SetBotAuthProviderFetchConfig = "SetBotAuthProviderFetchConfig",
|
|
166
169
|
SetBotAuthProviderHideCard = "SetBotAuthProviderHideCard",
|
|
@@ -238,6 +241,7 @@ export declare enum TelemetryEvent {
|
|
|
238
241
|
UXNotificationPaneCompleted = "UXNotificationPaneCompleted",
|
|
239
242
|
UXOutOfOfficeHoursPaneStart = "UXOutOfOfficeHoursPaneStart",
|
|
240
243
|
UXOutOfOfficeHoursPaneCompleted = "UXOutOfOfficeHoursPaneCompleted",
|
|
244
|
+
XSSTextDetected = "XSSTextDetected",
|
|
241
245
|
UXPostChatLoadingPaneStart = "UXPostChatLoadingPaneStart",
|
|
242
246
|
UXPostChatLoadingPaneCompleted = "UXPostChatLoadingPaneCompleted",
|
|
243
247
|
UXPrechatPaneStart = "UXPrechatPaneStart",
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detects potential Cross-Site Scripting (XSS) attacks in text input and sanitizes the content.
|
|
3
|
+
*
|
|
4
|
+
* This function performs comprehensive XSS detection using pattern matching for common attack vectors
|
|
5
|
+
* and then sanitizes the input using DOMPurify with strict configuration. It's designed to protect
|
|
6
|
+
* against various XSS techniques including script injection, event handler injection, style-based
|
|
7
|
+
* attacks, and encoded payloads.
|
|
8
|
+
*
|
|
9
|
+
* Security patterns detected:
|
|
10
|
+
* - JavaScript protocol URLs (javascript:)
|
|
11
|
+
* - HTML event handlers (onmouseover, onclick, etc.)
|
|
12
|
+
* - Script tags (<script>)
|
|
13
|
+
* - CSS expression() functions
|
|
14
|
+
* - CSS url() functions
|
|
15
|
+
* - Position-based CSS attacks (position: fixed/absolute)
|
|
16
|
+
* - VBScript protocol URLs
|
|
17
|
+
* - Data URLs with HTML content
|
|
18
|
+
* - Fragment identifiers with escaped quotes
|
|
19
|
+
* - HTML entity-encoded angle brackets
|
|
20
|
+
*
|
|
21
|
+
* @param text - The input text to be analyzed and sanitized
|
|
22
|
+
* @returns An object containing:
|
|
23
|
+
* - cleanText: The sanitized version of the input text with all HTML tags and attributes removed
|
|
24
|
+
* - isXSSDetected: Boolean flag indicating whether potential XSS patterns were found in the original text
|
|
25
|
+
*/
|
|
26
|
+
export declare const detectAndCleanXSS: (text: string) => {
|
|
27
|
+
cleanText: string;
|
|
28
|
+
isXSSDetected: boolean;
|
|
29
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React, { Component } from 'react';
|
|
2
|
+
interface ErrorBoundaryProps {
|
|
3
|
+
children: React.ReactNode | (() => React.ReactNode);
|
|
4
|
+
onError?: (error: Error) => void;
|
|
5
|
+
}
|
|
6
|
+
interface ErrorBoundaryState {
|
|
7
|
+
hasError: boolean;
|
|
8
|
+
}
|
|
9
|
+
declare class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
|
10
|
+
constructor(props: ErrorBoundaryProps);
|
|
11
|
+
componentDidCatch(error: Error): void;
|
|
12
|
+
render(): false | React.JSX.Element;
|
|
13
|
+
}
|
|
14
|
+
export default ErrorBoundary;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { FacadeChatSDK } from "../../../common/facades/FacadeChatSDK";
|
|
2
2
|
export declare const isPostChatSurveyEnabled: (facadeChatSDK: FacadeChatSDK) => Promise<boolean>;
|
|
3
|
-
export declare const isPersistentChatEnabled: (conversationMode: string | undefined) =>
|
|
3
|
+
export declare const isPersistentChatEnabled: (conversationMode: string | undefined) => boolean;
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import { FacadeChatSDK } from "../../../common/facades/FacadeChatSDK";
|
|
2
|
+
export declare const shouldSetPreChatIfPersistentChat: (facadeChatSDK: FacadeChatSDK, conversationMode: string, showPreChat: boolean) => Promise<boolean>;
|
|
@@ -4,3 +4,4 @@ import { ILiveChatWidgetAction } from "../../../contexts/common/ILiveChatWidgetA
|
|
|
4
4
|
import { ILiveChatWidgetProps } from "../interfaces/ILiveChatWidgetProps";
|
|
5
5
|
export declare const handleStartChatError: (dispatch: Dispatch<ILiveChatWidgetAction>, facadeChatSDK: FacadeChatSDK, props: ILiveChatWidgetProps | undefined, ex: any, isStartChatSuccessful: boolean) => void;
|
|
6
6
|
export declare const logWidgetLoadComplete: (additionalMessage?: string) => void;
|
|
7
|
+
export declare const logWidgetLoadWithUnexpectedError: (ex: any) => void;
|
|
@@ -2,4 +2,5 @@ import { IPostChatSurveyPaneProps } from "@microsoft/omnichannel-chat-components
|
|
|
2
2
|
export interface IPostChatSurveyPaneStatefulProps extends IPostChatSurveyPaneProps {
|
|
3
3
|
isCustomerVoiceSurveyCompact?: boolean;
|
|
4
4
|
copilotSurveyContext?: Record<string, string>;
|
|
5
|
+
customerVoiceSurveyCorrelationId?: string;
|
|
5
6
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@microsoft/omnichannel-chat-widget",
|
|
3
|
-
"version": "1.8.1-main.
|
|
3
|
+
"version": "1.8.1-main.5ac9acf",
|
|
4
4
|
"description": "Microsoft Omnichannel Chat Widget",
|
|
5
5
|
"main": "lib/cjs/index.js",
|
|
6
6
|
"types": "lib/types/index.d.ts",
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
"@azure/core-tracing": "^1.2.0",
|
|
88
88
|
"@microsoft/applicationinsights-web": "^3.3.6",
|
|
89
89
|
"@microsoft/omnichannel-chat-components": "1.1.12",
|
|
90
|
-
"@microsoft/omnichannel-chat-sdk": "^1.11.
|
|
90
|
+
"@microsoft/omnichannel-chat-sdk": "^1.11.2",
|
|
91
91
|
"@opentelemetry/api": "^1.9.0",
|
|
92
92
|
"abort-controller": "^3",
|
|
93
93
|
"abort-controller-es5": "^2.0.1",
|