@asaleh37/ui-base 25.8.31 → 25.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +10 -1
- package/dist/index.js +134 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +134 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -2
- package/src/components/App.tsx +16 -1
- package/src/components/common/AzureLogin.tsx +70 -0
- package/src/components/common/Login.tsx +1 -0
- package/src/components/msalConfig.ts +11 -0
- package/src/hooks/useAxios.tsx +1 -0
- package/src/layout/Layout.tsx +14 -3
- package/src/layout/MainContent.tsx +0 -5
- package/src/layout/TopBar.tsx +2 -1
- package/src/main.tsx +7 -0
- package/src/navigationItems/index.tsx +1 -8
- package/src/redux/features/common/AppInfoSlice.ts +7 -0
- package/src/routes/index.ts +2 -6
- package/src/util/AppUtils.ts +18 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@asaleh37/ui-base",
|
|
3
|
-
"version": "25.
|
|
3
|
+
"version": "25.9.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"author": "Ahmed Saleh Mohamed",
|
|
@@ -113,7 +113,9 @@
|
|
|
113
113
|
"stylis-plugin-rtl": "^2.1.1",
|
|
114
114
|
"zod": "^3.24.2"
|
|
115
115
|
},
|
|
116
|
-
"dependencies": {
|
|
116
|
+
"dependencies": {
|
|
117
|
+
"@azure/msal-browser": "^4.21.1",
|
|
118
|
+
"@azure/msal-react": "^3.0.19",
|
|
117
119
|
"@rollup/plugin-json": "^6.1.0",
|
|
118
120
|
"rollup-plugin-terser": "^7.0.2"
|
|
119
121
|
}
|
package/src/components/App.tsx
CHANGED
|
@@ -13,9 +13,18 @@ import {
|
|
|
13
13
|
} from "../util";
|
|
14
14
|
import { setStoresMetaData } from "../redux/features/common/CommonStoreSlice";
|
|
15
15
|
import { ADMINISTRATION_STORES } from "../redux/features/administration/AdministrationStoresMetaData";
|
|
16
|
+
import { PublicClientApplication } from "@azure/msal-browser";
|
|
17
|
+
import { MsalProvider } from "@azure/msal-react";
|
|
16
18
|
|
|
17
19
|
const App: React.FC<AppInfo> = (props: AppInfo) => {
|
|
18
20
|
const dispatch = useDispatch();
|
|
21
|
+
const msalInstance = new PublicClientApplication({
|
|
22
|
+
auth: {
|
|
23
|
+
clientId: props?.azureConfiguration?.frontEndClientId,
|
|
24
|
+
authority: `https://login.microsoftonline.com/${props?.azureConfiguration?.tenantId}`,
|
|
25
|
+
redirectUri: props?.azureConfiguration?.redirectURL,
|
|
26
|
+
},
|
|
27
|
+
});
|
|
19
28
|
LicenseInfo.setLicenseKey(props.muiPremiumKey);
|
|
20
29
|
const LightThemeOptions: ThemeOptions = {
|
|
21
30
|
components: {
|
|
@@ -115,7 +124,13 @@ const App: React.FC<AppInfo> = (props: AppInfo) => {
|
|
|
115
124
|
}, [props]);
|
|
116
125
|
return (
|
|
117
126
|
<ThemeProvider theme={theme}>
|
|
118
|
-
|
|
127
|
+
{props?.authenticationMethod === "AZURE" ? (
|
|
128
|
+
<MsalProvider instance={msalInstance}>
|
|
129
|
+
<Layout msalInstance={msalInstance} />
|
|
130
|
+
</MsalProvider>
|
|
131
|
+
) : (
|
|
132
|
+
<Layout msalInstance={msalInstance} />
|
|
133
|
+
)}
|
|
119
134
|
</ThemeProvider>
|
|
120
135
|
);
|
|
121
136
|
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { PublicClientApplication } from "@azure/msal-browser";
|
|
2
|
+
import { Box, Button } from "@mui/material";
|
|
3
|
+
import { useDispatch, useSelector } from "react-redux";
|
|
4
|
+
import { AppInfo } from "../../redux/features/common/AppInfoSlice";
|
|
5
|
+
import { useAxios } from "../../hooks";
|
|
6
|
+
import { UserSessionActions } from "../../redux/features/common/UserSessionSlice";
|
|
7
|
+
import { useEffect } from "react";
|
|
8
|
+
|
|
9
|
+
interface AzureLoginProps {
|
|
10
|
+
msalInstance: PublicClientApplication;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const AzureLogin: React.FC<AzureLoginProps> = ({ msalInstance }) => {
|
|
14
|
+
const appInfo: AppInfo = useSelector((state: any) => state.AppInfo.value);
|
|
15
|
+
const userSession = useSelector((state: any) => state.UserSession.value);
|
|
16
|
+
const { handleGetRequest } = useAxios();
|
|
17
|
+
const dispatch = useDispatch();
|
|
18
|
+
const checkUserSession = async () => {
|
|
19
|
+
if (appInfo?.apiBaseUrl) {
|
|
20
|
+
if (userSession.isAuthenticated == null) {
|
|
21
|
+
const token = localStorage.getItem("TOKEN");
|
|
22
|
+
handleGetRequest({
|
|
23
|
+
endPointURI: "api/auth/userInfo",
|
|
24
|
+
showMask: true,
|
|
25
|
+
successCallBkFn: (response) => {
|
|
26
|
+
if (response != null && response.data != null) {
|
|
27
|
+
const UserSession = {
|
|
28
|
+
...response.data,
|
|
29
|
+
isAuthenticated: true,
|
|
30
|
+
};
|
|
31
|
+
dispatch(UserSessionActions.setAuthenticated(UserSession));
|
|
32
|
+
} else {
|
|
33
|
+
dispatch(UserSessionActions.setUnAuthenticated());
|
|
34
|
+
localStorage.removeItem("TOKEN");
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const handleLogin = async () => {
|
|
42
|
+
const response = await msalInstance.acquireTokenPopup({
|
|
43
|
+
scopes: appInfo?.azureConfiguration?.scopes,
|
|
44
|
+
});
|
|
45
|
+
if (response?.accessToken) {
|
|
46
|
+
localStorage.setItem("TOKEN", response.accessToken);
|
|
47
|
+
checkUserSession();
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const getUserInfo = async () => {
|
|
51
|
+
const response = await handleGetRequest({
|
|
52
|
+
endPointURI: "api/auth/userInfo",
|
|
53
|
+
showMask: true,
|
|
54
|
+
successCallBkFn: (response) => {
|
|
55
|
+
console.log(response);
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// useEffect(()=>{
|
|
61
|
+
// handleLogin()
|
|
62
|
+
// },[])
|
|
63
|
+
return (
|
|
64
|
+
<Box>
|
|
65
|
+
<Button onClick={handleLogin}>Azure Login </Button>
|
|
66
|
+
</Box>
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export default AzureLogin;
|
|
@@ -121,6 +121,7 @@ const Login: React.FC = () => {
|
|
|
121
121
|
dispatch(UserSessionActions.setAuthenticated(UserSession));
|
|
122
122
|
} else {
|
|
123
123
|
dispatch(UserSessionActions.setUnAuthenticated());
|
|
124
|
+
localStorage.removeItem("TOKEN");
|
|
124
125
|
}
|
|
125
126
|
} catch (error) {
|
|
126
127
|
dispatch(UserSessionActions.setUnAuthenticated());
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { PublicClientApplication } from "@azure/msal-browser";
|
|
2
|
+
|
|
3
|
+
export const msalConfig = {
|
|
4
|
+
auth: {
|
|
5
|
+
clientId: "your-frontend-client-id",
|
|
6
|
+
authority: "https://login.microsoftonline.com/<tenant-id>",
|
|
7
|
+
redirectUri: "http://localhost:3000"
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const msalInstance = new PublicClientApplication(msalConfig);
|
package/src/hooks/useAxios.tsx
CHANGED
package/src/layout/Layout.tsx
CHANGED
|
@@ -14,6 +14,9 @@ import { UserSessionProps } from "../redux/features/common/UserSessionSlice";
|
|
|
14
14
|
import LoadingMask from "../components/common/LoadingMask";
|
|
15
15
|
import Login from "../components/common/Login";
|
|
16
16
|
import NoLicenseComponent from "../components/common/NoLicenseComponent";
|
|
17
|
+
import { msalInstance } from "../components/msalConfig";
|
|
18
|
+
import { PublicClientApplication } from "@azure/msal-browser";
|
|
19
|
+
import AzureLogin from "../components/common/AzureLogin";
|
|
17
20
|
|
|
18
21
|
const Main = styled("main", {
|
|
19
22
|
shouldForwardProp: (prop) => prop !== "open",
|
|
@@ -53,9 +56,13 @@ const Main = styled("main", {
|
|
|
53
56
|
};
|
|
54
57
|
});
|
|
55
58
|
|
|
56
|
-
|
|
57
|
-
|
|
59
|
+
interface LayoutProps {
|
|
60
|
+
msalInstance: PublicClientApplication;
|
|
61
|
+
}
|
|
58
62
|
|
|
63
|
+
const Layout: React.FC<LayoutProps> = ({ msalInstance }) => {
|
|
64
|
+
const SideBarState = useSelector((state: any) => state.SideBar);
|
|
65
|
+
const appInfo = useSelector((state: any) => state.AppInfo.value);
|
|
59
66
|
const isMobile = useIsMobile();
|
|
60
67
|
const UserSession: UserSessionProps = useSelector(
|
|
61
68
|
(state: any) => state.UserSession
|
|
@@ -80,9 +87,13 @@ export default function Layout() {
|
|
|
80
87
|
<MainContent />
|
|
81
88
|
<NoLicenseComponent />
|
|
82
89
|
</Main>
|
|
90
|
+
) : appInfo.authenticationMethod === "AZURE" ? (
|
|
91
|
+
<AzureLogin msalInstance={msalInstance} />
|
|
83
92
|
) : (
|
|
84
93
|
<Login />
|
|
85
94
|
)}
|
|
86
95
|
</BrowserRouter>
|
|
87
96
|
);
|
|
88
|
-
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export default Layout;
|
package/src/layout/TopBar.tsx
CHANGED
|
@@ -102,6 +102,7 @@ const TopBar: React.FC = () => {
|
|
|
102
102
|
await handleGetRequest({ endPointURI: "api/auth/logout" });
|
|
103
103
|
} catch (error) {}
|
|
104
104
|
dispatch(UserSessionActions.setUnAuthenticated());
|
|
105
|
+
localStorage.removeItem("TOKEN");
|
|
105
106
|
};
|
|
106
107
|
const toggleSideBar = () => {
|
|
107
108
|
dispatch(toggleSideBarState());
|
|
@@ -169,7 +170,7 @@ const TopBar: React.FC = () => {
|
|
|
169
170
|
<AttachmentImageViewer
|
|
170
171
|
showAsAvatar={true}
|
|
171
172
|
attachmentCode="ORGANIZATION_LOGOS"
|
|
172
|
-
refKey={UserSession
|
|
173
|
+
refKey={UserSession?.value?.currentOrganization?.id + ""}
|
|
173
174
|
onErrorImage="/logo.png"
|
|
174
175
|
style={{
|
|
175
176
|
marginRight: 1,
|
package/src/main.tsx
CHANGED
|
@@ -8,6 +8,13 @@ createRoot(document.getElementById("root")!).render(
|
|
|
8
8
|
appLogo={"/logo.png"}
|
|
9
9
|
appName="UI Base Library"
|
|
10
10
|
appVersion="0.0"
|
|
11
|
+
authenticationMethod="AZURE"
|
|
12
|
+
azureConfiguration={{
|
|
13
|
+
frontEndClientId: "c3bbbdbd-f392-4459-b3dd-2351cb07f924",
|
|
14
|
+
tenantId: "9f136fef-4529-475f-98e6-d271eb04eb00",
|
|
15
|
+
redirectURL: "http://localhost:3000",
|
|
16
|
+
scopes: ["api://6008a934-2a32-4776-a3df-1842ac9371da/access_as_user"],
|
|
17
|
+
}}
|
|
11
18
|
businessCommonStoresMetaData={{}}
|
|
12
19
|
businessNavigationItems={[]}
|
|
13
20
|
businessReduxReducers={{}}
|
|
@@ -31,12 +31,5 @@ export const findNavigationItemById = (
|
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
export const NavigationItems: TreeViewBaseItem<ExtendedTreeItemProps>[] = [
|
|
34
|
-
...AdministrationItems
|
|
35
|
-
{
|
|
36
|
-
icon: "user",
|
|
37
|
-
label: "Example Grid",
|
|
38
|
-
id: "example",
|
|
39
|
-
action: "NAVIGATION",
|
|
40
|
-
actionPayload: { path: "example" },
|
|
41
|
-
},
|
|
34
|
+
...AdministrationItems
|
|
42
35
|
];
|
|
@@ -19,6 +19,13 @@ export type AppInfo = {
|
|
|
19
19
|
ar: { [key: string]: string };
|
|
20
20
|
en: { [key: string]: string };
|
|
21
21
|
};
|
|
22
|
+
authenticationMethod: "AZURE" | "APP";
|
|
23
|
+
azureConfiguration?: {
|
|
24
|
+
frontEndClientId: string;
|
|
25
|
+
tenantId: string;
|
|
26
|
+
redirectURL: string;
|
|
27
|
+
scopes: Array<string>;
|
|
28
|
+
};
|
|
22
29
|
businessRoutes?: Array<SystemRoute>;
|
|
23
30
|
businessNavigationItems?: Array<ExtendedTreeItemProps>;
|
|
24
31
|
businessReduxReducers?: { [key: string]: Reducer<any> };
|
package/src/routes/index.ts
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
import ExampleGrid from "../examples/ExampleGrid";
|
|
1
|
+
|
|
3
2
|
import { ADMINISTRATION_ROUTES } from "./administration";
|
|
4
3
|
import { SystemRoute } from "./types";
|
|
5
4
|
|
|
6
|
-
export const SYSTEM_ROUTES: Array<SystemRoute> = [
|
|
7
|
-
...ADMINISTRATION_ROUTES,
|
|
8
|
-
{ path: "example", component: ExampleGrid },
|
|
9
|
-
];
|
|
5
|
+
export const SYSTEM_ROUTES: Array<SystemRoute> = [...ADMINISTRATION_ROUTES];
|
package/src/util/AppUtils.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import moment from "moment";
|
|
1
2
|
import { FormElementProps } from "../components";
|
|
3
|
+
import { DATE_FORMAT } from "./constants";
|
|
2
4
|
|
|
3
5
|
export function hasDigitsOnly(str: string) {
|
|
4
6
|
return /^\d+$/.test(str);
|
|
@@ -53,3 +55,19 @@ export function timeAgo(dateInput, appDirection: "ltr" | "rtl") {
|
|
|
53
55
|
|
|
54
56
|
return locale === "ar" ? "الآن" : "just now";
|
|
55
57
|
}
|
|
58
|
+
|
|
59
|
+
export const formatDate = (date, format) => {
|
|
60
|
+
if (format) {
|
|
61
|
+
return moment(date).format(format);
|
|
62
|
+
} else {
|
|
63
|
+
return moment(date).format(DATE_FORMAT);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const parseStringToDate = (dateString, format) => {
|
|
68
|
+
if (format) {
|
|
69
|
+
return moment(dateString, format).toDate();
|
|
70
|
+
} else {
|
|
71
|
+
return moment(dateString, DATE_FORMAT).toDate();
|
|
72
|
+
}
|
|
73
|
+
};
|