@asaleh37/ui-base 25.8.31 → 25.9.3-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 +15 -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/public/bg.jpg +0 -0
- package/src/components/App.tsx +16 -1
- package/src/components/common/AzureLogin.tsx +222 -0
- package/src/components/common/Login.tsx +123 -77
- 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 +11 -0
- package/src/navigationItems/index.tsx +1 -8
- package/src/redux/features/common/AppInfoSlice.ts +13 -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.3-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/public/bg.jpg
ADDED
|
Binary file
|
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,222 @@
|
|
|
1
|
+
import { PublicClientApplication } from "@azure/msal-browser";
|
|
2
|
+
import {
|
|
3
|
+
Box,
|
|
4
|
+
Button,
|
|
5
|
+
CircularProgress,
|
|
6
|
+
createTheme,
|
|
7
|
+
Paper,
|
|
8
|
+
Typography,
|
|
9
|
+
} from "@mui/material";
|
|
10
|
+
import { useDispatch, useSelector } from "react-redux";
|
|
11
|
+
import { AppInfo } from "../../redux/features/common/AppInfoSlice";
|
|
12
|
+
import { useAxios } from "../../hooks";
|
|
13
|
+
import { UserSessionActions } from "../../redux/features/common/UserSessionSlice";
|
|
14
|
+
import { useEffect, useState } from "react";
|
|
15
|
+
|
|
16
|
+
import { ThemeProvider } from "@emotion/react";
|
|
17
|
+
import {
|
|
18
|
+
DARK_THEME_INITIAL_MAIN_COLOR,
|
|
19
|
+
DARK_THEME_INITIAL_SECANDARY_COLOR,
|
|
20
|
+
LIGHT_THEME_INITIAL_MAIN_COLOR,
|
|
21
|
+
LIGHT_THEME_INITIAL_SECANDARY_COLOR,
|
|
22
|
+
} from "../../util";
|
|
23
|
+
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
24
|
+
interface AzureLoginProps {
|
|
25
|
+
msalInstance: PublicClientApplication;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const AzureLogin: React.FC<AzureLoginProps> = ({ msalInstance }) => {
|
|
29
|
+
const appInfo: AppInfo = useSelector((state: any) => state.AppInfo.value);
|
|
30
|
+
const userSession = useSelector((state: any) => state.UserSession.value);
|
|
31
|
+
const [isLoginInProcess, setIsLoginInProcess] = useState(false);
|
|
32
|
+
const { handleGetRequest } = useAxios();
|
|
33
|
+
const dispatch = useDispatch();
|
|
34
|
+
const checkUserSession = async () => {
|
|
35
|
+
if (localStorage.getItem("TOKEN")) {
|
|
36
|
+
if (appInfo?.apiBaseUrl) {
|
|
37
|
+
handleGetRequest({
|
|
38
|
+
endPointURI: "api/auth/userInfo",
|
|
39
|
+
showMask: true,
|
|
40
|
+
successCallBkFn: (response) => {
|
|
41
|
+
setIsLoginInProcess(false);
|
|
42
|
+
if (response != null && response.data != null) {
|
|
43
|
+
const UserSession = {
|
|
44
|
+
...response.data,
|
|
45
|
+
isAuthenticated: true,
|
|
46
|
+
};
|
|
47
|
+
dispatch(UserSessionActions.setAuthenticated(UserSession));
|
|
48
|
+
} else {
|
|
49
|
+
dispatch(UserSessionActions.setUnAuthenticated());
|
|
50
|
+
localStorage.removeItem("TOKEN");
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
failureCallBkFn: () => {
|
|
54
|
+
setIsLoginInProcess(false);
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
} else {
|
|
59
|
+
dispatch(UserSessionActions.setUnAuthenticated());
|
|
60
|
+
setIsLoginInProcess(false);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
const handleLogin = async () => {
|
|
64
|
+
setIsLoginInProcess(true);
|
|
65
|
+
const response = await msalInstance.acquireTokenPopup({
|
|
66
|
+
scopes: appInfo?.azureConfiguration?.scopes,
|
|
67
|
+
});
|
|
68
|
+
if (response?.accessToken) {
|
|
69
|
+
localStorage.setItem("TOKEN", response.accessToken);
|
|
70
|
+
checkUserSession();
|
|
71
|
+
} else {
|
|
72
|
+
setIsLoginInProcess(false);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
const UserSessionState = useSelector((state: any) => state.UserSession.value);
|
|
76
|
+
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
checkUserSession();
|
|
79
|
+
}, [appInfo]);
|
|
80
|
+
|
|
81
|
+
const loginTheme = createTheme({
|
|
82
|
+
components: {
|
|
83
|
+
MuiCssBaseline: {
|
|
84
|
+
styleOverrides: `
|
|
85
|
+
/* Custom Scrollbar */
|
|
86
|
+
* {
|
|
87
|
+
scrollbar-width: thin;
|
|
88
|
+
scrollbar-color: ${
|
|
89
|
+
appInfo.appTheme?.dark?.primaryColor ||
|
|
90
|
+
DARK_THEME_INITIAL_MAIN_COLOR
|
|
91
|
+
} #121212;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* Webkit Browsers */
|
|
95
|
+
*::-webkit-scrollbar {
|
|
96
|
+
width: 12px;
|
|
97
|
+
height: 10px;
|
|
98
|
+
}
|
|
99
|
+
`,
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
palette: {
|
|
103
|
+
mode: appInfo?.loginScreenStyle?.themeMode || "dark",
|
|
104
|
+
primary: {
|
|
105
|
+
main:
|
|
106
|
+
appInfo?.loginScreenStyle?.themeMode === "light"
|
|
107
|
+
? appInfo.appTheme?.light?.primaryColor ||
|
|
108
|
+
LIGHT_THEME_INITIAL_MAIN_COLOR
|
|
109
|
+
: appInfo.appTheme?.dark?.primaryColor ||
|
|
110
|
+
DARK_THEME_INITIAL_MAIN_COLOR,
|
|
111
|
+
},
|
|
112
|
+
secondary: {
|
|
113
|
+
main:
|
|
114
|
+
appInfo?.loginScreenStyle?.themeMode === "light"
|
|
115
|
+
? appInfo.appTheme?.light?.secondaryColor ||
|
|
116
|
+
LIGHT_THEME_INITIAL_SECANDARY_COLOR
|
|
117
|
+
: appInfo.appTheme?.dark?.secondaryColor ||
|
|
118
|
+
DARK_THEME_INITIAL_SECANDARY_COLOR,
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
return (
|
|
123
|
+
<ThemeProvider theme={loginTheme}>
|
|
124
|
+
{UserSessionState.isAuthenticated == false ? (
|
|
125
|
+
<Box
|
|
126
|
+
sx={{
|
|
127
|
+
// position: "relative",
|
|
128
|
+
display: "flex",
|
|
129
|
+
alignItems: "center",
|
|
130
|
+
justifyContent: "center",
|
|
131
|
+
minHeight: "100vh",
|
|
132
|
+
width: "100%",
|
|
133
|
+
backgroundImage: "url('/bg.jpg')",
|
|
134
|
+
backgroundRepeat: "no-repeat",
|
|
135
|
+
backgroundSize: "cover",
|
|
136
|
+
backgroundPosition: "center",
|
|
137
|
+
"&::before": {
|
|
138
|
+
content: '""',
|
|
139
|
+
position: "absolute",
|
|
140
|
+
top: 0,
|
|
141
|
+
left: 0,
|
|
142
|
+
right: 0,
|
|
143
|
+
bottom: 0,
|
|
144
|
+
backgroundColor: "rgba(0, 0, 0, 0.4)", // 👈 controls opacity
|
|
145
|
+
zIndex: 0,
|
|
146
|
+
},
|
|
147
|
+
}}
|
|
148
|
+
>
|
|
149
|
+
<Paper
|
|
150
|
+
sx={{
|
|
151
|
+
display: "flex",
|
|
152
|
+
width: "fit-content",
|
|
153
|
+
padding: 2,
|
|
154
|
+
height: "fit-content",
|
|
155
|
+
borderRadius: 5,
|
|
156
|
+
alignItems: "center",
|
|
157
|
+
justifyContent: "center",
|
|
158
|
+
textAlign: "center",
|
|
159
|
+
zIndex: 1,
|
|
160
|
+
p: 4,
|
|
161
|
+
}}
|
|
162
|
+
>
|
|
163
|
+
<Box
|
|
164
|
+
sx={{
|
|
165
|
+
display: "flex",
|
|
166
|
+
flexDirection: "column",
|
|
167
|
+
alignItems: "center",
|
|
168
|
+
justifyContent: "center",
|
|
169
|
+
}}
|
|
170
|
+
>
|
|
171
|
+
<img src={appInfo?.appLogo} width={150} height={150} />
|
|
172
|
+
<Typography sx={{ m: 1 }} variant="h4" color="textSecondary">
|
|
173
|
+
{appInfo?.appName}
|
|
174
|
+
</Typography>
|
|
175
|
+
<Typography
|
|
176
|
+
sx={{
|
|
177
|
+
paddingRight: 1,
|
|
178
|
+
width: "100%",
|
|
179
|
+
textAlign: "right",
|
|
180
|
+
fontSize: 10,
|
|
181
|
+
}}
|
|
182
|
+
variant="caption"
|
|
183
|
+
color="textSecondary"
|
|
184
|
+
>
|
|
185
|
+
V.{appInfo.appVersion}
|
|
186
|
+
</Typography>
|
|
187
|
+
<Button
|
|
188
|
+
loading={isLoginInProcess}
|
|
189
|
+
onClick={handleLogin}
|
|
190
|
+
variant="contained"
|
|
191
|
+
color="primary"
|
|
192
|
+
sx={{ m: 1 }}
|
|
193
|
+
startIcon={
|
|
194
|
+
<FontAwesomeIcon
|
|
195
|
+
icon={{ iconName: "microsoft", prefix: "fab" }}
|
|
196
|
+
/>
|
|
197
|
+
}
|
|
198
|
+
>
|
|
199
|
+
login
|
|
200
|
+
</Button>
|
|
201
|
+
</Box>
|
|
202
|
+
</Paper>
|
|
203
|
+
</Box>
|
|
204
|
+
) : (
|
|
205
|
+
<Paper
|
|
206
|
+
sx={{
|
|
207
|
+
width: "100%",
|
|
208
|
+
height: "100vh",
|
|
209
|
+
display: "flex",
|
|
210
|
+
alignItems: "center",
|
|
211
|
+
justifyContent: "center",
|
|
212
|
+
}}
|
|
213
|
+
>
|
|
214
|
+
<CircularProgress sx={{ marginRight: 1 }} />
|
|
215
|
+
<div>You will be redirected shortly ... please wait</div>
|
|
216
|
+
</Paper>
|
|
217
|
+
)}
|
|
218
|
+
</ThemeProvider>
|
|
219
|
+
);
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
export default AzureLogin;
|
|
@@ -16,10 +16,13 @@ import { UserSessionActions } from "../../redux/features/common/UserSessionSlice
|
|
|
16
16
|
import {
|
|
17
17
|
DARK_THEME_INITIAL_MAIN_COLOR,
|
|
18
18
|
DARK_THEME_INITIAL_SECANDARY_COLOR,
|
|
19
|
+
LIGHT_THEME_INITIAL_MAIN_COLOR,
|
|
20
|
+
LIGHT_THEME_INITIAL_SECANDARY_COLOR,
|
|
19
21
|
} from "../../util";
|
|
22
|
+
import { AppInfo } from "../../redux/features/common/AppInfoSlice";
|
|
20
23
|
|
|
21
24
|
const Login: React.FC = () => {
|
|
22
|
-
const appInfo = useSelector((state: any) => state.AppInfo.value);
|
|
25
|
+
const appInfo: AppInfo = useSelector((state: any) => state.AppInfo.value);
|
|
23
26
|
const [username, setUsername] = useState("");
|
|
24
27
|
const [password, setPassword] = useState("");
|
|
25
28
|
const [isLoginInProcess, setIsLoginInProcess] = useState(false);
|
|
@@ -89,15 +92,22 @@ const Login: React.FC = () => {
|
|
|
89
92
|
},
|
|
90
93
|
},
|
|
91
94
|
palette: {
|
|
92
|
-
mode: "dark",
|
|
95
|
+
mode: appInfo?.loginScreenStyle?.themeMode || "dark",
|
|
93
96
|
primary: {
|
|
94
97
|
main:
|
|
95
|
-
appInfo
|
|
98
|
+
appInfo?.loginScreenStyle?.themeMode === "light"
|
|
99
|
+
? appInfo.appTheme?.light?.primaryColor ||
|
|
100
|
+
LIGHT_THEME_INITIAL_MAIN_COLOR
|
|
101
|
+
: appInfo.appTheme?.dark?.primaryColor ||
|
|
102
|
+
DARK_THEME_INITIAL_MAIN_COLOR,
|
|
96
103
|
},
|
|
97
104
|
secondary: {
|
|
98
105
|
main:
|
|
99
|
-
appInfo
|
|
100
|
-
|
|
106
|
+
appInfo?.loginScreenStyle?.themeMode === "light"
|
|
107
|
+
? appInfo.appTheme?.light?.secondaryColor ||
|
|
108
|
+
LIGHT_THEME_INITIAL_SECANDARY_COLOR
|
|
109
|
+
: appInfo.appTheme?.dark?.secondaryColor ||
|
|
110
|
+
DARK_THEME_INITIAL_SECANDARY_COLOR,
|
|
101
111
|
},
|
|
102
112
|
},
|
|
103
113
|
});
|
|
@@ -121,6 +131,7 @@ const Login: React.FC = () => {
|
|
|
121
131
|
dispatch(UserSessionActions.setAuthenticated(UserSession));
|
|
122
132
|
} else {
|
|
123
133
|
dispatch(UserSessionActions.setUnAuthenticated());
|
|
134
|
+
localStorage.removeItem("TOKEN");
|
|
124
135
|
}
|
|
125
136
|
} catch (error) {
|
|
126
137
|
dispatch(UserSessionActions.setUnAuthenticated());
|
|
@@ -129,92 +140,127 @@ const Login: React.FC = () => {
|
|
|
129
140
|
}
|
|
130
141
|
};
|
|
131
142
|
useEffect(() => {
|
|
132
|
-
console.log("checking usersession on reload", userSession);
|
|
133
|
-
console.log("checking usersession app info", appInfo);
|
|
134
143
|
checkUserSession();
|
|
135
144
|
}, [appInfo, userSession.isAuthenticated]);
|
|
136
145
|
|
|
137
146
|
return (
|
|
138
147
|
<ThemeProvider theme={loginTheme}>
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
148
|
+
{UserSessionState.isAuthenticated == false ? (
|
|
149
|
+
<Box
|
|
150
|
+
sx={{
|
|
151
|
+
// position: "relative",
|
|
152
|
+
display: "flex",
|
|
153
|
+
alignItems: "center",
|
|
154
|
+
justifyContent: "center",
|
|
155
|
+
minHeight: "100vh",
|
|
156
|
+
width: "100%",
|
|
157
|
+
backgroundImage: "url('/bg.jpg')",
|
|
158
|
+
backgroundRepeat: "no-repeat",
|
|
159
|
+
backgroundSize: "cover",
|
|
160
|
+
backgroundPosition: "center",
|
|
161
|
+
"&::before": {
|
|
162
|
+
content: '""',
|
|
163
|
+
position: "absolute",
|
|
164
|
+
top: 0,
|
|
165
|
+
left: 0,
|
|
166
|
+
right: 0,
|
|
167
|
+
bottom: 0,
|
|
168
|
+
backgroundColor: "rgba(0, 0, 0, 0.4)", // 👈 controls opacity
|
|
169
|
+
zIndex: 0,
|
|
170
|
+
},
|
|
171
|
+
}}
|
|
172
|
+
>
|
|
173
|
+
<Paper
|
|
151
174
|
sx={{
|
|
152
175
|
display: "flex",
|
|
153
|
-
|
|
176
|
+
width: "fit-content",
|
|
177
|
+
padding: 2,
|
|
178
|
+
height: "fit-content",
|
|
179
|
+
borderRadius: 5,
|
|
154
180
|
alignItems: "center",
|
|
155
181
|
justifyContent: "center",
|
|
182
|
+
textAlign: "center",
|
|
183
|
+
zIndex: 1,
|
|
184
|
+
p: 4,
|
|
156
185
|
}}
|
|
157
186
|
>
|
|
158
|
-
<
|
|
159
|
-
<Typography sx={{ m: 1 }} variant="h4" color="textSecondary">
|
|
160
|
-
{appInfo?.appName}
|
|
161
|
-
</Typography>
|
|
162
|
-
<Typography
|
|
187
|
+
<Box
|
|
163
188
|
sx={{
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
189
|
+
display: "flex",
|
|
190
|
+
flexDirection: "column",
|
|
191
|
+
alignItems: "center",
|
|
192
|
+
justifyContent: "center",
|
|
168
193
|
}}
|
|
169
|
-
variant="caption"
|
|
170
|
-
color="textSecondary"
|
|
171
194
|
>
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
195
|
+
<img src={appInfo?.appLogo} width={150} height={150} />
|
|
196
|
+
<Typography sx={{ m: 1 }} variant="h4" color="textSecondary">
|
|
197
|
+
{appInfo?.appName}
|
|
198
|
+
</Typography>
|
|
199
|
+
<Typography
|
|
200
|
+
sx={{
|
|
201
|
+
paddingRight: 1,
|
|
202
|
+
width: "100%",
|
|
203
|
+
textAlign: "right",
|
|
204
|
+
fontSize: 10,
|
|
205
|
+
}}
|
|
206
|
+
variant="caption"
|
|
207
|
+
color="textSecondary"
|
|
208
|
+
>
|
|
209
|
+
V.{appInfo.appVersion}
|
|
210
|
+
</Typography>
|
|
211
|
+
<TextField
|
|
212
|
+
label="username"
|
|
213
|
+
sx={{ width: 300, m: 1 }}
|
|
214
|
+
value={username}
|
|
215
|
+
onChange={(event) => {
|
|
216
|
+
setUsername(event.target.value);
|
|
217
|
+
}}
|
|
218
|
+
onKeyDown={(event) => {
|
|
219
|
+
if (event.key === "Enter") {
|
|
220
|
+
handleLogin();
|
|
221
|
+
}
|
|
222
|
+
}}
|
|
223
|
+
/>
|
|
224
|
+
<TextField
|
|
225
|
+
label="password"
|
|
226
|
+
sx={{ width: 300, m: 1 }}
|
|
227
|
+
value={password}
|
|
228
|
+
type="password"
|
|
229
|
+
onChange={(event) => {
|
|
230
|
+
setPassword(event.target.value);
|
|
231
|
+
}}
|
|
232
|
+
onKeyDown={(event) => {
|
|
233
|
+
if (event.key === "Enter") {
|
|
234
|
+
handleLogin();
|
|
235
|
+
}
|
|
236
|
+
}}
|
|
237
|
+
/>
|
|
238
|
+
<Button
|
|
239
|
+
loading={isLoginInProcess}
|
|
240
|
+
onClick={handleLogin}
|
|
241
|
+
variant="contained"
|
|
242
|
+
color="primary"
|
|
243
|
+
sx={{ m: 1 }}
|
|
244
|
+
>
|
|
245
|
+
login
|
|
246
|
+
</Button>
|
|
247
|
+
</Box>
|
|
248
|
+
</Paper>
|
|
249
|
+
</Box>
|
|
250
|
+
) : (
|
|
251
|
+
<Paper
|
|
252
|
+
sx={{
|
|
253
|
+
width: "100%",
|
|
254
|
+
height: "100vh",
|
|
255
|
+
display: "flex",
|
|
256
|
+
alignItems: "center",
|
|
257
|
+
justifyContent: "center",
|
|
258
|
+
}}
|
|
259
|
+
>
|
|
260
|
+
<CircularProgress sx={{ marginRight: 1 }} />
|
|
261
|
+
<div>You will be redirected shortly ... please wait</div>
|
|
262
|
+
</Paper>
|
|
263
|
+
)}
|
|
218
264
|
</ThemeProvider>
|
|
219
265
|
);
|
|
220
266
|
};
|
|
@@ -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
|
@@ -7,7 +7,18 @@ createRoot(document.getElementById("root")!).render(
|
|
|
7
7
|
enableUINotifications={false}
|
|
8
8
|
appLogo={"/logo.png"}
|
|
9
9
|
appName="UI Base Library"
|
|
10
|
+
loginScreenStyle={{
|
|
11
|
+
themeMode: "dark",
|
|
12
|
+
backgroundImageNameInPublicFolder: "bg.jpg",
|
|
13
|
+
}}
|
|
10
14
|
appVersion="0.0"
|
|
15
|
+
authenticationMethod="AZURE"
|
|
16
|
+
azureConfiguration={{
|
|
17
|
+
frontEndClientId: "c3bbbdbd-f392-4459-b3dd-2351cb07f924",
|
|
18
|
+
tenantId: "9f136fef-4529-475f-98e6-d271eb04eb00",
|
|
19
|
+
redirectURL: "http://localhost:3000",
|
|
20
|
+
scopes: ["api://6008a934-2a32-4776-a3df-1842ac9371da/access_as_user"],
|
|
21
|
+
}}
|
|
11
22
|
businessCommonStoresMetaData={{}}
|
|
12
23
|
businessNavigationItems={[]}
|
|
13
24
|
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,18 @@ export type AppInfo = {
|
|
|
19
19
|
ar: { [key: string]: string };
|
|
20
20
|
en: { [key: string]: string };
|
|
21
21
|
};
|
|
22
|
+
loginScreenStyle?: {
|
|
23
|
+
themeMode: "dark" | "light";
|
|
24
|
+
backgroundImageNameInPublicFolder?: string;
|
|
25
|
+
backgroundColor?: string;
|
|
26
|
+
};
|
|
27
|
+
authenticationMethod: "AZURE" | "APP";
|
|
28
|
+
azureConfiguration?: {
|
|
29
|
+
frontEndClientId: string;
|
|
30
|
+
tenantId: string;
|
|
31
|
+
redirectURL: string;
|
|
32
|
+
scopes: Array<string>;
|
|
33
|
+
};
|
|
22
34
|
businessRoutes?: Array<SystemRoute>;
|
|
23
35
|
businessNavigationItems?: Array<ExtendedTreeItemProps>;
|
|
24
36
|
businessReduxReducers?: { [key: string]: Reducer<any> };
|
|
@@ -41,6 +53,7 @@ const initialState: AppInfoProp = {
|
|
|
41
53
|
value: {
|
|
42
54
|
documentTitle: null,
|
|
43
55
|
apiBaseUrl: null,
|
|
56
|
+
authenticationMethod: "APP",
|
|
44
57
|
appName: null,
|
|
45
58
|
appVersion: null,
|
|
46
59
|
appLogo: null,
|