@microsoft/omnichannel-chat-widget 1.8.2-main.d82a79b → 1.8.2-main.f638bed

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 (26) hide show
  1. package/README.md +46 -1
  2. package/lib/cjs/common/Constants.js +5 -0
  3. package/lib/cjs/common/telemetry/TelemetryConstants.js +1 -0
  4. package/lib/cjs/common/utils.js +21 -2
  5. package/lib/cjs/components/chatbuttonstateful/ChatButtonStateful.js +4 -4
  6. package/lib/cjs/components/livechatwidget/common/customEventHandler.js +53 -0
  7. package/lib/cjs/components/livechatwidget/common/initWebChatComposer.js +3 -1
  8. package/lib/cjs/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +5 -1
  9. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/customEventMiddleware.js +41 -0
  10. package/lib/cjs/contexts/common/CustomEventType.js +1 -0
  11. package/lib/esm/common/Constants.js +5 -0
  12. package/lib/esm/common/telemetry/TelemetryConstants.js +1 -0
  13. package/lib/esm/common/utils.js +17 -0
  14. package/lib/esm/components/chatbuttonstateful/ChatButtonStateful.js +4 -4
  15. package/lib/esm/components/livechatwidget/common/customEventHandler.js +45 -0
  16. package/lib/esm/components/livechatwidget/common/initWebChatComposer.js +3 -1
  17. package/lib/esm/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +5 -1
  18. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/customEventMiddleware.js +33 -0
  19. package/lib/esm/contexts/common/CustomEventType.js +1 -0
  20. package/lib/types/common/Constants.d.ts +5 -0
  21. package/lib/types/common/telemetry/TelemetryConstants.d.ts +1 -0
  22. package/lib/types/common/utils.d.ts +3 -0
  23. package/lib/types/components/livechatwidget/common/customEventHandler.d.ts +4 -0
  24. package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/customEventMiddleware.d.ts +22 -0
  25. package/lib/types/contexts/common/CustomEventType.d.ts +6 -0
  26. package/package.json +1 -1
