@asaleh37/ui-base 25.9.17 → 25.9.19

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.17",
3
+ "version": "25.9.19",
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
+ }
@@ -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;
@@ -238,6 +238,7 @@ export type FormElementGroupProps = {
238
238
  formActions?: any;
239
239
  hiddenFields?: string[];
240
240
  disabledFields?: string[];
241
+ formValuesChangeCallBk?: FormValueChangeCallBk;
241
242
  };
242
243
 
243
244
  export type FormValueChangeCallBk = (
@@ -53,6 +53,7 @@ const FormElementGroup: React.FC<FormElementGroupProps> = (
53
53
  formActions={props.formActions}
54
54
  hiddenFields={props.hiddenFields}
55
55
  disabledFields={props.disabledFields}
56
+ formValuesChangeCallBk={props?.formValuesChangeCallBk}
56
57
  />
57
58
  );
58
59
  } else if (element.type === "field" && element.mode === "props") {
@@ -64,6 +65,7 @@ const FormElementGroup: React.FC<FormElementGroupProps> = (
64
65
  formActions={props.formActions}
65
66
  hiddenFields={props.hiddenFields}
66
67
  disabledFields={props.disabledFields}
68
+ formValuesChangeCallBk={props?.formValuesChangeCallBk}
67
69
  />
68
70
  );
69
71
  } else if (element.type === "field" && element.mode === "node") {
@@ -260,6 +260,7 @@ const TemplateForm: React.FC<TemplateFormProps> = (
260
260
  formActions={formActions}
261
261
  hiddenFields={hiddenFields}
262
262
  disabledFields={disabledFields}
263
+ formValuesChangeCallBk={props.formValuesChangeCallBk}
263
264
  />
264
265
  );
265
266
  } else if (
@@ -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",
@@ -32,11 +32,4 @@ export const findNavigationItemById = (
32
32
 
33
33
  export const NavigationItems: TreeViewBaseItem<ExtendedTreeItemProps>[] = [
34
34
  ...AdministrationItems,
35
- {
36
- id: "example",
37
- icon: "wind",
38
- action: "NAVIGATION",
39
- actionPayload: { path: "example" },
40
- label: "Example",
41
- },
42
35
  ];
@@ -2,7 +2,4 @@ import ExampleTrial from "../components/ExampleTrial";
2
2
  import { ADMINISTRATION_ROUTES } from "./administration";
3
3
  import { SystemRoute } from "./types";
4
4
 
5
- export const SYSTEM_ROUTES: Array<SystemRoute> = [
6
- ...ADMINISTRATION_ROUTES,
7
- { path: "example", component: ExampleTrial },
8
- ];
5
+ export const SYSTEM_ROUTES: Array<SystemRoute> = [...ADMINISTRATION_ROUTES];
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
  });