ui-soxo-bootstrap-core 2.6.59 → 2.6.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.babelrc +8 -8
- package/.github/workflows/npm-publish.yml +41 -41
- package/.husky/pre-commit +11 -11
- package/.prettierrc.json +10 -10
- package/DEVELOPER_GUIDE.md +294 -294
- package/PUBLISHING.md +333 -333
- package/babel.config.js +2 -2
- package/core/components/component-loader/component-loader.js +125 -125
- package/core/components/component-wrapper/component-wrapper.js +121 -121
- package/core/components/external-window/DEVELOPER_GUIDE.md +705 -705
- package/core/components/external-window/external-window.js +236 -236
- package/core/components/external-window/external-window.test.js +80 -80
- package/core/components/extra-info/extra-info-details.js +155 -155
- package/core/components/extra-info/extra-info-details.scss +26 -26
- package/core/components/extra-info/extra-info.js +134 -134
- package/core/components/index.js +14 -14
- package/core/components/landing-api/landing-api.js +733 -733
- package/core/components/landing-api/landing-api.scss +41 -41
- package/core/components/license-management/license-alert.js +97 -97
- package/core/components/menu-template-api/menu-template-api.js +321 -321
- package/core/components/root-application-api/root-application-api.js +174 -174
- package/core/index.js +13 -13
- package/core/lib/Store.js +375 -375
- package/core/lib/components/application-bootstrap/application-bootstrap.js +115 -115
- package/core/lib/components/approval-form/approval-form.js +280 -280
- package/core/lib/components/approval-form/approval-form.scss +183 -183
- package/core/lib/components/approval-list/approval-list.js +143 -143
- package/core/lib/components/approval-list/approval-list.scss +2 -2
- package/core/lib/components/approval-list/components/request-card/request-card.js +42 -42
- package/core/lib/components/approval-list/components/request-card/request-card.scss +30 -30
- package/core/lib/components/camera/camera.js +230 -230
- package/core/lib/components/camera/camera.scss +86 -86
- package/core/lib/components/comment-block/comment-block.js +138 -138
- package/core/lib/components/comment-block/comment-block.scss +3 -3
- package/core/lib/components/confirm-modal/confirm-modal.js +82 -82
- package/core/lib/components/confirm-modal/confirm-modal.scss +2 -2
- package/core/lib/components/consent/consent.js +67 -67
- package/core/lib/components/consent/pdf-signature.js +299 -299
- package/core/lib/components/consent/signature-pad.js +227 -227
- package/core/lib/components/consent/signature-pad.scss +23 -23
- package/core/lib/components/file-upload/file-upload.js +133 -133
- package/core/lib/components/finger-print-reader/finger-print-reader.js +295 -295
- package/core/lib/components/finger-print-reader/finger-print-reader.scss +47 -47
- package/core/lib/components/finger-print-search/finger-print-search.js +200 -200
- package/core/lib/components/finger-print-search/finger-print-search.scss +47 -47
- package/core/lib/components/global-header/animations.js +18 -18
- package/core/lib/components/global-header/global-header.js +293 -293
- package/core/lib/components/global-header/global-header.scss +399 -399
- package/core/lib/components/header/generic-header.js +76 -76
- package/core/lib/components/header/generic-header.scss +99 -99
- package/core/lib/components/image-preview/image-preview.js +33 -33
- package/core/lib/components/image-wrapper/image-wrapper.js +108 -108
- package/core/lib/components/image-wrapper/image-wrapper.scss +12 -12
- package/core/lib/components/index.js +206 -206
- package/core/lib/components/landing/landing.js +403 -403
- package/core/lib/components/language-switcher/language-switcher.js +49 -49
- package/core/lib/components/menu-context/menu-context.js +69 -69
- package/core/lib/components/menu-template/menu-template.js +249 -249
- package/core/lib/components/menu-template/menu-template.scss +9 -9
- package/core/lib/components/modal-search/modal-search.js +153 -153
- package/core/lib/components/modal-search/modal-search.scss +78 -78
- package/core/lib/components/modal-wrapper/modal-manager.js +15 -15
- package/core/lib/components/modal-wrapper/modal-wrapper.js +108 -108
- package/core/lib/components/modal-wrapper/modal-wrapper.scss +13 -13
- package/core/lib/components/notice-board/notice-board.js +132 -132
- package/core/lib/components/notice-board/notice-board.scss +65 -65
- package/core/lib/components/page-container/page-container.js +55 -55
- package/core/lib/components/page-container/page-container.scss +8 -8
- package/core/lib/components/page-header/page-header.js +23 -23
- package/core/lib/components/page-header/page-header.scss +17 -17
- package/core/lib/components/pdf-viewer/pdf-viewer.js +56 -56
- package/core/lib/components/portlet-table/components/table-actions/table-actions.js +58 -58
- package/core/lib/components/portlet-table/components/table-actions/table-actions.scss +1 -1
- package/core/lib/components/portlet-table/components/table-data/table-data.js +106 -106
- package/core/lib/components/portlet-table/portlet-table.js +63 -63
- package/core/lib/components/portlet-table/portlet-table.scss +90 -90
- package/core/lib/components/progress-bar/progress-bar.js +58 -58
- package/core/lib/components/progress-bar/progress-bar.scss +15 -15
- package/core/lib/components/request-form/request-form.js +110 -110
- package/core/lib/components/root-application/root-application.js +70 -70
- package/core/lib/components/rupee/rupee.js +14 -14
- package/core/lib/components/script-input/script-input.js +169 -169
- package/core/lib/components/script-input/script-input.scss +8 -8
- package/core/lib/components/sidemenu/animations.js +51 -51
- package/core/lib/components/sidemenu/sidemenu.js +632 -632
- package/core/lib/components/sidemenu/sidemenu.scss +314 -314
- package/core/lib/components/spotlight-search/spotlight-search.component.js +635 -635
- package/core/lib/components/spotlight-search/spotlight-search.component.scss +78 -78
- package/core/lib/components/table-wrapper/table-wrapper.js +135 -135
- package/core/lib/components/table-wrapper/table-wrapper.scss +72 -72
- package/core/lib/components/ui_elements/Loader.js +12 -12
- package/core/lib/components/ui_elements/Notify.js +12 -12
- package/core/lib/components/ui_elements/PlaceHolder.js +33 -33
- package/core/lib/components/web-camera/web-camera.js +161 -161
- package/core/lib/components/web-camera/web-camera.scss +28 -28
- package/core/lib/core.md +9 -9
- package/core/lib/elements/Elements.md +2 -2
- package/core/lib/elements/basic/LoggedUserRedirect.js +21 -21
- package/core/lib/elements/basic/PrivateRoute.js +16 -16
- package/core/lib/elements/basic/button/Button.md +43 -43
- package/core/lib/elements/basic/button/button.js +170 -170
- package/core/lib/elements/basic/card/Card.md +15 -15
- package/core/lib/elements/basic/card/card.js +40 -40
- package/core/lib/elements/basic/card/card.scss +13 -13
- package/core/lib/elements/basic/checkbox/checkbox.js +23 -23
- package/core/lib/elements/basic/col/col.js +15 -15
- package/core/lib/elements/basic/copy-to-clipboard/Readme.md +40 -40
- package/core/lib/elements/basic/copy-to-clipboard/copy-to-clipboard.js +61 -61
- package/core/lib/elements/basic/country-phone-input/Readme.md +98 -98
- package/core/lib/elements/basic/country-phone-input/country-phone-input.js +81 -81
- package/core/lib/elements/basic/country-phone-input/phone-input.scss +75 -75
- package/core/lib/elements/basic/datepicker/datepicker.js +33 -33
- package/core/lib/elements/basic/dragabble-wrapper/draggable-wrapper.js +203 -203
- package/core/lib/elements/basic/empty/empty.js +14 -14
- package/core/lib/elements/basic/fingerprint-protrected/fingerprint-protected.js +118 -118
- package/core/lib/elements/basic/fingerprint-protrected/fingerprint-protected.scss +10 -10
- package/core/lib/elements/basic/form/form.js +70 -70
- package/core/lib/elements/basic/form/form.scss +3 -3
- package/core/lib/elements/basic/image/image.js +45 -45
- package/core/lib/elements/basic/image/image.scss +17 -17
- package/core/lib/elements/basic/image/readme.md +26 -26
- package/core/lib/elements/basic/image-viewer/image-viewer.js +108 -108
- package/core/lib/elements/basic/image-viewer/image-viewer.scss +7 -7
- package/core/lib/elements/basic/input/input.js +81 -81
- package/core/lib/elements/basic/input/readme.md +77 -77
- package/core/lib/elements/basic/json-input/json-input.js +51 -51
- package/core/lib/elements/basic/menu-dashboard/menu-dashboard.js +216 -216
- package/core/lib/elements/basic/menu-dashboard/menu-dashboard.scss +28 -28
- package/core/lib/elements/basic/menu-tree/menu-tree.js +127 -127
- package/core/lib/elements/basic/modal/modal.js +64 -64
- package/core/lib/elements/basic/modal/readme.md +62 -62
- package/core/lib/elements/basic/popconfirm/popconfirm.js +17 -17
- package/core/lib/elements/basic/popover/popover.js +12 -12
- package/core/lib/elements/basic/radio/radio.js +18 -18
- package/core/lib/elements/basic/rangepicker/rangepicker.js +141 -141
- package/core/lib/elements/basic/rangepicker/rangepicker.scss +24 -24
- package/core/lib/elements/basic/rangepicker/readme.md +81 -81
- package/core/lib/elements/basic/reference-select/readme.md +18 -18
- package/core/lib/elements/basic/reference-select/reference-select.js +341 -341
- package/core/lib/elements/basic/row/row.js +15 -15
- package/core/lib/elements/basic/select/select.js +46 -46
- package/core/lib/elements/basic/select-box/readme.md +52 -52
- package/core/lib/elements/basic/select-box/select-box.js +63 -63
- package/core/lib/elements/basic/skeleton/readme.md +35 -35
- package/core/lib/elements/basic/skeleton/skeleton.js +35 -35
- package/core/lib/elements/basic/skeleton/skeleton.scss +53 -53
- package/core/lib/elements/basic/space/space.js +12 -12
- package/core/lib/elements/basic/switch/readme.md +29 -29
- package/core/lib/elements/basic/switch/switch.js +67 -67
- package/core/lib/elements/basic/tab/tab.js +14 -14
- package/core/lib/elements/basic/table/readme.md +8 -8
- package/core/lib/elements/basic/table/table.js +95 -95
- package/core/lib/elements/basic/tag/tag.js +63 -63
- package/core/lib/elements/basic/tag/tag.scss +2 -2
- package/core/lib/elements/basic/timeline/timeline.js +13 -13
- package/core/lib/elements/basic/title/readme.md +20 -20
- package/core/lib/elements/basic/title/title.js +37 -37
- package/core/lib/elements/basic/user-search/user-search.js +192 -192
- package/core/lib/elements/complex/barcode/barcode.js +27 -27
- package/core/lib/elements/complex/bargraph/bar-graph.js +262 -262
- package/core/lib/elements/complex/basic-table/basic-table.js +110 -110
- package/core/lib/elements/complex/basic-table/basic-table.scss +4 -4
- package/core/lib/elements/complex/date-display/date-display.js +37 -37
- package/core/lib/elements/complex/error-boundary/error-boundary.js +29 -29
- package/core/lib/elements/complex/google-location-input/map-container-library-load.js +92 -92
- package/core/lib/elements/complex/google-map/google-map.js +230 -230
- package/core/lib/elements/complex/google-map/google-map.scss +13 -13
- package/core/lib/elements/complex/line-graph/line-graph.js +108 -108
- package/core/lib/elements/complex/location-search-input/location-search-input.js +100 -100
- package/core/lib/elements/complex/pie-chart/pie-chart.js +202 -202
- package/core/lib/elements/complex/qr-code/qr-code.js +29 -29
- package/core/lib/elements/complex/qrscanner/qrscanner.js +57 -57
- package/core/lib/elements/complex/search-debounce/search-debounce.js +37 -37
- package/core/lib/elements/complex/statistic-card/dashboard-statistic-card.js +75 -75
- package/core/lib/elements/complex/statistic-card/statistic-card.js +28 -28
- package/core/lib/elements/index.js +226 -226
- package/core/lib/hooks/device-detect.js +25 -25
- package/core/lib/hooks/index.js +9 -9
- package/core/lib/hooks/use-location.js +33 -33
- package/core/lib/hooks/use-otp-timer.js +80 -80
- package/core/lib/hooks/use-window-size.js +34 -34
- package/core/lib/i18n.js +69 -69
- package/core/lib/index.js +106 -106
- package/core/lib/introduction.md +73 -73
- package/core/lib/js-styleguide.md +4112 -4112
- package/core/lib/models/actions/actions.js +127 -127
- package/core/lib/models/actions/components/action-detail/action-detail.js +190 -190
- package/core/lib/models/actions/components/custom-actions/custom-actions.js +185 -185
- package/core/lib/models/attachments/attachments.js +231 -231
- package/core/lib/models/base-loader.js +99 -99
- package/core/lib/models/base.js +716 -716
- package/core/lib/models/branches/branches.js +125 -125
- package/core/lib/models/checklists/checklists.js +114 -114
- package/core/lib/models/columns/columns.js +169 -169
- package/core/lib/models/columns/components/columns-add/columns-add.js +171 -171
- package/core/lib/models/comments/comments.js +213 -213
- package/core/lib/models/departments/departments.js +107 -107
- package/core/lib/models/financial-years/financial_years.js +127 -127
- package/core/lib/models/forms/components/form-creator/form-creator.js +667 -667
- package/core/lib/models/forms/components/form-creator/form-creator.scss +39 -39
- package/core/lib/models/forms/components/form-detail/form-detail.js +224 -224
- package/core/lib/models/forms/forms.js +121 -121
- package/core/lib/models/index.js +203 -203
- package/core/lib/models/invoice-numbers/invoice_numbers.js +204 -204
- package/core/lib/models/lookup-types/components/lookup-detail/lookup-detail.js +145 -145
- package/core/lib/models/lookup-types/lookup-types.js +113 -113
- package/core/lib/models/lookup-values/components/lookup-values-add/lookup-values-add.js +126 -126
- package/core/lib/models/lookup-values/lookup-values.js +107 -107
- package/core/lib/models/menu-roles/menu-roles.js +127 -127
- package/core/lib/models/menus/components/menu-add/menu-add.js +228 -228
- package/core/lib/models/menus/components/menu-detail/menu-detail.js +170 -170
- package/core/lib/models/menus/components/menu-list/menu-list.js +550 -550
- package/core/lib/models/menus/components/menu-list/menu-list.scss +5 -5
- package/core/lib/models/menus/components/menu-roles-add/menu-roles-add.js +183 -183
- package/core/lib/models/menus/menus.js +499 -499
- package/core/lib/models/models/components/model-detail/model-detail.js +137 -137
- package/core/lib/models/models/components/models.js +128 -128
- package/core/lib/models/modules/modules.js +204 -204
- package/core/lib/models/outbox/outbox.js +73 -73
- package/core/lib/models/pages/pages.js +107 -107
- package/core/lib/models/permissions/permissions.js +71 -71
- package/core/lib/models/process/components/process-add/process-add.js +181 -181
- package/core/lib/models/process/components/process-dashboard/process-dashboard.js +1068 -1068
- package/core/lib/models/process/components/process-dashboard/process-dashboard.scss +66 -66
- package/core/lib/models/process/components/process-detail/process-detail.js +140 -140
- package/core/lib/models/process/components/process-timeline/process-timeline.js +139 -139
- package/core/lib/models/process/components/task-detail/task-detail.js +240 -240
- package/core/lib/models/process/components/task-detail/task-detail.scss +27 -27
- package/core/lib/models/process/components/task-form/task-form.js +528 -528
- package/core/lib/models/process/components/task-form/task-form.scss +7 -7
- package/core/lib/models/process/components/task-list/task-list.js +221 -221
- package/core/lib/models/process/components/task-list/task-list.scss +14 -14
- package/core/lib/models/process/components/task-overview/task-overview.js +299 -299
- package/core/lib/models/process/components/task-overview-legacy/task-overview-legacy.js +192 -192
- package/core/lib/models/process/components/task-routes/task-routes.js +45 -45
- package/core/lib/models/process/components/task-status/task-status.js +175 -175
- package/core/lib/models/process/components/task-status/task-status.scss +11 -11
- package/core/lib/models/process/process.js +780 -780
- package/core/lib/models/process-transactions/process-transactions.js +123 -123
- package/core/lib/models/roles/roles.js +106 -106
- package/core/lib/models/scripts/scripts.js +111 -111
- package/core/lib/models/step-transactions/step-transcations.js +147 -147
- package/core/lib/models/steps/components/step-add/step-add.js +261 -261
- package/core/lib/models/steps/components/step-detail/step-detail.js +157 -157
- package/core/lib/models/steps/steps.js +356 -356
- package/core/lib/models/user-preferences/user-preferences.js +83 -83
- package/core/lib/models/users/components/user-add/user-add.js +226 -226
- package/core/lib/models/users/users.js +119 -119
- package/core/lib/modules/business/launch-page/launch-page.js +29 -29
- package/core/lib/modules/business/launch-page/launch-page.scss +5 -5
- package/core/lib/modules/business/slots/slots.js +231 -231
- package/core/lib/modules/business/slots/slots.scss +108 -108
- package/core/lib/modules/forms/components/field-customizer/field-customizer.js +138 -138
- package/core/lib/modules/forms/components/field-selector/field-selector.js +157 -157
- package/core/lib/modules/forms/components/field-selector/field-selector.scss +25 -25
- package/core/lib/modules/forms/components/form-display/form-display.js +203 -203
- package/core/lib/modules/forms/components/form-display/form-display.scss +9 -9
- package/core/lib/modules/forms/components/tab-customizer/tab-customizer.js +124 -124
- package/core/lib/modules/generic/generic-add/generic-add.js +213 -213
- package/core/lib/modules/generic/generic-detail/generic-detail.js +199 -199
- package/core/lib/modules/generic/generic-edit/generic-edit.js +120 -120
- package/core/lib/modules/generic/generic-list/ExportReactCSV.js +508 -508
- package/core/lib/modules/generic/generic-list/fonts/NotoSansBold.js +8 -8
- package/core/lib/modules/generic/generic-list/fonts/NotoSansRegular.js +15 -15
- package/core/lib/modules/generic/generic-list/generic-list.js +705 -705
- package/core/lib/modules/generic/generic-list/generic-list.scss +68 -68
- package/core/lib/modules/generic/generic-upload/generic-upload.js +483 -483
- package/core/lib/modules/generic/table-settings/table-settings.js +226 -226
- package/core/lib/modules/generic/table-settings/table-settings.scss +37 -37
- package/core/lib/modules/index.js +52 -52
- package/core/lib/modules/modules-routes/module-routes.js +35 -35
- package/core/lib/pages/change-password/change-password.js +204 -204
- package/core/lib/pages/change-password/change-password.scss +73 -73
- package/core/lib/pages/homepage/homepage.js +53 -53
- package/core/lib/pages/index.js +19 -19
- package/core/lib/pages/login/commnication-mode-selection.js +46 -46
- package/core/lib/pages/login/communication-mode-selection.scss +60 -60
- package/core/lib/pages/login/login.js +872 -872
- package/core/lib/pages/login/login.scss +353 -353
- package/core/lib/pages/login/reset-password.js +124 -124
- package/core/lib/pages/login/reset-password.scss +31 -31
- package/core/lib/pages/manage-users/manage-users.js +429 -429
- package/core/lib/pages/manage-users/manage-users.scss +25 -25
- package/core/lib/pages/profile/profile.js +247 -247
- package/core/lib/pages/profile/profile.scss +107 -107
- package/core/lib/pages/profile/theme-config.js +18 -18
- package/core/lib/pages/profile/themes-backup.json +310 -310
- package/core/lib/pages/profile/themes.json +254 -254
- package/core/lib/pages/register/register.js +176 -176
- package/core/lib/pages/register/register.scss +128 -128
- package/core/lib/react-styleguide.md +756 -756
- package/core/lib/utils/api/api.utils.js +207 -207
- package/core/lib/utils/api/readme.md +426 -426
- package/core/lib/utils/async.js +35 -35
- package/core/lib/utils/common/common.utils.js +237 -237
- package/core/lib/utils/common/readme.md +30 -30
- package/core/lib/utils/date/date.utils.js +295 -295
- package/core/lib/utils/date/readme.md +2 -2
- package/core/lib/utils/firebase.support.utils.js +98 -98
- package/core/lib/utils/firebase.utils.js +808 -808
- package/core/lib/utils/font-awesome.utils.js +168 -168
- package/core/lib/utils/form/form.utils.js +255 -255
- package/core/lib/utils/generic/generic.utils.js +70 -70
- package/core/lib/utils/http/auth.helper.js +95 -95
- package/core/lib/utils/http/http.utils.js +190 -190
- package/core/lib/utils/http/readme.md +14 -14
- package/core/lib/utils/index.js +43 -43
- package/core/lib/utils/location/location.utils.js +137 -137
- package/core/lib/utils/location/readme.md +18 -18
- package/core/lib/utils/modal.utils.js +15 -15
- package/core/lib/utils/notification.utils.js +34 -34
- package/core/lib/utils/pwa/pwa.utils.js +88 -88
- package/core/lib/utils/script.utils.js +235 -235
- package/core/lib/utils/setting.utils.js +68 -68
- package/core/lib/utils/upload.utils.js +29 -29
- package/core/models/Preference/Preferences.js +46 -46
- package/core/models/base/base.js +403 -403
- package/core/models/base-clone-loader.js +107 -107
- package/core/models/base-clone.js +187 -187
- package/core/models/base-loader.js +97 -97
- package/core/models/core-scripts/core-scripts.js +179 -179
- package/core/models/dashboard/dashboard.js +201 -201
- package/core/models/detail-loader.js +88 -88
- package/core/models/doctor/components/doctor-add/doctor-add.js +432 -432
- package/core/models/doctor/components/doctor-add/doctor-add.scss +32 -32
- package/core/models/groups.js +82 -82
- package/core/models/index.js +100 -100
- package/core/models/lookup-types/components/lookup-detail/lookup-detail.js +129 -129
- package/core/models/lookup-types/lookup-types.js +96 -96
- package/core/models/lookup-values/components/lookup-values-modal/lookup-values-modal.js +95 -95
- package/core/models/lookup-values/lookup-values.js +92 -92
- package/core/models/menu-roles/components/menu-roles-add/menu-roles-add.js +153 -153
- package/core/models/menu-roles/menu-roles.js +158 -158
- package/core/models/menus/components/menu-add/menu-add.js +315 -315
- package/core/models/menus/components/menu-add/menu-add.scss +31 -31
- package/core/models/menus/components/menu-detail/menu-detail.js +263 -263
- package/core/models/menus/components/menu-list/menu-list.js +392 -392
- package/core/models/menus/components/menu-lists/menu-lists.js +647 -647
- package/core/models/menus/components/menu-lists/menu-lists.scss +73 -73
- package/core/models/menus/menus.js +338 -338
- package/core/models/model-columns.js +121 -121
- package/core/models/models/components/model-detail/model-add.js +120 -120
- package/core/models/models/components/model-detail/model-detail.js +133 -133
- package/core/models/models/models.js +154 -154
- package/core/models/pages/components/page-add/page-add.js +163 -163
- package/core/models/pages/components/page-add/page-add.scss +30 -30
- package/core/models/pages/components/page-details/page-details.js +209 -209
- package/core/models/pages/components/page-list/page-list.js +248 -248
- package/core/models/pages/pages.js +142 -142
- package/core/models/pages.js +142 -142
- package/core/models/roles/components/role-add/menu-label.js +14 -14
- package/core/models/roles/components/role-add/menu-tree.js +127 -127
- package/core/models/roles/components/role-add/role-add.js +230 -230
- package/core/models/roles/components/role-add/role-add.scss +4 -4
- package/core/models/roles/components/role-list/role-list.js +406 -406
- package/core/models/roles/roles.js +199 -199
- package/core/models/staff/components/staff-add/staff-add.js +455 -455
- package/core/models/user-roles/components/user-roles-add/user-roles-add.js +149 -149
- package/core/models/user-roles/user-roles.js +113 -113
- package/core/models/users/components/assign-role/assign-role.js +428 -428
- package/core/models/users/components/assign-role/assign-role.scss +281 -281
- package/core/models/users/components/assign-role/avatar-props.js +45 -45
- package/core/models/users/components/user-add/user-add.js +847 -847
- package/core/models/users/components/user-add/user-edit.js +110 -110
- package/core/models/users/components/user-detail/user-detail.js +236 -236
- package/core/models/users/components/user-list/user-list.js +397 -397
- package/core/models/users/users.js +379 -379
- package/core/modules/Informations/change-info/change-info.js +618 -618
- package/core/modules/Informations/change-info/change-info.scss +134 -134
- package/core/modules/dashboard/components/dashboard-card/animations.js +64 -64
- package/core/modules/dashboard/components/dashboard-card/dashboard-card.js +197 -197
- package/core/modules/dashboard/components/dashboard-card/menu-dashboard-card.js +430 -430
- package/core/modules/dashboard/components/dashboard-card/menu-dashboard-card.scss +59 -59
- package/core/modules/dashboard/components/pop-query-dashboard/pop-query-dashboard.js +66 -66
- package/core/modules/generic/components/generic-add/generic-add.js +121 -121
- package/core/modules/generic/components/generic-add/generic-add.scss +13 -13
- package/core/modules/generic/components/generic-add-modal/generic-add-modal.js +125 -125
- package/core/modules/generic/components/generic-add-modal/generic-add-modal.scss +13 -13
- package/core/modules/generic/components/generic-detail/generic-detail.js +184 -184
- package/core/modules/generic/components/generic-detail/generic-detail.scss +25 -25
- package/core/modules/generic/components/generic-edit/generic-edit.js +123 -123
- package/core/modules/generic/components/generic-list/generic-list.js +335 -335
- package/core/modules/generic/components/generic-list/generic-list.scss +35 -35
- package/core/modules/index.js +42 -42
- package/core/modules/module-routes/module-routes.js +37 -37
- package/core/modules/reporting/components/index.js +6 -6
- package/core/modules/reporting/components/reporting-dashboard/README.md +316 -316
- package/core/modules/reporting/components/reporting-dashboard/adavance-search/advance-search.js +271 -271
- package/core/modules/reporting/components/reporting-dashboard/adavance-search/advance-search.scss +76 -76
- package/core/modules/reporting/components/reporting-dashboard/display-columns/build-display-columns.js +90 -90
- package/core/modules/reporting/components/reporting-dashboard/display-columns/build-display-columns.test.js +74 -74
- package/core/modules/reporting/components/reporting-dashboard/display-columns/display-cell-renderer.js +404 -404
- package/core/modules/reporting/components/reporting-dashboard/display-columns/display-cell-renderer.test.js +179 -179
- package/core/modules/reporting/components/reporting-dashboard/reporting-dashboard.js +652 -652
- package/core/modules/reporting/components/reporting-dashboard/reporting-dashboard.scss +215 -215
- package/core/modules/reporting/components/reporting-dashboard/reporting-table.js +537 -537
- package/core/modules/steps/action-buttons.js +92 -92
- package/core/modules/steps/action-buttons.scss +62 -62
- package/core/modules/steps/chat-assistant.js +141 -141
- package/core/modules/steps/narration.js +192 -192
- package/core/modules/steps/openai-realtime.js +275 -275
- package/core/modules/steps/progress-storage.js +140 -140
- package/core/modules/steps/readme.md +167 -167
- package/core/modules/steps/steps.js +1716 -1597
- package/core/modules/steps/steps.scss +1068 -1051
- package/core/modules/steps/timeline.js +56 -56
- package/core/modules/steps/voice-navigation.js +709 -709
- package/core/pages/homepage-api/homepage-api.js +106 -106
- package/core/pages/homepage-api/homepage-api.scss +233 -233
- package/core/pages/homepage-api/menu-dashboard.js +169 -169
- package/core/pages/homepage-api/menu-dashboard.scss +11 -11
- package/core/translation.json +53 -53
- package/core/translations.json +19 -19
- package/core/utils/script.utils.js +129 -129
- package/core/utils/settings.utils.js +25 -25
- package/eslint.config.mjs +79 -79
- package/index.js +35 -35
- package/jest.config.js +7 -7
- package/jest.setup.js +1 -1
- package/package.json +125 -125
- package/tsconfig.json +26 -26
- package/webpack.config.js +173 -173
|
@@ -1,652 +1,652 @@
|
|
|
1
|
-
import React, { useState, useEffect, useContext, useRef } from 'react';
|
|
2
|
-
|
|
3
|
-
import { Table, Skeleton, Input, Modal, message, Tag } from 'antd';
|
|
4
|
-
|
|
5
|
-
import { Location, FormCreator, GlobalContext, Card } from './../../../../lib/';
|
|
6
|
-
|
|
7
|
-
import { CoreScripts } from './../../../../models/';
|
|
8
|
-
|
|
9
|
-
import moment from 'moment-timezone';
|
|
10
|
-
|
|
11
|
-
import './reporting-dashboard.scss';
|
|
12
|
-
|
|
13
|
-
// import MenuDashBoard from '../../../../pages/homepage-api/menu-dashboard';
|
|
14
|
-
import MenuDashBoardComponent from '../../../../lib/elements/basic/menu-dashboard/menu-dashboard';
|
|
15
|
-
|
|
16
|
-
import ReportingTable from './reporting-table';
|
|
17
|
-
|
|
18
|
-
// Input parameter that decides which date column the report is filtered by
|
|
19
|
-
const DATE_FILTER_FIELD = 'date_filter_type';
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* ReportingDashboard component renders the dashboard and handles patient details,
|
|
23
|
-
* configuration, and form layout for generating reports.
|
|
24
|
-
*
|
|
25
|
-
* @param {Object} props - The component's props.
|
|
26
|
-
* @param {Object} props.match - The match object containing the URL parameters.
|
|
27
|
-
* @param {Object} props.CustomComponents - Custom components for rendering.
|
|
28
|
-
* @param {string} props.reportId - The report ID.
|
|
29
|
-
* @param {boolean} props.isFixedIndex - Determines if the index is fixed.
|
|
30
|
-
* @param {Array<string>} props.dashBoardIds - The list of dashboard IDs.
|
|
31
|
-
*
|
|
32
|
-
* @returns {JSX.Element} The rendered ReportingDashboard component.
|
|
33
|
-
*/
|
|
34
|
-
export default function ReportingDashboard({
|
|
35
|
-
match,
|
|
36
|
-
scope,
|
|
37
|
-
CustomComponents,
|
|
38
|
-
reportId,
|
|
39
|
-
isFixedIndex,
|
|
40
|
-
dashBoardIds,
|
|
41
|
-
barcodeFilterKey,
|
|
42
|
-
showScanner,
|
|
43
|
-
dbPtr,
|
|
44
|
-
attributes,
|
|
45
|
-
}) {
|
|
46
|
-
const [config, setConfig] = useState({});
|
|
47
|
-
|
|
48
|
-
// State to manage the layout of the form
|
|
49
|
-
const [formLayout] = useState('inline');
|
|
50
|
-
|
|
51
|
-
const [loading, setLoading] = useState(true);
|
|
52
|
-
|
|
53
|
-
const [cardLoading, setCardLoading] = useState(true);
|
|
54
|
-
|
|
55
|
-
const [searchParameters, setSearchParameters] = useState([]);
|
|
56
|
-
|
|
57
|
-
const [searchValues, setSearchValues] = useState({});
|
|
58
|
-
|
|
59
|
-
const [dashboardVisible, setDashBoardVisible] = useState(false);
|
|
60
|
-
|
|
61
|
-
const [formContents, setformContents] = useState({});
|
|
62
|
-
const [liveFormContents, setLiveFormContents] = useState({});
|
|
63
|
-
const [reportMailRequest, setReportMailRequest] = useState({
|
|
64
|
-
scriptId: null,
|
|
65
|
-
inputParameters: {},
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
const scriptId = useRef(null);
|
|
69
|
-
|
|
70
|
-
//In case of reports from core_script , there will be id from params
|
|
71
|
-
// In case of normal menu we need to take id from props
|
|
72
|
-
let id = reportId ? reportId : match?.params?.id;
|
|
73
|
-
|
|
74
|
-
const { CustomModels = {} } = useContext(GlobalContext);
|
|
75
|
-
|
|
76
|
-
const [details, setDetails] = useState([]);
|
|
77
|
-
|
|
78
|
-
const [columns, setColumns] = useState([]); // To set columns
|
|
79
|
-
|
|
80
|
-
const [, setSummaryColumns] = useState([]);
|
|
81
|
-
|
|
82
|
-
const [reportRequestPayload, setReportRequestPayload] = useState(null);
|
|
83
|
-
|
|
84
|
-
const urlParams = Location.search();
|
|
85
|
-
|
|
86
|
-
// Pagination
|
|
87
|
-
const [pagination, setPagination] = useState({
|
|
88
|
-
current: 1,
|
|
89
|
-
pageSize: 20,
|
|
90
|
-
total: 0,
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
// Settings db pointer
|
|
94
|
-
if (!dbPtr) dbPtr = localStorage.db_ptr;
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Fetches patient details from the server and updates the relevant state.
|
|
98
|
-
* This includes input parameters, columns, summary columns, and configuration.
|
|
99
|
-
*
|
|
100
|
-
* @returns {Promise<void>} A promise that resolves when the patient details have been fetched and the state has been updated.
|
|
101
|
-
*/
|
|
102
|
-
async function getPatientDetails(idOverride) {
|
|
103
|
-
const fetchId = idOverride || id;
|
|
104
|
-
await CoreScripts.getRecord({ id: fetchId, dbPtr }).then(async ({ result }) => {
|
|
105
|
-
// Check if display columns are provided from backend
|
|
106
|
-
let parsedColumns = [];
|
|
107
|
-
|
|
108
|
-
if (result.display_columns) {
|
|
109
|
-
parsedColumns = JSON.parse(result.display_columns);
|
|
110
|
-
}
|
|
111
|
-
setColumns(parsedColumns);
|
|
112
|
-
|
|
113
|
-
await prepareInputParameters(result, parsedColumns, fetchId);
|
|
114
|
-
|
|
115
|
-
if (result.summary_columns) {
|
|
116
|
-
setSummaryColumns(JSON.parse(result.summary_columns));
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
setConfig({ ...result });
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// useEffect(() => {
|
|
124
|
-
// if (!dashboardVisible) {
|
|
125
|
-
// refresh(false);
|
|
126
|
-
// }
|
|
127
|
-
// }, [dashboardVisible]);
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
* Manage initial render
|
|
133
|
-
*/
|
|
134
|
-
|
|
135
|
-
useEffect(() => {
|
|
136
|
-
getPatientDetails();
|
|
137
|
-
}, []);
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Effect hook that triggers the `getPatientDetails` function
|
|
141
|
-
* whenever the `match.params.id` value changes.
|
|
142
|
-
*
|
|
143
|
-
* @returns {void} This hook does not return anything.
|
|
144
|
-
*/
|
|
145
|
-
// useEffect(() => {
|
|
146
|
-
// getPatientDetails();
|
|
147
|
-
// }, [match.params.id]);
|
|
148
|
-
|
|
149
|
-
let parameters;
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Some parameters would need binding with the model
|
|
153
|
-
*
|
|
154
|
-
* @param {*} inputParameters Input parameters from the report configuration.
|
|
155
|
-
*/
|
|
156
|
-
|
|
157
|
-
//Prepare input parameters by mapping default values and binding models if needed
|
|
158
|
-
async function prepareInputParameters(record, parsedColumns, fetchId) {
|
|
159
|
-
setLoading(true);
|
|
160
|
-
let urlParams = Location.search();
|
|
161
|
-
|
|
162
|
-
// If script id exist set into variable
|
|
163
|
-
if (urlParams.script_id) scriptId.current = urlParams.script_id;
|
|
164
|
-
|
|
165
|
-
let otherDetails = record.other_details1 ? JSON.parse(record.other_details1) : null;
|
|
166
|
-
|
|
167
|
-
parameters = record.input_parameters ? JSON.parse(record.input_parameters) : [];
|
|
168
|
-
|
|
169
|
-
let formContent = {};
|
|
170
|
-
const searchFields = (parameters || []).filter((p) => p.type === 'search' && p.search_enabled === 'yes');
|
|
171
|
-
setSearchParameters([...searchFields]);
|
|
172
|
-
|
|
173
|
-
parameters = await parameters?.map((record) => {
|
|
174
|
-
// Only if the url params does have a matching value ,
|
|
175
|
-
// we should not consider the default value
|
|
176
|
-
|
|
177
|
-
if (urlParams[record.field]) {
|
|
178
|
-
if (record.type === 'date') {
|
|
179
|
-
formContent[record.field] = moment.utc(urlParams[record.field]);
|
|
180
|
-
} else if (record.type !== 'search') {
|
|
181
|
-
// Restore plain values ( eg : select filters ) back from the url
|
|
182
|
-
formContent[record.field] = urlParams[record.field];
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// return formContent;
|
|
186
|
-
} else {
|
|
187
|
-
// let StartDate, EndDate;
|
|
188
|
-
switch (record.default) {
|
|
189
|
-
case 'startOfDay':
|
|
190
|
-
formContent[record.field] = moment().tz(process.env.REACT_APP_TIMEZONE).startOf('day');
|
|
191
|
-
break;
|
|
192
|
-
|
|
193
|
-
case 'endOfDay':
|
|
194
|
-
formContent[record.field] = moment().tz(process.env.REACT_APP_TIMEZONE).endOf('day');
|
|
195
|
-
break;
|
|
196
|
-
|
|
197
|
-
case 'startOfWeek':
|
|
198
|
-
formContent[record.field] = moment().tz(process.env.REACT_APP_TIMEZONE).startOf('week');
|
|
199
|
-
break;
|
|
200
|
-
|
|
201
|
-
case 'endOfWeek':
|
|
202
|
-
formContent[record.field] = moment().tz(process.env.REACT_APP_TIMEZONE).endOf('week');
|
|
203
|
-
break;
|
|
204
|
-
|
|
205
|
-
case 'currentDate':
|
|
206
|
-
formContent[record.field] = moment().tz(process.env.REACT_APP_TIMEZONE);
|
|
207
|
-
break;
|
|
208
|
-
|
|
209
|
-
default:
|
|
210
|
-
// Any other default is taken as the value itself ( eg : select filters )
|
|
211
|
-
if (record.default !== undefined && record.default !== null && record.type !== 'date') {
|
|
212
|
-
formContent[record.field] = record.default;
|
|
213
|
-
}
|
|
214
|
-
break;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// If it is a date field and still no value, set it to today's date
|
|
219
|
-
if (record.type === 'date' && !formContent[record.field]) {
|
|
220
|
-
formContent[record.field] = moment().tz(process.env.REACT_APP_TIMEZONE);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// For a static select with no value yet , preselect the first option
|
|
224
|
-
if (record.type === 'select' && Array.isArray(record.options) && formContent[record.field] === undefined) {
|
|
225
|
-
formContent[record.field] = record.options[0]?.valueMember;
|
|
226
|
-
}
|
|
227
|
-
if (record.type === 'search') {
|
|
228
|
-
if (!formContent[record.field]) formContent[record.field] = [];
|
|
229
|
-
return {
|
|
230
|
-
...record,
|
|
231
|
-
reportId: fetchId,
|
|
232
|
-
onReset: () => getPatientDetails(fetchId),
|
|
233
|
-
required: record.required,
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
if (['reference-select', 'reference-search', 'select'].indexOf(record.type) !== -1) {
|
|
237
|
-
// let model = "";
|
|
238
|
-
let model = CustomModels[record.modelName];
|
|
239
|
-
|
|
240
|
-
return {
|
|
241
|
-
...record,
|
|
242
|
-
model,
|
|
243
|
-
required: record.required,
|
|
244
|
-
};
|
|
245
|
-
} else {
|
|
246
|
-
return {
|
|
247
|
-
...record,
|
|
248
|
-
required: true,
|
|
249
|
-
};
|
|
250
|
-
}
|
|
251
|
-
});
|
|
252
|
-
// Update form content state
|
|
253
|
-
setformContents(formContent);
|
|
254
|
-
setLiveFormContents(formContent);
|
|
255
|
-
|
|
256
|
-
// Trigger form submission
|
|
257
|
-
onFinish(formContent, null, record.input_parameters, parsedColumns);
|
|
258
|
-
|
|
259
|
-
setLoading(false);
|
|
260
|
-
|
|
261
|
-
// Check if input parameters are enabled or disabled in otherDetails
|
|
262
|
-
if (otherDetails?.isDisableInputParameters) {
|
|
263
|
-
// If enabled, clear the details array
|
|
264
|
-
setDetails([]);
|
|
265
|
-
} else {
|
|
266
|
-
// The date filter input is shown only when the filter is enabled in otherDetails .
|
|
267
|
-
// Otherwise it stays hidden holding its default value , so the report keeps filtering
|
|
268
|
-
// on the default date
|
|
269
|
-
const filterKey = otherDetails ? Object.keys(otherDetails).find((key) => key.toLowerCase().trim() === 'enableuserfilter') : null;
|
|
270
|
-
|
|
271
|
-
const isFilterEnabled = filterKey ? otherDetails[filterKey] === true || otherDetails[filterKey] === 'true' : false;
|
|
272
|
-
|
|
273
|
-
// Keep all parameters with a type (including search) to render in FormCreator
|
|
274
|
-
setDetails([
|
|
275
|
-
...parameters
|
|
276
|
-
.filter((ele) => ele.type)
|
|
277
|
-
.map((ele) => (ele.field === DATE_FILTER_FIELD ? { ...ele, visible: isFilterEnabled } : ele)),
|
|
278
|
-
]);
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// Refresh patient details.
|
|
283
|
-
|
|
284
|
-
function refresh() {
|
|
285
|
-
getPatientDetails(scriptId.current || id);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
const buildReportRequestPayload = (values = {}, paginationOverride) => {
|
|
289
|
-
const pager = paginationOverride || pagination;
|
|
290
|
-
const formattedValues = {};
|
|
291
|
-
|
|
292
|
-
Object.keys(values || {}).forEach((key) => {
|
|
293
|
-
const val = values[key];
|
|
294
|
-
formattedValues[key] = moment.isMoment(val) ? val.format('YYYY-MM-DD') : val;
|
|
295
|
-
});
|
|
296
|
-
|
|
297
|
-
const paginationData = {
|
|
298
|
-
page: pager.current || 1,
|
|
299
|
-
limit: pager.pageSize || 10,
|
|
300
|
-
};
|
|
301
|
-
|
|
302
|
-
if (scope) {
|
|
303
|
-
return {
|
|
304
|
-
body: {
|
|
305
|
-
...scope,
|
|
306
|
-
...paginationData,
|
|
307
|
-
},
|
|
308
|
-
};
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
return {
|
|
312
|
-
body: {
|
|
313
|
-
...formattedValues,
|
|
314
|
-
...paginationData,
|
|
315
|
-
},
|
|
316
|
-
};
|
|
317
|
-
};
|
|
318
|
-
|
|
319
|
-
const handleSubmit = (values) => {
|
|
320
|
-
// Extract search fields from the form values
|
|
321
|
-
const searchKeys = searchParameters.map((p) => p.field);
|
|
322
|
-
const currentSearchValues = {};
|
|
323
|
-
const formValues = {};
|
|
324
|
-
|
|
325
|
-
Object.keys(values).forEach((key) => {
|
|
326
|
-
if (searchKeys.includes(key)) {
|
|
327
|
-
currentSearchValues[key] = values[key];
|
|
328
|
-
} else {
|
|
329
|
-
formValues[key] = values[key];
|
|
330
|
-
}
|
|
331
|
-
});
|
|
332
|
-
|
|
333
|
-
const hasSearchValues = Object.values(currentSearchValues).some((v) => Array.isArray(v) && v.length > 0);
|
|
334
|
-
|
|
335
|
-
if (!hasSearchValues) {
|
|
336
|
-
runSubmit(formValues);
|
|
337
|
-
return;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
// Check if main form values (non-search) changed
|
|
341
|
-
const formChanged = Object.keys(formValues).some((key) => {
|
|
342
|
-
const newVal = formValues[key];
|
|
343
|
-
const oldVal = formContents[key];
|
|
344
|
-
|
|
345
|
-
if (moment.isMoment(newVal) && moment.isMoment(oldVal)) {
|
|
346
|
-
return !newVal.isSame(oldVal, 'day');
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
return newVal !== oldVal;
|
|
350
|
-
});
|
|
351
|
-
|
|
352
|
-
if (formChanged) {
|
|
353
|
-
Modal.confirm({
|
|
354
|
-
title: 'Filters changed',
|
|
355
|
-
content: 'You changed some filters. Do you want to search using these filters also?',
|
|
356
|
-
okText: 'Yes',
|
|
357
|
-
cancelText: 'No',
|
|
358
|
-
|
|
359
|
-
onOk() {
|
|
360
|
-
// YES → send form values + search condition
|
|
361
|
-
const finalValues = {
|
|
362
|
-
...formValues,
|
|
363
|
-
search_values: currentSearchValues,
|
|
364
|
-
};
|
|
365
|
-
|
|
366
|
-
runSubmit(finalValues);
|
|
367
|
-
},
|
|
368
|
-
|
|
369
|
-
onCancel() {
|
|
370
|
-
// NO → reset form values
|
|
371
|
-
const resetValues = {};
|
|
372
|
-
Object.keys(formValues).forEach((key) => {
|
|
373
|
-
resetValues[key] = null;
|
|
374
|
-
});
|
|
375
|
-
|
|
376
|
-
const finalValues = {
|
|
377
|
-
...resetValues,
|
|
378
|
-
search_values: currentSearchValues,
|
|
379
|
-
};
|
|
380
|
-
|
|
381
|
-
runSubmit(finalValues);
|
|
382
|
-
},
|
|
383
|
-
});
|
|
384
|
-
} else {
|
|
385
|
-
// no form change
|
|
386
|
-
const resetValues = {};
|
|
387
|
-
Object.keys(formValues).forEach((key) => {
|
|
388
|
-
resetValues[key] = null;
|
|
389
|
-
});
|
|
390
|
-
|
|
391
|
-
const finalValues = {
|
|
392
|
-
...resetValues,
|
|
393
|
-
search_values: currentSearchValues,
|
|
394
|
-
};
|
|
395
|
-
|
|
396
|
-
runSubmit(finalValues);
|
|
397
|
-
}
|
|
398
|
-
};
|
|
399
|
-
|
|
400
|
-
const runSubmit = (finalValues) => {
|
|
401
|
-
const { pageSize } = pagination;
|
|
402
|
-
const resetPage = 1;
|
|
403
|
-
|
|
404
|
-
scriptId.current = null;
|
|
405
|
-
|
|
406
|
-
const hasSearchValues = finalValues.search_values && Object.values(finalValues.search_values).some((v) => Array.isArray(v) && v.length > 0);
|
|
407
|
-
|
|
408
|
-
if (!hasSearchValues) {
|
|
409
|
-
const currentUrlParams = Location.search();
|
|
410
|
-
const searchKeys = new Set(searchParameters.map((parameter) => parameter.field));
|
|
411
|
-
const cleanParams = Object.fromEntries(
|
|
412
|
-
Object.entries(currentUrlParams).filter(
|
|
413
|
-
([key]) => key !== 'script_id' && key !== 'selected_card' && !searchKeys.has(key)
|
|
414
|
-
)
|
|
415
|
-
);
|
|
416
|
-
|
|
417
|
-
const newParams = new URLSearchParams({
|
|
418
|
-
...cleanParams,
|
|
419
|
-
current: resetPage,
|
|
420
|
-
pageSize,
|
|
421
|
-
});
|
|
422
|
-
|
|
423
|
-
const newUrl = `${window.location.pathname}?${newParams.toString()}`;
|
|
424
|
-
window.history.replaceState({}, '', newUrl);
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
onFinish(finalValues, resetPage);
|
|
428
|
-
};
|
|
429
|
-
|
|
430
|
-
const selectedSearchFields = details.filter((field) => {
|
|
431
|
-
if (field.type !== 'search') return false;
|
|
432
|
-
|
|
433
|
-
const value = liveFormContents[field.field];
|
|
434
|
-
return Array.isArray(value) ? value.length > 0 : !!value;
|
|
435
|
-
});
|
|
436
|
-
|
|
437
|
-
const handleRemoveSearchField = (fieldName) => {
|
|
438
|
-
const updatedValues = {
|
|
439
|
-
...liveFormContents,
|
|
440
|
-
[fieldName]: [],
|
|
441
|
-
};
|
|
442
|
-
|
|
443
|
-
setLiveFormContents(updatedValues);
|
|
444
|
-
handleSubmit(updatedValues);
|
|
445
|
-
};
|
|
446
|
-
|
|
447
|
-
/**
|
|
448
|
-
*
|
|
449
|
-
* @param {*} values
|
|
450
|
-
*/
|
|
451
|
-
|
|
452
|
-
const onFinish = async (values, resetPage, inputParamsString, parsedColumns) => {
|
|
453
|
-
setLoading(true);
|
|
454
|
-
setCardLoading(true);
|
|
455
|
-
// // Check if the dashboard is visible and both start and end values are provided
|
|
456
|
-
// If true, proceed with hiding the dashboard by setting dashboardVisible to false
|
|
457
|
-
if (dashboardVisible && values.start && values.end) {
|
|
458
|
-
setDashBoardVisible((prev) => {
|
|
459
|
-
if (!prev) return prev; // Prevent unnecessary updates
|
|
460
|
-
|
|
461
|
-
return false;
|
|
462
|
-
});
|
|
463
|
-
}
|
|
464
|
-
const paramsString = inputParamsString || (config.input_parameters ? config.input_parameters : null);
|
|
465
|
-
// Cheacking if there is data and making the data url friendly, ie, if there is date in url
|
|
466
|
-
if (paramsString) {
|
|
467
|
-
let urlsToUpdate = {};
|
|
468
|
-
|
|
469
|
-
let parameterValue = JSON.parse(paramsString);
|
|
470
|
-
|
|
471
|
-
// Variable to store/update the form initial Values
|
|
472
|
-
|
|
473
|
-
let formContent = {};
|
|
474
|
-
|
|
475
|
-
parameters = parameterValue.map((parameter) => {
|
|
476
|
-
//Getting url friendly value by matching the url values and input_parameter values
|
|
477
|
-
let value = values[parameter.field];
|
|
478
|
-
|
|
479
|
-
// If the value is missing at the root level (which happens when search fields are moved
|
|
480
|
-
// into search_values during submission), try to retrieve it from the nested object.
|
|
481
|
-
if (value === undefined && values.search_values && values.search_values[parameter.field] !== undefined) {
|
|
482
|
-
value = values.search_values[parameter.field];
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
// Keep Moment object in state for picker
|
|
486
|
-
if (parameter.type === 'date' && value) {
|
|
487
|
-
formContent[parameter.field] = value.isValid ? value : moment(value); // ensure Moment
|
|
488
|
-
// Format for URL
|
|
489
|
-
urlsToUpdate[parameter.field] = moment(value).format('YYYY-MM-DD');
|
|
490
|
-
} else {
|
|
491
|
-
formContent[parameter.field] = value;
|
|
492
|
-
if (parameter.type) {
|
|
493
|
-
urlsToUpdate[parameter.field] = value;
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
return parameter;
|
|
498
|
-
});
|
|
499
|
-
|
|
500
|
-
const currentParams = Location.search();
|
|
501
|
-
// Mark existing empty values as null so Location.search removes stale query params.
|
|
502
|
-
const filteredParams = Object.fromEntries(
|
|
503
|
-
Object.entries(urlsToUpdate).flatMap(([key, value]) => {
|
|
504
|
-
const shouldRemove = value === undefined || value === null || value === '' || (Array.isArray(value) && value.length === 0);
|
|
505
|
-
if (shouldRemove && !Object.prototype.hasOwnProperty.call(currentParams, key)) {
|
|
506
|
-
return [];
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
return [[key, shouldRemove ? null : value]];
|
|
510
|
-
})
|
|
511
|
-
);
|
|
512
|
-
|
|
513
|
-
setformContents(formContent);
|
|
514
|
-
setLiveFormContents(formContent);
|
|
515
|
-
Location.search({ ...currentParams, ...filteredParams });
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
// Reset Pagination Data
|
|
519
|
-
const latestUrlParams = Location.search();
|
|
520
|
-
const paginationData = {
|
|
521
|
-
current: resetPage || Number(latestUrlParams.current) || 1,
|
|
522
|
-
pageSize: Number(latestUrlParams.pageSize) || pagination.pageSize,
|
|
523
|
-
};
|
|
524
|
-
|
|
525
|
-
// Call API
|
|
526
|
-
try {
|
|
527
|
-
setPagination((prev) => ({
|
|
528
|
-
...prev,
|
|
529
|
-
current: paginationData.current,
|
|
530
|
-
pageSize: paginationData.pageSize,
|
|
531
|
-
}));
|
|
532
|
-
setReportRequestPayload(buildReportRequestPayload(values, paginationData));
|
|
533
|
-
} finally {
|
|
534
|
-
setLoading(false);
|
|
535
|
-
setCardLoading(false);
|
|
536
|
-
}
|
|
537
|
-
};
|
|
538
|
-
|
|
539
|
-
let model = {
|
|
540
|
-
fields: details,
|
|
541
|
-
};
|
|
542
|
-
|
|
543
|
-
return (
|
|
544
|
-
<Card className="reporting-dashboard card card-shadow">
|
|
545
|
-
{/** If dashBoardIds exist and contain elements, render MenuDashBoard*/}
|
|
546
|
-
|
|
547
|
-
{dashBoardIds?.length > 0 ? (
|
|
548
|
-
<MenuDashBoardComponent
|
|
549
|
-
dashBoardIds={dashBoardIds} //Pass the available dashboard IDs to the componen
|
|
550
|
-
activeId={Number(urlParams?.selected_card || 0)}
|
|
551
|
-
dbPtr={dbPtr}
|
|
552
|
-
callback={(record) => {
|
|
553
|
-
const selectedCard = record?.id;
|
|
554
|
-
if (record.other_details) {
|
|
555
|
-
// Convert the other_details string to a JSON object
|
|
556
|
-
let json = JSON.parse(record.other_details);
|
|
557
|
-
const newScriptId = json.script_id;
|
|
558
|
-
|
|
559
|
-
scriptId.current = newScriptId;
|
|
560
|
-
|
|
561
|
-
// Reset Pagination on card click
|
|
562
|
-
setPagination((prev) => ({
|
|
563
|
-
...prev,
|
|
564
|
-
current: 1,
|
|
565
|
-
total: 0,
|
|
566
|
-
}));
|
|
567
|
-
|
|
568
|
-
//Update URL
|
|
569
|
-
Location.search({
|
|
570
|
-
...Location.search(),
|
|
571
|
-
current: 1,
|
|
572
|
-
pageSize: pagination.pageSize,
|
|
573
|
-
script_id: newScriptId,
|
|
574
|
-
selected_card: selectedCard,
|
|
575
|
-
});
|
|
576
|
-
|
|
577
|
-
// menudashBoardVisible = true;
|
|
578
|
-
// Show the dashboard component
|
|
579
|
-
setDashBoardVisible(true);
|
|
580
|
-
// Fetch and update patient details based on the selected item
|
|
581
|
-
getPatientDetails(newScriptId);
|
|
582
|
-
// setDashBoard(true);
|
|
583
|
-
}
|
|
584
|
-
}}
|
|
585
|
-
></MenuDashBoardComponent>
|
|
586
|
-
) : null}
|
|
587
|
-
|
|
588
|
-
{/* Content Below */}
|
|
589
|
-
{loading ? (
|
|
590
|
-
<>
|
|
591
|
-
<Skeleton active />
|
|
592
|
-
</>
|
|
593
|
-
) : (
|
|
594
|
-
<>
|
|
595
|
-
<div>
|
|
596
|
-
{/* <Card className="form-card" style={{ padding: '10px 10px' }}> */}
|
|
597
|
-
{details && details[0] && !loading ? (
|
|
598
|
-
<FormCreator
|
|
599
|
-
{...formLayout}
|
|
600
|
-
layout={formLayout}
|
|
601
|
-
initialValues={{
|
|
602
|
-
layout: formLayout,
|
|
603
|
-
}}
|
|
604
|
-
styles={{ paddingRight: '15px', alignItems: 'center' }}
|
|
605
|
-
fields={details}
|
|
606
|
-
reportId={id}
|
|
607
|
-
formContent={formContents}
|
|
608
|
-
// formContent={{ [model]: {} }}
|
|
609
|
-
modelIndex="requestId"
|
|
610
|
-
model={model}
|
|
611
|
-
onSubmit={handleSubmit}
|
|
612
|
-
onFormValuesChange={setLiveFormContents}
|
|
613
|
-
callback={() => {
|
|
614
|
-
// history.goBack();
|
|
615
|
-
}}
|
|
616
|
-
/>
|
|
617
|
-
) : null}
|
|
618
|
-
</div>
|
|
619
|
-
|
|
620
|
-
<ReportingTable
|
|
621
|
-
columns={columns}
|
|
622
|
-
isFixedIndex={isFixedIndex}
|
|
623
|
-
showScanner={showScanner}
|
|
624
|
-
reportId={reportId}
|
|
625
|
-
requestId={scriptId.current ? scriptId.current : id}
|
|
626
|
-
requestPayload={reportRequestPayload}
|
|
627
|
-
dbPtr={dbPtr}
|
|
628
|
-
barcodeFilterKey={barcodeFilterKey}
|
|
629
|
-
CustomComponents={CustomComponents}
|
|
630
|
-
refresh={refresh}
|
|
631
|
-
config={config}
|
|
632
|
-
|
|
633
|
-
loading={cardLoading}
|
|
634
|
-
pagination={pagination}
|
|
635
|
-
onPaginationChange={(nextPagination) => {
|
|
636
|
-
Location.search({
|
|
637
|
-
...Location.search(),
|
|
638
|
-
current: nextPagination.current,
|
|
639
|
-
pageSize: nextPagination.pageSize,
|
|
640
|
-
});
|
|
641
|
-
setPagination((prev) => ({
|
|
642
|
-
...prev,
|
|
643
|
-
...nextPagination,
|
|
644
|
-
}));
|
|
645
|
-
}}
|
|
646
|
-
attributes={attributes}
|
|
647
|
-
/>
|
|
648
|
-
</>
|
|
649
|
-
)}
|
|
650
|
-
</Card>
|
|
651
|
-
);
|
|
652
|
-
}
|
|
1
|
+
import React, { useState, useEffect, useContext, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
import { Table, Skeleton, Input, Modal, message, Tag } from 'antd';
|
|
4
|
+
|
|
5
|
+
import { Location, FormCreator, GlobalContext, Card } from './../../../../lib/';
|
|
6
|
+
|
|
7
|
+
import { CoreScripts } from './../../../../models/';
|
|
8
|
+
|
|
9
|
+
import moment from 'moment-timezone';
|
|
10
|
+
|
|
11
|
+
import './reporting-dashboard.scss';
|
|
12
|
+
|
|
13
|
+
// import MenuDashBoard from '../../../../pages/homepage-api/menu-dashboard';
|
|
14
|
+
import MenuDashBoardComponent from '../../../../lib/elements/basic/menu-dashboard/menu-dashboard';
|
|
15
|
+
|
|
16
|
+
import ReportingTable from './reporting-table';
|
|
17
|
+
|
|
18
|
+
// Input parameter that decides which date column the report is filtered by
|
|
19
|
+
const DATE_FILTER_FIELD = 'date_filter_type';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* ReportingDashboard component renders the dashboard and handles patient details,
|
|
23
|
+
* configuration, and form layout for generating reports.
|
|
24
|
+
*
|
|
25
|
+
* @param {Object} props - The component's props.
|
|
26
|
+
* @param {Object} props.match - The match object containing the URL parameters.
|
|
27
|
+
* @param {Object} props.CustomComponents - Custom components for rendering.
|
|
28
|
+
* @param {string} props.reportId - The report ID.
|
|
29
|
+
* @param {boolean} props.isFixedIndex - Determines if the index is fixed.
|
|
30
|
+
* @param {Array<string>} props.dashBoardIds - The list of dashboard IDs.
|
|
31
|
+
*
|
|
32
|
+
* @returns {JSX.Element} The rendered ReportingDashboard component.
|
|
33
|
+
*/
|
|
34
|
+
export default function ReportingDashboard({
|
|
35
|
+
match,
|
|
36
|
+
scope,
|
|
37
|
+
CustomComponents,
|
|
38
|
+
reportId,
|
|
39
|
+
isFixedIndex,
|
|
40
|
+
dashBoardIds,
|
|
41
|
+
barcodeFilterKey,
|
|
42
|
+
showScanner,
|
|
43
|
+
dbPtr,
|
|
44
|
+
attributes,
|
|
45
|
+
}) {
|
|
46
|
+
const [config, setConfig] = useState({});
|
|
47
|
+
|
|
48
|
+
// State to manage the layout of the form
|
|
49
|
+
const [formLayout] = useState('inline');
|
|
50
|
+
|
|
51
|
+
const [loading, setLoading] = useState(true);
|
|
52
|
+
|
|
53
|
+
const [cardLoading, setCardLoading] = useState(true);
|
|
54
|
+
|
|
55
|
+
const [searchParameters, setSearchParameters] = useState([]);
|
|
56
|
+
|
|
57
|
+
const [searchValues, setSearchValues] = useState({});
|
|
58
|
+
|
|
59
|
+
const [dashboardVisible, setDashBoardVisible] = useState(false);
|
|
60
|
+
|
|
61
|
+
const [formContents, setformContents] = useState({});
|
|
62
|
+
const [liveFormContents, setLiveFormContents] = useState({});
|
|
63
|
+
const [reportMailRequest, setReportMailRequest] = useState({
|
|
64
|
+
scriptId: null,
|
|
65
|
+
inputParameters: {},
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const scriptId = useRef(null);
|
|
69
|
+
|
|
70
|
+
//In case of reports from core_script , there will be id from params
|
|
71
|
+
// In case of normal menu we need to take id from props
|
|
72
|
+
let id = reportId ? reportId : match?.params?.id;
|
|
73
|
+
|
|
74
|
+
const { CustomModels = {} } = useContext(GlobalContext);
|
|
75
|
+
|
|
76
|
+
const [details, setDetails] = useState([]);
|
|
77
|
+
|
|
78
|
+
const [columns, setColumns] = useState([]); // To set columns
|
|
79
|
+
|
|
80
|
+
const [, setSummaryColumns] = useState([]);
|
|
81
|
+
|
|
82
|
+
const [reportRequestPayload, setReportRequestPayload] = useState(null);
|
|
83
|
+
|
|
84
|
+
const urlParams = Location.search();
|
|
85
|
+
|
|
86
|
+
// Pagination
|
|
87
|
+
const [pagination, setPagination] = useState({
|
|
88
|
+
current: 1,
|
|
89
|
+
pageSize: 20,
|
|
90
|
+
total: 0,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Settings db pointer
|
|
94
|
+
if (!dbPtr) dbPtr = localStorage.db_ptr;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Fetches patient details from the server and updates the relevant state.
|
|
98
|
+
* This includes input parameters, columns, summary columns, and configuration.
|
|
99
|
+
*
|
|
100
|
+
* @returns {Promise<void>} A promise that resolves when the patient details have been fetched and the state has been updated.
|
|
101
|
+
*/
|
|
102
|
+
async function getPatientDetails(idOverride) {
|
|
103
|
+
const fetchId = idOverride || id;
|
|
104
|
+
await CoreScripts.getRecord({ id: fetchId, dbPtr }).then(async ({ result }) => {
|
|
105
|
+
// Check if display columns are provided from backend
|
|
106
|
+
let parsedColumns = [];
|
|
107
|
+
|
|
108
|
+
if (result.display_columns) {
|
|
109
|
+
parsedColumns = JSON.parse(result.display_columns);
|
|
110
|
+
}
|
|
111
|
+
setColumns(parsedColumns);
|
|
112
|
+
|
|
113
|
+
await prepareInputParameters(result, parsedColumns, fetchId);
|
|
114
|
+
|
|
115
|
+
if (result.summary_columns) {
|
|
116
|
+
setSummaryColumns(JSON.parse(result.summary_columns));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
setConfig({ ...result });
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// useEffect(() => {
|
|
124
|
+
// if (!dashboardVisible) {
|
|
125
|
+
// refresh(false);
|
|
126
|
+
// }
|
|
127
|
+
// }, [dashboardVisible]);
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
*
|
|
131
|
+
*
|
|
132
|
+
* Manage initial render
|
|
133
|
+
*/
|
|
134
|
+
|
|
135
|
+
useEffect(() => {
|
|
136
|
+
getPatientDetails();
|
|
137
|
+
}, []);
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Effect hook that triggers the `getPatientDetails` function
|
|
141
|
+
* whenever the `match.params.id` value changes.
|
|
142
|
+
*
|
|
143
|
+
* @returns {void} This hook does not return anything.
|
|
144
|
+
*/
|
|
145
|
+
// useEffect(() => {
|
|
146
|
+
// getPatientDetails();
|
|
147
|
+
// }, [match.params.id]);
|
|
148
|
+
|
|
149
|
+
let parameters;
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Some parameters would need binding with the model
|
|
153
|
+
*
|
|
154
|
+
* @param {*} inputParameters Input parameters from the report configuration.
|
|
155
|
+
*/
|
|
156
|
+
|
|
157
|
+
//Prepare input parameters by mapping default values and binding models if needed
|
|
158
|
+
async function prepareInputParameters(record, parsedColumns, fetchId) {
|
|
159
|
+
setLoading(true);
|
|
160
|
+
let urlParams = Location.search();
|
|
161
|
+
|
|
162
|
+
// If script id exist set into variable
|
|
163
|
+
if (urlParams.script_id) scriptId.current = urlParams.script_id;
|
|
164
|
+
|
|
165
|
+
let otherDetails = record.other_details1 ? JSON.parse(record.other_details1) : null;
|
|
166
|
+
|
|
167
|
+
parameters = record.input_parameters ? JSON.parse(record.input_parameters) : [];
|
|
168
|
+
|
|
169
|
+
let formContent = {};
|
|
170
|
+
const searchFields = (parameters || []).filter((p) => p.type === 'search' && p.search_enabled === 'yes');
|
|
171
|
+
setSearchParameters([...searchFields]);
|
|
172
|
+
|
|
173
|
+
parameters = await parameters?.map((record) => {
|
|
174
|
+
// Only if the url params does have a matching value ,
|
|
175
|
+
// we should not consider the default value
|
|
176
|
+
|
|
177
|
+
if (urlParams[record.field]) {
|
|
178
|
+
if (record.type === 'date') {
|
|
179
|
+
formContent[record.field] = moment.utc(urlParams[record.field]);
|
|
180
|
+
} else if (record.type !== 'search') {
|
|
181
|
+
// Restore plain values ( eg : select filters ) back from the url
|
|
182
|
+
formContent[record.field] = urlParams[record.field];
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// return formContent;
|
|
186
|
+
} else {
|
|
187
|
+
// let StartDate, EndDate;
|
|
188
|
+
switch (record.default) {
|
|
189
|
+
case 'startOfDay':
|
|
190
|
+
formContent[record.field] = moment().tz(process.env.REACT_APP_TIMEZONE).startOf('day');
|
|
191
|
+
break;
|
|
192
|
+
|
|
193
|
+
case 'endOfDay':
|
|
194
|
+
formContent[record.field] = moment().tz(process.env.REACT_APP_TIMEZONE).endOf('day');
|
|
195
|
+
break;
|
|
196
|
+
|
|
197
|
+
case 'startOfWeek':
|
|
198
|
+
formContent[record.field] = moment().tz(process.env.REACT_APP_TIMEZONE).startOf('week');
|
|
199
|
+
break;
|
|
200
|
+
|
|
201
|
+
case 'endOfWeek':
|
|
202
|
+
formContent[record.field] = moment().tz(process.env.REACT_APP_TIMEZONE).endOf('week');
|
|
203
|
+
break;
|
|
204
|
+
|
|
205
|
+
case 'currentDate':
|
|
206
|
+
formContent[record.field] = moment().tz(process.env.REACT_APP_TIMEZONE);
|
|
207
|
+
break;
|
|
208
|
+
|
|
209
|
+
default:
|
|
210
|
+
// Any other default is taken as the value itself ( eg : select filters )
|
|
211
|
+
if (record.default !== undefined && record.default !== null && record.type !== 'date') {
|
|
212
|
+
formContent[record.field] = record.default;
|
|
213
|
+
}
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// If it is a date field and still no value, set it to today's date
|
|
219
|
+
if (record.type === 'date' && !formContent[record.field]) {
|
|
220
|
+
formContent[record.field] = moment().tz(process.env.REACT_APP_TIMEZONE);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// For a static select with no value yet , preselect the first option
|
|
224
|
+
if (record.type === 'select' && Array.isArray(record.options) && formContent[record.field] === undefined) {
|
|
225
|
+
formContent[record.field] = record.options[0]?.valueMember;
|
|
226
|
+
}
|
|
227
|
+
if (record.type === 'search') {
|
|
228
|
+
if (!formContent[record.field]) formContent[record.field] = [];
|
|
229
|
+
return {
|
|
230
|
+
...record,
|
|
231
|
+
reportId: fetchId,
|
|
232
|
+
onReset: () => getPatientDetails(fetchId),
|
|
233
|
+
required: record.required,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
if (['reference-select', 'reference-search', 'select'].indexOf(record.type) !== -1) {
|
|
237
|
+
// let model = "";
|
|
238
|
+
let model = CustomModels[record.modelName];
|
|
239
|
+
|
|
240
|
+
return {
|
|
241
|
+
...record,
|
|
242
|
+
model,
|
|
243
|
+
required: record.required,
|
|
244
|
+
};
|
|
245
|
+
} else {
|
|
246
|
+
return {
|
|
247
|
+
...record,
|
|
248
|
+
required: true,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
// Update form content state
|
|
253
|
+
setformContents(formContent);
|
|
254
|
+
setLiveFormContents(formContent);
|
|
255
|
+
|
|
256
|
+
// Trigger form submission
|
|
257
|
+
onFinish(formContent, null, record.input_parameters, parsedColumns);
|
|
258
|
+
|
|
259
|
+
setLoading(false);
|
|
260
|
+
|
|
261
|
+
// Check if input parameters are enabled or disabled in otherDetails
|
|
262
|
+
if (otherDetails?.isDisableInputParameters) {
|
|
263
|
+
// If enabled, clear the details array
|
|
264
|
+
setDetails([]);
|
|
265
|
+
} else {
|
|
266
|
+
// The date filter input is shown only when the filter is enabled in otherDetails .
|
|
267
|
+
// Otherwise it stays hidden holding its default value , so the report keeps filtering
|
|
268
|
+
// on the default date
|
|
269
|
+
const filterKey = otherDetails ? Object.keys(otherDetails).find((key) => key.toLowerCase().trim() === 'enableuserfilter') : null;
|
|
270
|
+
|
|
271
|
+
const isFilterEnabled = filterKey ? otherDetails[filterKey] === true || otherDetails[filterKey] === 'true' : false;
|
|
272
|
+
|
|
273
|
+
// Keep all parameters with a type (including search) to render in FormCreator
|
|
274
|
+
setDetails([
|
|
275
|
+
...parameters
|
|
276
|
+
.filter((ele) => ele.type)
|
|
277
|
+
.map((ele) => (ele.field === DATE_FILTER_FIELD ? { ...ele, visible: isFilterEnabled } : ele)),
|
|
278
|
+
]);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Refresh patient details.
|
|
283
|
+
|
|
284
|
+
function refresh() {
|
|
285
|
+
getPatientDetails(scriptId.current || id);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const buildReportRequestPayload = (values = {}, paginationOverride) => {
|
|
289
|
+
const pager = paginationOverride || pagination;
|
|
290
|
+
const formattedValues = {};
|
|
291
|
+
|
|
292
|
+
Object.keys(values || {}).forEach((key) => {
|
|
293
|
+
const val = values[key];
|
|
294
|
+
formattedValues[key] = moment.isMoment(val) ? val.format('YYYY-MM-DD') : val;
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
const paginationData = {
|
|
298
|
+
page: pager.current || 1,
|
|
299
|
+
limit: pager.pageSize || 10,
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
if (scope) {
|
|
303
|
+
return {
|
|
304
|
+
body: {
|
|
305
|
+
...scope,
|
|
306
|
+
...paginationData,
|
|
307
|
+
},
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return {
|
|
312
|
+
body: {
|
|
313
|
+
...formattedValues,
|
|
314
|
+
...paginationData,
|
|
315
|
+
},
|
|
316
|
+
};
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
const handleSubmit = (values) => {
|
|
320
|
+
// Extract search fields from the form values
|
|
321
|
+
const searchKeys = searchParameters.map((p) => p.field);
|
|
322
|
+
const currentSearchValues = {};
|
|
323
|
+
const formValues = {};
|
|
324
|
+
|
|
325
|
+
Object.keys(values).forEach((key) => {
|
|
326
|
+
if (searchKeys.includes(key)) {
|
|
327
|
+
currentSearchValues[key] = values[key];
|
|
328
|
+
} else {
|
|
329
|
+
formValues[key] = values[key];
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
const hasSearchValues = Object.values(currentSearchValues).some((v) => Array.isArray(v) && v.length > 0);
|
|
334
|
+
|
|
335
|
+
if (!hasSearchValues) {
|
|
336
|
+
runSubmit(formValues);
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Check if main form values (non-search) changed
|
|
341
|
+
const formChanged = Object.keys(formValues).some((key) => {
|
|
342
|
+
const newVal = formValues[key];
|
|
343
|
+
const oldVal = formContents[key];
|
|
344
|
+
|
|
345
|
+
if (moment.isMoment(newVal) && moment.isMoment(oldVal)) {
|
|
346
|
+
return !newVal.isSame(oldVal, 'day');
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return newVal !== oldVal;
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
if (formChanged) {
|
|
353
|
+
Modal.confirm({
|
|
354
|
+
title: 'Filters changed',
|
|
355
|
+
content: 'You changed some filters. Do you want to search using these filters also?',
|
|
356
|
+
okText: 'Yes',
|
|
357
|
+
cancelText: 'No',
|
|
358
|
+
|
|
359
|
+
onOk() {
|
|
360
|
+
// YES → send form values + search condition
|
|
361
|
+
const finalValues = {
|
|
362
|
+
...formValues,
|
|
363
|
+
search_values: currentSearchValues,
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
runSubmit(finalValues);
|
|
367
|
+
},
|
|
368
|
+
|
|
369
|
+
onCancel() {
|
|
370
|
+
// NO → reset form values
|
|
371
|
+
const resetValues = {};
|
|
372
|
+
Object.keys(formValues).forEach((key) => {
|
|
373
|
+
resetValues[key] = null;
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
const finalValues = {
|
|
377
|
+
...resetValues,
|
|
378
|
+
search_values: currentSearchValues,
|
|
379
|
+
};
|
|
380
|
+
|
|
381
|
+
runSubmit(finalValues);
|
|
382
|
+
},
|
|
383
|
+
});
|
|
384
|
+
} else {
|
|
385
|
+
// no form change
|
|
386
|
+
const resetValues = {};
|
|
387
|
+
Object.keys(formValues).forEach((key) => {
|
|
388
|
+
resetValues[key] = null;
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
const finalValues = {
|
|
392
|
+
...resetValues,
|
|
393
|
+
search_values: currentSearchValues,
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
runSubmit(finalValues);
|
|
397
|
+
}
|
|
398
|
+
};
|
|
399
|
+
|
|
400
|
+
const runSubmit = (finalValues) => {
|
|
401
|
+
const { pageSize } = pagination;
|
|
402
|
+
const resetPage = 1;
|
|
403
|
+
|
|
404
|
+
scriptId.current = null;
|
|
405
|
+
|
|
406
|
+
const hasSearchValues = finalValues.search_values && Object.values(finalValues.search_values).some((v) => Array.isArray(v) && v.length > 0);
|
|
407
|
+
|
|
408
|
+
if (!hasSearchValues) {
|
|
409
|
+
const currentUrlParams = Location.search();
|
|
410
|
+
const searchKeys = new Set(searchParameters.map((parameter) => parameter.field));
|
|
411
|
+
const cleanParams = Object.fromEntries(
|
|
412
|
+
Object.entries(currentUrlParams).filter(
|
|
413
|
+
([key]) => key !== 'script_id' && key !== 'selected_card' && !searchKeys.has(key)
|
|
414
|
+
)
|
|
415
|
+
);
|
|
416
|
+
|
|
417
|
+
const newParams = new URLSearchParams({
|
|
418
|
+
...cleanParams,
|
|
419
|
+
current: resetPage,
|
|
420
|
+
pageSize,
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
const newUrl = `${window.location.pathname}?${newParams.toString()}`;
|
|
424
|
+
window.history.replaceState({}, '', newUrl);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
onFinish(finalValues, resetPage);
|
|
428
|
+
};
|
|
429
|
+
|
|
430
|
+
const selectedSearchFields = details.filter((field) => {
|
|
431
|
+
if (field.type !== 'search') return false;
|
|
432
|
+
|
|
433
|
+
const value = liveFormContents[field.field];
|
|
434
|
+
return Array.isArray(value) ? value.length > 0 : !!value;
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
const handleRemoveSearchField = (fieldName) => {
|
|
438
|
+
const updatedValues = {
|
|
439
|
+
...liveFormContents,
|
|
440
|
+
[fieldName]: [],
|
|
441
|
+
};
|
|
442
|
+
|
|
443
|
+
setLiveFormContents(updatedValues);
|
|
444
|
+
handleSubmit(updatedValues);
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
*
|
|
449
|
+
* @param {*} values
|
|
450
|
+
*/
|
|
451
|
+
|
|
452
|
+
const onFinish = async (values, resetPage, inputParamsString, parsedColumns) => {
|
|
453
|
+
setLoading(true);
|
|
454
|
+
setCardLoading(true);
|
|
455
|
+
// // Check if the dashboard is visible and both start and end values are provided
|
|
456
|
+
// If true, proceed with hiding the dashboard by setting dashboardVisible to false
|
|
457
|
+
if (dashboardVisible && values.start && values.end) {
|
|
458
|
+
setDashBoardVisible((prev) => {
|
|
459
|
+
if (!prev) return prev; // Prevent unnecessary updates
|
|
460
|
+
|
|
461
|
+
return false;
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
const paramsString = inputParamsString || (config.input_parameters ? config.input_parameters : null);
|
|
465
|
+
// Cheacking if there is data and making the data url friendly, ie, if there is date in url
|
|
466
|
+
if (paramsString) {
|
|
467
|
+
let urlsToUpdate = {};
|
|
468
|
+
|
|
469
|
+
let parameterValue = JSON.parse(paramsString);
|
|
470
|
+
|
|
471
|
+
// Variable to store/update the form initial Values
|
|
472
|
+
|
|
473
|
+
let formContent = {};
|
|
474
|
+
|
|
475
|
+
parameters = parameterValue.map((parameter) => {
|
|
476
|
+
//Getting url friendly value by matching the url values and input_parameter values
|
|
477
|
+
let value = values[parameter.field];
|
|
478
|
+
|
|
479
|
+
// If the value is missing at the root level (which happens when search fields are moved
|
|
480
|
+
// into search_values during submission), try to retrieve it from the nested object.
|
|
481
|
+
if (value === undefined && values.search_values && values.search_values[parameter.field] !== undefined) {
|
|
482
|
+
value = values.search_values[parameter.field];
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// Keep Moment object in state for picker
|
|
486
|
+
if (parameter.type === 'date' && value) {
|
|
487
|
+
formContent[parameter.field] = value.isValid ? value : moment(value); // ensure Moment
|
|
488
|
+
// Format for URL
|
|
489
|
+
urlsToUpdate[parameter.field] = moment(value).format('YYYY-MM-DD');
|
|
490
|
+
} else {
|
|
491
|
+
formContent[parameter.field] = value;
|
|
492
|
+
if (parameter.type) {
|
|
493
|
+
urlsToUpdate[parameter.field] = value;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
return parameter;
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
const currentParams = Location.search();
|
|
501
|
+
// Mark existing empty values as null so Location.search removes stale query params.
|
|
502
|
+
const filteredParams = Object.fromEntries(
|
|
503
|
+
Object.entries(urlsToUpdate).flatMap(([key, value]) => {
|
|
504
|
+
const shouldRemove = value === undefined || value === null || value === '' || (Array.isArray(value) && value.length === 0);
|
|
505
|
+
if (shouldRemove && !Object.prototype.hasOwnProperty.call(currentParams, key)) {
|
|
506
|
+
return [];
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
return [[key, shouldRemove ? null : value]];
|
|
510
|
+
})
|
|
511
|
+
);
|
|
512
|
+
|
|
513
|
+
setformContents(formContent);
|
|
514
|
+
setLiveFormContents(formContent);
|
|
515
|
+
Location.search({ ...currentParams, ...filteredParams });
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// Reset Pagination Data
|
|
519
|
+
const latestUrlParams = Location.search();
|
|
520
|
+
const paginationData = {
|
|
521
|
+
current: resetPage || Number(latestUrlParams.current) || 1,
|
|
522
|
+
pageSize: Number(latestUrlParams.pageSize) || pagination.pageSize,
|
|
523
|
+
};
|
|
524
|
+
|
|
525
|
+
// Call API
|
|
526
|
+
try {
|
|
527
|
+
setPagination((prev) => ({
|
|
528
|
+
...prev,
|
|
529
|
+
current: paginationData.current,
|
|
530
|
+
pageSize: paginationData.pageSize,
|
|
531
|
+
}));
|
|
532
|
+
setReportRequestPayload(buildReportRequestPayload(values, paginationData));
|
|
533
|
+
} finally {
|
|
534
|
+
setLoading(false);
|
|
535
|
+
setCardLoading(false);
|
|
536
|
+
}
|
|
537
|
+
};
|
|
538
|
+
|
|
539
|
+
let model = {
|
|
540
|
+
fields: details,
|
|
541
|
+
};
|
|
542
|
+
|
|
543
|
+
return (
|
|
544
|
+
<Card className="reporting-dashboard card card-shadow">
|
|
545
|
+
{/** If dashBoardIds exist and contain elements, render MenuDashBoard*/}
|
|
546
|
+
|
|
547
|
+
{dashBoardIds?.length > 0 ? (
|
|
548
|
+
<MenuDashBoardComponent
|
|
549
|
+
dashBoardIds={dashBoardIds} //Pass the available dashboard IDs to the componen
|
|
550
|
+
activeId={Number(urlParams?.selected_card || 0)}
|
|
551
|
+
dbPtr={dbPtr}
|
|
552
|
+
callback={(record) => {
|
|
553
|
+
const selectedCard = record?.id;
|
|
554
|
+
if (record.other_details) {
|
|
555
|
+
// Convert the other_details string to a JSON object
|
|
556
|
+
let json = JSON.parse(record.other_details);
|
|
557
|
+
const newScriptId = json.script_id;
|
|
558
|
+
|
|
559
|
+
scriptId.current = newScriptId;
|
|
560
|
+
|
|
561
|
+
// Reset Pagination on card click
|
|
562
|
+
setPagination((prev) => ({
|
|
563
|
+
...prev,
|
|
564
|
+
current: 1,
|
|
565
|
+
total: 0,
|
|
566
|
+
}));
|
|
567
|
+
|
|
568
|
+
//Update URL
|
|
569
|
+
Location.search({
|
|
570
|
+
...Location.search(),
|
|
571
|
+
current: 1,
|
|
572
|
+
pageSize: pagination.pageSize,
|
|
573
|
+
script_id: newScriptId,
|
|
574
|
+
selected_card: selectedCard,
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
// menudashBoardVisible = true;
|
|
578
|
+
// Show the dashboard component
|
|
579
|
+
setDashBoardVisible(true);
|
|
580
|
+
// Fetch and update patient details based on the selected item
|
|
581
|
+
getPatientDetails(newScriptId);
|
|
582
|
+
// setDashBoard(true);
|
|
583
|
+
}
|
|
584
|
+
}}
|
|
585
|
+
></MenuDashBoardComponent>
|
|
586
|
+
) : null}
|
|
587
|
+
|
|
588
|
+
{/* Content Below */}
|
|
589
|
+
{loading ? (
|
|
590
|
+
<>
|
|
591
|
+
<Skeleton active />
|
|
592
|
+
</>
|
|
593
|
+
) : (
|
|
594
|
+
<>
|
|
595
|
+
<div>
|
|
596
|
+
{/* <Card className="form-card" style={{ padding: '10px 10px' }}> */}
|
|
597
|
+
{details && details[0] && !loading ? (
|
|
598
|
+
<FormCreator
|
|
599
|
+
{...formLayout}
|
|
600
|
+
layout={formLayout}
|
|
601
|
+
initialValues={{
|
|
602
|
+
layout: formLayout,
|
|
603
|
+
}}
|
|
604
|
+
styles={{ paddingRight: '15px', alignItems: 'center' }}
|
|
605
|
+
fields={details}
|
|
606
|
+
reportId={id}
|
|
607
|
+
formContent={formContents}
|
|
608
|
+
// formContent={{ [model]: {} }}
|
|
609
|
+
modelIndex="requestId"
|
|
610
|
+
model={model}
|
|
611
|
+
onSubmit={handleSubmit}
|
|
612
|
+
onFormValuesChange={setLiveFormContents}
|
|
613
|
+
callback={() => {
|
|
614
|
+
// history.goBack();
|
|
615
|
+
}}
|
|
616
|
+
/>
|
|
617
|
+
) : null}
|
|
618
|
+
</div>
|
|
619
|
+
|
|
620
|
+
<ReportingTable
|
|
621
|
+
columns={columns}
|
|
622
|
+
isFixedIndex={isFixedIndex}
|
|
623
|
+
showScanner={showScanner}
|
|
624
|
+
reportId={reportId}
|
|
625
|
+
requestId={scriptId.current ? scriptId.current : id}
|
|
626
|
+
requestPayload={reportRequestPayload}
|
|
627
|
+
dbPtr={dbPtr}
|
|
628
|
+
barcodeFilterKey={barcodeFilterKey}
|
|
629
|
+
CustomComponents={CustomComponents}
|
|
630
|
+
refresh={refresh}
|
|
631
|
+
config={config}
|
|
632
|
+
|
|
633
|
+
loading={cardLoading}
|
|
634
|
+
pagination={pagination}
|
|
635
|
+
onPaginationChange={(nextPagination) => {
|
|
636
|
+
Location.search({
|
|
637
|
+
...Location.search(),
|
|
638
|
+
current: nextPagination.current,
|
|
639
|
+
pageSize: nextPagination.pageSize,
|
|
640
|
+
});
|
|
641
|
+
setPagination((prev) => ({
|
|
642
|
+
...prev,
|
|
643
|
+
...nextPagination,
|
|
644
|
+
}));
|
|
645
|
+
}}
|
|
646
|
+
attributes={attributes}
|
|
647
|
+
/>
|
|
648
|
+
</>
|
|
649
|
+
)}
|
|
650
|
+
</Card>
|
|
651
|
+
);
|
|
652
|
+
}
|