@asaleh37/ui-base 25.8.1-4 → 25.8.1-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/.github/workflows/publish-npm.yml +1 -1
- package/dist/index.d.ts +20 -4
- package/dist/index.js +7 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +7 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/components/App.tsx +11 -11
- package/src/components/common/Login.tsx +7 -0
- package/src/components/common/NoLicenseComponent.tsx +79 -0
- package/src/components/index.ts +0 -3
- package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormElementField.tsx +32 -3
- package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/CheckBox.tsx +2 -0
- package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/ComboBox.tsx +5 -1
- package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/Datefield.tsx +6 -1
- package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/DatetimeField.tsx +7 -0
- package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/SystemLookupCombobox.tsx +1 -0
- package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/TemplateTextField.tsx +2 -1
- package/src/components/templates/DataEntryTemplates/TemplateDataGrid/TemplateGrid.tsx +3 -1
- package/src/components/templates/index.ts +2 -0
- package/src/hooks/UseConfirmationWindow.tsx +2 -0
- package/src/hooks/index.ts +14 -0
- package/src/hooks/useAxios.tsx +13 -0
- package/src/layout/Layout.tsx +4 -6
- package/src/locales/arabic/adminLocalsAr.json +2 -1
- package/src/locales/english/adminLocalsEn.json +1 -0
- package/src/main.tsx +1 -1
- package/src/navigationItems/Administration/adminNavigationItems.tsx +9 -1
- package/src/redux/features/administration/AdministrationStoresMetaData.ts +3 -3
- package/src/redux/features/common/AppInfoSlice.ts +7 -0
- package/src/routes/index.ts +1 -7
- package/src/util/index.ts +3 -0
- package/tsconfig.json +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@asaleh37/ui-base",
|
|
3
|
-
"version": "25.8.1
|
|
3
|
+
"version": "25.8.15.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"author": "Ahmed Saleh Mohamed",
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
"stylis-plugin-rtl": "^2.1.1",
|
|
114
114
|
"zod": "^3.24.2"
|
|
115
115
|
},
|
|
116
|
-
"dependencies": {
|
|
116
|
+
"dependencies": {
|
|
117
117
|
"@rollup/plugin-json": "^6.1.0",
|
|
118
118
|
"rollup-plugin-terser": "^7.0.2"
|
|
119
119
|
}
|
package/src/components/App.tsx
CHANGED
|
@@ -89,17 +89,6 @@ const App: React.FC<AppInfo> = (props: AppInfo) => {
|
|
|
89
89
|
},
|
|
90
90
|
};
|
|
91
91
|
|
|
92
|
-
let commonStores = {};
|
|
93
|
-
if (props.enableAdministrationModule) {
|
|
94
|
-
commonStores = { ...ADMINISTRATION_STORES };
|
|
95
|
-
}
|
|
96
|
-
if (props.businessCommonStoresMetaData) {
|
|
97
|
-
commonStores = {
|
|
98
|
-
...commonStores,
|
|
99
|
-
...props.businessCommonStoresMetaData,
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
dispatch(setStoresMetaData(commonStores));
|
|
103
92
|
const AppLayoutState = useSelector((state: any) => state.AppLayout);
|
|
104
93
|
let themeOptions = { ...LightThemeOptions };
|
|
105
94
|
if (AppLayoutState.themeMode === "dark") {
|
|
@@ -112,6 +101,17 @@ const App: React.FC<AppInfo> = (props: AppInfo) => {
|
|
|
112
101
|
useEffect(() => {
|
|
113
102
|
document.title = props.documentTitle;
|
|
114
103
|
dispatch(AppInfoActions.setAppInfo(props));
|
|
104
|
+
let commonStores = {};
|
|
105
|
+
if (props.enableAdministrationModule) {
|
|
106
|
+
commonStores = { ...ADMINISTRATION_STORES };
|
|
107
|
+
}
|
|
108
|
+
if (props.businessCommonStoresMetaData) {
|
|
109
|
+
commonStores = {
|
|
110
|
+
...commonStores,
|
|
111
|
+
...props.businessCommonStoresMetaData,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
dispatch(setStoresMetaData(commonStores));
|
|
115
115
|
}, []);
|
|
116
116
|
return (
|
|
117
117
|
<ThemeProvider theme={theme}>
|
|
@@ -126,6 +126,13 @@ const Login: React.FC = () => {
|
|
|
126
126
|
useEffect(() => {
|
|
127
127
|
checkUserSession();
|
|
128
128
|
}, [appInfo]);
|
|
129
|
+
|
|
130
|
+
useEffect(() => {
|
|
131
|
+
if (userSession.isAuthenticated === null) {
|
|
132
|
+
console.log("checking usersession on reload", userSession);
|
|
133
|
+
checkUserSession();
|
|
134
|
+
}
|
|
135
|
+
}, [userSession.isAuthenticated]);
|
|
129
136
|
return (
|
|
130
137
|
<ThemeProvider theme={loginTheme}>
|
|
131
138
|
<Paper
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { Box, Typography } from "@mui/material";
|
|
2
|
+
import {
|
|
3
|
+
AppInfo,
|
|
4
|
+
LicenseCheckObject,
|
|
5
|
+
} from "../../redux/features/common/AppInfoSlice";
|
|
6
|
+
import { useSelector } from "react-redux";
|
|
7
|
+
import { useEffect, useState } from "react";
|
|
8
|
+
import { useAxios } from "../../hooks";
|
|
9
|
+
|
|
10
|
+
const NoLicenseComponent: React.FC = () => {
|
|
11
|
+
const [licenseCheckObj, setLicenseCheckObject] = useState<LicenseCheckObject>(
|
|
12
|
+
{ isLicensed: true, lastLicenseCheckMessage: "", lastLicenseCheckTime: "" }
|
|
13
|
+
);
|
|
14
|
+
const { handleGetRequest } = useAxios();
|
|
15
|
+
const appInfo: AppInfo = useSelector((state: any) => state.AppInfo.value);
|
|
16
|
+
const checkSystemLicense = async () => {
|
|
17
|
+
if (appInfo?.checkLicense?.endpoint) {
|
|
18
|
+
await handleGetRequest({
|
|
19
|
+
endPointURI: appInfo.checkLicense?.endpoint,
|
|
20
|
+
successCallBkFn: (response) => {
|
|
21
|
+
setLicenseCheckObject(response.data);
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
if (appInfo?.checkLicense?.endpoint) {
|
|
29
|
+
const interval = appInfo?.checkLicense?.interval || 60000;
|
|
30
|
+
const intervalId = setInterval(() => {
|
|
31
|
+
checkSystemLicense();
|
|
32
|
+
}, interval);
|
|
33
|
+
return () => {
|
|
34
|
+
clearInterval(intervalId);
|
|
35
|
+
console.log("Interval cleared");
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}, [appInfo]);
|
|
39
|
+
return !licenseCheckObj.isLicensed ? (
|
|
40
|
+
<Box
|
|
41
|
+
sx={{
|
|
42
|
+
flex: 1,
|
|
43
|
+
width: "100%",
|
|
44
|
+
height: "100%",
|
|
45
|
+
display: "flex",
|
|
46
|
+
flexDirection: "column",
|
|
47
|
+
alignItems: "center",
|
|
48
|
+
justifyContent: "center",
|
|
49
|
+
position: "fixed",
|
|
50
|
+
top: 0,
|
|
51
|
+
background: "rgba(235, 235, 235, 0.8)",
|
|
52
|
+
left: 0,
|
|
53
|
+
zIndex: 9999,
|
|
54
|
+
}}
|
|
55
|
+
>
|
|
56
|
+
<img src={appInfo.appLogo} style={{ height: 200, width: 200 }} />
|
|
57
|
+
<Typography variant="h5">
|
|
58
|
+
{appInfo.appName} - {appInfo.appVersion}
|
|
59
|
+
</Typography>
|
|
60
|
+
<Typography variant="h6" color="error">
|
|
61
|
+
Your license is missing or has expired.
|
|
62
|
+
</Typography>
|
|
63
|
+
<Typography variant="h6" color="error">
|
|
64
|
+
Please reach out to your vendor for assistance.
|
|
65
|
+
</Typography>
|
|
66
|
+
<Typography>
|
|
67
|
+
License Check @{licenseCheckObj?.lastLicenseCheckTime || "--------"}
|
|
68
|
+
</Typography>
|
|
69
|
+
<Typography>
|
|
70
|
+
License Check Result :{" "}
|
|
71
|
+
{licenseCheckObj?.lastLicenseCheckMessage || "--------"}
|
|
72
|
+
</Typography>
|
|
73
|
+
</Box>
|
|
74
|
+
) : (
|
|
75
|
+
<></>
|
|
76
|
+
);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export default NoLicenseComponent;
|
package/src/components/index.ts
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
export { useDispatch, useSelector } from "react-redux";
|
|
2
|
-
export { useParams as useParams } from "react-router-dom";
|
|
3
1
|
export * from "./BaseApp";
|
|
4
2
|
export * from "@mui/material";
|
|
5
|
-
export * from "zod";
|
|
6
3
|
export * from "@mui/lab";
|
|
7
4
|
export { toast } from "react-toastify";
|
|
8
5
|
export { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
@@ -46,7 +46,11 @@ const FormElementField: React.FC<FormElementFieldProps> = (
|
|
|
46
46
|
? true
|
|
47
47
|
: false
|
|
48
48
|
}
|
|
49
|
-
hidden={
|
|
49
|
+
hidden={
|
|
50
|
+
props?.hidden || element.hiddenFields.includes(fieldName)
|
|
51
|
+
? true
|
|
52
|
+
: false
|
|
53
|
+
}
|
|
50
54
|
label={props?.fieldLabel}
|
|
51
55
|
value={formValues[fieldName]}
|
|
52
56
|
onChange={(event) => {
|
|
@@ -90,6 +94,11 @@ const FormElementField: React.FC<FormElementFieldProps> = (
|
|
|
90
94
|
? true
|
|
91
95
|
: false
|
|
92
96
|
}
|
|
97
|
+
hidden={
|
|
98
|
+
props?.hidden || element.hiddenFields.includes(fieldName)
|
|
99
|
+
? true
|
|
100
|
+
: false
|
|
101
|
+
}
|
|
93
102
|
label={props?.fieldLabel}
|
|
94
103
|
onChangeCallBack={(v: any) => {
|
|
95
104
|
formManager.setValue(fieldName, v);
|
|
@@ -127,6 +136,11 @@ const FormElementField: React.FC<FormElementFieldProps> = (
|
|
|
127
136
|
);
|
|
128
137
|
}
|
|
129
138
|
}}
|
|
139
|
+
hidden={
|
|
140
|
+
props?.hidden || element.hiddenFields.includes(fieldName)
|
|
141
|
+
? true
|
|
142
|
+
: false
|
|
143
|
+
}
|
|
130
144
|
value={formValues[fieldName]}
|
|
131
145
|
error={formManager.formState.errors[fieldName] != undefined}
|
|
132
146
|
errorMessage={formManager?.formState?.errors[
|
|
@@ -146,6 +160,11 @@ const FormElementField: React.FC<FormElementFieldProps> = (
|
|
|
146
160
|
);
|
|
147
161
|
}
|
|
148
162
|
}}
|
|
163
|
+
hidden={
|
|
164
|
+
props?.hidden || element.hiddenFields.includes(fieldName)
|
|
165
|
+
? true
|
|
166
|
+
: false
|
|
167
|
+
}
|
|
149
168
|
value={formValues[fieldName]}
|
|
150
169
|
checkedValue={props?.checkedValue || true}
|
|
151
170
|
unCheckedValue={props?.unCheckedValue || false}
|
|
@@ -165,10 +184,15 @@ const FormElementField: React.FC<FormElementFieldProps> = (
|
|
|
165
184
|
? true
|
|
166
185
|
: false
|
|
167
186
|
}
|
|
187
|
+
hidden={
|
|
188
|
+
props?.hidden || element.hiddenFields.includes(fieldName)
|
|
189
|
+
? true
|
|
190
|
+
: false
|
|
191
|
+
}
|
|
168
192
|
onChangeCallBack={(v: any, selectedRecord: any) => {
|
|
169
193
|
let newValue = null;
|
|
170
194
|
if (v) {
|
|
171
|
-
newValue = v
|
|
195
|
+
newValue = v;
|
|
172
196
|
}
|
|
173
197
|
formManager.setValue(fieldName, newValue);
|
|
174
198
|
if (props?.formProps?.onValueChangeCallBack) {
|
|
@@ -197,10 +221,15 @@ const FormElementField: React.FC<FormElementFieldProps> = (
|
|
|
197
221
|
? true
|
|
198
222
|
: false
|
|
199
223
|
}
|
|
224
|
+
hidden={
|
|
225
|
+
props?.hidden || element.hiddenFields.includes(fieldName)
|
|
226
|
+
? true
|
|
227
|
+
: false
|
|
228
|
+
}
|
|
200
229
|
onChangeCallBack={(v: any, selectedRecord: any) => {
|
|
201
230
|
let newValue = null;
|
|
202
231
|
if (v) {
|
|
203
|
-
newValue = v
|
|
232
|
+
newValue = v ;
|
|
204
233
|
}
|
|
205
234
|
formManager.setValue(fieldName, newValue);
|
|
206
235
|
if (props?.formProps?.onValueChangeCallBack) {
|
package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/CheckBox.tsx
CHANGED
|
@@ -5,6 +5,7 @@ interface CheckBoxProps {
|
|
|
5
5
|
value: any;
|
|
6
6
|
disabled?: boolean;
|
|
7
7
|
required?: boolean;
|
|
8
|
+
hidden?: boolean;
|
|
8
9
|
label: string;
|
|
9
10
|
checkedValue?: any;
|
|
10
11
|
unCheckedValue?: any;
|
|
@@ -17,6 +18,7 @@ const CheckBox: React.FC<CheckBoxProps> = (props) => {
|
|
|
17
18
|
return (
|
|
18
19
|
<FormControlLabel
|
|
19
20
|
sx={props.sx}
|
|
21
|
+
hidden={props?.hidden || false}
|
|
20
22
|
disabled={props.disabled || false}
|
|
21
23
|
required={props.required || false}
|
|
22
24
|
control={
|
package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/ComboBox.tsx
CHANGED
|
@@ -10,6 +10,7 @@ interface ComboBoxProps {
|
|
|
10
10
|
required?: boolean;
|
|
11
11
|
options: Array<any>;
|
|
12
12
|
errorMessage?: any;
|
|
13
|
+
hidden?: boolean;
|
|
13
14
|
displayField: string;
|
|
14
15
|
valueField: string;
|
|
15
16
|
sx?: any;
|
|
@@ -32,6 +33,7 @@ const ComboBox: React.FC<ComboBoxProps> = (props) => {
|
|
|
32
33
|
value={getValue(props.value)}
|
|
33
34
|
options={props.options}
|
|
34
35
|
disabled={props.disabled}
|
|
36
|
+
hidden={props?.hidden || false}
|
|
35
37
|
onChange={(event, newValue) => {
|
|
36
38
|
if (
|
|
37
39
|
props.onChangeCallBack !== undefined &&
|
|
@@ -71,7 +73,9 @@ const ComboBox: React.FC<ComboBoxProps> = (props) => {
|
|
|
71
73
|
{...params}
|
|
72
74
|
required={props.required || false}
|
|
73
75
|
variant="outlined"
|
|
74
|
-
|
|
76
|
+
slotProps={{
|
|
77
|
+
inputLabel: { shrink: true, sx: { fontWeight: "bold" } },
|
|
78
|
+
}}
|
|
75
79
|
label={t(props.label)}
|
|
76
80
|
error={
|
|
77
81
|
props.errorMessage != null && props.errorMessage !== undefined
|
package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/Datefield.tsx
CHANGED
|
@@ -3,12 +3,14 @@ import { AdapterMoment } from "@mui/x-date-pickers/AdapterMoment";
|
|
|
3
3
|
import moment from "moment";
|
|
4
4
|
import { DATE_FORMAT } from "../../../../../util/constants";
|
|
5
5
|
import { useTranslation } from "react-i18next";
|
|
6
|
+
import TemplateTextField from "./TemplateTextField";
|
|
6
7
|
|
|
7
8
|
interface DatefieldProps {
|
|
8
9
|
value: string | null;
|
|
9
10
|
label: string;
|
|
10
11
|
disabled?: boolean;
|
|
11
12
|
required?: boolean;
|
|
13
|
+
hidden?: boolean;
|
|
12
14
|
sx?: any;
|
|
13
15
|
format?: string;
|
|
14
16
|
errorMessage?: any;
|
|
@@ -18,6 +20,9 @@ interface DatefieldProps {
|
|
|
18
20
|
|
|
19
21
|
const Datefield: React.FC<DatefieldProps> = (props) => {
|
|
20
22
|
const { t } = useTranslation();
|
|
23
|
+
if (props?.hidden) {
|
|
24
|
+
return <></>;
|
|
25
|
+
}
|
|
21
26
|
return (
|
|
22
27
|
<LocalizationProvider dateAdapter={AdapterMoment}>
|
|
23
28
|
<DatePicker
|
|
@@ -44,7 +49,7 @@ const Datefield: React.FC<DatefieldProps> = (props) => {
|
|
|
44
49
|
}}
|
|
45
50
|
slotProps={{
|
|
46
51
|
textField: {
|
|
47
|
-
InputLabelProps: { shrink: true },
|
|
52
|
+
InputLabelProps: { shrink: true, sx: { fontWeight: "bold" } },
|
|
48
53
|
variant: "outlined",
|
|
49
54
|
required: props.required,
|
|
50
55
|
error:
|
package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/DatetimeField.tsx
CHANGED
|
@@ -3,12 +3,15 @@ import { AdapterMoment } from "@mui/x-date-pickers/AdapterMoment";
|
|
|
3
3
|
import moment from "moment";
|
|
4
4
|
import { useTranslation } from "react-i18next";
|
|
5
5
|
import { DATE_TIME_FORMAT } from "../../../../../util/constants";
|
|
6
|
+
import TemplateTextField from "./TemplateTextField";
|
|
7
|
+
import { Hidden, TextField } from "@mui/material";
|
|
6
8
|
|
|
7
9
|
interface DatetimeFieldProps {
|
|
8
10
|
value: string | null;
|
|
9
11
|
label: string;
|
|
10
12
|
disabled?: boolean;
|
|
11
13
|
required?: boolean;
|
|
14
|
+
hidden?: boolean;
|
|
12
15
|
format?: string;
|
|
13
16
|
sx?: any;
|
|
14
17
|
errorMessage?: any;
|
|
@@ -18,6 +21,9 @@ interface DatetimeFieldProps {
|
|
|
18
21
|
|
|
19
22
|
const DatetimeField: React.FC<DatetimeFieldProps> = (props) => {
|
|
20
23
|
const { t } = useTranslation();
|
|
24
|
+
if (props?.hidden) {
|
|
25
|
+
return <></>;
|
|
26
|
+
}
|
|
21
27
|
return (
|
|
22
28
|
<LocalizationProvider dateAdapter={AdapterMoment}>
|
|
23
29
|
<DateTimePicker
|
|
@@ -44,6 +50,7 @@ const DatetimeField: React.FC<DatetimeFieldProps> = (props) => {
|
|
|
44
50
|
}}
|
|
45
51
|
slotProps={{
|
|
46
52
|
textField: {
|
|
53
|
+
InputLabelProps: { shrink: true, sx: { fontWeight: "bold" } },
|
|
47
54
|
variant: "outlined",
|
|
48
55
|
required: props.required,
|
|
49
56
|
error:
|
|
@@ -8,8 +8,9 @@ const TemplateTextField: React.FC<Omit<TextFieldProps, "outlined">> = (
|
|
|
8
8
|
return (
|
|
9
9
|
<TextField
|
|
10
10
|
{...props}
|
|
11
|
-
slotProps={{ inputLabel: { shrink: true } }}
|
|
11
|
+
slotProps={{ inputLabel: { shrink: true, sx: { fontWeight: "bold" } } }}
|
|
12
12
|
label={<>{props?.label ? t(props.label) : ""}</>}
|
|
13
|
+
helperText={props?.helperText ? t(props.helperText) : undefined}
|
|
13
14
|
/>
|
|
14
15
|
);
|
|
15
16
|
};
|
|
@@ -820,7 +820,9 @@ const TemplateGrid: React.FC<TemplateGridProps> = (props) => {
|
|
|
820
820
|
navigate(-1, { replace: true });
|
|
821
821
|
}}
|
|
822
822
|
>
|
|
823
|
-
<FontAwesomeIcon
|
|
823
|
+
<FontAwesomeIcon
|
|
824
|
+
icon={themeDirection === "ltr" ? "arrow-left" : "arrow-right"}
|
|
825
|
+
/>
|
|
824
826
|
</IconButton>
|
|
825
827
|
) : (
|
|
826
828
|
<></>
|
|
@@ -29,5 +29,7 @@ export { default as TemplatePieChart } from "./visuals/charts/TemplatePieChart";
|
|
|
29
29
|
export { default as DashboardRouteView } from "./visuals/DashboardRouteView";
|
|
30
30
|
export { default as DashboardViewer } from "./visuals/DashboardViewer";
|
|
31
31
|
|
|
32
|
+
export { default as FormElement } from "./DataEntryTemplates/TemplateDataForm/FormElementField";
|
|
33
|
+
|
|
32
34
|
export type * from "./DataEntryTemplates/DataEntryTypes";
|
|
33
35
|
export type { TransferListProps } from "./TransferList";
|
|
@@ -28,6 +28,7 @@ export const useConfirmationWindow = (props: ConfirmationWindowProps) => {
|
|
|
28
28
|
<DialogActions>
|
|
29
29
|
<Button
|
|
30
30
|
variant="contained"
|
|
31
|
+
sx={{marginRight:2,marginLeft:2}}
|
|
31
32
|
color="primary"
|
|
32
33
|
onClick={() => {
|
|
33
34
|
setOpen(false);
|
|
@@ -37,6 +38,7 @@ export const useConfirmationWindow = (props: ConfirmationWindowProps) => {
|
|
|
37
38
|
</Button>
|
|
38
39
|
<Button
|
|
39
40
|
variant="contained"
|
|
41
|
+
sx={{marginRight:2,marginLeft:2}}
|
|
40
42
|
color="error"
|
|
41
43
|
onClick={() => {
|
|
42
44
|
props.onConfirmationCallBk();
|
package/src/hooks/index.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
import { useRef } from 'react';
|
|
2
|
+
import { useTranslation } from "react-i18next";
|
|
3
|
+
import { useForm } from "react-hook-form";
|
|
4
|
+
import { useParams } from "react-router-dom";
|
|
5
|
+
import { zodResolver } from "@hookform/resolvers/zod";
|
|
6
|
+
import { useNavigate } from "react-router-dom";
|
|
7
|
+
import * as z from "zod";
|
|
8
|
+
import { useDispatch, useSelector } from "react-redux";
|
|
1
9
|
export { default as useAxios } from "./useAxios";
|
|
2
10
|
export { useConfirmationWindow } from "./UseConfirmationWindow";
|
|
3
11
|
export { default as useLoadingMask } from "./useLoadingMask";
|
|
@@ -5,3 +13,9 @@ export { useIsMobile } from "./UseMobile";
|
|
|
5
13
|
export { default as useSession } from "./UseSession";
|
|
6
14
|
export { useWindow } from "./UseWindow";
|
|
7
15
|
export { default as useApiActions } from "./useApiActions";
|
|
16
|
+
export { useDispatch };
|
|
17
|
+
export { useSelector };
|
|
18
|
+
export { useParams };
|
|
19
|
+
export { useForm, zodResolver, z };
|
|
20
|
+
export { useTranslation };
|
|
21
|
+
export {useNavigate};
|
package/src/hooks/useAxios.tsx
CHANGED
|
@@ -57,6 +57,19 @@ const useAxios = () => {
|
|
|
57
57
|
toast.error("your session is now expired, you need to login again", {
|
|
58
58
|
autoClose: false,
|
|
59
59
|
});
|
|
60
|
+
} else if (
|
|
61
|
+
error
|
|
62
|
+
? error.response
|
|
63
|
+
? error.response.status
|
|
64
|
+
? error.response.status === 402
|
|
65
|
+
: false
|
|
66
|
+
: false
|
|
67
|
+
: false
|
|
68
|
+
) {
|
|
69
|
+
dispatch(UserSessionActions.setUnAuthenticated());
|
|
70
|
+
toast.error(
|
|
71
|
+
"Your license is missing or has expired,Please reach out to your vendor for assistance."
|
|
72
|
+
);
|
|
60
73
|
} else if (
|
|
61
74
|
error
|
|
62
75
|
? error.response
|
package/src/layout/Layout.tsx
CHANGED
|
@@ -8,16 +8,12 @@ import MainContent from "./MainContent";
|
|
|
8
8
|
import { BrowserRouter } from "react-router-dom";
|
|
9
9
|
import MobileDrawer from "./MobileDrawer";
|
|
10
10
|
import { ToastContainer } from "react-toastify";
|
|
11
|
-
import { useEffect, useState } from "react";
|
|
12
|
-
import useLoadingMask from "../hooks/useLoadingMask";
|
|
13
11
|
import { useIsMobile } from "../hooks/UseMobile";
|
|
14
|
-
import useSession from "../hooks/UseSession";
|
|
15
|
-
import useAxios from "../hooks/useAxios";
|
|
16
12
|
import { DRAWER_WIDTH } from "../redux/features/common/AppLayoutSlice";
|
|
17
13
|
import { UserSessionProps } from "../redux/features/common/UserSessionSlice";
|
|
18
14
|
import LoadingMask from "../components/common/LoadingMask";
|
|
19
15
|
import Login from "../components/common/Login";
|
|
20
|
-
import
|
|
16
|
+
import NoLicenseComponent from "../components/common/NoLicenseComponent";
|
|
21
17
|
|
|
22
18
|
const Main = styled("main", {
|
|
23
19
|
shouldForwardProp: (prop) => prop !== "open",
|
|
@@ -59,12 +55,12 @@ const Main = styled("main", {
|
|
|
59
55
|
|
|
60
56
|
export default function Layout() {
|
|
61
57
|
const SideBarState = useSelector((state: any) => state.SideBar);
|
|
58
|
+
|
|
62
59
|
const isMobile = useIsMobile();
|
|
63
60
|
const UserSession: UserSessionProps = useSelector(
|
|
64
61
|
(state: any) => state.UserSession
|
|
65
62
|
);
|
|
66
63
|
const AppLayout = useSelector((state: any) => state.AppLayout);
|
|
67
|
-
|
|
68
64
|
return (
|
|
69
65
|
<BrowserRouter>
|
|
70
66
|
<ToastContainer
|
|
@@ -74,6 +70,7 @@ export default function Layout() {
|
|
|
74
70
|
/>
|
|
75
71
|
<LoadingMask />
|
|
76
72
|
{UserSession.value.isAuthenticated === true ? (
|
|
73
|
+
// licenseCheckObj?.isLicensed ? (
|
|
77
74
|
<Main open={SideBarState.isOpened}>
|
|
78
75
|
<CssBaseline />
|
|
79
76
|
<TopBar />
|
|
@@ -81,6 +78,7 @@ export default function Layout() {
|
|
|
81
78
|
{isMobile ? <MobileDrawer /> : null}
|
|
82
79
|
<DrawerHeader />
|
|
83
80
|
<MainContent />
|
|
81
|
+
<NoLicenseComponent />
|
|
84
82
|
</Main>
|
|
85
83
|
) : (
|
|
86
84
|
<Login />
|
|
@@ -46,7 +46,8 @@
|
|
|
46
46
|
"ORGANIZATION_UNIT_TYPE_UNIT_TYPE_CODE": "Unit type code",
|
|
47
47
|
"ORGANIZATION_UNIT_TYPE_UNIT_TYPE_EN_NAME": "Unit type en name",
|
|
48
48
|
"PERSON_SINGULAR": "person",
|
|
49
|
-
"PERSON_PLURAL": "
|
|
49
|
+
"PERSON_PLURAL": "المستخدمين",
|
|
50
|
+
"ROLES": "الصلاحيات",
|
|
50
51
|
"PERSON_EMAIL": "Email",
|
|
51
52
|
"PERSON_EMPLOYEE_AR_NAME": "Employee ar name",
|
|
52
53
|
"PERSON_EMPLOYEE_EN_NAME": "Employee en name",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"ORGANIZATION_RANK_ENABLED": "Enabled",
|
|
27
27
|
"ORGANIZATION_RANK_ORGANIZATION_ID": "Organization id",
|
|
28
28
|
"ORGANIZATION_RANK_RANK_ORDER": "Rank order",
|
|
29
|
+
"ROLES": "System Roles",
|
|
29
30
|
"ORGANIZATION_RANK_RANK_AR_NAME": "Rank ar name",
|
|
30
31
|
"ORGANIZATION_RANK_RANK_CODE": "Rank code",
|
|
31
32
|
"ORGANIZATION_RANK_RANK_EN_NAME": "Rank en name",
|
package/src/main.tsx
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { createRoot } from "react-dom/client";
|
|
2
2
|
import { BaseApp } from "./components";
|
|
3
3
|
|
|
4
|
-
|
|
5
4
|
createRoot(document.getElementById("root")!).render(
|
|
6
5
|
<BaseApp
|
|
7
6
|
apiBaseUrl="http://localhost:8080/api-base"
|
|
7
|
+
enableUINotifications={false}
|
|
8
8
|
appLogo={"/logo.png"}
|
|
9
9
|
appName="UI Base Library"
|
|
10
10
|
appVersion="0.0"
|
|
@@ -11,10 +11,18 @@ export const adminNavigationItems: TreeViewBaseItem<ExtendedTreeItemProps>[] = [
|
|
|
11
11
|
{
|
|
12
12
|
id: "system_admin.Person",
|
|
13
13
|
label: "PERSON_PLURAL",
|
|
14
|
+
authority: "SYSTEM_ADMIN",
|
|
14
15
|
icon: "users",
|
|
15
16
|
action: "NAVIGATION",
|
|
16
17
|
actionPayload: { path: "admin/persons" },
|
|
17
18
|
},
|
|
19
|
+
{
|
|
20
|
+
id: "system_admin.devtools.rolesx",
|
|
21
|
+
label: "ROLES",
|
|
22
|
+
icon: "tag",
|
|
23
|
+
action: "NAVIGATION",
|
|
24
|
+
actionPayload: { path: "dev/system/roles" },
|
|
25
|
+
},
|
|
18
26
|
{
|
|
19
27
|
id: "development_admin.SystemApplication",
|
|
20
28
|
label: "SYSTEM_APPLICATION_PLURAL",
|
|
@@ -192,7 +200,7 @@ export const adminNavigationItems: TreeViewBaseItem<ExtendedTreeItemProps>[] = [
|
|
|
192
200
|
{
|
|
193
201
|
id: "system_admin.followup",
|
|
194
202
|
label: "SYSTEM_MONITORING",
|
|
195
|
-
authority: "
|
|
203
|
+
authority: "DEVELOPMENT_ADMIN",
|
|
196
204
|
icon: "tv",
|
|
197
205
|
children: [
|
|
198
206
|
{
|
|
@@ -130,19 +130,19 @@ export const ADMINISTRATION_STORES: CommonStores = {
|
|
|
130
130
|
SystemApplicationModules: {
|
|
131
131
|
autoLoad: true,
|
|
132
132
|
data: [],
|
|
133
|
-
authority: "
|
|
133
|
+
authority: "SYSTEM_ADMIN",
|
|
134
134
|
url: "api/v1/admin/systemapplicationmodule/application/all",
|
|
135
135
|
},
|
|
136
136
|
SystemApplicationAuthorities: {
|
|
137
137
|
autoLoad: true,
|
|
138
138
|
data: [],
|
|
139
|
-
authority: "
|
|
139
|
+
authority: "SYSTEM_ADMIN",
|
|
140
140
|
url: "api/v1/admin/systemapplicationauthority/all",
|
|
141
141
|
},
|
|
142
142
|
SystemApplicationRoles: {
|
|
143
143
|
autoLoad: true,
|
|
144
144
|
data: [],
|
|
145
|
-
authority: "
|
|
145
|
+
authority: "SYSTEM_ADMIN",
|
|
146
146
|
url: "api/v1/admin/systemapplicationrole/all",
|
|
147
147
|
},
|
|
148
148
|
};
|
|
@@ -3,6 +3,12 @@ import { SystemRoute } from "../../../routes/types";
|
|
|
3
3
|
import { ExtendedTreeItemProps } from "../../../navigationItems";
|
|
4
4
|
import { StoreMetaData } from "./CommonStoreSlice";
|
|
5
5
|
|
|
6
|
+
export type LicenseCheckObject = {
|
|
7
|
+
isLicensed: boolean;
|
|
8
|
+
lastLicenseCheckMessage: string;
|
|
9
|
+
lastLicenseCheckTime: string;
|
|
10
|
+
};
|
|
11
|
+
|
|
6
12
|
export type AppInfo = {
|
|
7
13
|
documentTitle: string | null;
|
|
8
14
|
apiBaseUrl: string | null;
|
|
@@ -24,6 +30,7 @@ export type AppInfo = {
|
|
|
24
30
|
light: { primaryColor: string; secondaryColor: string };
|
|
25
31
|
dark: { primaryColor: string; secondaryColor: string };
|
|
26
32
|
};
|
|
33
|
+
checkLicense?: { endpoint: string; interval: number };
|
|
27
34
|
};
|
|
28
35
|
|
|
29
36
|
export type AppInfoProp = {
|
package/src/routes/index.ts
CHANGED
|
@@ -2,10 +2,4 @@ import Home from "../components/common/Home";
|
|
|
2
2
|
import { ADMINISTRATION_ROUTES } from "./administration";
|
|
3
3
|
import { SystemRoute } from "./types";
|
|
4
4
|
|
|
5
|
-
export const SYSTEM_ROUTES: Array<SystemRoute> = [
|
|
6
|
-
{
|
|
7
|
-
path: "/",
|
|
8
|
-
component: Home,
|
|
9
|
-
},
|
|
10
|
-
...ADMINISTRATION_ROUTES,
|
|
11
|
-
];
|
|
5
|
+
export const SYSTEM_ROUTES: Array<SystemRoute> = [...ADMINISTRATION_ROUTES];
|
package/src/util/index.ts
CHANGED
package/tsconfig.json
CHANGED