@@ -25,6 +25,9 @@ import {
25
25
FORM_SUBMISSION_ERROR ,
26
26
} from './data/constants' ;
27
27
import { registrationErrorSelector , validationsSelector } from './data/selectors' ;
28
+ import {
29
+ emailRegex , getSuggestionForInvalidEmail , urlRegex , validateCountryField , validateEmailAddress ,
30
+ } from './data/utils' ;
28
31
import messages from './messages' ;
29
32
import RegistrationFailure from './RegistrationFailure' ;
30
33
import { EmailField , UsernameField } from './registrationFields' ;
@@ -36,7 +39,7 @@ import {
36
39
fieldDescriptionSelector ,
37
40
} from '../common-components/data/selectors' ;
38
41
import {
39
- DEFAULT_STATE , REDIRECT ,
42
+ DEFAULT_STATE , LETTER_REGEX , NUMBER_REGEX , REDIRECT , USERNAME_REGEX ,
40
43
} from '../data/constants' ;
41
44
import {
42
45
getAllPossibleQueryParams , setCookie ,
@@ -173,16 +176,76 @@ const EmbeddableRegistrationPage = (props) => {
173
176
}
174
177
} , [ registrationResult , host ] ) ;
175
178
176
- const validateInput = ( fieldName , value , payload , shouldValidateFromBackend ) => {
179
+ const validateInput = ( fieldName , value , payload , shouldValidateFromBackend , shouldSetErrors = true ) => {
180
+ let fieldError = '' ;
181
+
177
182
switch ( fieldName ) {
178
- case 'name' :
179
- if ( value && ! payload . username . trim ( ) && shouldValidateFromBackend ) {
180
- validateFromBackend ( payload ) ;
183
+ case 'name' :
184
+ if ( value && value . match ( urlRegex ) ) {
185
+ fieldError = formatMessage ( messages [ 'name.validation.message' ] ) ;
186
+ } else if ( value && ! payload . username . trim ( ) && shouldValidateFromBackend ) {
187
+ validateFromBackend ( payload ) ;
188
+ }
189
+ break ;
190
+ case 'email' :
191
+ if ( value . length <= 2 ) {
192
+ fieldError = formatMessage ( messages [ 'email.invalid.format.error' ] ) ;
193
+ } else {
194
+ const [ username , domainName ] = value . split ( '@' ) ;
195
+ // Check if email address is invalid. If we have a suggestion for invalid email
196
+ // provide that along with the error message.
197
+ if ( ! emailRegex . test ( value ) ) {
198
+ fieldError = formatMessage ( messages [ 'email.invalid.format.error' ] ) ;
199
+ setEmailSuggestion ( {
200
+ suggestion : getSuggestionForInvalidEmail ( domainName , username ) ,
201
+ type : 'error' ,
202
+ } ) ;
203
+ } else {
204
+ const response = validateEmailAddress ( value , username , domainName ) ;
205
+ if ( response . hasError ) {
206
+ fieldError = formatMessage ( messages [ 'email.invalid.format.error' ] ) ;
207
+ delete response . hasError ;
208
+ }
209
+ setEmailSuggestion ( { ...response } ) ;
181
210
}
182
- break ;
183
- default :
184
- break ;
211
+ }
212
+ break ;
213
+ case 'username' :
214
+ if ( ! value . match ( USERNAME_REGEX ) ) {
215
+ fieldError = formatMessage ( messages [ 'username.format.validation.message' ] ) ;
216
+ }
217
+ break ;
218
+ case 'password' :
219
+ if ( ! value || ! LETTER_REGEX . test ( value ) || ! NUMBER_REGEX . test ( value ) || value . length < 8 ) {
220
+ fieldError = formatMessage ( messages [ 'password.validation.message' ] ) ;
221
+ }
222
+ break ;
223
+ case 'country' :
224
+ if ( flags . showConfigurableEdxFields || flags . showConfigurableRegistrationFields ) {
225
+ const {
226
+ countryCode, displayValue, error,
227
+ } = validateCountryField ( value . trim ( ) , countryList , formatMessage ( messages [ 'empty.country.field.error' ] ) ) ;
228
+ fieldError = error ;
229
+ setConfigurableFormFields ( prevState => ( { ...prevState , country : { countryCode, displayValue } } ) ) ;
230
+ }
231
+ break ;
232
+ default :
233
+ if ( flags . showConfigurableRegistrationFields ) {
234
+ if ( ! value && fieldDescriptions [ fieldName ] ?. error_message ) {
235
+ fieldError = fieldDescriptions [ fieldName ] . error_message ;
236
+ } else if ( fieldName === 'confirm_email' && formFields . email && value !== formFields . email ) {
237
+ fieldError = formatMessage ( messages [ 'email.do.not.match' ] ) ;
238
+ }
239
+ }
240
+ break ;
185
241
}
242
+ if ( shouldSetErrors && fieldError ) {
243
+ setErrors ( prevErrors => ( {
244
+ ...prevErrors ,
245
+ [ fieldName ] : fieldError ,
246
+ } ) ) ;
247
+ }
248
+ return fieldError ;
186
249
} ;
187
250
188
251
const isFormValid = ( payload ) => {
@@ -226,6 +289,10 @@ const EmbeddableRegistrationPage = (props) => {
226
289
event . preventDefault ( ) ;
227
290
setErrors ( prevErrors => ( { ...prevErrors , [ fieldName ] : '' } ) ) ;
228
291
switch ( fieldName ) {
292
+ case 'email' :
293
+ setFormFields ( prevState => ( { ...prevState , email : emailSuggestion . suggestion } ) ) ;
294
+ setEmailSuggestion ( { suggestion : '' , type : '' } ) ;
295
+ break ;
229
296
case 'username' :
230
297
setFormFields ( prevState => ( { ...prevState , username : suggestion } ) ) ;
231
298
props . resetUsernameSuggestions ( ) ;
@@ -267,8 +334,12 @@ const EmbeddableRegistrationPage = (props) => {
267
334
value ,
268
335
{ name : formFields . name , username : formFields . username , form_field_key : name } ,
269
336
! validationApiRateLimited ,
337
+ false ,
270
338
) ;
271
339
}
340
+ if ( name === 'email' ) {
341
+ validateInput ( name , value , null , ! validationApiRateLimited , false ) ;
342
+ }
272
343
} ;
273
344
274
345
const handleOnFocus = ( event ) => {
@@ -294,7 +365,6 @@ const EmbeddableRegistrationPage = (props) => {
294
365
e . preventDefault ( ) ;
295
366
const totalRegistrationTime = ( Date . now ( ) - formStartTime ) / 1000 ;
296
367
let payload = { ...formFields } ;
297
-
298
368
if ( ! isFormValid ( payload ) ) {
299
369
setErrorCode ( prevState => ( { type : FORM_SUBMISSION_ERROR , count : prevState . count + 1 } ) ) ;
300
370
return ;
@@ -307,12 +377,20 @@ const EmbeddableRegistrationPage = (props) => {
307
377
payload [ fieldName ] = configurableFormFields [ fieldName ] ;
308
378
}
309
379
} ) ;
310
-
311
380
// Don't send the marketing email opt-in value if the flag is turned off
312
381
if ( ! flags . showMarketingEmailOptInCheckbox ) {
313
382
delete payload . marketingEmailsOptIn ;
314
383
}
315
-
384
+ let isValid = true ;
385
+ Object . entries ( payload ) . forEach ( ( [ key , value ] ) => {
386
+ if ( validateInput ( key , value , payload , false , true ) !== '' ) {
387
+ isValid = false ;
388
+ }
389
+ } ) ;
390
+ if ( ! isValid ) {
391
+ setErrorCode ( prevState => ( { type : FORM_SUBMISSION_ERROR , count : prevState . count + 1 } ) ) ;
392
+ return ;
393
+ }
316
394
payload = snakeCaseObject ( payload ) ;
317
395
payload . totalRegistrationTime = totalRegistrationTime ;
318
396
@@ -350,6 +428,7 @@ const EmbeddableRegistrationPage = (props) => {
350
428
handleChange = { handleOnChange }
351
429
handleBlur = { handleOnBlur }
352
430
handleFocus = { handleOnFocus }
431
+ handleSuggestionClick = { ( e ) => handleSuggestionClick ( e , 'email' ) }
353
432
handleOnClose = { handleEmailSuggestionClosed }
354
433
emailSuggestion = { emailSuggestion }
355
434
errorMessage = { errors . email }
0 commit comments