Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DRAFT Implemente react lazy #531

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions chat-widget/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@
"react",
"@typescript-eslint"
],
"settings": {
"react": {
"version": "detect"
}
},
"rules": {
"indent": [
"error",
Expand Down
35 changes: 20 additions & 15 deletions chat-widget/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
"types": "lib/types/index.d.ts",
"repository": "https://github.com/microsoft/omnichannel-chat-widget",
"author": "Microsoft",
"license": "MIT",
"type": "module",
"license": "ISC",
"files": [
"lib"
],
Expand All @@ -22,8 +21,8 @@
"devDependencies": {
"@babel/core": "^7.15.8",
"@babel/preset-env": "^7.15.8",
"@babel/preset-react": "^7.14.5",
"@babel/preset-typescript": "^7.15.0",
"@babel/preset-react": "^7.24.7",
"@babel/preset-typescript": "^7.24.7",
"@storybook/addon-a11y": "^6.4.8",
"@storybook/addon-actions": "^6.4.8",
"@storybook/addon-essentials": "^6.4.8",
Expand All @@ -39,13 +38,13 @@
"@types/jest": "^27.0.2",
"@types/jest-image-snapshot": "^4.3.1",
"@types/markdown-it": "^12.2.3",
"@types/react": "^17.0.30",
"@types/react-dom": "^17.0.10",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@types/styled-components": "^5.1.15",
"@typescript-eslint/eslint-plugin": "^5.3.0",
"@typescript-eslint/parser": "^5.2.0",
"babel-jest": "^27.3.1",
"babel-loader": "^8.2.3",
"babel-loader": "^9.1.0",
"botframework-directlinejs": "^0.15.0",
"copyfiles": "^2.4.1",
"eslint": "^7.32.0",
Expand All @@ -62,16 +61,22 @@
"json": "^11.0.0",
"playwright": "^1.16.3",
"postcss": "^8.3.9",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-test-renderer": "^17.0.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-test-renderer": "^18.3.1",
"storybook-addon-playwright": "^4.9.2",
"swiper": "^9.0.5",
"terser-webpack-plugin": "^4.2.3",
"ts-loader": "^9.2.6",
"typescript": "4.6.4",
"webpack": "^4.44.2",
"webpack-cli": "^4.9.2"
"terser-webpack-plugin": "^5.3.10",
"ts-loader": "^9.5.1",
"typescript": "5.5.4",
"webpack": "^5.94.0",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^5.1.0",
"clean-webpack-plugin": "^4.0.0",
"crypto-browserify": "^3.12.0",
"stream-browserify": "^3.0.0",
"thread-loader": "^4.0.4",
"fork-ts-checker-webpack-plugin": "^9.0.2"
},
"dependencies": {
"@microsoft/omnichannel-chat-components": "1.1.5",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Constants } from "./Constants";
import { Constants } from "./Constants.js";

export const memoryDataStore = () => {
var internalCache = {};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Constants } from "./Constants";
import { memoryDataStore } from "./MemoryDataStore";
import { Constants } from "./Constants.js";
import { memoryDataStore } from "./MemoryDataStore.js";

export const clientDataStoreProvider = () => {
const _memoryDataStore = memoryDataStore();
Expand Down
8 changes: 4 additions & 4 deletions chat-widget/samples/javascript-sample/SampleWidget.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import * as React from "react";

import { getUnreadMessageCount, registerVisibilityListener } from "./getUnreadMessageCount";
import { getUnreadMessageCount, registerVisibilityListener } from "./getUnreadMessageCount.js";

import { BroadcastService } from "../../lib/esm/index.js";
import LiveChatWidget from "../../lib/esm/components/livechatwidget/LiveChatWidget.js";
Expand All @@ -11,9 +11,9 @@ import ReactDOM from "react-dom";
import { version as chatComponentVersion } from "@microsoft/omnichannel-chat-components/package.json";
import { version as chatSdkVersion } from "@microsoft/omnichannel-chat-sdk/package.json";
import { version as chatWidgetVersion } from "../../package.json";
import { getCustomizationJson } from "./getCustomizationJson";
import { memoryDataStore } from "./Common/MemoryDataStore";
import getMockChatSDKIfApplicable from "./getMockChatSDKIfApplicable";
import { getCustomizationJson } from "./getCustomizationJson.js";
import { memoryDataStore } from "./Common/MemoryDataStore.js";
import getMockChatSDKIfApplicable from "./getMockChatSDKIfApplicable.js";

let liveChatWidgetProps;

Expand Down
4 changes: 2 additions & 2 deletions chat-widget/samples/javascript-sample/cacheWidgetState.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { BroadcastService } from "@microsoft/omnichannel-chat-components";
import { clientDataStoreProvider } from "./Common/clientDataStoreProvider";
import { Constants } from "./Common/Constants";
import { clientDataStoreProvider } from "./Common/clientDataStoreProvider.js";
import { Constants } from "./Common/Constants.js";

export const registerCacheWidgetStateEvent = async () => {
BroadcastService.getMessageByEventName(Constants.WidgetStateChangedEventName).subscribe((msg) => {
Expand Down
10 changes: 8 additions & 2 deletions chat-widget/samples/javascript-sample/test.html
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,14 @@
}
</script>
<div id="oc-lcw-container" style="width: 370px; height: 100%; position: fixed; right: 0; bottom: 0"></div>
<script id="oc-lcw-script" src="../../dist/out.js" data-customization-callback="lcw" data-org-id="" data-app-id=""
data-org-url=""></script>
<script id="oc-lcw-script" src="../../dist/out.js" data-customization-callback="lcw"


data-org-id="ce4db5f6-1c20-ee11-a66d-000d3a0a02f3"
data-app-id="148d0ead-14d2-41ea-bfc9-f4d4287f060c"
data-org-url="https://m-ce4db5f6-1c20-ee11-a66d-000d3a0a02f3.ca.omnichannelengagementhub.com"

></script>
</body>

</html>
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { LogLevel, TelemetryEvent } from "../../common/telemetry/TelemetryConstants";
import React, { Dispatch, useCallback, useEffect } from "react";
import React, { Dispatch, Suspense, lazy, useCallback, useEffect } from "react";

import { CallingContainer } from "@microsoft/omnichannel-chat-components";
import { ICallingContainerControlProps } from "@microsoft/omnichannel-chat-components/lib/types/components/callingcontainer/interfaces/ICallingContainerControlProps";
import { ICallingContainerStatefulProps } from "./ICallingContainerStatefulProps";
import { ILiveChatWidgetAction } from "../../contexts/common/ILiveChatWidgetAction";
Expand All @@ -13,7 +12,7 @@ import useChatSDKStore from "../../hooks/useChatSDKStore";

export const CallingContainerStateful = (props: ICallingContainerStatefulProps) => {

//TODO : Close button confirmation implmentation is pending
const CallingContainer = lazy(() => import(/* webpackChunkName: "CallingContainer" */ "@microsoft/omnichannel-chat-components").then(module => ({ default: module.CallingContainer })));

const [state, dispatch]: [ILiveChatWidgetContext, Dispatch<ILiveChatWidgetAction>] = useChatContextStore();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down Expand Up @@ -281,7 +280,9 @@ export const CallingContainerStateful = (props: ICallingContainerStatefulProps)
return (
<>
{state.uiStates.showCallingPopup &&
<CallingContainer controlProps={controlProps} styleProps={props?.styleProps} />
<Suspense fallback={<div>Loading...</div>}>
<CallingContainer controlProps={controlProps} styleProps={props?.styleProps} />
</Suspense>
}
</>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { LogLevel, TelemetryEvent } from "../../common/telemetry/TelemetryConstants";
import React, { Dispatch, useEffect, useRef, useState } from "react";
import React, { Dispatch, Suspense, lazy, useEffect, useRef, useState } from "react";

import { ChatButton } from "@microsoft/omnichannel-chat-components";
import { Constants } from "../../common/Constants";
import { ConversationState } from "../../contexts/common/ConversationState";
import { IChatButtonControlProps } from "@microsoft/omnichannel-chat-components/lib/types/components/chatbutton/interfaces/IChatButtonControlProps";
Expand All @@ -18,6 +17,9 @@ import useChatContextStore from "../../hooks/useChatContextStore";

export const ChatButtonStateful = (props: IChatButtonStatefulParams) => {

const ChatButton = lazy(() => import(/* webpackChunkName: "ChatButton" */ "@microsoft/omnichannel-chat-components").then((module) => ({ default: module.ChatButton })));


const [state, dispatch]: [ILiveChatWidgetContext, Dispatch<ILiveChatWidgetAction>] = useChatContextStore();
const { buttonProps, outOfOfficeButtonProps, startChat } = props;
//Setting OutOfOperatingHours Flag
Expand Down Expand Up @@ -88,11 +90,13 @@ export const ChatButtonStateful = (props: IChatButtonStatefulParams) => {
}, []);

return (
<ChatButton
componentOverrides={buttonProps?.componentOverrides}
controlProps={outOfOperatingHours ? outOfOfficeControlProps : controlProps}
styleProps={outOfOperatingHours ? outOfOfficeStyleProps : buttonProps?.styleProps}
/>
<Suspense fallback={<div>Loading..</div>}>
<ChatButton
componentOverrides={buttonProps?.componentOverrides}
controlProps={outOfOperatingHours ? outOfOfficeControlProps : controlProps}
styleProps={outOfOperatingHours ? outOfOfficeStyleProps : buttonProps?.styleProps}
/>
</Suspense>
);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import { LogLevel, TelemetryEvent } from "../../common/telemetry/TelemetryConstants";
import { ConfirmationPane } from "@microsoft/omnichannel-chat-components";
import React, { Dispatch, useEffect } from "react";
import React, { Dispatch, Suspense, lazy, useEffect } from "react";
import { findAllFocusableElement, findParentFocusableElementsWithoutChildContainer, preventFocusToMoveOutOfElement, setFocusOnElement, setFocusOnSendBox, setTabIndices } from "../../common/utils";
import { DimLayer } from "../dimlayer/DimLayer";

import { ConfirmationState } from "../../common/Constants";
import { IConfirmationPaneControlProps } from "@microsoft/omnichannel-chat-components/lib/types/components/confirmationpane/interfaces/IConfirmationPaneControlProps";
import { IConfirmationPaneStatefulParams } from "./interfaces/IConfirmationPaneStatefulParams";
import { ILiveChatWidgetAction } from "../../contexts/common/ILiveChatWidgetAction";
import { ILiveChatWidgetContext } from "../../contexts/common/ILiveChatWidgetContext";
import { LiveChatWidgetActionType } from "../../contexts/common/LiveChatWidgetActionType";
import { TelemetryHelper } from "../../common/telemetry/TelemetryHelper";
import useChatContextStore from "../../hooks/useChatContextStore";
import { ConfirmationState } from "../../common/Constants";

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const ConfirmationPaneStateful = (props: IConfirmationPaneStatefulParams) => {

const ConfirmationPane = lazy(() => import(/* webpackChunkName: "ConfirmationPane" */ "@microsoft/omnichannel-chat-components").then(module => ({ default: module.ConfirmationPane })));
const DimLayer = lazy(() => import(/* webpackChunkName: "DimLayer" */ "../dimlayer/DimLayer").then(module => ({ default: module.DimLayer })));

const initialTabIndexMap: Map<string, number> = new Map();
let elements: HTMLElement[] | null = [];

Expand Down Expand Up @@ -72,11 +74,13 @@ export const ConfirmationPaneStateful = (props: IConfirmationPaneStatefulParams)

return (
<>
<DimLayer brightness={controlProps?.brightnessValueOnDim ?? "0.2"} />
<ConfirmationPane
componentOverrides={props?.componentOverrides}
controlProps={controlProps}
styleProps={props?.styleProps} />
<Suspense fallback={<div>Loading..</div>}>
<DimLayer brightness={controlProps?.brightnessValueOnDim ?? "0.2"} />
<ConfirmationPane
componentOverrides={props?.componentOverrides}
controlProps={controlProps}
styleProps={props?.styleProps} />
</Suspense>
</>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { LogLevel, TelemetryEvent } from "../../common/telemetry/TelemetryConstants";
import React, { Dispatch, useCallback, useEffect, useState } from "react";
import React, { Dispatch, Suspense, lazy, useCallback, useEffect, useState } from "react";
import { findAllFocusableElement, findParentFocusableElementsWithoutChildContainer, formatTemplateString, preventFocusToMoveOutOfElement, setFocusOnElement, setFocusOnSendBox, setTabIndices } from "../../common/utils";

import { DimLayer } from "../dimlayer/DimLayer";
Expand All @@ -8,17 +8,19 @@ import { IEmailTranscriptPaneProps } from "./interfaces/IEmailTranscriptPaneProp
import { IInputValidationPaneControlProps } from "@microsoft/omnichannel-chat-components/lib/types/components/inputvalidationpane/interfaces/IInputValidationPaneControlProps";
import { ILiveChatWidgetAction } from "../../contexts/common/ILiveChatWidgetAction";
import { ILiveChatWidgetContext } from "../../contexts/common/ILiveChatWidgetContext";
import { InputValidationPane } from "@microsoft/omnichannel-chat-components";
import { LiveChatWidgetActionType } from "../../contexts/common/LiveChatWidgetActionType";
import { NotificationHandler } from "../webchatcontainerstateful/webchatcontroller/notification/NotificationHandler";
import { NotificationScenarios } from "../webchatcontainerstateful/webchatcontroller/enums/NotificationScenarios";
import { Regex } from "../../common/Constants";
import { TelemetryHelper } from "../../common/telemetry/TelemetryHelper";
import { defaultMiddlewareLocalizedTexts } from "../webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts";
import useChatContextStore from "../../hooks/useChatContextStore";
import useChatSDKStore from "../../hooks/useChatSDKStore";
import { defaultMiddlewareLocalizedTexts } from "../webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts";

export const EmailTranscriptPaneStateful = (props: IEmailTranscriptPaneProps) => {

const InputValidationPane = lazy(() => import(/* webpackChunkName: "InputValidationPane" */ "@microsoft/omnichannel-chat-components").then(module => ({ default: module.InputValidationPane })));

const initialTabIndexMap: Map<string, number> = new Map();
let elements: HTMLElement[] | null = [];
const [state, dispatch]: [ILiveChatWidgetContext, Dispatch<ILiveChatWidgetAction>] = useChatContextStore();
Expand Down Expand Up @@ -96,10 +98,12 @@ export const EmailTranscriptPaneStateful = (props: IEmailTranscriptPaneProps) =>
return (
<>
<DimLayer brightness={controlProps?.brightnessValueOnDim ?? "0.2"} />
<InputValidationPane
componentOverrides={props.componentOverrides}
controlProps={controlProps}
styleProps={props.styleProps} />
<Suspense fallback={<div>Loading..</div>}>
<InputValidationPane
componentOverrides={props.componentOverrides}
controlProps={controlProps}
styleProps={props.styleProps} />
</Suspense>
</>
);
};
Expand Down
33 changes: 19 additions & 14 deletions chat-widget/src/components/footerstateful/FooterStateful.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { LogLevel, TelemetryEvent } from "../../common/telemetry/TelemetryConstants";
import React, { Dispatch } from "react";
import React, { Dispatch, Suspense, lazy } from "react";

import AudioNotificationStateful from "./audionotificationstateful/AudioNotificationStateful";
import { Constants } from "../../common/Constants";
import { Footer } from "@microsoft/omnichannel-chat-components";
import { IFooterControlProps } from "@microsoft/omnichannel-chat-components/lib/types/components/footer/interfaces/IFooterControlProps";
import { ILiveChatWidgetAction } from "../../contexts/common/ILiveChatWidgetAction";
import { ILiveChatWidgetContext } from "../../contexts/common/ILiveChatWidgetContext";
Expand All @@ -19,6 +17,8 @@ import useChatSDKStore from "../../hooks/useChatSDKStore";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const FooterStateful = (props: any) => {
const [state, dispatch]: [ILiveChatWidgetContext, Dispatch<ILiveChatWidgetAction>] = useChatContextStore();
const AudioNotificationStateful = lazy(() => import(/* webpackChunkName: "AudioNotificationStateful" */ "./audionotificationstateful/AudioNotificationStateful").then(module => ({ default: module.AudioNotificationStateful })));
const Footer = lazy(() => import(/* webpackChunkName: "Footer" */ "@microsoft/omnichannel-chat-components").then(module => ({ default: module.Footer })));
// hideFooterDisplay - the purpose of this is to keep the footer always "active",
// but hide it visually in certain states (e.g., loading state) and show in some other states (e.g. active state).
// The reason for this approach is to make sure that state variables for audio notification work correctly after minimizing
Expand Down Expand Up @@ -66,18 +66,23 @@ export const FooterStateful = (props: any) => {
return (
<>
{!hideFooterDisplay &&
<Footer
componentOverrides={footerProps?.componentOverrides}
controlProps={controlProps}
styleProps={footerProps?.styleProps}
/>
<Suspense fallback={<div>Loading</div>}>
<Footer
componentOverrides={footerProps?.componentOverrides}
controlProps={controlProps}
styleProps={footerProps?.styleProps}
/>
</Suspense>
}
<AudioNotificationStateful
audioSrc={audioNotificationProps?.audioSrc ?? NewMessageNotificationSoundBase64}
isAudioMuted={state.appStates.isAudioMuted === null ?
footerProps?.controlProps?.hideAudioNotificationButton ?? false :
state.appStates.isAudioMuted ?? false}
/>

<Suspense fallback={<div>Loading</div>}>
<AudioNotificationStateful
audioSrc={audioNotificationProps?.audioSrc ?? NewMessageNotificationSoundBase64}
isAudioMuted={state.appStates.isAudioMuted === null ?
footerProps?.controlProps?.hideAudioNotificationButton ?? false :
state.appStates.isAudioMuted ?? false}
/>
</Suspense>
</>
);
};
Expand Down
Loading
Loading