@asaleh37/ui-base 25.6.19-6 → 25.6.21

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 (162) hide show
  1. package/.github/workflows/publish-npm.yml +49 -0
  2. package/README.md +51 -51
  3. package/dist/index.d.ts +5 -0
  4. package/dist/index.js +6 -6
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +6 -6
  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 -120
  11. package/public/no_user.png +0 -0
  12. package/rollup.config-1748377725725.cjs +50 -50
  13. package/rollup.config.js +45 -45
  14. package/src/components/App.tsx +123 -123
  15. package/src/components/BaseApp.tsx +53 -53
  16. package/src/components/administration/admin/OrgMemberRoleForm.tsx +83 -83
  17. package/src/components/administration/admin/OrganizationApplicationModuleGrid.tsx +107 -107
  18. package/src/components/administration/admin/OrganizationGrid.tsx +118 -82
  19. package/src/components/administration/admin/OrganizationMemberGrid.tsx +176 -176
  20. package/src/components/administration/admin/OrganizationMemberRoleGrid.tsx +87 -87
  21. package/src/components/administration/admin/OrganizationRankGrid.tsx +133 -133
  22. package/src/components/administration/admin/OrganizationUnitGrid.tsx +143 -143
  23. package/src/components/administration/admin/OrganizationUnitTypeGrid.tsx +108 -108
  24. package/src/components/administration/admin/PersonGrid.tsx +334 -231
  25. package/src/components/administration/admin/RoleAuthoritiesForm.tsx +82 -82
  26. package/src/components/administration/admin/SystemApplicationAuthorityGrid.tsx +117 -126
  27. package/src/components/administration/admin/SystemApplicationGrid.tsx +83 -83
  28. package/src/components/administration/admin/SystemApplicationModuleGrid.tsx +96 -96
  29. package/src/components/administration/admin/SystemApplicationRoleAuthorityGrid.tsx +75 -67
  30. package/src/components/administration/admin/SystemApplicationRoleGrid.tsx +116 -116
  31. package/src/components/administration/dev/AttachmentConfigGrid.tsx +223 -223
  32. package/src/components/administration/dev/AttachmentGrid.tsx +172 -172
  33. package/src/components/administration/dev/BluePrintGrid.tsx +129 -129
  34. package/src/components/administration/dev/DashboardGrid.tsx +173 -173
  35. package/src/components/administration/dev/DashboardWidgetGrid.tsx +164 -164
  36. package/src/components/administration/dev/DataQueryGrid.tsx +206 -206
  37. package/src/components/administration/dev/DataQueryParameterGrid.tsx +191 -191
  38. package/src/components/administration/dev/DataQueryParametersForm.tsx +84 -84
  39. package/src/components/administration/dev/DatasourceConnectionGrid.tsx +150 -150
  40. package/src/components/administration/dev/EntityParameterGrid.tsx +279 -279
  41. package/src/components/administration/dev/LookupGrid.tsx +120 -120
  42. package/src/components/administration/dev/MailAttachmentGrid.tsx +155 -155
  43. package/src/components/administration/dev/MailBodyGrid.tsx +216 -216
  44. package/src/components/administration/dev/MailNotificationQueueGrid.tsx +245 -245
  45. package/src/components/administration/dev/MailRecipientGrid.tsx +169 -169
  46. package/src/components/administration/dev/MailSenderConfigGrid.tsx +478 -478
  47. package/src/components/administration/dev/MailTemplateGrid.tsx +384 -384
  48. package/src/components/administration/dev/NotificationGrid.tsx +432 -432
  49. package/src/components/administration/dev/NotificationQueueGrid.tsx +222 -222
  50. package/src/components/administration/dev/ReportGrid.tsx +506 -506
  51. package/src/components/administration/dev/ReportParameterGrid.tsx +186 -186
  52. package/src/components/administration/dev/ReportParametersForm.tsx +84 -84
  53. package/src/components/administration/dev/WidgetGrid.tsx +431 -431
  54. package/src/components/administration/dev/WorkflowDocumentActionGrid.tsx +264 -264
  55. package/src/components/administration/dev/WorkflowDocumentActionHistoryGrid.tsx +172 -172
  56. package/src/components/administration/dev/WorkflowDocumentActionMailGrid.tsx +161 -161
  57. package/src/components/administration/dev/WorkflowDocumentGrid.tsx +377 -377
  58. package/src/components/administration/dev/WorkflowDocumentMailLogGrid.tsx +218 -218
  59. package/src/components/administration/dev/WorkflowDocumentStatusGrid.tsx +243 -243
  60. package/src/components/common/ChangeOrgForm.tsx +81 -81
  61. package/src/components/common/Home.tsx +43 -43
  62. package/src/components/common/LanguageSwitcher.tsx +25 -25
  63. package/src/components/common/LayoutHandlers.tsx +11 -11
  64. package/src/components/common/LoadingMask.tsx +24 -24
  65. package/src/components/common/Login.tsx +214 -214
  66. package/src/components/common/MyNotificationsPanel.tsx +109 -103
  67. package/src/components/common/NotificationItem.tsx +138 -138
  68. package/src/components/index.ts +9 -9
  69. package/src/components/templates/DataEntryTemplates/DataEntryTypes.ts +324 -324
  70. package/src/components/templates/DataEntryTemplates/DataEntryUtil.ts +248 -248
  71. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormAction.tsx +60 -60
  72. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormElementField.tsx +231 -231
  73. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormElementGroup.tsx +106 -106
  74. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/CheckBox.tsx +64 -64
  75. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/ComboBox.tsx +93 -93
  76. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/Datefield.tsx +65 -65
  77. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/DatetimeField.tsx +64 -64
  78. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/FiltersPanel.tsx +237 -237
  79. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/SystemLookupCombobox.tsx +55 -55
  80. package/src/components/templates/DataEntryTemplates/TemplateDataForm/FormFields/TemplateTextField.tsx +17 -17
  81. package/src/components/templates/DataEntryTemplates/TemplateDataForm/TemplateForm.tsx +387 -387
  82. package/src/components/templates/DataEntryTemplates/TemplateDataGrid/DataGridColumnsUtil.tsx +189 -189
  83. package/src/components/templates/DataEntryTemplates/TemplateDataGrid/TemplateGrid.tsx +998 -998
  84. package/src/components/templates/DataEntryTemplates/TemplateDataGrid/TemplateGridMultiRecordAction.tsx +89 -89
  85. package/src/components/templates/DataEntryTemplates/TemplateDataGrid/TemplateGridRecordAction.tsx +95 -95
  86. package/src/components/templates/DataEntryTemplates/TemplateDataGrid/TemplateGridTopBar.tsx +227 -227
  87. package/src/components/templates/TransferList.tsx +257 -257
  88. package/src/components/templates/Window/ConfirmationWindow.tsx +55 -55
  89. package/src/components/templates/attachment/AttachmentCard.tsx +141 -141
  90. package/src/components/templates/attachment/AttachmentImageViewer.tsx +83 -45
  91. package/src/components/templates/attachment/AttachmentPanel.tsx +285 -271
  92. package/src/components/templates/index.ts +33 -33
  93. package/src/components/templates/report/ExcelReportViewer.tsx +71 -71
  94. package/src/components/templates/report/ReportViewer.tsx +382 -382
  95. package/src/components/templates/visuals/DashboardRouteView.tsx +9 -9
  96. package/src/components/templates/visuals/DashboardViewer.tsx +148 -148
  97. package/src/components/templates/visuals/WidgetViewer.tsx +198 -198
  98. package/src/components/templates/visuals/charts/TemplateBarChart.tsx +23 -23
  99. package/src/components/templates/visuals/charts/TemplateDataCard.tsx +35 -35
  100. package/src/components/templates/visuals/charts/TemplateGauge.tsx +21 -21
  101. package/src/components/templates/visuals/charts/TemplateLineChart.tsx +22 -22
  102. package/src/components/templates/visuals/charts/TemplateLineProgress.tsx +42 -42
  103. package/src/components/templates/visuals/charts/TemplatePieChart.tsx +24 -24
  104. package/src/components/templates/workflow/WorkflowDocumentPanel.tsx +606 -606
  105. package/src/components/templates/workflow/WorkflowDocumentTimeLine.tsx +140 -140
  106. package/src/components/templates/workflow/WorkflowRouteComponent.tsx +14 -14
  107. package/src/hooks/UseConfirmationWindow.tsx +54 -54
  108. package/src/hooks/UseMobile.tsx +13 -13
  109. package/src/hooks/UseSession.tsx +59 -40
  110. package/src/hooks/UseWindow.tsx +107 -107
  111. package/src/hooks/index.ts +7 -7
  112. package/src/hooks/useApiActions.ts +124 -124
  113. package/src/hooks/useAxios.tsx +316 -316
  114. package/src/hooks/useInterval.tsx +23 -23
  115. package/src/hooks/useLoadingMask.tsx +16 -16
  116. package/src/hooks/useLookupGridColumn.tsx +35 -35
  117. package/src/index.ts +4 -4
  118. package/src/layout/DrawerHeader.tsx +10 -10
  119. package/src/layout/Layout.tsx +90 -90
  120. package/src/layout/MainContent.tsx +117 -114
  121. package/src/layout/MobileDrawer.tsx +103 -103
  122. package/src/layout/NavigationTree.tsx +298 -293
  123. package/src/layout/NotificationButton.tsx +207 -207
  124. package/src/layout/RouteWrapper.tsx +63 -36
  125. package/src/layout/SideBar.tsx +85 -85
  126. package/src/layout/TopBar.tsx +229 -215
  127. package/src/locales/arabic/adminLocalsAr.json +93 -93
  128. package/src/locales/arabic/common.json +44 -44
  129. package/src/locales/arabic/devLocalsAr.json +317 -317
  130. package/src/locales/arabic/index.ts +9 -9
  131. package/src/locales/english/adminLocalsEn.json +96 -96
  132. package/src/locales/english/common.json +43 -43
  133. package/src/locales/english/devLocalsEn.json +318 -318
  134. package/src/locales/english/index.ts +9 -9
  135. package/src/locales/i18n.ts +8 -8
  136. package/src/locales/index.ts +9 -9
  137. package/src/main.tsx +23 -23
  138. package/src/navigationItems/Administration/adminNavigationItems.tsx +223 -222
  139. package/src/navigationItems/Administration/index.tsx +16 -16
  140. package/src/navigationItems/common/CommonNavigationItems.tsx +12 -12
  141. package/src/navigationItems/common/index.tsx +7 -7
  142. package/src/navigationItems/index.tsx +35 -34
  143. package/src/redux/features/administration/AdministrationStoresMetaData.ts +148 -126
  144. package/src/redux/features/common/AppInfoSlice.ts +65 -63
  145. package/src/redux/features/common/AppLayoutSlice.ts +29 -29
  146. package/src/redux/features/common/CommonStoreSlice.ts +44 -44
  147. package/src/redux/features/common/LoadingMaskSlice.ts +30 -30
  148. package/src/redux/features/common/SideBarSlice.ts +27 -27
  149. package/src/redux/features/common/UserSessionSlice.ts +54 -54
  150. package/src/redux/store.ts +29 -29
  151. package/src/routes/administration/adminRoutes.tsx +99 -99
  152. package/src/routes/administration/devRoutes.tsx +129 -129
  153. package/src/routes/administration/index.ts +8 -8
  154. package/src/routes/index.ts +11 -11
  155. package/src/routes/types/index.ts +6 -5
  156. package/src/styles/index.css +19 -19
  157. package/src/types/index.ts +8 -8
  158. package/src/util/AppUtils.ts +53 -53
  159. package/src/util/constants.ts +6 -6
  160. package/src/util/index.ts +2 -2
  161. package/tsconfig.json +135 -135
  162. package/vite.config.ts +24 -36
@@ -1,382 +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
- },
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;
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;