@microsoft/omnichannel-chat-widget 0.1.0-main.b59a07c → 0.1.0-main.c2417f9

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 (49) hide show
  1. package/README.md +32 -0
  2. package/lib/cjs/common/Constants.js +12 -0
  3. package/lib/cjs/common/telemetry/TelemetryConstants.js +9 -4
  4. package/lib/cjs/components/chatbuttonstateful/ChatButtonStateful.js +5 -1
  5. package/lib/cjs/components/footerstateful/downloadtranscriptstateful/DownloadTranscriptStateful.js +10 -1
  6. package/lib/cjs/components/livechatwidget/common/defaultProps/dummyDefaultProps.js +4 -0
  7. package/lib/cjs/components/livechatwidget/common/endChat.js +3 -3
  8. package/lib/cjs/components/livechatwidget/common/initWebChatComposer.js +8 -3
  9. package/lib/cjs/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +99 -44
  10. package/lib/cjs/components/webchatcontainerstateful/WebChatContainerStateful.js +80 -0
  11. package/lib/cjs/components/webchatcontainerstateful/interfaces/IBotMagicCodeConfig.js +1 -0
  12. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/BotMagicCodeStore.js +14 -0
  13. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activityMiddleware.js +16 -2
  14. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/cardActionMiddleware.js +52 -0
  15. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/cardActionMiddleware.spec.js +98 -0
  16. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/messageTimestampMiddleware.js +117 -0
  17. package/lib/cjs/contexts/common/LiveChatWidgetActionType.js +2 -0
  18. package/lib/cjs/contexts/common/LiveChatWidgetContextInitialState.js +2 -1
  19. package/lib/cjs/contexts/createReducer.js +8 -0
  20. package/lib/esm/common/Constants.js +12 -0
  21. package/lib/esm/common/telemetry/TelemetryConstants.js +9 -4
  22. package/lib/esm/components/chatbuttonstateful/ChatButtonStateful.js +7 -4
  23. package/lib/esm/components/footerstateful/downloadtranscriptstateful/DownloadTranscriptStateful.js +8 -2
  24. package/lib/esm/components/livechatwidget/common/defaultProps/dummyDefaultProps.js +4 -0
  25. package/lib/esm/components/livechatwidget/common/endChat.js +3 -2
  26. package/lib/esm/components/livechatwidget/common/initWebChatComposer.js +7 -4
  27. package/lib/esm/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +92 -41
  28. package/lib/esm/components/webchatcontainerstateful/WebChatContainerStateful.js +72 -0
  29. package/lib/esm/components/webchatcontainerstateful/interfaces/IBotMagicCodeConfig.js +1 -0
  30. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/BotMagicCodeStore.js +5 -0
  31. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activityMiddleware.js +16 -2
  32. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/cardActionMiddleware.js +41 -0
  33. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/cardActionMiddleware.spec.js +94 -0
  34. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/messageTimestampMiddleware.js +107 -0
  35. package/lib/esm/contexts/common/LiveChatWidgetActionType.js +2 -0
  36. package/lib/esm/contexts/common/LiveChatWidgetContextInitialState.js +2 -1
  37. package/lib/esm/contexts/createReducer.js +8 -0
  38. package/lib/types/common/Constants.d.ts +6 -0
  39. package/lib/types/common/interfaces/IContextDataStore.d.ts +1 -1
  40. package/lib/types/common/telemetry/TelemetryConstants.d.ts +10 -5
  41. package/lib/types/components/webchatcontainerstateful/interfaces/IBotMagicCodeConfig.d.ts +4 -0
  42. package/lib/types/components/webchatcontainerstateful/interfaces/IWebChatContainerStatefulProps.d.ts +2 -0
  43. package/lib/types/components/webchatcontainerstateful/webchatcontroller/BotMagicCodeStore.d.ts +3 -0
  44. package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/cardActionMiddleware.d.ts +2 -0
  45. package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/cardActionMiddleware.spec.d.ts +1 -0
  46. package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/messageTimestampMiddleware.d.ts +5 -0
  47. package/lib/types/contexts/common/ILiveChatWidgetContext.d.ts +1 -0
  48. package/lib/types/contexts/common/LiveChatWidgetActionType.d.ts +3 -1
  49. package/package.json +2 -2
@@ -68,6 +68,7 @@ export const LiveChatWidgetStateful = props => {
68
68
  TelemetryTimers.LcwLoadToChatButtonTimer = createTimer();
69
69
  const widgetElementId = ((_props$controlProps = props.controlProps) === null || _props$controlProps === void 0 ? void 0 : _props$controlProps.id) || "oc-lcw";
70
70
  const currentMessageCountRef = useRef(0);
71
+ let widgetStateEventName = "";
71
72
  useEffect(() => {
72
73
  var _props$controlProps2, _props$controlProps3, _props$reconnectChatP, _props$controlProps4, _props$chatConfig, _props$chatConfig$Cha, _state$domainStates;
73
74
 
@@ -114,7 +115,8 @@ export const LiveChatWidgetStateful = props => {
114
115
  };
115
116
  initStartChat(chatSDK, dispatch, setAdapter, optionalParams);
116
117
  }
117
- }, []);
118
+ }, []); // useEffect for when skip chat button rendering
119
+
118
120
  useEffect(() => {
119
121
  if (state.appStates.skipChatButtonRendering) {
120
122
  var _props$reconnectChatP3;
@@ -148,9 +150,10 @@ export const LiveChatWidgetStateful = props => {
148
150
  });
149
151
  }
150
152
  }
