@asaleh37/ui-base 1.2.30 → 25.6.2-0.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.
Files changed (161) hide show
  1. package/.github/workflows/publish-npm.yml +31 -0
  2. package/README.md +51 -51
  3. package/dist/index.d.ts +3 -3
  4. package/dist/index.js +3 -3
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +5 -5
  7. package/dist/index.mjs.map +1 -1
  8. package/eslint.config.js +29 -29
  9. package/index.html +13 -13
  10. package/package.json +120 -119
  11. package/rollup.config-1748377725725.cjs +50 -50
  12. package/rollup.config.js +45 -45
  13. package/src/components/App.tsx +123 -123
  14. package/src/components/BaseApp.tsx +53 -53
  15. package/src/components/administration/admin/OrgMemberRoleForm.tsx +83 -83
  16. package/src/components/administration/admin/OrganizationApplicationModuleGrid.tsx +107 -107
  17. package/src/components/administration/admin/OrganizationGrid.tsx +82 -82
  18. package/src/components/administration/admin/OrganizationMemberGrid.tsx +176 -176
  19. package/src/components/administration/admin/OrganizationMemberRoleGrid.tsx +87 -87
  20. package/src/components/administration/admin/OrganizationRankGrid.tsx +133 -133
  21. package/src/components/administration/admin/OrganizationUnitGrid.tsx +143 -143
  22. package/src/components/administration/admin/OrganizationUnitTypeGrid.tsx +108 -108
  23. package/src/components/administration/admin/PersonGrid.tsx +231 -231
  24. package/src/components/administration/admin/RoleAuthoritiesForm.tsx +82 -82
  25. package/src/components/administration/admin/SystemApplicationAuthorityGrid.tsx +126 -126
  26. package/src/components/administration/admin/SystemApplicationGrid.tsx +83 -83
  27. package/src/components/administration/admin/SystemApplicationModuleGrid.tsx +96 -96
  28. package/src/components/administration/admin/SystemApplicationRoleAuthorityGrid.tsx +67 -67
  29. package/src/components/administration/admin/SystemApplicationRoleGrid.tsx +116 -116
  30. package/src/components/administration/dev/AttachmentConfigGrid.tsx +223 -213
  31. package/src/components/administration/dev/AttachmentGrid.tsx +172 -172
  32. package/src/components/administration/dev/BluePrintGrid.tsx +129 -129
  33. package/src/components/administration/dev/DashboardGrid.tsx +173 -173
  34. package/src/components/administration/dev/DashboardWidgetGrid.tsx +164 -164
  35. package/src/components/administration/dev/DataQueryGrid.tsx +206 -206
  36. package/src/components/administration/dev/DataQueryParameterGrid.tsx +191 -191
  37. package/src/components/administration/dev/DataQueryParametersForm.tsx +84 -84
  38. package/src/components/administration/dev/DatasourceConnectionGrid.tsx +150 -150
  39. package/src/components/administration/dev/EntityParameterGrid.tsx +279 -279
  40. package/src/components/administration/dev/LookupGrid.tsx +120 -120
  41. package/src/components/administration/dev/MailAttachmentGrid.tsx +155 -155
  42. package/src/components/administration/dev/MailBodyGrid.tsx +216 -216
  43. package/src/components/administration/dev/MailNotificationQueueGrid.tsx +245 -245
  44. package/src/components/administration/dev/MailRecipientGrid.tsx +169 -169
  45. package/src/components/administration/dev/MailSenderConfigGrid.tsx +478 -478
  46. package/src/components/administration/dev/MailTemplateGrid.tsx +384 -384
  47. package/src/components/administration/dev/NotificationGrid.tsx +432 -432
  48. package/src/components/administration/dev/NotificationQueueGrid.tsx +222 -222
  49. package/src/components/administration/dev/ReportGrid.tsx +506 -504
  50. package/src/components/administration/dev/ReportParameterGrid.tsx +186 -186
  51. package/src/components/administration/dev/ReportParametersForm.tsx +84 -84
  52. package/src/components/administration/dev/WidgetGrid.tsx +431 -431
  53. package/src/components/administration/dev/WorkflowDocumentActionGrid.tsx +264 -264
  54. package/src/components/administration/dev/WorkflowDocumentActionHistoryGrid.tsx +172 -172
  55. package/src/components/administration/dev/WorkflowDocumentActionMailGrid.tsx +161 -161
  56. package/src/components/administration/dev/WorkflowDocumentGrid.tsx +377 -377
  57. package/src/components/administration/dev/WorkflowDocumentMailLogGrid.tsx +218 -218
  58. package/src/components/administration/dev/WorkflowDocumentStatusGrid.tsx +243 -243
  59. package/src/components/common/ChangeOrgForm.tsx +81 -81
  60. package/src/components/common/Home.tsx +43 -44
  61. package/src/components/common/LanguageSwitcher.tsx +25 -25
  62. package/src/components/common/LayoutHandlers.tsx +11 -11
  63. package/src/components/common/LoadingMask.tsx +24 -24
  64. package/src/components/common/Login.tsx +214 -214
  65. package/src/components/common/MyNotificationsPanel.tsx +103 -104
  66. package/src/components/common/NotificationItem.tsx +138 -138
  67. package/src/components/index.ts +9 -9
  68. package/src/components/templates/DataEntryTemplates/DataEntryTypes.ts +324 -324
  69. package/src/components/templates/DataEntryTemplates/DataEntryUtil.ts +248 -248
  70. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormAction.tsx +60 -60
  71. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormElementField.tsx +231 -231
  72. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormElementGroup.tsx +106 -106
  73. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/CheckBox.tsx +64 -64
  74. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/ComboBox.tsx +93 -93
  75. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/Datefield.tsx +65 -65
  76. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/DatetimeField.tsx +64 -64
  77. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/FiltersPanel.tsx +237 -237
  78. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/SystemLookupCombobox.tsx +55 -55
  79. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/TemplateTextField.tsx +17 -17
  80. package/src/components/templates/DataEntryTemplates/TemplateDataForm/TemplateForm.tsx +387 -388
  81. package/src/components/templates/DataEntryTemplates/TemplateDataGrid/DataGridColumnsUtil.tsx +189 -189
  82. package/src/components/templates/DataEntryTemplates/TemplateDataGrid/TemplateGrid.tsx +998 -998
  83. package/src/components/templates/DataEntryTemplates/TemplateDataGrid/TemplateGridMultiRecordAction.tsx +89 -89
  84. package/src/components/templates/DataEntryTemplates/TemplateDataGrid/TemplateGridRecordAction.tsx +95 -95
  85. package/src/components/templates/DataEntryTemplates/TemplateDataGrid/TemplateGridTopBar.tsx +227 -227
  86. package/src/components/templates/TransferList.tsx +257 -257
  87. package/src/components/templates/Window/ConfirmationWindow.tsx +55 -55
  88. package/src/components/templates/attachment/AttachmentCard.tsx +141 -141
  89. package/src/components/templates/attachment/AttachmentImageViewer.tsx +45 -45
  90. package/src/components/templates/attachment/AttachmentPanel.tsx +271 -271
  91. package/src/components/templates/index.ts +33 -33
  92. package/src/components/templates/report/ExcelReportViewer.tsx +71 -72
  93. package/src/components/templates/report/ReportViewer.tsx +382 -383
  94. package/src/components/templates/visuals/DashboardRouteView.tsx +9 -9
  95. package/src/components/templates/visuals/DashboardViewer.tsx +148 -148
  96. package/src/components/templates/visuals/WidgetViewer.tsx +198 -198
  97. package/src/components/templates/visuals/charts/TemplateBarChart.tsx +23 -23
  98. package/src/components/templates/visuals/charts/TemplateDataCard.tsx +35 -35
  99. package/src/components/templates/visuals/charts/TemplateGauge.tsx +21 -21
  100. package/src/components/templates/visuals/charts/TemplateLineChart.tsx +22 -22
  101. package/src/components/templates/visuals/charts/TemplateLineProgress.tsx +42 -42
  102. package/src/components/templates/visuals/charts/TemplatePieChart.tsx +24 -24
  103. package/src/components/templates/workflow/WorkflowDocumentPanel.tsx +606 -606
  104. package/src/components/templates/workflow/WorkflowDocumentTimeLine.tsx +140 -140
  105. package/src/components/templates/workflow/WorkflowRouteComponent.tsx +14 -14
  106. package/src/hooks/UseConfirmationWindow.tsx +54 -54
  107. package/src/hooks/UseMobile.tsx +13 -13
  108. package/src/hooks/UseSession.tsx +40 -40
  109. package/src/hooks/UseWindow.tsx +107 -107
  110. package/src/hooks/index.ts +7 -7
  111. package/src/hooks/useApiActions.ts +124 -124
  112. package/src/hooks/useAxios.tsx +316 -316
  113. package/src/hooks/useInterval.tsx +23 -23
  114. package/src/hooks/useLoadingMask.tsx +16 -16
  115. package/src/hooks/useLookupGridColumn.tsx +35 -35
  116. package/src/index.ts +4 -4
  117. package/src/layout/DrawerHeader.tsx +10 -10
  118. package/src/layout/Layout.tsx +90 -90
  119. package/src/layout/MainContent.tsx +114 -114
  120. package/src/layout/MobileDrawer.tsx +103 -103
  121. package/src/layout/NavigationTree.tsx +295 -291
  122. package/src/layout/NotificationButton.tsx +207 -207
  123. package/src/layout/RouteWrapper.tsx +36 -36
  124. package/src/layout/SideBar.tsx +85 -85
  125. package/src/layout/TopBar.tsx +215 -217
  126. package/src/locales/arabic/adminLocalsAr.json +93 -93
  127. package/src/locales/arabic/common.json +44 -44
  128. package/src/locales/arabic/devLocalsAr.json +317 -317
  129. package/src/locales/arabic/index.ts +9 -9
  130. package/src/locales/english/adminLocalsEn.json +96 -96
  131. package/src/locales/english/common.json +43 -43
  132. package/src/locales/english/devLocalsEn.json +318 -318
  133. package/src/locales/english/index.ts +9 -9
  134. package/src/locales/i18n.ts +8 -8
  135. package/src/locales/index.ts +9 -9
  136. package/src/main.tsx +23 -23
  137. package/src/navigationItems/Administration/adminNavigationItems.tsx +222 -222
  138. package/src/navigationItems/Administration/index.tsx +16 -16
  139. package/src/navigationItems/common/CommonNavigationItems.tsx +12 -12
  140. package/src/navigationItems/common/index.tsx +7 -7
  141. package/src/navigationItems/index.tsx +34 -34
  142. package/src/redux/features/administration/AdministrationStoresMetaData.ts +126 -126
  143. package/src/redux/features/common/AppInfoSlice.ts +63 -63
  144. package/src/redux/features/common/AppLayoutSlice.ts +29 -29
  145. package/src/redux/features/common/CommonStoreSlice.ts +44 -44
  146. package/src/redux/features/common/LoadingMaskSlice.ts +30 -30
  147. package/src/redux/features/common/SideBarSlice.ts +27 -27
  148. package/src/redux/features/common/UserSessionSlice.ts +54 -54
  149. package/src/redux/store.ts +29 -29
  150. package/src/routes/administration/adminRoutes.tsx +99 -99
  151. package/src/routes/administration/devRoutes.tsx +129 -129
  152. package/src/routes/administration/index.ts +8 -8
  153. package/src/routes/index.ts +11 -11
  154. package/src/routes/types/index.ts +5 -5
  155. package/src/styles/index.css +19 -19
  156. package/src/types/index.ts +8 -7
  157. package/src/util/AppUtils.ts +53 -53
  158. package/src/util/constants.ts +6 -6
  159. package/src/util/index.ts +2 -2
  160. package/tsconfig.json +135 -135
  161. package/vite.config.ts +36 -23
