1
- import { useEffect , useMemo , useState } from 'react' ;
2
- import { connect } from 'react-redux' ;
1
+ import {
2
+ useCallback , useEffect , useMemo , useState ,
3
+ } from 'react' ;
4
+ import { useDispatch , useSelector } from 'react-redux' ;
3
5
4
6
import { getConfig } from '@edx/frontend-platform' ;
5
7
import { sendPageEvent , sendTrackEvent } from '@edx/frontend-platform/analytics' ;
6
8
import { useIntl } from '@edx/frontend-platform/i18n' ;
7
- import {
8
- Form , StatefulButton ,
9
- } from '@openedx/paragon' ;
9
+ import { Form , StatefulButton } from '@openedx/paragon' ;
10
10
import PropTypes from 'prop-types' ;
11
11
import { Helmet } from 'react-helmet' ;
12
12
import Skeleton from 'react-loading-skeleton' ;
13
13
import { Link } from 'react-router-dom' ;
14
14
15
- import AccountActivationMessage from './AccountActivationMessage' ;
16
- import {
17
- backupLoginFormBegin ,
18
- dismissPasswordResetBanner ,
19
- loginRequest ,
20
- } from './data/actions' ;
21
- import { INVALID_FORM , TPA_AUTHENTICATION_FAILURE } from './data/constants' ;
22
- import LoginFailureMessage from './LoginFailure' ;
23
- import messages from './messages' ;
24
15
import {
25
16
FormGroup ,
26
17
InstitutionLogistration ,
27
18
PasswordField ,
28
19
RedirectLogistration ,
29
20
ThirdPartyAuthAlert ,
30
21
} from '../common-components' ;
22
+ import AccountActivationMessage from './AccountActivationMessage' ;
31
23
import { getThirdPartyAuthContext } from '../common-components/data/actions' ;
32
24
import { thirdPartyAuthContextSelector } from '../common-components/data/selectors' ;
33
25
import EnterpriseSSO from '../common-components/EnterpriseSSO' ;
34
26
import ThirdPartyAuth from '../common-components/ThirdPartyAuth' ;
35
- import {
36
- DEFAULT_STATE , PENDING_STATE , RESET_PAGE ,
37
- } from '../data/constants' ;
27
+ import { PENDING_STATE , RESET_PAGE } from '../data/constants' ;
38
28
import {
39
29
getActivationStatus ,
40
30
getAllPossibleQueryParams ,
@@ -43,37 +33,57 @@ import {
43
33
updatePathWithQueryParams ,
44
34
} from '../data/utils' ;
45
35
import ResetPasswordSuccess from '../reset-password/ResetPasswordSuccess' ;
36
+ import { backupLoginFormBegin , dismissPasswordResetBanner , loginRequest } from './data/actions' ;
37
+ import { INVALID_FORM , TPA_AUTHENTICATION_FAILURE } from './data/constants' ;
38
+ import LoginFailureMessage from './LoginFailure' ;
39
+ import messages from './messages' ;
46
40
47
- const LoginPage = ( props ) => {
41
+ const LoginPage = ( {
42
+ institutionLogin,
43
+ handleInstitutionLogin,
44
+ } ) => {
45
+ const dispatch = useDispatch ( ) ;
46
+ const backupFormState = useCallback ( ( data ) => dispatch ( backupLoginFormBegin ( data ) ) , [ dispatch ] ) ;
47
+ const getTPADataFromBackend = useCallback ( ( ) => dispatch ( getThirdPartyAuthContext ( ) ) , [ dispatch ] ) ;
48
48
const {
49
49
backedUpFormData,
50
50
loginErrorCode,
51
51
loginErrorContext,
52
52
loginResult,
53
53
shouldBackupState,
54
- thirdPartyAuthContext : {
55
- providers,
56
- currentProvider,
57
- secondaryProviders,
58
- finishAuthUrl,
59
- platformName,
60
- errorMessage : thirdPartyErrorMessage ,
61
- } ,
62
- thirdPartyAuthApiStatus,
63
- institutionLogin,
64
54
showResetPasswordSuccessBanner,
65
55
submitState,
66
- // Actions
67
- backupFormState,
68
- handleInstitutionLogin,
69
- getTPADataFromBackend,
70
- } = props ;
56
+ thirdPartyAuthContext,
57
+ thirdPartyAuthApiStatus,
58
+ } = useSelector ( ( state ) => ( {
59
+ backedUpFormData : state . login . loginFormData ,
60
+ loginErrorCode : state . login . loginErrorCode ,
61
+ loginErrorContext : state . login . loginErrorContext ,
62
+ loginResult : state . login . loginResult ,
63
+ shouldBackupState : state . login . shouldBackupState ,
64
+ showResetPasswordSuccessBanner : state . login . showResetPasswordSuccessBanner ,
65
+ submitState : state . login . submitState ,
66
+ thirdPartyAuthContext : thirdPartyAuthContextSelector ( state ) ,
67
+ thirdPartyAuthApiStatus : state . commonComponents . thirdPartyAuthApiStatus ,
68
+ } ) ) ;
69
+ const {
70
+ providers,
71
+ currentProvider,
72
+ secondaryProviders,
73
+ finishAuthUrl,
74
+ platformName,
75
+ errorMessage : thirdPartyErrorMessage ,
76
+ } = thirdPartyAuthContext ;
71
77
const { formatMessage } = useIntl ( ) ;
72
78
const activationMsgType = getActivationStatus ( ) ;
73
79
const queryParams = useMemo ( ( ) => getAllPossibleQueryParams ( ) , [ ] ) ;
74
80
75
81
const [ formFields , setFormFields ] = useState ( { ...backedUpFormData . formFields } ) ;
76
- const [ errorCode , setErrorCode ] = useState ( { type : '' , count : 0 , context : { } } ) ;
82
+ const [ errorCode , setErrorCode ] = useState ( {
83
+ type : '' ,
84
+ count : 0 ,
85
+ context : { } ,
86
+ } ) ;
77
87
const [ errors , setErrors ] = useState ( { ...backedUpFormData . errors } ) ;
78
88
const tpaHint = getTpaHint ( ) ;
79
89
@@ -87,7 +97,7 @@ const LoginPage = (props) => {
87
97
payload . tpa_hint = tpaHint ;
88
98
}
89
99
getTPADataFromBackend ( payload ) ;
90
- } , [ getTPADataFromBackend , queryParams , tpaHint ] ) ;
100
+ } , [ queryParams , tpaHint , getTPADataFromBackend ] ) ;
91
101
/**
92
102
* Backup the login form in redux when login page is toggled.
93
103
*/
@@ -98,7 +108,7 @@ const LoginPage = (props) => {
98
108
errors : { ...errors } ,
99
109
} ) ;
100
110
}
101
- } , [ shouldBackupState , formFields , errors , backupFormState ] ) ;
111
+ } , [ backupFormState , shouldBackupState , formFields , errors ] ) ;
102
112
103
113
useEffect ( ( ) => {
104
114
if ( loginErrorCode ) {
@@ -123,7 +133,10 @@ const LoginPage = (props) => {
123
133
} , [ thirdPartyErrorMessage ] ) ;
124
134
125
135
const validateFormFields = ( payload ) => {
126
- const { emailOrUsername, password } = payload ;
136
+ const {
137
+ emailOrUsername,
138
+ password,
139
+ } = payload ;
127
140
const fieldErrors = { ...errors } ;
128
141
129
142
if ( emailOrUsername === '' ) {
@@ -141,14 +154,18 @@ const LoginPage = (props) => {
141
154
const handleSubmit = ( event ) => {
142
155
event . preventDefault ( ) ;
143
156
if ( showResetPasswordSuccessBanner ) {
144
- props . dismissPasswordResetBanner ( ) ;
157
+ dispatch ( dismissPasswordResetBanner ( ) ) ;
145
158
}
146
159
147
160
const formData = { ...formFields } ;
148
161
const validationErrors = validateFormFields ( formData ) ;
149
162
if ( validationErrors . emailOrUsername || validationErrors . password ) {
150
163
setErrors ( { ...validationErrors } ) ;
151
- setErrorCode ( prevState => ( { type : INVALID_FORM , count : prevState . count + 1 , context : { } } ) ) ;
164
+ setErrorCode ( prevState => ( {
165
+ type : INVALID_FORM ,
166
+ count : prevState . count + 1 ,
167
+ context : { } ,
168
+ } ) ) ;
152
169
return ;
153
170
}
154
171
@@ -158,23 +175,35 @@ const LoginPage = (props) => {
158
175
password : formData . password ,
159
176
...queryParams ,
160
177
} ;
161
- props . loginRequest ( payload ) ;
178
+ dispatch ( loginRequest ( payload ) ) ;
162
179
} ;
163
180
164
181
const handleOnChange = ( event ) => {
165
- const { name, value } = event . target ;
166
- setFormFields ( prevState => ( { ...prevState , [ name ] : value } ) ) ;
182
+ const {
183
+ name,
184
+ value,
185
+ } = event . target ;
186
+ setFormFields ( prevState => ( {
187
+ ...prevState ,
188
+ [ name ] : value ,
189
+ } ) ) ;
167
190
} ;
168
191
169
192
const handleOnFocus = ( event ) => {
170
193
const { name } = event . target ;
171
- setErrors ( prevErrors => ( { ...prevErrors , [ name ] : '' } ) ) ;
194
+ setErrors ( prevErrors => ( {
195
+ ...prevErrors ,
196
+ [ name ] : '' ,
197
+ } ) ) ;
172
198
} ;
173
199
const trackForgotPasswordLinkClick = ( ) => {
174
200
sendTrackEvent ( 'edx.bi.password-reset_form.toggled' , { category : 'user-engagement' } ) ;
175
201
} ;
176
202
177
- const { provider, skipHintedLogin } = getTpaProvider ( tpaHint , providers , secondaryProviders ) ;
203
+ const {
204
+ provider,
205
+ skipHintedLogin,
206
+ } = getTpaProvider ( tpaHint , providers , secondaryProviders ) ;
178
207
179
208
if ( tpaHint ) {
180
209
if ( thirdPartyAuthApiStatus === PENDING_STATE ) {
@@ -281,88 +310,9 @@ const LoginPage = (props) => {
281
310
) ;
282
311
} ;
283
312
284
- const mapStateToProps = state => {
285
- const loginPageState = state . login ;
286
- return {
287
- backedUpFormData : loginPageState . loginFormData ,
288
- loginErrorCode : loginPageState . loginErrorCode ,
289
- loginErrorContext : loginPageState . loginErrorContext ,
290
- loginResult : loginPageState . loginResult ,
291
- shouldBackupState : loginPageState . shouldBackupState ,
292
- showResetPasswordSuccessBanner : loginPageState . showResetPasswordSuccessBanner ,
293
- submitState : loginPageState . submitState ,
294
- thirdPartyAuthContext : thirdPartyAuthContextSelector ( state ) ,
295
- thirdPartyAuthApiStatus : state . commonComponents . thirdPartyAuthApiStatus ,
296
- } ;
297
- } ;
298
-
299
313
LoginPage . propTypes = {
300
- backedUpFormData : PropTypes . shape ( {
301
- formFields : PropTypes . shape ( { } ) ,
302
- errors : PropTypes . shape ( { } ) ,
303
- } ) ,
304
- loginErrorCode : PropTypes . string ,
305
- loginErrorContext : PropTypes . shape ( {
306
- email : PropTypes . string ,
307
- redirectUrl : PropTypes . string ,
308
- context : PropTypes . shape ( { } ) ,
309
- } ) ,
310
- loginResult : PropTypes . shape ( {
311
- redirectUrl : PropTypes . string ,
312
- success : PropTypes . bool ,
313
- } ) ,
314
- shouldBackupState : PropTypes . bool ,
315
- showResetPasswordSuccessBanner : PropTypes . bool ,
316
- submitState : PropTypes . string ,
317
- thirdPartyAuthApiStatus : PropTypes . string ,
318
314
institutionLogin : PropTypes . bool . isRequired ,
319
- thirdPartyAuthContext : PropTypes . shape ( {
320
- currentProvider : PropTypes . string ,
321
- errorMessage : PropTypes . string ,
322
- platformName : PropTypes . string ,
323
- providers : PropTypes . arrayOf ( PropTypes . shape ( { } ) ) ,
324
- secondaryProviders : PropTypes . arrayOf ( PropTypes . shape ( { } ) ) ,
325
- finishAuthUrl : PropTypes . string ,
326
- } ) ,
327
- // Actions
328
- backupFormState : PropTypes . func . isRequired ,
329
- dismissPasswordResetBanner : PropTypes . func . isRequired ,
330
- loginRequest : PropTypes . func . isRequired ,
331
- getTPADataFromBackend : PropTypes . func . isRequired ,
332
315
handleInstitutionLogin : PropTypes . func . isRequired ,
333
316
} ;
334
317
335
- LoginPage . defaultProps = {
336
- backedUpFormData : {
337
- formFields : {
338
- emailOrUsername : '' , password : '' ,
339
- } ,
340
- errors : {
341
- emailOrUsername : '' , password : '' ,
342
- } ,
343
- } ,
344
- loginErrorCode : null ,
345
- loginErrorContext : { } ,
346
- loginResult : { } ,
347
- shouldBackupState : false ,
348
- showResetPasswordSuccessBanner : false ,
349
- submitState : DEFAULT_STATE ,
350
- thirdPartyAuthApiStatus : PENDING_STATE ,
351
- thirdPartyAuthContext : {
352
- currentProvider : null ,
353
- errorMessage : null ,
354
- finishAuthUrl : null ,
355
- providers : [ ] ,
356
- secondaryProviders : [ ] ,
357
- } ,
358
- } ;
359
-
360
- export default connect (
361
- mapStateToProps ,
362
- {
363
- backupFormState : backupLoginFormBegin ,
364
- dismissPasswordResetBanner,
365
- loginRequest,
366
- getTPADataFromBackend : getThirdPartyAuthContext ,
367
- } ,
368
- ) ( LoginPage ) ;
318
+ export default LoginPage ;
0 commit comments