@microsoft/omnichannel-chat-widget 1.7.3-main.c5e352d → 1.7.3-main.e452e73

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.
Files changed (22) hide show
  1. package/lib/cjs/common/Constants.js +1 -0
  2. package/lib/cjs/common/telemetry/TelemetryConstants.js +1 -0
  3. package/lib/cjs/components/livechatwidget/common/chatDisconnectHelper.js +2 -2
  4. package/lib/cjs/components/livechatwidget/common/createInternetConnectionChangeHandler.js +6 -2
  5. package/lib/cjs/components/livechatwidget/common/createMarkdown.js +2 -2
  6. package/lib/cjs/components/livechatwidget/common/helpers/markdownHelper.js +23 -0
  7. package/lib/cjs/components/livechatwidget/common/persistentChatHelper.js +2 -1
  8. package/lib/cjs/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +30 -0
  9. package/lib/cjs/plugins/createChatTranscript.js +84 -0
  10. package/lib/esm/common/Constants.js +1 -0
  11. package/lib/esm/common/telemetry/TelemetryConstants.js +1 -0
  12. package/lib/esm/components/livechatwidget/common/chatDisconnectHelper.js +3 -2
  13. package/lib/esm/components/livechatwidget/common/createInternetConnectionChangeHandler.js +6 -2
  14. package/lib/esm/components/livechatwidget/common/createMarkdown.js +2 -2
  15. package/lib/esm/components/livechatwidget/common/helpers/markdownHelper.js +15 -0
  16. package/lib/esm/components/livechatwidget/common/persistentChatHelper.js +2 -1
  17. package/lib/esm/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +31 -1
  18. package/lib/esm/plugins/createChatTranscript.js +84 -0
  19. package/lib/types/common/Constants.d.ts +1 -0
  20. package/lib/types/common/telemetry/TelemetryConstants.d.ts +2 -1
  21. package/lib/types/components/livechatwidget/common/helpers/markdownHelper.d.ts +2 -0
  22. package/package.json +2 -2
@@ -307,6 +307,7 @@ class WidgetLoadCustomErrorString {}
307
307
  exports.WidgetLoadCustomErrorString = WidgetLoadCustomErrorString;
308
308
  _defineProperty(WidgetLoadCustomErrorString, "AuthenticationFailedErrorString", "Authentication was not successful");
309
309
  _defineProperty(WidgetLoadCustomErrorString, "NetworkErrorString", "Network Error");
310
+ _defineProperty(WidgetLoadCustomErrorString, "CloseAdapterAfterDisconnectionErrorString", "Error trying to end/close chat adapter after the widget is back on-line, for an already disconnected session");
310
311
  class PrepareEndChatDescriptionConstants {}
311
312
  exports.PrepareEndChatDescriptionConstants = PrepareEndChatDescriptionConstants;
312
313
  _defineProperty(PrepareEndChatDescriptionConstants, "ConversationEndedByCustomerWithoutPostChat", "Conversation ended by customer. Post chat not configured or should not show.");
@@ -216,6 +216,7 @@ exports.TelemetryEvent = TelemetryEvent;
216
216
  TelemetryEvent["PostChatSurveyLoaded"] = "PostChatSurveyLoaded";
217
217
  TelemetryEvent["ChatDisconnectThreadEventReceived"] = "ChatDisconnectThreadEventReceived";
218
218
  TelemetryEvent["HiddenAdaptiveCardMessageReceived"] = "HiddenAdaptiveCardMessageReceived";
219
+ TelemetryEvent["EndingAdapterAfterDisconnectionError"] = "EndingAdapterAfterDisconnectionError";
219
220
  })(TelemetryEvent || (exports.TelemetryEvent = TelemetryEvent = {}));
