@microsoft/omnichannel-chat-widget 1.7.8-main.d38af40 → 1.7.8-main.d71f599
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 +15 -4
- package/lib/cjs/common/telemetry/TelemetryConstants.js +4 -0
- package/lib/cjs/components/chatbuttonstateful/ChatButtonStateful.js +4 -5
- package/lib/cjs/components/headerstateful/HeaderStateful.js +3 -5
- package/lib/cjs/components/livechatwidget/common/chatDisconnectHelper.js +3 -1
- package/lib/cjs/components/livechatwidget/common/reconnectChatHelper.js +0 -5
- package/lib/cjs/components/livechatwidget/common/startChat.js +2 -23
- package/lib/cjs/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +3 -3
- package/lib/cjs/components/ooohpanestateful/OOOHPaneStateful.js +6 -4
- package/lib/cjs/components/webchatcontainerstateful/WebChatContainerStateful.js +4 -3
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/timestamps/DeliveredTimestamp.js +4 -0
- package/lib/cjs/contexts/common/LiveChatWidgetContextInitialState.js +14 -2
- package/lib/cjs/firstresponselatency/FirstMessageTrackerFromBot.js +118 -0
- package/lib/cjs/firstresponselatency/FirstResponseLatencyTracker.js +32 -5
- package/lib/cjs/firstresponselatency/util.js +15 -2
- package/lib/esm/common/facades/FacadeChatSDK.js +15 -4
- package/lib/esm/common/telemetry/TelemetryConstants.js +4 -0
- package/lib/esm/components/chatbuttonstateful/ChatButtonStateful.js +4 -5
- package/lib/esm/components/headerstateful/HeaderStateful.js +3 -5
- package/lib/esm/components/livechatwidget/common/chatDisconnectHelper.js +3 -1
- package/lib/esm/components/livechatwidget/common/reconnectChatHelper.js +1 -6
- package/lib/esm/components/livechatwidget/common/startChat.js +3 -24
- package/lib/esm/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +3 -3
- package/lib/esm/components/ooohpanestateful/OOOHPaneStateful.js +6 -4
- package/lib/esm/components/webchatcontainerstateful/WebChatContainerStateful.js +4 -3
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/timestamps/DeliveredTimestamp.js +4 -0
- package/lib/esm/contexts/common/LiveChatWidgetContextInitialState.js +14 -2
- package/lib/esm/firstresponselatency/FirstMessageTrackerFromBot.js +112 -0
- package/lib/esm/firstresponselatency/FirstResponseLatencyTracker.js +33 -6
- package/lib/esm/firstresponselatency/util.js +12 -0
- package/lib/types/common/facades/FacadeChatSDK.d.ts +1 -0
- package/lib/types/common/telemetry/TelemetryConstants.d.ts +5 -1
- package/lib/types/firstresponselatency/FirstMessageTrackerFromBot.d.ts +1 -0
- package/lib/types/firstresponselatency/FirstResponseLatencyTracker.d.ts +5 -0
- package/lib/types/firstresponselatency/util.d.ts +2 -1
- package/package.json +13 -3
|
@@ -142,9 +142,20 @@ export class FacadeChatSDK {
|
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
|
+
async corroborateTokenIsSet(chatSDK) {
|
|
146
|
+
var _chatSDK$chatSDKConfi;
|
|
147
|
+
// if getAuthToken is not set, it's because handleAuthentication hasnt being called
|
|
148
|
+
// so we need to call it
|
|
149
|
+
if (this.isAuthenticated && (chatSDK === null || chatSDK === void 0 ? void 0 : (_chatSDK$chatSDKConfi = chatSDK.chatSDKConfig) === null || _chatSDK$chatSDKConfi === void 0 ? void 0 : _chatSDK$chatSDKConfi.getAuthToken) === undefined) {
|
|
150
|
+
handleAuthentication(this.chatSDK, this.chatConfig, this.getAuthToken);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
145
153
|
async tokenRing() {
|
|
146
154
|
var _this$chatSDK$chatSDK;
|
|
147
155
|
if (this.disableReauthentication === true) {
|
|
156
|
+
// Since we are not validating the token anymore, we at least need to check if the token is set
|
|
157
|
+
// no need to validate anything other that the token is set
|
|
158
|
+
await this.corroborateTokenIsSet(this.chatSDK);
|
|
148
159
|
// facade feature is disabled, so we are bypassing the re authentication and let it fail.
|
|
149
160
|
return {
|
|
150
161
|
result: true,
|
|
@@ -188,7 +199,7 @@ export class FacadeChatSDK {
|
|
|
188
199
|
this.expiration = 0;
|
|
189
200
|
try {
|
|
190
201
|
const ring = await handleAuthentication(this.chatSDK, this.chatConfig, this.getAuthToken);
|
|
191
|
-
if (ring.result === true && ring.token) {
|
|
202
|
+
if ((ring === null || ring === void 0 ? void 0 : ring.result) === true && ring !== null && ring !== void 0 && ring.token) {
|
|
192
203
|
await this.setToken(ring.token);
|
|
193
204
|
TelemetryHelper.logFacadeChatSDKEvent(LogLevel.INFO, {
|
|
194
205
|
Event: TelemetryEvent.NewTokenSuccess,
|
|
@@ -205,12 +216,12 @@ export class FacadeChatSDK {
|
|
|
205
216
|
var _ring$error, _ring$error2;
|
|
206
217
|
TelemetryHelper.logFacadeChatSDKEvent(LogLevel.ERROR, {
|
|
207
218
|
Event: TelemetryEvent.NewTokenFailed,
|
|
208
|
-
Description: (_ring$error = ring.error) === null || _ring$error === void 0 ? void 0 : _ring$error.message,
|
|
209
|
-
ExceptionDetails: ring.error
|
|
219
|
+
Description: ring === null || ring === void 0 ? void 0 : (_ring$error = ring.error) === null || _ring$error === void 0 ? void 0 : _ring$error.message,
|
|
220
|
+
ExceptionDetails: ring === null || ring === void 0 ? void 0 : ring.error
|
|
210
221
|
});
|
|
211
222
|
return {
|
|
212
223
|
result: false,
|
|
213
|
-
message: ((_ring$error2 = ring.error) === null || _ring$error2 === void 0 ? void 0 : _ring$error2.message) || "Failed to get token"
|
|
224
|
+
message: (ring === null || ring === void 0 ? void 0 : (_ring$error2 = ring.error) === null || _ring$error2 === void 0 ? void 0 : _ring$error2.message) || "Failed to get token"
|
|
214
225
|
};
|
|
215
226
|
}
|
|
216
227
|
} catch (e) {
|
|
@@ -61,6 +61,8 @@ export let BroadcastEvent;
|
|
|
61
61
|
BroadcastEvent["ContactIdNotFound"] = "ContactIdNotFound";
|
|
62
62
|
BroadcastEvent["SyncMinimize"] = "SyncMinimize";
|
|
63
63
|
BroadcastEvent["OnWidgetError"] = "OnWidgetError";
|
|
64
|
+
BroadcastEvent["FMLTrackingCompletedAck"] = "FMLTrackingCompletedAck";
|
|
65
|
+
BroadcastEvent["FMLTrackingCompleted"] = "FMLTrackingCompleted";
|
|
64
66
|
})(BroadcastEvent || (BroadcastEvent = {}));
|
|
65
67
|
export let TelemetryEvent;
|
|
66
68
|
(function (TelemetryEvent) {
|
|
@@ -200,6 +202,8 @@ export let TelemetryEvent;
|
|
|
200
202
|
TelemetryEvent["MessageSent"] = "MessageSent";
|
|
201
203
|
TelemetryEvent["MessageReceived"] = "MessageReceived";
|
|
202
204
|
TelemetryEvent["MessageLapTrack"] = "MessageLapTrack";
|
|
205
|
+
TelemetryEvent["BotFirstMessageLapTrack"] = "BotFirstMessageLapTrack";
|
|
206
|
+
TelemetryEvent["BotFirstMessageLapTrackError"] = "BotFirstMessageLapTrackError";
|
|
203
207
|
TelemetryEvent["MessageStartLapTrackError"] = "MessageStartLapTrackError";
|
|
204
208
|
TelemetryEvent["MessageStopLapTrackError"] = "MessageStopLapTrackError";
|
|
205
209
|
TelemetryEvent["SystemMessageReceived"] = "SystemMessageReceived";
|
|
@@ -11,7 +11,7 @@ import { defaultOutOfOfficeChatButtonStyleProps } from "./common/styleProps/defa
|
|
|
11
11
|
import useChatContextStore from "../../hooks/useChatContextStore";
|
|
12
12
|
let uiTimer;
|
|
13
13
|
export const ChatButtonStateful = props => {
|
|
14
|
-
var
|
|
14
|
+
var _buttonProps$controlP, _props$buttonProps, _props$buttonProps$co, _props$buttonProps2, _props$buttonProps2$c, _props$buttonProps3, _props$buttonProps3$c;
|
|
15
15
|
// this is to ensure the telemetry is set only once and start the load timer
|
|
16
16
|
useEffect(() => {
|
|
17
17
|
uiTimer = createTimer();
|
|
@@ -28,7 +28,8 @@ export const ChatButtonStateful = props => {
|
|
|
28
28
|
startChat
|
|
29
29
|
} = props;
|
|
30
30
|
//Setting OutOfOperatingHours Flag
|
|
31
|
-
|
|
31
|
+
//Setting OutOfOperatingHours Flag - to string conversion to normalize the value (could be boolean from other states or string directly from config)
|
|
32
|
+
const [outOfOperatingHours, setOutOfOperatingHours] = useState(state.appStates.outsideOperatingHours);
|
|
32
33
|
const ref = useRef(() => {
|
|
33
34
|
return;
|
|
34
35
|
});
|
|
@@ -87,9 +88,7 @@ export const ChatButtonStateful = props => {
|
|
|
87
88
|
...(outOfOfficeButtonProps === null || outOfOfficeButtonProps === void 0 ? void 0 : outOfOfficeButtonProps.controlProps)
|
|
88
89
|
};
|
|
89
90
|
useEffect(() => {
|
|
90
|
-
|
|
91
|
-
setOutOfOperatingHours(true);
|
|
92
|
-
}
|
|
91
|
+
setOutOfOperatingHours(state.appStates.outsideOperatingHours);
|
|
93
92
|
TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
|
|
94
93
|
Event: TelemetryEvent.LCWChatButtonShow,
|
|
95
94
|
ElapsedTimeInMilliseconds: TelemetryTimers.LcwLoadToChatButtonTimer.milliSecondsElapsed
|
|
@@ -12,7 +12,7 @@ import useChatAdapterStore from "../../hooks/useChatAdapterStore";
|
|
|
12
12
|
import useChatContextStore from "../../hooks/useChatContextStore";
|
|
13
13
|
let uiTimer;
|
|
14
14
|
export const HeaderStateful = props => {
|
|
15
|
-
var _state$domainStates
|
|
15
|
+
var _state$domainStates, _headerProps$controlP, _headerProps$controlP2, _headerProps$controlP3, _outOfOfficeHeaderPro, _state$domainStates3;
|
|
16
16
|
useEffect(() => {
|
|
17
17
|
uiTimer = createTimer();
|
|
18
18
|
TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
|
|
@@ -28,7 +28,7 @@ export const HeaderStateful = props => {
|
|
|
28
28
|
endChat
|
|
29
29
|
} = props;
|
|
30
30
|
//Setting OutOfOperatingHours Flag
|
|
31
|
-
const [outOfOperatingHours, setOutOfOperatingHours] = useState(
|
|
31
|
+
const [outOfOperatingHours, setOutOfOperatingHours] = useState(state.appStates.outsideOperatingHours);
|
|
32
32
|
const outOfOfficeStyleProps = Object.assign({}, defaultOutOfOfficeHeaderStyleProps, outOfOfficeHeaderProps === null || outOfOfficeHeaderProps === void 0 ? void 0 : outOfOfficeHeaderProps.styleProps);
|
|
33
33
|
|
|
34
34
|
// For some reason state object is not getting updated values in this component
|
|
@@ -100,9 +100,7 @@ export const HeaderStateful = props => {
|
|
|
100
100
|
hideCloseButton: state.appStates.conversationState === ConversationState.OutOfOffice || (outOfOfficeHeaderProps === null || outOfOfficeHeaderProps === void 0 ? void 0 : (_outOfOfficeHeaderPro = outOfOfficeHeaderProps.controlProps) === null || _outOfOfficeHeaderPro === void 0 ? void 0 : _outOfOfficeHeaderPro.hideCloseButton)
|
|
101
101
|
};
|
|
102
102
|
useEffect(() => {
|
|
103
|
-
|
|
104
|
-
setOutOfOperatingHours(true);
|
|
105
|
-
}
|
|
103
|
+
setOutOfOperatingHours(state.appStates.outsideOperatingHours);
|
|
106
104
|
}, []);
|
|
107
105
|
useEffect(() => {
|
|
108
106
|
var _state$domainStates2;
|
|
@@ -6,7 +6,7 @@ import { defaultMiddlewareLocalizedTexts } from "../../webchatcontainerstateful/
|
|
|
6
6
|
|
|
7
7
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8
8
|
const handleChatDisconnect = (props, state, setWebChatStyles) => {
|
|
9
|
-
var _state$appStates, _state$domainStates, _state$domainStates$m, _props$webChatContain, _props$webChatContain2;
|
|
9
|
+
var _state$appStates, _state$domainStates, _state$domainStates$m, _props$webChatContain, _props$webChatContain2, _props$webChatContain3, _props$webChatContain4;
|
|
10
10
|
const chatDisconnectState = state === null || state === void 0 ? void 0 : (_state$appStates = state.appStates) === null || _state$appStates === void 0 ? void 0 : _state$appStates.chatDisconnectEventReceived;
|
|
11
11
|
const chatDisconnectMessage = (state === null || state === void 0 ? void 0 : (_state$domainStates = state.domainStates) === null || _state$domainStates === void 0 ? void 0 : (_state$domainStates$m = _state$domainStates.middlewareLocalizedTexts) === null || _state$domainStates$m === void 0 ? void 0 : _state$domainStates$m.MIDDLEWARE_BANNER_CHAT_DISCONNECT) ?? defaultMiddlewareLocalizedTexts.MIDDLEWARE_BANNER_CHAT_DISCONNECT;
|
|
12
12
|
const hideSendBoxOnConversationEnd = props === null || props === void 0 ? void 0 : (_props$webChatContain = props.webChatContainerProps) === null || _props$webChatContain === void 0 ? void 0 : (_props$webChatContain2 = _props$webChatContain.renderingMiddlewareProps) === null || _props$webChatContain2 === void 0 ? void 0 : _props$webChatContain2.hideSendboxOnConversationEnd;
|
|
@@ -27,6 +27,8 @@ const handleChatDisconnect = (props, state, setWebChatStyles) => {
|
|
|
27
27
|
});
|
|
28
28
|
break;
|
|
29
29
|
case false:
|
|
30
|
+
// this means customer on purpose wants to hide the send box, we should not override it
|
|
31
|
+
if ((props === null || props === void 0 ? void 0 : (_props$webChatContain3 = props.webChatContainerProps) === null || _props$webChatContain3 === void 0 ? void 0 : (_props$webChatContain4 = _props$webChatContain3.webChatStyles) === null || _props$webChatContain4 === void 0 ? void 0 : _props$webChatContain4.hideSendBox) === true) return;
|
|
30
32
|
if (hideSendBoxOnConversationEnd !== false) {
|
|
31
33
|
setWebChatStyles(styles => {
|
|
32
34
|
return {
|
|
@@ -2,7 +2,7 @@ import "regenerator-runtime/runtime";
|
|
|
2
2
|
import { BroadcastEvent, LogLevel, TelemetryEvent } from "../../../common/telemetry/TelemetryConstants";
|
|
3
3
|
import { ConversationMode, WidgetLoadCustomErrorString } from "../../../common/Constants";
|
|
4
4
|
import { checkContactIdError, isNullOrEmptyString, isNullOrUndefined } from "../../../common/utils";
|
|
5
|
-
import {
|
|
5
|
+
import { removeAuthTokenProvider } from "./authHelper";
|
|
6
6
|
import { BroadcastService } from "@microsoft/omnichannel-chat-components";
|
|
7
7
|
import { ConversationState } from "../../../contexts/common/ConversationState";
|
|
8
8
|
import { LiveChatWidgetActionType } from "../../../contexts/common/LiveChatWidgetActionType";
|
|
@@ -61,11 +61,6 @@ const getChatReconnectContext = async (facadeChatSDK, chatConfig, props, isAuthe
|
|
|
61
61
|
const chatReconnectOptionalParams = {
|
|
62
62
|
reconnectId: (_props$reconnectChatP4 = props.reconnectChatPaneProps) === null || _props$reconnectChatP4 === void 0 ? void 0 : _props$reconnectChatP4.reconnectId
|
|
63
63
|
};
|
|
64
|
-
// Get auth token for getting chat reconnect context
|
|
65
|
-
if (isAuthenticatedChat) {
|
|
66
|
-
// handle authentication will throw error if auth token is not available, so no need to check for response
|
|
67
|
-
await handleAuthentication(facadeChatSDK.getChatSDK(), chatConfig, props.getAuthToken);
|
|
68
|
-
}
|
|
69
64
|
const reconnectChatContext = await (facadeChatSDK === null || facadeChatSDK === void 0 ? void 0 : facadeChatSDK.getChatReconnectContext(chatReconnectOptionalParams));
|
|
70
65
|
if (isAuthenticatedChat) {
|
|
71
66
|
// remove auth token after reconnectId is fetched
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { BroadcastEvent, LogLevel, TelemetryEvent } from "../../../common/telemetry/TelemetryConstants";
|
|
2
|
-
import { Constants, LiveWorkItemState,
|
|
2
|
+
import { Constants, LiveWorkItemState, WidgetLoadTelemetryMessage } from "../../../common/Constants";
|
|
3
3
|
import { checkContactIdError, createTimer, getConversationDetailsCall, getStateFromCache, getWidgetCacheIdfromProps, isNullOrEmptyString, isNullOrUndefined, isUndefinedOrEmpty } from "../../../common/utils";
|
|
4
|
-
import { getAuthClientFunction, handleAuthentication } from "./authHelper";
|
|
5
4
|
import { handleChatReconnect, isPersistentEnabled, isReconnectEnabled } from "./reconnectChatHelper";
|
|
6
5
|
import { handleStartChatError, logWidgetLoadComplete } from "./startChatErrorHandler";
|
|
7
6
|
import { ActivityStreamHandler } from "./ActivityStreamHandler";
|
|
@@ -13,6 +12,7 @@ import { TelemetryTimers } from "../../../common/telemetry/TelemetryManager";
|
|
|
13
12
|
import { chatSDKStateCleanUp } from "./endChat";
|
|
14
13
|
import { createAdapter } from "./createAdapter";
|
|
15
14
|
import { createOnNewAdapterActivityHandler } from "../../../plugins/newMessageEventHandler";
|
|
15
|
+
import { createTrackingForFirstMessage } from "../../../firstresponselatency/FirstMessageTrackerFromBot";
|
|
16
16
|
import { isPersistentChatEnabled } from "./liveChatConfigUtils";
|
|
17
17
|
import { setPostChatContextAndLoadSurvey } from "./setPostChatContextAndLoadSurvey";
|
|
18
18
|
import { shouldSetPreChatIfPersistentChat } from "./persistentChatHelper";
|
|
@@ -25,20 +25,6 @@ let widgetInstanceId;
|
|
|
25
25
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
26
26
|
let popoutWidgetInstanceId;
|
|
27
27
|
|
|
28
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
29
|
-
const setAuthenticationIfApplicable = async (props, facadeChatSDK) => {
|
|
30
|
-
const chatConfig = props === null || props === void 0 ? void 0 : props.chatConfig;
|
|
31
|
-
const getAuthToken = props === null || props === void 0 ? void 0 : props.getAuthToken;
|
|
32
|
-
const authClientFunction = getAuthClientFunction(chatConfig);
|
|
33
|
-
if (getAuthToken && authClientFunction) {
|
|
34
|
-
// set auth token to chat sdk before start chat
|
|
35
|
-
const authSuccess = await handleAuthentication(facadeChatSDK.getChatSDK(), chatConfig, getAuthToken);
|
|
36
|
-
if (!authSuccess.result) {
|
|
37
|
-
throw new Error(WidgetLoadCustomErrorString.AuthenticationFailedErrorString);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
|
|
42
28
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
43
29
|
const prepareStartChat = async (props, facadeChatSDK, state, dispatch, setAdapter) => {
|
|
44
30
|
optionalParams = {}; //Resetting to ensure no stale values
|
|
@@ -66,11 +52,6 @@ const prepareStartChat = async (props, facadeChatSDK, state, dispatch, setAdapte
|
|
|
66
52
|
const isProactiveChat = state.appStates.conversationState === ConversationState.ProactiveChat;
|
|
67
53
|
const isPreChatEnabledInProactiveChat = state.appStates.proactiveChatStates.proactiveChatEnablePrechat;
|
|
68
54
|
|
|
69
|
-
// Setting auth settings to OC API to retrieve existing persistent chat session before start chat if any
|
|
70
|
-
if (isPersistentEnabled(props.chatConfig)) {
|
|
71
|
-
await setAuthenticationIfApplicable(props, facadeChatSDK);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
55
|
//Setting PreChat and intiate chat
|
|
75
56
|
await setPreChatAndInitiateChat(facadeChatSDK, dispatch, setAdapter, isProactiveChat, isPreChatEnabledInProactiveChat, state, props);
|
|
76
57
|
};
|
|
@@ -145,6 +126,7 @@ const setPreChatAndInitiateChat = async (facadeChatSDK, dispatch, setAdapter, is
|
|
|
145
126
|
const optionalParams = {
|
|
146
127
|
isProactiveChat
|
|
147
128
|
};
|
|
129
|
+
createTrackingForFirstMessage();
|
|
148
130
|
await initStartChat(facadeChatSDK, dispatch, setAdapter, state, props, optionalParams);
|
|
149
131
|
};
|
|
150
132
|
|
|
@@ -172,9 +154,6 @@ const initStartChat = async (facadeChatSDK, dispatch, setAdapter, state, props,
|
|
|
172
154
|
Description: "Widget loading started"
|
|
173
155
|
});
|
|
174
156
|
|
|
175
|
-
// Auth token retrieval needs to happen during start chat to support pop-out chat
|
|
176
|
-
await setAuthenticationIfApplicable(props, facadeChatSDK);
|
|
177
|
-
|
|
178
157
|
//Check if chat retrieved from cache
|
|
179
158
|
if (persistedState || params !== null && params !== void 0 && params.liveChatContext) {
|
|
180
159
|
var _persistedState$domai, _persistedState$domai2, _persistedState$domai3, _persistedState$domai4, _persistedState$domai5;
|
|
@@ -56,7 +56,7 @@ import useChatContextStore from "../../../hooks/useChatContextStore";
|
|
|
56
56
|
import useFacadeSDKStore from "../../../hooks/useFacadeChatSDKStore";
|
|
57
57
|
let uiTimer;
|
|
58
58
|
export const LiveChatWidgetStateful = props => {
|
|
59
|
-
var _props$webChatContain, _props$styleProps, _props$webChatContain2, _props$webChatContain3, _props$controlProps, _props$controlProps3, _state$appStates7, _props$webChatContain7, _state$appStates14, _props$webChatContain9, _props$webChatContain10, _props$controlProps12, _props$draggableChatW, _props$draggableChatW2, _props$draggableChatW3, _props$draggableChatW4, _props$draggableChatW5, _livechatProps$webCha, _props$webChatContain11, _props$webChatContain12, _props$webChatContain13, _props$webChatContain14, _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;
|
|
59
|
+
var _props$webChatContain, _props$styleProps, _props$webChatContain2, _props$webChatContain3, _props$controlProps, _props$controlProps3, _state$appStates7, _props$webChatContain7, _state$appStates14, _props$webChatContain9, _props$webChatContain10, _props$controlProps12, _props$draggableChatW, _props$draggableChatW2, _props$draggableChatW3, _props$draggableChatW4, _props$draggableChatW5, _livechatProps$webCha, _props$webChatContain11, _props$webChatContain12, _props$webChatContain13, _props$webChatContain14, _props$webChatContain15, _props$webChatContain16, _props$webChatContain17, _props$webChatContain18, _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
60
|
useEffect(() => {
|
|
61
61
|
uiTimer = createTimer();
|
|
62
62
|
TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
|
|
@@ -874,8 +874,8 @@ export const LiveChatWidgetStateful = props => {
|
|
|
874
874
|
userID: userID,
|
|
875
875
|
styleOptions: {
|
|
876
876
|
...webChatStyles,
|
|
877
|
-
bubbleBackground: ((_props$webChatContain11 = props.webChatContainerProps) === null || _props$webChatContain11 === void 0 ? void 0 : (_props$webChatContain12 = _props$webChatContain11.
|
|
878
|
-
bubbleTextColor: ((_props$
|
|
877
|
+
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,
|
|
878
|
+
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
|
|
879
879
|
},
|
|
880
880
|
directLine: directLine
|
|
881
881
|
}), /*#__PURE__*/React.createElement(Stack, {
|
|
@@ -1,11 +1,11 @@
|
|
|
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";
|
|
4
5
|
import { OutOfOfficeHoursPane } from "@microsoft/omnichannel-chat-components";
|
|
5
6
|
import { TelemetryHelper } from "../../common/telemetry/TelemetryHelper";
|
|
6
7
|
import { defaultGeneralStyleProps } from "./common/defaultStyleProps/defaultgeneralOOOHPaneStyleProps";
|
|
7
8
|
import useChatContextStore from "../../hooks/useChatContextStore";
|
|
8
|
-
import DOMPurify from "dompurify";
|
|
9
9
|
let uiTimer;
|
|
10
10
|
export const OutOfOfficeHoursPaneStateful = props => {
|
|
11
11
|
var _props$styleProps;
|
|
@@ -29,9 +29,11 @@ export const OutOfOfficeHoursPaneStateful = props => {
|
|
|
29
29
|
|
|
30
30
|
// Move focus to the first button
|
|
31
31
|
useEffect(() => {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
firstElement[0]
|
|
32
|
+
if (state.domainStates.widgetElementId !== null && state.domainStates.widgetElementId !== undefined && state.domainStates.widgetElementId.trim() !== "") {
|
|
33
|
+
const firstElement = findAllFocusableElement(`#${state.domainStates.widgetElementId}`);
|
|
34
|
+
if (firstElement && firstElement[0]) {
|
|
35
|
+
firstElement[0].focus();
|
|
36
|
+
}
|
|
35
37
|
}
|
|
36
38
|
TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
|
|
37
39
|
Event: TelemetryEvent.OutOfOfficePaneLoaded
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
|
|
3
|
+
import { Constants, HtmlAttributeNames, HtmlClassNames } from "../../common/Constants";
|
|
3
4
|
import { Stack } from "@fluentui/react";
|
|
4
5
|
import { LogLevel, TelemetryEvent } from "../../common/telemetry/TelemetryConstants";
|
|
5
6
|
import React, { useEffect } from "react";
|
|
6
7
|
import { createTimer, getDeviceType, setFocusOnSendBox } from "../../common/utils";
|
|
7
8
|
import { BotMagicCodeStore } from "./webchatcontroller/BotMagicCodeStore";
|
|
8
9
|
import { Components } from "botframework-webchat";
|
|
9
|
-
import { Constants, HtmlAttributeNames, HtmlClassNames } from "../../common/Constants";
|
|
10
10
|
import { LiveChatWidgetActionType } from "../../contexts/common/LiveChatWidgetActionType";
|
|
11
11
|
import { NotificationHandler } from "./webchatcontroller/notification/NotificationHandler";
|
|
12
12
|
import { NotificationScenarios } from "./webchatcontroller/enums/NotificationScenarios";
|
|
@@ -48,7 +48,7 @@ const createMagicCodeSuccessResponse = signin => {
|
|
|
48
48
|
};
|
|
49
49
|
};
|
|
50
50
|
export const WebChatContainerStateful = props => {
|
|
51
|
-
var _webChatContainerProp, _webChatContainerProp2, _webChatContainerProp3, _webChatContainerProp4, _webChatContainerProp5, _webChatContainerProp6, _webChatContainerProp7, _props$webChatContain5, _props$webChatContain6, _defaultWebChatContai, _props$webChatContain7, _props$webChatContain8, _defaultWebChatContai2, _webChatContainerProp8, _webChatContainerProp9, _webChatContainerProp10, _webChatContainerProp11, _webChatContainerProp12, _webChatContainerProp13, _webChatContainerProp14, _webChatContainerProp15, _props$webChatContain9, _props$webChatContain10;
|
|
51
|
+
var _webChatContainerProp, _webChatContainerProp2, _webChatContainerProp3, _webChatContainerProp4, _webChatContainerProp5, _webChatContainerProp6, _webChatContainerProp7, _props$webChatContain5, _props$webChatContain6, _defaultWebChatContai, _props$webChatContain7, _props$webChatContain8, _defaultWebChatContai2, _webChatContainerProp8, _webChatContainerProp9, _webChatContainerProp10, _webChatContainerProp11, _webChatContainerProp12, _webChatContainerProp13, _webChatContainerProp14, _webChatContainerProp15, _webChatContainerProp16, _props$webChatContain9, _props$webChatContain10;
|
|
52
52
|
useEffect(() => {
|
|
53
53
|
uiTimer = createTimer();
|
|
54
54
|
TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
|
|
@@ -233,8 +233,9 @@ export const WebChatContainerStateful = props => {
|
|
|
233
233
|
color: ${(webChatContainerProps === null || webChatContainerProps === void 0 ? void 0 : (_webChatContainerProp14 = webChatContainerProps.renderingMiddlewareProps) === null || _webChatContainerProp14 === void 0 ? void 0 : (_webChatContainerProp15 = _webChatContainerProp14.sentMessageAnchorStyles) === null || _webChatContainerProp15 === void 0 ? void 0 : _webChatContainerProp15.color) ?? (defaultSentMessageAnchorStyles === null || defaultSentMessageAnchorStyles === void 0 ? void 0 : defaultSentMessageAnchorStyles.color)};
|
|
234
234
|
}
|
|
235
235
|
|
|
236
|
+
// we had a nasty bug long time ago with crashing borders messing with the sendbox, so if customer adds this value, they need to deal with that
|
|
236
237
|
.webchat__bubble:not(.webchat__bubble--from-user) .webchat__bubble__content {
|
|
237
|
-
border-radius: 0 !important; /* Override border-radius */
|
|
238
|
+
border-radius: ${(webChatContainerProps === null || webChatContainerProps === void 0 ? void 0 : (_webChatContainerProp16 = webChatContainerProps.webChatStyles) === null || _webChatContainerProp16 === void 0 ? void 0 : _webChatContainerProp16.bubbleBorderRadius) ?? 0} !important; /* Override border-radius */
|
|
238
239
|
}
|
|
239
240
|
|
|
240
241
|
.webchat__stacked-layout_container>div {
|
|
@@ -35,6 +35,10 @@ export const DeliveredTimestamp = _ref => {
|
|
|
35
35
|
return /*#__PURE__*/React.createElement("span", {
|
|
36
36
|
dir: "ltr"
|
|
37
37
|
}, getTimestampHourMinute(timestamp));
|
|
38
|
+
} else {
|
|
39
|
+
return /*#__PURE__*/React.createElement("span", {
|
|
40
|
+
dir: dir
|
|
41
|
+
}, getTimestampHourMinute(timestamp));
|
|
38
42
|
}
|
|
39
43
|
return timeString;
|
|
40
44
|
};
|
|
@@ -6,6 +6,10 @@ import { defaultClientDataStoreProvider } from "../../common/storage/default/def
|
|
|
6
6
|
import { defaultMiddlewareLocalizedTexts } from "../../components/webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts";
|
|
7
7
|
export const getLiveChatWidgetContextInitialState = props => {
|
|
8
8
|
var _props$controlProps, _props$webChatContain;
|
|
9
|
+
const isOutsideOperatingHours = () => {
|
|
10
|
+
var _props$chatConfig, _props$chatConfig$Liv, _props$chatConfig$Liv2;
|
|
11
|
+
return ((_props$chatConfig = props.chatConfig) === null || _props$chatConfig === void 0 ? void 0 : (_props$chatConfig$Liv = _props$chatConfig.LiveWSAndLiveChatEngJoin) === null || _props$chatConfig$Liv === void 0 ? void 0 : (_props$chatConfig$Liv2 = _props$chatConfig$Liv.OutOfOperatingHours) === null || _props$chatConfig$Liv2 === void 0 ? void 0 : _props$chatConfig$Liv2.toString().toLowerCase()) === "true";
|
|
12
|
+
};
|
|
9
13
|
const widgetCacheId = getWidgetCacheIdfromProps(props);
|
|
10
14
|
const cacheTtlInMins = (props === null || props === void 0 ? void 0 : (_props$controlProps = props.controlProps) === null || _props$controlProps === void 0 ? void 0 : _props$controlProps.cacheTtlInMins) ?? Constants.CacheTtlInMinutes;
|
|
11
15
|
const storageType = (props === null || props === void 0 ? void 0 : props.useSessionStorage) === true ? StorageType.sessionStorage : StorageType.localStorage;
|
|
@@ -22,6 +26,14 @@ export const getLiveChatWidgetContextInitialState = props => {
|
|
|
22
26
|
if (initialStateFromCache.appStates.conversationState === ConversationState.Prechat) {
|
|
23
27
|
initialStateFromCache.appStates.conversationState = ConversationState.Closed;
|
|
24
28
|
}
|
|
29
|
+
|
|
30
|
+
// we are always setting the chatConfig from the props to avoid any issues with the cache
|
|
31
|
+
initialStateFromCache.domainStates.liveChatConfig = props.chatConfig;
|
|
32
|
+
|
|
33
|
+
// Cache the result of isOutsideOperatingHours() to ensure consistency
|
|
34
|
+
const outsideOperatingHours = isOutsideOperatingHours();
|
|
35
|
+
initialStateFromCache.appStates.outsideOperatingHours = outsideOperatingHours;
|
|
36
|
+
initialStateFromCache.appStates.conversationState = outsideOperatingHours ? ConversationState.OutOfOffice : initialStateFromCache.appStates.conversationState;
|
|
25
37
|
return initialStateFromCache;
|
|
26
38
|
}
|
|
27
39
|
const LiveChatWidgetContextInitialState = {
|
|
@@ -46,11 +58,11 @@ export const getLiveChatWidgetContextInitialState = props => {
|
|
|
46
58
|
startChatFailureType: StartChatFailureType.Generic
|
|
47
59
|
},
|
|
48
60
|
appStates: {
|
|
49
|
-
conversationState: ConversationState.Closed,
|
|
61
|
+
conversationState: isOutsideOperatingHours() ? ConversationState.OutOfOffice : ConversationState.Closed,
|
|
50
62
|
isMinimized: undefined,
|
|
51
63
|
previousElementIdOnFocusBeforeModalOpen: null,
|
|
52
64
|
startChatFailed: false,
|
|
53
|
-
outsideOperatingHours:
|
|
65
|
+
outsideOperatingHours: isOutsideOperatingHours(),
|
|
54
66
|
preChatResponseEmail: "",
|
|
55
67
|
isAudioMuted: null,
|
|
56
68
|
newMessage: false,
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { BroadcastEvent, LogLevel, TelemetryEvent } from "../common/telemetry/TelemetryConstants";
|
|
2
|
+
import { BroadcastService } from "@microsoft/omnichannel-chat-components";
|
|
3
|
+
import { TelemetryHelper } from "../common/telemetry/TelemetryHelper";
|
|
4
|
+
import { createTrackingMessage } from "./util";
|
|
5
|
+
|
|
6
|
+
// This tracker is event based, this is since we are tracking events coming from different sources
|
|
7
|
+
// with different timeline, therefore this is a functional approach to track the events, instead of a class based approach
|
|
8
|
+
export const createTrackingForFirstMessage = () => {
|
|
9
|
+
// Reset the tracking variables
|
|
10
|
+
let startTracking = false;
|
|
11
|
+
let stopTracking = false;
|
|
12
|
+
let startTime = 0;
|
|
13
|
+
let stopTime = 0;
|
|
14
|
+
let stopTrackingMessage;
|
|
15
|
+
let flag = false;
|
|
16
|
+
const isMessageFromValidSender = payload => {
|
|
17
|
+
var _payload$tags;
|
|
18
|
+
// agent scenario
|
|
19
|
+
if (payload !== null && payload !== void 0 && (_payload$tags = payload.tags) !== null && _payload$tags !== void 0 && _payload$tags.includes("public")) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
return true;
|
|
23
|
+
};
|
|
24
|
+
const widgetLoadListener = BroadcastService.getMessageByEventName(TelemetryEvent.WidgetLoadComplete).subscribe(() => {
|
|
25
|
+
if (startTracking) return;
|
|
26
|
+
startTracking = true;
|
|
27
|
+
startTime = new Date().getTime();
|
|
28
|
+
});
|
|
29
|
+
const newMessageListener = BroadcastService.getMessageByEventName(BroadcastEvent.NewMessageReceived).subscribe(message => {
|
|
30
|
+
const payload = message.payload;
|
|
31
|
+
|
|
32
|
+
// we only care for bot, so we need to check if the message is from the bot
|
|
33
|
+
// pending to add typing message indicator signal detection
|
|
34
|
+
|
|
35
|
+
if (isMessageFromValidSender(payload)) {
|
|
36
|
+
if (startTracking && !stopTracking) {
|
|
37
|
+
stopTime = new Date().getTime();
|
|
38
|
+
const elapsedTime = stopTime - startTime;
|
|
39
|
+
stopTracking = true;
|
|
40
|
+
stopTrackingMessage = createTrackingMessage(payload, "botMessage");
|
|
41
|
+
notifyFMLTrackingCompleted();
|
|
42
|
+
TelemetryHelper.logActionEvent(LogLevel.INFO, {
|
|
43
|
+
Event: TelemetryEvent.BotFirstMessageLapTrack,
|
|
44
|
+
Description: "First Message from Bot latency tracking",
|
|
45
|
+
CustomProperties: {
|
|
46
|
+
elapsedTime,
|
|
47
|
+
widgetLoadedAt: startTime,
|
|
48
|
+
botMessage: stopTrackingMessage
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// this track only first message, if coming from the bot or not
|
|
55
|
+
// the only difference is that it logs only those from bot
|
|
56
|
+
disconnectListener();
|
|
57
|
+
});
|
|
58
|
+
const notifyFMLTrackingCompleted = () => {
|
|
59
|
+
ackListener();
|
|
60
|
+
// Retry sending until flag is true, but do not block the main thread
|
|
61
|
+
const interval = setInterval(() => {
|
|
62
|
+
if (flag) {
|
|
63
|
+
clearInterval(interval);
|
|
64
|
+
} else {
|
|
65
|
+
BroadcastService.postMessage({
|
|
66
|
+
eventName: BroadcastEvent.FMLTrackingCompleted,
|
|
67
|
+
payload: null
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}, 100);
|
|
71
|
+
};
|
|
72
|
+
const ackListener = () => {
|
|
73
|
+
const listen = BroadcastService.getMessageByEventName(BroadcastEvent.FMLTrackingCompletedAck).subscribe(() => {
|
|
74
|
+
flag = true;
|
|
75
|
+
listen.unsubscribe();
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// Rehydrate message is received when the widget is reloaded, this is to ensure that we are not tracking messages that are not part of the current conversation
|
|
80
|
+
// No need to keep listerning for tracking, enforcing disconnection for the listners
|
|
81
|
+
const rehydrateListener = BroadcastService.getMessageByEventName(TelemetryEvent.RehydrateMessageReceived).subscribe(() => {
|
|
82
|
+
startTracking = false;
|
|
83
|
+
stopTracking = false;
|
|
84
|
+
disconnectListener();
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Rehydrate message is received when the widget is reloaded, this is to ensure that we are not tracking messages that are not part of the current conversation
|
|
88
|
+
// No need to keep listerning for tracking, enforcing disconnection for the listners
|
|
89
|
+
const historyListener = BroadcastService.getMessageByEventName(BroadcastEvent.HistoryMessageReceived).subscribe(() => {
|
|
90
|
+
startTracking = false;
|
|
91
|
+
stopTracking = false;
|
|
92
|
+
disconnectListener();
|
|
93
|
+
});
|
|
94
|
+
const offlineNetworkListener = BroadcastService.getMessageByEventName(TelemetryEvent.NetworkDisconnected).subscribe(() => {
|
|
95
|
+
startTracking = false;
|
|
96
|
+
stopTracking = false;
|
|
97
|
+
disconnectListener();
|
|
98
|
+
TelemetryHelper.logActionEvent(LogLevel.INFO, {
|
|
99
|
+
Event: TelemetryEvent.BotFirstMessageLapTrackError,
|
|
100
|
+
Description: "Tracker Stopped due to network disconnection"
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// this is to ensure that we are not tracking messages that are not part of the current conversation
|
|
105
|
+
const disconnectListener = () => {
|
|
106
|
+
historyListener.unsubscribe();
|
|
107
|
+
rehydrateListener.unsubscribe();
|
|
108
|
+
newMessageListener.unsubscribe();
|
|
109
|
+
widgetLoadListener.unsubscribe();
|
|
110
|
+
offlineNetworkListener.unsubscribe();
|
|
111
|
+
};
|
|
112
|
+
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
2
2
|
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
3
3
|
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
4
|
-
import { LogLevel, TelemetryEvent } from "../common/telemetry/TelemetryConstants";
|
|
4
|
+
import { BroadcastEvent, LogLevel, TelemetryEvent } from "../common/telemetry/TelemetryConstants";
|
|
5
|
+
import { BroadcastService } from "@microsoft/omnichannel-chat-components";
|
|
5
6
|
import { TelemetryHelper } from "../common/telemetry/TelemetryHelper";
|
|
6
7
|
export class FirstResponseLatencyTracker {
|
|
7
8
|
constructor() {
|
|
@@ -10,6 +11,32 @@ export class FirstResponseLatencyTracker {
|
|
|
10
11
|
_defineProperty(this, "isEnded", false);
|
|
11
12
|
_defineProperty(this, "startTrackingMessage", void 0);
|
|
12
13
|
_defineProperty(this, "stopTrackingMessage", void 0);
|
|
14
|
+
_defineProperty(this, "isReady", false);
|
|
15
|
+
_defineProperty(this, "offlineNetworkListener", BroadcastService.getMessageByEventName(TelemetryEvent.NetworkDisconnected).subscribe(() => {
|
|
16
|
+
this.isStarted = false;
|
|
17
|
+
this.isEnded = false;
|
|
18
|
+
TelemetryHelper.logActionEvent(LogLevel.INFO, {
|
|
19
|
+
Event: TelemetryEvent.MessageStopLapTrackError,
|
|
20
|
+
Description: "Tracker Stopped due to network disconnection"
|
|
21
|
+
});
|
|
22
|
+
}));
|
|
23
|
+
_defineProperty(this, "fmltrackingListener", BroadcastService.getMessageByEventName(BroadcastEvent.FMLTrackingCompleted).subscribe(() => {
|
|
24
|
+
this.isReady = true;
|
|
25
|
+
BroadcastService.postMessage({
|
|
26
|
+
eventName: BroadcastEvent.FMLTrackingCompletedAck,
|
|
27
|
+
payload: null
|
|
28
|
+
});
|
|
29
|
+
}));
|
|
30
|
+
// Rehydrate message is received when the widget is reloaded, this is to ensure that we are not tracking messages that are not part of the current conversation
|
|
31
|
+
// No need to keep listerning for tracking, enforcing disconnection for the listners
|
|
32
|
+
_defineProperty(this, "rehydrateListener", BroadcastService.getMessageByEventName(TelemetryEvent.RehydrateMessageReceived).subscribe(() => {
|
|
33
|
+
this.isReady = true;
|
|
34
|
+
}));
|
|
35
|
+
// Rehydrate message is received when the widget is reloaded, this is to ensure that we are not tracking messages that are not part of the current conversation
|
|
36
|
+
// No need to keep listerning for tracking, enforcing disconnection for the listners
|
|
37
|
+
_defineProperty(this, "historyListener", BroadcastService.getMessageByEventName(BroadcastEvent.HistoryMessageReceived).subscribe(() => {
|
|
38
|
+
this.isReady = true;
|
|
39
|
+
}));
|
|
13
40
|
// this is a workaround to ensure in reload we track effectively the messages
|
|
14
41
|
// we do have a mechanism in place to prevent log agent messages.
|
|
15
42
|
this.isABotConversation = true;
|
|
@@ -29,6 +56,7 @@ export class FirstResponseLatencyTracker {
|
|
|
29
56
|
|
|
30
57
|
// Tracking Functions
|
|
31
58
|
startTracking(payload) {
|
|
59
|
+
if (!this.isReady) return;
|
|
32
60
|
// this prevents to initiate tracking for multiple incoming messages
|
|
33
61
|
if (this.isStarted) {
|
|
34
62
|
return;
|
|
@@ -37,11 +65,9 @@ export class FirstResponseLatencyTracker {
|
|
|
37
65
|
if (!this.isABotConversation) {
|
|
38
66
|
return;
|
|
39
67
|
}
|
|
40
|
-
|
|
41
68
|
// control of states to prevent clashing of messages
|
|
42
69
|
this.isStarted = true;
|
|
43
70
|
this.isEnded = false;
|
|
44
|
-
|
|
45
71
|
// The idea of using types is to enrich telemetry data
|
|
46
72
|
this.startTrackingMessage = this.createTrackingMessage(payload, "userMessage");
|
|
47
73
|
}
|
|
@@ -93,9 +119,6 @@ export class FirstResponseLatencyTracker {
|
|
|
93
119
|
if (!payload || !payload.Id) {
|
|
94
120
|
throw new Error("Invalid payload");
|
|
95
121
|
}
|
|
96
|
-
// in the case of a reload, tracker will be paused, until last history message is received
|
|
97
|
-
// this is because we dont have a way to identidy send messages as part of the history
|
|
98
|
-
//if (this.inPause) return;
|
|
99
122
|
this.startTracking(payload);
|
|
100
123
|
} catch (e) {
|
|
101
124
|
TelemetryHelper.logActionEvent(LogLevel.ERROR, {
|
|
@@ -141,5 +164,9 @@ export class FirstResponseLatencyTracker {
|
|
|
141
164
|
this.isEnded = false;
|
|
142
165
|
this.startTrackingMessage = undefined;
|
|
143
166
|
this.stopTrackingMessage = undefined;
|
|
167
|
+
this.offlineNetworkListener.unsubscribe();
|
|
168
|
+
this.fmltrackingListener.unsubscribe();
|
|
169
|
+
this.rehydrateListener.unsubscribe();
|
|
170
|
+
this.historyListener.unsubscribe();
|
|
144
171
|
}
|
|
145
172
|
}
|
|
@@ -72,4 +72,16 @@ export const getScenarioType = activity => {
|
|
|
72
72
|
return ScenarioType.SystemMessageStrategy;
|
|
73
73
|
}
|
|
74
74
|
return ScenarioType.ReceivedMessageStrategy;
|
|
75
|
+
};
|
|
76
|
+
export const createTrackingMessage = (payload, type) => {
|
|
77
|
+
return {
|
|
78
|
+
Id: payload.Id,
|
|
79
|
+
role: payload.role,
|
|
80
|
+
timestamp: payload === null || payload === void 0 ? void 0 : payload.timestamp,
|
|
81
|
+
tags: payload.tags,
|
|
82
|
+
messageType: payload.messageType,
|
|
83
|
+
text: payload.text,
|
|
84
|
+
type: type,
|
|
85
|
+
checkTime: new Date().getTime()
|
|
86
|
+
};
|
|
75
87
|
};
|
|
@@ -43,6 +43,7 @@ export declare class FacadeChatSDK {
|
|
|
43
43
|
private enforceBase64Encoding;
|
|
44
44
|
private extractExpFromToken;
|
|
45
45
|
private setToken;
|
|
46
|
+
private corroborateTokenIsSet;
|
|
46
47
|
private tokenRing;
|
|
47
48
|
private validateAndExecuteCall;
|
|
48
49
|
initialize(optionalParams?: InitializeOptionalParams): Promise<ChatConfig>;
|
|
@@ -54,7 +54,9 @@ export declare enum BroadcastEvent {
|
|
|
54
54
|
UpdateConversationDataForTelemetry = "UpdateConversationDataForTelemetry",
|
|
55
55
|
ContactIdNotFound = "ContactIdNotFound",
|
|
56
56
|
SyncMinimize = "SyncMinimize",
|
|
57
|
-
OnWidgetError = "OnWidgetError"
|
|
57
|
+
OnWidgetError = "OnWidgetError",
|
|
58
|
+
FMLTrackingCompletedAck = "FMLTrackingCompletedAck",
|
|
59
|
+
FMLTrackingCompleted = "FMLTrackingCompleted"
|
|
58
60
|
}
|
|
59
61
|
export declare enum TelemetryEvent {
|
|
60
62
|
CallAdded = "CallAdded",
|
|
@@ -193,6 +195,8 @@ export declare enum TelemetryEvent {
|
|
|
193
195
|
MessageSent = "MessageSent",
|
|
194
196
|
MessageReceived = "MessageReceived",
|
|
195
197
|
MessageLapTrack = "MessageLapTrack",
|
|
198
|
+
BotFirstMessageLapTrack = "BotFirstMessageLapTrack",
|
|
199
|
+
BotFirstMessageLapTrackError = "BotFirstMessageLapTrackError",
|
|
196
200
|
MessageStartLapTrackError = "MessageStartLapTrackError",
|
|
197
201
|
MessageStopLapTrackError = "MessageStopLapTrackError",
|
|
198
202
|
SystemMessageReceived = "SystemMessageReceived",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const createTrackingForFirstMessage: () => void;
|