ui-soxo-bootstrap-core 2.6.5 → 2.6.6
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 +33 -33
- package/.husky/pre-commit +11 -11
- package/.prettierrc.json +10 -10
- 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 +20 -20
- package/core/components/landing-api/landing-api.js +492 -492
- package/core/components/landing-api/landing-api.scss +19 -19
- 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 +365 -365
- 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 +90 -90
- package/core/lib/components/consent/signature-pad.scss +14 -14
- 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 +413 -413
- package/core/lib/components/global-header/global-header.scss +369 -369
- 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 +578 -578
- package/core/lib/components/sidemenu/sidemenu.scss +277 -277
- 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 +106 -106
- package/core/lib/elements/basic/country-phone-input/phone-input.scss +61 -61
- package/core/lib/elements/basic/datepicker/datepicker.js +33 -33
- package/core/lib/elements/basic/dragabble-wrapper/draggable-wrapper.js +136 -136
- 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 +114 -114
- 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 +337 -337
- 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 +100 -100
- 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 +27 -27
- 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 +624 -624
- package/core/lib/models/forms/components/form-creator/form-creator.scss +30 -29
- 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 +593 -593
- 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 +601 -601
- package/core/lib/models/process/components/process-dashboard/process-dashboard.scss +62 -62
- 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 +62 -62
- package/core/lib/modules/generic/generic-list/generic-list.js +705 -705
- package/core/lib/modules/generic/generic-list/generic-list.scss +34 -34
- 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 +201 -201
- 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 +864 -864
- package/core/lib/pages/login/login.scss +344 -344
- package/core/lib/pages/login/reset-password.js +125 -125
- package/core/lib/pages/login/reset-password.scss +22 -22
- 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 +211 -211
- 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 +223 -223
- 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/form/form.utils.js +255 -255
- package/core/lib/utils/generic/generic.utils.js +69 -69
- package/core/lib/utils/http/auth.helper.js +95 -95
- package/core/lib/utils/http/http.utils.js +158 -158
- package/core/lib/utils/http/readme.md +14 -14
- package/core/lib/utils/index.js +40 -40
- 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 +150 -150
- 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 +427 -427
- 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 +288 -288
- 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 +585 -585
- package/core/models/menus/components/menu-lists/menu-lists.scss +46 -46
- package/core/models/menus/menus.js +310 -310
- 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/role-add.js +312 -312
- package/core/models/roles/components/role-add/role-add.scss +4 -4
- package/core/models/roles/components/role-list/role-list.js +386 -386
- package/core/models/roles/roles.js +196 -196
- package/core/models/staff/components/staff-add/staff-add.js +467 -467
- 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 +406 -406
- 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 +856 -856
- package/core/models/users/components/user-add/user-edit.js +106 -106
- 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 -0
- package/core/modules/reporting/components/reporting-dashboard/display-columns/build-display-columns.js +74 -0
- package/core/modules/reporting/components/reporting-dashboard/display-columns/build-display-columns.test.js +74 -0
- package/core/modules/reporting/components/reporting-dashboard/display-columns/display-cell-renderer.js +252 -0
- package/core/modules/reporting/components/reporting-dashboard/display-columns/display-cell-renderer.test.js +126 -0
- package/core/modules/reporting/components/reporting-dashboard/reporting-dashboard.js +880 -1206
- package/core/modules/reporting/components/reporting-dashboard/reporting-dashboard.scss +171 -171
- package/core/modules/steps/action-buttons.js +74 -76
- package/core/modules/steps/action-buttons.scss +44 -15
- package/core/modules/steps/steps.js +348 -346
- package/core/modules/steps/steps.scss +357 -159
- package/core/modules/steps/timeline.js +56 -54
- 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 +123 -123
- package/tsconfig.json +26 -26
- package/webpack.config.js +173 -173
|
@@ -1,864 +1,864 @@
|
|
|
1
|
-
import React, { useState, useContext, useEffect } from 'react';
|
|
2
|
-
|
|
3
|
-
import { Form, Input, message, Result, Radio, Divider, Typography } from 'antd';
|
|
4
|
-
|
|
5
|
-
import { withRouter, Link } from 'react-router-dom';
|
|
6
|
-
|
|
7
|
-
import backgroundImage from './../../../assets/images/vector.png';
|
|
8
|
-
|
|
9
|
-
import OTPInput from 'otp-input-react';
|
|
10
|
-
|
|
11
|
-
import { useOtpTimer } from '../../hooks/use-otp-timer';
|
|
12
|
-
|
|
13
|
-
import { motion } from 'framer-motion';
|
|
14
|
-
|
|
15
|
-
import { Button } from '../../elements';
|
|
16
|
-
|
|
17
|
-
import './login.scss';
|
|
18
|
-
|
|
19
|
-
// import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
20
|
-
|
|
21
|
-
// import { faCheck } from "@fortawesome/free-solid-svg-icons";
|
|
22
|
-
|
|
23
|
-
import FirebaseUtils from '../../../lib/utils/firebase.utils';
|
|
24
|
-
|
|
25
|
-
import ApiUtils from '../../utils/api/api.utils';
|
|
26
|
-
|
|
27
|
-
import { GlobalContext } from './../../Store';
|
|
28
|
-
|
|
29
|
-
import { getAccessToken, getRefreshToken } from '../../utils/http/auth.helper';
|
|
30
|
-
|
|
31
|
-
import { Location } from '../../utils';
|
|
32
|
-
|
|
33
|
-
import { checkLicenseStatus, formatMobile, checkExpiryStatus, safeJSON } from '../../utils/common/common.utils';
|
|
34
|
-
|
|
35
|
-
import { MailOutlined, MessageOutlined, WhatsAppOutlined } from '@ant-design/icons';
|
|
36
|
-
|
|
37
|
-
import ResetPassword from './reset-password';
|
|
38
|
-
|
|
39
|
-
const { Text, Title } = Typography;
|
|
40
|
-
|
|
41
|
-
const layout = {
|
|
42
|
-
labelCol: { span: 24 },
|
|
43
|
-
|
|
44
|
-
wrapperCol: { span: 24 },
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
const tailLayout = {
|
|
48
|
-
wrapperCol: { span: 8 },
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
const LICENSE_EXPIRY = '2026-12-12';
|
|
52
|
-
|
|
53
|
-
//password valdity expire
|
|
54
|
-
const PASSWORD_VALIDITY_DAYS = 90;
|
|
55
|
-
|
|
56
|
-
const headers = {
|
|
57
|
-
db_ptr: 'nuraho',
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
*
|
|
62
|
-
* @param {*} param0
|
|
63
|
-
* @returns
|
|
64
|
-
*/
|
|
65
|
-
function LoginPhone({ history, appSettings }) {
|
|
66
|
-
const { brandLogo, heroImage, footerLogo } = appSettings;
|
|
67
|
-
|
|
68
|
-
// Hook for OTP Timer
|
|
69
|
-
const { expired: otpExpired, formatted, startFromExpiry } = useOtpTimer();
|
|
70
|
-
|
|
71
|
-
const { dispatch, state, isMobile } = useContext(GlobalContext);
|
|
72
|
-
// variabel used for btnloading
|
|
73
|
-
|
|
74
|
-
const [loading, setLoading] = useState(false);
|
|
75
|
-
|
|
76
|
-
const [ldaploading, setLdapLoading] = useState(false);
|
|
77
|
-
|
|
78
|
-
// variable used to show otp generating
|
|
79
|
-
|
|
80
|
-
const [otpVisible, setOtpVisible] = useState(false);
|
|
81
|
-
// variabale used to show otp entering screen
|
|
82
|
-
|
|
83
|
-
const [otpVerification, setotpVerification] = useState(false);
|
|
84
|
-
// otp sucess
|
|
85
|
-
const [otpSuccess, setOtpSuccess] = useState(false);
|
|
86
|
-
// otp fail err
|
|
87
|
-
const [otpError, setOtpError] = useState(false);
|
|
88
|
-
|
|
89
|
-
const [otpValue, setOtpValue] = useState('');
|
|
90
|
-
// setting user credentials
|
|
91
|
-
const [user, setUser] = useState([]);
|
|
92
|
-
|
|
93
|
-
// for communication mode [mobile,sms,email]
|
|
94
|
-
const [communicationMode, setCommunicationMode] = useState(null); // default selected email
|
|
95
|
-
const [modeError, setModeError] = useState(false);
|
|
96
|
-
|
|
97
|
-
//for forgot password show
|
|
98
|
-
const [showResetpassword, setShowResetpassword] = useState(false);
|
|
99
|
-
|
|
100
|
-
//for expired password show
|
|
101
|
-
const [expiredPassword, setExpiredPassword] = useState(false);
|
|
102
|
-
|
|
103
|
-
//for default name select when expire case
|
|
104
|
-
const [defaultUsername, setDefaultUsername] = useState('');
|
|
105
|
-
|
|
106
|
-
const isAuthenticated = Boolean(getAccessToken());
|
|
107
|
-
const isRefreshTokenExist = Boolean(getRefreshToken());
|
|
108
|
-
|
|
109
|
-
const path = window.location.pathname;
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* handlePasswordExpiryCheck
|
|
113
|
-
* --------------------------
|
|
114
|
-
* Validates whether a user's password is expired or nearing expiry.
|
|
115
|
-
*
|
|
116
|
-
* - Parses `last_password_change` from user.other_details.
|
|
117
|
-
* - Calculates expiry using PASSWORD_VALIDITY_DAYS.
|
|
118
|
-
* - Uses `checkExpiryStatus()` to determine status.
|
|
119
|
-
* - Shows Ant Design warning message if expired or within warning period.
|
|
120
|
-
* - Warning message includes navigation to `/change-password`.
|
|
121
|
-
*
|
|
122
|
-
* Requires:
|
|
123
|
-
* - PASSWORD_VALIDITY_DAYS constant
|
|
124
|
-
* - checkExpiryStatus utility
|
|
125
|
-
* - React Router history
|
|
126
|
-
* - antd message component
|
|
127
|
-
*/
|
|
128
|
-
const handlePasswordExpiryCheck = (user) => {
|
|
129
|
-
const otherDetails = user?.other_details ? JSON.parse(user.other_details) : null;
|
|
130
|
-
|
|
131
|
-
const lastPasswordChange = otherDetails?.last_password_change;
|
|
132
|
-
|
|
133
|
-
if (lastPasswordChange) {
|
|
134
|
-
const onlyDate = new Date(lastPasswordChange).toISOString().split('T')[0];
|
|
135
|
-
const passwordExpiryDate = new Date(onlyDate);
|
|
136
|
-
passwordExpiryDate.setDate(passwordExpiryDate.getDate() + PASSWORD_VALIDITY_DAYS);
|
|
137
|
-
|
|
138
|
-
const passwordStatus = checkExpiryStatus({
|
|
139
|
-
expiryDate: passwordExpiryDate,
|
|
140
|
-
warningDays: 2,
|
|
141
|
-
expiredMessage: 'Your password has expired. Please reset it.',
|
|
142
|
-
warningMessage: (d) => (
|
|
143
|
-
<span>
|
|
144
|
-
Your password will expire in {d} day(s).{' '}
|
|
145
|
-
<a
|
|
146
|
-
onClick={() => {
|
|
147
|
-
history.push('/change-password');
|
|
148
|
-
}}
|
|
149
|
-
>
|
|
150
|
-
Click here to update.
|
|
151
|
-
</a>
|
|
152
|
-
</span>
|
|
153
|
-
),
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
if (passwordStatus.message) {
|
|
157
|
-
message.warning(passwordStatus.message);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
const onFinish = (values) => {
|
|
163
|
-
setLoading(true);
|
|
164
|
-
|
|
165
|
-
const status = checkLicenseStatus(LICENSE_EXPIRY);
|
|
166
|
-
|
|
167
|
-
if (!status.valid) {
|
|
168
|
-
message.error(status.message);
|
|
169
|
-
setLoading(false);
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
if (status.message) {
|
|
174
|
-
if (status.level === 'error') {
|
|
175
|
-
message.error(status.message);
|
|
176
|
-
} else if (status.level === 'warning') {
|
|
177
|
-
message.warning(status.message);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
if (process.env.REACT_APP_PRIMARY_BACKEND === 'SQL') {
|
|
182
|
-
let formBody = {
|
|
183
|
-
username: values.email,
|
|
184
|
-
|
|
185
|
-
password: values.password,
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
return ApiUtils.post({ url: 'auth/login', formBody, headers })
|
|
189
|
-
|
|
190
|
-
.then((result) => {
|
|
191
|
-
setLoading(false);
|
|
192
|
-
|
|
193
|
-
const { user, access_token, refresh_token, insider_token } = result;
|
|
194
|
-
if (access_token) localStorage.access_token = access_token;
|
|
195
|
-
|
|
196
|
-
if (insider_token) localStorage.insider_token = insider_token;
|
|
197
|
-
|
|
198
|
-
if (result.success) {
|
|
199
|
-
handlePasswordExpiryCheck(user);
|
|
200
|
-
|
|
201
|
-
//two_factor_authentication variable is present then proceed Two factor authentication
|
|
202
|
-
if (result.data && result.data.two_factor_authentication) {
|
|
203
|
-
let data;
|
|
204
|
-
|
|
205
|
-
// set variable used for otp send screen
|
|
206
|
-
setOtpVisible(true);
|
|
207
|
-
|
|
208
|
-
// set user credentials
|
|
209
|
-
data = {
|
|
210
|
-
username: result.data.email,
|
|
211
|
-
password: values.password,
|
|
212
|
-
mode: result.data.mode ? result.data.mode : null,
|
|
213
|
-
mobile: result.data.mobile ? result.data.mobile : null,
|
|
214
|
-
};
|
|
215
|
-
|
|
216
|
-
// set user values
|
|
217
|
-
setUser(data);
|
|
218
|
-
// Set default communication mode automatically
|
|
219
|
-
if (result.data.mode) {
|
|
220
|
-
setCommunicationMode(result.data.mode);
|
|
221
|
-
}
|
|
222
|
-
} else {
|
|
223
|
-
let d = user;
|
|
224
|
-
|
|
225
|
-
let userInfo = {
|
|
226
|
-
id: user.id,
|
|
227
|
-
locations: [],
|
|
228
|
-
...d,
|
|
229
|
-
...{
|
|
230
|
-
loggedCheckDone: true,
|
|
231
|
-
},
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
dispatch({ type: 'user', payload: userInfo });
|
|
235
|
-
|
|
236
|
-
localStorage.setItem('userInfo', JSON.stringify(userInfo));
|
|
237
|
-
if (refresh_token) localStorage.setItem('refresh_token', refresh_token);
|
|
238
|
-
|
|
239
|
-
// Setting DBPTR
|
|
240
|
-
if (user?.organization_details) {
|
|
241
|
-
const data = safeJSON(user?.organization_details);
|
|
242
|
-
|
|
243
|
-
const defaultBranch = data.branch.find((b) => b.defaultBranch === true);
|
|
244
|
-
|
|
245
|
-
const defaultDbptr = defaultBranch?.dbPtr;
|
|
246
|
-
|
|
247
|
-
localStorage.setItem('db_ptr', defaultDbptr);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
history.push('/');
|
|
251
|
-
}
|
|
252
|
-
} else {
|
|
253
|
-
if (result.passwordChange) {
|
|
254
|
-
message.warning(result.message);
|
|
255
|
-
|
|
256
|
-
//time for redirect when expire
|
|
257
|
-
setTimeout(() => {
|
|
258
|
-
setExpiredPassword(true);
|
|
259
|
-
setDefaultUsername(values.email);
|
|
260
|
-
|
|
261
|
-
setShowResetpassword(true);
|
|
262
|
-
}, 1500);
|
|
263
|
-
} else {
|
|
264
|
-
message.warning(result.message);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
})
|
|
268
|
-
.catch((error) => {
|
|
269
|
-
console.log(error);
|
|
270
|
-
|
|
271
|
-
message.error('This operation has failed.');
|
|
272
|
-
|
|
273
|
-
setLoading(false);
|
|
274
|
-
});
|
|
275
|
-
} else {
|
|
276
|
-
FirebaseUtils.loginWithEmail(values)
|
|
277
|
-
|
|
278
|
-
.then((result) => {
|
|
279
|
-
setLoading(false);
|
|
280
|
-
|
|
281
|
-
if (result.id) {
|
|
282
|
-
if (result.active) {
|
|
283
|
-
let d = result;
|
|
284
|
-
|
|
285
|
-
let userInfo = {
|
|
286
|
-
id: result.id,
|
|
287
|
-
locations: [],
|
|
288
|
-
...d,
|
|
289
|
-
...{
|
|
290
|
-
loggedCheckDone: true,
|
|
291
|
-
},
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
if (result.role && result.role.name === 'admin') {
|
|
295
|
-
userInfo.isAdmin = true;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
dispatch({ type: 'user', payload: userInfo });
|
|
299
|
-
|
|
300
|
-
localStorage.setItem('userInfo', JSON.stringify(userInfo));
|
|
301
|
-
|
|
302
|
-
history.push('/');
|
|
303
|
-
} else {
|
|
304
|
-
message.error('Your account is inactive, Please contact support.');
|
|
305
|
-
}
|
|
306
|
-
} else {
|
|
307
|
-
message.error('No accounts found.');
|
|
308
|
-
}
|
|
309
|
-
})
|
|
310
|
-
.catch((result) => {
|
|
311
|
-
console.log(result);
|
|
312
|
-
|
|
313
|
-
setLoading(false);
|
|
314
|
-
|
|
315
|
-
message.error('Login Failed');
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
};
|
|
319
|
-
|
|
320
|
-
/**
|
|
321
|
-
*
|
|
322
|
-
* Function to implement 2 factor authentication on login
|
|
323
|
-
*
|
|
324
|
-
*/
|
|
325
|
-
const sendAuthenticationOtp = () => {
|
|
326
|
-
// Reset previous error
|
|
327
|
-
setModeError(false);
|
|
328
|
-
|
|
329
|
-
// Validate communication mode
|
|
330
|
-
if (!communicationMode) {
|
|
331
|
-
setModeError(true); // Show error
|
|
332
|
-
return; // Stop OTP send
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
setLoading(true);
|
|
336
|
-
|
|
337
|
-
// set formbody
|
|
338
|
-
let formBody;
|
|
339
|
-
formBody = {
|
|
340
|
-
email: user.username,
|
|
341
|
-
mode: communicationMode,
|
|
342
|
-
};
|
|
343
|
-
|
|
344
|
-
// api used to send otp corresponding mail address
|
|
345
|
-
return ApiUtils.post({
|
|
346
|
-
url: 'auth/send-authentication-otp',
|
|
347
|
-
formBody,
|
|
348
|
-
headers,
|
|
349
|
-
}).then((result) => {
|
|
350
|
-
// if the api is sucess then go for otpverification step
|
|
351
|
-
if (result.success) {
|
|
352
|
-
// for expiry_time
|
|
353
|
-
startFromExpiry(result?.expiry_time);
|
|
354
|
-
// set button loading false
|
|
355
|
-
setLoading(false);
|
|
356
|
-
// if the api is sucess then go for otpverification step
|
|
357
|
-
setotpVerification(true);
|
|
358
|
-
} else {
|
|
359
|
-
setLoading(false);
|
|
360
|
-
message.error(result.message);
|
|
361
|
-
}
|
|
362
|
-
});
|
|
363
|
-
};
|
|
364
|
-
|
|
365
|
-
/**
|
|
366
|
-
* Function to implement 2 factor authentication verification
|
|
367
|
-
* @returns
|
|
368
|
-
*/
|
|
369
|
-
|
|
370
|
-
const verifyOtp = () => {
|
|
371
|
-
// If OTP expired, block verification
|
|
372
|
-
if (otpExpired) {
|
|
373
|
-
return;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
setLoading(true);
|
|
377
|
-
|
|
378
|
-
const formBody = {
|
|
379
|
-
username: user.username,
|
|
380
|
-
password: user.password,
|
|
381
|
-
mode: communicationMode,
|
|
382
|
-
mobile: user.mobile,
|
|
383
|
-
otp: otpValue,
|
|
384
|
-
};
|
|
385
|
-
// verifying is otp is correct or not
|
|
386
|
-
return ApiUtils.post({
|
|
387
|
-
url: 'auth/verify-authentication-otp',
|
|
388
|
-
formBody,
|
|
389
|
-
headers,
|
|
390
|
-
hideError: true, // removing unwanted error msg
|
|
391
|
-
})
|
|
392
|
-
.then((result) => {
|
|
393
|
-
if (result.success) {
|
|
394
|
-
// OTP success
|
|
395
|
-
setOtpSuccess(true);
|
|
396
|
-
setOtpError(false);
|
|
397
|
-
setLoading(false);
|
|
398
|
-
|
|
399
|
-
const userInfo = {
|
|
400
|
-
id: result.user.id,
|
|
401
|
-
locations: [],
|
|
402
|
-
...result.user,
|
|
403
|
-
loggedCheckDone: true,
|
|
404
|
-
};
|
|
405
|
-
// Setting access_token
|
|
406
|
-
if (result?.access_token) localStorage.access_token = result.access_token;
|
|
407
|
-
// Setting refresh_token
|
|
408
|
-
if (result.refresh_token) localStorage.setItem('refresh_token', result.refresh_token);
|
|
409
|
-
|
|
410
|
-
// Setting DBPTR
|
|
411
|
-
if (result?.user?.organization_details) {
|
|
412
|
-
const data = safeJSON(result?.user?.organization_details);
|
|
413
|
-
|
|
414
|
-
const defaultBranch = data.branch.find((b) => b.defaultBranch === true);
|
|
415
|
-
const defaultDbptr = defaultBranch?.dbPtr;
|
|
416
|
-
|
|
417
|
-
localStorage.setItem('db_ptr', defaultDbptr);
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
dispatch({ type: 'user', payload: userInfo });
|
|
421
|
-
// set user info into local storage
|
|
422
|
-
localStorage.setItem('userInfo', JSON.stringify(userInfo));
|
|
423
|
-
|
|
424
|
-
handlePasswordExpiryCheck(result.user);
|
|
425
|
-
|
|
426
|
-
setTimeout(() => history.push('/'), 500);
|
|
427
|
-
} else {
|
|
428
|
-
// OTP FAILED (wrong OTP)
|
|
429
|
-
setOtpSuccess(false);
|
|
430
|
-
setOtpError(true);
|
|
431
|
-
setOtpValue(''); // Clear OTP
|
|
432
|
-
setLoading(false);
|
|
433
|
-
}
|
|
434
|
-
})
|
|
435
|
-
.catch((error) => {
|
|
436
|
-
// Server error, timeout, network fail → treat as failed OTP
|
|
437
|
-
setOtpSuccess(false);
|
|
438
|
-
setOtpError(true);
|
|
439
|
-
|
|
440
|
-
setLoading(false);
|
|
441
|
-
});
|
|
442
|
-
};
|
|
443
|
-
|
|
444
|
-
const onFinishFailed = () => {
|
|
445
|
-
setLoading(false);
|
|
446
|
-
|
|
447
|
-
setOtpVisible(false);
|
|
448
|
-
};
|
|
449
|
-
|
|
450
|
-
/**
|
|
451
|
-
* otp onange
|
|
452
|
-
* @param {*} value
|
|
453
|
-
*/
|
|
454
|
-
const handleOtpChange = (value) => {
|
|
455
|
-
setOtpValue(value);
|
|
456
|
-
// Reset states so correct OTP will work after wrong OTP
|
|
457
|
-
setOtpError(false);
|
|
458
|
-
setOtpSuccess(false);
|
|
459
|
-
};
|
|
460
|
-
|
|
461
|
-
/**
|
|
462
|
-
* Otp resend Logic
|
|
463
|
-
*/
|
|
464
|
-
const handleResendOTP = () => {
|
|
465
|
-
setOtpValue('');
|
|
466
|
-
setModeError(false);
|
|
467
|
-
setOtpError(false);
|
|
468
|
-
setOtpSuccess(false);
|
|
469
|
-
// resend the OTP automatically
|
|
470
|
-
sendAuthenticationOtp();
|
|
471
|
-
};
|
|
472
|
-
|
|
473
|
-
/**
|
|
474
|
-
* Cancel otp send process
|
|
475
|
-
*/
|
|
476
|
-
const handlecancel = () => {
|
|
477
|
-
setOtpVisible(false);
|
|
478
|
-
setotpVerification(false);
|
|
479
|
-
setOtpValue('');
|
|
480
|
-
setModeError(false);
|
|
481
|
-
setOtpError(false);
|
|
482
|
-
};
|
|
483
|
-
|
|
484
|
-
// Redirect Home Page, When token is exist
|
|
485
|
-
useEffect(() => {
|
|
486
|
-
// Do NOT redirect when OTP is visible or verification is happening
|
|
487
|
-
if (otpVerification) return;
|
|
488
|
-
if (isAuthenticated && isRefreshTokenExist && path === '/login') {
|
|
489
|
-
Location.navigate({ url: '/' });
|
|
490
|
-
} else {
|
|
491
|
-
Location.navigate({ url: '/login' });
|
|
492
|
-
}
|
|
493
|
-
}, [isAuthenticated, isRefreshTokenExist, path]);
|
|
494
|
-
|
|
495
|
-
useEffect(() => {
|
|
496
|
-
// Dynamically set the CSS variables based on the current theme
|
|
497
|
-
// document.documentElement.style.setProperty('--custom-text-color', state.theme.colors.colorText);
|
|
498
|
-
// document.documentElement.style.setProperty('--custom-bg-color', state.theme.colors.primaryButtonBg);
|
|
499
|
-
// document.documentElement.style.setProperty('--custom-btn-text-color', state.theme.colors.primaryButtonText);
|
|
500
|
-
// document.documentElement.style.setProperty('--custom-input-bg-color', state.theme.colors.inputBgColor);
|
|
501
|
-
// document.documentElement.style.setProperty('--custom-input-color', state.theme.colors.inputColor);
|
|
502
|
-
}, [state.theme]);
|
|
503
|
-
|
|
504
|
-
// when otp is expired
|
|
505
|
-
useEffect(() => {
|
|
506
|
-
if (otpExpired) {
|
|
507
|
-
setOtpValue(''); // Clear OTP box
|
|
508
|
-
setOtpError(false);
|
|
509
|
-
}
|
|
510
|
-
}, [otpExpired]);
|
|
511
|
-
/**
|
|
512
|
-
* Function to get Ldap users
|
|
513
|
-
* @returns
|
|
514
|
-
*/
|
|
515
|
-
|
|
516
|
-
const loggedUser = () => {
|
|
517
|
-
return fetch('http://localhost:3800/users/logged-user', {
|
|
518
|
-
method: 'GET',
|
|
519
|
-
headers: {
|
|
520
|
-
'Content-Type': 'application/json',
|
|
521
|
-
},
|
|
522
|
-
})
|
|
523
|
-
.then((response) => {
|
|
524
|
-
if (!response.ok) {
|
|
525
|
-
throw message.warning('Client application not running');
|
|
526
|
-
}
|
|
527
|
-
return response.json();
|
|
528
|
-
})
|
|
529
|
-
.then((data) => {
|
|
530
|
-
if (data && data.success) {
|
|
531
|
-
return data.username;
|
|
532
|
-
} else {
|
|
533
|
-
message.warning('Client application not running');
|
|
534
|
-
}
|
|
535
|
-
})
|
|
536
|
-
.catch((error) => {
|
|
537
|
-
console.log(error);
|
|
538
|
-
message.warning('Client application not running');
|
|
539
|
-
setLdapLoading(false);
|
|
540
|
-
return null;
|
|
541
|
-
});
|
|
542
|
-
};
|
|
543
|
-
|
|
544
|
-
/**
|
|
545
|
-
*
|
|
546
|
-
* @returns Function to login with ldap
|
|
547
|
-
*
|
|
548
|
-
*/
|
|
549
|
-
const loginWithLdap = async () => {
|
|
550
|
-
//call function to get the current logged username
|
|
551
|
-
const username = await loggedUser();
|
|
552
|
-
|
|
553
|
-
//formbody consist of username from loggeduser
|
|
554
|
-
let formBody = {
|
|
555
|
-
username: username,
|
|
556
|
-
};
|
|
557
|
-
//calling ldap-login API
|
|
558
|
-
return ApiUtils.post({
|
|
559
|
-
// url: "users/logged-user",
|
|
560
|
-
url: 'auth/ldap-login',
|
|
561
|
-
formBody,
|
|
562
|
-
headers,
|
|
563
|
-
})
|
|
564
|
-
.then((result) => {
|
|
565
|
-
setLdapLoading(false);
|
|
566
|
-
|
|
567
|
-
const { user, access_token } = result;
|
|
568
|
-
|
|
569
|
-
localStorage.access_token = access_token;
|
|
570
|
-
|
|
571
|
-
if (result.success) {
|
|
572
|
-
//two_factor_authentication variable is present then proceed Two factor authentication
|
|
573
|
-
if (result.data && result.data.two_factor_authentication) {
|
|
574
|
-
let data;
|
|
575
|
-
|
|
576
|
-
// set variable used for otp send screen
|
|
577
|
-
setOtpVisible(true);
|
|
578
|
-
|
|
579
|
-
// set user credentials
|
|
580
|
-
data = {
|
|
581
|
-
username: result.data.email,
|
|
582
|
-
password: values.password,
|
|
583
|
-
mode: result.data.mode ? result.data.mode : null,
|
|
584
|
-
mobile: result.data.mobile ? result.data.mobile : null,
|
|
585
|
-
};
|
|
586
|
-
|
|
587
|
-
// set user values
|
|
588
|
-
setUser(data);
|
|
589
|
-
} else {
|
|
590
|
-
let d = user;
|
|
591
|
-
|
|
592
|
-
let userInfo = {
|
|
593
|
-
id: user.id,
|
|
594
|
-
locations: [],
|
|
595
|
-
...d,
|
|
596
|
-
...{
|
|
597
|
-
loggedCheckDone: true,
|
|
598
|
-
},
|
|
599
|
-
};
|
|
600
|
-
|
|
601
|
-
dispatch({ type: 'user', payload: userInfo });
|
|
602
|
-
|
|
603
|
-
localStorage.setItem('userInfo', JSON.stringify(userInfo));
|
|
604
|
-
|
|
605
|
-
history.push('/');
|
|
606
|
-
}
|
|
607
|
-
} else {
|
|
608
|
-
message.error(result.message);
|
|
609
|
-
}
|
|
610
|
-
})
|
|
611
|
-
.catch((error) => {
|
|
612
|
-
console.log(error);
|
|
613
|
-
|
|
614
|
-
message.error('This operation has failed.');
|
|
615
|
-
|
|
616
|
-
setLdapLoading(false);
|
|
617
|
-
});
|
|
618
|
-
};
|
|
619
|
-
|
|
620
|
-
// helper to show contact in OTP verification screen
|
|
621
|
-
const getOtpDestinationText = () => {
|
|
622
|
-
if (communicationMode === 'mobile') return formatMobile(user.mobile);
|
|
623
|
-
// if (communicationMode === 'whatsapp') return user.mobile;
|
|
624
|
-
return user.username;
|
|
625
|
-
};
|
|
626
|
-
|
|
627
|
-
const { globalCustomerHeader = () => {} } = appSettings;
|
|
628
|
-
|
|
629
|
-
const themeName = process.env.REACT_APP_THEME; // e.g., 'purple'
|
|
630
|
-
const isPurple = themeName === 'purple';
|
|
631
|
-
|
|
632
|
-
const sectionStyle = isPurple
|
|
633
|
-
? {
|
|
634
|
-
width: '100%',
|
|
635
|
-
height: '100vh',
|
|
636
|
-
backgroundImage: `${state.theme.colors.loginPageBackground}`,
|
|
637
|
-
backgroundPosition: 'center bottom, center',
|
|
638
|
-
backgroundRepeat: 'no-repeat, no-repeat',
|
|
639
|
-
backgroundSize: 'cover, cover',
|
|
640
|
-
}
|
|
641
|
-
: {
|
|
642
|
-
width: '100%',
|
|
643
|
-
height: '100vh',
|
|
644
|
-
background: 'linear-gradient(to bottom, #F7F6E3 0%, #EEF1DE 20%, #D5E4DA 45%, #9DBFC8 75%, #4F89A6 100%)',
|
|
645
|
-
backgroundPosition: 'center bottom, center',
|
|
646
|
-
backgroundRepeat: 'no-repeat, no-repeat',
|
|
647
|
-
backgroundSize: 'cover, cover',
|
|
648
|
-
};
|
|
649
|
-
|
|
650
|
-
return (
|
|
651
|
-
<section className="full-page" style={sectionStyle}>
|
|
652
|
-
<section className="user-authentication-section">
|
|
653
|
-
{/* Background Section */}
|
|
654
|
-
<motion.div
|
|
655
|
-
className="page-background"
|
|
656
|
-
initial={{ y: -50, opacity: 0 }}
|
|
657
|
-
animate={{ y: 0, opacity: 1 }}
|
|
658
|
-
transition={{ duration: 1, ease: 'anticipate' }}
|
|
659
|
-
exit={{ opacity: 0 }}
|
|
660
|
-
/>
|
|
661
|
-
{/* Background Section Ends */}
|
|
662
|
-
|
|
663
|
-
<motion.div
|
|
664
|
-
className="auth-form-wrapper"
|
|
665
|
-
initial={{ y: 20 }}
|
|
666
|
-
animate={{ y: 0 }}
|
|
667
|
-
transition={{ duration: 1, ease: 'anticipate' }}
|
|
668
|
-
exit={{ opacity: 0 }}
|
|
669
|
-
>
|
|
670
|
-
<div
|
|
671
|
-
className=" login-form-container"
|
|
672
|
-
style={{
|
|
673
|
-
background: state.theme.colors.tableBg,
|
|
674
|
-
borderStyle: state.theme.colors.tableBorderStyle,
|
|
675
|
-
}}
|
|
676
|
-
>
|
|
677
|
-
<div className="brand-logo">
|
|
678
|
-
<img className="logo-welcome" src={brandLogo} alt="Logo" />
|
|
679
|
-
</div>
|
|
680
|
-
|
|
681
|
-
<div className="otp-form">
|
|
682
|
-
{/* OTP Verification Section */}
|
|
683
|
-
|
|
684
|
-
{/* OTP Method Selection Section */}
|
|
685
|
-
{otpVisible && (
|
|
686
|
-
<div className="otp-input-container">
|
|
687
|
-
<div className="form-title">
|
|
688
|
-
{otpVerification ? (
|
|
689
|
-
<>
|
|
690
|
-
{/* <h3>OTP Verification</h3> */}
|
|
691
|
-
{/* <p>
|
|
692
|
-
Enter the verification code we sent to{' '}
|
|
693
|
-
<span className="otp-mode-text">
|
|
694
|
-
<strong>{getOtpDestinationText()}</strong>
|
|
695
|
-
</span>
|
|
696
|
-
</p> */}
|
|
697
|
-
</>
|
|
698
|
-
) : (
|
|
699
|
-
<>
|
|
700
|
-
<Text type="primary">Two Factor Authentication</Text>
|
|
701
|
-
<p>
|
|
702
|
-
Two-Factor Authentication is enabled for your account. Please verify your account before logging in to enhance security.
|
|
703
|
-
</p>
|
|
704
|
-
|
|
705
|
-
</>
|
|
706
|
-
)}
|
|
707
|
-
</div>
|
|
708
|
-
|
|
709
|
-
{/* Show Communication Method ONLY IF:
|
|
710
|
-
- OTP not sent OR
|
|
711
|
-
- OTP expired
|
|
712
|
-
*/}
|
|
713
|
-
|
|
714
|
-
{(!otpVerification || otpExpired) && (
|
|
715
|
-
<>
|
|
716
|
-
<Divider />
|
|
717
|
-
<div className="otp-method-section">
|
|
718
|
-
<Text type="primary">Select Preferred OTP Verification Method</Text>
|
|
719
|
-
<div className="otp-method-group">
|
|
720
|
-
<Radio checked={communicationMode === 'email'} onChange={() => setCommunicationMode('email')}>
|
|
721
|
-
Email <MailOutlined className="otp-icon" style={{ marginLeft: 6 }} />
|
|
722
|
-
</Radio>
|
|
723
|
-
<Radio checked={communicationMode === 'mobile'} onChange={() => setCommunicationMode('mobile')}>
|
|
724
|
-
SMS <MessageOutlined className="otp-icon" style={{ marginLeft: 6 }} />
|
|
725
|
-
</Radio>
|
|
726
|
-
</div>
|
|
727
|
-
{modeError && <p className="otp-mode-error">Please select a communication mode.</p>}
|
|
728
|
-
</div>
|
|
729
|
-
</>
|
|
730
|
-
)}
|
|
731
|
-
|
|
732
|
-
{!otpVerification ? (
|
|
733
|
-
<div className="otp-container">
|
|
734
|
-
<Button type="primary" onClick={sendAuthenticationOtp} style={{ marginTop: '6px' }}>
|
|
735
|
-
Send OTP
|
|
736
|
-
</Button>
|
|
737
|
-
</div>
|
|
738
|
-
) : (
|
|
739
|
-
<>
|
|
740
|
-
{/* <Divider /> */}
|
|
741
|
-
<div className="otp-container">
|
|
742
|
-
<p>
|
|
743
|
-
Enter the verification code we sent to{' '}
|
|
744
|
-
<span className="otp-mode-text">
|
|
745
|
-
<strong>{getOtpDestinationText()}</strong>
|
|
746
|
-
</span>
|
|
747
|
-
</p>
|
|
748
|
-
<OTPInput
|
|
749
|
-
value={otpValue}
|
|
750
|
-
onChange={handleOtpChange}
|
|
751
|
-
autoFocus
|
|
752
|
-
OTPLength={6}
|
|
753
|
-
disabled={loading || otpExpired}
|
|
754
|
-
inputStyles={{
|
|
755
|
-
border: otpSuccess
|
|
756
|
-
? '2px solid #52c41a' // green
|
|
757
|
-
: otpError
|
|
758
|
-
? '2px solid #FF5C5C' // red
|
|
759
|
-
: '1px solid #d9d9d9', // default
|
|
760
|
-
borderRadius: 4,
|
|
761
|
-
width: isMobile ? 28 : 45, // MOBILE FIX
|
|
762
|
-
height: isMobile ? 36 : 40, // MOBILE FIX
|
|
763
|
-
margin: isMobile ? '2px' : '0 4px',
|
|
764
|
-
fontSize: isMobile ? 16 : 18,
|
|
765
|
-
textAlign: 'center',
|
|
766
|
-
}}
|
|
767
|
-
/>
|
|
768
|
-
{/* Timer below OTP */}
|
|
769
|
-
<div className="otp-timer">
|
|
770
|
-
{/* {!otpExpired ? */}
|
|
771
|
-
{otpSuccess ? null : <span>{formatted}</span>}
|
|
772
|
-
{/* {otpError && (
|
|
773
|
-
<p style={{ color: 'red', marginTop: 8 }}>Invalid OTP, please try again</p>
|
|
774
|
-
)} */}
|
|
775
|
-
|
|
776
|
-
{otpSuccess && <p style={{ color: 'green', marginTop: 8 }}>Your OTP has been verified successfully.</p>}
|
|
777
|
-
</div>
|
|
778
|
-
</div>
|
|
779
|
-
{!otpSuccess && (
|
|
780
|
-
<Button type="primary" disabled={otpExpired} onClick={verifyOtp} style={{ marginTop: 16 }}>
|
|
781
|
-
Verify OTP
|
|
782
|
-
</Button>
|
|
783
|
-
)}
|
|
784
|
-
</>
|
|
785
|
-
)}
|
|
786
|
-
</div>
|
|
787
|
-
)}
|
|
788
|
-
|
|
789
|
-
{/* Login Form Section */}
|
|
790
|
-
{!otpVerification && !otpVisible && !showResetpassword && (
|
|
791
|
-
<Form {...layout} layout="vertical" name="basic" onFinish={onFinish} onFinishFailed={onFinishFailed}>
|
|
792
|
-
<div className="form-title">
|
|
793
|
-
<h4></h4>
|
|
794
|
-
</div>
|
|
795
|
-
|
|
796
|
-
{/* {!process.env.REACT_APP_SHOW_BRANCH_SWITCHER && <div className="branch-switcher">{globalCustomerHeader()}</div>} */}
|
|
797
|
-
|
|
798
|
-
{process.env.REACT_APP_ENABLE_LDAP === 'true' && (
|
|
799
|
-
<Button loading={ldaploading} type="secondary" className="SubmitBtn" onClick={loginWithLdap}>
|
|
800
|
-
Sign in using AD
|
|
801
|
-
</Button>
|
|
802
|
-
)}
|
|
803
|
-
|
|
804
|
-
<Form.Item label="Email" name="email" rules={[{ required: true, message: 'Please input your email!' }]}>
|
|
805
|
-
<Input autoComplete="off" autoFocus />
|
|
806
|
-
</Form.Item>
|
|
807
|
-
|
|
808
|
-
<Form.Item label="Password" name="password" rules={[{ required: true, message: 'Please input your password!' }]}>
|
|
809
|
-
<Input.Password autoComplete="off" />
|
|
810
|
-
</Form.Item>
|
|
811
|
-
|
|
812
|
-
<Form.Item {...tailLayout} style={{ marginBottom: '0px' }}>
|
|
813
|
-
<Button loading={loading} type="primary" htmlType="submit" className="SubmitBtn">
|
|
814
|
-
Submit
|
|
815
|
-
</Button>
|
|
816
|
-
<div className="forgot-password" style={{ marginTop: '8px', textAlign: 'center' }}>
|
|
817
|
-
<Link onClick={() => setShowResetpassword(true)}>Forgot Password?</Link>
|
|
818
|
-
</div>
|
|
819
|
-
</Form.Item>
|
|
820
|
-
</Form>
|
|
821
|
-
)}
|
|
822
|
-
|
|
823
|
-
{/* Forgot Password Section */}
|
|
824
|
-
{showResetpassword && (
|
|
825
|
-
<ResetPassword
|
|
826
|
-
defaultUsername={expiredPassword ? defaultUsername : undefined}
|
|
827
|
-
disabledUserName={expiredPassword}
|
|
828
|
-
onBack={() => {
|
|
829
|
-
setShowResetpassword(false);
|
|
830
|
-
setExpiredPassword(false);
|
|
831
|
-
}}
|
|
832
|
-
title={expiredPassword ? 'Password Expired!' : 'Forgot Password?'}
|
|
833
|
-
// subtitle={
|
|
834
|
-
// expiredPassword
|
|
835
|
-
// ? 'Your password has expired. Select a preferred communication method to receive the One-Time Password (OTP) to continue.'
|
|
836
|
-
// : 'Enter your username and Select a preferred communication method to receive the One-Time Password (OTP) to continue..'
|
|
837
|
-
// }
|
|
838
|
-
buttonText={expiredPassword ? 'Send Reset Link' : 'Reset Password'}
|
|
839
|
-
/>
|
|
840
|
-
)}
|
|
841
|
-
</div>
|
|
842
|
-
</div>
|
|
843
|
-
{!otpSuccess && otpVerification && (
|
|
844
|
-
<div className="otp-actions">
|
|
845
|
-
<div className="resend-action">
|
|
846
|
-
<Text disabled>Didn't receive OTP?</Text>
|
|
847
|
-
|
|
848
|
-
<Link className="resend-otp-link" disabled={!otpExpired} onClick={handleResendOTP}>
|
|
849
|
-
Resend OTP
|
|
850
|
-
</Link>
|
|
851
|
-
</div>
|
|
852
|
-
|
|
853
|
-
<Button size="small" type="default" onClick={handlecancel}>
|
|
854
|
-
Cancel
|
|
855
|
-
</Button>
|
|
856
|
-
</div>
|
|
857
|
-
)}
|
|
858
|
-
</motion.div>
|
|
859
|
-
</section>
|
|
860
|
-
</section>
|
|
861
|
-
);
|
|
862
|
-
}
|
|
863
|
-
|
|
864
|
-
export default withRouter(LoginPhone);
|
|
1
|
+
import React, { useState, useContext, useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
import { Form, Input, message, Result, Radio, Divider, Typography } from 'antd';
|
|
4
|
+
|
|
5
|
+
import { withRouter, Link } from 'react-router-dom';
|
|
6
|
+
|
|
7
|
+
import backgroundImage from './../../../assets/images/vector.png';
|
|
8
|
+
|
|
9
|
+
import OTPInput from 'otp-input-react';
|
|
10
|
+
|
|
11
|
+
import { useOtpTimer } from '../../hooks/use-otp-timer';
|
|
12
|
+
|
|
13
|
+
import { motion } from 'framer-motion';
|
|
14
|
+
|
|
15
|
+
import { Button } from '../../elements';
|
|
16
|
+
|
|
17
|
+
import './login.scss';
|
|
18
|
+
|
|
19
|
+
// import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
20
|
+
|
|
21
|
+
// import { faCheck } from "@fortawesome/free-solid-svg-icons";
|
|
22
|
+
|
|
23
|
+
import FirebaseUtils from '../../../lib/utils/firebase.utils';
|
|
24
|
+
|
|
25
|
+
import ApiUtils from '../../utils/api/api.utils';
|
|
26
|
+
|
|
27
|
+
import { GlobalContext } from './../../Store';
|
|
28
|
+
|
|
29
|
+
import { getAccessToken, getRefreshToken } from '../../utils/http/auth.helper';
|
|
30
|
+
|
|
31
|
+
import { Location } from '../../utils';
|
|
32
|
+
|
|
33
|
+
import { checkLicenseStatus, formatMobile, checkExpiryStatus, safeJSON } from '../../utils/common/common.utils';
|
|
34
|
+
|
|
35
|
+
import { MailOutlined, MessageOutlined, WhatsAppOutlined } from '@ant-design/icons';
|
|
36
|
+
|
|
37
|
+
import ResetPassword from './reset-password';
|
|
38
|
+
|
|
39
|
+
const { Text, Title } = Typography;
|
|
40
|
+
|
|
41
|
+
const layout = {
|
|
42
|
+
labelCol: { span: 24 },
|
|
43
|
+
|
|
44
|
+
wrapperCol: { span: 24 },
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const tailLayout = {
|
|
48
|
+
wrapperCol: { span: 8 },
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const LICENSE_EXPIRY = '2026-12-12';
|
|
52
|
+
|
|
53
|
+
//password valdity expire
|
|
54
|
+
const PASSWORD_VALIDITY_DAYS = 90;
|
|
55
|
+
|
|
56
|
+
const headers = {
|
|
57
|
+
db_ptr: 'nuraho',
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
*
|
|
62
|
+
* @param {*} param0
|
|
63
|
+
* @returns
|
|
64
|
+
*/
|
|
65
|
+
function LoginPhone({ history, appSettings }) {
|
|
66
|
+
const { brandLogo, heroImage, footerLogo } = appSettings;
|
|
67
|
+
|
|
68
|
+
// Hook for OTP Timer
|
|
69
|
+
const { expired: otpExpired, formatted, startFromExpiry } = useOtpTimer();
|
|
70
|
+
|
|
71
|
+
const { dispatch, state, isMobile } = useContext(GlobalContext);
|
|
72
|
+
// variabel used for btnloading
|
|
73
|
+
|
|
74
|
+
const [loading, setLoading] = useState(false);
|
|
75
|
+
|
|
76
|
+
const [ldaploading, setLdapLoading] = useState(false);
|
|
77
|
+
|
|
78
|
+
// variable used to show otp generating
|
|
79
|
+
|
|
80
|
+
const [otpVisible, setOtpVisible] = useState(false);
|
|
81
|
+
// variabale used to show otp entering screen
|
|
82
|
+
|
|
83
|
+
const [otpVerification, setotpVerification] = useState(false);
|
|
84
|
+
// otp sucess
|
|
85
|
+
const [otpSuccess, setOtpSuccess] = useState(false);
|
|
86
|
+
// otp fail err
|
|
87
|
+
const [otpError, setOtpError] = useState(false);
|
|
88
|
+
|
|
89
|
+
const [otpValue, setOtpValue] = useState('');
|
|
90
|
+
// setting user credentials
|
|
91
|
+
const [user, setUser] = useState([]);
|
|
92
|
+
|
|
93
|
+
// for communication mode [mobile,sms,email]
|
|
94
|
+
const [communicationMode, setCommunicationMode] = useState(null); // default selected email
|
|
95
|
+
const [modeError, setModeError] = useState(false);
|
|
96
|
+
|
|
97
|
+
//for forgot password show
|
|
98
|
+
const [showResetpassword, setShowResetpassword] = useState(false);
|
|
99
|
+
|
|
100
|
+
//for expired password show
|
|
101
|
+
const [expiredPassword, setExpiredPassword] = useState(false);
|
|
102
|
+
|
|
103
|
+
//for default name select when expire case
|
|
104
|
+
const [defaultUsername, setDefaultUsername] = useState('');
|
|
105
|
+
|
|
106
|
+
const isAuthenticated = Boolean(getAccessToken());
|
|
107
|
+
const isRefreshTokenExist = Boolean(getRefreshToken());
|
|
108
|
+
|
|
109
|
+
const path = window.location.pathname;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* handlePasswordExpiryCheck
|
|
113
|
+
* --------------------------
|
|
114
|
+
* Validates whether a user's password is expired or nearing expiry.
|
|
115
|
+
*
|
|
116
|
+
* - Parses `last_password_change` from user.other_details.
|
|
117
|
+
* - Calculates expiry using PASSWORD_VALIDITY_DAYS.
|
|
118
|
+
* - Uses `checkExpiryStatus()` to determine status.
|
|
119
|
+
* - Shows Ant Design warning message if expired or within warning period.
|
|
120
|
+
* - Warning message includes navigation to `/change-password`.
|
|
121
|
+
*
|
|
122
|
+
* Requires:
|
|
123
|
+
* - PASSWORD_VALIDITY_DAYS constant
|
|
124
|
+
* - checkExpiryStatus utility
|
|
125
|
+
* - React Router history
|
|
126
|
+
* - antd message component
|
|
127
|
+
*/
|
|
128
|
+
const handlePasswordExpiryCheck = (user) => {
|
|
129
|
+
const otherDetails = user?.other_details ? JSON.parse(user.other_details) : null;
|
|
130
|
+
|
|
131
|
+
const lastPasswordChange = otherDetails?.last_password_change;
|
|
132
|
+
|
|
133
|
+
if (lastPasswordChange) {
|
|
134
|
+
const onlyDate = new Date(lastPasswordChange).toISOString().split('T')[0];
|
|
135
|
+
const passwordExpiryDate = new Date(onlyDate);
|
|
136
|
+
passwordExpiryDate.setDate(passwordExpiryDate.getDate() + PASSWORD_VALIDITY_DAYS);
|
|
137
|
+
|
|
138
|
+
const passwordStatus = checkExpiryStatus({
|
|
139
|
+
expiryDate: passwordExpiryDate,
|
|
140
|
+
warningDays: 2,
|
|
141
|
+
expiredMessage: 'Your password has expired. Please reset it.',
|
|
142
|
+
warningMessage: (d) => (
|
|
143
|
+
<span>
|
|
144
|
+
Your password will expire in {d} day(s).{' '}
|
|
145
|
+
<a
|
|
146
|
+
onClick={() => {
|
|
147
|
+
history.push('/change-password');
|
|
148
|
+
}}
|
|
149
|
+
>
|
|
150
|
+
Click here to update.
|
|
151
|
+
</a>
|
|
152
|
+
</span>
|
|
153
|
+
),
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
if (passwordStatus.message) {
|
|
157
|
+
message.warning(passwordStatus.message);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const onFinish = (values) => {
|
|
163
|
+
setLoading(true);
|
|
164
|
+
|
|
165
|
+
const status = checkLicenseStatus(LICENSE_EXPIRY);
|
|
166
|
+
|
|
167
|
+
if (!status.valid) {
|
|
168
|
+
message.error(status.message);
|
|
169
|
+
setLoading(false);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (status.message) {
|
|
174
|
+
if (status.level === 'error') {
|
|
175
|
+
message.error(status.message);
|
|
176
|
+
} else if (status.level === 'warning') {
|
|
177
|
+
message.warning(status.message);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (process.env.REACT_APP_PRIMARY_BACKEND === 'SQL') {
|
|
182
|
+
let formBody = {
|
|
183
|
+
username: values.email,
|
|
184
|
+
|
|
185
|
+
password: values.password,
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
return ApiUtils.post({ url: 'auth/login', formBody, headers })
|
|
189
|
+
|
|
190
|
+
.then((result) => {
|
|
191
|
+
setLoading(false);
|
|
192
|
+
|
|
193
|
+
const { user, access_token, refresh_token, insider_token } = result;
|
|
194
|
+
if (access_token) localStorage.access_token = access_token;
|
|
195
|
+
|
|
196
|
+
if (insider_token) localStorage.insider_token = insider_token;
|
|
197
|
+
|
|
198
|
+
if (result.success) {
|
|
199
|
+
handlePasswordExpiryCheck(user);
|
|
200
|
+
|
|
201
|
+
//two_factor_authentication variable is present then proceed Two factor authentication
|
|
202
|
+
if (result.data && result.data.two_factor_authentication) {
|
|
203
|
+
let data;
|
|
204
|
+
|
|
205
|
+
// set variable used for otp send screen
|
|
206
|
+
setOtpVisible(true);
|
|
207
|
+
|
|
208
|
+
// set user credentials
|
|
209
|
+
data = {
|
|
210
|
+
username: result.data.email,
|
|
211
|
+
password: values.password,
|
|
212
|
+
mode: result.data.mode ? result.data.mode : null,
|
|
213
|
+
mobile: result.data.mobile ? result.data.mobile : null,
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
// set user values
|
|
217
|
+
setUser(data);
|
|
218
|
+
// Set default communication mode automatically
|
|
219
|
+
if (result.data.mode) {
|
|
220
|
+
setCommunicationMode(result.data.mode);
|
|
221
|
+
}
|
|
222
|
+
} else {
|
|
223
|
+
let d = user;
|
|
224
|
+
|
|
225
|
+
let userInfo = {
|
|
226
|
+
id: user.id,
|
|
227
|
+
locations: [],
|
|
228
|
+
...d,
|
|
229
|
+
...{
|
|
230
|
+
loggedCheckDone: true,
|
|
231
|
+
},
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
dispatch({ type: 'user', payload: userInfo });
|
|
235
|
+
|
|
236
|
+
localStorage.setItem('userInfo', JSON.stringify(userInfo));
|
|
237
|
+
if (refresh_token) localStorage.setItem('refresh_token', refresh_token);
|
|
238
|
+
|
|
239
|
+
// Setting DBPTR
|
|
240
|
+
if (user?.organization_details) {
|
|
241
|
+
const data = safeJSON(user?.organization_details);
|
|
242
|
+
|
|
243
|
+
const defaultBranch = data.branch.find((b) => b.defaultBranch === true);
|
|
244
|
+
|
|
245
|
+
const defaultDbptr = defaultBranch?.dbPtr;
|
|
246
|
+
|
|
247
|
+
localStorage.setItem('db_ptr', defaultDbptr);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
history.push('/');
|
|
251
|
+
}
|
|
252
|
+
} else {
|
|
253
|
+
if (result.passwordChange) {
|
|
254
|
+
message.warning(result.message);
|
|
255
|
+
|
|
256
|
+
//time for redirect when expire
|
|
257
|
+
setTimeout(() => {
|
|
258
|
+
setExpiredPassword(true);
|
|
259
|
+
setDefaultUsername(values.email);
|
|
260
|
+
|
|
261
|
+
setShowResetpassword(true);
|
|
262
|
+
}, 1500);
|
|
263
|
+
} else {
|
|
264
|
+
message.warning(result.message);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
})
|
|
268
|
+
.catch((error) => {
|
|
269
|
+
console.log(error);
|
|
270
|
+
|
|
271
|
+
message.error('This operation has failed.');
|
|
272
|
+
|
|
273
|
+
setLoading(false);
|
|
274
|
+
});
|
|
275
|
+
} else {
|
|
276
|
+
FirebaseUtils.loginWithEmail(values)
|
|
277
|
+
|
|
278
|
+
.then((result) => {
|
|
279
|
+
setLoading(false);
|
|
280
|
+
|
|
281
|
+
if (result.id) {
|
|
282
|
+
if (result.active) {
|
|
283
|
+
let d = result;
|
|
284
|
+
|
|
285
|
+
let userInfo = {
|
|
286
|
+
id: result.id,
|
|
287
|
+
locations: [],
|
|
288
|
+
...d,
|
|
289
|
+
...{
|
|
290
|
+
loggedCheckDone: true,
|
|
291
|
+
},
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
if (result.role && result.role.name === 'admin') {
|
|
295
|
+
userInfo.isAdmin = true;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
dispatch({ type: 'user', payload: userInfo });
|
|
299
|
+
|
|
300
|
+
localStorage.setItem('userInfo', JSON.stringify(userInfo));
|
|
301
|
+
|
|
302
|
+
history.push('/');
|
|
303
|
+
} else {
|
|
304
|
+
message.error('Your account is inactive, Please contact support.');
|
|
305
|
+
}
|
|
306
|
+
} else {
|
|
307
|
+
message.error('No accounts found.');
|
|
308
|
+
}
|
|
309
|
+
})
|
|
310
|
+
.catch((result) => {
|
|
311
|
+
console.log(result);
|
|
312
|
+
|
|
313
|
+
setLoading(false);
|
|
314
|
+
|
|
315
|
+
message.error('Login Failed');
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
*
|
|
322
|
+
* Function to implement 2 factor authentication on login
|
|
323
|
+
*
|
|
324
|
+
*/
|
|
325
|
+
const sendAuthenticationOtp = () => {
|
|
326
|
+
// Reset previous error
|
|
327
|
+
setModeError(false);
|
|
328
|
+
|
|
329
|
+
// Validate communication mode
|
|
330
|
+
if (!communicationMode) {
|
|
331
|
+
setModeError(true); // Show error
|
|
332
|
+
return; // Stop OTP send
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
setLoading(true);
|
|
336
|
+
|
|
337
|
+
// set formbody
|
|
338
|
+
let formBody;
|
|
339
|
+
formBody = {
|
|
340
|
+
email: user.username,
|
|
341
|
+
mode: communicationMode,
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
// api used to send otp corresponding mail address
|
|
345
|
+
return ApiUtils.post({
|
|
346
|
+
url: 'auth/send-authentication-otp',
|
|
347
|
+
formBody,
|
|
348
|
+
headers,
|
|
349
|
+
}).then((result) => {
|
|
350
|
+
// if the api is sucess then go for otpverification step
|
|
351
|
+
if (result.success) {
|
|
352
|
+
// for expiry_time
|
|
353
|
+
startFromExpiry(result?.expiry_time);
|
|
354
|
+
// set button loading false
|
|
355
|
+
setLoading(false);
|
|
356
|
+
// if the api is sucess then go for otpverification step
|
|
357
|
+
setotpVerification(true);
|
|
358
|
+
} else {
|
|
359
|
+
setLoading(false);
|
|
360
|
+
message.error(result.message);
|
|
361
|
+
}
|
|
362
|
+
});
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Function to implement 2 factor authentication verification
|
|
367
|
+
* @returns
|
|
368
|
+
*/
|
|
369
|
+
|
|
370
|
+
const verifyOtp = () => {
|
|
371
|
+
// If OTP expired, block verification
|
|
372
|
+
if (otpExpired) {
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
setLoading(true);
|
|
377
|
+
|
|
378
|
+
const formBody = {
|
|
379
|
+
username: user.username,
|
|
380
|
+
password: user.password,
|
|
381
|
+
mode: communicationMode,
|
|
382
|
+
mobile: user.mobile,
|
|
383
|
+
otp: otpValue,
|
|
384
|
+
};
|
|
385
|
+
// verifying is otp is correct or not
|
|
386
|
+
return ApiUtils.post({
|
|
387
|
+
url: 'auth/verify-authentication-otp',
|
|
388
|
+
formBody,
|
|
389
|
+
headers,
|
|
390
|
+
hideError: true, // removing unwanted error msg
|
|
391
|
+
})
|
|
392
|
+
.then((result) => {
|
|
393
|
+
if (result.success) {
|
|
394
|
+
// OTP success
|
|
395
|
+
setOtpSuccess(true);
|
|
396
|
+
setOtpError(false);
|
|
397
|
+
setLoading(false);
|
|
398
|
+
|
|
399
|
+
const userInfo = {
|
|
400
|
+
id: result.user.id,
|
|
401
|
+
locations: [],
|
|
402
|
+
...result.user,
|
|
403
|
+
loggedCheckDone: true,
|
|
404
|
+
};
|
|
405
|
+
// Setting access_token
|
|
406
|
+
if (result?.access_token) localStorage.access_token = result.access_token;
|
|
407
|
+
// Setting refresh_token
|
|
408
|
+
if (result.refresh_token) localStorage.setItem('refresh_token', result.refresh_token);
|
|
409
|
+
|
|
410
|
+
// Setting DBPTR
|
|
411
|
+
if (result?.user?.organization_details) {
|
|
412
|
+
const data = safeJSON(result?.user?.organization_details);
|
|
413
|
+
|
|
414
|
+
const defaultBranch = data.branch.find((b) => b.defaultBranch === true);
|
|
415
|
+
const defaultDbptr = defaultBranch?.dbPtr;
|
|
416
|
+
|
|
417
|
+
localStorage.setItem('db_ptr', defaultDbptr);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
dispatch({ type: 'user', payload: userInfo });
|
|
421
|
+
// set user info into local storage
|
|
422
|
+
localStorage.setItem('userInfo', JSON.stringify(userInfo));
|
|
423
|
+
|
|
424
|
+
handlePasswordExpiryCheck(result.user);
|
|
425
|
+
|
|
426
|
+
setTimeout(() => history.push('/'), 500);
|
|
427
|
+
} else {
|
|
428
|
+
// OTP FAILED (wrong OTP)
|
|
429
|
+
setOtpSuccess(false);
|
|
430
|
+
setOtpError(true);
|
|
431
|
+
setOtpValue(''); // Clear OTP
|
|
432
|
+
setLoading(false);
|
|
433
|
+
}
|
|
434
|
+
})
|
|
435
|
+
.catch((error) => {
|
|
436
|
+
// Server error, timeout, network fail → treat as failed OTP
|
|
437
|
+
setOtpSuccess(false);
|
|
438
|
+
setOtpError(true);
|
|
439
|
+
|
|
440
|
+
setLoading(false);
|
|
441
|
+
});
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
const onFinishFailed = () => {
|
|
445
|
+
setLoading(false);
|
|
446
|
+
|
|
447
|
+
setOtpVisible(false);
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* otp onange
|
|
452
|
+
* @param {*} value
|
|
453
|
+
*/
|
|
454
|
+
const handleOtpChange = (value) => {
|
|
455
|
+
setOtpValue(value);
|
|
456
|
+
// Reset states so correct OTP will work after wrong OTP
|
|
457
|
+
setOtpError(false);
|
|
458
|
+
setOtpSuccess(false);
|
|
459
|
+
};
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Otp resend Logic
|
|
463
|
+
*/
|
|
464
|
+
const handleResendOTP = () => {
|
|
465
|
+
setOtpValue('');
|
|
466
|
+
setModeError(false);
|
|
467
|
+
setOtpError(false);
|
|
468
|
+
setOtpSuccess(false);
|
|
469
|
+
// resend the OTP automatically
|
|
470
|
+
sendAuthenticationOtp();
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Cancel otp send process
|
|
475
|
+
*/
|
|
476
|
+
const handlecancel = () => {
|
|
477
|
+
setOtpVisible(false);
|
|
478
|
+
setotpVerification(false);
|
|
479
|
+
setOtpValue('');
|
|
480
|
+
setModeError(false);
|
|
481
|
+
setOtpError(false);
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
// Redirect Home Page, When token is exist
|
|
485
|
+
useEffect(() => {
|
|
486
|
+
// Do NOT redirect when OTP is visible or verification is happening
|
|
487
|
+
if (otpVerification) return;
|
|
488
|
+
if (isAuthenticated && isRefreshTokenExist && path === '/login') {
|
|
489
|
+
Location.navigate({ url: '/' });
|
|
490
|
+
} else {
|
|
491
|
+
Location.navigate({ url: '/login' });
|
|
492
|
+
}
|
|
493
|
+
}, [isAuthenticated, isRefreshTokenExist, path]);
|
|
494
|
+
|
|
495
|
+
useEffect(() => {
|
|
496
|
+
// Dynamically set the CSS variables based on the current theme
|
|
497
|
+
// document.documentElement.style.setProperty('--custom-text-color', state.theme.colors.colorText);
|
|
498
|
+
// document.documentElement.style.setProperty('--custom-bg-color', state.theme.colors.primaryButtonBg);
|
|
499
|
+
// document.documentElement.style.setProperty('--custom-btn-text-color', state.theme.colors.primaryButtonText);
|
|
500
|
+
// document.documentElement.style.setProperty('--custom-input-bg-color', state.theme.colors.inputBgColor);
|
|
501
|
+
// document.documentElement.style.setProperty('--custom-input-color', state.theme.colors.inputColor);
|
|
502
|
+
}, [state.theme]);
|
|
503
|
+
|
|
504
|
+
// when otp is expired
|
|
505
|
+
useEffect(() => {
|
|
506
|
+
if (otpExpired) {
|
|
507
|
+
setOtpValue(''); // Clear OTP box
|
|
508
|
+
setOtpError(false);
|
|
509
|
+
}
|
|
510
|
+
}, [otpExpired]);
|
|
511
|
+
/**
|
|
512
|
+
* Function to get Ldap users
|
|
513
|
+
* @returns
|
|
514
|
+
*/
|
|
515
|
+
|
|
516
|
+
const loggedUser = () => {
|
|
517
|
+
return fetch('http://localhost:3800/users/logged-user', {
|
|
518
|
+
method: 'GET',
|
|
519
|
+
headers: {
|
|
520
|
+
'Content-Type': 'application/json',
|
|
521
|
+
},
|
|
522
|
+
})
|
|
523
|
+
.then((response) => {
|
|
524
|
+
if (!response.ok) {
|
|
525
|
+
throw message.warning('Client application not running');
|
|
526
|
+
}
|
|
527
|
+
return response.json();
|
|
528
|
+
})
|
|
529
|
+
.then((data) => {
|
|
530
|
+
if (data && data.success) {
|
|
531
|
+
return data.username;
|
|
532
|
+
} else {
|
|
533
|
+
message.warning('Client application not running');
|
|
534
|
+
}
|
|
535
|
+
})
|
|
536
|
+
.catch((error) => {
|
|
537
|
+
console.log(error);
|
|
538
|
+
message.warning('Client application not running');
|
|
539
|
+
setLdapLoading(false);
|
|
540
|
+
return null;
|
|
541
|
+
});
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
*
|
|
546
|
+
* @returns Function to login with ldap
|
|
547
|
+
*
|
|
548
|
+
*/
|
|
549
|
+
const loginWithLdap = async () => {
|
|
550
|
+
//call function to get the current logged username
|
|
551
|
+
const username = await loggedUser();
|
|
552
|
+
|
|
553
|
+
//formbody consist of username from loggeduser
|
|
554
|
+
let formBody = {
|
|
555
|
+
username: username,
|
|
556
|
+
};
|
|
557
|
+
//calling ldap-login API
|
|
558
|
+
return ApiUtils.post({
|
|
559
|
+
// url: "users/logged-user",
|
|
560
|
+
url: 'auth/ldap-login',
|
|
561
|
+
formBody,
|
|
562
|
+
headers,
|
|
563
|
+
})
|
|
564
|
+
.then((result) => {
|
|
565
|
+
setLdapLoading(false);
|
|
566
|
+
|
|
567
|
+
const { user, access_token } = result;
|
|
568
|
+
|
|
569
|
+
localStorage.access_token = access_token;
|
|
570
|
+
|
|
571
|
+
if (result.success) {
|
|
572
|
+
//two_factor_authentication variable is present then proceed Two factor authentication
|
|
573
|
+
if (result.data && result.data.two_factor_authentication) {
|
|
574
|
+
let data;
|
|
575
|
+
|
|
576
|
+
// set variable used for otp send screen
|
|
577
|
+
setOtpVisible(true);
|
|
578
|
+
|
|
579
|
+
// set user credentials
|
|
580
|
+
data = {
|
|
581
|
+
username: result.data.email,
|
|
582
|
+
password: values.password,
|
|
583
|
+
mode: result.data.mode ? result.data.mode : null,
|
|
584
|
+
mobile: result.data.mobile ? result.data.mobile : null,
|
|
585
|
+
};
|
|
586
|
+
|
|
587
|
+
// set user values
|
|
588
|
+
setUser(data);
|
|
589
|
+
} else {
|
|
590
|
+
let d = user;
|
|
591
|
+
|
|
592
|
+
let userInfo = {
|
|
593
|
+
id: user.id,
|
|
594
|
+
locations: [],
|
|
595
|
+
...d,
|
|
596
|
+
...{
|
|
597
|
+
loggedCheckDone: true,
|
|
598
|
+
},
|
|
599
|
+
};
|
|
600
|
+
|
|
601
|
+
dispatch({ type: 'user', payload: userInfo });
|
|
602
|
+
|
|
603
|
+
localStorage.setItem('userInfo', JSON.stringify(userInfo));
|
|
604
|
+
|
|
605
|
+
history.push('/');
|
|
606
|
+
}
|
|
607
|
+
} else {
|
|
608
|
+
message.error(result.message);
|
|
609
|
+
}
|
|
610
|
+
})
|
|
611
|
+
.catch((error) => {
|
|
612
|
+
console.log(error);
|
|
613
|
+
|
|
614
|
+
message.error('This operation has failed.');
|
|
615
|
+
|
|
616
|
+
setLdapLoading(false);
|
|
617
|
+
});
|
|
618
|
+
};
|
|
619
|
+
|
|
620
|
+
// helper to show contact in OTP verification screen
|
|
621
|
+
const getOtpDestinationText = () => {
|
|
622
|
+
if (communicationMode === 'mobile') return formatMobile(user.mobile);
|
|
623
|
+
// if (communicationMode === 'whatsapp') return user.mobile;
|
|
624
|
+
return user.username;
|
|
625
|
+
};
|
|
626
|
+
|
|
627
|
+
const { globalCustomerHeader = () => {} } = appSettings;
|
|
628
|
+
|
|
629
|
+
const themeName = process.env.REACT_APP_THEME; // e.g., 'purple'
|
|
630
|
+
const isPurple = themeName === 'purple';
|
|
631
|
+
|
|
632
|
+
const sectionStyle = isPurple
|
|
633
|
+
? {
|
|
634
|
+
width: '100%',
|
|
635
|
+
height: '100vh',
|
|
636
|
+
backgroundImage: `${state.theme.colors.loginPageBackground}`,
|
|
637
|
+
backgroundPosition: 'center bottom, center',
|
|
638
|
+
backgroundRepeat: 'no-repeat, no-repeat',
|
|
639
|
+
backgroundSize: 'cover, cover',
|
|
640
|
+
}
|
|
641
|
+
: {
|
|
642
|
+
width: '100%',
|
|
643
|
+
height: '100vh',
|
|
644
|
+
background: 'linear-gradient(to bottom, #F7F6E3 0%, #EEF1DE 20%, #D5E4DA 45%, #9DBFC8 75%, #4F89A6 100%)',
|
|
645
|
+
backgroundPosition: 'center bottom, center',
|
|
646
|
+
backgroundRepeat: 'no-repeat, no-repeat',
|
|
647
|
+
backgroundSize: 'cover, cover',
|
|
648
|
+
};
|
|
649
|
+
|
|
650
|
+
return (
|
|
651
|
+
<section className="full-page" style={sectionStyle}>
|
|
652
|
+
<section className="user-authentication-section">
|
|
653
|
+
{/* Background Section */}
|
|
654
|
+
<motion.div
|
|
655
|
+
className="page-background"
|
|
656
|
+
initial={{ y: -50, opacity: 0 }}
|
|
657
|
+
animate={{ y: 0, opacity: 1 }}
|
|
658
|
+
transition={{ duration: 1, ease: 'anticipate' }}
|
|
659
|
+
exit={{ opacity: 0 }}
|
|
660
|
+
/>
|
|
661
|
+
{/* Background Section Ends */}
|
|
662
|
+
|
|
663
|
+
<motion.div
|
|
664
|
+
className="auth-form-wrapper"
|
|
665
|
+
initial={{ y: 20 }}
|
|
666
|
+
animate={{ y: 0 }}
|
|
667
|
+
transition={{ duration: 1, ease: 'anticipate' }}
|
|
668
|
+
exit={{ opacity: 0 }}
|
|
669
|
+
>
|
|
670
|
+
<div
|
|
671
|
+
className=" login-form-container"
|
|
672
|
+
style={{
|
|
673
|
+
background: state.theme.colors.tableBg,
|
|
674
|
+
borderStyle: state.theme.colors.tableBorderStyle,
|
|
675
|
+
}}
|
|
676
|
+
>
|
|
677
|
+
<div className="brand-logo">
|
|
678
|
+
<img className="logo-welcome" src={brandLogo} alt="Logo" />
|
|
679
|
+
</div>
|
|
680
|
+
|
|
681
|
+
<div className="otp-form">
|
|
682
|
+
{/* OTP Verification Section */}
|
|
683
|
+
|
|
684
|
+
{/* OTP Method Selection Section */}
|
|
685
|
+
{otpVisible && (
|
|
686
|
+
<div className="otp-input-container">
|
|
687
|
+
<div className="form-title">
|
|
688
|
+
{otpVerification ? (
|
|
689
|
+
<>
|
|
690
|
+
{/* <h3>OTP Verification</h3> */}
|
|
691
|
+
{/* <p>
|
|
692
|
+
Enter the verification code we sent to{' '}
|
|
693
|
+
<span className="otp-mode-text">
|
|
694
|
+
<strong>{getOtpDestinationText()}</strong>
|
|
695
|
+
</span>
|
|
696
|
+
</p> */}
|
|
697
|
+
</>
|
|
698
|
+
) : (
|
|
699
|
+
<>
|
|
700
|
+
<Text type="primary">Two Factor Authentication</Text>
|
|
701
|
+
<p>
|
|
702
|
+
Two-Factor Authentication is enabled for your account. Please verify your account before logging in to enhance security.
|
|
703
|
+
</p>
|
|
704
|
+
|
|
705
|
+
</>
|
|
706
|
+
)}
|
|
707
|
+
</div>
|
|
708
|
+
|
|
709
|
+
{/* Show Communication Method ONLY IF:
|
|
710
|
+
- OTP not sent OR
|
|
711
|
+
- OTP expired
|
|
712
|
+
*/}
|
|
713
|
+
|
|
714
|
+
{(!otpVerification || otpExpired) && (
|
|
715
|
+
<>
|
|
716
|
+
<Divider />
|
|
717
|
+
<div className="otp-method-section">
|
|
718
|
+
<Text type="primary">Select Preferred OTP Verification Method</Text>
|
|
719
|
+
<div className="otp-method-group">
|
|
720
|
+
<Radio checked={communicationMode === 'email'} onChange={() => setCommunicationMode('email')}>
|
|
721
|
+
Email <MailOutlined className="otp-icon" style={{ marginLeft: 6 }} />
|
|
722
|
+
</Radio>
|
|
723
|
+
<Radio checked={communicationMode === 'mobile'} onChange={() => setCommunicationMode('mobile')}>
|
|
724
|
+
SMS <MessageOutlined className="otp-icon" style={{ marginLeft: 6 }} />
|
|
725
|
+
</Radio>
|
|
726
|
+
</div>
|
|
727
|
+
{modeError && <p className="otp-mode-error">Please select a communication mode.</p>}
|
|
728
|
+
</div>
|
|
729
|
+
</>
|
|
730
|
+
)}
|
|
731
|
+
|
|
732
|
+
{!otpVerification ? (
|
|
733
|
+
<div className="otp-container">
|
|
734
|
+
<Button type="primary" onClick={sendAuthenticationOtp} style={{ marginTop: '6px' }}>
|
|
735
|
+
Send OTP
|
|
736
|
+
</Button>
|
|
737
|
+
</div>
|
|
738
|
+
) : (
|
|
739
|
+
<>
|
|
740
|
+
{/* <Divider /> */}
|
|
741
|
+
<div className="otp-container">
|
|
742
|
+
<p>
|
|
743
|
+
Enter the verification code we sent to{' '}
|
|
744
|
+
<span className="otp-mode-text">
|
|
745
|
+
<strong>{getOtpDestinationText()}</strong>
|
|
746
|
+
</span>
|
|
747
|
+
</p>
|
|
748
|
+
<OTPInput
|
|
749
|
+
value={otpValue}
|
|
750
|
+
onChange={handleOtpChange}
|
|
751
|
+
autoFocus
|
|
752
|
+
OTPLength={6}
|
|
753
|
+
disabled={loading || otpExpired}
|
|
754
|
+
inputStyles={{
|
|
755
|
+
border: otpSuccess
|
|
756
|
+
? '2px solid #52c41a' // green
|
|
757
|
+
: otpError
|
|
758
|
+
? '2px solid #FF5C5C' // red
|
|
759
|
+
: '1px solid #d9d9d9', // default
|
|
760
|
+
borderRadius: 4,
|
|
761
|
+
width: isMobile ? 28 : 45, // MOBILE FIX
|
|
762
|
+
height: isMobile ? 36 : 40, // MOBILE FIX
|
|
763
|
+
margin: isMobile ? '2px' : '0 4px',
|
|
764
|
+
fontSize: isMobile ? 16 : 18,
|
|
765
|
+
textAlign: 'center',
|
|
766
|
+
}}
|
|
767
|
+
/>
|
|
768
|
+
{/* Timer below OTP */}
|
|
769
|
+
<div className="otp-timer">
|
|
770
|
+
{/* {!otpExpired ? */}
|
|
771
|
+
{otpSuccess ? null : <span>{formatted}</span>}
|
|
772
|
+
{/* {otpError && (
|
|
773
|
+
<p style={{ color: 'red', marginTop: 8 }}>Invalid OTP, please try again</p>
|
|
774
|
+
)} */}
|
|
775
|
+
|
|
776
|
+
{otpSuccess && <p style={{ color: 'green', marginTop: 8 }}>Your OTP has been verified successfully.</p>}
|
|
777
|
+
</div>
|
|
778
|
+
</div>
|
|
779
|
+
{!otpSuccess && (
|
|
780
|
+
<Button type="primary" disabled={otpExpired} onClick={verifyOtp} style={{ marginTop: 16 }}>
|
|
781
|
+
Verify OTP
|
|
782
|
+
</Button>
|
|
783
|
+
)}
|
|
784
|
+
</>
|
|
785
|
+
)}
|
|
786
|
+
</div>
|
|
787
|
+
)}
|
|
788
|
+
|
|
789
|
+
{/* Login Form Section */}
|
|
790
|
+
{!otpVerification && !otpVisible && !showResetpassword && (
|
|
791
|
+
<Form {...layout} layout="vertical" name="basic" onFinish={onFinish} onFinishFailed={onFinishFailed}>
|
|
792
|
+
<div className="form-title">
|
|
793
|
+
<h4></h4>
|
|
794
|
+
</div>
|
|
795
|
+
|
|
796
|
+
{/* {!process.env.REACT_APP_SHOW_BRANCH_SWITCHER && <div className="branch-switcher">{globalCustomerHeader()}</div>} */}
|
|
797
|
+
|
|
798
|
+
{process.env.REACT_APP_ENABLE_LDAP === 'true' && (
|
|
799
|
+
<Button loading={ldaploading} type="secondary" className="SubmitBtn" onClick={loginWithLdap}>
|
|
800
|
+
Sign in using AD
|
|
801
|
+
</Button>
|
|
802
|
+
)}
|
|
803
|
+
|
|
804
|
+
<Form.Item label="Email" name="email" rules={[{ required: true, message: 'Please input your email!' }]}>
|
|
805
|
+
<Input autoComplete="off" autoFocus />
|
|
806
|
+
</Form.Item>
|
|
807
|
+
|
|
808
|
+
<Form.Item label="Password" name="password" rules={[{ required: true, message: 'Please input your password!' }]}>
|
|
809
|
+
<Input.Password autoComplete="off" />
|
|
810
|
+
</Form.Item>
|
|
811
|
+
|
|
812
|
+
<Form.Item {...tailLayout} style={{ marginBottom: '0px' }}>
|
|
813
|
+
<Button loading={loading} type="primary" htmlType="submit" className="SubmitBtn">
|
|
814
|
+
Submit
|
|
815
|
+
</Button>
|
|
816
|
+
<div className="forgot-password" style={{ marginTop: '8px', textAlign: 'center' }}>
|
|
817
|
+
<Link onClick={() => setShowResetpassword(true)}>Forgot Password?</Link>
|
|
818
|
+
</div>
|
|
819
|
+
</Form.Item>
|
|
820
|
+
</Form>
|
|
821
|
+
)}
|
|
822
|
+
|
|
823
|
+
{/* Forgot Password Section */}
|
|
824
|
+
{showResetpassword && (
|
|
825
|
+
<ResetPassword
|
|
826
|
+
defaultUsername={expiredPassword ? defaultUsername : undefined}
|
|
827
|
+
disabledUserName={expiredPassword}
|
|
828
|
+
onBack={() => {
|
|
829
|
+
setShowResetpassword(false);
|
|
830
|
+
setExpiredPassword(false);
|
|
831
|
+
}}
|
|
832
|
+
title={expiredPassword ? 'Password Expired!' : 'Forgot Password?'}
|
|
833
|
+
// subtitle={
|
|
834
|
+
// expiredPassword
|
|
835
|
+
// ? 'Your password has expired. Select a preferred communication method to receive the One-Time Password (OTP) to continue.'
|
|
836
|
+
// : 'Enter your username and Select a preferred communication method to receive the One-Time Password (OTP) to continue..'
|
|
837
|
+
// }
|
|
838
|
+
buttonText={expiredPassword ? 'Send Reset Link' : 'Reset Password'}
|
|
839
|
+
/>
|
|
840
|
+
)}
|
|
841
|
+
</div>
|
|
842
|
+
</div>
|
|
843
|
+
{!otpSuccess && otpVerification && (
|
|
844
|
+
<div className="otp-actions">
|
|
845
|
+
<div className="resend-action">
|
|
846
|
+
<Text disabled>Didn't receive OTP?</Text>
|
|
847
|
+
|
|
848
|
+
<Link className="resend-otp-link" disabled={!otpExpired} onClick={handleResendOTP}>
|
|
849
|
+
Resend OTP
|
|
850
|
+
</Link>
|
|
851
|
+
</div>
|
|
852
|
+
|
|
853
|
+
<Button size="small" type="default" onClick={handlecancel}>
|
|
854
|
+
Cancel
|
|
855
|
+
</Button>
|
|
856
|
+
</div>
|
|
857
|
+
)}
|
|
858
|
+
</motion.div>
|
|
859
|
+
</section>
|
|
860
|
+
</section>
|
|
861
|
+
);
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
export default withRouter(LoginPhone);
|