220
221
  class TelemetryConstants {
221
222
  static map(eventTypeOrScenarioType) {
@@ -4,11 +4,11 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.handleChatDisconnect = void 0;
7
+ var _TelemetryConstants = require("../../../common/telemetry/TelemetryConstants");
7
8
  var _NotificationHandler = require("../../webchatcontainerstateful/webchatcontroller/notification/NotificationHandler");
8
9
  var _NotificationScenarios = require("../../webchatcontainerstateful/webchatcontroller/enums/NotificationScenarios");
9
- var _defaultMiddlewareLocalizedTexts = require("../../webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts");
10
- var _TelemetryConstants = require("../../../common/telemetry/TelemetryConstants");
11
10
  var _TelemetryHelper = require("../../../common/telemetry/TelemetryHelper");
11
+ var _defaultMiddlewareLocalizedTexts = require("../../webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts");
12
12
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
13
  const handleChatDisconnect = (props, state, setWebChatStyles) => {
14
14
  var _state$appStates, _state$domainStates, _state$domainStates$m, _props$webChatContain, _props$webChatContain2;
@@ -4,12 +4,13 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.createInternetConnectionChangeHandler = void 0;
7
+ var _TelemetryConstants = require("../../../common/telemetry/TelemetryConstants");
8
+ var _omnichannelChatComponents = require("@microsoft/omnichannel-chat-components");
7
9
  var _Constants = require("../../../common/Constants");
8
10
  var _NotificationHandler = require("../../webchatcontainerstateful/webchatcontroller/notification/NotificationHandler");
9
11
  var _NotificationScenarios = require("../../webchatcontainerstateful/webchatcontroller/enums/NotificationScenarios");
10
- var _defaultMiddlewareLocalizedTexts = require("../../webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts");
11
12
  var _TelemetryHelper = require("../../../common/telemetry/TelemetryHelper");
12
- var _TelemetryConstants = require("../../../common/telemetry/TelemetryConstants");
13
+ var _defaultMiddlewareLocalizedTexts = require("../../webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts");
13
14
  const isInternetConnected = async () => {
14
15
  try {
15
16
  const response = await fetch(_Constants.Constants.internetConnectionTestUrl);
@@ -32,6 +33,9 @@ const createInternetConnectionChangeHandler = async () => {
32
33
  Event: _TelemetryConstants.TelemetryEvent.NetworkReconnected
33
34
  });
34
35
  _NotificationHandler.NotificationHandler.notifySuccess(_NotificationScenarios.NotificationScenarios.InternetConnection, _defaultMiddlewareLocalizedTexts.defaultMiddlewareLocalizedTexts.MIDDLEWARE_BANNER_INTERNET_BACK_ONLINE);
36
+ _omnichannelChatComponents.BroadcastService.postMessage({
37
+ eventName: _TelemetryConstants.BroadcastEvent.NetworkReconnected
38
+ });
35
39
  }
36
40
  };
37
41
 
@@ -7,8 +7,8 @@ exports.createMarkdown = void 0;
7
7
  var _Constants = require("../../../common/Constants");
8
8
  var _markdownIt = _interopRequireDefault(require("markdown-it"));
9
9
  var _markdownItForInline = _interopRequireDefault(require("markdown-it-for-inline"));
10
- var _slackMarkdownIt = _interopRequireDefault(require("slack-markdown-it"));
11
10
  var _defaultMarkdownLocalizedTexts = require("../../webchatcontainerstateful/common/defaultProps/defaultMarkdownLocalizedTexts");
11
+ var _markdownHelper = require("./helpers/markdownHelper");
12
12
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
13
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
14
  const createMarkdown = (disableMarkdownMessageFormatting, disableNewLineMarkdownSupport) => {
@@ -19,7 +19,7 @@ const createMarkdown = (disableMarkdownMessageFormatting, disableNewLineMarkdown
19
19
  linkify: true,
20
20
  breaks: !disableNewLineMarkdownSupport
21
21
  });
22
- markdown.use(_slackMarkdownIt.default);
22
+ markdown = (0, _markdownHelper.addSlackMarkdownIt)(markdown);
23
23
  } else {
24
24
  markdown = new _markdownIt.default(_Constants.Constants.Zero, {
25
25
  html: true,
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.addSlackMarkdownIt = void 0;
7
+ var _slackMarkdownIt = _interopRequireDefault(require("slack-markdown-it"));
8
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
9
+ const addSlackMarkdownIt = markdown => {
10
+ try {
11
+ markdown.use(_slackMarkdownIt.default);
12
+ } catch (e) {
13
+ // this is to support the case when slack-markdown-it
14
+ // transpiled code doesn't export default (webpack5)
15
+ if (_slackMarkdownIt.default.default.apply) {
16
+ markdown.use(_slackMarkdownIt.default.default);
17
+ } else {
18
+ console.error("Error while adding slackMarkdown plugin", e);
19
+ }
20
+ }
21
+ return markdown;
22
+ };
23
+ exports.addSlackMarkdownIt = addSlackMarkdownIt;
@@ -11,7 +11,8 @@ const shouldSetPreChatIfPersistentChat = async (chatSDK, conversationMode, showP
11
11
  let skipPreChat = false;
12
12
  if (persistentEnabled) {
13
13
  const reconnectableChatsParams = {
14
- authenticatedUserToken: chatSDK.authenticatedUserToken
14
+ authenticatedUserToken: chatSDK.authenticatedUserToken,
15
+ requestId: chatSDK.requestId
15
16
  };
16
17
  try {
17
18
  const reconnectableChatsResponse = await chatSDK.OCClient.getReconnectableChats(reconnectableChatsParams);
@@ -354,6 +354,23 @@ const LiveChatWidgetStateful = props => {
354
354
  }
355
355
  }
356
356
  });
357
+ _omnichannelChatComponents.BroadcastService.getMessageByEventName(_TelemetryConstants.BroadcastEvent.NetworkReconnected).subscribe(async () => {
358
+ var _window2, _window2$location;
359
+ if ((0, _utils.isThisSessionPopout)((_window2 = window) === null || _window2 === void 0 ? void 0 : (_window2$location = _window2.location) === null || _window2$location === void 0 ? void 0 : _window2$location.href)) {
360
+ return;
361
+ }
362
+ const conversationDetails = await (0, _utils.getConversationDetailsCall)(chatSDK);
363
+ if ((conversationDetails === null || conversationDetails === void 0 ? void 0 : conversationDetails.state) === _Constants.LiveWorkItemState.WrapUp || (conversationDetails === null || conversationDetails === void 0 ? void 0 : conversationDetails.state) === _Constants.LiveWorkItemState.Closed) {
364
+ dispatch({
365
+ type: _LiveChatWidgetActionType.LiveChatWidgetActionType.SET_CHAT_DISCONNECT_EVENT_RECEIVED,
366
+ payload: true
367
+ });
368
+ _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.INFO, {
369
+ Event: _TelemetryConstants.TelemetryEvent.ChatDisconnectThreadEventReceived,
370
+ Description: "Chat disconnected due to timeout, user went offline or blocked the device (including closing laptop)"
371
+ });
372
+ }
373
+ });
357
374
 
358
375
  /**
359
376
  * This will allow to sync multiple tabs to handle minimize and maximize state,
@@ -671,11 +688,24 @@ const LiveChatWidgetStateful = props => {
671
688
 
672
689
  // Handle Chat disconnect cases
673
690
  (0, _react2.useEffect)(() => {
691
+ var _inMemoryState$appSta5;
674
692
  const inMemoryState = (0, _createReducer.executeReducer)(state, {
675
693
  type: _LiveChatWidgetActionType.LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
676
694
  payload: null
677
695
  });
678
696
  (0, _chatDisconnectHelper.handleChatDisconnect)(props, inMemoryState, setWebChatStyles);
697
+ const chatDisconnectState = inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta5 = inMemoryState.appStates) === null || _inMemoryState$appSta5 === void 0 ? void 0 : _inMemoryState$appSta5.chatDisconnectEventReceived;
698
+ if (chatDisconnectState && adapter) {
699
+ try {
700
+ adapter.end();
701
+ adapter.close();
702
+ } catch (e) {
703
+ _TelemetryHelper.TelemetryHelper.logWebChatEvent(_TelemetryConstants.LogLevel.ERROR, {
704
+ Event: _TelemetryConstants.TelemetryEvent.EndingAdapterAfterDisconnectionError,
705
+ Description: _Constants.WidgetLoadCustomErrorString.CloseAdapterAfterDisconnectionErrorString
706
+ });
707
+ }
708
+ }
679
709
  }, [state.appStates.chatDisconnectEventReceived]);
680
710
 
681
711
  // if props state gets updates we need to update the renderingMiddlewareProps in the state
@@ -376,6 +376,90 @@ class TranscriptHTMLBuilder {
376
376
  window.addEventListener("online", () => {
377
377
  document.body.innerHTML = \`${this.networkOnlineMessage} <button onclick="window.location.reload()"> Refresh </button>\`;
378
378
  });
379
+
380
+ document.addEventListener("copy", (event) => {
381
+ const clonedSelectedContent = window.getSelection().getRangeAt(0).cloneContents();
382
+ const copiedContent = document.createElement("div");
383
+ copiedContent.appendChild(clonedSelectedContent);
384
+
385
+ event.clipboardData.setData("text/plain", getAllText(copiedContent));
386
+ event.preventDefault();
387
+ });
388
+
389
+
390
+ getAllText = (element) => {
391
+ let plainText = "";
392
+ Array.from(element.childNodes).forEach((node) => {
393
+ // ignore aria-hidden elements and keyboard help text
394
+ const ariaHiddenAttr = node.attributes ? node.attributes.getNamedItem("aria-hidden") : null;
395
+ if ((ariaHiddenAttr && ariaHiddenAttr.value === "true") || node.classList && node.classList.contains("webchat__keyboard-help")) {
396
+ return;
397
+ }
398
+
399
+ // get all texts inside activity body, including message, translated message, attachment name, adaptive card content, status footer, etc.
400
+ if (node.classList && node.classList.contains("webchat__basic-transcript__activity-body")) {
401
+ plainText += this.processTranscriptActivityNode(node);
402
+ return;
403
+ }
404
+ if (node.nodeType === Node.TEXT_NODE) {
405
+ plainText += node.textContent + '\\n';
406
+ } else {
407
+ plainText += this.getAllText(node);
408
+ }
409
+ });
410
+ return plainText;
411
+ }
412
+
413
+ processTranscriptActivityNode = (node) => {
414
+ const divs = node.getElementsByTagName("div");
415
+ let plainText = "";
416
+
417
+ if (divs && divs.length > 1 && divs[1]) {
418
+ const messageRow = node.querySelector(".webchat__stacked-layout__message-row[aria-roledescription='message']");
419
+ const author = node.querySelector(".message-name");
420
+ const attachmentRow = node.querySelector(".webchat__stacked-layout__attachment-row[aria-roledescription='attachment']");
421
+
422
+ if (messageRow) {
423
+ let message = messageRow.getElementsByClassName("webchat__text-content__markdown");
424
+
425
+ if (message.length === 0) {
426
+ message = messageRow.getElementsByClassName("markdown");
427
+ }
428
+
429
+ if (message.length > 0) {
430
+ plainText += author.textContent + '\\n' + message[0].textContent + '\\n';
431
+ }
432
+ } else if (attachmentRow) {
433
+ const attachment = attachmentRow.getElementsByClassName("webchat__fileContent__fileName");
434
+ const adaptiveCard = this.getAdaptiveCardContent(attachmentRow.querySelector(".ac-container.ac-adaptiveCard"));
435
+
436
+ plainText += attachment && attachment.length > 0 ? author.textContent +'\\n' + attachment[0].textContent +'\\n': author.textContent +'\\n' + adaptiveCard +'\\n';
437
+ }
438
+
439
+ const statusElements = node.getElementsByClassName("webchat__stacked-layout__status");
440
+ if (statusElements.length > 0) {
441
+ const timestampelement = statusElements[0].querySelector(".message-timestamp");
442
+ plainText += timestampelement ? timestampelement.textContent+'\\n\\n' : '\\n';
443
+ }
444
+ }
445
+
446
+ return plainText;
447
+ }
448
+
449
+ getAdaptiveCardContent = (node) => {
450
+ if (!node) {
451
+ return undefined;
452
+ }
453
+
454
+ let plainText = "";
455
+ const rows = node.querySelectorAll(".ac-textBlock p");
456
+ rows.forEach((row) => {
457
+ plainText += row.textContent+ '\\n';
458
+ });
459
+
460
+ return plainText;
461
+ }
462
+
379
463
  <\/script>
380
464
  <div id="transcript"></div>
381
465
  <script>
@@ -276,6 +276,7 @@ _defineProperty(WidgetLoadTelemetryMessage, "PersistedStateRetrievedMessage", "P
276
276
  export class WidgetLoadCustomErrorString {}
277
277
  _defineProperty(WidgetLoadCustomErrorString, "AuthenticationFailedErrorString", "Authentication was not successful");
278
278
  _defineProperty(WidgetLoadCustomErrorString, "NetworkErrorString", "Network Error");
279
+ _defineProperty(WidgetLoadCustomErrorString, "CloseAdapterAfterDisconnectionErrorString", "Error trying to end/close chat adapter after the widget is back on-line, for an already disconnected session");
279
280
  export class PrepareEndChatDescriptionConstants {}
280
281
  _defineProperty(PrepareEndChatDescriptionConstants, "ConversationEndedByCustomerWithoutPostChat", "Conversation ended by customer. Post chat not configured or should not show.");
281
282
  _defineProperty(PrepareEndChatDescriptionConstants, "ConversationEndedByCustomerWithInvalidPostChat", "Conversation ended by customer. Post chat context is invalid.");
@@ -210,6 +210,7 @@ export let TelemetryEvent;
210
210
  TelemetryEvent["PostChatSurveyLoaded"] = "PostChatSurveyLoaded";
211
211
  TelemetryEvent["ChatDisconnectThreadEventReceived"] = "ChatDisconnectThreadEventReceived";
212
212
  TelemetryEvent["HiddenAdaptiveCardMessageReceived"] = "HiddenAdaptiveCardMessageReceived";
213
+ TelemetryEvent["EndingAdapterAfterDisconnectionError"] = "EndingAdapterAfterDisconnectionError";
213
214
  })(TelemetryEvent || (TelemetryEvent = {}));
214
215
  export class TelemetryConstants {
215
216
  static map(eventTypeOrScenarioType) {
@@ -1,8 +1,9 @@
1
+ import { LogLevel, TelemetryEvent } from "../../../common/telemetry/TelemetryConstants";
1
2
  import { NotificationHandler } from "../../webchatcontainerstateful/webchatcontroller/notification/NotificationHandler";
2
3
  import { NotificationScenarios } from "../../webchatcontainerstateful/webchatcontroller/enums/NotificationScenarios";
3
- import { defaultMiddlewareLocalizedTexts } from "../../webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts";
4
- import { LogLevel, TelemetryEvent } from "../../../common/telemetry/TelemetryConstants";
5
4
  import { TelemetryHelper } from "../../../common/telemetry/TelemetryHelper";
5
+ import { defaultMiddlewareLocalizedTexts } from "../../webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts";
6
+
6
7
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
8
  const handleChatDisconnect = (props, state, setWebChatStyles) => {
8
9
  var _state$appStates, _state$domainStates, _state$domainStates$m, _props$webChatContain, _props$webChatContain2;
@@ -1,9 +1,10 @@
1
+ import { BroadcastEvent, LogLevel, TelemetryEvent } from "../../../common/telemetry/TelemetryConstants";
2
+ import { BroadcastService } from "@microsoft/omnichannel-chat-components";
1
3
  import { Constants } from "../../../common/Constants";
2
4
  import { NotificationHandler } from "../../webchatcontainerstateful/webchatcontroller/notification/NotificationHandler";
3
5
  import { NotificationScenarios } from "../../webchatcontainerstateful/webchatcontroller/enums/NotificationScenarios";
4
- import { defaultMiddlewareLocalizedTexts } from "../../webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts";
5
6
  import { TelemetryHelper } from "../../../common/telemetry/TelemetryHelper";
6
- import { LogLevel, TelemetryEvent } from "../../../common/telemetry/TelemetryConstants";
7
+ import { defaultMiddlewareLocalizedTexts } from "../../webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts";
7
8
  const isInternetConnected = async () => {
8
9
  try {
9
10
  const response = await fetch(Constants.internetConnectionTestUrl);
@@ -26,6 +27,9 @@ export const createInternetConnectionChangeHandler = async () => {
26
27
  Event: TelemetryEvent.NetworkReconnected
27
28
  });
28
29
  NotificationHandler.notifySuccess(NotificationScenarios.InternetConnection, defaultMiddlewareLocalizedTexts.MIDDLEWARE_BANNER_INTERNET_BACK_ONLINE);
30
+ BroadcastService.postMessage({
31
+ eventName: BroadcastEvent.NetworkReconnected
32
+ });
29
33
  }
30
34
  };
31
35
 
@@ -1,8 +1,8 @@
1
1
  import { Constants } from "../../../common/Constants";
2
2
  import MarkdownIt from "markdown-it";
3
3
  import MarkdownItForInline from "markdown-it-for-inline";
4
- import MarkdownSlack from "slack-markdown-it";
5
4
  import { defaultMarkdownLocalizedTexts } from "../../webchatcontainerstateful/common/defaultProps/defaultMarkdownLocalizedTexts";
5
+ import { addSlackMarkdownIt } from "./helpers/markdownHelper";
6
6
 
7
7
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
8
  export const createMarkdown = (disableMarkdownMessageFormatting, disableNewLineMarkdownSupport) => {
@@ -13,7 +13,7 @@ export const createMarkdown = (disableMarkdownMessageFormatting, disableNewLineM
13
13
  linkify: true,
14
14
  breaks: !disableNewLineMarkdownSupport
15
15
  });
16
- markdown.use(MarkdownSlack);
16
+ markdown = addSlackMarkdownIt(markdown);
17
17
  } else {
18
18
  markdown = new MarkdownIt(Constants.Zero, {
19
19
  html: true,
@@ -0,0 +1,15 @@
1
+ import SlackMarkdown from "slack-markdown-it";
2
+ export const addSlackMarkdownIt = markdown => {
3
+ try {
4
+ markdown.use(SlackMarkdown);
5
+ } catch (e) {
6
+ // this is to support the case when slack-markdown-it
7
+ // transpiled code doesn't export default (webpack5)
8
+ if (SlackMarkdown.default.apply) {
9
+ markdown.use(SlackMarkdown.default);
10
+ } else {
11
+ console.error("Error while adding slackMarkdown plugin", e);
12
+ }
13
+ }
14
+ return markdown;
15
+ };
@@ -6,7 +6,8 @@ export const shouldSetPreChatIfPersistentChat = async (chatSDK, conversationMode
6
6
  let skipPreChat = false;
7
7
  if (persistentEnabled) {
8
8
  const reconnectableChatsParams = {
9
- authenticatedUserToken: chatSDK.authenticatedUserToken
9
+ authenticatedUserToken: chatSDK.authenticatedUserToken,
10
+ requestId: chatSDK.requestId
10
11
  };
11
12
  try {
12
13
  const reconnectableChatsResponse = await chatSDK.OCClient.getReconnectableChats(reconnectableChatsParams);
@@ -2,7 +2,7 @@ function _extends() { _extends = Object.assign ? Object.assign.bind() : function
2
2
  import { BroadcastEvent, LogLevel, TelemetryEvent } from "../../../common/telemetry/TelemetryConstants";
3
3
  import { BroadcastService, BroadcastServiceInitialize, decodeComponentString } from "@microsoft/omnichannel-chat-components";
4
4
  import { Components } from "botframework-webchat";
5
- import { ConfirmationState, Constants, ConversationEndEntity, E2VVOptions, LiveWorkItemState, PrepareEndChatDescriptionConstants, StorageType } from "../../../common/Constants";
5
+ import { ConfirmationState, Constants, ConversationEndEntity, E2VVOptions, LiveWorkItemState, PrepareEndChatDescriptionConstants, StorageType, WidgetLoadCustomErrorString } from "../../../common/Constants";
6
6
  import { Stack } from "@fluentui/react";
7
7
  import React, { useEffect, useRef, useState } from "react";
8
8
  import { TelemetryManager, TelemetryTimers } from "../../../common/telemetry/TelemetryManager";
@@ -346,6 +346,23 @@ export const LiveChatWidgetStateful = props => {
346
346
  }
347
347
  }
348
348
  });
349
+ BroadcastService.getMessageByEventName(BroadcastEvent.NetworkReconnected).subscribe(async () => {
350
+ var _window2, _window2$location;
351
+ if (isThisSessionPopout((_window2 = window) === null || _window2 === void 0 ? void 0 : (_window2$location = _window2.location) === null || _window2$location === void 0 ? void 0 : _window2$location.href)) {
352
+ return;
353
+ }
354
+ const conversationDetails = await getConversationDetailsCall(chatSDK);
355
+ if ((conversationDetails === null || conversationDetails === void 0 ? void 0 : conversationDetails.state) === LiveWorkItemState.WrapUp || (conversationDetails === null || conversationDetails === void 0 ? void 0 : conversationDetails.state) === LiveWorkItemState.Closed) {
356
+ dispatch({
357
+ type: LiveChatWidgetActionType.SET_CHAT_DISCONNECT_EVENT_RECEIVED,
358
+ payload: true
359
+ });
360
+ TelemetryHelper.logActionEvent(LogLevel.INFO, {
361
+ Event: TelemetryEvent.ChatDisconnectThreadEventReceived,
362
+ Description: "Chat disconnected due to timeout, user went offline or blocked the device (including closing laptop)"
363
+ });
364
+ }
365
+ });
349
366
 
350
367
  /**
351
368
  * This will allow to sync multiple tabs to handle minimize and maximize state,
@@ -663,11 +680,24 @@ export const LiveChatWidgetStateful = props => {
663
680
 
664
681
  // Handle Chat disconnect cases
665
682
  useEffect(() => {
683
+ var _inMemoryState$appSta5;
666
684
  const inMemoryState = executeReducer(state, {
667
685
  type: LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
668
686
  payload: null
669
687
  });
670
688
  handleChatDisconnect(props, inMemoryState, setWebChatStyles);
689
+ const chatDisconnectState = inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta5 = inMemoryState.appStates) === null || _inMemoryState$appSta5 === void 0 ? void 0 : _inMemoryState$appSta5.chatDisconnectEventReceived;
690
+ if (chatDisconnectState && adapter) {
691
+ try {
692
+ adapter.end();
693
+ adapter.close();
694
+ } catch (e) {
695
+ TelemetryHelper.logWebChatEvent(LogLevel.ERROR, {
696
+ Event: TelemetryEvent.EndingAdapterAfterDisconnectionError,
697
+ Description: WidgetLoadCustomErrorString.CloseAdapterAfterDisconnectionErrorString
698
+ });
699
+ }
700
+ }
671
701
  }, [state.appStates.chatDisconnectEventReceived]);
672
702
 
673
703
  // if props state gets updates we need to update the renderingMiddlewareProps in the state
@@ -371,6 +371,90 @@ class TranscriptHTMLBuilder {
371
371
  window.addEventListener("online", () => {
372
372
  document.body.innerHTML = \`${this.networkOnlineMessage} <button onclick="window.location.reload()"> Refresh </button>\`;
373
373
  });
374
+
375
+ document.addEventListener("copy", (event) => {
376
+ const clonedSelectedContent = window.getSelection().getRangeAt(0).cloneContents();
377
+ const copiedContent = document.createElement("div");
378
+ copiedContent.appendChild(clonedSelectedContent);
379
+
380
+ event.clipboardData.setData("text/plain", getAllText(copiedContent));
381
+ event.preventDefault();
382
+ });
383
+
384
+
385
+ getAllText = (element) => {
386
+ let plainText = "";
387
+ Array.from(element.childNodes).forEach((node) => {
388
+ // ignore aria-hidden elements and keyboard help text
389
+ const ariaHiddenAttr = node.attributes ? node.attributes.getNamedItem("aria-hidden") : null;
390
+ if ((ariaHiddenAttr && ariaHiddenAttr.value === "true") || node.classList && node.classList.contains("webchat__keyboard-help")) {
391
+ return;
392
+ }
393
+
394
+ // get all texts inside activity body, including message, translated message, attachment name, adaptive card content, status footer, etc.
395
+ if (node.classList && node.classList.contains("webchat__basic-transcript__activity-body")) {
396
+ plainText += this.processTranscriptActivityNode(node);
397
+ return;
398
+ }
399
+ if (node.nodeType === Node.TEXT_NODE) {
400
+ plainText += node.textContent + '\\n';
401
+ } else {
402
+ plainText += this.getAllText(node);
403
+ }
404
+ });
405
+ return plainText;
406
+ }
407
+
408
+ processTranscriptActivityNode = (node) => {
409
+ const divs = node.getElementsByTagName("div");
410
+ let plainText = "";
411
+
412
+ if (divs && divs.length > 1 && divs[1]) {
413
+ const messageRow = node.querySelector(".webchat__stacked-layout__message-row[aria-roledescription='message']");
414
+ const author = node.querySelector(".message-name");
415
+ const attachmentRow = node.querySelector(".webchat__stacked-layout__attachment-row[aria-roledescription='attachment']");
416
+
417
+ if (messageRow) {
418
+ let message = messageRow.getElementsByClassName("webchat__text-content__markdown");
419
+
420
+ if (message.length === 0) {
421
+ message = messageRow.getElementsByClassName("markdown");
422
+ }
423
+
424
+ if (message.length > 0) {
425
+ plainText += author.textContent + '\\n' + message[0].textContent + '\\n';
426
+ }
427
+ } else if (attachmentRow) {
428
+ const attachment = attachmentRow.getElementsByClassName("webchat__fileContent__fileName");
429
+ const adaptiveCard = this.getAdaptiveCardContent(attachmentRow.querySelector(".ac-container.ac-adaptiveCard"));
430
+
431
+ plainText += attachment && attachment.length > 0 ? author.textContent +'\\n' + attachment[0].textContent +'\\n': author.textContent +'\\n' + adaptiveCard +'\\n';
432
+ }
433
+
434
+ const statusElements = node.getElementsByClassName("webchat__stacked-layout__status");
435
+ if (statusElements.length > 0) {
436
+ const timestampelement = statusElements[0].querySelector(".message-timestamp");
437
+ plainText += timestampelement ? timestampelement.textContent+'\\n\\n' : '\\n';
438
+ }
439
+ }
440
+
441
+ return plainText;
442
+ }
443
+
444
+ getAdaptiveCardContent = (node) => {
445
+ if (!node) {
446
+ return undefined;
447
+ }
448
+
449
+ let plainText = "";
450
+ const rows = node.querySelectorAll(".ac-textBlock p");
451
+ rows.forEach((row) => {
452
+ plainText += row.textContent+ '\\n';
453
+ });
454
+
455
+ return plainText;
456
+ }
457
+
374
458
  <\/script>
375
459
  <div id="transcript"></div>
376
460
  <script>
@@ -254,6 +254,7 @@ export declare class WidgetLoadTelemetryMessage {
254
254
  export declare class WidgetLoadCustomErrorString {
255
255
  static readonly AuthenticationFailedErrorString = "Authentication was not successful";
256
256
  static readonly NetworkErrorString = "Network Error";
257
+ static readonly CloseAdapterAfterDisconnectionErrorString = "Error trying to end/close chat adapter after the widget is back on-line, for an already disconnected session";
257
258
  }
258
259
  export declare class PrepareEndChatDescriptionConstants {
259
260
  static readonly ConversationEndedByCustomerWithoutPostChat = "Conversation ended by customer. Post chat not configured or should not show.";
@@ -202,7 +202,8 @@ export declare enum TelemetryEvent {
202
202
  PostChatSurveyLoadingPaneLoaded = "PostChatSurveyLoadingPaneLoaded",
203
203
  PostChatSurveyLoaded = "PostChatSurveyLoaded",
204
204
  ChatDisconnectThreadEventReceived = "ChatDisconnectThreadEventReceived",
205
- HiddenAdaptiveCardMessageReceived = "HiddenAdaptiveCardMessageReceived"
205
+ HiddenAdaptiveCardMessageReceived = "HiddenAdaptiveCardMessageReceived",
206
+ EndingAdapterAfterDisconnectionError = "EndingAdapterAfterDisconnectionError"
206
207
  }
207
208
  export interface TelemetryInput {
208
209
  scenarioType: ScenarioType;
@@ -0,0 +1,2 @@
1
+ import MarkdownIt from "markdown-it";
2
+ export declare const addSlackMarkdownIt: (markdown: MarkdownIt) => MarkdownIt;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microsoft/omnichannel-chat-widget",
3
- "version": "1.7.3-main.c5e352d",
3
+ "version": "1.7.3-main.e452e73",
4
4
  "description": "Microsoft Omnichannel Chat Widget",
5
5
  "main": "lib/cjs/index.js",
6
6
  "types": "lib/types/index.d.ts",
@@ -75,7 +75,7 @@
75
75
  },
76
76
  "dependencies": {
77
77
  "@microsoft/omnichannel-chat-components": "1.1.5",
78
- "@microsoft/omnichannel-chat-sdk": "^1.9.9",
78
+ "@microsoft/omnichannel-chat-sdk": "^1.10.1",
79
79
  "abort-controller-es5": "^2.0.1",
80
80
  "dompurify": "^2.5.4",
81
81
  "markdown-it": "^12.3.2",