@microsoft/omnichannel-chat-widget 1.8.2-main.4b1a5f0 → 1.8.2-main.5195aba
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/README.md +2 -0
- package/lib/cjs/common/Constants.js +12 -4
- package/lib/cjs/common/telemetry/TelemetryConstants.js +1 -0
- package/lib/cjs/common/utils.js +7 -1
- package/lib/cjs/components/chatbuttonstateful/ChatButtonStateful.js +28 -15
- package/lib/cjs/components/draggable/DraggableChatWidget.js +16 -1
- package/lib/cjs/components/headerstateful/HeaderStateful.js +12 -2
- package/lib/cjs/components/livechatwidget/LiveChatWidget.js +2 -8
- package/lib/cjs/components/livechatwidget/common/createInternetConnectionChangeHandler.js +22 -9
- package/lib/cjs/components/livechatwidget/common/endChat.js +18 -7
- package/lib/cjs/components/livechatwidget/common/initWebChatComposer.js +30 -1
- package/lib/cjs/components/livechatwidget/common/liveChatConfigUtils.js +18 -1
- package/lib/cjs/components/livechatwidget/common/renderSurveyHelpers.js +31 -7
- package/lib/cjs/components/livechatwidget/common/setPostChatContextAndLoadSurvey.js +15 -2
- package/lib/cjs/components/livechatwidget/common/startChat.js +5 -3
- package/lib/cjs/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +22 -11
- package/lib/cjs/components/webchatcontainerstateful/WebChatContainerStateful.js +52 -14
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/channelDataMiddleware.js +4 -3
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/conversationEndMiddleware.js +12 -6
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/queueOverflowHandlerMiddleware.js +45 -0
- package/lib/cjs/contexts/common/LiveChatWidgetActionType.js +3 -1
- package/lib/cjs/contexts/common/LiveChatWidgetContextInitialState.js +3 -1
- package/lib/cjs/contexts/createReducer.js +30 -0
- package/lib/cjs/controller/componentController.js +2 -2
- package/lib/cjs/firstresponselatency/util.js +52 -27
- package/lib/cjs/plugins/newMessageEventHandler.js +12 -6
- package/lib/esm/common/Constants.js +10 -3
- package/lib/esm/common/telemetry/TelemetryConstants.js +1 -0
- package/lib/esm/common/utils.js +4 -0
- package/lib/esm/components/chatbuttonstateful/ChatButtonStateful.js +28 -15
- package/lib/esm/components/draggable/DraggableChatWidget.js +16 -1
- package/lib/esm/components/headerstateful/HeaderStateful.js +12 -2
- package/lib/esm/components/livechatwidget/LiveChatWidget.js +2 -8
- package/lib/esm/components/livechatwidget/common/createInternetConnectionChangeHandler.js +22 -9
- package/lib/esm/components/livechatwidget/common/endChat.js +18 -7
- package/lib/esm/components/livechatwidget/common/initWebChatComposer.js +30 -1
- package/lib/esm/components/livechatwidget/common/liveChatConfigUtils.js +16 -0
- package/lib/esm/components/livechatwidget/common/renderSurveyHelpers.js +33 -9
- package/lib/esm/components/livechatwidget/common/setPostChatContextAndLoadSurvey.js +16 -3
- package/lib/esm/components/livechatwidget/common/startChat.js +5 -3
- package/lib/esm/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +22 -11
- package/lib/esm/components/webchatcontainerstateful/WebChatContainerStateful.js +52 -14
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/channelDataMiddleware.js +4 -4
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/conversationEndMiddleware.js +12 -6
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/queueOverflowHandlerMiddleware.js +38 -0
- package/lib/esm/contexts/common/LiveChatWidgetActionType.js +3 -1
- package/lib/esm/contexts/common/LiveChatWidgetContextInitialState.js +3 -1
- package/lib/esm/contexts/createReducer.js +30 -0
- package/lib/esm/controller/componentController.js +2 -2
- package/lib/esm/firstresponselatency/util.js +49 -25
- package/lib/esm/plugins/newMessageEventHandler.js +12 -6
- package/lib/types/common/Constants.d.ts +9 -3
- package/lib/types/common/telemetry/TelemetryConstants.d.ts +1 -0
- package/lib/types/common/utils.d.ts +5 -0
- package/lib/types/components/livechatwidget/common/liveChatConfigUtils.d.ts +1 -0
- package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/channelDataMiddleware.d.ts +1 -1
- package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/conversationEndMiddleware.d.ts +1 -1
- package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/queueOverflowHandlerMiddleware.d.ts +5 -0
- package/lib/types/contexts/common/ILiveChatWidgetContext.d.ts +2 -0
- package/lib/types/contexts/common/LiveChatWidgetActionType.d.ts +3 -1
- package/lib/types/firstresponselatency/util.d.ts +17 -0
- package/lib/types/plugins/newMessageEventHandler.d.ts +1 -1
- package/package.json +4 -4
|
@@ -3,41 +3,66 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.polyfillMessagePayloadForEvent = exports.isHistoryMessage = exports.getScenarioType = exports.createTrackingMessage = exports.buildMessagePayload = void 0;
|
|
6
|
+
exports.polyfillMessagePayloadForEvent = exports.isHistoryMessage = exports.getScenarioType = exports.extractTimestampFromId = exports.createTrackingMessage = exports.buildMessagePayload = void 0;
|
|
7
7
|
var _Constants = require("./Constants");
|
|
8
8
|
var _Constants2 = require("../common/Constants");
|
|
9
|
+
/**
|
|
10
|
+
* Determines whether a given activity is a historical message.
|
|
11
|
+
*
|
|
12
|
+
* This function checks if the activity is a message type and uses a combination
|
|
13
|
+
* of legacy tags and timestamp-based logic to determine if the message is historical.
|
|
14
|
+
*
|
|
15
|
+
* @param {IActivity} activity - The activity object to evaluate.
|
|
16
|
+
* @param {number} startTime - The start time (in milliseconds since epoch) to compare against.
|
|
17
|
+
* @returns {boolean} - Returns true if the activity is a historical message, false otherwise.
|
|
18
|
+
*
|
|
19
|
+
* Logic:
|
|
20
|
+
* - If the activity type is not a message, it is not historical.
|
|
21
|
+
* - If the activity contains a legacy history message tag, it is considered historical.
|
|
22
|
+
* - Otherwise, the function extracts a timestamp from the activity ID using `extractTimestampFromId`.
|
|
23
|
+
* - If the ID is valid and the timestamp is older than the start time, the message is historical.
|
|
24
|
+
*/
|
|
9
25
|
const isHistoryMessage = (activity, startTime) => {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
26
|
+
var _activity$channelData, _activity$channelData2;
|
|
27
|
+
// Only process message activities
|
|
28
|
+
if ((activity === null || activity === void 0 ? void 0 : activity.type) !== _Constants2.Constants.message) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
15
31
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
32
|
+
// Legacy check for history message tag
|
|
33
|
+
if (activity !== null && activity !== void 0 && (_activity$channelData = activity.channelData) !== null && _activity$channelData !== void 0 && (_activity$channelData2 = _activity$channelData.tags) !== null && _activity$channelData2 !== void 0 && _activity$channelData2.includes(_Constants2.Constants.historyMessageTag)) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
const activityId = extractTimestampFromId(activity);
|
|
37
|
+
const isValidId = !isNaN(activityId) && activityId > 0;
|
|
38
|
+
const isOlderThanStartTime = activityId < startTime;
|
|
39
|
+
const isHistoryById = isValidId && isOlderThanStartTime;
|
|
40
|
+
return isHistoryById;
|
|
41
|
+
};
|
|
42
|
+
exports.isHistoryMessage = isHistoryMessage;
|
|
43
|
+
const extractTimestampFromId = activity => {
|
|
44
|
+
const id = (activity === null || activity === void 0 ? void 0 : activity.id) ?? "";
|
|
20
45
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
46
|
+
// Helper function to get timestamp fallback
|
|
47
|
+
const getTimestampFallback = () => {
|
|
48
|
+
const timestamp = new Date((activity === null || activity === void 0 ? void 0 : activity.timestamp) ?? "").getTime();
|
|
49
|
+
return isNaN(timestamp) ? 0 : timestamp;
|
|
50
|
+
};
|
|
25
51
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
console.error("Error in parsing activity id: ", e);
|
|
52
|
+
// Check if ID looks like a UUID (contains dashes or is very long)
|
|
53
|
+
const UUID_LENGTH_THRESHOLD = 13; // Threshold to distinguish UUIDs from epoch timestamps
|
|
54
|
+
if (id.includes("-") || id.length > UUID_LENGTH_THRESHOLD) {
|
|
55
|
+
// Likely UUID, use timestamp instead
|
|
56
|
+
return getTimestampFallback();
|
|
57
|
+
}
|
|
58
|
+
const activityId = parseInt(id);
|
|
59
|
+
// if activity id is not a number, then we use timestamp field
|
|
60
|
+
if (isNaN(activityId)) {
|
|
61
|
+
return getTimestampFallback();
|
|
37
62
|
}
|
|
38
|
-
return
|
|
63
|
+
return activityId;
|
|
39
64
|
};
|
|
40
|
-
exports.
|
|
65
|
+
exports.extractTimestampFromId = extractTimestampFromId;
|
|
41
66
|
const buildMessagePayload = (activity, userId) => {
|
|
42
67
|
var _text, _text2, _activity$channelData3, _activity$from;
|
|
43
68
|
return {
|
|
@@ -12,13 +12,13 @@ var _Constants2 = require("../common/Constants");
|
|
|
12
12
|
var _FirstResponseLatencyTracker = require("../firstresponselatency/FirstResponseLatencyTracker");
|
|
13
13
|
var _TelemetryHelper = require("../common/telemetry/TelemetryHelper");
|
|
14
14
|
var _TelemetryManager = require("../common/telemetry/TelemetryManager");
|
|
15
|
-
const createOnNewAdapterActivityHandler = (chatId, userId) => {
|
|
15
|
+
const createOnNewAdapterActivityHandler = (chatId, userId, startTime) => {
|
|
16
16
|
// Hooking the message tracker in the listener, a bit invasive but easier to control.
|
|
17
17
|
const firstResponseLatencyTracker = new _FirstResponseLatencyTracker.FirstResponseLatencyTracker();
|
|
18
18
|
// epoch time in utc for when start to listen.
|
|
19
19
|
// We dont longer have a mechanism to know if a message is history or new, so any message older than the time we start listening will be considered a history message.
|
|
20
20
|
// this is a workaround for the fact that we dont have a way to identify if a message is history or new, and it will provide consistency across different scenarios
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
let isHistoryMessageReceivedEventRaised = false;
|
|
23
23
|
const onNewAdapterActivityHandler = activity => {
|
|
24
24
|
raiseMessageEvent(activity);
|
|
@@ -41,6 +41,7 @@ const createOnNewAdapterActivityHandler = (chatId, userId) => {
|
|
|
41
41
|
});
|
|
42
42
|
};
|
|
43
43
|
const systemMessageStrategy = activity => {
|
|
44
|
+
var _TelemetryManager$Int3;
|
|
44
45
|
const payload = (0, _util.buildMessagePayload)(activity, userId);
|
|
45
46
|
payload.messageType = _Constants2.Constants.systemMessageTag;
|
|
46
47
|
if ((0, _util.isHistoryMessage)(activity, startTime)) {
|
|
@@ -48,6 +49,11 @@ const createOnNewAdapterActivityHandler = (chatId, userId) => {
|
|
|
48
49
|
historyMessageStrategy((0, _util.polyfillMessagePayloadForEvent)(activity, payload, (_TelemetryManager$Int2 = _TelemetryManager.TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int2 === void 0 ? void 0 : _TelemetryManager$Int2.conversationId));
|
|
49
50
|
return;
|
|
50
51
|
}
|
|
52
|
+
const newMessageReceivedEvent = {
|
|
53
|
+
eventName: _TelemetryConstants.BroadcastEvent.NewMessageReceived,
|
|
54
|
+
payload: (0, _util.polyfillMessagePayloadForEvent)(activity, payload, (_TelemetryManager$Int3 = _TelemetryManager.TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int3 === void 0 ? void 0 : _TelemetryManager$Int3.conversationId)
|
|
55
|
+
};
|
|
56
|
+
_omnichannelChatComponents.BroadcastService.postMessage(newMessageReceivedEvent);
|
|
51
57
|
_TelemetryHelper.TelemetryHelper.logActionEventToAllTelemetry(_TelemetryConstants.LogLevel.INFO, {
|
|
52
58
|
Event: _TelemetryConstants.TelemetryEvent.SystemMessageReceived,
|
|
53
59
|
Description: "System message received"
|
|
@@ -83,20 +89,20 @@ const createOnNewAdapterActivityHandler = (chatId, userId) => {
|
|
|
83
89
|
return true;
|
|
84
90
|
};
|
|
85
91
|
const receivedMessageStrategy = activity => {
|
|
86
|
-
var _TelemetryManager$
|
|
92
|
+
var _TelemetryManager$Int5;
|
|
87
93
|
if (!isValidMessage(activity)) return;
|
|
88
94
|
const isHistoryMessageReceived = (0, _util.isHistoryMessage)(activity, startTime);
|
|
89
95
|
const payload = (0, _util.buildMessagePayload)(activity, userId);
|
|
90
96
|
payload.messageType = _Constants2.Constants.userMessageTag;
|
|
91
97
|
if (isHistoryMessageReceived) {
|
|
92
|
-
var _TelemetryManager$
|
|
93
|
-
historyMessageStrategy((0, _util.polyfillMessagePayloadForEvent)(activity, payload, (_TelemetryManager$
|
|
98
|
+
var _TelemetryManager$Int4;
|
|
99
|
+
historyMessageStrategy((0, _util.polyfillMessagePayloadForEvent)(activity, payload, (_TelemetryManager$Int4 = _TelemetryManager.TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int4 === void 0 ? void 0 : _TelemetryManager$Int4.conversationId));
|
|
94
100
|
return;
|
|
95
101
|
}
|
|
96
102
|
firstResponseLatencyTracker.stopClock(payload);
|
|
97
103
|
const newMessageReceivedEvent = {
|
|
98
104
|
eventName: _TelemetryConstants.BroadcastEvent.NewMessageReceived,
|
|
99
|
-
payload: (0, _util.polyfillMessagePayloadForEvent)(activity, payload, (_TelemetryManager$
|
|
105
|
+
payload: (0, _util.polyfillMessagePayloadForEvent)(activity, payload, (_TelemetryManager$Int5 = _TelemetryManager.TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int5 === void 0 ? void 0 : _TelemetryManager$Int5.conversationId)
|
|
100
106
|
};
|
|
101
107
|
_omnichannelChatComponents.BroadcastService.postMessage(newMessageReceivedEvent);
|
|
102
108
|
_TelemetryHelper.TelemetryHelper.logActionEventToAllTelemetry(_TelemetryConstants.LogLevel.INFO, {
|
|
@@ -16,6 +16,9 @@ _defineProperty(Constants, "channelMessageTag", "channel");
|
|
|
16
16
|
_defineProperty(Constants, "historyMessageTag", "history");
|
|
17
17
|
_defineProperty(Constants, "agentEndConversationMessageTag", "agentendconversation");
|
|
18
18
|
_defineProperty(Constants, "supervisorForceCloseMessageTag", "supervisorforceclosedconversation");
|
|
19
|
+
_defineProperty(Constants, "endConversationalSurveyMessageTag", "endconversationalsurvey");
|
|
20
|
+
_defineProperty(Constants, "startConversationalSurveyMessageTag", "startconversationalsurvey");
|
|
21
|
+
_defineProperty(Constants, "c2ConversationalSurveyMessageTag", "c2conversationalsurvey");
|
|
19
22
|
_defineProperty(Constants, "receivedMessageClassName", "ms_lcw_webchat_received_message");
|
|
20
23
|
_defineProperty(Constants, "sentMessageClassName", "ms_lcw_webchat_sent_message");
|
|
21
24
|
_defineProperty(Constants, "webchatChannelId", "webchat");
|
|
@@ -105,8 +108,7 @@ _defineProperty(Constants, "TargetRelationshipAttributes", "noopener noreferrer"
|
|
|
105
108
|
// Markdown icons
|
|
106
109
|
_defineProperty(Constants, "OpenLinkIconCssClass", "webchat__render-markdown__external-link-icon");
|
|
107
110
|
// internet connection test
|
|
108
|
-
_defineProperty(Constants, "
|
|
109
|
-
_defineProperty(Constants, "internetConnectionTestUrlText", "Omnichannel Connect Test");
|
|
111
|
+
_defineProperty(Constants, "internetConnectionTestPath", "/livechatwidget/version.txt");
|
|
110
112
|
_defineProperty(Constants, "ChatWidgetStateChangedPrefix", "ChatWidgetStateChanged");
|
|
111
113
|
_defineProperty(Constants, "PostChatLoadingDurationInMs", 2000);
|
|
112
114
|
_defineProperty(Constants, "BrowserUnloadConfirmationMessage", "Do you want to leave chat?");
|
|
@@ -122,9 +124,10 @@ _defineProperty(Constants, "InitContextParamsResponse", "initContextParamsRespon
|
|
|
122
124
|
_defineProperty(Constants, "OCOriginalMessageId", "OriginalMessageId");
|
|
123
125
|
_defineProperty(Constants, "WebchatSequenceIdAttribute", "webchat:sequence-id");
|
|
124
126
|
_defineProperty(Constants, "MessageSequenceIdOverride", "MessageSequenceIdOverride");
|
|
127
|
+
_defineProperty(Constants, "EndConversationDueToOverflow", "endconversationduetooverflow");
|
|
125
128
|
export const Regex = (_class = /*#__PURE__*/_createClass(function Regex() {
|
|
126
129
|
_classCallCheck(this, Regex);
|
|
127
|
-
}), _defineProperty(_class, "EmailRegex", "(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"
|
|
130
|
+
}), _defineProperty(_class, "EmailRegex", "^(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\")@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?)*|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\])$"), _class);
|
|
128
131
|
export let HtmlIdNames = /*#__PURE__*/_createClass(function HtmlIdNames() {
|
|
129
132
|
_classCallCheck(this, HtmlIdNames);
|
|
130
133
|
});
|
|
@@ -220,6 +223,10 @@ export let ConversationMode;
|
|
|
220
223
|
ConversationMode["Regular"] = "192350000";
|
|
221
224
|
ConversationMode["Persistent"] = "192350001";
|
|
222
225
|
})(ConversationMode || (ConversationMode = {}));
|
|
226
|
+
export let SurveyProvider;
|
|
227
|
+
(function (SurveyProvider) {
|
|
228
|
+
SurveyProvider["MicrosoftCopilotStudio"] = "600990001";
|
|
229
|
+
})(SurveyProvider || (SurveyProvider = {}));
|
|
223
230
|
export let LiveWorkItemState;
|
|
224
231
|
(function (LiveWorkItemState) {
|
|
225
232
|
LiveWorkItemState["Active"] = "Active";
|
|
@@ -184,6 +184,7 @@ export let TelemetryEvent;
|
|
|
184
184
|
TelemetryEvent["BotAuthActivityUndefinedSignInId"] = "BotAuthActivityUndefinedSignInId";
|
|
185
185
|
TelemetryEvent["ThirdPartyCookiesBlocked"] = "ThirdPartyCookiesBlocked";
|
|
186
186
|
TelemetryEvent["ParticipantsRemovedEvent"] = "ParticipantsRemovedEvent";
|
|
187
|
+
TelemetryEvent["QueueOverflowEvent"] = "QueueOverflowEvent";
|
|
187
188
|
TelemetryEvent["ProcessingHTMLTextMiddlewareFailed"] = "ProcessingHTMLTextMiddlewareFailed";
|
|
188
189
|
TelemetryEvent["ProcessingSanitizationMiddlewareFailed"] = "ProcessingSanitizationMiddlewareFailed";
|
|
189
190
|
TelemetryEvent["FormatTagsMiddlewareJSONStringifyFailed"] = "FormatTagsMiddlewareJSONStringifyFailed";
|
package/lib/esm/common/utils.js
CHANGED
|
@@ -453,4 +453,8 @@ export function getDeviceType() {
|
|
|
453
453
|
} else {
|
|
454
454
|
return "standard";
|
|
455
455
|
}
|
|
456
|
+
}
|
|
457
|
+
export function isEndConversationDueToOverflowActivity(activity) {
|
|
458
|
+
var _activity$channelData, _activity$channelData2;
|
|
459
|
+
return (activity === null || activity === void 0 ? void 0 : (_activity$channelData = activity.channelData) === null || _activity$channelData === void 0 ? void 0 : _activity$channelData.tags) && Array.isArray(activity === null || activity === void 0 ? void 0 : (_activity$channelData2 = activity.channelData) === null || _activity$channelData2 === void 0 ? void 0 : _activity$channelData2.tags) && activity.channelData.tags.includes(Constants.EndConversationDueToOverflow);
|
|
456
460
|
}
|
|
@@ -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 _buttonProps$controlP, _props$buttonProps, _props$buttonProps$co, _props$buttonProps2, _props$buttonProps2$c, _props$buttonProps3, _props$buttonProps3$c;
|
|
14
|
+
var _buttonProps$controlP, _props$buttonProps, _props$buttonProps$co, _props$buttonProps2, _props$buttonProps2$c, _outOfOfficeButtonPro, _outOfOfficeButtonPro2, _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();
|
|
@@ -30,7 +30,10 @@ export const ChatButtonStateful = props => {
|
|
|
30
30
|
} = props;
|
|
31
31
|
//Setting OutOfOperatingHours Flag
|
|
32
32
|
//Setting OutOfOperatingHours Flag - to string conversion to normalize the value (could be boolean from other states or string directly from config)
|
|
33
|
-
|
|
33
|
+
// Initialize with the current state value to prevent visual flicker
|
|
34
|
+
const [outOfOperatingHours, setOutOfOperatingHours] = useState(() => {
|
|
35
|
+
return state.appStates.conversationState === ConversationState.Closed && state.appStates.outsideOperatingHours;
|
|
36
|
+
});
|
|
34
37
|
const ref = useRef(() => {
|
|
35
38
|
return;
|
|
36
39
|
});
|
|
@@ -62,33 +65,38 @@ export const ChatButtonStateful = props => {
|
|
|
62
65
|
};
|
|
63
66
|
const outOfOfficeStyleProps = Object.assign({}, defaultOutOfOfficeChatButtonStyleProps, outOfOfficeButtonProps === null || outOfOfficeButtonProps === void 0 ? void 0 : outOfOfficeButtonProps.styleProps);
|
|
64
67
|
const controlProps = {
|
|
68
|
+
...(buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.controlProps),
|
|
65
69
|
id: "oc-lcw-chat-button",
|
|
66
70
|
dir: state.domainStates.globalDir,
|
|
67
71
|
titleText: "Let's Chat!",
|
|
68
72
|
subtitleText: "We're online.",
|
|
69
73
|
hideNotificationBubble: (buttonProps === null || buttonProps === void 0 ? void 0 : (_buttonProps$controlP = buttonProps.controlProps) === null || _buttonProps$controlP === void 0 ? void 0 : _buttonProps$controlP.hideNotificationBubble) === true || state.appStates.isMinimized === false,
|
|
70
74
|
unreadMessageCount: state.appStates.unreadMessageCount ? state.appStates.unreadMessageCount > Constants.maximumUnreadMessageCount ? (_props$buttonProps = props.buttonProps) === null || _props$buttonProps === void 0 ? void 0 : (_props$buttonProps$co = _props$buttonProps.controlProps) === null || _props$buttonProps$co === void 0 ? void 0 : _props$buttonProps$co.largeUnreadMessageString : state.appStates.unreadMessageCount.toString() : "0",
|
|
71
|
-
onClick: () => ref.current(),
|
|
72
75
|
unreadMessageString: (_props$buttonProps2 = props.buttonProps) === null || _props$buttonProps2 === void 0 ? void 0 : (_props$buttonProps2$c = _props$buttonProps2.controlProps) === null || _props$buttonProps2$c === void 0 ? void 0 : _props$buttonProps2$c.unreadMessageString,
|
|
73
|
-
|
|
76
|
+
// Regular chat button onClick - this will always take precedence
|
|
77
|
+
onClick: () => ref.current()
|
|
74
78
|
};
|
|
75
79
|
const outOfOfficeControlProps = {
|
|
80
|
+
// Only take specific properties from outOfOfficeButtonProps, never onClick
|
|
76
81
|
id: "oc-lcw-chat-button",
|
|
77
82
|
dir: state.domainStates.globalDir,
|
|
78
|
-
titleText: "We're Offline",
|
|
79
|
-
subtitleText: "No agents available",
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
titleText: (outOfOfficeButtonProps === null || outOfOfficeButtonProps === void 0 ? void 0 : (_outOfOfficeButtonPro = outOfOfficeButtonProps.controlProps) === null || _outOfOfficeButtonPro === void 0 ? void 0 : _outOfOfficeButtonPro.titleText) || "We're Offline",
|
|
84
|
+
subtitleText: (outOfOfficeButtonProps === null || outOfOfficeButtonProps === void 0 ? void 0 : (_outOfOfficeButtonPro2 = outOfOfficeButtonProps.controlProps) === null || _outOfOfficeButtonPro2 === void 0 ? void 0 : _outOfOfficeButtonPro2.subtitleText) || "No agents available",
|
|
85
|
+
unreadMessageString: (_props$buttonProps3 = props.buttonProps) === null || _props$buttonProps3 === void 0 ? void 0 : (_props$buttonProps3$c = _props$buttonProps3.controlProps) === null || _props$buttonProps3$c === void 0 ? void 0 : _props$buttonProps3$c.unreadMessageString,
|
|
86
|
+
...(outOfOfficeButtonProps === null || outOfOfficeButtonProps === void 0 ? void 0 : outOfOfficeButtonProps.controlProps),
|
|
87
|
+
// Out-of-office specific onClick - this will ALWAYS take precedence
|
|
88
|
+
onClick: () => {
|
|
89
|
+
if (state.appStates.isMinimized) {
|
|
90
|
+
dispatch({
|
|
91
|
+
type: LiveChatWidgetActionType.SET_MINIMIZED,
|
|
92
|
+
payload: false
|
|
93
|
+
});
|
|
94
|
+
}
|
|
85
95
|
dispatch({
|
|
86
96
|
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE,
|
|
87
97
|
payload: ConversationState.OutOfOffice
|
|
88
98
|
});
|
|
89
|
-
}
|
|
90
|
-
unreadMessageString: (_props$buttonProps3 = props.buttonProps) === null || _props$buttonProps3 === void 0 ? void 0 : (_props$buttonProps3$c = _props$buttonProps3.controlProps) === null || _props$buttonProps3$c === void 0 ? void 0 : _props$buttonProps3$c.unreadMessageString,
|
|
91
|
-
...(outOfOfficeButtonProps === null || outOfOfficeButtonProps === void 0 ? void 0 : outOfOfficeButtonProps.controlProps)
|
|
99
|
+
}
|
|
92
100
|
};
|
|
93
101
|
useEffect(() => {
|
|
94
102
|
TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
|
|
@@ -114,8 +122,13 @@ export const ChatButtonStateful = props => {
|
|
|
114
122
|
// If the conversation state is closed, check if we are outside operating hours
|
|
115
123
|
const isOutsideOperatingHours = state.appStates.outsideOperatingHours;
|
|
116
124
|
setOutOfOperatingHours(isOutsideOperatingHours);
|
|
125
|
+
} else {
|
|
126
|
+
// If conversation state is not Closed, we should not be in out-of-office mode
|
|
127
|
+
if (outOfOperatingHours) {
|
|
128
|
+
setOutOfOperatingHours(false);
|
|
129
|
+
}
|
|
117
130
|
}
|
|
118
|
-
}, [state.appStates.conversationState]);
|
|
131
|
+
}, [state.appStates.conversationState, state.appStates.outsideOperatingHours, state.appStates.isMinimized]);
|
|
119
132
|
return /*#__PURE__*/React.createElement(ChatButton, {
|
|
120
133
|
componentOverrides: buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.componentOverrides,
|
|
121
134
|
controlProps: outOfOperatingHours ? outOfOfficeControlProps : controlProps,
|
|
@@ -25,8 +25,11 @@ const DraggableChatWidget = props => {
|
|
|
25
25
|
};
|
|
26
26
|
const calculateOffsetsWithinViewport = useCallback((id, offset, delta) => {
|
|
27
27
|
const draggableElement = document.getElementById(id);
|
|
28
|
+
if (isNullOrUndefined(draggableElement)) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
28
31
|
const positionRelativeToViewport = draggableElement.getBoundingClientRect();
|
|
29
|
-
if (isNullOrUndefined(
|
|
32
|
+
if (isNullOrUndefined(positionRelativeToViewport) || isNullOrUndefined(offset.offsetLeft) || isNullOrUndefined(offset.offsetTop)) {
|
|
30
33
|
return;
|
|
31
34
|
}
|
|
32
35
|
let offsetLeft = offset.offsetLeft;
|
|
@@ -68,6 +71,9 @@ const DraggableChatWidget = props => {
|
|
|
68
71
|
}
|
|
69
72
|
const cacheInitialPosition = () => {
|
|
70
73
|
const draggableElement = document.getElementById(props.elementId);
|
|
74
|
+
if (isNullOrUndefined(draggableElement)) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
71
77
|
const offsetLeft = draggableElement.offsetLeft;
|
|
72
78
|
const offsetTop = draggableElement.offsetTop;
|
|
73
79
|
setInitialPosition({
|
|
@@ -77,6 +83,9 @@ const DraggableChatWidget = props => {
|
|
|
77
83
|
};
|
|
78
84
|
const calculateOffsets = () => {
|
|
79
85
|
const draggableElement = document.getElementById(props.elementId);
|
|
86
|
+
if (isNullOrUndefined(draggableElement)) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
80
89
|
const offsetLeft = draggableElement.offsetLeft;
|
|
81
90
|
const offsetTop = draggableElement.offsetTop;
|
|
82
91
|
|
|
@@ -111,6 +120,9 @@ const DraggableChatWidget = props => {
|
|
|
111
120
|
resetPosition(initialPosition);
|
|
112
121
|
} else if (state.appStates.isMinimized) {
|
|
113
122
|
const draggableElement = document.getElementById(props.elementId);
|
|
123
|
+
if (isNullOrUndefined(draggableElement)) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
114
126
|
const offsetLeft = draggableElement.offsetLeft;
|
|
115
127
|
const offsetTop = draggableElement.offsetTop;
|
|
116
128
|
if (!cachedPosition) {
|
|
@@ -135,6 +147,9 @@ const DraggableChatWidget = props => {
|
|
|
135
147
|
|
|
136
148
|
// Update position via DOM manipulation to prevent <Stack/> continuously rendering on style change causing high CPU spike
|
|
137
149
|
const draggableElement = document.getElementById(props.elementId);
|
|
150
|
+
if (isNullOrUndefined(draggableElement)) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
138
153
|
repositionElement(draggableElement, offsetLeft, offsetTop);
|
|
139
154
|
setPosition({
|
|
140
155
|
offsetLeft,
|
|
@@ -28,7 +28,10 @@ export const HeaderStateful = props => {
|
|
|
28
28
|
endChat
|
|
29
29
|
} = props;
|
|
30
30
|
//Setting OutOfOperatingHours Flag
|
|
31
|
-
|
|
31
|
+
// Initialize with the current state value to prevent visual flicker
|
|
32
|
+
const [outOfOperatingHours, setOutOfOperatingHours] = useState(() => {
|
|
33
|
+
return state.appStates.conversationState === ConversationState.Closed && state.appStates.outsideOperatingHours;
|
|
34
|
+
});
|
|
32
35
|
const outOfOfficeStyleProps = Object.assign({}, defaultOutOfOfficeHeaderStyleProps, outOfOfficeHeaderProps === null || outOfOfficeHeaderProps === void 0 ? void 0 : outOfOfficeHeaderProps.styleProps);
|
|
33
36
|
|
|
34
37
|
// For some reason state object is not getting updated values in this component
|
|
@@ -103,6 +106,13 @@ export const HeaderStateful = props => {
|
|
|
103
106
|
type: LiveChatWidgetActionType.SET_MINIMIZED,
|
|
104
107
|
payload: true
|
|
105
108
|
});
|
|
109
|
+
// Ensure conversation state remains Closed to maintain out-of-office mode
|
|
110
|
+
if (state.appStates.conversationState !== ConversationState.Closed) {
|
|
111
|
+
dispatch({
|
|
112
|
+
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE,
|
|
113
|
+
payload: ConversationState.Closed
|
|
114
|
+
});
|
|
115
|
+
}
|
|
106
116
|
TelemetryHelper.logActionEventToAllTelemetry(LogLevel.INFO, {
|
|
107
117
|
Event: TelemetryEvent.MinimizeChatActionCompleted,
|
|
108
118
|
Description: "Header Minimize action completed."
|
|
@@ -132,7 +142,7 @@ export const HeaderStateful = props => {
|
|
|
132
142
|
const isOutsideOperatingHours = state.appStates.outsideOperatingHours;
|
|
133
143
|
setOutOfOperatingHours(isOutsideOperatingHours);
|
|
134
144
|
}
|
|
135
|
-
}, [state.appStates.conversationState]);
|
|
145
|
+
}, [state.appStates.conversationState, state.appStates.outsideOperatingHours]);
|
|
136
146
|
if (props.draggable === true) {
|
|
137
147
|
var _generalStyleProps;
|
|
138
148
|
const styleProps = outOfOperatingHours || state.appStates.conversationState === ConversationState.OutOfOffice ? outOfOfficeStyleProps : headerProps === null || headerProps === void 0 ? void 0 : headerProps.styleProps;
|
|
@@ -2,7 +2,6 @@ import React, { useEffect, useReducer, useState } from "react";
|
|
|
2
2
|
import { ChatAdapterStore } from "../../contexts/ChatAdapterStore";
|
|
3
3
|
import { ChatContextStore } from "../../contexts/ChatContextStore";
|
|
4
4
|
import { ChatSDKStore } from "../../contexts/ChatSDKStore";
|
|
5
|
-
import ErrorBoundary from "../errorboundary/ErrorBoundary";
|
|
6
5
|
import { FacadeChatSDK } from "../../common/facades/FacadeChatSDK";
|
|
7
6
|
import { FacadeChatSDKStore } from "../../contexts/FacadeChatSDKStore";
|
|
8
7
|
import LiveChatWidgetStateful from "./livechatwidgetstateful/LiveChatWidgetStateful";
|
|
@@ -11,7 +10,6 @@ import { getLiveChatWidgetContextInitialState } from "../../contexts/common/Live
|
|
|
11
10
|
import { getMockChatSDKIfApplicable } from "./common/getMockChatSDKIfApplicable";
|
|
12
11
|
import { isNullOrUndefined } from "../../common/utils";
|
|
13
12
|
import { isPersistentChatEnabled } from "./common/liveChatConfigUtils";
|
|
14
|
-
import { logWidgetLoadWithUnexpectedError } from "./common/startChatErrorHandler";
|
|
15
13
|
import overridePropsOnMockIfApplicable from "./common/overridePropsOnMockIfApplicable";
|
|
16
14
|
import { registerTelemetryLoggers } from "./common/registerTelemetryLoggers";
|
|
17
15
|
export const LiveChatWidget = props => {
|
|
@@ -44,11 +42,7 @@ export const LiveChatWidget = props => {
|
|
|
44
42
|
useEffect(() => {
|
|
45
43
|
registerTelemetryLoggers(props, dispatch);
|
|
46
44
|
}, [dispatch]);
|
|
47
|
-
return /*#__PURE__*/React.createElement(
|
|
48
|
-
onError: error => {
|
|
49
|
-
logWidgetLoadWithUnexpectedError(error);
|
|
50
|
-
}
|
|
51
|
-
}, /*#__PURE__*/React.createElement(FacadeChatSDKStore.Provider, {
|
|
45
|
+
return /*#__PURE__*/React.createElement(FacadeChatSDKStore.Provider, {
|
|
52
46
|
value: [facadeChatSDK, setFacadeChatSDK]
|
|
53
47
|
}, /*#__PURE__*/React.createElement(ChatSDKStore.Provider, {
|
|
54
48
|
value: chatSDK
|
|
@@ -56,6 +50,6 @@ export const LiveChatWidget = props => {
|
|
|
56
50
|
value: [adapter, setAdapter]
|
|
57
51
|
}, /*#__PURE__*/React.createElement(ChatContextStore.Provider, {
|
|
58
52
|
value: [state, dispatch]
|
|
59
|
-
}, /*#__PURE__*/React.createElement(LiveChatWidgetStateful, props)))))
|
|
53
|
+
}, /*#__PURE__*/React.createElement(LiveChatWidgetStateful, props)))));
|
|
60
54
|
};
|
|
61
55
|
export default LiveChatWidget;
|
|
@@ -7,34 +7,47 @@ import { TelemetryHelper } from "../../../common/telemetry/TelemetryHelper";
|
|
|
7
7
|
import { defaultMiddlewareLocalizedTexts } from "../../webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts";
|
|
8
8
|
import { executeReducer } from "../../../contexts/createReducer";
|
|
9
9
|
import { LiveChatWidgetActionType } from "../../../contexts/common/LiveChatWidgetActionType";
|
|
10
|
-
const
|
|
10
|
+
const getRegionBasedInternetTestUrl = widgetSnippet => {
|
|
11
|
+
var _widgetSnippet$match;
|
|
12
|
+
if (!widgetSnippet) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
const widgetSnippetSourceRegex = new RegExp("src=\"(https:\\/\\/[\\w-.]+)[\\w-.\\/]+\"");
|
|
16
|
+
const baseCdnUrl = (_widgetSnippet$match = widgetSnippet.match(widgetSnippetSourceRegex)) === null || _widgetSnippet$match === void 0 ? void 0 : _widgetSnippet$match[1];
|
|
17
|
+
return baseCdnUrl ? `${baseCdnUrl}${Constants.internetConnectionTestPath}` : null;
|
|
18
|
+
};
|
|
19
|
+
const isInternetConnected = async testUrl => {
|
|
11
20
|
try {
|
|
12
|
-
const response = await fetch(
|
|
13
|
-
|
|
14
|
-
|
|
21
|
+
const response = await fetch(testUrl, {
|
|
22
|
+
method: "GET",
|
|
23
|
+
cache: "no-cache"
|
|
24
|
+
});
|
|
25
|
+
return response.ok;
|
|
15
26
|
} catch {
|
|
16
27
|
return false;
|
|
17
28
|
}
|
|
18
29
|
};
|
|
19
30
|
export const createInternetConnectionChangeHandler = async state => {
|
|
20
31
|
const handler = async () => {
|
|
21
|
-
|
|
32
|
+
var _inMemoryState$domain, _inMemoryState$domain2;
|
|
22
33
|
const inMemoryState = executeReducer(state, {
|
|
23
34
|
type: LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
|
|
24
35
|
payload: null
|
|
25
36
|
});
|
|
37
|
+
const testUrl = getRegionBasedInternetTestUrl((_inMemoryState$domain = inMemoryState.domainStates.liveChatConfig) === null || _inMemoryState$domain === void 0 ? void 0 : (_inMemoryState$domain2 = _inMemoryState$domain.LiveWSAndLiveChatEngJoin) === null || _inMemoryState$domain2 === void 0 ? void 0 : _inMemoryState$domain2.msdyn_widgetsnippet);
|
|
38
|
+
const connected = testUrl ? await isInternetConnected(testUrl) : false;
|
|
26
39
|
if (!connected) {
|
|
27
|
-
var _inMemoryState$
|
|
40
|
+
var _inMemoryState$domain3, _inMemoryState$domain4;
|
|
28
41
|
TelemetryHelper.logActionEvent(LogLevel.WARN, {
|
|
29
42
|
Event: TelemetryEvent.NetworkDisconnected
|
|
30
43
|
});
|
|
31
|
-
NotificationHandler.notifyError(NotificationScenarios.InternetConnection, (inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$
|
|
44
|
+
NotificationHandler.notifyError(NotificationScenarios.InternetConnection, (inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$domain3 = inMemoryState.domainStates) === null || _inMemoryState$domain3 === void 0 ? void 0 : (_inMemoryState$domain4 = _inMemoryState$domain3.middlewareLocalizedTexts) === null || _inMemoryState$domain4 === void 0 ? void 0 : _inMemoryState$domain4.MIDDLEWARE_BANNER_NO_INTERNET_CONNECTION) ?? defaultMiddlewareLocalizedTexts.MIDDLEWARE_BANNER_NO_INTERNET_CONNECTION);
|
|
32
45
|
} else {
|
|
33
|
-
var _inMemoryState$
|
|
46
|
+
var _inMemoryState$domain5, _inMemoryState$domain6;
|
|
34
47
|
TelemetryHelper.logActionEvent(LogLevel.WARN, {
|
|
35
48
|
Event: TelemetryEvent.NetworkReconnected
|
|
36
49
|
});
|
|
37
|
-
NotificationHandler.notifySuccess(NotificationScenarios.InternetConnection, (inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$
|
|
50
|
+
NotificationHandler.notifySuccess(NotificationScenarios.InternetConnection, (inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$domain5 = inMemoryState.domainStates) === null || _inMemoryState$domain5 === void 0 ? void 0 : (_inMemoryState$domain6 = _inMemoryState$domain5.middlewareLocalizedTexts) === null || _inMemoryState$domain6 === void 0 ? void 0 : _inMemoryState$domain6.MIDDLEWARE_BANNER_INTERNET_BACK_ONLINE) ?? defaultMiddlewareLocalizedTexts.MIDDLEWARE_BANNER_INTERNET_BACK_ONLINE);
|
|
38
51
|
BroadcastService.postMessage({
|
|
39
52
|
eventName: BroadcastEvent.NetworkReconnected
|
|
40
53
|
});
|
|
@@ -16,7 +16,7 @@ import { uuidv4 } from "@microsoft/omnichannel-chat-sdk";
|
|
|
16
16
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
17
17
|
const prepareEndChat = async (props, facadeChatSDK, state, dispatch, setAdapter, setWebChatStyles, adapter) => {
|
|
18
18
|
try {
|
|
19
|
-
var _conversationDetails$, _state$domainStates, _state$
|
|
19
|
+
var _conversationDetails$, _state$domainStates, _state$appStates5;
|
|
20
20
|
const {
|
|
21
21
|
chatConfig
|
|
22
22
|
} = props;
|
|
@@ -27,7 +27,7 @@ const prepareEndChat = async (props, facadeChatSDK, state, dispatch, setAdapter,
|
|
|
27
27
|
|
|
28
28
|
// Use Case: When post chat is not configured
|
|
29
29
|
if ((conversationDetails === null || conversationDetails === void 0 ? void 0 : (_conversationDetails$ = conversationDetails.canRenderPostChat) === null || _conversationDetails$ === void 0 ? void 0 : _conversationDetails$.toLowerCase()) === Constants.false) {
|
|
30
|
-
var _state$appStates;
|
|
30
|
+
var _state$appStates, _state$appStates2, _state$appStates3;
|
|
31
31
|
// If ended by customer, just close chat
|
|
32
32
|
if ((state === null || state === void 0 ? void 0 : (_state$appStates = state.appStates) === null || _state$appStates === void 0 ? void 0 : _state$appStates.conversationEndedBy) === ConversationEndEntity.Customer) {
|
|
33
33
|
TelemetryHelper.logSDKEvent(LogLevel.INFO, {
|
|
@@ -38,6 +38,13 @@ const prepareEndChat = async (props, facadeChatSDK, state, dispatch, setAdapter,
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
// Use Case: If ended by Agent, stay chat in InActive state
|
|
41
|
+
let isConversationalSurveyEnabled = state.appStates.isConversationalSurveyEnabled;
|
|
42
|
+
if (isConversationalSurveyEnabled && ((state === null || state === void 0 ? void 0 : (_state$appStates2 = state.appStates) === null || _state$appStates2 === void 0 ? void 0 : _state$appStates2.conversationEndedBy) === ConversationEndEntity.Agent || (state === null || state === void 0 ? void 0 : (_state$appStates3 = state.appStates) === null || _state$appStates3 === void 0 ? void 0 : _state$appStates3.conversationEndedBy) === ConversationEndEntity.Bot)) {
|
|
43
|
+
dispatch({
|
|
44
|
+
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE,
|
|
45
|
+
payload: ConversationState.InActive
|
|
46
|
+
});
|
|
47
|
+
}
|
|
41
48
|
return;
|
|
42
49
|
}
|
|
43
50
|
|
|
@@ -53,7 +60,7 @@ const prepareEndChat = async (props, facadeChatSDK, state, dispatch, setAdapter,
|
|
|
53
60
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
54
61
|
const postchatContext = (await getPostChatContext(facadeChatSDK, state, dispatch)) ?? (state === null || state === void 0 ? void 0 : (_state$domainStates = state.domainStates) === null || _state$domainStates === void 0 ? void 0 : _state$domainStates.postChatContext);
|
|
55
62
|
if (postchatContext === undefined) {
|
|
56
|
-
var _state$
|
|
63
|
+
var _state$appStates4;
|
|
57
64
|
BroadcastService.postMessage({
|
|
58
65
|
eventName: BroadcastEvent.OnWidgetError,
|
|
59
66
|
payload: {
|
|
@@ -62,7 +69,7 @@ const prepareEndChat = async (props, facadeChatSDK, state, dispatch, setAdapter,
|
|
|
62
69
|
});
|
|
63
70
|
|
|
64
71
|
// For Customer intiated conversations, just close chat widget
|
|
65
|
-
if ((state === null || state === void 0 ? void 0 : (_state$
|
|
72
|
+
if ((state === null || state === void 0 ? void 0 : (_state$appStates4 = state.appStates) === null || _state$appStates4 === void 0 ? void 0 : _state$appStates4.conversationEndedBy) === ConversationEndEntity.Customer) {
|
|
66
73
|
TelemetryHelper.logSDKEvent(LogLevel.INFO, {
|
|
67
74
|
Event: TelemetryEvent.PrepareEndChat,
|
|
68
75
|
Description: PrepareEndChatDescriptionConstants.ConversationEndedByCustomerWithInvalidPostChat
|
|
@@ -80,11 +87,11 @@ const prepareEndChat = async (props, facadeChatSDK, state, dispatch, setAdapter,
|
|
|
80
87
|
}
|
|
81
88
|
|
|
82
89
|
// Log PrepareEndChat if conversation ended by customer (bot and agent cases are handled in LiveChatWidgetStateful.tsx)
|
|
83
|
-
if (state !== null && state !== void 0 && (_state$
|
|
84
|
-
var _state$
|
|
90
|
+
if (state !== null && state !== void 0 && (_state$appStates5 = state.appStates) !== null && _state$appStates5 !== void 0 && _state$appStates5.conversationEndedBy) {
|
|
91
|
+
var _state$appStates6;
|
|
85
92
|
TelemetryHelper.logSDKEvent(LogLevel.INFO, {
|
|
86
93
|
Event: TelemetryEvent.PrepareEndChat,
|
|
87
|
-
Description: `${PrepareEndChatDescriptionConstants.ConversationEndedByCustomerWithInvalidPostChat} ${state === null || state === void 0 ? void 0 : (_state$
|
|
94
|
+
Description: `${PrepareEndChatDescriptionConstants.ConversationEndedByCustomerWithInvalidPostChat} ${state === null || state === void 0 ? void 0 : (_state$appStates6 = state.appStates) === null || _state$appStates6 === void 0 ? void 0 : _state$appStates6.conversationEndedBy}.`
|
|
88
95
|
});
|
|
89
96
|
}
|
|
90
97
|
const persistentEnabled = isPersistentEnabled(chatConfig);
|
|
@@ -256,6 +263,10 @@ export const closeChatStateCleanUp = dispatch => {
|
|
|
256
263
|
payload: undefined
|
|
257
264
|
});
|
|
258
265
|
// dispatch({ type: LiveChatWidgetActionType.SET_CONVERSATION_STATE, payload: ConversationState.Closed });
|
|
266
|
+
dispatch({
|
|
267
|
+
type: LiveChatWidgetActionType.SET_CONVERSATIONAL_SURVEY_DISPLAY,
|
|
268
|
+
payload: false
|
|
269
|
+
});
|
|
259
270
|
dispatch({
|
|
260
271
|
type: LiveChatWidgetActionType.SET_RECONNECT_ID,
|
|
261
272
|
payload: undefined
|
|
@@ -32,6 +32,9 @@ import htmlTextMiddleware from "../../webchatcontainerstateful/webchatcontroller
|
|
|
32
32
|
import preProcessingMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/preProcessingMiddleware";
|
|
33
33
|
import sanitizationMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/sanitizationMiddleware";
|
|
34
34
|
import { Constants } from "../../../common/Constants";
|
|
35
|
+
import { ConversationState } from "../../../contexts/common/ConversationState";
|
|
36
|
+
import { executeReducer } from "../../../contexts/createReducer";
|
|
37
|
+
import { createQueueOverflowMiddleware } from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/queueOverflowHandlerMiddleware";
|
|
35
38
|
|
|
36
39
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
37
40
|
export const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endChat) => {
|
|
@@ -53,6 +56,20 @@ export const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endCh
|
|
|
53
56
|
let webChatStore = WebChatStoreLoader.store;
|
|
54
57
|
if (!webChatStore) {
|
|
55
58
|
var _state$domainStates$l, _state$domainStates$l2, _state$domainStates$l3, _props$webChatContain7;
|
|
59
|
+
const addConversationalSurveyTagsCallback = action => {
|
|
60
|
+
var _inMemoryState$appSta;
|
|
61
|
+
const inMemoryState = executeReducer(state, {
|
|
62
|
+
type: LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
|
|
63
|
+
payload: null
|
|
64
|
+
});
|
|
65
|
+
const isConversationalSurvey = (_inMemoryState$appSta = inMemoryState.appStates) === null || _inMemoryState$appSta === void 0 ? void 0 : _inMemoryState$appSta.isConversationalSurvey;
|
|
66
|
+
if (isConversationalSurvey) {
|
|
67
|
+
if (!action.payload.activity.channelData.tags.includes(Constants.c2ConversationalSurveyMessageTag)) {
|
|
68
|
+
action.payload.activity.channelData.tags.push(Constants.c2ConversationalSurveyMessageTag);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return action;
|
|
72
|
+
};
|
|
56
73
|
const conversationEndCallback = async () => {
|
|
57
74
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
58
75
|
const conversationDetails = await getConversationDetailsCall(facadeChatSDK);
|
|
@@ -82,9 +99,21 @@ export const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endCh
|
|
|
82
99
|
});
|
|
83
100
|
}
|
|
84
101
|
};
|
|
102
|
+
const startConversationalSurveyCallback = async () => {
|
|
103
|
+
dispatch({
|
|
104
|
+
type: LiveChatWidgetActionType.SET_CONVERSATIONAL_SURVEY_DISPLAY,
|
|
105
|
+
payload: true
|
|
106
|
+
});
|
|
107
|
+
};
|
|
108
|
+
const endConversationalSurveyCallback = async () => {
|
|
109
|
+
dispatch({
|
|
110
|
+
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE,
|
|
111
|
+
payload: ConversationState.InActive
|
|
112
|
+
});
|
|
113
|
+
};
|
|
85
114
|
webChatStore = createStore({},
|
|
86
115
|
//initial state
|
|
87
|
-
preProcessingMiddleware, attachmentProcessingMiddleware, createAttachmentUploadValidatorMiddleware((_state$domainStates$l = state.domainStates.liveChatConfig) === null || _state$domainStates$l === void 0 ? void 0 : _state$domainStates$l.allowedFileExtensions, (_state$domainStates$l2 = state.domainStates.liveChatConfig) === null || _state$domainStates$l2 === void 0 ? void 0 : _state$domainStates$l2.maxUploadFileSize, localizedTexts), channelDataMiddleware, createConversationEndMiddleware(conversationEndCallback), createDataMaskingMiddleware((_state$domainStates$l3 = state.domainStates.liveChatConfig) === null || _state$domainStates$l3 === void 0 ? void 0 : _state$domainStates$l3.DataMaskingInfo), createMessageTimeStampMiddleware, createMessageSequenceIdOverrideMiddleware, gifUploadMiddleware, htmlPlayerMiddleware, htmlTextMiddleware(honorsTargetInHTMLLinks), createMaxMessageSizeValidator(localizedTexts), sanitizationMiddleware,
|
|
116
|
+
preProcessingMiddleware, attachmentProcessingMiddleware, createAttachmentUploadValidatorMiddleware((_state$domainStates$l = state.domainStates.liveChatConfig) === null || _state$domainStates$l === void 0 ? void 0 : _state$domainStates$l.allowedFileExtensions, (_state$domainStates$l2 = state.domainStates.liveChatConfig) === null || _state$domainStates$l2 === void 0 ? void 0 : _state$domainStates$l2.maxUploadFileSize, localizedTexts), createQueueOverflowMiddleware(state, dispatch), channelDataMiddleware(addConversationalSurveyTagsCallback), createConversationEndMiddleware(conversationEndCallback, startConversationalSurveyCallback, endConversationalSurveyCallback), createDataMaskingMiddleware((_state$domainStates$l3 = state.domainStates.liveChatConfig) === null || _state$domainStates$l3 === void 0 ? void 0 : _state$domainStates$l3.DataMaskingInfo), createMessageTimeStampMiddleware, createMessageSequenceIdOverrideMiddleware, gifUploadMiddleware, htmlPlayerMiddleware, htmlTextMiddleware(honorsTargetInHTMLLinks), createMaxMessageSizeValidator(localizedTexts), sanitizationMiddleware,
|
|
88
117
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
89
118
|
...(((_props$webChatContain7 = props.webChatContainerProps) === null || _props$webChatContain7 === void 0 ? void 0 : _props$webChatContain7.storeMiddlewares) ?? []));
|
|
90
119
|
WebChatStoreLoader.store = webChatStore;
|