151
- }, [state.appStates.skipChatButtonRendering]);
153
+ }, [state.appStates.skipChatButtonRendering]); // useEffect for when skip chat button rendering
154
+
152
155
  useEffect(() => {
153
- var _chatSDK$omnichannelC, _chatSDK$omnichannelC2;
156
+ var _chatSDK$omnichannelC3, _chatSDK$omnichannelC4;
154
157
 
155
158
  // Add the custom context on receiving the SetCustomContext event
156
159
  BroadcastService.getMessageByEventName(BroadcastEvent.SetCustomContext).subscribe(msg => {
@@ -179,49 +182,77 @@ export const LiveChatWidgetStateful = props => {
179
182
  Description: "Start proactive chat method called, when chat was already triggered."
180
183
  });
181
184
  }
182
- }); // start chat from SDK Event
185
+ }); // Start chat from SDK Event
183
186
 
184
187
  BroadcastService.getMessageByEventName(BroadcastEvent.StartChat).subscribe(() => {
188
+ var _chatSDK$omnichannelC, _chatSDK$omnichannelC2, _DataStoreManager$cli;
189
+
185
190
  TelemetryHelper.logActionEvent(LogLevel.INFO, {
186
191
  Event: TelemetryEvent.StartChatEventRecevied,
187
192
  Description: "Start chat event received."
188
- });
193
+ }); // Getting updated state from cache
194
+
195
+ const widgetStateEventName = getWidgetCacheId((chatSDK === null || chatSDK === void 0 ? void 0 : (_chatSDK$omnichannelC = chatSDK.omnichannelConfig) === null || _chatSDK$omnichannelC === void 0 ? void 0 : _chatSDK$omnichannelC.orgId) ?? "", (chatSDK === null || chatSDK === void 0 ? void 0 : (_chatSDK$omnichannelC2 = chatSDK.omnichannelConfig) === null || _chatSDK$omnichannelC2 === void 0 ? void 0 : _chatSDK$omnichannelC2.widgetId) ?? "");
196
+ const widgetStateFromCache = (_DataStoreManager$cli = DataStoreManager.clientDataStore) === null || _DataStoreManager$cli === void 0 ? void 0 : _DataStoreManager$cli.getData(widgetStateEventName, "localStorage");
197
+ const persistedState = widgetStateFromCache ? JSON.parse(widgetStateFromCache) : undefined;
198
+
199
+ if (persistedState.appStates.conversationState === ConversationState.Closed || persistedState.appStates.conversationState === ConversationState.InActive || persistedState.appStates.conversationState === ConversationState.Postchat) {
200
+ BroadcastService.postMessage({
201
+ eventName: BroadcastEvent.ChatInitiated
202
+ });
203
+ prepareStartChat(props, chatSDK, state, dispatch, setAdapter);
204
+ } else {
205
+ var _persistedState$domai, _persistedState$domai2, _persistedState$domai3, _persistedState$domai4;
189
206
 
190
- if (state.appStates.isMinimized) {
191
207
  dispatch({
192
208
  type: LiveChatWidgetActionType.SET_MINIMIZED,
193
209
  payload: false
194
210
  });
195
- } else {
196
- prepareStartChat(props, chatSDK, state, dispatch, setAdapter);
211
+ BroadcastService.postMessage({
212
+ eventName: BroadcastEvent.MaximizeChat,
213
+ payload: {
214
+ height: persistedState === null || persistedState === void 0 ? void 0 : (_persistedState$domai = persistedState.domainStates) === null || _persistedState$domai === void 0 ? void 0 : (_persistedState$domai2 = _persistedState$domai.widgetSize) === null || _persistedState$domai2 === void 0 ? void 0 : _persistedState$domai2.height,
215
+ width: persistedState === null || persistedState === void 0 ? void 0 : (_persistedState$domai3 = persistedState.domainStates) === null || _persistedState$domai3 === void 0 ? void 0 : (_persistedState$domai4 = _persistedState$domai3.widgetSize) === null || _persistedState$domai4 === void 0 ? void 0 : _persistedState$domai4.width
216
+ }
217
+ });
197
218
  }
198
- }); // end chat from SDK Event
219
+ }); // End chat
220
+
221
+ BroadcastService.getMessageByEventName(BroadcastEvent.InitiateEndChat).subscribe(async msg => {
222
+ var _msg$payload4, _msg$payload5;
199
223
 
200
- BroadcastService.getMessageByEventName(BroadcastEvent.EndChat).subscribe(async () => {
224
+ const isChatUnloading = ((_msg$payload4 = msg.payload) === null || _msg$payload4 === void 0 ? void 0 : _msg$payload4.chatUnloading) ?? false;
225
+ const isSdkCall = ((_msg$payload5 = msg.payload) === null || _msg$payload5 === void 0 ? void 0 : _msg$payload5.isSdkCall) ?? false;
226
+ const eventDescription = isChatUnloading ? "End chat event received from unload." : "End chat event received.";
201
227
  TelemetryHelper.logActionEvent(LogLevel.INFO, {
202
228
  Event: TelemetryEvent.EndChatEventReceived,
203
- Description: "End chat event received."
229
+ Description: eventDescription
204
230
  });
205
231
 
206
- if (canEndChat.current) {
232
+ if (isChatUnloading) {
233
+ var _DataStoreManager$cli2;
234
+
235
+ //Browser close scenario/no room for PCS/so just end chat and notify agent immidiately
236
+ endChat(props, chatSDK, setAdapter, setWebChatStyles, dispatch, adapter, false, false, false); // Clean local storage
237
+
238
+ (_DataStoreManager$cli2 = DataStoreManager.clientDataStore) === null || _DataStoreManager$cli2 === void 0 ? void 0 : _DataStoreManager$cli2.removeData(widgetStateEventName, "localStorage");
239
+ } else if (canEndChat.current) {
207
240
  prepareEndChat(props, chatSDK, setAdapter, setWebChatStyles, dispatch, adapter, state);
208
241
  } else {
209
242
  const skipEndChatSDK = true;
210
243
  const skipCloseChat = false;
211
244
  endChat(props, chatSDK, setAdapter, setWebChatStyles, dispatch, adapter, skipEndChatSDK, skipCloseChat);
212
- }
213
- }); // Listen to end chat event from other tabs
245
+ } // Raise chatClose for SDK events
214
246
 
215
- const endChatEventName = getWidgetEndChatEventName(chatSDK === null || chatSDK === void 0 ? void 0 : (_chatSDK$omnichannelC = chatSDK.omnichannelConfig) === null || _chatSDK$omnichannelC === void 0 ? void 0 : _chatSDK$omnichannelC.orgId, chatSDK === null || chatSDK === void 0 ? void 0 : (_chatSDK$omnichannelC2 = chatSDK.omnichannelConfig) === null || _chatSDK$omnichannelC2 === void 0 ? void 0 : _chatSDK$omnichannelC2.widgetId);
216
- BroadcastService.getMessageByEventName(endChatEventName).subscribe(async () => {
217
- endChat(props, chatSDK, setAdapter, setWebChatStyles, dispatch, adapter, false, false, false);
218
- }); // Close popout window
219
247
 
220
- BroadcastService.getMessageByEventName(BroadcastEvent.ClosePopoutWindow).subscribe(() => {
221
- TelemetryHelper.logActionEvent(LogLevel.INFO, {
222
- Event: TelemetryEvent.ClosePopoutWindowEventRecevied,
223
- Description: "Close popout window event received."
224
- });
248
+ if (isSdkCall) {
249
+ BroadcastService.postMessage({
250
+ eventName: BroadcastEvent.CloseChat
251
+ });
252
+ }
253
+ }); // reset proactive chat params
254
+
255
+ BroadcastService.getMessageByEventName(BroadcastEvent.ResetProactiveChatParams).subscribe(async () => {
225
256
  dispatch({
226
257
  type: LiveChatWidgetActionType.SET_PROACTIVE_CHAT_PARAMS,
227
258
  payload: {
@@ -230,17 +261,34 @@ export const LiveChatWidgetStateful = props => {
230
261
  proactiveChatInNewWindow: false
231
262
  }
232
263
  });
233
- });
264
+ }); // Listen to end chat event from other tabs
265
+
266
+ const endChatEventName = getWidgetEndChatEventName(chatSDK === null || chatSDK === void 0 ? void 0 : (_chatSDK$omnichannelC3 = chatSDK.omnichannelConfig) === null || _chatSDK$omnichannelC3 === void 0 ? void 0 : _chatSDK$omnichannelC3.orgId, chatSDK === null || chatSDK === void 0 ? void 0 : (_chatSDK$omnichannelC4 = chatSDK.omnichannelConfig) === null || _chatSDK$omnichannelC4 === void 0 ? void 0 : _chatSDK$omnichannelC4.widgetId);
267
+ BroadcastService.getMessageByEventName(endChatEventName).subscribe(async () => {
268
+ endChat(props, chatSDK, setAdapter, setWebChatStyles, dispatch, adapter, false, false, false);
269
+ }); // Close popout window
270
+
234
271
  window.addEventListener("beforeunload", () => {
272
+ TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
273
+ Event: TelemetryEvent.WindowClosed,
274
+ Description: "Closed window."
275
+ });
235
276
  disposeTelemetryLoggers();
236
277
  });
