@asaleh37/ui-base 1.0.9 → 1.1.0

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.
Files changed (125) hide show
  1. package/dist/index.js +1 -1
  2. package/dist/index.js.map +1 -1
  3. package/dist/index.mjs +1 -1
  4. package/dist/index.mjs.map +1 -1
  5. package/package.json +1 -1
  6. package/src/components/App.tsx +31 -0
  7. package/src/components/admin/AttachmentGrid.tsx +116 -0
  8. package/src/components/admin/AuthorityGrid.tsx +88 -0
  9. package/src/components/admin/BluePrintGrid.tsx +55 -0
  10. package/src/components/admin/BluePrintPageGrid.tsx +85 -0
  11. package/src/components/admin/BluePrintPointGrid.tsx +85 -0
  12. package/src/components/admin/DashboardGrid.tsx +95 -0
  13. package/src/components/admin/DashboardWidgetGrid.tsx +75 -0
  14. package/src/components/admin/DataQueryGrid.tsx +75 -0
  15. package/src/components/admin/DataQueryParameterGrid.tsx +98 -0
  16. package/src/components/admin/DatasourceConnectionGrid.tsx +98 -0
  17. package/src/components/admin/EmployeeGrid.tsx +105 -0
  18. package/src/components/admin/EntityParameterGrid.tsx +125 -0
  19. package/src/components/admin/ExcelUploaderDetailGrid.tsx +78 -0
  20. package/src/components/admin/ExcelUploaderHeaderGrid.tsx +78 -0
  21. package/src/components/admin/LookupGrid.tsx +95 -0
  22. package/src/components/admin/MailAttachmentGrid.tsx +65 -0
  23. package/src/components/admin/MailBodyGrid.tsx +105 -0
  24. package/src/components/admin/MailNotificationQueueGrid.tsx +131 -0
  25. package/src/components/admin/MailRecipientGrid.tsx +75 -0
  26. package/src/components/admin/MailTemplateGrid.tsx +145 -0
  27. package/src/components/admin/NewTableGrid.tsx +65 -0
  28. package/src/components/admin/NotificationGrid.tsx +115 -0
  29. package/src/components/admin/NotificationQueueGrid.tsx +125 -0
  30. package/src/components/admin/OrganizationApplicationGrid.tsx +81 -0
  31. package/src/components/admin/OrganizationGrid.tsx +65 -0
  32. package/src/components/admin/OrganizationRankGrid.tsx +85 -0
  33. package/src/components/admin/OrganizationUnitGrid.tsx +85 -0
  34. package/src/components/admin/OrganizationUserGrid.tsx +75 -0
  35. package/src/components/admin/OrganizationUserRoleGrid.tsx +98 -0
  36. package/src/components/admin/ReportGrid.tsx +155 -0
  37. package/src/components/admin/ReportParameterGrid.tsx +95 -0
  38. package/src/components/admin/RoleAuthorityGrid.tsx +65 -0
  39. package/src/components/admin/RoleGrid.tsx +78 -0
  40. package/src/components/admin/UserAccountGrid.tsx +65 -0
  41. package/src/components/admin/UserRequestGrid.tsx +145 -0
  42. package/src/components/admin/WidgetGrid.tsx +175 -0
  43. package/src/components/admin/WorkflowDocumentActionGrid.tsx +111 -0
  44. package/src/components/admin/WorkflowDocumentActionHistoryGrid.tsx +111 -0
  45. package/src/components/admin/WorkflowDocumentActionMailGrid.tsx +71 -0
  46. package/src/components/admin/WorkflowDocumentGrid.tsx +185 -0
  47. package/src/components/admin/WorkflowDocumentMailLogGrid.tsx +141 -0
  48. package/src/components/admin/WorkflowDocumentStatusGrid.tsx +121 -0
  49. package/src/components/common/Home.tsx +31 -0
  50. package/src/components/common/LanguageSwitcher.tsx +25 -0
  51. package/src/components/common/LayoutHandlers.tsx +12 -0
  52. package/src/components/common/LoadingMask.tsx +19 -0
  53. package/src/components/common/Login.tsx +183 -0
  54. package/src/components/templates/DataEntryTemplates/DataEntryTypes.ts +288 -0
  55. package/src/components/templates/DataEntryTemplates/DataEntryUtil.ts +201 -0
  56. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormAction.tsx +60 -0
  57. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormElementField.tsx +194 -0
  58. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormElementGroup.tsx +98 -0
  59. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/CheckBox.tsx +64 -0
  60. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/ComboBox.tsx +94 -0
  61. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/Datefield.tsx +65 -0
  62. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/DatetimeField.tsx +64 -0
  63. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/FiltersPanel.tsx +237 -0
  64. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/TemplateTextField.tsx +9 -0
  65. package/src/components/templates/DataEntryTemplates/TemplateDataForm/TemplateForm.tsx +256 -0
  66. package/src/components/templates/DataEntryTemplates/TemplateDataGrid/DataGridColumnsUtil.tsx +188 -0
  67. package/src/components/templates/DataEntryTemplates/TemplateDataGrid/TemplateGrid.tsx +844 -0
  68. package/src/components/templates/DataEntryTemplates/TemplateDataGrid/TemplateGridMultiRecordAction.tsx +89 -0
  69. package/src/components/templates/DataEntryTemplates/TemplateDataGrid/TemplateGridRecordAction.tsx +92 -0
  70. package/src/components/templates/DataEntryTemplates/TemplateDataGrid/TemplateGridTopBar.tsx +228 -0
  71. package/src/components/templates/DataEntryTemplates/useApiActions.ts +125 -0
  72. package/src/components/templates/TransferList.tsx +250 -0
  73. package/src/components/templates/Window/ConfirmationWindow.tsx +55 -0
  74. package/src/components/templates/visuals/TemplateDashboard.tsx +126 -0
  75. package/src/components/templates/visuals/charts/TemplateBarChart.tsx +16 -0
  76. package/src/components/templates/visuals/charts/TemplateDataCard.tsx +60 -0
  77. package/src/components/templates/visuals/charts/TemplateGauge.tsx +16 -0
  78. package/src/components/templates/visuals/charts/TemplateLineChart.tsx +16 -0
  79. package/src/components/templates/visuals/charts/TemplateLineProgress.tsx +40 -0
  80. package/src/components/templates/visuals/charts/TemplatePieChart.tsx +25 -0
  81. package/src/hooks/UseConfirmationWindow.tsx +54 -0
  82. package/src/hooks/UseMobile.tsx +13 -0
  83. package/src/hooks/UseSession.tsx +26 -0
  84. package/src/hooks/UseWindow.tsx +106 -0
  85. package/src/hooks/useAxios.tsx +271 -0
  86. package/src/hooks/useLoadingMask.tsx +16 -0
  87. package/src/layout/DrawerHeader.tsx +10 -0
  88. package/src/layout/Layout.tsx +122 -0
  89. package/src/layout/MainContent.tsx +43 -0
  90. package/src/layout/MobileDrawer.tsx +103 -0
  91. package/src/layout/NavigationTree.tsx +284 -0
  92. package/src/layout/SideBar.tsx +80 -0
  93. package/src/layout/TopBar.tsx +142 -0
  94. package/src/locales/arabic/adminLocalsAr.json +356 -0
  95. package/src/locales/arabic/common.json +34 -0
  96. package/src/locales/arabic/index.ts +7 -0
  97. package/src/locales/english/adminLocalsEn.json +356 -0
  98. package/src/locales/english/common.json +33 -0
  99. package/src/locales/english/index.ts +6 -0
  100. package/src/locales/english/index.tsx +0 -0
  101. package/src/locales/i18n.ts +15 -0
  102. package/src/locales/index.ts +9 -0
  103. package/src/navigationItems/Administration/adminNavigationItems.tsx +182 -0
  104. package/src/navigationItems/Administration/index.tsx +71 -0
  105. package/src/navigationItems/common/CommonNavigationItems.tsx +12 -0
  106. package/src/navigationItems/common/index.tsx +7 -0
  107. package/src/navigationItems/index.tsx +34 -0
  108. package/src/redux/features/administration/AdministrationStoresMetaData.ts +72 -0
  109. package/src/redux/features/business/BusinessStoresMetaData.ts +3 -0
  110. package/src/redux/features/business/CommonStoreSlice.ts +37 -0
  111. package/src/redux/features/common/AppInfoSlice.ts +30 -0
  112. package/src/redux/features/common/AppLayoutSlice.ts +37 -0
  113. package/src/redux/features/common/LoadingMaskSlice.ts +30 -0
  114. package/src/redux/features/common/UserSessionSlice.ts +62 -0
  115. package/src/redux/store.ts +10 -10
  116. package/src/routes/administration/adminRoutes.tsx +259 -0
  117. package/src/routes/administration/index.ts +4 -0
  118. package/src/routes/index.ts +11 -0
  119. package/src/routes/types/index.ts +5 -0
  120. package/src/theme/DarkThemeOptions.ts +30 -0
  121. package/src/theme/LightThemeOptions.ts +34 -0
  122. package/src/util/AppUtils.ts +18 -0
  123. package/src/util/constants.ts +2 -0
  124. package/tsconfig.json +2 -2
  125. package/src/redux/CounterSlice.ts +0 -17
