ui-soxo-bootstrap-core 2.6.0 → 2.6.1-dev.10
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/.github/workflows/npm-publish.yml +49 -19
- package/core/components/extra-info/extra-info-details.js +2 -2
- package/core/components/menu-template-api/menu-template-api.js +2 -2
- package/core/lib/Store.js +3 -3
- package/core/lib/components/global-header/global-header.js +2 -2
- package/core/lib/components/sidemenu/sidemenu.js +19 -13
- package/core/lib/elements/basic/country-phone-input/country-phone-input.js +35 -60
- package/core/lib/elements/basic/country-phone-input/phone-input.scss +14 -0
- package/core/lib/elements/basic/dragabble-wrapper/draggable-wrapper.js +1 -1
- package/core/lib/elements/basic/menu-tree/menu-tree.js +26 -13
- package/core/lib/models/forms/components/form-creator/form-creator.js +468 -502
- package/core/lib/models/forms/components/form-creator/form-creator.scss +5 -4
- package/core/lib/models/menus/components/menu-list/menu-list.js +424 -467
- package/core/lib/pages/change-password/change-password.js +17 -24
- package/core/lib/pages/change-password/change-password.scss +45 -48
- package/core/lib/pages/login/commnication-mode-selection.js +46 -0
- package/core/lib/pages/login/communication-mode-selection.scss +60 -0
- package/core/lib/pages/login/login.js +153 -24
- package/core/lib/pages/login/login.scss +229 -334
- package/core/lib/pages/login/reset-password.js +124 -0
- package/core/lib/pages/login/reset-password.scss +31 -0
- package/core/lib/pages/profile/themes.json +4 -4
- package/core/lib/utils/api/api.utils.js +71 -48
- package/core/lib/utils/common/common.utils.js +109 -0
- package/core/lib/utils/http/http.utils.js +1 -0
- package/core/lib/utils/index.js +25 -28
- package/core/models/base/base.js +7 -3
- package/core/models/core-scripts/core-scripts.js +9 -0
- package/core/models/doctor/components/doctor-add/doctor-add.js +9 -4
- package/core/models/menus/components/menu-add/menu-add.js +1 -1
- package/core/models/menus/components/menu-lists/menu-lists.js +5 -9
- package/core/models/menus/menus.js +21 -2
- package/core/models/roles/components/role-add/role-add.js +92 -59
- package/core/models/roles/components/role-list/role-list.js +1 -1
- package/core/models/roles/roles.js +9 -0
- package/core/models/staff/components/staff-add/staff-add.js +20 -32
- package/core/models/users/components/assign-role/assign-role.js +145 -50
- package/core/models/users/components/assign-role/assign-role.scss +209 -45
- package/core/models/users/components/assign-role/avatar-props.js +45 -0
- package/core/models/users/components/user-add/user-add.js +47 -56
- package/core/models/users/components/user-add/user-edit.js +25 -4
- package/core/models/users/users.js +34 -8
- package/core/modules/dashboard/components/dashboard-card/menu-dashboard-card.js +1 -1
- package/core/modules/reporting/components/reporting-dashboard/README.md +316 -0
- package/core/modules/reporting/components/reporting-dashboard/adavance-search/advance-search.js +120 -0
- package/core/modules/reporting/components/reporting-dashboard/display-columns/build-display-columns.js +75 -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 +222 -376
- package/core/modules/steps/action-buttons.js +47 -45
- package/core/modules/steps/action-buttons.scss +35 -6
- package/core/modules/steps/steps.js +12 -10
- package/core/modules/steps/steps.scss +229 -31
- package/core/modules/steps/timeline.js +21 -19
- package/package.json +3 -2
- package/core/components/external-window/DEVELOPER_GUIDE.md +0 -705
|
@@ -39,7 +39,7 @@ function ChangePassword({ history }) {
|
|
|
39
39
|
|
|
40
40
|
const [loading, setLoading] = useState(false);
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
|
|
43
43
|
|
|
44
44
|
const onFinish = (values) => {
|
|
45
45
|
|
|
@@ -55,34 +55,27 @@ function ChangePassword({ history }) {
|
|
|
55
55
|
confirm_password: values.conpassword
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
//If current Password is entered wrong
|
|
68
|
-
message.error('Incorrect Password')
|
|
69
|
-
setLoading(false);
|
|
70
|
-
return false
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
58
|
+
ApiUtils.post({
|
|
59
|
+
url: `users/change-password`,
|
|
60
|
+
headers: {
|
|
61
|
+
db_ptr: 'nuraho'
|
|
62
|
+
},
|
|
63
|
+
formBody,
|
|
64
|
+
hideError: true
|
|
65
|
+
})
|
|
66
|
+
.then((result) => {
|
|
73
67
|
|
|
74
68
|
setLoading(false);
|
|
75
69
|
|
|
76
70
|
history.goBack();
|
|
77
71
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
message.error(error.result || error.message)
|
|
72
|
+
// Update successful.
|
|
73
|
+
message.success(result.result || 'Your password has been updated!');
|
|
74
|
+
|
|
75
|
+
}).catch(function (error) {
|
|
76
|
+
|
|
77
|
+
// An error happened.
|
|
78
|
+
message.warning(error.result || error.message);
|
|
86
79
|
|
|
87
80
|
setLoading(false);
|
|
88
81
|
|
|
@@ -1,63 +1,51 @@
|
|
|
1
|
-
.change-password {
|
|
2
|
-
margin:
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
// margin: 10px 3%;
|
|
6
|
-
// align-items: center;
|
|
7
|
-
|
|
8
|
-
@media only screen and (min-width: 768px) {
|
|
9
|
-
justify-content: left;
|
|
10
|
-
align-items: left;
|
|
1
|
+
.change-password.card {
|
|
2
|
+
margin: -6px 8px;
|
|
3
|
+
.ant-card-body {
|
|
4
|
+
padding: 16px;
|
|
11
5
|
}
|
|
12
6
|
|
|
13
|
-
.homescreen{
|
|
14
|
-
width: 100%;
|
|
15
|
-
margin: 10px 0px;
|
|
16
|
-
border-radius: 4px;
|
|
17
|
-
background-color: aliceblue;
|
|
18
|
-
padding:10px;
|
|
19
|
-
height: 40px;
|
|
20
|
-
}
|
|
21
7
|
.auth-form-wrapper {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
8
|
+
display: flex;
|
|
9
|
+
flex-direction: column;
|
|
10
|
+
gap: 18px;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.form-title {
|
|
14
|
+
h4 {
|
|
15
|
+
margin-bottom: 6px;
|
|
16
|
+
font-weight: 600;
|
|
17
|
+
color: #111827;
|
|
28
18
|
}
|
|
29
19
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
20
|
+
p {
|
|
21
|
+
margin: 0;
|
|
22
|
+
font-size: 14px;
|
|
23
|
+
line-height: 1.6;
|
|
24
|
+
color: #6b7280;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
35
27
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
28
|
+
.ant-form-item {
|
|
29
|
+
margin-bottom: 18px;
|
|
30
|
+
|
|
31
|
+
.ant-form-item-label > label {
|
|
32
|
+
font-weight: 500;
|
|
33
|
+
font-size: 14px;
|
|
34
|
+
color: #374151;
|
|
39
35
|
}
|
|
40
36
|
|
|
41
|
-
.ant-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
margin: 0 0 8px 0;
|
|
47
|
-
line-height: 020px;
|
|
48
|
-
padding: 0px;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
.ant-btn-primary {
|
|
52
|
-
margin-top: 0px;
|
|
53
|
-
}
|
|
37
|
+
.ant-input-password {
|
|
38
|
+
border-radius: 6px;
|
|
39
|
+
padding: 10px 12px;
|
|
40
|
+
transition: border 0.2s ease, box-shadow 0.2s ease;
|
|
41
|
+
|
|
54
42
|
}
|
|
55
43
|
|
|
56
|
-
.ant-form-explain {
|
|
57
|
-
position: absolute;
|
|
44
|
+
.ant-form-item-explain-error {
|
|
58
45
|
font-size: 12px;
|
|
59
|
-
margin-
|
|
46
|
+
margin-top: 4px;
|
|
60
47
|
}
|
|
48
|
+
}
|
|
61
49
|
|
|
62
50
|
.ant-btn-primary {
|
|
63
51
|
width: 110px;
|
|
@@ -70,6 +58,15 @@
|
|
|
70
58
|
.ant-btn-secondary {
|
|
71
59
|
width: 100px;
|
|
72
60
|
}
|
|
61
|
+
|
|
62
|
+
@media (max-width: 768px) {
|
|
63
|
+
margin: 0px ;
|
|
64
|
+
.ant-card-body {
|
|
65
|
+
padding: 24px;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
@media only screen and (max-width: 1024px) {
|
|
69
|
+
margin: 60px 8px;
|
|
73
70
|
}
|
|
74
71
|
|
|
75
72
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CommunicationModeSelection Component
|
|
3
|
+
*
|
|
4
|
+
* Renders radio options for selecting OTP delivery method.
|
|
5
|
+
* Supports Email and SMS modes.
|
|
6
|
+
*
|
|
7
|
+
* Props:
|
|
8
|
+
* @param {string} communicationMode - Currently selected mode ('email' | 'mobile')
|
|
9
|
+
* @param {Function} setCommunicationMode - Updates selected mode
|
|
10
|
+
* @param {boolean} modeError - Displays validation error if true
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import React from 'react';
|
|
14
|
+
import { Radio, Divider, Typography } from 'antd';
|
|
15
|
+
import { MailOutlined, MessageOutlined } from '@ant-design/icons';
|
|
16
|
+
|
|
17
|
+
import './communication-mode-selection.scss';
|
|
18
|
+
|
|
19
|
+
const { Text } = Typography;
|
|
20
|
+
|
|
21
|
+
function CommunicationModeSelection({ communicationMode, setCommunicationMode, modeError }) {
|
|
22
|
+
return (
|
|
23
|
+
<>
|
|
24
|
+
<div className="otp-method-section">
|
|
25
|
+
<Text type="primary">Select Preferred OTP Verification Method</Text>
|
|
26
|
+
<div className="otp-method-group">
|
|
27
|
+
|
|
28
|
+
{/* Email Option */}
|
|
29
|
+
<Radio checked={communicationMode === 'email'} onChange={() => setCommunicationMode('email')}>
|
|
30
|
+
Email <MailOutlined className="otp-icon" style={{ marginLeft: 6 }} />
|
|
31
|
+
</Radio>
|
|
32
|
+
|
|
33
|
+
{/* SMS Option */}
|
|
34
|
+
<Radio checked={communicationMode === 'mobile'} disabled onChange={() => setCommunicationMode('mobile')}>
|
|
35
|
+
SMS <MessageOutlined className="otp-icon" style={{ marginLeft: 6 }} />
|
|
36
|
+
</Radio>
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
{/* Validation Error */}
|
|
40
|
+
{modeError && <p className="otp-mode-error">Please select a communication mode.</p>}
|
|
41
|
+
</div>
|
|
42
|
+
</>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export default CommunicationModeSelection;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
$error-color: red;
|
|
2
|
+
|
|
3
|
+
.otp-method-section {
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
gap: 6px;
|
|
7
|
+
|
|
8
|
+
.otp-method-title {
|
|
9
|
+
font-size: 16px;
|
|
10
|
+
font-weight: 600;
|
|
11
|
+
margin-bottom: 8px;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.otp-method-group {
|
|
15
|
+
display: flex;
|
|
16
|
+
align-items: center;
|
|
17
|
+
margin-bottom: 10px;
|
|
18
|
+
gap: 30px;
|
|
19
|
+
font-size: 12px;
|
|
20
|
+
|
|
21
|
+
.ant-radio-wrapper {
|
|
22
|
+
display: flex;
|
|
23
|
+
gap: 6px;
|
|
24
|
+
|
|
25
|
+
svg {
|
|
26
|
+
font-size: 18px;
|
|
27
|
+
opacity: 0.8;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@media only screen and (max-width: 600px) {
|
|
32
|
+
flex-direction: column !important;
|
|
33
|
+
align-items: flex-start !important;
|
|
34
|
+
gap: 12px !important;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@media only screen and (min-width: 601px) and (max-width: 1024px) {
|
|
38
|
+
flex-direction: row !important;
|
|
39
|
+
align-items: center !important;
|
|
40
|
+
justify-content: space-between !important;
|
|
41
|
+
gap: 20px !important;
|
|
42
|
+
width: 100%;
|
|
43
|
+
|
|
44
|
+
.ant-radio-wrapper {
|
|
45
|
+
flex: 1;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.otp-mode-error {
|
|
51
|
+
margin: 5px;
|
|
52
|
+
font-size: 13px;
|
|
53
|
+
color: $error-color;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.otp-icon {
|
|
57
|
+
position: relative;
|
|
58
|
+
top: 2px;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -30,10 +30,12 @@ import { getAccessToken, getRefreshToken } from '../../utils/http/auth.helper';
|
|
|
30
30
|
|
|
31
31
|
import { Location } from '../../utils';
|
|
32
32
|
|
|
33
|
-
import { checkLicenseStatus, formatMobile } from '../../utils/common/common.utils';
|
|
33
|
+
import { checkLicenseStatus, formatMobile, checkExpiryStatus, safeJSON } from '../../utils/common/common.utils';
|
|
34
34
|
|
|
35
35
|
import { MailOutlined, MessageOutlined, WhatsAppOutlined } from '@ant-design/icons';
|
|
36
36
|
|
|
37
|
+
import ResetPassword from './reset-password';
|
|
38
|
+
|
|
37
39
|
const { Text, Title } = Typography;
|
|
38
40
|
|
|
39
41
|
const layout = {
|
|
@@ -48,13 +50,20 @@ const tailLayout = {
|
|
|
48
50
|
|
|
49
51
|
const LICENSE_EXPIRY = '2026-12-12';
|
|
50
52
|
|
|
53
|
+
//password valdity expire
|
|
54
|
+
const PASSWORD_VALIDITY_DAYS = 90;
|
|
55
|
+
|
|
56
|
+
const headers = {
|
|
57
|
+
db_ptr: 'nuraho',
|
|
58
|
+
};
|
|
59
|
+
|
|
51
60
|
/**
|
|
52
61
|
*
|
|
53
62
|
* @param {*} param0
|
|
54
63
|
* @returns
|
|
55
64
|
*/
|
|
56
65
|
function LoginPhone({ history, appSettings }) {
|
|
57
|
-
const { brandLogo, heroImage, footerLogo
|
|
66
|
+
const { brandLogo, heroImage, footerLogo } = appSettings;
|
|
58
67
|
|
|
59
68
|
// Hook for OTP Timer
|
|
60
69
|
const { expired: otpExpired, formatted, startFromExpiry } = useOtpTimer();
|
|
@@ -85,11 +94,71 @@ function LoginPhone({ history, appSettings }) {
|
|
|
85
94
|
const [communicationMode, setCommunicationMode] = useState(null); // default selected email
|
|
86
95
|
const [modeError, setModeError] = useState(false);
|
|
87
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
|
+
|
|
88
106
|
const isAuthenticated = Boolean(getAccessToken());
|
|
89
107
|
const isRefreshTokenExist = Boolean(getRefreshToken());
|
|
90
108
|
|
|
91
109
|
const path = window.location.pathname;
|
|
92
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
|
+
|
|
93
162
|
const onFinish = (values) => {
|
|
94
163
|
setLoading(true);
|
|
95
164
|
|
|
@@ -127,6 +196,8 @@ function LoginPhone({ history, appSettings }) {
|
|
|
127
196
|
if (insider_token) localStorage.insider_token = insider_token;
|
|
128
197
|
|
|
129
198
|
if (result.success) {
|
|
199
|
+
handlePasswordExpiryCheck(user);
|
|
200
|
+
|
|
130
201
|
//two_factor_authentication variable is present then proceed Two factor authentication
|
|
131
202
|
if (result.data && result.data.two_factor_authentication) {
|
|
132
203
|
let data;
|
|
@@ -146,7 +217,7 @@ function LoginPhone({ history, appSettings }) {
|
|
|
146
217
|
setUser(data);
|
|
147
218
|
// Set default communication mode automatically
|
|
148
219
|
if (result.data.mode) {
|
|
149
|
-
setCommunicationMode(result.data.mode);
|
|
220
|
+
setCommunicationMode(result.data.mode);
|
|
150
221
|
}
|
|
151
222
|
} else {
|
|
152
223
|
let d = user;
|
|
@@ -165,10 +236,33 @@ function LoginPhone({ history, appSettings }) {
|
|
|
165
236
|
localStorage.setItem('userInfo', JSON.stringify(userInfo));
|
|
166
237
|
if (refresh_token) localStorage.setItem('refresh_token', refresh_token);
|
|
167
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
|
+
|
|
168
250
|
history.push('/');
|
|
169
251
|
}
|
|
170
252
|
} else {
|
|
171
|
-
|
|
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
|
+
}
|
|
172
266
|
}
|
|
173
267
|
})
|
|
174
268
|
.catch((error) => {
|
|
@@ -257,10 +351,10 @@ function LoginPhone({ history, appSettings }) {
|
|
|
257
351
|
if (result.success) {
|
|
258
352
|
// for expiry_time
|
|
259
353
|
startFromExpiry(result?.expiry_time);
|
|
260
|
-
// if the api is sucess then go for otpverification step
|
|
261
|
-
setotpVerification(true);
|
|
262
354
|
// set button loading false
|
|
263
355
|
setLoading(false);
|
|
356
|
+
// if the api is sucess then go for otpverification step
|
|
357
|
+
setotpVerification(true);
|
|
264
358
|
} else {
|
|
265
359
|
setLoading(false);
|
|
266
360
|
message.error(result.message);
|
|
@@ -313,10 +407,22 @@ function LoginPhone({ history, appSettings }) {
|
|
|
313
407
|
// Setting refresh_token
|
|
314
408
|
if (result.refresh_token) localStorage.setItem('refresh_token', result.refresh_token);
|
|
315
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
|
+
|
|
316
420
|
dispatch({ type: 'user', payload: userInfo });
|
|
317
421
|
// set user info into local storage
|
|
318
422
|
localStorage.setItem('userInfo', JSON.stringify(userInfo));
|
|
319
423
|
|
|
424
|
+
handlePasswordExpiryCheck(result.user);
|
|
425
|
+
|
|
320
426
|
setTimeout(() => history.push('/'), 500);
|
|
321
427
|
} else {
|
|
322
428
|
// OTP FAILED (wrong OTP)
|
|
@@ -518,28 +624,28 @@ function LoginPhone({ history, appSettings }) {
|
|
|
518
624
|
return user.username;
|
|
519
625
|
};
|
|
520
626
|
|
|
521
|
-
const { globalCustomerHeader = () => {} } = appSettings;
|
|
627
|
+
const { globalCustomerHeader = () => { } } = appSettings;
|
|
522
628
|
|
|
523
629
|
const themeName = process.env.REACT_APP_THEME; // e.g., 'purple'
|
|
524
630
|
const isPurple = themeName === 'purple';
|
|
525
631
|
|
|
526
632
|
const sectionStyle = isPurple
|
|
527
633
|
? {
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
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
|
+
}
|
|
535
641
|
: {
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
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
|
+
};
|
|
543
649
|
|
|
544
650
|
return (
|
|
545
651
|
<section className="full-page" style={sectionStyle}>
|
|
@@ -681,13 +787,13 @@ function LoginPhone({ history, appSettings }) {
|
|
|
681
787
|
)}
|
|
682
788
|
|
|
683
789
|
{/* Login Form Section */}
|
|
684
|
-
{!otpVerification && !otpVisible && (
|
|
790
|
+
{!otpVerification && !otpVisible && !showResetpassword && (
|
|
685
791
|
<Form {...layout} layout="vertical" name="basic" onFinish={onFinish} onFinishFailed={onFinishFailed}>
|
|
686
792
|
<div className="form-title">
|
|
687
793
|
<h4></h4>
|
|
688
794
|
</div>
|
|
689
795
|
|
|
690
|
-
{!process.env.REACT_APP_SHOW_BRANCH_SWITCHER && <div className="branch-switcher">{globalCustomerHeader()}</div>}
|
|
796
|
+
{/* {!process.env.REACT_APP_SHOW_BRANCH_SWITCHER && <div className="branch-switcher">{globalCustomerHeader()}</div>} */}
|
|
691
797
|
|
|
692
798
|
{process.env.REACT_APP_ENABLE_LDAP === 'true' && (
|
|
693
799
|
<Button loading={ldaploading} type="secondary" className="SubmitBtn" onClick={loginWithLdap}>
|
|
@@ -703,19 +809,42 @@ function LoginPhone({ history, appSettings }) {
|
|
|
703
809
|
<Input.Password autoComplete="off" />
|
|
704
810
|
</Form.Item>
|
|
705
811
|
|
|
706
|
-
<Form.Item {...tailLayout}>
|
|
812
|
+
<Form.Item {...tailLayout} style={{ marginBottom: '0px' }}>
|
|
707
813
|
<Button loading={loading} type="primary" htmlType="submit" className="SubmitBtn">
|
|
708
814
|
Submit
|
|
709
815
|
</Button>
|
|
816
|
+
<div className="forgot-password">
|
|
817
|
+
<Link onClick={() => setShowResetpassword(true)}>Forgot Password?</Link>
|
|
818
|
+
</div>
|
|
710
819
|
</Form.Item>
|
|
711
820
|
</Form>
|
|
712
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' : 'Send Reset Link'}
|
|
839
|
+
/>
|
|
840
|
+
)}
|
|
713
841
|
</div>
|
|
714
842
|
</div>
|
|
715
843
|
{!otpSuccess && otpVerification && (
|
|
716
844
|
<div className="otp-actions">
|
|
717
845
|
<div className="resend-action">
|
|
718
846
|
<Text disabled>Didn't receive OTP?</Text>
|
|
847
|
+
|
|
719
848
|
<Link className="resend-otp-link" disabled={!otpExpired} onClick={handleResendOTP}>
|
|
720
849
|
Resend OTP
|
|
721
850
|
</Link>
|