@microsoft/omnichannel-chat-widget 1.7.8-main.7a07fc5 → 1.7.8-main.ab4d3b4
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/telemetry/TelemetryConstants.js +9 -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/ActivitySubscriber/BotAuthActivitySubscriber.js +4 -1
- package/lib/cjs/components/livechatwidget/common/chatDisconnectHelper.js +3 -1
- package/lib/cjs/components/livechatwidget/common/endChat.js +4 -18
- package/lib/cjs/components/livechatwidget/common/startChat.js +2 -0
- package/lib/cjs/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +17 -11
- package/lib/cjs/components/ooohpanestateful/OOOHPaneStateful.js +6 -4
- package/lib/cjs/components/postchatsurveypanestateful/PostChatSurveyPaneStateful.js +22 -6
- package/lib/cjs/components/postchatsurveypanestateful/common/isValidSurveyUrl.js +28 -0
- 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 +18 -6
- package/lib/cjs/firstresponselatency/Constants.js +13 -0
- package/lib/cjs/firstresponselatency/FirstMessageTrackerFromBot.js +118 -0
- package/lib/cjs/firstresponselatency/FirstResponseLatencyTracker.js +179 -0
- package/lib/cjs/firstresponselatency/util.js +98 -0
- package/lib/cjs/plugins/createChatTranscript.js +4 -4
- package/lib/cjs/plugins/newMessageEventHandler.js +102 -88
- package/lib/esm/common/telemetry/TelemetryConstants.js +9 -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/ActivitySubscriber/BotAuthActivitySubscriber.js +4 -1
- package/lib/esm/components/livechatwidget/common/chatDisconnectHelper.js +3 -1
- package/lib/esm/components/livechatwidget/common/endChat.js +4 -18
- package/lib/esm/components/livechatwidget/common/startChat.js +2 -0
- package/lib/esm/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +17 -11
- package/lib/esm/components/ooohpanestateful/OOOHPaneStateful.js +6 -4
- package/lib/esm/components/postchatsurveypanestateful/PostChatSurveyPaneStateful.js +22 -6
- package/lib/esm/components/postchatsurveypanestateful/common/isValidSurveyUrl.js +21 -0
- 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 +18 -6
- package/lib/esm/firstresponselatency/Constants.js +6 -0
- package/lib/esm/firstresponselatency/FirstMessageTrackerFromBot.js +112 -0
- package/lib/esm/firstresponselatency/FirstResponseLatencyTracker.js +172 -0
- package/lib/esm/firstresponselatency/util.js +87 -0
- package/lib/esm/plugins/createChatTranscript.js +4 -4
- package/lib/esm/plugins/newMessageEventHandler.js +100 -86
- package/lib/types/common/telemetry/TelemetryConstants.d.ts +10 -1
- package/lib/types/components/postchatsurveypanestateful/common/isValidSurveyUrl.d.ts +2 -0
- package/lib/types/contexts/common/ILiveChatWidgetContext.d.ts +1 -1
- package/lib/types/firstresponselatency/Constants.d.ts +30 -0
- package/lib/types/firstresponselatency/FirstMessageTrackerFromBot.d.ts +1 -0
- package/lib/types/firstresponselatency/FirstResponseLatencyTracker.d.ts +22 -0
- package/lib/types/firstresponselatency/util.d.ts +7 -0
- package/package.json +13 -3
|
@@ -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) {
|
|
@@ -199,6 +201,11 @@ export let TelemetryEvent;
|
|
|
199
201
|
TelemetryEvent["ReconnectChatMinimize"] = "ReconnectChatMinimize";
|
|
200
202
|
TelemetryEvent["MessageSent"] = "MessageSent";
|
|
201
203
|
TelemetryEvent["MessageReceived"] = "MessageReceived";
|
|
204
|
+
TelemetryEvent["MessageLapTrack"] = "MessageLapTrack";
|
|
205
|
+
TelemetryEvent["BotFirstMessageLapTrack"] = "BotFirstMessageLapTrackError";
|
|
206
|
+
TelemetryEvent["BotFirstMessageLapTrackError"] = "BotFirstMessageLapTrack";
|
|
207
|
+
TelemetryEvent["MessageStartLapTrackError"] = "MessageStartLapTrackError";
|
|
208
|
+
TelemetryEvent["MessageStopLapTrackError"] = "MessageStopLapTrackError";
|
|
202
209
|
TelemetryEvent["SystemMessageReceived"] = "SystemMessageReceived";
|
|
203
210
|
TelemetryEvent["RehydrateMessageReceived"] = "RehydrateMessageReceived";
|
|
204
211
|
TelemetryEvent["CustomContextReceived"] = "CustomContextReceived";
|
|
@@ -213,6 +220,8 @@ export let TelemetryEvent;
|
|
|
213
220
|
TelemetryEvent["PostChatContextCallFailed"] = "PostChatContextCallFailed";
|
|
214
221
|
TelemetryEvent["PostChatSurveyLoadingPaneLoaded"] = "PostChatSurveyLoadingPaneLoaded";
|
|
215
222
|
TelemetryEvent["PostChatSurveyLoaded"] = "PostChatSurveyLoaded";
|
|
223
|
+
TelemetryEvent["PostChatSurveyUrlValidationCompleted"] = "PostChatSurveyUrlValidationCompleted";
|
|
224
|
+
TelemetryEvent["PostChatSurveyUrlValidationFailed"] = "PostChatSurveyUrlValidationFailed";
|
|
216
225
|
TelemetryEvent["ChatDisconnectThreadEventReceived"] = "ChatDisconnectThreadEventReceived";
|
|
217
226
|
TelemetryEvent["HiddenAdaptiveCardMessageReceived"] = "HiddenAdaptiveCardMessageReceived";
|
|
218
227
|
TelemetryEvent["EndingAdapterAfterDisconnectionError"] = "EndingAdapterAfterDisconnectionError";
|
|
@@ -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;
|
package/lib/esm/components/livechatwidget/common/ActivitySubscriber/BotAuthActivitySubscriber.js
CHANGED
|
@@ -6,6 +6,7 @@ function _toPrimitive(input, hint) { if (typeof input !== "object" || input ===
|
|
|
6
6
|
import { BroadcastService } from "@microsoft/omnichannel-chat-components";
|
|
7
7
|
import { BroadcastEvent, LogLevel, TelemetryEvent } from "../../../../common/telemetry/TelemetryConstants";
|
|
8
8
|
import { TelemetryHelper } from "../../../../common/telemetry/TelemetryHelper";
|
|
9
|
+
import { TelemetryManager } from "../../../../common/telemetry/TelemetryManager";
|
|
9
10
|
const supportedSignInCardContentTypes = ["application/vnd.microsoft.card.signin", "application/vnd.microsoft.card.oauth"];
|
|
10
11
|
const botOauthUrlRegex = /[\S]+.botframework.com\/api\/oauth\/signin\?signin=([\S]+)/;
|
|
11
12
|
const delay = t => new Promise(resolve => setTimeout(resolve, t));
|
|
@@ -83,6 +84,7 @@ export class BotAuthActivitySubscriber {
|
|
|
83
84
|
return (activity === null || activity === void 0 ? void 0 : (_activity$attachments = activity.attachments) === null || _activity$attachments === void 0 ? void 0 : _activity$attachments.length) > 0 && activity.attachments[0] && supportedSignInCardContentTypes.indexOf(activity.attachments[0].contentType) >= 0;
|
|
84
85
|
}
|
|
85
86
|
async apply(activity) {
|
|
87
|
+
var _TelemetryManager$Int;
|
|
86
88
|
this.observer.next(false); // Hides card
|
|
87
89
|
const attachment = activity.attachments[0];
|
|
88
90
|
const signInUrl = attachment.content.buttons[0].value;
|
|
@@ -102,7 +104,8 @@ export class BotAuthActivitySubscriber {
|
|
|
102
104
|
const event = {
|
|
103
105
|
eventName: BroadcastEvent.SigninCardReceived,
|
|
104
106
|
payload: {
|
|
105
|
-
sasUrl
|
|
107
|
+
sasUrl,
|
|
108
|
+
conversationId: (_TelemetryManager$Int = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int === void 0 ? void 0 : _TelemetryManager$Int.conversationId
|
|
106
109
|
}
|
|
107
110
|
};
|
|
108
111
|
if (!sasUrl) {
|
|
@@ -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 {
|
|
@@ -203,7 +203,7 @@ const endChat = async (props, facadeChatSDK, state, dispatch, setAdapter, setWeb
|
|
|
203
203
|
payload: undefined
|
|
204
204
|
});
|
|
205
205
|
// Always allow to close the chat for embedded mode irrespective of end chat errors
|
|
206
|
-
closeChatWidget(dispatch
|
|
206
|
+
closeChatWidget(dispatch);
|
|
207
207
|
facadeChatSDK.destroy();
|
|
208
208
|
}
|
|
209
209
|
}
|
|
@@ -327,21 +327,7 @@ export const endVoiceVideoCallIfOngoing = async (facadeChatSDK, dispatch) => {
|
|
|
327
327
|
}, callId);
|
|
328
328
|
}
|
|
329
329
|
};
|
|
330
|
-
const closeChatWidget =
|
|
331
|
-
var _state$appStates5;
|
|
332
|
-
if (state !== null && state !== void 0 && (_state$appStates5 = state.appStates) !== null && _state$appStates5 !== void 0 && _state$appStates5.hideStartChatButton) {
|
|
333
|
-
var _props$controlProps2, _props$controlProps3;
|
|
334
|
-
// Only close chat if header is enabled for popout
|
|
335
|
-
// TODO : This condition needs to be removed eventually when the filler UX is ready for popout, removing this condition would show a blank screen for OOB Widget
|
|
336
|
-
if ((props === null || props === void 0 ? void 0 : (_props$controlProps2 = props.controlProps) === null || _props$controlProps2 === void 0 ? void 0 : _props$controlProps2.hideHeader) === undefined || (props === null || props === void 0 ? void 0 : (_props$controlProps3 = props.controlProps) === null || _props$controlProps3 === void 0 ? void 0 : _props$controlProps3.hideHeader) === false) {
|
|
337
|
-
dispatch({
|
|
338
|
-
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE,
|
|
339
|
-
payload: ConversationState.Closed
|
|
340
|
-
});
|
|
341
|
-
}
|
|
342
|
-
return;
|
|
343
|
-
}
|
|
344
|
-
|
|
330
|
+
const closeChatWidget = dispatch => {
|
|
345
331
|
// Embedded chat
|
|
346
332
|
dispatch({
|
|
347
333
|
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE,
|
|
@@ -361,7 +347,7 @@ const chatTokenCleanUp = async dispatch => {
|
|
|
361
347
|
};
|
|
362
348
|
|
|
363
349
|
const getEndChatEventName = async (facadeChatSDK, props) => {
|
|
364
|
-
var _facadeChatSDK$getCha2, _facadeChatSDK$getCha3, _facadeChatSDK$getCha4, _facadeChatSDK$getCha5, _props$
|
|
365
|
-
return getWidgetEndChatEventName((_facadeChatSDK$getCha2 = facadeChatSDK.getChatSDK()) === null || _facadeChatSDK$getCha2 === void 0 ? void 0 : (_facadeChatSDK$getCha3 = _facadeChatSDK$getCha2.omnichannelConfig) === null || _facadeChatSDK$getCha3 === void 0 ? void 0 : _facadeChatSDK$getCha3.orgId, (_facadeChatSDK$getCha4 = facadeChatSDK.getChatSDK()) === null || _facadeChatSDK$getCha4 === void 0 ? void 0 : (_facadeChatSDK$getCha5 = _facadeChatSDK$getCha4.omnichannelConfig) === null || _facadeChatSDK$getCha5 === void 0 ? void 0 : _facadeChatSDK$getCha5.widgetId, (props === null || props === void 0 ? void 0 : (_props$
|
|
350
|
+
var _facadeChatSDK$getCha2, _facadeChatSDK$getCha3, _facadeChatSDK$getCha4, _facadeChatSDK$getCha5, _props$controlProps2;
|
|
351
|
+
return getWidgetEndChatEventName((_facadeChatSDK$getCha2 = facadeChatSDK.getChatSDK()) === null || _facadeChatSDK$getCha2 === void 0 ? void 0 : (_facadeChatSDK$getCha3 = _facadeChatSDK$getCha2.omnichannelConfig) === null || _facadeChatSDK$getCha3 === void 0 ? void 0 : _facadeChatSDK$getCha3.orgId, (_facadeChatSDK$getCha4 = facadeChatSDK.getChatSDK()) === null || _facadeChatSDK$getCha4 === void 0 ? void 0 : (_facadeChatSDK$getCha5 = _facadeChatSDK$getCha4.omnichannelConfig) === null || _facadeChatSDK$getCha5 === void 0 ? void 0 : _facadeChatSDK$getCha5.widgetId, (props === null || props === void 0 ? void 0 : (_props$controlProps2 = props.controlProps) === null || _props$controlProps2 === void 0 ? void 0 : _props$controlProps2.widgetInstanceId) ?? "");
|
|
366
352
|
};
|
|
367
353
|
export { prepareEndChat, endChat };
|
|
@@ -13,6 +13,7 @@ import { TelemetryTimers } from "../../../common/telemetry/TelemetryManager";
|
|
|
13
13
|
import { chatSDKStateCleanUp } from "./endChat";
|
|
14
14
|
import { createAdapter } from "./createAdapter";
|
|
15
15
|
import { createOnNewAdapterActivityHandler } from "../../../plugins/newMessageEventHandler";
|
|
16
|
+
import { createTrackingForFirstMessage } from "../../../firstresponselatency/FirstMessageTrackerFromBot";
|
|
16
17
|
import { isPersistentChatEnabled } from "./liveChatConfigUtils";
|
|
17
18
|
import { setPostChatContextAndLoadSurvey } from "./setPostChatContextAndLoadSurvey";
|
|
18
19
|
import { shouldSetPreChatIfPersistentChat } from "./persistentChatHelper";
|
|
@@ -145,6 +146,7 @@ const setPreChatAndInitiateChat = async (facadeChatSDK, dispatch, setAdapter, is
|
|
|
145
146
|
const optionalParams = {
|
|
146
147
|
isProactiveChat
|
|
147
148
|
};
|
|
149
|
+
createTrackingForFirstMessage();
|
|
148
150
|
await initStartChat(facadeChatSDK, dispatch, setAdapter, state, props, optionalParams);
|
|
149
151
|
};
|
|
150
152
|
|
|
@@ -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, {
|
|
@@ -409,7 +409,7 @@ export const LiveChatWidgetStateful = props => {
|
|
|
409
409
|
|
|
410
410
|
// Start chat from SDK Event
|
|
411
411
|
BroadcastService.getMessageByEventName(BroadcastEvent.StartChat).subscribe(msg => {
|
|
412
|
-
var _props$chatConfig5, _props$chatConfig5$Li, _props$chatConfig6, _props$chatConfig6$Li, _msg$payload5, _msg$payload6, _msg$payload7, _msg$payload9, _inMemoryState$appSta2, _inMemoryState$appSta3
|
|
412
|
+
var _props$chatConfig5, _props$chatConfig5$Li, _props$chatConfig6, _props$chatConfig6$Li, _msg$payload5, _msg$payload6, _msg$payload7, _msg$payload9, _inMemoryState$appSta2, _inMemoryState$appSta3;
|
|
413
413
|
// If chat is out of operating hours chat widget sets the conversation state to OutOfOffice.
|
|
414
414
|
if (typeof (props === null || props === void 0 ? void 0 : (_props$chatConfig5 = props.chatConfig) === null || _props$chatConfig5 === void 0 ? void 0 : (_props$chatConfig5$Li = _props$chatConfig5.LiveWSAndLiveChatEngJoin) === null || _props$chatConfig5$Li === void 0 ? void 0 : _props$chatConfig5$Li.OutOfOperatingHours) === "string" && (props === null || props === void 0 ? void 0 : (_props$chatConfig6 = props.chatConfig) === null || _props$chatConfig6 === void 0 ? void 0 : (_props$chatConfig6$Li = _props$chatConfig6.LiveWSAndLiveChatEngJoin) === null || _props$chatConfig6$Li === void 0 ? void 0 : _props$chatConfig6$Li.OutOfOperatingHours.toLowerCase()) === "true") {
|
|
415
415
|
(state === null || state === void 0 ? void 0 : state.appStates.isMinimized) && dispatch({
|
|
@@ -447,8 +447,14 @@ export const LiveChatWidgetStateful = props => {
|
|
|
447
447
|
});
|
|
448
448
|
inMemoryState.domainStates.customContext = msg === null || msg === void 0 ? void 0 : (_msg$payload9 = msg.payload) === null || _msg$payload9 === void 0 ? void 0 : _msg$payload9.customContext;
|
|
449
449
|
|
|
450
|
-
|
|
451
|
-
|
|
450
|
+
/*
|
|
451
|
+
* If the conversation is in closed state then we start a new chat,
|
|
452
|
+
* else if the conversation is in active state then we maximize the chat
|
|
453
|
+
* If the conversation is in inactive or postchat state then we maximize the chat.
|
|
454
|
+
*
|
|
455
|
+
* To start a new chat, it needs to be called via the close button or close chat via SDK.
|
|
456
|
+
**/
|
|
457
|
+
if (((_inMemoryState$appSta2 = inMemoryState.appStates) === null || _inMemoryState$appSta2 === void 0 ? void 0 : _inMemoryState$appSta2.conversationState) === ConversationState.Closed) {
|
|
452
458
|
BroadcastService.postMessage({
|
|
453
459
|
eventName: BroadcastEvent.ChatInitiated
|
|
454
460
|
});
|
|
@@ -457,7 +463,7 @@ export const LiveChatWidgetStateful = props => {
|
|
|
457
463
|
}
|
|
458
464
|
|
|
459
465
|
// If minimized, maximize the chat
|
|
460
|
-
if ((inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$
|
|
466
|
+
if ((inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta3 = inMemoryState.appStates) === null || _inMemoryState$appSta3 === void 0 ? void 0 : _inMemoryState$appSta3.isMinimized) === true) {
|
|
461
467
|
var _inMemoryState$domain, _inMemoryState$domain2, _inMemoryState$domain3, _inMemoryState$domain4;
|
|
462
468
|
dispatch({
|
|
463
469
|
type: LiveChatWidgetActionType.SET_MINIMIZED,
|
|
@@ -585,12 +591,12 @@ export const LiveChatWidgetStateful = props => {
|
|
|
585
591
|
disablePolling: true
|
|
586
592
|
});
|
|
587
593
|
facadeChatSDK === null || facadeChatSDK === void 0 ? void 0 : facadeChatSDK.onAgentEndSession(event => {
|
|
588
|
-
var _inMemoryState$
|
|
594
|
+
var _inMemoryState$appSta4;
|
|
589
595
|
const inMemoryState = executeReducer(state, {
|
|
590
596
|
type: LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
|
|
591
597
|
payload: null
|
|
592
598
|
});
|
|
593
|
-
if ("participantsRemoved" in event && (inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$
|
|
599
|
+
if ("participantsRemoved" in event && (inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta4 = inMemoryState.appStates) === null || _inMemoryState$appSta4 === void 0 ? void 0 : _inMemoryState$appSta4.conversationState) === ConversationState.Active) {
|
|
594
600
|
setWebChatStyles(styles => {
|
|
595
601
|
return {
|
|
596
602
|
...styles,
|
|
@@ -733,13 +739,13 @@ export const LiveChatWidgetStateful = props => {
|
|
|
733
739
|
|
|
734
740
|
// Handle Chat disconnect cases
|
|
735
741
|
useEffect(() => {
|
|
736
|
-
var _inMemoryState$
|
|
742
|
+
var _inMemoryState$appSta5;
|
|
737
743
|
const inMemoryState = executeReducer(state, {
|
|
738
744
|
type: LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
|
|
739
745
|
payload: null
|
|
740
746
|
});
|
|
741
747
|
handleChatDisconnect(props, inMemoryState, setWebChatStyles);
|
|
742
|
-
const chatDisconnectState = inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$
|
|
748
|
+
const chatDisconnectState = inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta5 = inMemoryState.appStates) === null || _inMemoryState$appSta5 === void 0 ? void 0 : _inMemoryState$appSta5.chatDisconnectEventReceived;
|
|
743
749
|
if (chatDisconnectState && adapter) {
|
|
744
750
|
try {
|
|
745
751
|
adapter.end();
|
|
@@ -868,8 +874,8 @@ export const LiveChatWidgetStateful = props => {
|
|
|
868
874
|
userID: userID,
|
|
869
875
|
styleOptions: {
|
|
870
876
|
...webChatStyles,
|
|
871
|
-
bubbleBackground: ((_props$webChatContain11 = props.webChatContainerProps) === null || _props$webChatContain11 === void 0 ? void 0 : (_props$webChatContain12 = _props$webChatContain11.
|
|
872
|
-
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
|
|
873
879
|
},
|
|
874
880
|
directLine: directLine
|
|
875
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
|
|
@@ -8,14 +8,16 @@ import { TelemetryHelper } from "../../common/telemetry/TelemetryHelper";
|
|
|
8
8
|
import { defaultGeneralPostChatSurveyPaneStyleProps } from "./common/defaultStyleProps/defaultgeneralPostChatSurveyPaneStyleProps";
|
|
9
9
|
import { findAllFocusableElement } from "../../common/utils";
|
|
10
10
|
import useChatContextStore from "../../hooks/useChatContextStore";
|
|
11
|
+
import isValidSurveyUrl from "./common/isValidSurveyUrl";
|
|
11
12
|
const generateSurveyInviteLink = function (surveyInviteLink, isEmbed, locale, compact) {
|
|
12
13
|
let showMultiLingual = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
const surveyLinkParams = new URLSearchParams({
|
|
15
|
+
embed: isEmbed.toString(),
|
|
16
|
+
compact: (compact ?? true).toString(),
|
|
17
|
+
lang: locale ?? "en-us",
|
|
18
|
+
showmultilingual: (showMultiLingual ?? false).toString()
|
|
19
|
+
});
|
|
20
|
+
return `${surveyInviteLink}&${surveyLinkParams.toString()}`;
|
|
19
21
|
};
|
|
20
22
|
export const PostChatSurveyPaneStateful = props => {
|
|
21
23
|
var _props$styleProps, _state$appStates, _props$controlProps;
|
|
@@ -45,6 +47,20 @@ export const PostChatSurveyPaneStateful = props => {
|
|
|
45
47
|
surveyURL: ((_props$controlProps = props.controlProps) === null || _props$controlProps === void 0 ? void 0 : _props$controlProps.surveyURL) ?? surveyInviteLink,
|
|
46
48
|
...props.controlProps
|
|
47
49
|
};
|
|
50
|
+
if (controlProps.surveyURL) {
|
|
51
|
+
if (!isValidSurveyUrl(controlProps.surveyURL)) {
|
|
52
|
+
TelemetryHelper.logLoadingEvent(LogLevel.ERROR, {
|
|
53
|
+
Event: TelemetryEvent.PostChatSurveyUrlValidationFailed,
|
|
54
|
+
Description: `${controlProps.surveyURL} is not a valid Survey URL`
|
|
55
|
+
});
|
|
56
|
+
controlProps.surveyURL = "";
|
|
57
|
+
} else {
|
|
58
|
+
TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
|
|
59
|
+
Event: TelemetryEvent.PostChatSurveyUrlValidationCompleted,
|
|
60
|
+
Description: `${controlProps.surveyURL} is a valid Survey URL`
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
48
64
|
|
|
49
65
|
// Move focus to the first button
|
|
50
66
|
useEffect(() => {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { isNullOrEmptyString } from "../../../common/utils";
|
|
2
|
+
const validRootDomains = ["microsoft.com", "microsoft.us", "appsplatform.us", "powervirtualagents.cn"];
|
|
3
|
+
const isValidSurveyUrl = url => {
|
|
4
|
+
if (isNullOrEmptyString(url)) {
|
|
5
|
+
return false;
|
|
6
|
+
}
|
|
7
|
+
try {
|
|
8
|
+
const objectUrl = new URL(url);
|
|
9
|
+
if (!objectUrl.origin || objectUrl.origin === "null") {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
const validDomain = validRootDomains.find(domain => objectUrl.origin.endsWith(domain));
|
|
13
|
+
if (validDomain) {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
} catch (error) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
return false;
|
|
20
|
+
};
|
|
21
|
+
export default isValidSurveyUrl;
|
|
@@ -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
|
};
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import { ConversationState } from "./ConversationState";
|
|
2
|
-
import { defaultMiddlewareLocalizedTexts } from "../../components/webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts";
|
|
3
|
-
import { getWidgetCacheIdfromProps, isNullOrUndefined } from "../../common/utils";
|
|
4
|
-
import { defaultClientDataStoreProvider } from "../../common/storage/default/defaultClientDataStoreProvider";
|
|
5
1
|
import { ConfirmationState, Constants, ConversationEndEntity, StorageType } from "../../common/Constants";
|
|
2
|
+
import { getWidgetCacheIdfromProps, isNullOrUndefined } from "../../common/utils";
|
|
3
|
+
import { ConversationState } from "./ConversationState";
|
|
6
4
|
import { StartChatFailureType } from "./StartChatFailureType";
|
|
5
|
+
import { defaultClientDataStoreProvider } from "../../common/storage/default/defaultClientDataStoreProvider";
|
|
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,6 @@
|
|
|
1
|
+
export let ScenarioType;
|
|
2
|
+
(function (ScenarioType) {
|
|
3
|
+
ScenarioType["UserSendMessageStrategy"] = "UserSendMessageStrategy";
|
|
4
|
+
ScenarioType["SystemMessageStrategy"] = "SystemMessageStrategy";
|
|
5
|
+
ScenarioType["ReceivedMessageStrategy"] = "ReceivedMessageStrategy";
|
|
6
|
+
})(ScenarioType || (ScenarioType = {}));
|
|
@@ -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
|
+
};
|