@@ -0,0 +1,183 @@
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 { RootState } from "../../redux/store";
16
+ import { UserSessionActions } from "../../redux/features/common/UserSessionSlice";
17
+ import { DarkThemeOptions } from "../../theme/DarkThemeOptions";
18
+
19
+ const Login: React.FC = () => {
20
+ const appInfo = useSelector((state: RootState) => state.AppInfo);
21
+ const [username, setUsername] = useState("");
22
+ const [password, setPassword] = useState("");
23
+ const [isLoginInProcess, setIsLoginInProcess] = useState(false);
24
+ const UserSessionState = useSelector(
25
+ (state: RootState) => state.UserSession.value
26
+ );
27
+ const dispatch = useDispatch();
28
+ const handleLogin = async () => {
29
+ if (username == null || username == "") {
30
+ toast.error("username is required to proceed");
31
+ return;
32
+ }
33
+ if (password == null || password == "") {
34
+ toast.error("password is required to proceed");
35
+ return;
36
+ }
37
+ setIsLoginInProcess(true);
38
+ let response: any = null;
39
+ try {
40
+ response = await axios.post(
41
+ `${appInfo.apiBaseUrl}/api/auth/login`,
42
+ {
43
+ username,
44
+ password,
45
+ },
46
+ {
47
+ withCredentials: true,
48
+ }
49
+ );
50
+ if (response.data != null && response.data !== "") {
51
+ setIsLoginInProcess(false);
52
+ const UserSession = {
53
+ isAuthenticated: true,
54
+ authorities: response.data.authorities,
55
+ userProfile: response.data,
56
+ };
57
+ dispatch(UserSessionActions.setAuthenticated(UserSession));
58
+ }
59
+ } catch (e: any) {
60
+ setIsLoginInProcess(false);
61
+ toast.error(
62
+ e?.response?.data ||
63
+ "failed to authenticate, contact your administrator"
64
+ );
65
+ }
66
+ };
67
+ const userSession = useSelector(
68
+ (state: RootState) => state.UserSession.value
69
+ );
70
+ const loginTheme = createTheme(DarkThemeOptions);
71
+ const checkUserSession = async () => {
72
+ if (userSession.isAuthenticated == null) {
73
+ try {
74
+ let response = await axios.get(
75
+ `${appInfo.apiBaseUrl}/api/auth/userInfo`,
76
+ {
77
+ withCredentials: true,
78
+ }
79
+ );
80
+ if (response != null && response.data != null) {
81
+ const UserSession = {
82
+ isAuthenticated: true,
83
+ authorities: response.data.authorities,
84
+ userProfile: response.data,
85
+ };
86
+ dispatch(UserSessionActions.setAuthenticated(UserSession));
87
+ } else {
88
+ dispatch(UserSessionActions.setUnAuthenticated());
89
+ }
90
+ } catch (error) {
91
+ dispatch(UserSessionActions.setUnAuthenticated());
92
+ }
93
+ }
94
+ };
95
+ useEffect(() => {
96
+ checkUserSession();
97
+ }, []);
98
+ return (
99
+ <ThemeProvider theme={loginTheme}>
100
+ <Paper
101
+ sx={{
102
+ display: "flex",
103
+ height: "100vh",
104
+ width: "100%",
105
+ borderRadius: 0,
106
+ alignItems: "center",
107
+ justifyContent: "center",
108
+ }}
109
+ >
110
+ {UserSessionState.isAuthenticated == false ? (
111
+ <Box
112
+ sx={{
113
+ display: "flex",
114
+ flexDirection: "column",
115
+ alignItems: "center",
116
+ justifyContent: "center",
117
+ }}
118
+ >
119
+ <img src={appInfo?.appLogo} width={150} height={150} />
120
+ <Typography sx={{ m: 1 }} variant="h4" color="textSecondary">
121
+ {appInfo?.appName}
122
+ </Typography>
123
+ <Typography
124
+ sx={{
125
+ paddingRight: 1,
126
+ width: "100%",
127
+ textAlign: "right",
128
+ fontSize: 10,
129
+ }}
130
+ variant="caption"
131
+ color="textSecondary"
132
+ >
133
+ V.{appInfo.appVersion}
134
+ </Typography>
135
+ <TextField
136
+ label="username"
137
+ sx={{ width: 300, m: 1 }}
138
+ value={username}
139
+ onChange={(event) => {
140
+ setUsername(event.target.value);
141
+ }}
142
+ onKeyDown={(event) => {
143
+ if (event.key === "Enter") {
144
+ handleLogin();
145
+ }
146
+ }}
147
+ />
148
+ <TextField
149
+ label="password"
150
+ sx={{ width: 300, m: 1 }}
151
+ value={password}
152
+ type="password"
153
+ onChange={(event) => {
154
+ setPassword(event.target.value);
155
+ }}
156
+ onKeyDown={(event) => {
157
+ if (event.key === "Enter") {
158
+ handleLogin();
159
+ }
160
+ }}
161
+ />
162
+ <Button
163
+ loading={isLoginInProcess}
164
+ onClick={handleLogin}
165
+ variant="contained"
166
+ color="primary"
167
+ sx={{ m: 1 }}
168
+ >
169
+ login
170
+ </Button>
171
+ </Box>
172
+ ) : (
173
+ <>
174
+ <CircularProgress sx={{ marginRight: 1 }} />
175
+ <div>You will be redirected shortly ... please wait</div>
176
+ </>
177
+ )}
178
+ </Paper>
179
+ </ThemeProvider>
180
+ );
181
+ };
182
+
183
+ export default Login;
@@ -0,0 +1,288 @@
1
+ import { IconProp } from "@fortawesome/fontawesome-svg-core";
2
+ import {
3
+ DataGridPremiumProps,
4
+ GridColDef,
5
+ GridRowSelectionModel,
6
+ GridToolbarProps,
7
+ ToolbarPropsOverrides,
8
+ } from "@mui/x-data-grid-premium";
9
+ import { UseFormReturn } from "react-hook-form";
10
+ import { SxProps } from "@mui/material";
11
+ import { ApiActions } from "./useApiActions";
12
+ export type MakeOptional<T, K extends keyof T> = Omit<T, K> &
13
+ Partial<Pick<T, K>>;
14
+
15
+ // Generic Types for Data Entry
16
+ export type RecordAction = {
17
+ label?: string;
18
+ icon: IconProp;
19
+ isConfirmationRequired?: boolean;
20
+ confirmationMessage?: string;
21
+ authority?: string;
22
+ getActionIconStyleForRecord?: (record: any) => object;
23
+ isActionVisibleForRecord?: (record: any) => boolean;
24
+ isActionDisabledForRecord?: (record: any) => boolean;
25
+ actionFn: (
26
+ data: any | Array<any>,
27
+ recordIdsToProcessActionOn?: Array<any>
28
+ ) => Promise<void>;
29
+ preActionValidation?: (record: any) => boolean | Promise<boolean>;
30
+ postActionCallBack?: (record: any) => any | void;
31
+ gridActionProps?: {
32
+ showInMenu?: boolean;
33
+ multiRecord?: boolean;
34
+ };
35
+ formActionProps?: {
36
+ enabled?: boolean;
37
+ actionButtonVariant?: "text" | "outlined" | "contained";
38
+ actionButtonColor?:
39
+ | "inherit"
40
+ | "primary"
41
+ | "secondary"
42
+ | "success"
43
+ | "error"
44
+ | "info"
45
+ | "warning";
46
+ };
47
+ record?: any;
48
+ reloadData?: (parameters?: any) => Promise<void>;
49
+ recordsToProcessActionOn?: Array<any>;
50
+ recordIdsToProcessActionOn?: Array<any>;
51
+ };
52
+
53
+ export type EditDeleteAction = {
54
+ isEnabled: boolean;
55
+ authority?: string;
56
+ isActionVisibleForRecord?: (record: any) => boolean;
57
+ isActionDisabledForRecord?: (record: any) => boolean;
58
+ preActionValidation?: (record: any) => boolean | Promise<boolean>;
59
+ postActionCallBack?: (record: any) => any | void;
60
+ gridActionProps?: {
61
+ showInMenu?: boolean;
62
+ };
63
+ formActionProps?: {
64
+ actionButtonVariant?: "text" | "outlined" | "contained";
65
+ actionButtonColor?:
66
+ | "inherit"
67
+ | "primary"
68
+ | "secondary"
69
+ | "success"
70
+ | "error"
71
+ | "info"
72
+ | "warning";
73
+ };
74
+ record?: any;
75
+ reloadData?: (parameters?: any) => Promise<void>;
76
+ };
77
+
78
+ // Template Grid Types
79
+
80
+ export type TemplateGridColumnProps = {
81
+ hidden?: boolean;
82
+ searchable?: boolean;
83
+ options?: Array<object>;
84
+ displayField?: string;
85
+ valueField?: string;
86
+ muiProps?: MakeOptional<GridColDef, "field">;
87
+ };
88
+
89
+ export type TemplateGridColDef = GridColDef & {
90
+ hidden?: boolean;
91
+ searchable?: boolean;
92
+ options?: Array<object>;
93
+ displayField?: string;
94
+ valueField?: string;
95
+ };
96
+
97
+ export type TemplateGridProps = {
98
+ formElements: Array<FormElementProps>;
99
+ gridStateKey?: string;
100
+ data: Array<any>;
101
+ setData: any;
102
+ keyColumnName?: any;
103
+ autoLoad?: boolean;
104
+ gridTitle: string;
105
+ girdIcon: IconProp;
106
+ editAction?: EditDeleteAction;
107
+ deleteAction?: EditDeleteAction;
108
+ rowActions?: Array<RecordAction>;
109
+ gridLoadParameters?: Array<FormElementProps>;
110
+ gridLoadParametersValues?: { [key: string]: any };
111
+ setGridLoadParametersValues?: any;
112
+ tBar?: any;
113
+ disableDefaultAction?: boolean;
114
+ enableQuickSearch?: boolean;
115
+ enableExport?: boolean;
116
+ enableDensitySelector?: boolean;
117
+ hideInfoBar?: boolean;
118
+ hideBackButton?: boolean;
119
+ apiActions: ApiActions;
120
+ rowSelectionModel?: GridRowSelectionModel;
121
+ setRowSelectionModel?: any;
122
+ setSelectedRecord?: any;
123
+ setSelectedRecordIds?: any;
124
+ editMode:
125
+ | { editMode: "none" }
126
+ | {
127
+ editMode: "row";
128
+ reloadAfterSave?: boolean;
129
+ }
130
+ | {
131
+ editMode: "modal";
132
+ specs?: {
133
+ modalTitle?: string;
134
+ modalIcon?: IconProp;
135
+ modalHeight?: any;
136
+ modalWidth?: any;
137
+ modalMinHeight?: any;
138
+ modalMinWidth?: any;
139
+ formComponent?: React.FC<ModalFormProps>;
140
+ };
141
+ }
142
+ | {
143
+ editMode: "form";
144
+ specs: {
145
+ formRoute: string;
146
+ };
147
+ };
148
+ muiProps?: MakeOptional<DataGridPremiumProps, "rows" | "columns">;
149
+ };
150
+
151
+ // Form Types
152
+ export type ModalFormProps = {
153
+ recordIdToEdit?: any;
154
+ formCloseCallBk?: () => void;
155
+ };
156
+
157
+ export type FormElementSize = {
158
+ lg?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
159
+ md?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
160
+ sm?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
161
+ };
162
+
163
+ export type RecordFieldProps = {
164
+ fieldName: string;
165
+ fieldLabel: string;
166
+ fieldType: "text" | "number" | "date" | "datetime" | "combobox" | "checkbox";
167
+ required?: boolean;
168
+ disabled?: boolean;
169
+ hidden?: boolean;
170
+ dateFormat?: string;
171
+ options?: Array<any>;
172
+ optionValueField?: string;
173
+ optionDisplayField?: string;
174
+ checkedValue?: any;
175
+ unCheckedValue?: any;
176
+ gridProps?: TemplateGridColumnProps;
177
+ formProps?: {
178
+ fieldSize?: FormElementSize;
179
+ style?: SxProps;
180
+ onValueChangeCallBack?: (
181
+ value: any,
182
+ formManager: UseFormReturn,
183
+ formActions?: FormActionProps,
184
+ selectedRecord?: any
185
+ ) => void;
186
+ };
187
+ };
188
+
189
+ export type FormElementGroupProps = {
190
+ style?: SxProps;
191
+ icon?: IconProp;
192
+ label?: string;
193
+ elements?: Array<FormElementProps>;
194
+ actions?: Array<RecordAction>;
195
+ formManager?: UseFormReturn;
196
+ formValues?: any;
197
+ formActions?: any;
198
+ hiddenFields: string[];
199
+ disabledFields: string[];
200
+ };
201
+
202
+ export type FormElementFieldProps = {
203
+ fieldInfo: RecordFieldProps;
204
+ formManager?: UseFormReturn;
205
+ formValues?: any;
206
+ formActions?: any;
207
+ hiddenFields: string[];
208
+ disabledFields: string[];
209
+ };
210
+
211
+ export type FormElementNodeProps = {
212
+ formManager?: UseFormReturn;
213
+ formValues: any;
214
+ formActions?: any;
215
+ };
216
+
217
+ export type FormElementProps =
218
+ | {
219
+ type: "group";
220
+ props: FormElementGroupProps;
221
+ }
222
+ | {
223
+ type: "field";
224
+ mode: "node";
225
+ node: React.FC<FormElementNodeProps>;
226
+ props?: RecordFieldProps;
227
+ }
228
+ | {
229
+ type: "field";
230
+ mode: "props";
231
+ props: RecordFieldProps;
232
+ };
233
+
234
+ export type FormActionProps = {
235
+ setFieldValue: (fieldName: string, fieldValue: any) => void;
236
+ hideField: (fieldName: string) => void;
237
+ showField: (fieldName: string) => void;
238
+ disableField: (fieldName: string) => void;
239
+ enableField: (fieldName: string) => void;
240
+ };
241
+
242
+ export type TemplateFormProps = {
243
+ elements: Array<FormElementProps>;
244
+ findByIdParamName?: string;
245
+ recordIdToEdit?: any;
246
+ formRouteRecordIdParamName?: string;
247
+ actions?: Array<RecordAction>;
248
+ editAuthorityKey?: string;
249
+ apiActions: ApiActions;
250
+ preSaveValidation?: (record: any) => boolean | Promise<boolean>;
251
+ formSavedSuccessfullyCallBk?: (response: any) => void;
252
+ formCloseCallBk?: () => void;
253
+ saveButtonSpecs?: {
254
+ label?: string;
255
+ icon?: IconProp;
256
+ hidden?: boolean;
257
+ actionButtonVariant?: "text" | "outlined" | "contained";
258
+ actionButtonColor?:
259
+ | "inherit"
260
+ | "primary"
261
+ | "secondary"
262
+ | "success"
263
+ | "error"
264
+ | "info"
265
+ | "warning";
266
+ };
267
+ cancelButtonSpecs?: {
268
+ label?: string;
269
+ icon?: IconProp;
270
+ hidden?: boolean;
271
+ actionButtonVariant?: "text" | "outlined" | "contained";
272
+ actionButtonColor?:
273
+ | "inherit"
274
+ | "primary"
275
+ | "secondary"
276
+ | "success"
277
+ | "error"
278
+ | "info"
279
+ | "warning";
280
+ };
281
+ };
282
+
283
+ export type TemplateGridTopBarProps = GridToolbarProps &
284
+ ToolbarPropsOverrides & {
285
+ templateProps: TemplateGridProps;
286
+ handleCreateNewRecord?: () => void;
287
+ clearGridState: () => void;
288
+ };
@@ -0,0 +1,201 @@
1
+ import { GridRowSelectionModel } from "@mui/x-data-grid-premium";
2
+ import {
3
+ FormElementProps,
4
+ RecordFieldProps,
5
+ TemplateGridColDef,
6
+ } from "./DataEntryTypes";
7
+ import {
8
+ generateCheckBoxColumn,
9
+ generateComboColumn,
10
+ generateDateColumn,
11
+ generateDateTimeColumn,
12
+ } from "./TemplateDataGrid/DataGridColumnsUtil";
13
+ import * as z from "zod";
14
+ import { TFunction } from "i18next";
15
+
16
+ export const getElementFields: (
17
+ element: FormElementProps
18
+ ) => Array<RecordFieldProps> = (element: FormElementProps) => {
19
+ const fields: Array<RecordFieldProps> = [];
20
+ if (element.type === "field" && element.mode === "props" && element?.props) {
21
+ fields.push(element.props);
22
+ } else if (
23
+ element.type === "group" &&
24
+ element?.props &&
25
+ element?.props?.elements
26
+ ) {
27
+ for (const childElement of element.props.elements) {
28
+ fields.push(...getElementFields(childElement));
29
+ }
30
+ }
31
+ return fields;
32
+ };
33
+
34
+ export const getAllFields: (
35
+ elements: Array<FormElementProps>
36
+ ) => Array<RecordFieldProps> = (elements: Array<FormElementProps>) => {
37
+ const fields: Array<RecordFieldProps> = [];
38
+ for (const element of elements) {
39
+ fields.push(...getElementFields(element));
40
+ }
41
+ return fields;
42
+ };
43
+
44
+ export const constructGridColumnsFromFields: (
45
+ fields: Array<RecordFieldProps>,
46
+ isDefaultEditable: boolean,
47
+ t: TFunction<"translation", undefined>
48
+ ) => Array<TemplateGridColDef> = (fields, isDefaultEditable, t) => {
49
+ const columns: Array<TemplateGridColDef> = [];
50
+ for (const tableField of fields) {
51
+ if (
52
+ tableField?.fieldType === "text" ||
53
+ tableField?.fieldType === "number"
54
+ ) {
55
+ const column: TemplateGridColDef = {
56
+ ...tableField?.gridProps?.muiProps,
57
+ editable:
58
+ tableField?.gridProps?.muiProps?.editable || isDefaultEditable,
59
+ type: tableField?.fieldType == "number" ? "number" : "string",
60
+ field: tableField?.fieldName,
61
+ headerName: t(tableField?.fieldLabel || tableField?.fieldName),
62
+ headerAlign: "center",
63
+ align: "center",
64
+ hidden: tableField?.hidden,
65
+ searchable: tableField?.gridProps?.searchable,
66
+ flex: 1,
67
+ minWidth: 200,
68
+ };
69
+ columns.push(column);
70
+ } else if (tableField?.fieldType === "date") {
71
+ const column: TemplateGridColDef = generateDateColumn({
72
+ ...tableField?.gridProps?.muiProps,
73
+ editable:
74
+ tableField?.gridProps?.muiProps?.editable || isDefaultEditable,
75
+ field: tableField?.fieldName,
76
+ headerName: t(tableField?.fieldLabel || tableField?.fieldName),
77
+ headerAlign: "center",
78
+ align: "center",
79
+ hidden: tableField?.hidden,
80
+ searchable: tableField?.gridProps?.searchable,
81
+ flex: 1,
82
+ minWidth: 200,
83
+ });
84
+ columns.push(column);
85
+ } else if (tableField?.fieldType === "datetime") {
86
+ const column: TemplateGridColDef = generateDateTimeColumn({
87
+ ...tableField?.gridProps?.muiProps,
88
+ editable:
89
+ tableField?.gridProps?.muiProps?.editable || isDefaultEditable,
90
+ field: tableField?.fieldName,
91
+ headerName: t(tableField?.fieldLabel || tableField?.fieldName),
92
+ headerAlign: "center",
93
+ align: "center",
94
+ hidden: tableField?.hidden,
95
+ searchable: tableField?.gridProps?.searchable,
96
+ flex: 1,
97
+ minWidth: 200,
98
+ });
99
+ columns.push(column);
100
+ } else if (tableField?.fieldType === "checkbox") {
101
+ const column = generateCheckBoxColumn({
102
+ ...tableField?.gridProps?.muiProps,
103
+ editable:
104
+ tableField?.gridProps?.muiProps?.editable || isDefaultEditable,
105
+ field: tableField?.fieldName,
106
+ headerName: t(tableField?.fieldLabel || tableField?.fieldName),
107
+ headerAlign: "center",
108
+ align: "center",
109
+ hidden: tableField?.hidden,
110
+ searchable: tableField?.gridProps?.searchable,
111
+ checkedValue: tableField?.checkedValue,
112
+ unCheckedValue: tableField?.unCheckedValue,
113
+ width: 150,
114
+ });
115
+ columns.push(column);
116
+ } else if (tableField?.fieldType === "combobox") {
117
+ const column: TemplateGridColDef = generateComboColumn({
118
+ ...tableField?.gridProps?.muiProps,
119
+ editable:
120
+ tableField?.gridProps?.muiProps?.editable || isDefaultEditable,
121
+ field: tableField?.fieldName,
122
+ headerName: t(tableField?.fieldLabel || tableField?.fieldName),
123
+ headerAlign: "center",
124
+ align: "center",
125
+ hidden: tableField?.hidden,
126
+ searchable: tableField?.gridProps?.searchable,
127
+ valueField: tableField?.optionValueField || "value",
128
+ displayField: tableField?.optionDisplayField || "display",
129
+ options: tableField?.options || [],
130
+ flex: 1,
131
+ minWidth: 200,
132
+ });
133
+ columns.push(column);
134
+ }
135
+ }
136
+ return columns;
137
+ };
138
+
139
+ export const constructValidationSchema = (fields: Array<RecordFieldProps>) => {
140
+ const validationSchemaObj: any = {};
141
+ for (const field of fields) {
142
+ if (field?.fieldName) {
143
+ const fieldName = field.fieldName;
144
+ if (field.fieldType === "number") {
145
+ if (field?.required === true) {
146
+ validationSchemaObj[fieldName] = z.number({
147
+ required_error: "This field is required",
148
+ invalid_type_error: "This field must be a number",
149
+ });
150
+ } else {
151
+ validationSchemaObj[fieldName] = z.number().optional().nullable();
152
+ }
153
+ } else {
154
+ if (field?.required === true) {
155
+ validationSchemaObj[fieldName] = z
156
+ .string({ message: "This field is required" })
157
+ .min(1, "This field is required");
158
+ } else {
159
+ validationSchemaObj[fieldName] = z.string().optional().nullable();
160
+ }
161
+ }
162
+ }
163
+ }
164
+ return validationSchemaObj;
165
+ };
166
+
167
+ export type GridSelection = {
168
+ selectedRecords: Array<any>;
169
+ selectedRecordIds: Array<any>;
170
+ };
171
+
172
+ export const getGridSelection: (
173
+ rowSelectionModel: GridRowSelectionModel,
174
+ data: Array<any>,
175
+ keyColumnName: string
176
+ ) => GridSelection = (
177
+ rowSelectionModel: GridRowSelectionModel,
178
+ data: Array<any>,
179
+ keyColumnName: string
180
+ ) => {
181
+ const sRecords = [];
182
+ const sRecordIds = [];
183
+ if (
184
+ rowSelectionModel.type === "exclude" &&
185
+ rowSelectionModel.ids.size === 0
186
+ ) {
187
+ for (const record of data) {
188
+ sRecords.push(record);
189
+ sRecordIds.push(record[keyColumnName]);
190
+ }
191
+ } else {
192
+ if (rowSelectionModel?.ids) {
193
+ for (const selectedId of rowSelectionModel.ids) {
194
+ const record = data.find((x) => x[keyColumnName] === selectedId);
195
+ sRecords.push(record);
196
+ sRecordIds.push(selectedId);
197
+ }
198
+ }
199
+ }
200
+ return { selectedRecords: sRecords, selectedRecordIds: sRecordIds };
201
+ };