@microsoft/omnichannel-chat-widget 2.0.0 → 2.0.1-main.a2ef2a3
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 +4 -2
- package/lib/cjs/common/telemetry/TelemetryConstants.js +2 -0
- package/lib/cjs/components/livechatwidget/common/initWebChatComposer.js +9 -4
- package/lib/cjs/components/livechatwidget/common/recoveryEligibilityTelemetry.js +60 -0
- package/lib/cjs/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +8 -6
- package/lib/esm/common/telemetry/TelemetryConstants.js +2 -0
- package/lib/esm/components/livechatwidget/common/initWebChatComposer.js +9 -4
- package/lib/esm/components/livechatwidget/common/recoveryEligibilityTelemetry.js +52 -0
- package/lib/esm/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +8 -6
- package/lib/types/common/telemetry/TelemetryConstants.d.ts +1 -0
- package/lib/types/components/livechatwidget/common/recoveryEligibilityTelemetry.d.ts +17 -0
- package/package.json +7 -6
package/README.md
CHANGED
|
@@ -53,10 +53,12 @@ This package requires Node.js `>=22.12.0` for consumer builds. Node 20 is not su
|
|
|
53
53
|
For a production application, pin the exact stable versions:
|
|
54
54
|
|
|
55
55
|
```bash
|
|
56
|
-
npm install --save-exact @microsoft/omnichannel-chat-widget@2.0.
|
|
56
|
+
npm install --save-exact @microsoft/omnichannel-chat-widget@2.0.1 @microsoft/omnichannel-chat-components@1.2.0 @microsoft/omnichannel-chat-sdk@2.0.1
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
`2.0.
|
|
59
|
+
`2.0.1` release date is 2026-10-05. Official support ends on 2027-10-05. See the [root support table](https://github.com/microsoft/omnichannel-chat-widget#chat-widget).
|
|
60
|
+
|
|
61
|
+
_**Known issue:**_ Chat SDK versions earlier than `1.11.6` can start duplicate conversations when `startChat()` is called again before the previous call is complete. Chat Widget `1.8.1` and earlier can use these versions. Upgrade the Chat SDK to `1.11.8` or later. See [Duplicate conversations with Chat SDK versions before 1.11.6](https://github.com/microsoft/omnichannel-chat-widget/blob/main/docs/KNOWN_ISSUE_CONCURRENT_STARTCHAT.md).
|
|
60
62
|
|
|
61
63
|
TypeScript consumers that imported the exported Web Chat middleware factories now receive Redux 5 `unknown` actions. Narrow with `isWebChatAction` before reading `type` or `payload`. Runtime behavior is unchanged.
|
|
62
64
|
|
|
@@ -111,6 +111,7 @@ let TelemetryEvent = exports.TelemetryEvent = /*#__PURE__*/function (TelemetryEv
|
|
|
111
111
|
TelemetryEvent["MidConversationAuthSucceeded"] = "MidConversationAuthSucceeded";
|
|
112
112
|
TelemetryEvent["MidConversationAuthFailed"] = "MidConversationAuthFailed";
|
|
113
113
|
TelemetryEvent["MidConversationAuthReset"] = "MidConversationAuthReset";
|
|
114
|
+
TelemetryEvent["RecoveryEligibilityEvaluated"] = "RecoveryEligibilityEvaluated";
|
|
114
115
|
TelemetryEvent["GetConversationDetailsCallStarted"] = "GetConversationDetailsCallStarted";
|
|
115
116
|
TelemetryEvent["GetConversationDetailsCallFailed"] = "GetConversationDetailsCallFailed";
|
|
116
117
|
TelemetryEvent["EndChatSDKCallFailed"] = "EndChatSDKCallFailed";
|
|
@@ -414,6 +415,7 @@ let TelemetryConstants = exports.TelemetryConstants = /*#__PURE__*/function () {
|
|
|
414
415
|
case TelemetryEvent.SecureEventBusDispatchError:
|
|
415
416
|
case TelemetryEvent.AgentJoinedConversation:
|
|
416
417
|
case TelemetryEvent.BrowserTabHidden:
|
|
418
|
+
case TelemetryEvent.RecoveryEligibilityEvaluated:
|
|
417
419
|
return ScenarioType.ACTIONS;
|
|
418
420
|
case TelemetryEvent.StartChatSDKCall:
|
|
419
421
|
case TelemetryEvent.StartChatEventReceived:
|
|
@@ -256,6 +256,12 @@ const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endChat) =>
|
|
|
256
256
|
// Track what would be removed
|
|
257
257
|
const removedTags = [];
|
|
258
258
|
const removedAttributes = [];
|
|
259
|
+
const trackAttribute = name => {
|
|
260
|
+
const attrName = name.toLowerCase();
|
|
261
|
+
if (!strictConfig.ALLOWED_ATTR.includes(attrName) && attrName !== "class" && attrName !== "id") {
|
|
262
|
+
removedAttributes.push(attrName);
|
|
263
|
+
}
|
|
264
|
+
};
|
|
259
265
|
|
|
260
266
|
// Add hooks to the isolated monitoring instance
|
|
261
267
|
monitorDOMPurify.addHook("uponSanitizeElement", (node, data) => {
|
|
@@ -264,6 +270,8 @@ const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endChat) =>
|
|
|
264
270
|
// Filter out "body" tag which is DOMPurify's internal wrapper
|
|
265
271
|
if (node.nodeType === 1 && !strictConfig.ALLOWED_TAGS.includes(tagName) && tagName !== "body") {
|
|
266
272
|
removedTags.push(tagName);
|
|
273
|
+
// DOMPurify 3.4.16+ skips uponSanitizeAttribute for removed elements
|
|
274
|
+
Array.from(node.attributes ?? []).forEach(attr => trackAttribute(attr.name));
|
|
267
275
|
}
|
|
268
276
|
} catch (hookError) {
|
|
269
277
|
// Silently ignore hook errors
|
|
@@ -271,10 +279,7 @@ const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endChat) =>
|
|
|
271
279
|
});
|
|
272
280
|
monitorDOMPurify.addHook("uponSanitizeAttribute", (node, data) => {
|
|
273
281
|
try {
|
|
274
|
-
|
|
275
|
-
if (!strictConfig.ALLOWED_ATTR.includes(attrName) && attrName !== "class" && attrName !== "id") {
|
|
276
|
-
removedAttributes.push(attrName);
|
|
277
|
-
}
|
|
282
|
+
trackAttribute(data.attrName);
|
|
278
283
|
} catch (hookError) {
|
|
279
284
|
// Silently ignore hook errors
|
|
280
285
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.logRecoveryEligibilityTelemetry = exports.getRecoveryEligibilityTelemetryProperties = exports.RecoveryEligibilityReason = void 0;
|
|
7
|
+
var _ConversationState = require("../../../contexts/common/ConversationState");
|
|
8
|
+
var _TelemetryConstants = require("../../../common/telemetry/TelemetryConstants");
|
|
9
|
+
var _TelemetryHelper = require("../../../common/telemetry/TelemetryHelper");
|
|
10
|
+
var _utils = require("../../../common/utils");
|
|
11
|
+
let RecoveryEligibilityReason = exports.RecoveryEligibilityReason = /*#__PURE__*/function (RecoveryEligibilityReason) {
|
|
12
|
+
RecoveryEligibilityReason["ReconnectIdPresent"] = "ReconnectIdPresent";
|
|
13
|
+
RecoveryEligibilityReason["ActiveContextPresent"] = "ActiveContextPresent";
|
|
14
|
+
RecoveryEligibilityReason["MissingContext"] = "MissingContext";
|
|
15
|
+
RecoveryEligibilityReason["CachedContextNonActive"] = "CachedContextNonActive";
|
|
16
|
+
return RecoveryEligibilityReason;
|
|
17
|
+
}({});
|
|
18
|
+
const getConversationStateName = conversationState => {
|
|
19
|
+
if (typeof conversationState !== "number") {
|
|
20
|
+
return "Unknown";
|
|
21
|
+
}
|
|
22
|
+
const stateName = _ConversationState.ConversationState[conversationState];
|
|
23
|
+
return typeof stateName === "string" ? stateName : "Unknown";
|
|
24
|
+
};
|
|
25
|
+
const getRecoveryEligibilityTelemetryProperties = (state, eligible) => {
|
|
26
|
+
var _state$appStates, _state$domainStates, _state$appStates2, _state$appStates3;
|
|
27
|
+
const reconnectId = (_state$appStates = state.appStates) === null || _state$appStates === void 0 ? void 0 : _state$appStates.reconnectId;
|
|
28
|
+
const liveChatContext = (_state$domainStates = state.domainStates) === null || _state$domainStates === void 0 ? void 0 : _state$domainStates.liveChatContext;
|
|
29
|
+
const hasReconnectId = !(0, _utils.isUndefinedOrEmpty)(reconnectId);
|
|
30
|
+
const hasLiveChatContext = !(0, _utils.isUndefinedOrEmpty)(liveChatContext);
|
|
31
|
+
const hasRequestId = !(0, _utils.isUndefinedOrEmpty)(liveChatContext === null || liveChatContext === void 0 ? void 0 : liveChatContext.requestId);
|
|
32
|
+
let reason = RecoveryEligibilityReason.ActiveContextPresent;
|
|
33
|
+
if (hasReconnectId) {
|
|
34
|
+
reason = RecoveryEligibilityReason.ReconnectIdPresent;
|
|
35
|
+
} else if (!hasLiveChatContext) {
|
|
36
|
+
reason = RecoveryEligibilityReason.MissingContext;
|
|
37
|
+
} else if (((_state$appStates2 = state.appStates) === null || _state$appStates2 === void 0 ? void 0 : _state$appStates2.conversationState) !== _ConversationState.ConversationState.Active) {
|
|
38
|
+
reason = RecoveryEligibilityReason.CachedContextNonActive;
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
conversationState: getConversationStateName((_state$appStates3 = state.appStates) === null || _state$appStates3 === void 0 ? void 0 : _state$appStates3.conversationState),
|
|
42
|
+
hasReconnectId,
|
|
43
|
+
hasLiveChatContext,
|
|
44
|
+
hasRequestId,
|
|
45
|
+
eligible,
|
|
46
|
+
reason
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
exports.getRecoveryEligibilityTelemetryProperties = getRecoveryEligibilityTelemetryProperties;
|
|
50
|
+
const logRecoveryEligibilityTelemetry = (state, eligible) => {
|
|
51
|
+
try {
|
|
52
|
+
_TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.INFO, {
|
|
53
|
+
Event: _TelemetryConstants.TelemetryEvent.RecoveryEligibilityEvaluated,
|
|
54
|
+
CustomProperties: getRecoveryEligibilityTelemetryProperties(state, eligible)
|
|
55
|
+
});
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.warn(error);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
exports.logRecoveryEligibilityTelemetry = logRecoveryEligibilityTelemetry;
|
|
@@ -60,6 +60,7 @@ var _useChatAdapterStore3 = _interopRequireDefault(require("../../../hooks/useCh
|
|
|
60
60
|
var _useChatContextStore3 = _interopRequireDefault(require("../../../hooks/useChatContextStore"));
|
|
61
61
|
var _useFacadeChatSDKStore = _interopRequireDefault(require("../../../hooks/useFacadeChatSDKStore"));
|
|
62
62
|
var _renderSurveyHelpers = require("../common/renderSurveyHelpers");
|
|
63
|
+
var _recoveryEligibilityTelemetry = require("../common/recoveryEligibilityTelemetry");
|
|
63
64
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
64
65
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
65
66
|
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
@@ -157,6 +158,7 @@ const LiveChatWidgetStateful = props => {
|
|
|
157
158
|
activeCachedChatExist = false;
|
|
158
159
|
optionalParams = {};
|
|
159
160
|
}
|
|
161
|
+
(0, _recoveryEligibilityTelemetry.logRecoveryEligibilityTelemetry)(state, activeCachedChatExist);
|
|
160
162
|
};
|
|
161
163
|
|
|
162
164
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -1172,18 +1174,18 @@ const LiveChatWidgetStateful = props => {
|
|
|
1172
1174
|
.webchat__auto-resize-textarea.webchat__send-box-text-box__text-area {
|
|
1173
1175
|
min-height: ${sendBoxTextArea === null || sendBoxTextArea === void 0 ? void 0 : sendBoxTextArea.minHeight} !important;
|
|
1174
1176
|
}`}
|
|
1175
|
-
`), /*#__PURE__*/_react2.default.createElement(_DraggableChatWidget.default, chatWidgetDraggableConfig, /*#__PURE__*/_react2.default.createElement(
|
|
1176
|
-
userID: userID,
|
|
1177
|
-
styleOptions: styleOptions,
|
|
1178
|
-
directLine: directLine
|
|
1179
|
-
}), /*#__PURE__*/_react2.default.createElement(_react.Stack, {
|
|
1177
|
+
`), /*#__PURE__*/_react2.default.createElement(_DraggableChatWidget.default, chatWidgetDraggableConfig, /*#__PURE__*/_react2.default.createElement(_react.Stack, {
|
|
1180
1178
|
id: widgetElementId,
|
|
1181
1179
|
styles: generalStyles,
|
|
1182
1180
|
className: (_livechatProps$styleP = livechatProps.styleProps) === null || _livechatProps$styleP === void 0 ? void 0 : _livechatProps$styleP.className,
|
|
1183
1181
|
role: isWidgetOpen ? "dialog" : undefined,
|
|
1184
1182
|
"aria-modal": isWidgetOpen ? true : undefined,
|
|
1185
1183
|
"aria-label": isWidgetOpen ? ((_props$headerProps = props.headerProps) === null || _props$headerProps === void 0 || (_props$headerProps = _props$headerProps.controlProps) === null || _props$headerProps === void 0 || (_props$headerProps = _props$headerProps.headerTitleProps) === null || _props$headerProps === void 0 ? void 0 : _props$headerProps.text) ?? "Live Chat" : undefined
|
|
1186
|
-
},
|
|
1184
|
+
}, /*#__PURE__*/_react2.default.createElement(Composer, _extends({}, webChatProps, {
|
|
1185
|
+
userID: userID,
|
|
1186
|
+
styleOptions: styleOptions,
|
|
1187
|
+
directLine: directLine
|
|
1188
|
+
}), !((_livechatProps$contro = livechatProps.controlProps) !== null && _livechatProps$contro !== void 0 && _livechatProps$contro.hideChatButton) && !((_livechatProps$contro2 = livechatProps.controlProps) !== null && _livechatProps$contro2 !== void 0 && _livechatProps$contro2.hideStartChatButton) && (0, _componentController.shouldShowChatButton)(state) && ((0, _omnichannelChatComponents.decodeComponentString)((_livechatProps$compon = livechatProps.componentOverrides) === null || _livechatProps$compon === void 0 ? void 0 : _livechatProps$compon.chatButton) || /*#__PURE__*/_react2.default.createElement(_ChatButtonStateful.default, {
|
|
1187
1189
|
buttonProps: livechatProps.chatButtonProps,
|
|
1188
1190
|
outOfOfficeButtonProps: livechatProps.outOfOfficeChatButtonProps,
|
|
1189
1191
|
startChat: prepareStartChatRelay
|
|
@@ -109,6 +109,7 @@ export let TelemetryEvent = /*#__PURE__*/function (TelemetryEvent) {
|
|
|
109
109
|
TelemetryEvent["MidConversationAuthSucceeded"] = "MidConversationAuthSucceeded";
|
|
110
110
|
TelemetryEvent["MidConversationAuthFailed"] = "MidConversationAuthFailed";
|
|
111
111
|
TelemetryEvent["MidConversationAuthReset"] = "MidConversationAuthReset";
|
|
112
|
+
TelemetryEvent["RecoveryEligibilityEvaluated"] = "RecoveryEligibilityEvaluated";
|
|
112
113
|
TelemetryEvent["GetConversationDetailsCallStarted"] = "GetConversationDetailsCallStarted";
|
|
113
114
|
TelemetryEvent["GetConversationDetailsCallFailed"] = "GetConversationDetailsCallFailed";
|
|
114
115
|
TelemetryEvent["EndChatSDKCallFailed"] = "EndChatSDKCallFailed";
|
|
@@ -412,6 +413,7 @@ export let TelemetryConstants = /*#__PURE__*/function () {
|
|
|
412
413
|
case TelemetryEvent.SecureEventBusDispatchError:
|
|
413
414
|
case TelemetryEvent.AgentJoinedConversation:
|
|
414
415
|
case TelemetryEvent.BrowserTabHidden:
|
|
416
|
+
case TelemetryEvent.RecoveryEligibilityEvaluated:
|
|
415
417
|
return ScenarioType.ACTIONS;
|
|
416
418
|
case TelemetryEvent.StartChatSDKCall:
|
|
417
419
|
case TelemetryEvent.StartChatEventReceived:
|
|
@@ -251,6 +251,12 @@ export const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endCh
|
|
|
251
251
|
// Track what would be removed
|
|
252
252
|
const removedTags = [];
|
|
253
253
|
const removedAttributes = [];
|
|
254
|
+
const trackAttribute = name => {
|
|
255
|
+
const attrName = name.toLowerCase();
|
|
256
|
+
if (!strictConfig.ALLOWED_ATTR.includes(attrName) && attrName !== "class" && attrName !== "id") {
|
|
257
|
+
removedAttributes.push(attrName);
|
|
258
|
+
}
|
|
259
|
+
};
|
|
254
260
|
|
|
255
261
|
// Add hooks to the isolated monitoring instance
|
|
256
262
|
monitorDOMPurify.addHook("uponSanitizeElement", (node, data) => {
|
|
@@ -259,6 +265,8 @@ export const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endCh
|
|
|
259
265
|
// Filter out "body" tag which is DOMPurify's internal wrapper
|
|
260
266
|
if (node.nodeType === 1 && !strictConfig.ALLOWED_TAGS.includes(tagName) && tagName !== "body") {
|
|
261
267
|
removedTags.push(tagName);
|
|
268
|
+
// DOMPurify 3.4.16+ skips uponSanitizeAttribute for removed elements
|
|
269
|
+
Array.from(node.attributes ?? []).forEach(attr => trackAttribute(attr.name));
|
|
262
270
|
}
|
|
263
271
|
} catch (hookError) {
|
|
264
272
|
// Silently ignore hook errors
|
|
@@ -266,10 +274,7 @@ export const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endCh
|
|
|
266
274
|
});
|
|
267
275
|
monitorDOMPurify.addHook("uponSanitizeAttribute", (node, data) => {
|
|
268
276
|
try {
|
|
269
|
-
|
|
270
|
-
if (!strictConfig.ALLOWED_ATTR.includes(attrName) && attrName !== "class" && attrName !== "id") {
|
|
271
|
-
removedAttributes.push(attrName);
|
|
272
|
-
}
|
|
277
|
+
trackAttribute(data.attrName);
|
|
273
278
|
} catch (hookError) {
|
|
274
279
|
// Silently ignore hook errors
|
|
275
280
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { ConversationState } from "../../../contexts/common/ConversationState";
|
|
2
|
+
import { LogLevel, TelemetryEvent } from "../../../common/telemetry/TelemetryConstants";
|
|
3
|
+
import { TelemetryHelper } from "../../../common/telemetry/TelemetryHelper";
|
|
4
|
+
import { isUndefinedOrEmpty } from "../../../common/utils";
|
|
5
|
+
export let RecoveryEligibilityReason = /*#__PURE__*/function (RecoveryEligibilityReason) {
|
|
6
|
+
RecoveryEligibilityReason["ReconnectIdPresent"] = "ReconnectIdPresent";
|
|
7
|
+
RecoveryEligibilityReason["ActiveContextPresent"] = "ActiveContextPresent";
|
|
8
|
+
RecoveryEligibilityReason["MissingContext"] = "MissingContext";
|
|
9
|
+
RecoveryEligibilityReason["CachedContextNonActive"] = "CachedContextNonActive";
|
|
10
|
+
return RecoveryEligibilityReason;
|
|
11
|
+
}({});
|
|
12
|
+
const getConversationStateName = conversationState => {
|
|
13
|
+
if (typeof conversationState !== "number") {
|
|
14
|
+
return "Unknown";
|
|
15
|
+
}
|
|
16
|
+
const stateName = ConversationState[conversationState];
|
|
17
|
+
return typeof stateName === "string" ? stateName : "Unknown";
|
|
18
|
+
};
|
|
19
|
+
export const getRecoveryEligibilityTelemetryProperties = (state, eligible) => {
|
|
20
|
+
var _state$appStates, _state$domainStates, _state$appStates2, _state$appStates3;
|
|
21
|
+
const reconnectId = (_state$appStates = state.appStates) === null || _state$appStates === void 0 ? void 0 : _state$appStates.reconnectId;
|
|
22
|
+
const liveChatContext = (_state$domainStates = state.domainStates) === null || _state$domainStates === void 0 ? void 0 : _state$domainStates.liveChatContext;
|
|
23
|
+
const hasReconnectId = !isUndefinedOrEmpty(reconnectId);
|
|
24
|
+
const hasLiveChatContext = !isUndefinedOrEmpty(liveChatContext);
|
|
25
|
+
const hasRequestId = !isUndefinedOrEmpty(liveChatContext === null || liveChatContext === void 0 ? void 0 : liveChatContext.requestId);
|
|
26
|
+
let reason = RecoveryEligibilityReason.ActiveContextPresent;
|
|
27
|
+
if (hasReconnectId) {
|
|
28
|
+
reason = RecoveryEligibilityReason.ReconnectIdPresent;
|
|
29
|
+
} else if (!hasLiveChatContext) {
|
|
30
|
+
reason = RecoveryEligibilityReason.MissingContext;
|
|
31
|
+
} else if (((_state$appStates2 = state.appStates) === null || _state$appStates2 === void 0 ? void 0 : _state$appStates2.conversationState) !== ConversationState.Active) {
|
|
32
|
+
reason = RecoveryEligibilityReason.CachedContextNonActive;
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
conversationState: getConversationStateName((_state$appStates3 = state.appStates) === null || _state$appStates3 === void 0 ? void 0 : _state$appStates3.conversationState),
|
|
36
|
+
hasReconnectId,
|
|
37
|
+
hasLiveChatContext,
|
|
38
|
+
hasRequestId,
|
|
39
|
+
eligible,
|
|
40
|
+
reason
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
export const logRecoveryEligibilityTelemetry = (state, eligible) => {
|
|
44
|
+
try {
|
|
45
|
+
TelemetryHelper.logActionEvent(LogLevel.INFO, {
|
|
46
|
+
Event: TelemetryEvent.RecoveryEligibilityEvaluated,
|
|
47
|
+
CustomProperties: getRecoveryEligibilityTelemetryProperties(state, eligible)
|
|
48
|
+
});
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.warn(error);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
@@ -62,6 +62,7 @@ import useChatAdapterStore from "../../../hooks/useChatAdapterStore";
|
|
|
62
62
|
import useChatContextStore from "../../../hooks/useChatContextStore";
|
|
63
63
|
import useFacadeSDKStore from "../../../hooks/useFacadeChatSDKStore";
|
|
64
64
|
import { getPostChatContext, initiatePostChat } from "../common/renderSurveyHelpers";
|
|
65
|
+
import { logRecoveryEligibilityTelemetry } from "../common/recoveryEligibilityTelemetry";
|
|
65
66
|
let uiTimer;
|
|
66
67
|
export const LiveChatWidgetStateful = props => {
|
|
67
68
|
var _props$webChatContain, _props$webChatContain2, _props$webChatContain3, _props$webChatContain4, _props$webChatContain5, _props$styleProps, _props$webChatContain6, _props$controlProps, _props$controlProps3, _state$appStates7, _props$webChatContain9, _state$appStates8, _props$webChatContain1, _props$webChatContain10, _props$controlProps10, _props$draggableChatW, _props$draggableChatW2, _props$draggableChatW3, _props$draggableChatW4, _props$draggableChatW5, _livechatProps$webCha, _livechatProps$styleP, _props$headerProps, _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$contro0, _livechatProps$contro1, _livechatProps$compon9, _livechatProps$contro10, _livechatProps$compon0, _livechatProps$contro11, _livechatProps$compon1, _livechatProps$compon10, _livechatProps$compon11;
|
|
@@ -150,6 +151,7 @@ export const LiveChatWidgetStateful = props => {
|
|
|
150
151
|
activeCachedChatExist = false;
|
|
151
152
|
optionalParams = {};
|
|
152
153
|
}
|
|
154
|
+
logRecoveryEligibilityTelemetry(state, activeCachedChatExist);
|
|
153
155
|
};
|
|
154
156
|
|
|
155
157
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -1165,18 +1167,18 @@ export const LiveChatWidgetStateful = props => {
|
|
|
1165
1167
|
.webchat__auto-resize-textarea.webchat__send-box-text-box__text-area {
|
|
1166
1168
|
min-height: ${sendBoxTextArea === null || sendBoxTextArea === void 0 ? void 0 : sendBoxTextArea.minHeight} !important;
|
|
1167
1169
|
}`}
|
|
1168
|
-
`), /*#__PURE__*/React.createElement(DraggableChatWidget, chatWidgetDraggableConfig, /*#__PURE__*/React.createElement(
|
|
1169
|
-
userID: userID,
|
|
1170
|
-
styleOptions: styleOptions,
|
|
1171
|
-
directLine: directLine
|
|
1172
|
-
}), /*#__PURE__*/React.createElement(Stack, {
|
|
1170
|
+
`), /*#__PURE__*/React.createElement(DraggableChatWidget, chatWidgetDraggableConfig, /*#__PURE__*/React.createElement(Stack, {
|
|
1173
1171
|
id: widgetElementId,
|
|
1174
1172
|
styles: generalStyles,
|
|
1175
1173
|
className: (_livechatProps$styleP = livechatProps.styleProps) === null || _livechatProps$styleP === void 0 ? void 0 : _livechatProps$styleP.className,
|
|
1176
1174
|
role: isWidgetOpen ? "dialog" : undefined,
|
|
1177
1175
|
"aria-modal": isWidgetOpen ? true : undefined,
|
|
1178
1176
|
"aria-label": isWidgetOpen ? ((_props$headerProps = props.headerProps) === null || _props$headerProps === void 0 || (_props$headerProps = _props$headerProps.controlProps) === null || _props$headerProps === void 0 || (_props$headerProps = _props$headerProps.headerTitleProps) === null || _props$headerProps === void 0 ? void 0 : _props$headerProps.text) ?? "Live Chat" : undefined
|
|
1179
|
-
},
|
|
1177
|
+
}, /*#__PURE__*/React.createElement(Composer, _extends({}, webChatProps, {
|
|
1178
|
+
userID: userID,
|
|
1179
|
+
styleOptions: styleOptions,
|
|
1180
|
+
directLine: directLine
|
|
1181
|
+
}), !((_livechatProps$contro = livechatProps.controlProps) !== null && _livechatProps$contro !== void 0 && _livechatProps$contro.hideChatButton) && !((_livechatProps$contro2 = livechatProps.controlProps) !== null && _livechatProps$contro2 !== void 0 && _livechatProps$contro2.hideStartChatButton) && shouldShowChatButton(state) && (decodeComponentString((_livechatProps$compon = livechatProps.componentOverrides) === null || _livechatProps$compon === void 0 ? void 0 : _livechatProps$compon.chatButton) || /*#__PURE__*/React.createElement(ChatButtonStateful, {
|
|
1180
1182
|
buttonProps: livechatProps.chatButtonProps,
|
|
1181
1183
|
outOfOfficeButtonProps: livechatProps.outOfOfficeChatButtonProps,
|
|
1182
1184
|
startChat: prepareStartChatRelay
|
|
@@ -95,6 +95,7 @@ export declare enum TelemetryEvent {
|
|
|
95
95
|
MidConversationAuthSucceeded = "MidConversationAuthSucceeded",
|
|
96
96
|
MidConversationAuthFailed = "MidConversationAuthFailed",
|
|
97
97
|
MidConversationAuthReset = "MidConversationAuthReset",
|
|
98
|
+
RecoveryEligibilityEvaluated = "RecoveryEligibilityEvaluated",
|
|
98
99
|
GetConversationDetailsCallStarted = "GetConversationDetailsCallStarted",
|
|
99
100
|
GetConversationDetailsCallFailed = "GetConversationDetailsCallFailed",
|
|
100
101
|
EndChatSDKCallFailed = "EndChatSDKCallFailed",
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ILiveChatWidgetContext } from "../../../contexts/common/ILiveChatWidgetContext";
|
|
2
|
+
export declare enum RecoveryEligibilityReason {
|
|
3
|
+
ReconnectIdPresent = "ReconnectIdPresent",
|
|
4
|
+
ActiveContextPresent = "ActiveContextPresent",
|
|
5
|
+
MissingContext = "MissingContext",
|
|
6
|
+
CachedContextNonActive = "CachedContextNonActive"
|
|
7
|
+
}
|
|
8
|
+
export interface RecoveryEligibilityTelemetryProperties {
|
|
9
|
+
conversationState: string;
|
|
10
|
+
hasReconnectId: boolean;
|
|
11
|
+
hasLiveChatContext: boolean;
|
|
12
|
+
hasRequestId: boolean;
|
|
13
|
+
eligible: boolean;
|
|
14
|
+
reason: RecoveryEligibilityReason;
|
|
15
|
+
}
|
|
16
|
+
export declare const getRecoveryEligibilityTelemetryProperties: (state: ILiveChatWidgetContext, eligible: boolean) => RecoveryEligibilityTelemetryProperties;
|
|
17
|
+
export declare const logRecoveryEligibilityTelemetry: (state: ILiveChatWidgetContext, eligible: boolean) => void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@microsoft/omnichannel-chat-widget",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1-main.a2ef2a3",
|
|
4
4
|
"description": "Microsoft Omnichannel Chat Widget",
|
|
5
5
|
"main": "lib/cjs/index.js",
|
|
6
6
|
"types": "lib/types/index.d.ts",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"@axe-core/react": "^4.10.2",
|
|
73
73
|
"accessibility-insights-scan": "^3.0.0",
|
|
74
74
|
"@guidepup/guidepup": "^0.24.1",
|
|
75
|
-
"postcss": "
|
|
75
|
+
"postcss": "8.5.19",
|
|
76
76
|
"react": "^18.3.1",
|
|
77
77
|
"react-dom": "^18.3.1",
|
|
78
78
|
"react-native-web": "^0.21.2",
|
|
@@ -93,18 +93,18 @@
|
|
|
93
93
|
"@azure/core-tracing": "^1.2.0",
|
|
94
94
|
"@microsoft/applicationinsights-web": "^3.3.6",
|
|
95
95
|
"@microsoft/omnichannel-chat-components": "1.2.0",
|
|
96
|
-
"@microsoft/omnichannel-chat-sdk": "2.0.
|
|
96
|
+
"@microsoft/omnichannel-chat-sdk": "2.0.1",
|
|
97
97
|
"@opentelemetry/api": "^1.9.0",
|
|
98
98
|
"abort-controller": "^3",
|
|
99
99
|
"botframework-webchat": "4.18.1-hotfix.20260308.b15b405",
|
|
100
100
|
"core-js-pure": "^3.42.0",
|
|
101
|
-
"dompurify": "
|
|
101
|
+
"dompurify": "3.4.16",
|
|
102
102
|
"markdown-it": "^14.3.0",
|
|
103
103
|
"markdown-it-attrs": "^4.1.6",
|
|
104
104
|
"markdown-it-for-inline": "^0.1.1",
|
|
105
105
|
"md5-typescript": "^1.0.5",
|
|
106
106
|
"rxjs": "5.5.12",
|
|
107
|
-
"sanitize-html": "2.17.
|
|
107
|
+
"sanitize-html": "2.17.7",
|
|
108
108
|
"simple-update-in": "2.2.0",
|
|
109
109
|
"slack-markdown-it": "^1.0.5"
|
|
110
110
|
},
|
|
@@ -163,7 +163,8 @@
|
|
|
163
163
|
"**/@types/minimatch": "3.0.5",
|
|
164
164
|
"**/@types/trusted-types": "2.0.7",
|
|
165
165
|
"**/join-images": "1.1.5",
|
|
166
|
-
"**/valibot": "1.4.2"
|
|
166
|
+
"**/valibot": "1.4.2",
|
|
167
|
+
"**/nanoid": "3.3.18"
|
|
167
168
|
},
|
|
168
169
|
"jest": {
|
|
169
170
|
"verbose": true,
|