mirror of https://github.com/vector-im/riot-web
Merge pull request #2672 from jryans/password-validation
Report validity state of all registration fields on any changepull/21833/head
commit
426bdafe22
|
@ -58,6 +58,10 @@ limitations under the License.
|
||||||
background-color: $authpage-body-bg-color;
|
background-color: $authpage-body-bg-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_AuthBody input.error {
|
||||||
|
color: $warning-color;
|
||||||
|
}
|
||||||
|
|
||||||
.mx_AuthBody_editServerDetails {
|
.mx_AuthBody_editServerDetails {
|
||||||
padding-left: 1em;
|
padding-left: 1em;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
|
|
@ -308,7 +308,19 @@ module.exports = React.createClass({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
onFormValidationFailed: function(errCode) {
|
onFormValidationChange: function(fieldErrors) {
|
||||||
|
// `fieldErrors` is an object mapping field IDs to error codes when there is an
|
||||||
|
// error or `null` for no error, so the values array will be something like:
|
||||||
|
// `[ null, "RegistrationForm.ERR_PASSWORD_MISSING", null]`
|
||||||
|
// Find the first non-null error code and show that.
|
||||||
|
const errCode = Object.values(fieldErrors).find(value => !!value);
|
||||||
|
if (!errCode) {
|
||||||
|
this.setState({
|
||||||
|
errorText: null,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let errMsg;
|
let errMsg;
|
||||||
switch (errCode) {
|
switch (errCode) {
|
||||||
case "RegistrationForm.ERR_PASSWORD_MISSING":
|
case "RegistrationForm.ERR_PASSWORD_MISSING":
|
||||||
|
@ -510,7 +522,7 @@ module.exports = React.createClass({
|
||||||
defaultPhoneNumber={this.state.formVals.phoneNumber}
|
defaultPhoneNumber={this.state.formVals.phoneNumber}
|
||||||
defaultPassword={this.state.formVals.password}
|
defaultPassword={this.state.formVals.password}
|
||||||
minPasswordLength={MIN_PASSWORD_LENGTH}
|
minPasswordLength={MIN_PASSWORD_LENGTH}
|
||||||
onError={this.onFormValidationFailed}
|
onValidationChange={this.onFormValidationChange}
|
||||||
onRegisterClick={this.onFormSubmit}
|
onRegisterClick={this.onFormSubmit}
|
||||||
onEditServerDetailsClick={onEditServerDetailsClick}
|
onEditServerDetailsClick={onEditServerDetailsClick}
|
||||||
flows={this.state.flows}
|
flows={this.state.flows}
|
||||||
|
|
|
@ -46,7 +46,7 @@ module.exports = React.createClass({
|
||||||
defaultUsername: PropTypes.string,
|
defaultUsername: PropTypes.string,
|
||||||
defaultPassword: PropTypes.string,
|
defaultPassword: PropTypes.string,
|
||||||
minPasswordLength: PropTypes.number,
|
minPasswordLength: PropTypes.number,
|
||||||
onError: PropTypes.func,
|
onValidationChange: PropTypes.func,
|
||||||
onRegisterClick: PropTypes.func.isRequired, // onRegisterClick(Object) => ?Promise
|
onRegisterClick: PropTypes.func.isRequired, // onRegisterClick(Object) => ?Promise
|
||||||
onEditServerDetailsClick: PropTypes.func,
|
onEditServerDetailsClick: PropTypes.func,
|
||||||
flows: PropTypes.arrayOf(PropTypes.object).isRequired,
|
flows: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
|
@ -60,15 +60,14 @@ module.exports = React.createClass({
|
||||||
getDefaultProps: function() {
|
getDefaultProps: function() {
|
||||||
return {
|
return {
|
||||||
minPasswordLength: 6,
|
minPasswordLength: 6,
|
||||||
onError: function(e) {
|
onValidationChange: console.error,
|
||||||
console.error(e);
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
return {
|
return {
|
||||||
fieldValid: {},
|
// Field error codes by field ID
|
||||||
|
fieldErrors: {},
|
||||||
// The ISO2 country code selected in the phone number entry
|
// The ISO2 country code selected in the phone number entry
|
||||||
phoneCountry: this.props.defaultPhoneCountry,
|
phoneCountry: this.props.defaultPhoneCountry,
|
||||||
};
|
};
|
||||||
|
@ -81,12 +80,12 @@ module.exports = React.createClass({
|
||||||
// the error that ends up being displayed
|
// the error that ends up being displayed
|
||||||
// is the one from the first invalid field.
|
// is the one from the first invalid field.
|
||||||
// It's not super ideal that this just calls
|
// It's not super ideal that this just calls
|
||||||
// onError once for each invalid field.
|
// onValidationChange once for each invalid field.
|
||||||
|
this.validateField(FIELD_PHONE_NUMBER, ev.type);
|
||||||
|
this.validateField(FIELD_EMAIL, ev.type);
|
||||||
this.validateField(FIELD_PASSWORD_CONFIRM, ev.type);
|
this.validateField(FIELD_PASSWORD_CONFIRM, ev.type);
|
||||||
this.validateField(FIELD_PASSWORD, ev.type);
|
this.validateField(FIELD_PASSWORD, ev.type);
|
||||||
this.validateField(FIELD_USERNAME, ev.type);
|
this.validateField(FIELD_USERNAME, ev.type);
|
||||||
this.validateField(FIELD_PHONE_NUMBER, ev.type);
|
|
||||||
this.validateField(FIELD_EMAIL, ev.type);
|
|
||||||
|
|
||||||
const self = this;
|
const self = this;
|
||||||
if (this.allFieldsValid()) {
|
if (this.allFieldsValid()) {
|
||||||
|
@ -134,9 +133,9 @@ module.exports = React.createClass({
|
||||||
* @returns {boolean} true if all fields were valid last time they were validated.
|
* @returns {boolean} true if all fields were valid last time they were validated.
|
||||||
*/
|
*/
|
||||||
allFieldsValid: function() {
|
allFieldsValid: function() {
|
||||||
const keys = Object.keys(this.state.fieldValid);
|
const keys = Object.keys(this.state.fieldErrors);
|
||||||
for (let i = 0; i < keys.length; ++i) {
|
for (let i = 0; i < keys.length; ++i) {
|
||||||
if (this.state.fieldValid[keys[i]] == false) {
|
if (this.state.fieldErrors[keys[i]]) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -206,21 +205,29 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FIELD_PASSWORD_CONFIRM:
|
case FIELD_PASSWORD_CONFIRM:
|
||||||
this.markFieldValid(
|
if (allowEmpty && pwd2 === "") {
|
||||||
fieldID, pwd1 == pwd2,
|
this.markFieldValid(fieldID, true);
|
||||||
"RegistrationForm.ERR_PASSWORD_MISMATCH",
|
} else {
|
||||||
);
|
this.markFieldValid(
|
||||||
|
fieldID, pwd1 == pwd2,
|
||||||
|
"RegistrationForm.ERR_PASSWORD_MISMATCH",
|
||||||
|
);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
markFieldValid: function(fieldID, val, errorCode) {
|
markFieldValid: function(fieldID, valid, errorCode) {
|
||||||
const fieldValid = this.state.fieldValid;
|
const { fieldErrors } = this.state;
|
||||||
fieldValid[fieldID] = val;
|
if (valid) {
|
||||||
this.setState({fieldValid: fieldValid});
|
fieldErrors[fieldID] = null;
|
||||||
if (!val) {
|
} else {
|
||||||
this.props.onError(errorCode);
|
fieldErrors[fieldID] = errorCode;
|
||||||
}
|
}
|
||||||
|
this.setState({
|
||||||
|
fieldErrors,
|
||||||
|
});
|
||||||
|
this.props.onValidationChange(fieldErrors);
|
||||||
},
|
},
|
||||||
|
|
||||||
fieldElementById(fieldID) {
|
fieldElementById(fieldID) {
|
||||||
|
@ -240,7 +247,7 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
_classForField: function(fieldID, ...baseClasses) {
|
_classForField: function(fieldID, ...baseClasses) {
|
||||||
let cls = baseClasses.join(' ');
|
let cls = baseClasses.join(' ');
|
||||||
if (this.state.fieldValid[fieldID] === false) {
|
if (this.state.fieldErrors[fieldID]) {
|
||||||
if (cls) cls += ' ';
|
if (cls) cls += ' ';
|
||||||
cls += 'error';
|
cls += 'error';
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue