Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
Weblate 2018-06-25 13:29:14 +00:00
commit bc7858193b
3 changed files with 76 additions and 15 deletions

View file

@ -93,6 +93,13 @@ module.exports = React.createClass({
this._unmounted = true; this._unmounted = true;
}, },
onPasswordLoginError: function(errorText) {
this.setState({
errorText,
loginIncorrect: Boolean(errorText),
});
},
onPasswordLogin: function(username, phoneCountry, phoneNumber, password) { onPasswordLogin: function(username, phoneCountry, phoneNumber, password) {
this.setState({ this.setState({
busy: true, busy: true,
@ -357,6 +364,7 @@ module.exports = React.createClass({
return ( return (
<PasswordLogin <PasswordLogin
onSubmit={this.onPasswordLogin} onSubmit={this.onPasswordLogin}
onError={this.onPasswordLoginError}
initialUsername={this.state.username} initialUsername={this.state.username}
initialPhoneCountry={this.state.phoneCountry} initialPhoneCountry={this.state.phoneCountry}
initialPhoneNumber={this.state.phoneNumber} initialPhoneNumber={this.state.phoneNumber}

View file

@ -28,6 +28,7 @@ import SdkConfig from '../../../SdkConfig';
*/ */
class PasswordLogin extends React.Component { class PasswordLogin extends React.Component {
static defaultProps = { static defaultProps = {
onError: function() {},
onUsernameChanged: function() {}, onUsernameChanged: function() {},
onPasswordChanged: function() {}, onPasswordChanged: function() {},
onPhoneCountryChanged: function() {}, onPhoneCountryChanged: function() {},
@ -56,33 +57,64 @@ class PasswordLogin extends React.Component {
this.onPhoneCountryChanged = this.onPhoneCountryChanged.bind(this); this.onPhoneCountryChanged = this.onPhoneCountryChanged.bind(this);
this.onPhoneNumberChanged = this.onPhoneNumberChanged.bind(this); this.onPhoneNumberChanged = this.onPhoneNumberChanged.bind(this);
this.onPasswordChanged = this.onPasswordChanged.bind(this); this.onPasswordChanged = this.onPasswordChanged.bind(this);
this.isLoginEmpty = this.isLoginEmpty.bind(this);
} }
componentWillMount() { componentWillMount() {
this._passwordField = null; this._passwordField = null;
this._loginField = null;
} }
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
if (!this.props.loginIncorrect && nextProps.loginIncorrect) { if (!this.props.loginIncorrect && nextProps.loginIncorrect) {
field_input_incorrect(this._passwordField); field_input_incorrect(this.isLoginEmpty() ? this._loginField : this._passwordField);
} }
} }
onSubmitForm(ev) { onSubmitForm(ev) {
ev.preventDefault(); ev.preventDefault();
if (this.state.loginType === PasswordLogin.LOGIN_FIELD_PHONE) {
this.props.onSubmit( let username = ''; // XXX: Synapse breaks if you send null here:
'', // XXX: Synapse breaks if you send null here: let phoneCountry = null;
this.state.phoneCountry, let phoneNumber = null;
this.state.phoneNumber, let error;
this.state.password,
); switch (this.state.loginType) {
case PasswordLogin.LOGIN_FIELD_EMAIL:
username = this.state.username;
if (!username) {
error = _t('The email field must not be blank.');
}
break;
case PasswordLogin.LOGIN_FIELD_MXID:
username = this.state.username;
if (!username) {
error = _t('The user name field must not be blank.');
}
break;
case PasswordLogin.LOGIN_FIELD_PHONE:
phoneCountry = this.state.phoneCountry;
phoneNumber = this.state.phoneNumber;
if (!phoneNumber) {
error = _t('The phone number field must not be blank.');
}
break;
}
if (error) {
this.props.onError(error);
return; return;
} }
if (!this.state.password) {
this.props.onError(_t('The password field must not be blank.'));
return;
}
this.props.onSubmit( this.props.onSubmit(
this.state.username, username,
null, phoneCountry,
null, phoneNumber,
this.state.password, this.state.password,
); );
} }
@ -93,6 +125,7 @@ class PasswordLogin extends React.Component {
} }
onLoginTypeChange(loginType) { onLoginTypeChange(loginType) {
this.props.onError(null); // send a null error to clear any error messages
this.setState({ this.setState({
loginType: loginType, loginType: loginType,
username: "", // Reset because email and username use the same state username: "", // Reset because email and username use the same state
@ -126,8 +159,10 @@ class PasswordLogin extends React.Component {
switch (loginType) { switch (loginType) {
case PasswordLogin.LOGIN_FIELD_EMAIL: case PasswordLogin.LOGIN_FIELD_EMAIL:
classes.mx_Login_email = true; classes.mx_Login_email = true;
classes.error = this.props.loginIncorrect && !this.state.username;
return <input return <input
className={classNames(classes)} className={classNames(classes)}
ref={(e) => {this._loginField = e;}}
key="email_input" key="email_input"
type="text" type="text"
name="username" // make it a little easier for browser's remember-password name="username" // make it a little easier for browser's remember-password
@ -139,8 +174,10 @@ class PasswordLogin extends React.Component {
/>; />;
case PasswordLogin.LOGIN_FIELD_MXID: case PasswordLogin.LOGIN_FIELD_MXID:
classes.mx_Login_username = true; classes.mx_Login_username = true;
classes.error = this.props.loginIncorrect && !this.state.username;
return <input return <input
className={classNames(classes)} className={classNames(classes)}
ref={(e) => {this._loginField = e;}}
key="username_input" key="username_input"
type="text" type="text"
name="username" // make it a little easier for browser's remember-password name="username" // make it a little easier for browser's remember-password
@ -153,14 +190,14 @@ class PasswordLogin extends React.Component {
autoFocus autoFocus
disabled={disabled} disabled={disabled}
/>; />;
case PasswordLogin.LOGIN_FIELD_PHONE: case PasswordLogin.LOGIN_FIELD_PHONE: {
const CountryDropdown = sdk.getComponent('views.login.CountryDropdown'); const CountryDropdown = sdk.getComponent('views.login.CountryDropdown');
classes.mx_Login_phoneNumberField = true; classes.mx_Login_phoneNumberField = true;
classes.mx_Login_field_has_prefix = true; classes.mx_Login_field_has_prefix = true;
classes.error = this.props.loginIncorrect && !this.state.phoneNumber;
return <div className="mx_Login_phoneSection"> return <div className="mx_Login_phoneSection">
<CountryDropdown <CountryDropdown
className="mx_Login_phoneCountry mx_Login_field_prefix" className="mx_Login_phoneCountry mx_Login_field_prefix"
ref="phone_country"
onOptionChange={this.onPhoneCountryChanged} onOptionChange={this.onPhoneCountryChanged}
value={this.state.phoneCountry} value={this.state.phoneCountry}
isSmall={true} isSmall={true}
@ -169,7 +206,7 @@ class PasswordLogin extends React.Component {
/> />
<input <input
className={classNames(classes)} className={classNames(classes)}
ref="phoneNumber" ref={(e) => {this._loginField = e;}}
key="phone_input" key="phone_input"
type="text" type="text"
name="phoneNumber" name="phoneNumber"
@ -182,6 +219,17 @@ class PasswordLogin extends React.Component {
</div>; </div>;
} }
} }
}
isLoginEmpty() {
switch (this.state.loginType) {
case PasswordLogin.LOGIN_FIELD_EMAIL:
case PasswordLogin.LOGIN_FIELD_MXID:
return !this.state.username;
case PasswordLogin.LOGIN_FIELD_PHONE:
return !this.state.phoneCountry || !this.state.phoneNumber;
}
}
render() { render() {
let forgotPasswordJsx; let forgotPasswordJsx;
@ -207,7 +255,7 @@ class PasswordLogin extends React.Component {
const pwFieldClass = classNames({ const pwFieldClass = classNames({
mx_Login_field: true, mx_Login_field: true,
mx_Login_field_disabled: matrixIdText === '', mx_Login_field_disabled: matrixIdText === '',
error: this.props.loginIncorrect, error: this.props.loginIncorrect && !this.isLoginEmpty(), // only error password if error isn't top field
}); });
const Dropdown = sdk.getComponent('elements.Dropdown'); const Dropdown = sdk.getComponent('elements.Dropdown');
@ -258,6 +306,7 @@ PasswordLogin.LOGIN_FIELD_PHONE = "login_field_phone";
PasswordLogin.propTypes = { PasswordLogin.propTypes = {
onSubmit: PropTypes.func.isRequired, // fn(username, password) onSubmit: PropTypes.func.isRequired, // fn(username, password)
onError: PropTypes.func,
onForgotPasswordClick: PropTypes.func, // fn() onForgotPasswordClick: PropTypes.func, // fn()
initialUsername: PropTypes.string, initialUsername: PropTypes.string,
initialPhoneCountry: PropTypes.string, initialPhoneCountry: PropTypes.string,

View file

@ -616,6 +616,10 @@
"Code": "Code", "Code": "Code",
"Start authentication": "Start authentication", "Start authentication": "Start authentication",
"powered by Matrix": "powered by Matrix", "powered by Matrix": "powered by Matrix",
"The email field must not be blank.": "The email field must not be blank.",
"The user name field must not be blank.": "The user name field must not be blank.",
"The phone number field must not be blank.": "The phone number field must not be blank.",
"The password field must not be blank.": "The password field must not be blank.",
"Username on %(hs)s": "Username on %(hs)s", "Username on %(hs)s": "Username on %(hs)s",
"User name": "User name", "User name": "User name",
"Mobile phone number": "Mobile phone number", "Mobile phone number": "Mobile phone number",