@asaleh37/ui-base 25.9.16-2 → 25.9.17-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/index.html CHANGED
@@ -2,6 +2,13 @@
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="UTF-8" />
5
+ <link rel="manifest" href="/manifest.json" />
6
+ <meta name="mobile-web-app-capable" content="yes" />
7
+ <meta name="apple-mobile-web-app-capable" content="yes" />
8
+ <meta
9
+ name="apple-mobile-web-app-status-bar-style"
10
+ content="black-translucent"
11
+ />
5
12
  <link rel="icon" type="image/svg+xml" href="/logo.png" />
6
13
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
14
  <title>Loading...</title>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asaleh37/ui-base",
3
- "version": "25.9.16-2",
3
+ "version": "25.9.17-1",
4
4
  "description": "",
5
5
  "license": "ISC",
6
6
  "author": "Ahmed Saleh Mohamed",
@@ -0,0 +1,21 @@
1
+ {
2
+ "short_name": "MyApp",
3
+ "name": "My React App",
4
+ "start_url": ".",
5
+ "display": "standalone",
6
+ "background_color": "#ffffff",
7
+ "theme_color": "#ffffff",
8
+ "orientation": "portrait",
9
+ "icons": [
10
+ {
11
+ "src": "icon-192x192.png",
12
+ "sizes": "192x192",
13
+ "type": "image/png"
14
+ },
15
+ {
16
+ "src": "icon-512x512.png",
17
+ "sizes": "512x512",
18
+ "type": "image/png"
19
+ }
20
+ ]
21
+ }
@@ -18,13 +18,17 @@ import { MsalProvider } from "@azure/msal-react";
18
18
 
19
19
  const App: React.FC<AppInfo> = (props: AppInfo) => {
20
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
- });
21
+ let msalInstance;
22
+ if (props?.authenticationMethod === "AZURE") {
23
+ msalInstance = new PublicClientApplication({
24
+ auth: {
25
+ clientId: props?.azureConfiguration?.frontEndClientId,
26
+ authority: `https://login.microsoftonline.com/${props?.azureConfiguration?.tenantId}`,
27
+ redirectUri: props?.azureConfiguration?.redirectURL,
28
+ },
29
+ });
30
+ }
31
+
28
32
  LicenseInfo.setLicenseKey(props.muiPremiumKey);