237
278
 
238
279
  if (state.appStates.conversationEndedByAgent) {
239
280
  endChat(props, chatSDK, setAdapter, setWebChatStyles, dispatch, adapter);
240
- }
281
+ } //Listen to WidgetSize
282
+
283
+
284
+ BroadcastService.getMessageByEventName("WidgetSize").subscribe(msg => {
285
+ dispatch({
286
+ type: LiveChatWidgetActionType.SET_WIDGET_SIZE,
287
+ payload: msg === null || msg === void 0 ? void 0 : msg.payload
288
+ });
289
+ });
241
290
  }, []);
242
291
  useEffect(() => {
243
- canStartProactiveChat.current = state.appStates.conversationState === ConversationState.Closed;
244
292
  canEndChat.current = state.appStates.conversationState === ConversationState.Active;
245
293
 
246
294
  if (state.appStates.conversationState === ConversationState.Active) {
@@ -261,7 +309,10 @@ export const LiveChatWidgetStateful = props => {
261
309
  });
262
310
  });
263
311
  }
264
- }, [state.appStates.conversationState]); // Reset the UnreadMessageCount when minimized is toggled and broadcast it.
312
+ }, [state.appStates.conversationState]);
313
+ useEffect(() => {
314
+ canStartProactiveChat.current = state.appStates.conversationState === ConversationState.Closed && !state.appStates.proactiveChatStates.proactiveChatInNewWindow;
315
+ }, [state.appStates.conversationState, state.appStates.proactiveChatStates.proactiveChatInNewWindow]); // Reset the UnreadMessageCount when minimized is toggled and broadcast it.
265
316
 
266
317
  useEffect(() => {
267
318
  currentMessageCountRef.current = -1;
@@ -293,7 +344,19 @@ export const LiveChatWidgetStateful = props => {
293
344
  setWebChatStyles({ ...webChatStyles,
294
345
  ...((_props$webChatContain2 = props.webChatContainerProps) === null || _props$webChatContain2 === void 0 ? void 0 : _props$webChatContain2.webChatStyles)
295
346
  });
296
- }, [(_props$webChatContain3 = props.webChatContainerProps) === null || _props$webChatContain3 === void 0 ? void 0 : _props$webChatContain3.webChatStyles]);
347
+ }, [(_props$webChatContain3 = props.webChatContainerProps) === null || _props$webChatContain3 === void 0 ? void 0 : _props$webChatContain3.webChatStyles]); // Publish chat widget state
348
+
349
+ useEffect(() => {
350
+ var _props$chatSDK, _props$chatSDK$omnich, _props$chatSDK2, _props$chatSDK2$omnic;
351
+
352
+ widgetStateEventName = getWidgetCacheId(props === null || props === void 0 ? void 0 : (_props$chatSDK = props.chatSDK) === null || _props$chatSDK === void 0 ? void 0 : (_props$chatSDK$omnich = _props$chatSDK.omnichannelConfig) === null || _props$chatSDK$omnich === void 0 ? void 0 : _props$chatSDK$omnich.orgId, props === null || props === void 0 ? void 0 : (_props$chatSDK2 = props.chatSDK) === null || _props$chatSDK2 === void 0 ? void 0 : (_props$chatSDK2$omnic = _props$chatSDK2.omnichannelConfig) === null || _props$chatSDK2$omnic === void 0 ? void 0 : _props$chatSDK2$omnic.widgetId);
353
+ const chatWidgetStateChangeEvent = {
354
+ eventName: widgetStateEventName,
355
+ payload: { ...state
356
+ }
357
+ };
358
+ BroadcastService.postMessage(chatWidgetStateChangeEvent);
359
+ }, [state]);
297
360
  const webChatProps = initWebChatComposer(props, chatSDK, state, dispatch, setWebChatStyles);