@@ -1,383 +1,382 @@
1
- import { useEffect, useState } from "react";
2
- import { useAxios, useWindow } from "../../../hooks";
3
- import TemplateForm from "../DataEntryTemplates/TemplateDataForm/TemplateForm";
4
- import { useTranslation } from "react-i18next";
5
- import { FormElementProps } from "../DataEntryTemplates/DataEntryTypes";
6
- import {
7
- Accordion,
8
- AccordionDetails,
9
- AccordionSummary,
10
- Box,
11
- Icon,
12
- IconButton,
13
- Typography,
14
- } from "@mui/material";
15
- import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
16
- import ExcelReportViewer from "./ExcelReportViewer";
17
- import { GridExpandMoreIcon } from "@mui/x-data-grid-premium";
18
-
19
- type ReportViewerState =
20
- | "ERROR"
21
- | "WAITING_REPORT_CODE"
22
- | "LOADING_METADATA"
23
- | "WAITING_PARAMETER_INPUT"
24
- | "WAITING_RESULT"
25
- | "SHOWING_RESULT";
26
-
27
- type ReportViewerProps = {
28
- reportCode: string;
29
- resultMode: "Request" | "App";
30
- reportParametersValues?: { [key: string]: any };
31
- byPassParameterEntry?: boolean;
32
- jasperOutPutFileType?: "pdf" | "word" | "excel";
33
- };
34
-
35
- type ReportParameter = {
36
- parameterCode: string;
37
- parameterLabel: string;
38
- parameterValueFormat?: string;
39
- parameterValueField?: string;
40
- parameterDisplayField?: string;
41
- parameterDataset?: Array<any>;
42
- parameterDataQueryId?: number;
43
- hidden?: boolean;
44
- mandatory?: boolean;
45
- defaultValue?: any;
46
- parameterType:
47
- | "text"
48
- | "number"
49
- | "date"
50
- | "datetime"
51
- | "combobox"
52
- | "checkbox"
53
- | "html"
54
- | "lookup";
55
- };
56
-
57
- const ReportViewer: React.FC<ReportViewerProps> = (props) => {
58
- const [blobUrl, setBlobUrl] = useState(null);
59
- const [errorMessage, setErrorMessage] = useState(null);
60
- const [excelReportData, setExcelReportData] = useState<Array<any>>([]);
61
- const [reportViewerState, setReportViewerState] = useState<ReportViewerState>(
62
- "WAITING_REPORT_CODE"
63
- );
64
- const { handleGetRequest, handlePostRequest, HandleDownloadHTTPPostPDF } =
65
- useAxios();
66
- const [reportInfo, setReportInfo] = useState<any>(null);
67
- const [reportParametersValues, setReportParametersValues] = useState<any>({
68
- ...props?.reportParametersValues,
69
- });
70
- const [reportParametersElements, setReportParametersElements] = useState<
71
- Array<FormElementProps>
72
- >([]);
73
- const { t } = useTranslation();
74
-
75
- const getFormElementsFromReportParameters = (
76
- reportParameters: Array<ReportParameter>
77
- ) => {
78
- const formElements: Array<FormElementProps> = [];
79
- for (const reportParameter of reportParameters) {
80
- const formElement: FormElementProps = {
81
- type: "field",
82
- mode: "props",
83
- props: {
84
- fieldLabel: reportParameter?.parameterLabel,
85
- fieldName: reportParameter?.parameterCode,
86
- fieldType: reportParameter?.parameterType,
87
- hidden: reportParameter?.hidden,
88
- formProps: { fieldSize: { lg: 4, md: 6, sm: 12 } },
89
- required: reportParameter?.mandatory,
90
- defaultValue:
91
- reportParametersValues[reportParameter?.parameterCode] ||
92
- reportParameter?.defaultValue,
93
- },
94
- };
95
- formElements.push(formElement);
96
- }
97
- return formElements;
98
- };
99
- const loadReportData = async () => {
100
- setReportViewerState("LOADING_METADATA");
101
- await handleGetRequest({
102
- endPointURI: "api/v1/public/report/metadata",
103
- showMask: true,
104
- parameters: { reportCode: props.reportCode },
105
- successCallBkFn: (response: any) => {
106
- setReportInfo(response.data);
107
- setReportParametersElements(
108
- getFormElementsFromReportParameters(response.data.reportParameters)
109
- );
110
- if (
111
- props?.byPassParameterEntry === true ||
112
- response.data.reportParameters.length == 0
113
- ) {
114
- runReport(response.data, reportParametersValues);
115
- setReportViewerState("WAITING_RESULT");
116
- } else {
117
- setReportViewerState("WAITING_PARAMETER_INPUT");
118
- }
119
- },
120
- failureCallBkFn: (response) => {
121
- setErrorMessage(
122
- "Failed loading report metadata ... contact your administrator"
123
- );
124
- setReportViewerState("ERROR");
125
- },
126
- });
127
- };
128
-
129
- const runReport = async (reportInfoProp, params) => {
130
- setReportViewerState("WAITING_RESULT");
131
- if (reportInfoProp?.reportType === "Excel") {
132
- await handlePostRequest({
133
- endPointURI: "api/v1/public/report/run",
134
- showMask: true,
135
- data: {
136
- reportCode: props.reportCode,
137
- parameters: params,
138
- resultMode: props.resultMode,
139
- jasperOutPutFileType: props.jasperOutPutFileType,
140
- },
141
- successCallBkFn: (response: any) => {
142
- setReportViewerState("SHOWING_RESULT");
143
- setExcelReportData(response.data);
144
- },
145
- });
146
- } else if (reportInfoProp?.reportType) {
147
- await HandleDownloadHTTPPostPDF({
148
- endPointURI: "api/v1/public/report/run",
149
- showMask: true,
150
- data: {
151
- reportCode: props.reportCode,
152
- parameters: params,
153
- resultMode: props.resultMode,
154
- jasperOutPutFileType: props.jasperOutPutFileType,
155
- },
156
- successCallBkFn: (response: any) => {
157
- setReportViewerState("SHOWING_RESULT");
158
- const contentDisposition = response.headers["content-disposition"];
159
- debugger;
160
- let filename = "downloaded_file";
161
- if (
162
- contentDisposition &&
163
- contentDisposition.indexOf("filename=") !== -1
164
- ) {
165
- const match = contentDisposition.match(/filename="?([^"]+)"?/);
166
- if (match && match[1]) filename = match[1];
167
- }
168
- if (filename.includes("pdf")) {
169
- const file = new Blob([response.data], { type: "application/pdf" });
170
- const url = URL.createObjectURL(file);
171
- setBlobUrl(url);
172
- } else {
173
- const blob = new Blob([response.data], {
174
- type: response.headers["content-type"],
175
- });
176
- // Create a temporary anchor element
177
- const url = window.URL.createObjectURL(blob);
178
- const link = document.createElement("a");
179
- link.href = url;
180
- // Optional: Try to get filename from response headers
181
-
182
- link.download = filename;
183
- document.body.appendChild(link);
184
- link.click();
185
-
186
- // Clean up
187
- document.body.removeChild(link);
188
- window.URL.revokeObjectURL(url);
189
- }
190
- console.log(response);
191
- },
192
- failureCallBkFn: (response) => {
193
- setErrorMessage(
194
- "Failed To run report ... contact your administrator"
195
- );
196
- setReportViewerState("ERROR");
197
- },
198
- });
199
- }
200
- };
201
-
202
- useEffect(() => {
203
- if (props?.reportCode) {
204
- loadReportData();
205
- }
206
- }, [
207
- props.reportCode,
208
- props.byPassParameterEntry,
209
- props.reportParametersValues,
210
- props.jasperOutPutFileType,
211
- props.resultMode,
212
- ]);
213
-
214
- return (
215
- <>
216
- <Box
217
- sx={{
218
- display: "flex",
219
- alignItems: "center",
220
- justifyContent: "center",
221
- width: "100%",
222
- }}
223
- >
224
- <Box sx={{ flex: 1, textAlign: "center", marginBottom: 1 }}>
225
- <FontAwesomeIcon
226
- icon={
227
- reportInfo?.reportType === "Excel" ? "file-excel" : "file-pdf"
228
- }
229
- color={reportInfo?.reportType === "Excel" ? "darkgreen" : "darkred"}
230
- style={{ marginRight: 10, marginLeft: 10 }}
231
- />
232
- {reportInfo?.reportName}
233
- </Box>
234
- {reportInfo?.reportType != "Excel" ? (
235
- reportViewerState === "SHOWING_RESULT" ? (
236
- <>
237
- {props?.byPassParameterEntry === true ? (
238
- <></>
239
- ) : reportParametersElements.length > 0 ? (
240
- <IconButton
241
- onClick={() => {
242
- setReportParametersElements(
243
- getFormElementsFromReportParameters(
244
- reportInfo.reportParameters
245
- )
246
- );
247
- setReportViewerState("WAITING_PARAMETER_INPUT");
248
- }}
249
- >
250
- <FontAwesomeIcon icon="filter" />
251
- </IconButton>
252
- ) : (
253
- <></>
254
- )}
255
- <IconButton>
256
- <FontAwesomeIcon
257
- icon="refresh"
258
- onClick={() => {
259
- runReport(reportInfo, reportParametersValues);
260
- }}
261
- />
262
- </IconButton>
263
- </>
264
- ) : (
265
- <></>
266
- )
267
- ) : (
268
- <></>
269
- )}
270
- </Box>
271
- <Box
272
- sx={{
273
- flexGrow: 1,
274
- width: "100%",
275
- display: "flex",
276
- flexDirection: "column",
277
- alignItems: "center",
278
- justifyContent: "flex-start",
279
- }}
280
- >
281
- {reportViewerState === "WAITING_PARAMETER_INPUT" &&
282
- reportInfo?.reportType != "Excel" ? (
283
- <Accordion defaultExpanded sx={{ width: "100%" }} expanded={true}>
284
- <AccordionSummary>
285
- <Box
286
- sx={{
287
- display: "flex",
288
- alignItems: "center",
289
- justifyContent: "center",
290
- }}
291
- >
292
- <FontAwesomeIcon
293
- style={{ marginLeft: 5, marginRight: 5 }}
294
- icon="search"
295
- />
296
- <Typography component="span">Filters</Typography>
297
- </Box>
298
- </AccordionSummary>
299
- <AccordionDetails>
300
- <Box>
301
- <TemplateForm
302
- saveButtonSpecs={{
303
- label: t("SHOW_REPORT_BTN_LABEL"),
304
- icon: "search",
305
- actionButtonVariant: "outlined",
306
- actionButtonColor: "success",
307
- hidden: true,
308
- }}
309
- cancelButtonSpecs={{
310
- label: t("RESET_BTN_LABEL"),
311
- icon: "eraser",
312
- actionButtonVariant: "outlined",
313
- actionButtonColor: "error",
314
- }}
315
- apiActions={{
316
- deleteRecordById: async () => {
317
- return true;
318
- },
319
- saveRecord: async (params) => {
320
- if (params != undefined) {
321
- setReportParametersValues(params);
322
- } else {
323
- setReportParametersValues({});
324
- }
325
- runReport(reportInfo, params);
326
- },
327
- reloadData: async () => {},
328
- loadRecordById: async () => {},
329
- }}
330
- elements={reportParametersElements}
331
- />
332
- </Box>
333
- </AccordionDetails>
334
- </Accordion>
335
- ) : reportViewerState === "SHOWING_RESULT" ||
336
- ((reportViewerState === "WAITING_PARAMETER_INPUT" ||
337
- reportViewerState === "WAITING_RESULT") &&
338
- reportInfo?.reportType === "Excel") ? (
339
- reportInfo?.reportType === "Excel" ? (
340
- <ExcelReportViewer
341
- reportData={excelReportData}
342
- setReportData={setExcelReportData}
343
- reloadReport={async () => {
344
- runReport(reportInfo, reportParametersValues);
345
- }}
346
- gridLoadParameters={reportParametersElements}
347
- gridLoadParametersValues={reportParametersValues}
348
- setGridLoadParametersValues={setReportParametersValues}
349
- />
350
- ) : (
351
- <iframe
352
- src={blobUrl}
353
- width="100%"
354
- height="100%"
355
- title="PDF Preview"
356
- style={{ border: "1px solid #ccc", marginTop: "20px" }}
357
- ></iframe>
358
- )
359
- ) : reportViewerState === "ERROR" ? (
360
- <Box
361
- sx={{
362
- display: "flex",
363
- flex: 1,
364
- alignItems: "center",
365
- justifyContent: "center",
366
- }}
367
- >
368
- <FontAwesomeIcon
369
- icon="circle-exclamation"
370
- color="darkred"
371
- style={{ marginRight: 10, marginLeft: 10 }}
372
- />
373
- {errorMessage}
374
- </Box>
375
- ) : (
376
- <></>
377
- )}
378
- </Box>
379
- </>
380
- );
381
- };
382
-
383
- export default ReportViewer;
1
+ import { useEffect, useState } from "react";
2
+ import { useAxios, useWindow } from "../../../hooks";
3
+ import TemplateForm from "../DataEntryTemplates/TemplateDataForm/TemplateForm";
4
+ import { useTranslation } from "react-i18next";
5
+ import { FormElementProps } from "../DataEntryTemplates/DataEntryTypes";
6
+ import {
7
+ Accordion,
8
+ AccordionDetails,
9
+ AccordionSummary,
10
+ Box,
11
+ Icon,
12
+ IconButton,
13
+ Typography,
14
+ } from "@mui/material";
15
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
16
+ import ExcelReportViewer from "./ExcelReportViewer";
17
+ import { GridExpandMoreIcon } from "@mui/x-data-grid-premium";
18
+
19
+ type ReportViewerState =
20
+ | "ERROR"
21
+ | "WAITING_REPORT_CODE"
22
+ | "LOADING_METADATA"
23
+ | "WAITING_PARAMETER_INPUT"
24
+ | "WAITING_RESULT"
25
+ | "SHOWING_RESULT";
26
+
27
+ type ReportViewerProps = {
28
+ reportCode: string;
29
+ resultMode: "Request" | "App";
30
+ reportParametersValues?: { [key: string]: any };
31
+ byPassParameterEntry?: boolean;
32
+ jasperOutPutFileType?: "pdf" | "word" | "excel";
33
+ };
34
+
35
+ type ReportParameter = {
36
+ parameterCode: string;
37
+ parameterLabel: string;
38
+ parameterValueFormat?: string;
39
+ parameterValueField?: string;
40
+ parameterDisplayField?: string;
41
+ parameterDataset?: Array<any>;
42
+ parameterDataQueryId?: number;
43
+ hidden?: boolean;
44
+ mandatory?: boolean;
45
+ defaultValue?: any;
46
+ parameterType:
47
+ | "text"
48
+ | "number"
49
+ | "date"
50
+ | "datetime"
51
+ | "combobox"
52
+ | "checkbox"
53
+ | "html"
54
+ | "lookup";
55
+ };
56
+
57
+ const ReportViewer: React.FC<ReportViewerProps> = (props) => {
58
+ const [blobUrl, setBlobUrl] = useState(null);
59
+ const [errorMessage, setErrorMessage] = useState(null);
60
+ const [excelReportData, setExcelReportData] = useState<Array<any>>([]);
61
+ const [reportViewerState, setReportViewerState] = useState<ReportViewerState>(
62
+ "WAITING_REPORT_CODE"
63
+ );
64
+ const { handleGetRequest, handlePostRequest, HandleDownloadHTTPPostPDF } =
65
+ useAxios();
66
+ const [reportInfo, setReportInfo] = useState<any>(null);
67
+ const [reportParametersValues, setReportParametersValues] = useState<any>({
68
+ ...props?.reportParametersValues,
69
+ });
70
+ const [reportParametersElements, setReportParametersElements] = useState<
71
+ Array<FormElementProps>
72
+ >([]);
73
+ const { t } = useTranslation();
74
+
75
+ const getFormElementsFromReportParameters = (
76
+ reportParameters: Array<ReportParameter>
77
+ ) => {
78
+ const formElements: Array<FormElementProps> = [];
79
+ for (const reportParameter of reportParameters) {
80
+ const formElement: FormElementProps = {
81
+ type: "field",
82
+ mode: "props",
83
+ props: {
84
+ fieldLabel: reportParameter?.parameterLabel,
85
+ fieldName: reportParameter?.parameterCode,
86
+ fieldType: reportParameter?.parameterType,
87
+ hidden: reportParameter?.hidden,
88
+ formProps: { fieldSize: { lg: 4, md: 6, sm: 12 } },
89
+ required: reportParameter?.mandatory,
90
+ defaultValue:
91
+ reportParametersValues[reportParameter?.parameterCode] ||
92
+ reportParameter?.defaultValue,
93
+ },
94
+ };
95
+ formElements.push(formElement);
96
+ }
97
+ return formElements;
98
+ };
99
+ const loadReportData = async () => {
100
+ setReportViewerState("LOADING_METADATA");
101
+ await handleGetRequest({
102
+ endPointURI: "api/v1/public/report/metadata",
103
+ showMask: true,
104
+ parameters: { reportCode: props.reportCode },
105
+ successCallBkFn: (response: any) => {
106
+ setReportInfo(response.data);
107
+ setReportParametersElements(
108
+ getFormElementsFromReportParameters(response.data.reportParameters)
109
+ );
110
+ if (
111
+ props?.byPassParameterEntry === true ||
112
+ response.data.reportParameters.length == 0
113
+ ) {
114
+ runReport(response.data, reportParametersValues);
115
+ setReportViewerState("WAITING_RESULT");
116
+ } else {
117
+ setReportViewerState("WAITING_PARAMETER_INPUT");
118
+ }
119
+ },
120
+ failureCallBkFn: (response) => {
121
+ setErrorMessage(
122
+ "Failed loading report metadata ... contact your administrator"
123
+ );
124
+ setReportViewerState("ERROR");
125
+ },
126
+ });
127
+ };
128
+
129
+ const runReport = async (reportInfoProp, params) => {
130
+ setReportViewerState("WAITING_RESULT");
131
+ if (reportInfoProp?.reportType === "Excel") {
132
+ await handlePostRequest({
133
+ endPointURI: "api/v1/public/report/run",
134
+ showMask: true,
135
+ data: {
136
+ reportCode: props.reportCode,
137
+ parameters: params,
138
+ resultMode: props.resultMode,
139
+ jasperOutPutFileType: props.jasperOutPutFileType,
140
+ },
141
+ successCallBkFn: (response: any) => {
142
+ setReportViewerState("SHOWING_RESULT");
143
+ setExcelReportData(response.data);
144
+ },
145
+ });
146
+ } else if (reportInfoProp?.reportType) {
147
+ await HandleDownloadHTTPPostPDF({
148
+ endPointURI: "api/v1/public/report/run",
149
+ showMask: true,
150
+ data: {
151
+ reportCode: props.reportCode,
152
+ parameters: params,
153
+ resultMode: props.resultMode,
154
+ jasperOutPutFileType: props.jasperOutPutFileType,
155
+ },
156
+ successCallBkFn: (response: any) => {
157
+ setReportViewerState("SHOWING_RESULT");
158
+ const contentDisposition = response.headers["content-disposition"];
159
+ debugger;
160
+ let filename = "downloaded_file";
161
+ if (
162
+ contentDisposition &&
163
+ contentDisposition.indexOf("filename=") !== -1
164
+ ) {
165
+ const match = contentDisposition.match(/filename="?([^"]+)"?/);
166
+ if (match && match[1]) filename = match[1];
167
+ }
168
+ if (filename.includes("pdf")) {
169
+ const file = new Blob([response.data], { type: "application/pdf" });
170
+ const url = URL.createObjectURL(file);
171
+ setBlobUrl(url);
172
+ } else {
173
+ const blob = new Blob([response.data], {
174
+ type: response.headers["content-type"],
175
+ });
176
+ // Create a temporary anchor element
177
+ const url = window.URL.createObjectURL(blob);
178
+ const link = document.createElement("a");
179
+ link.href = url;
180
+ // Optional: Try to get filename from response headers
181
+
182
+ link.download = filename;
183
+ document.body.appendChild(link);
184
+ link.click();
185
+
186
+ // Clean up
187
+ document.body.removeChild(link);
188
+ window.URL.revokeObjectURL(url);
189
+ }
190
+ },
191
+ failureCallBkFn: (response) => {
192
+ setErrorMessage(
193
+ "Failed To run report ... contact your administrator"
194
+ );
195
+ setReportViewerState("ERROR");
196
+ },
197
+ });
198
+ }
199
+ };
200
+
201
+ useEffect(() => {
202
+ if (props?.reportCode) {
203
+ loadReportData();
204
+ }
205
+ }, [
206
+ props.reportCode,
207
+ props.byPassParameterEntry,
208
+ props.reportParametersValues,
209
+ props.jasperOutPutFileType,
210
+ props.resultMode,
211
+ ]);
212
+
213
+ return (
214
+ <>
215
+ <Box
216
+ sx={{
217
+ display: "flex",
218
+ alignItems: "center",
219
+ justifyContent: "center",
220
+ width: "100%",
221
+ }}
222
+ >
223
+ <Box sx={{ flex: 1, textAlign: "center", marginBottom: 1 }}>
224
+ <FontAwesomeIcon
225
+ icon={
226
+ reportInfo?.reportType === "Excel" ? "file-excel" : "file-pdf"
227
+ }
228
+ color={reportInfo?.reportType === "Excel" ? "darkgreen" : "darkred"}
229
+ style={{ marginRight: 10, marginLeft: 10 }}
230
+ />
231
+ {reportInfo?.reportName}
232
+ </Box>
233
+ {reportInfo?.reportType != "Excel" ? (
234
+ reportViewerState === "SHOWING_RESULT" ? (
235
+ <>
236
+ {props?.byPassParameterEntry === true ? (
237
+ <></>
238
+ ) : reportParametersElements.length > 0 ? (
239
+ <IconButton
240
+ onClick={() => {
241
+ setReportParametersElements(
242
+ getFormElementsFromReportParameters(
243
+ reportInfo.reportParameters
244
+ )
245
+ );
246
+ setReportViewerState("WAITING_PARAMETER_INPUT");
247
+ }}
248
+ >
249
+ <FontAwesomeIcon icon="filter" />
250
+ </IconButton>
251
+ ) : (
252
+ <></>
253
+ )}
254
+ <IconButton>
255
+ <FontAwesomeIcon
256
+ icon="refresh"
257
+ onClick={() => {
258
+ runReport(reportInfo, reportParametersValues);
259
+ }}
260
+ />
261
+ </IconButton>
262
+ </>
263
+ ) : (
264
+ <></>
265
+ )
266
+ ) : (
267
+ <></>
268
+ )}
269
+ </Box>
270
+ <Box
271
+ sx={{
272
+ flexGrow: 1,
273
+ width: "100%",
274
+ display: "flex",
275
+ flexDirection: "column",
276
+ alignItems: "center",
277
+ justifyContent: "flex-start",
278
+ }}
279
+ >
280
+ {reportViewerState === "WAITING_PARAMETER_INPUT" &&
281
+ reportInfo?.reportType != "Excel" ? (
282
+ <Accordion defaultExpanded sx={{ width: "100%" }} expanded={true}>
283
+ <AccordionSummary>
284
+ <Box
285
+ sx={{
286
+ display: "flex",
287
+ alignItems: "center",
288
+ justifyContent: "center",
289
+ }}
290
+ >
291
+ <FontAwesomeIcon
292
+ style={{ marginLeft: 5, marginRight: 5 }}
293
+ icon="search"
294
+ />
295
+ <Typography component="span">Filters</Typography>
296
+ </Box>
297
+ </AccordionSummary>
298
+ <AccordionDetails>
299
+ <Box>
300
+ <TemplateForm
301
+ saveButtonSpecs={{
302
+ label: t("SHOW_REPORT_BTN_LABEL"),
303
+ icon: "search",
304
+ actionButtonVariant: "outlined",
305
+ actionButtonColor: "success",
306
+ hidden: true,
307
+ }}
308
+ cancelButtonSpecs={{
309
+ label: t("RESET_BTN_LABEL"),
310
+ icon: "eraser",
311
+ actionButtonVariant: "outlined",
312
+ actionButtonColor: "error",
313
+ }}
314
+ apiActions={{
315
+ deleteRecordById: async () => {
316
+ return true;
317
+ },
318
+ saveRecord: async (params) => {
319
+ if (params != undefined) {
320
+ setReportParametersValues(params);
321
+ } else {
322
+ setReportParametersValues({});
323
+ }
324
+ runReport(reportInfo, params);
325
+ },
326
+ reloadData: async () => {},
327
+ loadRecordById: async () => {},
328
+ }}
329
+ elements={reportParametersElements}
330
+ />
331
+ </Box>
332
+ </AccordionDetails>
333
+ </Accordion>
334
+ ) : reportViewerState === "SHOWING_RESULT" ||
335
+ ((reportViewerState === "WAITING_PARAMETER_INPUT" ||
336
+ reportViewerState === "WAITING_RESULT") &&
337
+ reportInfo?.reportType === "Excel") ? (
338
+ reportInfo?.reportType === "Excel" ? (
339
+ <ExcelReportViewer
340
+ reportData={excelReportData}
341
+ setReportData={setExcelReportData}
342
+ reloadReport={async () => {
343
+ runReport(reportInfo, reportParametersValues);
344
+ }}
345
+ gridLoadParameters={reportParametersElements}
346
+ gridLoadParametersValues={reportParametersValues}
347
+ setGridLoadParametersValues={setReportParametersValues}
348
+ />
349
+ ) : (
350
+ <iframe
351
+ src={blobUrl}
352
+ width="100%"
353
+ height="100%"
354
+ title="PDF Preview"
355
+ style={{ border: "1px solid #ccc", marginTop: "20px" }}
356
+ ></iframe>
357
+ )
358
+ ) : reportViewerState === "ERROR" ? (
359
+ <Box
360
+ sx={{
361
+ display: "flex",
362
+ flex: 1,
363
+ alignItems: "center",
364
+ justifyContent: "center",
365
+ }}
366
+ >
367
+ <FontAwesomeIcon
368
+ icon="circle-exclamation"
369
+ color="darkred"
370
+ style={{ marginRight: 10, marginLeft: 10 }}
371
+ />
372
+ {errorMessage}
373
+ </Box>
374
+ ) : (
375
+ <></>
376
+ )}
377
+ </Box>
378
+ </>
379
+ );
380
+ };
381
+
382
+ export default ReportViewer;