29
33
  const LightThemeOptions: ThemeOptions = {
30
34
  components: {
@@ -0,0 +1,24 @@
1
+ import { useApiActions } from "../hooks";
2
+ import { FormElementProps, TemplateForm } from "./templates";
3
+
4
+ const ExampleTrial: React.FC = () => {
5
+ const formElements: FormElementProps[] = [
6
+ {
7
+ mode: "props",
8
+ type: "field",
9
+ props: {
10
+ fieldLabel: "test",
11
+ fieldName: "test",
12
+ fieldType: "combobox",
13
+ commonStoreKey: "SystemParameterTypes",
14
+ optionValueField: "value",
15
+ optionDisplayField: "value",
16
+ },
17
+ },
18
+ ];
19
+ const apiActions = useApiActions({});
20
+
21
+ return <TemplateForm apiActions={apiActions} elements={formElements} />;
22
+ };
23
+
24
+ export default ExampleTrial;
@@ -0,0 +1,229 @@
1
+ import {
2
+ Box,
3
+ Button,
4
+ CircularProgress,
5
+ createTheme,
6
+ Paper,
7
+ TextField,
8
+ Typography,
9
+ } from "@mui/material";
10
+ import { useDispatch, useSelector } from "react-redux";
11
+ import { ThemeProvider } from "@emotion/react";
12
+ import { useEffect, useState } from "react";
13
+ import axios from "axios";
14
+ import { toast } from "react-toastify";
15
+ import { UserSessionActions } from "../../redux/features/common/UserSessionSlice";
16
+ import {
17
+ DARK_THEME_INITIAL_MAIN_COLOR,
18
+ DARK_THEME_INITIAL_SECANDARY_COLOR,
19
+ LIGHT_THEME_INITIAL_MAIN_COLOR,
20
+ LIGHT_THEME_INITIAL_SECANDARY_COLOR,
21
+ } from "../../util";
22
+ import { AppInfo } from "../../redux/features/common/AppInfoSlice";
23
+ const MobileLogin: React.FC = () => {
24
+ const appInfo: AppInfo = useSelector((state: any) => state.AppInfo.value);
25
+ const [username, setUsername] = useState("");
26
+ const [password, setPassword] = useState("");
27
+ const [isLoginInProcess, setIsLoginInProcess] = useState(false);
28
+ const UserSessionState = useSelector((state: any) => state.UserSession.value);
29
+ const dispatch = useDispatch();
30
+ const handleLogin = async () => {
31
+ if (username == null || username == "") {
32
+ toast.error("username is required to proceed");
33
+ return;
34
+ }
35
+ if (password == null || password == "") {
36
+ toast.error("password is required to proceed");
37
+ return;
38
+ }
39
+ setIsLoginInProcess(true);
40
+ let response: any = null;
41
+ try {
42
+ response = await axios.post(
43
+ `${appInfo.apiBaseUrl}/api/auth/login`,
44
+ {
45
+ username,
46
+ password,
47
+ },
48
+ {
49
+ withCredentials: true,
50
+ }
51
+ );
52
+ if (response.data != null && response.data !== "") {
53
+ setIsLoginInProcess(false);
54
+ const UserSession = {
55
+ ...response.data,
56
+ isAuthenticated: true,
57
+ };
58
+ if (response?.data?.token) {
59
+ localStorage.setItem("TOKEN", response.data.token);
60
+ }
61
+ dispatch(UserSessionActions.setAuthenticated(UserSession));
62
+ }
63
+ } catch (e: any) {
64
+ setIsLoginInProcess(false);
65
+ toast.error(
66
+ e?.response?.data ||
67
+ "failed to authenticate, contact your administrator"
68
+ );
69
+ }
70
+ };
71
+ const userSession = useSelector((state: any) => state.UserSession.value);
72
+ const loginTheme = createTheme({
73
+ components: {
74
+ MuiCssBaseline: {
75
+ styleOverrides: `
76
+ /* Custom Scrollbar */
77
+ * {
78
+ scrollbar-width: thin;
79
+ scrollbar-color: ${
80
+ appInfo.appTheme?.dark?.primaryColor ||
81
+ DARK_THEME_INITIAL_MAIN_COLOR
82
+ } #121212;
83
+ }
84
+
85
+ /* Webkit Browsers */
86
+ *::-webkit-scrollbar {
87
+ width: 12px;
88
+ height: 10px;
89
+ }
90
+ `,
91
+ },
92
+ },
93
+ palette: {
94
+ mode: appInfo?.loginScreenStyle?.themeMode || "dark",
95
+ primary: {
96
+ main:
97
+ appInfo?.loginScreenStyle?.themeMode === "light"
98
+ ? appInfo.appTheme?.light?.primaryColor ||
99
+ LIGHT_THEME_INITIAL_MAIN_COLOR
100
+ : appInfo.appTheme?.dark?.primaryColor ||
101
+ DARK_THEME_INITIAL_MAIN_COLOR,
102
+ },
103
+ secondary: {
104
+ main:
105
+ appInfo?.loginScreenStyle?.themeMode === "light"
106
+ ? appInfo.appTheme?.light?.secondaryColor ||
107
+ LIGHT_THEME_INITIAL_SECANDARY_COLOR
108
+ : appInfo.appTheme?.dark?.secondaryColor ||
109
+ DARK_THEME_INITIAL_SECANDARY_COLOR,
110
+ },
111
+ },
112
+ });
113
+ const checkUserSession = async () => {
114
+ if (appInfo?.apiBaseUrl) {
115
+ if (userSession.isAuthenticated == null) {
116
+ const token = localStorage.getItem("TOKEN");
117
+ try {
118
+ let response = await axios.get(
119
+ `${appInfo.apiBaseUrl}/api/auth/userInfo`,
120
+ {
121
+ withCredentials: true,
122
+ headers: { Authorization: `Bearer ${token}` },
123
+ }
124
+ );
125
+ if (response != null && response.data != null) {
126
+ const UserSession = {
127
+ ...response.data,
128
+ isAuthenticated: true,
129
+ };
130
+ dispatch(UserSessionActions.setAuthenticated(UserSession));
131
+ } else {
132
+ dispatch(UserSessionActions.setUnAuthenticated());
133
+ localStorage.removeItem("TOKEN");
134
+ }
135
+ } catch (error) {
136
+ dispatch(UserSessionActions.setUnAuthenticated());
137
+ }
138
+ }
139
+ }
140
+ };
141
+ useEffect(() => {
142
+ checkUserSession();
143
+ }, [appInfo, userSession.isAuthenticated]);
144
+
145
+ return (
146
+ <ThemeProvider theme={loginTheme}>
147
+ {UserSessionState.isAuthenticated == false ? (
148
+ <Paper
149
+ sx={{
150
+ display: "flex",
151
+ flexDirection: "column",
152
+ alignItems: "center",
153
+ justifyContent: "center",
154
+ height: "100vh",
155
+ width: "100%",
156
+ }}
157
+ >
158
+ <img src={appInfo?.appLogo} width={70} height={70} />
159
+ <Typography sx={{ m: 1 }} variant="caption" color="textSecondary">
160
+ {appInfo?.appName}
161
+ </Typography>
162
+ <Typography
163
+ sx={{
164
+ paddingRight: 1,
165
+ width: 200,
166
+ textAlign: "right",
167
+ fontSize: 10,
168
+ }}
169
+ variant="caption"
170
+ color="textSecondary"
171
+ >
172
+ V.{appInfo.appVersion}
173
+ </Typography>
174
+ <TextField
175
+ label="username"
176
+ sx={{ width: 200, m: 1 }}
177
+ value={username}
178
+ onChange={(event) => {
179
+ setUsername(event.target.value);
180
+ }}
181
+ onKeyDown={(event) => {
182
+ if (event.key === "Enter") {
183
+ handleLogin();
184
+ }
185
+ }}
186
+ />
187
+ <TextField
188
+ label="password"
189
+ sx={{ width: 200, m: 1 }}
190
+ value={password}
191
+ type="password"
192
+ onChange={(event) => {
193
+ setPassword(event.target.value);
194
+ }}
195
+ onKeyDown={(event) => {
196
+ if (event.key === "Enter") {
197
+ handleLogin();
198
+ }
199
+ }}
200
+ />
201
+ <Button
202
+ loading={isLoginInProcess}
203
+ onClick={handleLogin}
204
+ variant="contained"
205
+ color="primary"
206
+ sx={{ m: 1 }}
207
+ >
208
+ login
209
+ </Button>
210
+ </Paper>
211
+ ) : (
212
+ <Paper
213
+ sx={{
214
+ width: "100%",
215
+ height: "100vh",
216
+ display: "flex",
217
+ alignItems: "center",
218
+ justifyContent: "center",
219
+ }}
220
+ >
221
+ <CircularProgress sx={{ marginRight: 1 }} />
222
+ <div>You will be redirected shortly ... please wait</div>
223
+ </Paper>
224
+ )}
225
+ </ThemeProvider>
226
+ );
227
+ };
228
+
229
+ export default MobileLogin;
@@ -17,6 +17,7 @@ import NoLicenseComponent from "../components/common/NoLicenseComponent";
17
17
  import { msalInstance } from "../components/msalConfig";
18
18
  import { PublicClientApplication } from "@azure/msal-browser";
19
19
  import AzureLogin from "../components/common/AzureLogin";
20
+ import MobileLogin from "../components/common/MobileLogin";
20
21
 
21
22
  const Main = styled("main", {
22
23
  shouldForwardProp: (prop) => prop !== "open",
@@ -89,8 +90,10 @@ const Layout: React.FC<LayoutProps> = ({ msalInstance }) => {
89
90
  </Main>
90
91
  ) : appInfo.authenticationMethod === "AZURE" ? (
91
92
  <AzureLogin msalInstance={msalInstance} />
92
- ) : (
93
+ ) : !isMobile ? (
93
94
  <Login />
95
+ ) : (
96
+ <MobileLogin />
94
97
  )}
95
98
  </BrowserRouter>
96
99
  );
package/src/main.tsx CHANGED
@@ -3,7 +3,7 @@ import { BaseApp } from "./components";
3
3
 
4
4
  createRoot(document.getElementById("root")!).render(
5
5
  <BaseApp
6
- apiBaseUrl="http://localhost:8080/api-base"
6
+ apiBaseUrl="http://10.14.22.13:8080/api-base"
7
7
  enableUINotifications={false}
8
8
  appLogo={"/logo.png"}
9
9
  appName="UI Base Library"
@@ -12,7 +12,7 @@ createRoot(document.getElementById("root")!).render(
12
12
  backgroundImageNameInPublicFolder: "bg.jpg",
13
13
  }}
14
14
  appVersion="0.0"
15
- authenticationMethod="AZURE"
15
+ authenticationMethod="APP"
16
16
  azureConfiguration={{
17
17
  frontEndClientId: "c3bbbdbd-f392-4459-b3dd-2351cb07f924",
18
18
  tenantId: "9f136fef-4529-475f-98e6-d271eb04eb00",
@@ -31,5 +31,5 @@ export const findNavigationItemById = (
31
31
  };
32
32
 
33
33
  export const NavigationItems: TreeViewBaseItem<ExtendedTreeItemProps>[] = [
34
- ...AdministrationItems
34
+ ...AdministrationItems,
35
35
  ];
@@ -1,4 +1,4 @@
1
-
1
+ import ExampleTrial from "../components/ExampleTrial";
2
2
  import { ADMINISTRATION_ROUTES } from "./administration";
3
3
  import { SystemRoute } from "./types";
4
4
 
package/vite.config.ts CHANGED
@@ -19,6 +19,6 @@ export default defineConfig({
19
19
  },
20
20
  },
21
21
  server: {
22
- port: 3000,
22
+ port: 8082,
23
23
  },
24
24
  });