298
361
 
299
362
  const setPostChatContextRelay = () => setPostChatContextAndLoadSurvey(chatSDK, dispatch); // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -309,19 +372,7 @@ export const LiveChatWidgetStateful = props => {
309
372
 
310
373
  const initStartChatRelay = (optionalParams, persistedState) => initStartChat(chatSDK, dispatch, setAdapter, optionalParams, persistedState);
311
374
 
312
- const confirmationPaneProps = initConfirmationPropsComposer(props); // publish chat widget state
313
-
314
- useEffect(() => {
315
- var _props$chatSDK, _props$chatSDK$omnich, _props$chatSDK2, _props$chatSDK2$omnic;
316
-
317
- const widgetStateEventName = getWidgetCacheId(props === null || props === void 0 ? void 0 : (_props$chatSDK = props.chatSDK) === null || _props$chatSDK === void 0 ? void 0 : (_props$chatSDK$omnich = _props$chatSDK.omnichannelConfig) === null || _props$chatSDK$omnich === void 0 ? void 0 : _props$chatSDK$omnich.orgId, props === null || props === void 0 ? void 0 : (_props$chatSDK2 = props.chatSDK) === null || _props$chatSDK2 === void 0 ? void 0 : (_props$chatSDK2$omnic = _props$chatSDK2.omnichannelConfig) === null || _props$chatSDK2$omnic === void 0 ? void 0 : _props$chatSDK2$omnic.widgetId);
318
- const chatWidgetStateChangeEvent = {
319
- eventName: widgetStateEventName,
320
- payload: { ...state
321
- }
322
- };
323
- BroadcastService.postMessage(chatWidgetStateChangeEvent);
324
- }, [state]);
375
+ const confirmationPaneProps = initConfirmationPropsComposer(props);
325
376
  return /*#__PURE__*/React.createElement(Composer, _extends({}, webChatProps, {
326
377
  styleOptions: webChatStyles,
327
378
  directLine: ((_props$webChatContain4 = props.webChatContainerProps) === null || _props$webChatContain4 === void 0 ? void 0 : _props$webChatContain4.directLine) ?? adapter ?? defaultWebChatContainerStatefulProps.directLine
@@ -8,11 +8,45 @@ import { defaultMiddlewareLocalizedTexts } from "./common/defaultProps/defaultMi
8
8
  import { defaultWebChatContainerStatefulProps } from "./common/defaultProps/defaultWebChatContainerStatefulProps";
9
9
  import { setFocusOnSendBox } from "../../common/utils";
10
10
  import { useChatContextStore } from "../..";
11
+ import { WebChatActionType } from "./webchatcontroller/enums/WebChatActionType";
12
+ import { WebChatStoreLoader } from "./webchatcontroller/WebChatStoreLoader";
13
+ import { Constants } from "../../common/Constants";
14
+ import { BotMagicCodeStore } from "./webchatcontroller/BotMagicCodeStore";
15
+ const broadcastChannelMessageEvent = "message";
16
+
17
+ const postActivity = activity => {
18
+ // eslint-disable-line @typescript-eslint/no-explicit-any
19
+ return {
20
+ type: WebChatActionType.DIRECT_LINE_POST_ACTIVITY,
21
+ meta: {
22
+ method: "keyboard"
23
+ },
24
+ payload: {
25
+ activity: {
26
+ channelData: undefined,
27
+ text: "",
28
+ textFormat: "plain",
29
+ type: Constants.message,
30
+ ...activity
31
+ }
32
+ }
33
+ };
34
+ };
35
+
36
+ const createMagicCodeSuccessResponse = signin => {
37
+ return {
38
+ signin,
39
+ result: "Success"
40
+ };
41
+ };
42
+
11
43
  export const WebChatContainerStateful = props => {
12
44
  const {
13
45
  BasicWebChat
14
46
  } = Components;
15
47
  const [state, dispatch] = useChatContextStore();
48
+ const magicCodeBroadcastChannel = new BroadcastChannel(Constants.magicCodeBroadcastChannel);
49
+ const magicCodeResponseBroadcastChannel = new BroadcastChannel(Constants.magicCodeResponseBroadcastChannel);
16
50
  const containerStyles = {
17
51
  root: Object.assign({}, defaultWebChatContainerStatefulProps.containerStyles, props === null || props === void 0 ? void 0 : props.containerStyles, {
18
52
  display: state.appStates.isMinimized ? "none" : ""
@@ -36,6 +70,44 @@ export const WebChatContainerStateful = props => {
36
70
  Event: TelemetryEvent.WebChatLoaded
37
71
  });
38
72
  }, []);
73
+ useEffect(() => {
74
+ const eventListener = event => {
75
+ // eslint-disable-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-empty-function
76
+ const {
77
+ data
78
+ } = event;
79
+
80
+ if (BotMagicCodeStore.botOAuthSignInId === data.signin) {
81
+ const {
82
+ signin,
83
+ code
84
+ } = data;
85
+ const text = `${code}`;
86
+ const action = postActivity({
87
+ text,
88
+ channelData: {
89
+ tags: [Constants.hiddenTag]
90
+ }
91
+ });
92
+ WebChatStoreLoader.store.dispatch(action);
93
+ const response = createMagicCodeSuccessResponse(signin);
94
+ magicCodeResponseBroadcastChannel.postMessage(response);
95
+ TelemetryHelper.logActionEvent(LogLevel.INFO, {
96
+ Event: TelemetryEvent.SuppressBotMagicCodeSucceeded
97
+ });
98
+ BotMagicCodeStore.botOAuthSignInId = "";
99
+ magicCodeBroadcastChannel.close();
100
+ magicCodeResponseBroadcastChannel.close();
101
+ } else {
102
+ TelemetryHelper.logActionEvent(LogLevel.ERROR, {
103
+ Event: TelemetryEvent.SuppressBotMagicCodeFailed,
104
+ Description: "Signin does not match"
105
+ });
106
+ }
107
+ };
108
+
109
+ magicCodeBroadcastChannel.addEventListener(broadcastChannelMessageEvent, eventListener);
110
+ }, []);
39
111
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("style", null, `
40
112
  .ms_lcw_webchat_received_message img.webchat__markdown__external-link-icon {
41
113
  background-image : url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIzIDMgMTggMTgiICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik03LjI1MDEgNC41MDAxN0gxMC43NDk1QzExLjE2MzcgNC41MDAxNyAxMS40OTk1IDQuODM1OTYgMTEuNDk5NSA1LjI1MDE3QzExLjQ5OTUgNS42Mjk4NiAxMS4yMTczIDUuOTQzNjYgMTAuODUxMyA1Ljk5MzMyTDEwLjc0OTUgNi4wMDAxN0g3LjI0OTc0QzYuMDcwNzkgNS45OTk2MSA1LjEwMzQ5IDYuOTA2NTYgNS4wMDc4NiA4LjA2MTEyTDUuMDAwMjggOC4yMjAwM0w1LjAwMzEyIDE2Ljc1MDdDNS4wMDM0MyAxNy45NDE1IDUuOTI4ODUgMTguOTE2MSA3LjA5OTY2IDE4Ljk5NDlMNy4yNTM3MSAxOS4wMDAxTDE1Ljc1MTggMTguOTg4NEMxNi45NDE1IDE4Ljk4NjggMTcuOTE0NSAxOC4wNjIgMTcuOTkzNSAxNi44OTIzTDE3Ljk5ODcgMTYuNzM4NFYxMy4yMzIxQzE3Ljk5ODcgMTIuODE3OSAxOC4zMzQ1IDEyLjQ4MjEgMTguNzQ4NyAxMi40ODIxQzE5LjEyODQgMTIuNDgyMSAxOS40NDIyIDEyLjc2NDMgMTkuNDkxOCAxMy4xMzAzTDE5LjQ5ODcgMTMuMjMyMVYxNi43Mzg0QzE5LjQ5ODcgMTguNzQwNyAxNy45MjkzIDIwLjM3NjkgMTUuOTUyOCAyMC40ODI5TDE1Ljc1MzggMjAuNDg4NEw3LjI1ODI3IDIwLjUwMDFMNy4wNTQ5NSAyMC40OTQ5QzUuMTQyMzkgMjAuMzk1NCAzLjYwODk1IDE4Ljg2MjcgMy41MDgzNyAxNi45NTAyTDMuNTAzMTIgMTYuNzUxMUwzLjUwMDg5IDguMjUyN0wzLjUwNTI5IDguMDUwMkMzLjYwNTM5IDYuMTM3NDkgNS4xMzg2NyA0LjYwNDQ5IDcuMDUwOTYgNC41MDUyN0w3LjI1MDEgNC41MDAxN0gxMC43NDk1SDcuMjUwMVpNMTMuNzQ4MSAzLjAwMTQ2TDIwLjMwMTggMy4wMDE5N0wyMC40MDE0IDMuMDE1NzVMMjAuNTAyMiAzLjA0MzkzTDIwLjU1OSAzLjA2ODAzQzIwLjYxMjIgMy4wOTEyMiAyMC42NjM0IDMuMTIxNjMgMjAuNzExMSAzLjE1ODg1TDIwLjc4MDQgMy4yMjE1NkwyMC44NjQxIDMuMzIwMTRMMjAuOTE4MyAzLjQxMDI1TDIwLjk1NyAzLjUwMDU3TDIwLjk3NjIgMy41NjQ3NkwyMC45ODk4IDMuNjI4NjJMMjAuOTk5MiAzLjcyMjgyTDIwLjk5OTcgMTAuMjU1NEMyMC45OTk3IDEwLjY2OTYgMjAuNjYzOSAxMS4wMDU0IDIwLjI0OTcgMTEuMDA1NEMxOS44NyAxMS4wMDU0IDE5LjU1NjIgMTAuNzIzMiAxOS41MDY1IDEwLjM1NzFMMTkuNDk5NyAxMC4yNTU0TDE5LjQ5ODkgNS41NjE0N0wxMi4yNzk3IDEyLjc4NDdDMTIuMDEzNCAxMy4wNTEgMTEuNTk2OCAxMy4wNzUzIDExLjMwMzEgMTIuODU3NUwxMS4yMTkgMTIuNzg0OUMxMC45NTI3IDEyLjUxODcgMTAuOTI4NCAxMi4xMDIxIDExLjE0NjIgMTEuODA4NEwxMS4yMTg4IDExLjcyNDNMMTguNDM2OSA0LjUwMTQ2SDEzLjc0ODFDMTMuMzY4NCA0LjUwMTQ2IDEzLjA1NDYgNC4yMTkzMSAxMy4wMDUgMy44NTMyNEwxMi45OTgxIDMuNzUxNDZDMTIuOTk4MSAzLjM3MTc3IDEzLjI4MDMgMy4wNTc5NyAxMy42NDY0IDMuMDA4MzFMMTMuNzQ4MSAzLjAwMTQ2WiIgZmlsbD0iI0ZGRkZGRiIgLz48L3N2Zz4) !important;
@@ -0,0 +1,5 @@
1
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
2
+
3
+ export class BotMagicCodeStore {}
4
+
5
+ _defineProperty(BotMagicCodeStore, "botOAuthSignInId", "");
@@ -54,6 +54,16 @@ const handleSystemMessage = (next, args, card, systemMessageStyleProps) => {
54
54
  }; // eslint-disable-next-line @typescript-eslint/no-explicit-any
55
55
 
56
56
 
57
+ const isTagIncluded = (card, tag) => {
58
+ return isDataTagsPresent(card) && card.activity.channelData.tags.includes(tag);
59
+ }; // eslint-disable-next-line @typescript-eslint/no-explicit-any
60
+
61
+
62
+ const isDataTagsPresent = card => {
63
+ return card && card.activity && card.activity.channelData && card.activity.channelData.tags && card.activity.channelData.tags.length > 0;
64
+ }; // eslint-disable-next-line @typescript-eslint/no-explicit-any
65
+
66
+
57
67
  export const createActivityMiddleware = (systemMessageStyleProps, userMessageStyleProps) => () => next => function () {
58
68
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
59
69
  args[_key] = arguments[_key];
@@ -62,7 +72,7 @@ export const createActivityMiddleware = (systemMessageStyleProps, userMessageSty
62
72
  const [card] = args;
63
73
 
64
74
  if (card.activity) {
65
- var _card$activity$from, _card$activity$channe4, _card$activity$channe5;
75
+ var _card$activity$from;
66
76
 
67
77
  if (((_card$activity$from = card.activity.from) === null || _card$activity$from === void 0 ? void 0 : _card$activity$from.role) === DirectLineSenderRole.Channel) {
68
78
  var _card$activity$channe3;
@@ -77,7 +87,11 @@ export const createActivityMiddleware = (systemMessageStyleProps, userMessageSty
77
87
  return () => false;
78
88
  }
79
89
 
80
- if ((_card$activity$channe4 = card.activity.channelData) !== null && _card$activity$channe4 !== void 0 && (_card$activity$channe5 = _card$activity$channe4.tags) !== null && _card$activity$channe5 !== void 0 && _card$activity$channe5.includes(Constants.systemMessageTag)) {
90
+ if (isTagIncluded(card, Constants.hiddenTag)) {
91
+ return () => false;
92
+ }
93
+
94
+ if (isTagIncluded(card, Constants.systemMessageTag)) {
81
95
  return handleSystemMessage(next, args, card, systemMessageStyleProps);
82
96
  } else if (card.activity.text && card.activity.type === DirectLineActivityType.Message) {
83
97
  if (!card.activity.channelData.isHtmlEncoded && card.activity.channelId === Constants.webchatChannelId) {
@@ -0,0 +1,41 @@
1
+ import { BotMagicCodeStore } from "../../BotMagicCodeStore";
2
+ var CardActionType;
3
+
4
+ (function (CardActionType) {
5
+ CardActionType["OpenUrl"] = "openUrl";
6
+ CardActionType["SignIn"] = "signin";
7
+ })(CardActionType || (CardActionType = {}));
8
+
9
+ const validCardActionTypes = [CardActionType.OpenUrl, CardActionType.SignIn];
10
+ const botOauthUrlRegex = /[\S]+.botframework.com\/api\/oauth\/signin\?signin=([\S]+)/;
11
+ export const createCardActionMiddleware = botMagicCodeConfig => {
12
+ const cardActionMiddleware = () => next => function () {
13
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
14
+ args[_key] = arguments[_key];
15
+ }
16
+
17
+ // eslint-disable-line @typescript-eslint/no-explicit-any
18
+ const [card] = args;
19
+
20
+ if (card.cardAction && validCardActionTypes.indexOf(card.cardAction.type) >= 0 && card.cardAction.value) {
21
+ // Override signin url only if fwdUrl is valid & feature is enabled
22
+ if ((botMagicCodeConfig === null || botMagicCodeConfig === void 0 ? void 0 : botMagicCodeConfig.disabled) === true && botMagicCodeConfig !== null && botMagicCodeConfig !== void 0 && botMagicCodeConfig.fwdUrl) {
23
+ const baseUrl = window.location.origin;
24
+ const result = botOauthUrlRegex.exec(card.cardAction.value);
25
+
26
+ if (result) {
27
+ BotMagicCodeStore.botOAuthSignInId = `${result[1]}`;
28
+ } // fwdUrl must be on the same domain as the chat widget
29
+
30
+
31
+ if (botMagicCodeConfig !== null && botMagicCodeConfig !== void 0 && botMagicCodeConfig.fwdUrl.startsWith(baseUrl)) {
32
+ card.cardAction.value += `&fwdUrl=${botMagicCodeConfig.fwdUrl}`;
33
+ }
34
+ }
35
+ }
36
+
37
+ return next(...args);
38
+ };
39
+
40
+ return cardActionMiddleware;
41
+ };
@@ -0,0 +1,94 @@
1
+ import "@testing-library/jest-dom/extend-expect";
2
+ import { createCardActionMiddleware } from "./cardActionMiddleware";
3
+ describe("cardActionMiddleware test", () => {
4
+ it("createCardActionMiddleware() with undefined botMagicCodeConfig should not change the sign in card url", () => {
5
+ const next = args => args; // eslint-disable-line @typescript-eslint/no-explicit-any
6
+
7
+
8
+ const signInUrl = "https://token.botframework.com/api/oauth/signin?signin=[signin]";
9
+ const args = {
10
+ cardAction: {
11
+ type: "signin",
12
+ value: signInUrl
13
+ }
14
+ };
15
+ const results = createCardActionMiddleware(undefined)()(next)(args);
16
+ expect(signInUrl).toEqual(results.cardAction.value);
17
+ });
18
+ it("createCardActionMiddleware() with botMagicCode enabled should not change the sign in card url", () => {
19
+ const botMagicCodeConfig = {
20
+ disabled: false
21
+ };
22
+
23
+ const next = args => args; // eslint-disable-line @typescript-eslint/no-explicit-any
24
+
25
+
26
+ const signInUrl = "https://token.botframework.com/api/oauth/signin?signin=[signin]";
27
+ const args = {
28
+ cardAction: {
29
+ type: "signin",
30
+ value: signInUrl
31
+ }
32
+ };
33
+ const results = createCardActionMiddleware(botMagicCodeConfig)()(next)(args);
34
+ expect(args.cardAction.value).toEqual(results.cardAction.value);
35
+ });
36
+ it("createCardActionMiddleware() with botMagicCode disabled & no fwdUrl should not change the sign in card url", () => {
37
+ const botMagicCodeConfig = {
38
+ disabled: true
39
+ };
40
+
41
+ const next = args => args; // eslint-disable-line @typescript-eslint/no-explicit-any
42
+
43
+
44
+ const signInUrl = "https://token.botframework.com/api/oauth/signin?signin=[signin]";
45
+ const args = {
46
+ cardAction: {
47
+ type: "signin",
48
+ value: signInUrl
49
+ }
50
+ };
51
+ const results = createCardActionMiddleware(botMagicCodeConfig)()(next)(args);
52
+ expect(args.cardAction.value).toEqual(results.cardAction.value);
53
+ });
54
+ it("createCardActionMiddleware() with botMagicCode disabled & fwdUrl should append the fwdUrl in the sign in card url", () => {
55
+ const botMagicCodeConfig = {
56
+ disabled: true,
57
+ fwdUrl: "http://localhost/forwarder.html"
58
+ };
59
+
60
+ const next = args => args; // eslint-disable-line @typescript-eslint/no-explicit-any
61
+
62
+
63
+ const signInUrl = "https://token.botframework.com/api/oauth/signin?signin=[signin]";
64
+ const args = {
65
+ cardAction: {
66
+ type: "signin",
67
+ value: signInUrl
68
+ }
69
+ };
70
+ const results = createCardActionMiddleware(botMagicCodeConfig)()(next)(args);
71
+ expect(signInUrl === results.cardAction.value).toBe(false);
72
+ expect(results.cardAction.value === `${signInUrl}&fwdUrl=${botMagicCodeConfig.fwdUrl}`).toBe(true);
73
+ });
74
+ it("createCardActionMiddleware() should not append fwdUrl if fwdUrl & sign in card url are not in the same domain", () => {
75
+ const botMagicCodeConfig = {
76
+ disabled: true,
77
+ fwdUrl: "https://localhost/forwarder.html"
78
+ };
79
+
80
+ const next = args => args; // eslint-disable-line @typescript-eslint/no-explicit-any
81
+
82
+
83
+ const signInUrl = "https://token.botframework.com/api/oauth/signin?signin=[signin]";
84
+ const args = {
85
+ cardAction: {
86
+ type: "signin",
87
+ value: signInUrl
88
+ }
89
+ };
90
+ const results = createCardActionMiddleware(botMagicCodeConfig)()(next)(args);
91
+ expect(signInUrl === results.cardAction.value).toBe(true);
92
+ expect(results.cardAction.value === `${signInUrl}&fwdUrl=${botMagicCodeConfig.fwdUrl}`).toBe(false);
93
+ });
94
+ });
@@ -0,0 +1,107 @@
1
+ import { WebChatActionType } from "../../enums/WebChatActionType";
2
+ import { Constants } from "../../../../../common/Constants"; // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
3
+
4
+ const createMessageTimeStampMiddleware = _ref => {
5
+ let {
6
+ dispatch
7
+ } = _ref;
8
+ return next => action => {
9
+ if (isApplicable(action)) {
10
+ return next(evaluateTagsAndOverrideTimeStamp(action));
11
+ }
12
+
13
+ return next(action);
14
+ };
15
+ };
16
+
17
+ const isApplicable = action => {
18
+ return action.type === WebChatActionType.DIRECT_LINE_INCOMING_ACTIVITY && isPVAConversation(action) && isPayloadValid(action) && isValidChannel(action);
19
+ };
20
+
21
+ const isPayloadValid = action => {
22
+ var _action$payload;
23
+
24
+ return action === null || action === void 0 ? void 0 : (_action$payload = action.payload) === null || _action$payload === void 0 ? void 0 : _action$payload.activity;
25
+ };
26
+
27
+ const isValidChannel = action => {
28
+ var _action$payload2, _action$payload2$acti;
29
+
30
+ return (action === null || action === void 0 ? void 0 : (_action$payload2 = action.payload) === null || _action$payload2 === void 0 ? void 0 : (_action$payload2$acti = _action$payload2.activity) === null || _action$payload2$acti === void 0 ? void 0 : _action$payload2$acti.channelId) === Constants.acsChannel;
31
+ };
32
+
33
+ const isPVAConversation = action => {
34
+ return !isTagIncluded(action, Constants.systemMessageTag) && !isTagIncluded(action, Constants.publicMessageTag) && !isRoleUserOn(action);
35
+ }; // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
+
37
+
38
+ const isTagIncluded = (action, tag) => {
39
+ return isDataTagsPresent(action) && action.payload.activity.channelData.tags.includes(tag);
40
+ };
41
+
42
+ const isRoleUserOn = action => {
43
+ var _action$payload3, _action$payload3$acti, _action$payload3$acti2;
44
+
45
+ return (action === null || action === void 0 ? void 0 : (_action$payload3 = action.payload) === null || _action$payload3 === void 0 ? void 0 : (_action$payload3$acti = _action$payload3.activity) === null || _action$payload3$acti === void 0 ? void 0 : (_action$payload3$acti2 = _action$payload3$acti.from) === null || _action$payload3$acti2 === void 0 ? void 0 : _action$payload3$acti2.role) === Constants.userMessageTag;
46
+ };
47
+
48
+ const overrideTimeStamp = (timestampOriginal, timeStampNew) => {
49
+ return isTimestampValid(timeStampNew) ? timeStampNew : timestampOriginal;
50
+ };
51
+
52
+ const isTimestampValid = timeStamp => {
53
+ const regex = /(\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])(T)(\d{2})(:{1})(\d{2})(:{1})(\d{2})(.\d+)([Z]{1}))/;
54
+ return regex.test(timeStamp);
55
+ };
56
+
57
+ const isDataTagsPresent = action => {
58
+ var _action$payload4, _action$payload4$acti, _action$payload4$acti2;
59
+
60
+ return (action === null || action === void 0 ? void 0 : (_action$payload4 = action.payload) === null || _action$payload4 === void 0 ? void 0 : (_action$payload4$acti = _action$payload4.activity) === null || _action$payload4$acti === void 0 ? void 0 : (_action$payload4$acti2 = _action$payload4$acti.channelData) === null || _action$payload4$acti2 === void 0 ? void 0 : _action$payload4$acti2.tags) && action.payload.activity.channelData.tags.length > 0;
61
+ };
62
+
63
+ const evaluateTagsAndOverrideTimeStamp = action => {
64
+ const tagValue = tagLookup(action, Constants.prefixTimestampTag);
65
+
66
+ if (tagValue) {
67
+ const newTimestamp = extractTimeStamp(tagValue);
68
+ action.payload.activity.timestamp = overrideTimeStamp(action.payload.activity.timestamp, newTimestamp);
69
+ }
70
+
71
+ return action;
72
+ };
73
+
74
+ const extractTimeStamp = timeStamp => {
75
+ if (timeStamp && timeStamp.length > 0) {
76
+ const ts = timeStamp.split(Constants.prefixTimestampTag);
77
+
78
+ if (ts && ts.length > 1) {
79
+ return ts[1];
80
+ }
81
+ }
82
+
83
+ return timeStamp;
84
+ };
85
+
86
+ const tagLookup = (action, tag) => {
87
+ if (!isDataTagsPresent(action)) {
88
+ return null;
89
+ }
90
+
91
+ const tags = action.payload.activity.channelData.tags;
92
+ let value;
93
+
94
+ if (tags && tags.length > 0) {
95
+ for (let i = 0; i < tags.length; i++) {
96
+ value = tags[i];
97
+
98
+ if (value && value.indexOf(tag) > -1) {
99
+ return value;
100
+ }
101
+ }
102
+ }
103
+
104
+ return null;
105
+ };
106
+
107
+ export default createMessageTimeStampMiddleware;
@@ -32,4 +32,6 @@ export let LiveChatWidgetActionType;
32
32
  LiveChatWidgetActionType[LiveChatWidgetActionType["SET_CONVERSATION_ENDED_BY_AGENT"] = 28] = "SET_CONVERSATION_ENDED_BY_AGENT";
33
33
  LiveChatWidgetActionType[LiveChatWidgetActionType["SET_WIDGET_STATE"] = 29] = "SET_WIDGET_STATE";
34
34
  LiveChatWidgetActionType[LiveChatWidgetActionType["SET_LIVE_CHAT_CONTEXT"] = 30] = "SET_LIVE_CHAT_CONTEXT";
35
+ LiveChatWidgetActionType[LiveChatWidgetActionType["SET_BOT_OAUTH_SIGNIN_ID"] = 31] = "SET_BOT_OAUTH_SIGNIN_ID";
36
+ LiveChatWidgetActionType[LiveChatWidgetActionType["SET_WIDGET_SIZE"] = 32] = "SET_WIDGET_SIZE";
35
37
  })(LiveChatWidgetActionType || (LiveChatWidgetActionType = {}));
@@ -19,7 +19,8 @@ export const getLiveChatWidgetContextInitialState = props => {
19
19
  telemetryInternalData: {},
20
20
  globalDir: "ltr",
21
21
  liveChatContext: undefined,
22
- customContext: undefined
22
+ customContext: undefined,
23
+ widgetSize: undefined
23
24
  },
24
25
  appStates: {
25
26
  conversationState: ConversationState.Closed,
@@ -227,6 +227,14 @@ export const createReducer = () => {
227
227
  }
228
228
  };
229
229
 
230
+ case LiveChatWidgetActionType.SET_WIDGET_SIZE:
231
+ return { ...state,
232
+ domainStates: { ...state.domainStates,
233
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
234
+ widgetSize: action.payload
235
+ }
236
+ };
237
+
230
238
  default:
231
239
  return state;
232
240
  }
@@ -1,4 +1,6 @@
1
1
  export declare class Constants {
2
+ static readonly magicCodeBroadcastChannel = "MagicCodeChannel";
3
+ static readonly magicCodeResponseBroadcastChannel = "MagicCodeResponseChannel";
2
4
  static readonly systemMessageTag = "system";
3
5
  static readonly userMessageTag = "user";
4
6
  static readonly historyMessageTag = "history";
@@ -32,6 +34,10 @@ export declare class Constants {
32
34
  static readonly queuePositionMessageTag = "queueposition";
33
35
  static readonly averageWaitTimeMessageTag = "averagewaittime";
34
36
  static readonly message = "message";
37
+ static readonly hiddenTag = "Hidden";
38
+ static readonly prefixTimestampTag = "ServerMessageTimestamp_";
39
+ static readonly acsChannel = "ACS_CHANNEL";
40
+ static readonly publicMessageTag = "public";
35
41
  static readonly supportedAdaptiveCardContentTypes: Array<string>;
36
42
  static readonly maxUploadFileSize = "500000";
37
43
  static readonly imageRegex: RegExp;