@asaleh37/ui-base 25.9.3 → 25.9.5-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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asaleh37/ui-base",
3
- "version": "25.9.3",
3
+ "version": "25.9.5-1",
4
4
  "description": "",
5
5
  "license": "ISC",
6
6
  "author": "Ahmed Saleh Mohamed",
package/public/bg.jpg ADDED
Binary file
@@ -23,7 +23,7 @@ const PersonGrid: React.FC = () => {
23
23
  );
24
24
  const [data, setData] = useState([]);
25
25
  const apiActions = useApiActions({
26
- findAll: "api/v1/public/person/all",
26
+ commonStoreKey: "persons",
27
27
  deleteById: "api/v1/admin/person",
28
28
  save: "api/v1/admin/person",
29
29
  findById: "api/v1/admin/person",
@@ -276,10 +276,10 @@ const PersonGrid: React.FC = () => {
276
276
  data={data}
277
277
  setData={setData}
278
278
  editMode={{
279
- editMode: "modal",
279
+ editMode: "modal",
280
280
  specs: {
281
281
  modalIcon: "user",
282
- modalTitle: "Person Profile",
282
+ modalTitle: "Person Profile",
283
283
  modalWidth: 300,
284
284
  },
285
285
  }}
@@ -320,7 +320,7 @@ const PersonGrid: React.FC = () => {
320
320
  ]}
321
321
  girdIcon="users"
322
322
  editAction={{
323
- isEnabled: true,
323
+ isEnabled: true,
324
324
  authority: "PERSON_EDIT",
325
325
  preActionValidation: (data) => {
326
326
  if (
@@ -1,11 +1,26 @@
1
1
  import { PublicClientApplication } from "@azure/msal-browser";
2
- import { Box, Button } from "@mui/material";
2
+ import {
3
+ Box,
4
+ Button,
5
+ CircularProgress,
6
+ createTheme,
7
+ Paper,
8
+ Typography,
9
+ } from "@mui/material";
3
10
  import { useDispatch, useSelector } from "react-redux";
4
11
  import { AppInfo } from "../../redux/features/common/AppInfoSlice";
5
12
  import { useAxios } from "../../hooks";
6
13
  import { UserSessionActions } from "../../redux/features/common/UserSessionSlice";
7
- import { useEffect } from "react";
14
+ import { useEffect, useState } from "react";
8
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";
9
24
  interface AzureLoginProps {
10
25
  msalInstance: PublicClientApplication;
11
26
  }
@@ -13,16 +28,17 @@ interface AzureLoginProps {
13
28
  const AzureLogin: React.FC<AzureLoginProps> = ({ msalInstance }) => {
14
29
  const appInfo: AppInfo = useSelector((state: any) => state.AppInfo.value);
15
30
  const userSession = useSelector((state: any) => state.UserSession.value);
31
+ const [isLoginInProcess, setIsLoginInProcess] = useState(false);
16
32
  const { handleGetRequest } = useAxios();
17
33
  const dispatch = useDispatch();
18
34
  const checkUserSession = async () => {
19
- if (appInfo?.apiBaseUrl) {
20
- if (userSession.isAuthenticated == null) {
21
- const token = localStorage.getItem("TOKEN");
35
+ if (localStorage.getItem("TOKEN")) {
36
+ if (appInfo?.apiBaseUrl) {
22
37
  handleGetRequest({
23
38
  endPointURI: "api/auth/userInfo",
24
39
  showMask: true,
25
40
  successCallBkFn: (response) => {
41
+ setIsLoginInProcess(false);
26
42
  if (response != null && response.data != null) {
27
43
  const UserSession = {
28
44
  ...response.data,
@@ -34,36 +50,172 @@ const AzureLogin: React.FC<AzureLoginProps> = ({ msalInstance }) => {
34
50
  localStorage.removeItem("TOKEN");
35
51
  }
36
52
  },
53
+ failureCallBkFn: () => {
54
+ setIsLoginInProcess(false);
55
+ },
37
56
  });
38
57
  }
58
+ } else {
59
+ dispatch(UserSessionActions.setUnAuthenticated());
60
+ setIsLoginInProcess(false);
39
61
  }
40
62
  };
41
63
  const handleLogin = async () => {
64
+ setIsLoginInProcess(true);
42
65
  const response = await msalInstance.acquireTokenPopup({
43
66
  scopes: appInfo?.azureConfiguration?.scopes,
44
67
  });
45
68
  if (response?.accessToken) {
46
69
  localStorage.setItem("TOKEN", response.accessToken);
47
70
  checkUserSession();
71
+ } else {
72
+ setIsLoginInProcess(false);
48
73
  }
49
74
  };
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
- };
75
+ const UserSessionState = useSelector((state: any) => state.UserSession.value);
59
76
 
60
- // useEffect(()=>{
61
- // handleLogin()
62
- // },[])
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
+ });
63
122
  return (
64
- <Box>
65
- <Button onClick={handleLogin}>Azure Login </Button>
66
- </Box>
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>
67
219
  );
68
220
  };
69
221
 
@@ -140,39 +140,50 @@ const Login: React.FC = () => {
140
140
  }
141
141
  };
142
142
  useEffect(() => {
143
- console.log("checking usersession on reload", userSession);
144
- console.log("checking usersession app info", appInfo);
145
143
  checkUserSession();
146
144
  }, [appInfo, userSession.isAuthenticated]);
147
145
 
148
146
  return (
149
147
  <ThemeProvider theme={loginTheme}>
150
- <Box
151
- sx={{
152
- minHeight: "100vh", // full page height
153
- width: "100%",
154
- display: "flex",
155
- alignItems: "center",
156
- justifyContent: "center",
157
- background: appInfo?.loginScreenStyle?.backgroundColor,
158
- backgroundImage: `url('/${appInfo?.loginScreenStyle?.backgroundImageNameInPublicFolder}')`,
159
- backgroundRepeat: "no-repeat",
160
- backgroundSize: "cover", // 🔥 makes it responsive
161
- backgroundPosition: "center", // keeps it centered
162
- }}
163
- >
164
- <Paper
148
+ {UserSessionState.isAuthenticated == false ? (
149
+ <Box
165
150
  sx={{
151
+ // position: "relative",
166
152
  display: "flex",
167
- width: "fit-content",
168
- padding: 2,
169
- height: "fit-content",
170
- borderRadius: 5,
171
153
  alignItems: "center",
172
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
+ },
173
171
  }}
174
172
  >
175
- {UserSessionState.isAuthenticated == false ? (
173
+ <Paper
174
+ sx={{
175
+ display: "flex",
176
+ width: "fit-content",
177
+ padding: 2,
178
+ height: "fit-content",
179
+ borderRadius: 5,
180
+ alignItems: "center",
181
+ justifyContent: "center",
182
+ textAlign: "center",
183
+ zIndex: 1,
184
+ p: 4,
185
+ }}
186
+ >
176
187
  <Box
177
188
  sx={{
178
189
  display: "flex",
@@ -234,14 +245,22 @@ const Login: React.FC = () => {
234
245
  login
235
246
  </Button>
236
247
  </Box>
237
- ) : (
238
- <>
239
- <CircularProgress sx={{ marginRight: 1 }} />
240
- <div>You will be redirected shortly ... please wait</div>
241
- </>
242
- )}
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>
243
262
  </Paper>
244
- </Box>
263
+ )}
245
264
  </ThemeProvider>
246
265
  );
247
266
  };
@@ -30,7 +30,7 @@ const FormElementField: React.FC<FormElementFieldProps> = (
30
30
  return element?.fieldInfo?.fieldLabel;
31
31
  }
32
32
  };
33
- return !element.hiddenFields.includes(fieldName) ? (
33
+ return (
34
34
  <Grid2
35
35
  size={
36
36
  props?.formProps?.fieldSize || {
@@ -49,16 +49,8 @@ const FormElementField: React.FC<FormElementFieldProps> = (
49
49
  {...props.muiTextFieldProps}
50
50
  fullWidth
51
51
  type={fieldType}
52
- disabled={
53
- props?.disabled || element.disabledFields.includes(fieldName)
54
- ? true
55
- : false
56
- }
57
- // hidden={
58
- // props?.hidden || element.hiddenFields.includes(fieldName)
59
- // ? true
60
- // : false
61
- // }
52
+ disabled={element.disabledFields.includes(fieldName)}
53
+ hidden={element.hiddenFields.includes(fieldName)}
62
54
  label={getFieldLabel()}
63
55
  value={formValues[fieldName]}
64
56
  onChange={(event) => {
@@ -99,16 +91,8 @@ const FormElementField: React.FC<FormElementFieldProps> = (
99
91
  <Datefield
100
92
  format={props?.dateFormat || DATE_FORMAT}
101
93
  sx={props?.formProps?.style || { width: "100%" }}
102
- disabled={
103
- props?.disabled || element.disabledFields.includes(fieldName)
104
- ? true
105
- : false
106
- }
107
- // hidden={
108
- // props?.hidden || element.hiddenFields.includes(fieldName)
109
- // ? true
110
- // : false
111
- // }
94
+ disabled={element.disabledFields.includes(fieldName)}
95
+ hidden={element.hiddenFields.includes(fieldName)}
112
96
  label={getFieldLabel()}
113
97
  onChangeCallBack={(v: any) => {
114
98
  formManager.setValue(fieldName, v);
@@ -132,11 +116,8 @@ const FormElementField: React.FC<FormElementFieldProps> = (
132
116
  <DatetimeField
133
117
  format={props?.dateFormat || DATE_TIME_FORMAT}
134
118
  sx={props?.formProps?.style || { width: "100%" }}
135
- disabled={
136
- props?.disabled || element.disabledFields.includes(fieldName)
137
- ? true
138
- : false
139
- }
119
+ disabled={element.disabledFields.includes(fieldName)}
120
+ hidden={element.hiddenFields.includes(fieldName)}
140
121
  label={getFieldLabel()}
141
122
  onChangeCallBack={(v: any) => {
142
123
  formManager.setValue(fieldName, v);
@@ -150,11 +131,6 @@ const FormElementField: React.FC<FormElementFieldProps> = (
150
131
  );
151
132
  }
152
133
  }}
153
- // hidden={
154
- // props?.hidden || element.hiddenFields.includes(fieldName)
155
- // ? true
156
- // : false
157
- // }
158
134
  value={formValues[fieldName]}
159
135
  error={formManager.formState.errors[fieldName] != undefined}
160
136
  errorMessage={formManager?.formState?.errors[
@@ -176,35 +152,19 @@ const FormElementField: React.FC<FormElementFieldProps> = (
176
152
  );
177
153
  }
178
154
  }}
179
- // hidden={
180
- // props?.hidden || element.hiddenFields.includes(fieldName)
181
- // ? true
182
- // : false
183
- // }
184
155
  value={formValues[fieldName]}
185
156
  checkedValue={props?.checkedValue || true}
186
157
  unCheckedValue={props?.unCheckedValue || false}
187
- disabled={
188
- props?.disabled || element.disabledFields.includes(fieldName)
189
- ? true
190
- : false
191
- }
158
+ disabled={element.disabledFields.includes(fieldName)}
159
+ hidden={element.hiddenFields.includes(fieldName)}
192
160
  sx={props?.formProps?.style}
193
161
  />
194
162
  ) : props?.fieldType === "combobox" ? (
195
163
  <ComboBox
196
164
  sx={props?.formProps?.style || { width: "100%" }}
197
165
  label={getFieldLabel()}
198
- disabled={
199
- props?.disabled || element.disabledFields.includes(fieldName)
200
- ? true
201
- : false
202
- }
203
- // hidden={
204
- // props?.hidden || element.hiddenFields.includes(fieldName)
205
- // ? true
206
- // : false
207
- // }
166
+ disabled={element.disabledFields.includes(fieldName)}
167
+ hidden={element.hiddenFields.includes(fieldName)}
208
168
  onChangeCallBack={(v: any, selectedRecord: any) => {
209
169
  let newValue = null;
210
170
  if (v) {
@@ -234,16 +194,8 @@ const FormElementField: React.FC<FormElementFieldProps> = (
234
194
  <SystemLookupCombobox
235
195
  sx={props?.formProps?.style || { width: "100%" }}
236
196
  label={getFieldLabel()}
237
- disabled={
238
- props?.disabled || element.disabledFields.includes(fieldName)
239
- ? true
240
- : false
241
- }
242
- // hidden={
243
- // props?.hidden || element.hiddenFields.includes(fieldName)
244
- // ? true
245
- // : false
246
- // }
197
+ disabled={element.disabledFields.includes(fieldName)}
198
+ hidden={element.hiddenFields.includes(fieldName)}
247
199
  onChangeCallBack={(v: any, selectedRecord: any) => {
248
200
  let newValue = null;
249
201
  if (v) {
@@ -269,8 +221,6 @@ const FormElementField: React.FC<FormElementFieldProps> = (
269
221
  />
270
222
  ) : null}
271
223
  </Grid2>
272
- ) : (
273
- <></>
274
224
  );
275
225
  } else {
276
226
  return <></>;
@@ -47,11 +47,18 @@ const TemplateForm: React.FC<TemplateFormProps> = (
47
47
  const { t } = useTranslation();
48
48
  const fields = getAllFields(props.elements);
49
49
  const initiallyHiddenFields = [];
50
+ const initiallyDisabledFields = [];
50
51
  for (const field of fields) {
51
52
  if (field?.hidden) {
52
53
  initiallyHiddenFields.push(field.fieldName);
53
54
  }
55
+ if (field?.disabled) {
56
+ initiallyDisabledFields.push(field.fieldName);
57
+ }
54
58
  }
59
+ const [disabledFields, setDisabledFields] = useState<string[]>(
60
+ initiallyDisabledFields
61
+ );
55
62
  const [hiddenFields, setHiddenFields] = useState<string[]>(
56
63
  initiallyHiddenFields
57
64
  );
@@ -65,7 +72,7 @@ const TemplateForm: React.FC<TemplateFormProps> = (
65
72
  initialValues[element.props.fieldName] = element.props.defaultValue;
66
73
  }
67
74
  }
68
- const [disabledFields, setDisabledFields] = useState<string[]>([]);
75
+
69
76
  let formSchema = null;
70
77
  if (props?.validationSchema) {
71
78
  formSchema = props.validationSchema;
package/src/main.tsx CHANGED
@@ -8,11 +8,11 @@ createRoot(document.getElementById("root")!).render(
8
8
  appLogo={"/logo.png"}
9
9
  appName="UI Base Library"
10
10
  loginScreenStyle={{
11
- themeMode: "light",
11
+ themeMode: "dark",
12
12
  backgroundImageNameInPublicFolder: "bg.jpg",
13
13
  }}
14
14
  appVersion="0.0"
15
- authenticationMethod="APP"
15
+ authenticationMethod="AZURE"
16
16
  azureConfiguration={{
17
17
  frontEndClientId: "c3bbbdbd-f392-4459-b3dd-2351cb07f924",
18
18
  tenantId: "9f136fef-4529-475f-98e6-d271eb04eb00",
@@ -145,4 +145,9 @@ export const ADMINISTRATION_STORES: CommonStores = {
145
145
  authority: "SYSTEM_ADMIN",
146
146
  url: "api/v1/admin/systemapplicationrole/all",
147
147
  },
148
+ persons: {
149
+ autoLoad: true,
150
+ data: [],
151
+ url: "api/v1/public/person/all",
152
+ },
148
153
  };