package/README.md CHANGED
@@ -223,6 +223,51 @@ const customizedFooterProp: IFooterProps = {
223
223
 
224
224
  > :pushpin: Note that [WebChat hooks](https://github.com/microsoft/BotFramework-WebChat/blob/main/docs/HOOKS.md) can also be used in any custom components.
225
225
 
226
+ #### Bidirectional Custom Events
227
+ - Sending events from a hosting web page to bots/agents
228
+ - Register a function to post event
229
+ ```js
230
+ //define sendCustomEvent function
231
+ const sendCustomEvent = (payload) => {
232
+ const customEvent = {
233
+ eventName: "sendCustomEvent",
234
+ payload
235
+ };
236
+ BroadcastService.postMessage(customEvent);
237
+ };
238
+
239
+ //attach the sendCustomEvent function to window object
240
+ window["sendCustomEvent"] = sendCustomEvent;
241
+
242
+ //invoke the sendCustomEvent function with some customized payload
243
+ window.sendCustomEvent({
244
+ customEventName: "TestEvent",
245
+ customEventValue: {
246
+ boolVar: true,
247
+ displayableVar: {
248
+ isDisplayable: true,
249
+ value: "From C2: "+ new Date().toISOString()
250
+ },
251
+ numberVar: -10.5,
252
+ stringVar: "Hello from C2 str: " + new Date().toISOString()
253
+ }
254
+ })
255
+ ```
256
+ - Receiving events from bots/agents
257
+ ```js
258
+ //define setOnCustomEvent function
259
+ const setOnCustomEvent = (callback) => {
260
+ BroadcastService.getMessageByEventName("onCustomEvent").subscribe((event) => {
261
+ if (event && typeof callback === "function") {
262
+ callback(event);
263
+ }
264
+ });
265
+ };
266
+
267
+ //set callback function
268
+ setOnCustomEvent((event) => console.log(event));
269
+ ```
270
+
226
271
  ## See Also
227
272
 
228
273
  [Customizations Dev Guide](https://github.com/microsoft/omnichannel-chat-widget/blob/main/docs/customizations/getstarted.md)\
@@ -232,4 +277,4 @@ const customizedFooterProp: IFooterProps = {
232
277
  [How to Add Visual Regression Tests](https://github.com/microsoft/omnichannel-chat-widget/blob/main/docs/VisualRegressionTestingGuide.md)\
233
278
  [Security](https://github.com/microsoft/omnichannel-chat-widget/blob/main/SECURITY.md)\
234
279
  [Third Party Cookie Support](https://github.com/microsoft/omnichannel-chat-widget/blob/main/docs/Tpc.md)\
235
- [Storybook](https://microsoft.github.io/omnichannel-chat-widget/docs/storybook/)
280
+ [Storybook](https://microsoft.github.io/omnichannel-chat-widget/docs/storybook/)
@@ -131,6 +131,11 @@ _defineProperty(Constants, "InitContextParamsResponse", "initContextParamsRespon
131
131
  _defineProperty(Constants, "OCOriginalMessageId", "OriginalMessageId");
132
132
  _defineProperty(Constants, "WebchatSequenceIdAttribute", "webchat:sequence-id");
133
133
  _defineProperty(Constants, "MessageSequenceIdOverride", "MessageSequenceIdOverride");
134
+ _defineProperty(Constants, "sendCustomEvent", "sendCustomEvent");
135
+ _defineProperty(Constants, "onCustomEvent", "onCustomEvent");
136
+ _defineProperty(Constants, "customEventName", "customEventName");
137
+ _defineProperty(Constants, "customEventValue", "customEventValue");
138
+ _defineProperty(Constants, "Hidden", "Hidden");
134
139
  _defineProperty(Constants, "EndConversationDueToOverflow", "endconversationduetooverflow");
135
140
  const Regex = (_class = /*#__PURE__*/_createClass(function Regex() {
136
141
  _classCallCheck(this, Regex);
@@ -229,6 +229,7 @@ exports.TelemetryEvent = TelemetryEvent;
229
229
  TelemetryEvent["SystemMessageReceived"] = "SystemMessageReceived";
230
230
  TelemetryEvent["RehydrateMessageReceived"] = "RehydrateMessageReceived";
231
231
  TelemetryEvent["CustomContextReceived"] = "CustomContextReceived";
232
+ TelemetryEvent["CustomEventAction"] = "CustomEventAction";
232
233
  TelemetryEvent["NetworkDisconnected"] = "NetworkDisconnected";
233
234
  TelemetryEvent["NetworkReconnected"] = "NetworkReconnected";
234
235
  TelemetryEvent["LinkModePostChatWorkflowStarted"] = "LinkModePostChatWorkflowStarted";
@@ -3,11 +3,11 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.getConversationDetailsCall = exports.getBroadcastChannelName = exports.formatTemplateString = exports.findParentFocusableElementsWithoutChildContainer = exports.findAllFocusableElement = exports.extractPreChatSurveyResponseValues = exports.escapeHtml = exports.debounceLeading = exports.createTimer = exports.createFileAndDownload = exports.checkContactIdError = exports.changeLanguageCodeFormatForWebChat = exports.addDelayInMs = void 0;
6
+ exports.getCustomEventValue = exports.getConversationDetailsCall = exports.getBroadcastChannelName = exports.formatTemplateString = exports.findParentFocusableElementsWithoutChildContainer = exports.findAllFocusableElement = exports.extractPreChatSurveyResponseValues = exports.escapeHtml = exports.debounceLeading = exports.createTimer = exports.createFileAndDownload = exports.checkContactIdError = exports.changeLanguageCodeFormatForWebChat = exports.addDelayInMs = void 0;
7
7
  exports.getDeviceType = getDeviceType;
8
8
  exports.getWidgetEndChatEventName = exports.getWidgetCacheIdfromProps = exports.getWidgetCacheId = exports.getTimestampHourMinute = exports.getStateFromCache = exports.getLocaleDirection = exports.getIconText = exports.getDomain = void 0;
9
9
  exports.isEndConversationDueToOverflowActivity = isEndConversationDueToOverflowActivity;
10
- exports.setTabIndices = exports.setOcUserAgent = exports.setFocusOnSendBox = exports.setFocusOnElement = exports.preventFocusToMoveOutOfElement = exports.parseLowerCaseString = exports.parseAdaptiveCardPayload = exports.newGuid = exports.isUndefinedOrEmpty = exports.isThisSessionPopout = exports.isNullOrUndefined = exports.isNullOrEmptyString = void 0;
10
+ exports.setTabIndices = exports.setOcUserAgent = exports.setFocusOnSendBox = exports.setFocusOnElement = exports.preventFocusToMoveOutOfElement = exports.parseLowerCaseString = exports.parseAdaptiveCardPayload = exports.newGuid = exports.isValidCustomEvent = exports.isUndefinedOrEmpty = exports.isThisSessionPopout = exports.isNullOrUndefined = exports.isNullOrEmptyString = void 0;
11
11
  var _Constants = require("./Constants");
12
12
  var _TelemetryConstants = require("./telemetry/TelemetryConstants");
13
13
  var _omnichannelChatComponents = require("@microsoft/omnichannel-chat-components");
@@ -497,6 +497,25 @@ function getDeviceType() {
497
497
  return "standard";
498
498
  }
499
499
  }
500
+
501
+ //Bots expect a payload containing:
502
+ //1. customEventName: this should be string describe the event name
503
+ //2. customEventValue: given the value is from customer with unknown type, it is required to stringify the payload later
504
+ const isValidCustomEvent = payload => {
505
+ if (_Constants.Constants.customEventName in payload && payload.customEventName && typeof payload.customEventName === _Constants.Constants.String && _Constants.Constants.customEventValue in payload && payload.customEventValue) return true;
506
+ return false;
507
+ };
508
+ exports.isValidCustomEvent = isValidCustomEvent;
509
+ const getCustomEventValue = customEventPayload => {
510
+ let returnVal = "";
511
+ try {
512
+ returnVal = typeof customEventPayload.customEventValue === _Constants.Constants.String ? customEventPayload.customEventValue : JSON.stringify(customEventPayload.customEventValue);
513
+ } catch (error) {
514
+ console.error(error);
515
+ }
516
+ return returnVal;
517
+ };
518
+ exports.getCustomEventValue = getCustomEventValue;
500
519
  function isEndConversationDueToOverflowActivity(activity) {
501
520
  var _activity$channelData, _activity$channelData2;
502
521
  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.Constants.EndConversationDueToOverflow);
@@ -74,7 +74,6 @@ const ChatButtonStateful = props => {
74
74
  };
75
75
  const outOfOfficeStyleProps = Object.assign({}, _defaultOutOfOfficeChatButtonStyleProps.defaultOutOfOfficeChatButtonStyleProps, outOfOfficeButtonProps === null || outOfOfficeButtonProps === void 0 ? void 0 : outOfOfficeButtonProps.styleProps);
76
76
  const controlProps = {
77
- ...(buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.controlProps),
78
77
  id: "oc-lcw-chat-button",
79
78
  dir: state.domainStates.globalDir,
80
79
  titleText: "Let's Chat!",
@@ -83,7 +82,8 @@ const ChatButtonStateful = props => {
83
82
  unreadMessageCount: state.appStates.unreadMessageCount ? state.appStates.unreadMessageCount > _Constants.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",
84
83
  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,
85
84
  // Regular chat button onClick - this will always take precedence
86
- onClick: () => ref.current()
85
+ onClick: () => ref.current(),
86
+ ...(buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.controlProps)
87
87
  };
88
88
  const outOfOfficeControlProps = {
89
89
  // Only take specific properties from outOfOfficeButtonProps, never onClick
@@ -92,7 +92,6 @@ const ChatButtonStateful = props => {
92
92
  titleText: (outOfOfficeButtonProps === null || outOfOfficeButtonProps === void 0 ? void 0 : (_outOfOfficeButtonPro = outOfOfficeButtonProps.controlProps) === null || _outOfOfficeButtonPro === void 0 ? void 0 : _outOfOfficeButtonPro.titleText) || "We're Offline",
93
93
  subtitleText: (outOfOfficeButtonProps === null || outOfOfficeButtonProps === void 0 ? void 0 : (_outOfOfficeButtonPro2 = outOfOfficeButtonProps.controlProps) === null || _outOfOfficeButtonPro2 === void 0 ? void 0 : _outOfOfficeButtonPro2.subtitleText) || "No agents available",
94
94
  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,
95
- ...(outOfOfficeButtonProps === null || outOfOfficeButtonProps === void 0 ? void 0 : outOfOfficeButtonProps.controlProps),
96
95
  // Out-of-office specific onClick - this will ALWAYS take precedence
97
96
  onClick: () => {
98
97
  if (state.appStates.isMinimized) {
@@ -105,7 +104,8 @@ const ChatButtonStateful = props => {
105
104
  type: _LiveChatWidgetActionType.LiveChatWidgetActionType.SET_CONVERSATION_STATE,
106
105
  payload: _ConversationState.ConversationState.OutOfOffice
107
106
  });
108
- }
107
+ },
108
+ ...(outOfOfficeButtonProps === null || outOfOfficeButtonProps === void 0 ? void 0 : outOfOfficeButtonProps.controlProps)
109
109
  };
110
110
  (0, _react.useEffect)(() => {
111
111
  _TelemetryHelper.TelemetryHelper.logLoadingEvent(_TelemetryConstants.LogLevel.INFO, {
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.subscribeToSendCustomEvent = exports.customEventCallback = void 0;
7
+ var _Constants = require("../../../common/Constants");
8
+ var _TelemetryHelper = require("../../../common/telemetry/TelemetryHelper");
9
+ var _TelemetryConstants = require("../../../common/telemetry/TelemetryConstants");
10
+ var _utils = require("../../../common/utils");
11
+ const customEventCallback = facadeChatSDK => event => {
12
+ if (!(_Constants.Constants.payload in event)) return;
13
+ if ((0, _utils.isValidCustomEvent)(event.payload)) {
14
+ const customEventPayload = event.payload;
15
+ try {
16
+ const customEventValueStr = (0, _utils.getCustomEventValue)(customEventPayload);
17
+ const customEventName = customEventPayload.customEventName;
18
+ const messageMeta = {
19
+ customEvent: _Constants.Constants.true,
20
+ customEventName: customEventName,
21
+ customEventValue: customEventValueStr
22
+ };
23
+ const messagePayload = {
24
+ content: "",
25
+ tags: [_Constants.Constants.Hidden],
26
+ metadata: messageMeta,
27
+ timestamp: new Date()
28
+ };
29
+ facadeChatSDK.sendMessage(messagePayload);
30
+ _TelemetryHelper.TelemetryHelper.logActionEventToAllTelemetry(_TelemetryConstants.LogLevel.DEBUG, {
31
+ Event: _TelemetryConstants.TelemetryEvent.CustomEventAction,
32
+ Description: "Sent customEvent.",
33
+ CustomProperties: {
34
+ customEventName,
35
+ lengthCustomEventValue: customEventValueStr.length
36
+ }
37
+ });
38
+ } catch (error) {
39
+ _TelemetryHelper.TelemetryHelper.logActionEventToAllTelemetry(_TelemetryConstants.LogLevel.ERROR, {
40
+ Event: _TelemetryConstants.TelemetryEvent.CustomEventAction,
41
+ Description: "Failed to process CustomEvent.",
42
+ ExceptionDetails: {
43
+ error
44
+ }
45
+ });
46
+ }
47
+ }
48
+ };
49
+ exports.customEventCallback = customEventCallback;
50
+ const subscribeToSendCustomEvent = (broadcastService, facadeChatSDK, customEventCallback) => {
51
+ broadcastService.getMessageByEventName(_Constants.Constants.sendCustomEvent).subscribe(customEventCallback(facadeChatSDK));
52
+ };
53
+ exports.subscribeToSendCustomEvent = subscribeToSendCustomEvent;
@@ -37,9 +37,11 @@ var _htmlPlayerMiddleware = _interopRequireDefault(require("../../webchatcontain
37
37
  var _htmlTextMiddleware = _interopRequireDefault(require("../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/htmlTextMiddleware"));
38
38
  var _preProcessingMiddleware = _interopRequireDefault(require("../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/preProcessingMiddleware"));
39
39
  var _sanitizationMiddleware = _interopRequireDefault(require("../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/sanitizationMiddleware"));
40
+ var _customEventMiddleware = _interopRequireDefault(require("../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/customEventMiddleware"));
40
41
  var _ConversationState = require("../../../contexts/common/ConversationState");
41
42
  var _createReducer = require("../../../contexts/createReducer");
42
43
  var _queueOverflowHandlerMiddleware = require("../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/queueOverflowHandlerMiddleware");
44
+ var _omnichannelChatComponents = require("@microsoft/omnichannel-chat-components");
43
45
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
44
46
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
45
47
  const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endChat) => {
@@ -118,7 +120,7 @@ const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endChat) =>
118
120
  };
119
121
  webChatStore = (0, _botframeworkWebchat.createStore)({},
120
122
  //initial state
121
- _preProcessingMiddleware.default, _attachmentProcessingMiddleware.default, (0, _attachmentUploadValidatorMiddleware.default)((_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), (0, _queueOverflowHandlerMiddleware.createQueueOverflowMiddleware)(state, dispatch), (0, _channelDataMiddleware.default)(addConversationalSurveyTagsCallback), (0, _conversationEndMiddleware.default)(conversationEndCallback, startConversationalSurveyCallback, endConversationalSurveyCallback), (0, _dataMaskingMiddleware.default)((_state$domainStates$l3 = state.domainStates.liveChatConfig) === null || _state$domainStates$l3 === void 0 ? void 0 : _state$domainStates$l3.DataMaskingInfo), _messageTimestampMiddleware.createMessageTimeStampMiddleware, _messageSequenceIdOverrideMiddleware.createMessageSequenceIdOverrideMiddleware, _gifUploadMiddleware.default, _htmlPlayerMiddleware.default, (0, _htmlTextMiddleware.default)(honorsTargetInHTMLLinks), (0, _maxMessageSizeValidator.default)(localizedTexts), _sanitizationMiddleware.default,
123
+ _preProcessingMiddleware.default, _attachmentProcessingMiddleware.default, (0, _attachmentUploadValidatorMiddleware.default)((_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), (0, _customEventMiddleware.default)(_omnichannelChatComponents.BroadcastService), (0, _queueOverflowHandlerMiddleware.createQueueOverflowMiddleware)(state, dispatch), (0, _channelDataMiddleware.default)(addConversationalSurveyTagsCallback), (0, _conversationEndMiddleware.default)(conversationEndCallback, startConversationalSurveyCallback, endConversationalSurveyCallback), (0, _dataMaskingMiddleware.default)((_state$domainStates$l3 = state.domainStates.liveChatConfig) === null || _state$domainStates$l3 === void 0 ? void 0 : _state$domainStates$l3.DataMaskingInfo), _messageTimestampMiddleware.createMessageTimeStampMiddleware, _messageSequenceIdOverrideMiddleware.createMessageSequenceIdOverrideMiddleware, _gifUploadMiddleware.default, _htmlPlayerMiddleware.default, (0, _htmlTextMiddleware.default)(honorsTargetInHTMLLinks), (0, _maxMessageSizeValidator.default)(localizedTexts), _sanitizationMiddleware.default,
122
124
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
123
125
  ...(((_props$webChatContain7 = props.webChatContainerProps) === null || _props$webChatContain7 === void 0 ? void 0 : _props$webChatContain7.storeMiddlewares) ?? []));
124
126
  _WebChatStoreLoader.WebChatStoreLoader.store = webChatStore;
@@ -57,6 +57,7 @@ var _startProactiveChat = require("../common/startProactiveChat");
57
57
  var _useChatAdapterStore = _interopRequireDefault(require("../../../hooks/useChatAdapterStore"));
58
58
  var _useChatContextStore = _interopRequireDefault(require("../../../hooks/useChatContextStore"));
59
59
  var _useFacadeChatSDKStore = _interopRequireDefault(require("../../../hooks/useFacadeChatSDKStore"));
60
+ var _customEventHandler = require("../common/customEventHandler");
60
61
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
61
62
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
62
63
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
@@ -421,7 +422,7 @@ const LiveChatWidgetStateful = props => {
421
422
  _omnichannelChatComponents.BroadcastService.getMessageByEventName(_TelemetryConstants.BroadcastEvent.StartChat).subscribe(msg => {
422
423
  var _msg$payload5, _msg$payload6, _msg$payload7, _msg$payload9, _inMemoryState$appSta2, _inMemoryState$appSta3, _inMemoryState$appSta4;
423
424
  // If chat is out of operating hours chat widget sets the conversation state to OutOfOffice.
424
- if (state.appStates.outsideOperatingHours === true) {
425
+ if (state.appStates.outsideOperatingHours && state.appStates.conversationState !== _ConversationState.ConversationState.Active) {
425
426
  dispatch({
426
427
  type: _LiveChatWidgetActionType.LiveChatWidgetActionType.SET_MINIMIZED,
427
428
  payload: false
@@ -588,6 +589,9 @@ const LiveChatWidgetStateful = props => {
588
589
  }
589
590
  });
590
591
 
592
+ // subscribe custom event
593
+ (0, _customEventHandler.subscribeToSendCustomEvent)(_omnichannelChatComponents.BroadcastService, facadeChatSDK, _customEventHandler.customEventCallback);
594
+
591
595
  // Check for TPC and log in telemetry if blocked
592
596
  (0, _defaultClientDataStoreProvider.isCookieAllowed)();
593
597
  return () => {
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.isValidCustomEvent = exports.default = void 0;
7
+ var _Constants = require("../../../../../common/Constants");
8
+ var _WebChatActionType = require("../../enums/WebChatActionType");
9
+ /******
10
+ * CustomEventMiddleware
11
+ *
12
+ * This middleware is invoked when a custom event is received.
13
+ * The callback is then invoked to handle the custom event.
14
+ ******/
15
+
16
+ const isValidCustomEvent = activity => {
17
+ var _activity$channelData, _activity$channelData2, _activity$channelData3, _activity$channelData4, _activity$channelData5, _activity$channelData6, _activity$channelData7, _activity$from, _activity$channelData8, _activity$channelData9, _activity$channelData10, _activity$channelData11;
18
+ return !!(activity !== null && activity !== void 0 && (_activity$channelData = activity.channelData) !== null && _activity$channelData !== void 0 && (_activity$channelData2 = _activity$channelData.metadata) !== null && _activity$channelData2 !== void 0 && _activity$channelData2.customEvent && typeof (activity === null || activity === void 0 ? void 0 : (_activity$channelData3 = activity.channelData) === null || _activity$channelData3 === void 0 ? void 0 : (_activity$channelData4 = _activity$channelData3.metadata) === null || _activity$channelData4 === void 0 ? void 0 : _activity$channelData4.customEvent) === _Constants.Constants.String && (activity === null || activity === void 0 ? void 0 : (_activity$channelData5 = activity.channelData) === null || _activity$channelData5 === void 0 ? void 0 : (_activity$channelData6 = _activity$channelData5.metadata) === null || _activity$channelData6 === void 0 ? void 0 : (_activity$channelData7 = _activity$channelData6.customEvent) === null || _activity$channelData7 === void 0 ? void 0 : _activity$channelData7.toLowerCase()) === _Constants.Constants.true && (activity === null || activity === void 0 ? void 0 : (_activity$from = activity.from) === null || _activity$from === void 0 ? void 0 : _activity$from.role) !== _Constants.Constants.userMessageTag && typeof (activity === null || activity === void 0 ? void 0 : (_activity$channelData8 = activity.channelData) === null || _activity$channelData8 === void 0 ? void 0 : (_activity$channelData9 = _activity$channelData8.metadata) === null || _activity$channelData9 === void 0 ? void 0 : _activity$channelData9.customEventName) === _Constants.Constants.String && activity !== null && activity !== void 0 && (_activity$channelData10 = activity.channelData) !== null && _activity$channelData10 !== void 0 && (_activity$channelData11 = _activity$channelData10.metadata) !== null && _activity$channelData11 !== void 0 && _activity$channelData11.customEventValue);
19
+ };
20
+ exports.isValidCustomEvent = isValidCustomEvent;
21
+ const createCustomEventMiddleware = broadcastservice => () => next => action => {
22
+ var _action$payload;
23
+ if ((action === null || action === void 0 ? void 0 : action.type) == _WebChatActionType.WebChatActionType.DIRECT_LINE_INCOMING_ACTIVITY && (_action$payload = action.payload) !== null && _action$payload !== void 0 && _action$payload.activity) {
24
+ const activity = action.payload.activity;
25
+ if (isValidCustomEvent(activity)) {
26
+ const customEvent = {
27
+ eventName: _Constants.Constants.onCustomEvent,
28
+ payload: {
29
+ messageId: activity.messageid ?? activity.id,
30
+ customEventName: activity.channelData.metadata.customEventName,
31
+ customEventValue: activity.channelData.metadata.customEventValue
32
+ }
33
+ };
34
+ broadcastservice.postMessage(customEvent);
35
+ return;
36
+ }
37
+ }
38
+ return next(action);
39
+ };
40
+ var _default = createCustomEventMiddleware;
41
+ exports.default = _default;
@@ -0,0 +1 @@
1
+ "use strict";
@@ -124,6 +124,11 @@ _defineProperty(Constants, "InitContextParamsResponse", "initContextParamsRespon
124
124
  _defineProperty(Constants, "OCOriginalMessageId", "OriginalMessageId");
125
125
  _defineProperty(Constants, "WebchatSequenceIdAttribute", "webchat:sequence-id");
126
126
  _defineProperty(Constants, "MessageSequenceIdOverride", "MessageSequenceIdOverride");
127
+ _defineProperty(Constants, "sendCustomEvent", "sendCustomEvent");
128
+ _defineProperty(Constants, "onCustomEvent", "onCustomEvent");
129
+ _defineProperty(Constants, "customEventName", "customEventName");
130
+ _defineProperty(Constants, "customEventValue", "customEventValue");
131
+ _defineProperty(Constants, "Hidden", "Hidden");
127
132
  _defineProperty(Constants, "EndConversationDueToOverflow", "endconversationduetooverflow");
128
133
  export const Regex = (_class = /*#__PURE__*/_createClass(function Regex() {
129
134
  _classCallCheck(this, Regex);
@@ -223,6 +223,7 @@ export let TelemetryEvent;
223
223
  TelemetryEvent["SystemMessageReceived"] = "SystemMessageReceived";
224
224
  TelemetryEvent["RehydrateMessageReceived"] = "RehydrateMessageReceived";
225
225
  TelemetryEvent["CustomContextReceived"] = "CustomContextReceived";
226
+ TelemetryEvent["CustomEventAction"] = "CustomEventAction";
226
227
  TelemetryEvent["NetworkDisconnected"] = "NetworkDisconnected";
227
228
  TelemetryEvent["NetworkReconnected"] = "NetworkReconnected";
228
229
  TelemetryEvent["LinkModePostChatWorkflowStarted"] = "LinkModePostChatWorkflowStarted";
@@ -454,6 +454,23 @@ export function getDeviceType() {
454
454
  return "standard";
455
455
  }
456
456
  }
457
+
458
+ //Bots expect a payload containing:
459
+ //1. customEventName: this should be string describe the event name
460
+ //2. customEventValue: given the value is from customer with unknown type, it is required to stringify the payload later
461
+ export const isValidCustomEvent = payload => {
462
+ if (Constants.customEventName in payload && payload.customEventName && typeof payload.customEventName === Constants.String && Constants.customEventValue in payload && payload.customEventValue) return true;
463
+ return false;
464
+ };
465
+ export const getCustomEventValue = customEventPayload => {
466
+ let returnVal = "";
467
+ try {
468
+ returnVal = typeof customEventPayload.customEventValue === Constants.String ? customEventPayload.customEventValue : JSON.stringify(customEventPayload.customEventValue);
469
+ } catch (error) {
470
+ console.error(error);
471
+ }
472
+ return returnVal;
473
+ };
457
474
  export function isEndConversationDueToOverflowActivity(activity) {
458
475
  var _activity$channelData, _activity$channelData2;
459
476
  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);
@@ -65,7 +65,6 @@ export const ChatButtonStateful = props => {
65
65
  };
66
66
  const outOfOfficeStyleProps = Object.assign({}, defaultOutOfOfficeChatButtonStyleProps, outOfOfficeButtonProps === null || outOfOfficeButtonProps === void 0 ? void 0 : outOfOfficeButtonProps.styleProps);
67
67
  const controlProps = {
68
- ...(buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.controlProps),
69
68
  id: "oc-lcw-chat-button",
70
69
  dir: state.domainStates.globalDir,
71
70
  titleText: "Let's Chat!",
@@ -74,7 +73,8 @@ export const ChatButtonStateful = props => {
74
73
  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",
75
74
  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,
76
75
  // Regular chat button onClick - this will always take precedence
77
- onClick: () => ref.current()
76
+ onClick: () => ref.current(),
77
+ ...(buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.controlProps)
78
78
  };
79
79
  const outOfOfficeControlProps = {
80
80
  // Only take specific properties from outOfOfficeButtonProps, never onClick
@@ -83,7 +83,6 @@ export const ChatButtonStateful = props => {
83
83
  titleText: (outOfOfficeButtonProps === null || outOfOfficeButtonProps === void 0 ? void 0 : (_outOfOfficeButtonPro = outOfOfficeButtonProps.controlProps) === null || _outOfOfficeButtonPro === void 0 ? void 0 : _outOfOfficeButtonPro.titleText) || "We're Offline",
84
84
  subtitleText: (outOfOfficeButtonProps === null || outOfOfficeButtonProps === void 0 ? void 0 : (_outOfOfficeButtonPro2 = outOfOfficeButtonProps.controlProps) === null || _outOfOfficeButtonPro2 === void 0 ? void 0 : _outOfOfficeButtonPro2.subtitleText) || "No agents available",
85
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
86
  // Out-of-office specific onClick - this will ALWAYS take precedence
88
87
  onClick: () => {
89
88
  if (state.appStates.isMinimized) {
@@ -96,7 +95,8 @@ export const ChatButtonStateful = props => {
96
95
  type: LiveChatWidgetActionType.SET_CONVERSATION_STATE,
97
96
  payload: ConversationState.OutOfOffice
98
97
  });
99
- }
98
+ },
99
+ ...(outOfOfficeButtonProps === null || outOfOfficeButtonProps === void 0 ? void 0 : outOfOfficeButtonProps.controlProps)
100
100
  };
101
101
  useEffect(() => {
102
102
  TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
@@ -0,0 +1,45 @@
1
+ import { Constants } from "../../../common/Constants";
2
+ import { TelemetryHelper } from "../../../common/telemetry/TelemetryHelper";
3
+ import { LogLevel, TelemetryEvent } from "../../../common/telemetry/TelemetryConstants";
4
+ import { getCustomEventValue, isValidCustomEvent } from "../../../common/utils";
5
+ export const customEventCallback = facadeChatSDK => event => {
6
+ if (!(Constants.payload in event)) return;
7
+ if (isValidCustomEvent(event.payload)) {
8
+ const customEventPayload = event.payload;
9
+ try {
10
+ const customEventValueStr = getCustomEventValue(customEventPayload);
11
+ const customEventName = customEventPayload.customEventName;
12
+ const messageMeta = {
13
+ customEvent: Constants.true,
14
+ customEventName: customEventName,
15
+ customEventValue: customEventValueStr
16
+ };
17
+ const messagePayload = {
18
+ content: "",
19
+ tags: [Constants.Hidden],
20
+ metadata: messageMeta,
21
+ timestamp: new Date()
22
+ };
23
+ facadeChatSDK.sendMessage(messagePayload);
24
+ TelemetryHelper.logActionEventToAllTelemetry(LogLevel.DEBUG, {
25
+ Event: TelemetryEvent.CustomEventAction,
26
+ Description: "Sent customEvent.",
27
+ CustomProperties: {
28
+ customEventName,
29
+ lengthCustomEventValue: customEventValueStr.length
30
+ }
31
+ });
32
+ } catch (error) {
33
+ TelemetryHelper.logActionEventToAllTelemetry(LogLevel.ERROR, {
34
+ Event: TelemetryEvent.CustomEventAction,
35
+ Description: "Failed to process CustomEvent.",
36
+ ExceptionDetails: {
37
+ error
38
+ }
39
+ });
40
+ }
41
+ }
42
+ };
43
+ export const subscribeToSendCustomEvent = (broadcastService, facadeChatSDK, customEventCallback) => {
44
+ broadcastService.getMessageByEventName(Constants.sendCustomEvent).subscribe(customEventCallback(facadeChatSDK));
45
+ };
@@ -32,9 +32,11 @@ 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 createCustomEventMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/customEventMiddleware";
35
36
  import { ConversationState } from "../../../contexts/common/ConversationState";
36
37
  import { executeReducer } from "../../../contexts/createReducer";
37
38
  import { createQueueOverflowMiddleware } from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/queueOverflowHandlerMiddleware";
39
+ import { BroadcastService } from "@microsoft/omnichannel-chat-components";
38
40
 
39
41
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
40
42
  export const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endChat) => {
@@ -113,7 +115,7 @@ export const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endCh
113
115
  };
114
116
  webChatStore = createStore({},
115
117
  //initial state
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,
118
+ 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), createCustomEventMiddleware(BroadcastService), 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,
117
119
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
118
120
  ...(((_props$webChatContain7 = props.webChatContainerProps) === null || _props$webChatContain7 === void 0 ? void 0 : _props$webChatContain7.storeMiddlewares) ?? []));
119
121
  WebChatStoreLoader.store = webChatStore;
@@ -53,6 +53,7 @@ import { startProactiveChat } from "../common/startProactiveChat";
53
53
  import useChatAdapterStore from "../../../hooks/useChatAdapterStore";
54
54
  import useChatContextStore from "../../../hooks/useChatContextStore";
55
55
  import useFacadeSDKStore from "../../../hooks/useFacadeChatSDKStore";
56
+ import { customEventCallback, subscribeToSendCustomEvent } from "../common/customEventHandler";
56
57
  let uiTimer;
57
58
  export const LiveChatWidgetStateful = props => {
58
59
  var _props$webChatContain, _props$webChatContain2, _props$webChatContain3, _props$webChatContain4, _props$webChatContain5, _props$webChatContain6, _props$webChatContain7, _props$webChatContain8, _props$webChatContain9, _props$styleProps, _props$webChatContain10, _props$webChatContain11, _props$controlProps, _props$controlProps3, _state$appStates7, _props$webChatContain15, _state$appStates14, _props$webChatContain17, _props$webChatContain18, _props$controlProps12, _props$draggableChatW, _props$draggableChatW2, _props$draggableChatW3, _props$draggableChatW4, _props$draggableChatW5, _livechatProps$webCha, _livechatProps$styleP, _livechatProps$contro, _livechatProps$contro2, _livechatProps$compon, _livechatProps$contro3, _livechatProps$compon2, _livechatProps$contro4, _livechatProps$compon3, _livechatProps$contro5, _livechatProps$compon4, _livechatProps$contro6, _livechatProps$compon5, _livechatProps$contro7, _livechatProps$compon6, _livechatProps$contro8, _livechatProps$compon7, _livechatProps$contro9, _livechatProps$compon8, _livechatProps$contro10, _livechatProps$contro11, _livechatProps$compon9, _livechatProps$contro12, _livechatProps$compon10, _livechatProps$contro13, _livechatProps$compon11, _livechatProps$compon12, _livechatProps$compon13;
@@ -413,7 +414,7 @@ export const LiveChatWidgetStateful = props => {
413
414
  BroadcastService.getMessageByEventName(BroadcastEvent.StartChat).subscribe(msg => {
414
415
  var _msg$payload5, _msg$payload6, _msg$payload7, _msg$payload9, _inMemoryState$appSta2, _inMemoryState$appSta3, _inMemoryState$appSta4;
415
416
  // If chat is out of operating hours chat widget sets the conversation state to OutOfOffice.
416
- if (state.appStates.outsideOperatingHours === true) {
417
+ if (state.appStates.outsideOperatingHours && state.appStates.conversationState !== ConversationState.Active) {
417
418
  dispatch({
418
419
  type: LiveChatWidgetActionType.SET_MINIMIZED,
419
420
  payload: false
@@ -580,6 +581,9 @@ export const LiveChatWidgetStateful = props => {
580
581
  }
581
582
  });
582
583
 
584
+ // subscribe custom event
585
+ subscribeToSendCustomEvent(BroadcastService, facadeChatSDK, customEventCallback);
586
+
583
587
  // Check for TPC and log in telemetry if blocked
584
588
  isCookieAllowed();
585
589
  return () => {
@@ -0,0 +1,33 @@
1
+ /******
2
+ * CustomEventMiddleware
3
+ *
4
+ * This middleware is invoked when a custom event is received.
5
+ * The callback is then invoked to handle the custom event.
6
+ ******/
7
+
8
+ import { Constants } from "../../../../../common/Constants";
9
+ import { WebChatActionType } from "../../enums/WebChatActionType";
10
+ export const isValidCustomEvent = activity => {
11
+ var _activity$channelData, _activity$channelData2, _activity$channelData3, _activity$channelData4, _activity$channelData5, _activity$channelData6, _activity$channelData7, _activity$from, _activity$channelData8, _activity$channelData9, _activity$channelData10, _activity$channelData11;
12
+ return !!(activity !== null && activity !== void 0 && (_activity$channelData = activity.channelData) !== null && _activity$channelData !== void 0 && (_activity$channelData2 = _activity$channelData.metadata) !== null && _activity$channelData2 !== void 0 && _activity$channelData2.customEvent && typeof (activity === null || activity === void 0 ? void 0 : (_activity$channelData3 = activity.channelData) === null || _activity$channelData3 === void 0 ? void 0 : (_activity$channelData4 = _activity$channelData3.metadata) === null || _activity$channelData4 === void 0 ? void 0 : _activity$channelData4.customEvent) === Constants.String && (activity === null || activity === void 0 ? void 0 : (_activity$channelData5 = activity.channelData) === null || _activity$channelData5 === void 0 ? void 0 : (_activity$channelData6 = _activity$channelData5.metadata) === null || _activity$channelData6 === void 0 ? void 0 : (_activity$channelData7 = _activity$channelData6.customEvent) === null || _activity$channelData7 === void 0 ? void 0 : _activity$channelData7.toLowerCase()) === Constants.true && (activity === null || activity === void 0 ? void 0 : (_activity$from = activity.from) === null || _activity$from === void 0 ? void 0 : _activity$from.role) !== Constants.userMessageTag && typeof (activity === null || activity === void 0 ? void 0 : (_activity$channelData8 = activity.channelData) === null || _activity$channelData8 === void 0 ? void 0 : (_activity$channelData9 = _activity$channelData8.metadata) === null || _activity$channelData9 === void 0 ? void 0 : _activity$channelData9.customEventName) === Constants.String && activity !== null && activity !== void 0 && (_activity$channelData10 = activity.channelData) !== null && _activity$channelData10 !== void 0 && (_activity$channelData11 = _activity$channelData10.metadata) !== null && _activity$channelData11 !== void 0 && _activity$channelData11.customEventValue);
13
+ };
14
+ const createCustomEventMiddleware = broadcastservice => () => next => action => {
15
+ var _action$payload;
16
+ if ((action === null || action === void 0 ? void 0 : action.type) == WebChatActionType.DIRECT_LINE_INCOMING_ACTIVITY && (_action$payload = action.payload) !== null && _action$payload !== void 0 && _action$payload.activity) {
17
+ const activity = action.payload.activity;
18
+ if (isValidCustomEvent(activity)) {
19
+ const customEvent = {
20
+ eventName: Constants.onCustomEvent,
21
+ payload: {
22
+ messageId: activity.messageid ?? activity.id,
23
+ customEventName: activity.channelData.metadata.customEventName,
24
+ customEventValue: activity.channelData.metadata.customEventValue
25
+ }
26
+ };
27
+ broadcastservice.postMessage(customEvent);
28
+ return;
29
+ }
30
+ }
31
+ return next(action);
32
+ };
33
+ export default createCustomEventMiddleware;
@@ -0,0 +1 @@
1
+ export {};
@@ -96,6 +96,11 @@ export declare class Constants {
96
96
  static readonly OCOriginalMessageId = "OriginalMessageId";
97
97
  static readonly WebchatSequenceIdAttribute = "webchat:sequence-id";
98
98
  static readonly MessageSequenceIdOverride = "MessageSequenceIdOverride";
99
+ static readonly sendCustomEvent = "sendCustomEvent";
100
+ static readonly onCustomEvent = "onCustomEvent";
101
+ static readonly customEventName = "customEventName";
102
+ static readonly customEventValue = "customEventValue";
103
+ static readonly Hidden = "Hidden";
99
104
  static readonly EndConversationDueToOverflow = "endconversationduetooverflow";
100
105
  }
101
106
  export declare const Regex: {
@@ -211,6 +211,7 @@ export declare enum TelemetryEvent {
211
211
  SystemMessageReceived = "SystemMessageReceived",
212
212
  RehydrateMessageReceived = "RehydrateMessageReceived",
213
213
  CustomContextReceived = "CustomContextReceived",
214
+ CustomEventAction = "CustomEventAction",
214
215
  NetworkDisconnected = "NetworkDisconnected",
215
216
  NetworkReconnected = "NetworkReconnected",
216
217
  LinkModePostChatWorkflowStarted = "LinkModePostChatWorkflowStarted",
@@ -1,5 +1,6 @@
1
1
  import { FacadeChatSDK } from "./facades/FacadeChatSDK";
2
2
  import { ITimer } from "./interfaces/ITimer";
3
+ import * as CustomEventType from "../contexts/common/CustomEventType";
3
4
  export declare const setTabIndices: (elements: HTMLElement[] | null, tabIndexMap: Map<string, number>, shouldBeFocusable: boolean) => void;
4
5
  export declare const findParentFocusableElementsWithoutChildContainer: (elementId: string) => HTMLElement[] | null;
5
6
  export declare const findAllFocusableElement: (parent: string | HTMLElement) => any[] | null;
@@ -47,6 +48,8 @@ export declare const formatTemplateString: (templateMessage: string, values: any
47
48
  export declare const parseLowerCaseString: (property: string | boolean | undefined) => string;
48
49
  export declare const setOcUserAgent: (chatSDK: any) => void;
49
50
  export declare function getDeviceType(): string;
51
+ export declare const isValidCustomEvent: (payload: object) => boolean;
52
+ export declare const getCustomEventValue: (customEventPayload: CustomEventType.ICustomEvent) => string;
50
53
  export declare function isEndConversationDueToOverflowActivity(activity: {
51
54
  channelData?: {
52
55
  tags?: string[];
@@ -0,0 +1,4 @@
1
+ import { FacadeChatSDK } from "../../../common/facades/FacadeChatSDK";
2
+ import { BroadcastService } from "@microsoft/omnichannel-chat-components";
3
+ export declare const customEventCallback: (facadeChatSDK: FacadeChatSDK) => (event: object) => void;
4
+ export declare const subscribeToSendCustomEvent: (broadcastService: typeof BroadcastService, facadeChatSDK: FacadeChatSDK, customEventCallback: (fackageSdK: FacadeChatSDK) => (event: object) => void) => void;
@@ -0,0 +1,22 @@
1
+ /******
2
+ * CustomEventMiddleware
3
+ *
4
+ * This middleware is invoked when a custom event is received.
5
+ * The callback is then invoked to handle the custom event.
6
+ ******/
7
+ import { IWebChatAction } from "../../../interfaces/IWebChatAction";
8
+ import { BroadcastService } from "@microsoft/omnichannel-chat-components";
9
+ export declare const isValidCustomEvent: (activity: {
10
+ channelData?: {
11
+ metadata?: {
12
+ customEvent?: string;
13
+ customEventName?: string;
14
+ customEventValue?: unknown;
15
+ };
16
+ };
17
+ from?: {
18
+ role: string;
19
+ };
20
+ }) => boolean;
21
+ declare const createCustomEventMiddleware: (broadcastservice: typeof BroadcastService) => () => (next: (action: IWebChatAction) => void) => (action: IWebChatAction) => void;
22
+ export default createCustomEventMiddleware;
@@ -0,0 +1,6 @@
1
+ export interface ICustomEvent {
2
+ messageId?: string;
3
+ customEvent?: string;
4
+ customEventName: string;
5
+ customEventValue: unknown;
6
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microsoft/omnichannel-chat-widget",
3
- "version": "1.8.2-main.d82a79b",
3
+ "version": "1.8.2-main.f638bed",
4
4
  "description": "Microsoft Omnichannel Chat Widget",
5
5
  "main": "lib/cjs/index.js",
6
6
  "types": "lib/types/index.d.ts",