Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Login local errors for blank fields #2009

Merged
merged 5 commits into from
Jun 25, 2018
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/components/structures/login/Login.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ module.exports = React.createClass({
this._unmounted = true;
},

onPasswordLoginError: function(errorText) {
this.setState({
errorText,
loginIncorrect: Boolean(errorText),
});
},

onPasswordLogin: function(username, phoneCountry, phoneNumber, password) {
this.setState({
busy: true,
Expand Down Expand Up @@ -357,6 +364,7 @@ module.exports = React.createClass({
return (
<PasswordLogin
onSubmit={this.onPasswordLogin}
onError={this.onPasswordLoginError}
initialUsername={this.state.username}
initialPhoneCountry={this.state.phoneCountry}
initialPhoneNumber={this.state.phoneNumber}
Expand Down
79 changes: 64 additions & 15 deletions src/components/views/login/PasswordLogin.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import SdkConfig from '../../../SdkConfig';
*/
class PasswordLogin extends React.Component {
static defaultProps = {
onError: function() {},
onUsernameChanged: function() {},
onPasswordChanged: function() {},
onPhoneCountryChanged: function() {},
Expand Down Expand Up @@ -56,33 +57,64 @@ class PasswordLogin extends React.Component {
this.onPhoneCountryChanged = this.onPhoneCountryChanged.bind(this);
this.onPhoneNumberChanged = this.onPhoneNumberChanged.bind(this);
this.onPasswordChanged = this.onPasswordChanged.bind(this);
this.isLoginEmpty = this.isLoginEmpty.bind(this);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ftr, I don't think you need to bind this as you're not passing it in as a callback anywhere. Arguably it's clearer if we just always bind component methods though.

}

componentWillMount() {
this._passwordField = null;
this._loginField = null;
}

componentWillReceiveProps(nextProps) {
if (!this.props.loginIncorrect && nextProps.loginIncorrect) {
field_input_incorrect(this._passwordField);
field_input_incorrect(this.isLoginEmpty() ? this._loginField : this._passwordField);
}
}

onSubmitForm(ev) {
ev.preventDefault();
if (this.state.loginType === PasswordLogin.LOGIN_FIELD_PHONE) {
this.props.onSubmit(
'', // XXX: Synapse breaks if you send null here:
this.state.phoneCountry,
this.state.phoneNumber,
this.state.password,
);

let username = ''; // XXX: Synapse breaks if you send null here:
let phoneCountry = null;
let phoneNumber = null;
let error;

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;
}

if (!this.state.password) {
this.props.onError(_t('The password field must not be blank.'));
return;
}

this.props.onSubmit(
this.state.username,
null,
null,
username,
phoneCountry,
phoneNumber,
this.state.password,
);
}
Expand All @@ -93,6 +125,7 @@ class PasswordLogin extends React.Component {
}

onLoginTypeChange(loginType) {
this.props.onError(null); // send a null error to clear any error messages
this.setState({
loginType: loginType,
username: "", // Reset because email and username use the same state
Expand Down Expand Up @@ -126,8 +159,10 @@ class PasswordLogin extends React.Component {
switch (loginType) {
case PasswordLogin.LOGIN_FIELD_EMAIL:
classes.mx_Login_email = true;
classes.error = this.props.loginIncorrect && !this.state.username;
return <input
className={classNames(classes)}
ref={(e) => {this._loginField = e;}}
key="email_input"
type="text"
name="username" // make it a little easier for browser's remember-password
Expand All @@ -139,8 +174,10 @@ class PasswordLogin extends React.Component {
/>;
case PasswordLogin.LOGIN_FIELD_MXID:
classes.mx_Login_username = true;
classes.error = this.props.loginIncorrect && !this.state.username;
return <input
className={classNames(classes)}
ref={(e) => {this._loginField = e;}}
key="username_input"
type="text"
name="username" // make it a little easier for browser's remember-password
Expand All @@ -153,14 +190,14 @@ class PasswordLogin extends React.Component {
autoFocus
disabled={disabled}
/>;
case PasswordLogin.LOGIN_FIELD_PHONE:
case PasswordLogin.LOGIN_FIELD_PHONE: {
const CountryDropdown = sdk.getComponent('views.login.CountryDropdown');
classes.mx_Login_phoneNumberField = true;
classes.mx_Login_field_has_prefix = true;
classes.error = this.props.loginIncorrect && !this.state.phoneNumber;
return <div className="mx_Login_phoneSection">
<CountryDropdown
className="mx_Login_phoneCountry mx_Login_field_prefix"
ref="phone_country"
onOptionChange={this.onPhoneCountryChanged}
value={this.state.phoneCountry}
isSmall={true}
Expand All @@ -169,7 +206,7 @@ class PasswordLogin extends React.Component {
/>
<input
className={classNames(classes)}
ref="phoneNumber"
ref={(e) => {this._loginField = e;}}
key="phone_input"
type="text"
name="phoneNumber"
Expand All @@ -180,6 +217,17 @@ class PasswordLogin extends React.Component {
disabled={disabled}
/>
</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;
}
}

Expand Down Expand Up @@ -207,7 +255,7 @@ class PasswordLogin extends React.Component {
const pwFieldClass = classNames({
mx_Login_field: true,
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');
Expand Down Expand Up @@ -258,6 +306,7 @@ PasswordLogin.LOGIN_FIELD_PHONE = "login_field_phone";

PasswordLogin.propTypes = {
onSubmit: PropTypes.func.isRequired, // fn(username, password)
onError: PropTypes.func,
onForgotPasswordClick: PropTypes.func, // fn()
initialUsername: PropTypes.string,
initialPhoneCountry: PropTypes.string,
Expand Down
1 change: 0 additions & 1 deletion src/i18n/strings/el.json
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,6 @@
"%(widgetName)s widget removed by %(senderName)s": "Το widget %(widgetName)s αφαιρέθηκε από τον/την %(senderName)s",
"%(names)s and %(count)s others are typing|other": "Ο/Η %(names)s και άλλοι/ες %(count)s πληκτρολογούν",
"%(names)s and %(count)s others are typing|one": "Ο/Η %(names)s και άλλος ένας πληκτρολογούν",
"Message Replies": "Απαντήσεις",
"Message Pinning": "Καρφίτσωμα Μηνυμάτων",
"Hide avatar changes": "Απόκρυψη αλλαγών εικονιδίων χρηστών",
"Hide display name changes": "Απόκρυψη αλλαγών εμφανιζόμενων ονομάτων",
Expand Down
64 changes: 34 additions & 30 deletions src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@
"The file '%(fileName)s' failed to upload": "The file '%(fileName)s' failed to upload",
"The file '%(fileName)s' exceeds this home server's size limit for uploads": "The file '%(fileName)s' exceeds this home server's size limit for uploads",
"Upload Failed": "Upload Failed",
"Failure to create room": "Failure to create room",
"Server may be unavailable, overloaded, or you hit a bug.": "Server may be unavailable, overloaded, or you hit a bug.",
"Send anyway": "Send anyway",
"Send": "Send",
"Sun": "Sun",
"Mon": "Mon",
"Tue": "Tue",
Expand Down Expand Up @@ -81,6 +85,7 @@
"Failed to invite users to community": "Failed to invite users to community",
"Failed to invite users to %(groupId)s": "Failed to invite users to %(groupId)s",
"Failed to add the following rooms to %(groupId)s:": "Failed to add the following rooms to %(groupId)s:",
"Unnamed Room": "Unnamed Room",
"Riot does not have permission to send you notifications - please check your browser settings": "Riot does not have permission to send you notifications - please check your browser settings",
"Riot was not given permission to send notifications - please try again": "Riot was not given permission to send notifications - please try again",
"Unable to enable Notifications": "Unable to enable Notifications",
Expand Down Expand Up @@ -194,11 +199,6 @@
"%(names)s and %(count)s others are typing|other": "%(names)s and %(count)s others are typing",
"%(names)s and %(count)s others are typing|one": "%(names)s and one other is typing",
"%(names)s and %(lastPerson)s are typing": "%(names)s and %(lastPerson)s are typing",
"Failure to create room": "Failure to create room",
"Server may be unavailable, overloaded, or you hit a bug.": "Server may be unavailable, overloaded, or you hit a bug.",
"Send anyway": "Send anyway",
"Send": "Send",
"Unnamed Room": "Unnamed Room",
"Your browser does not support the required cryptography extensions": "Your browser does not support the required cryptography extensions",
"Not a valid Riot keyfile": "Not a valid Riot keyfile",
"Authentication check failed: incorrect password?": "Authentication check failed: incorrect password?",
Expand Down Expand Up @@ -311,6 +311,29 @@
"Off": "Off",
"On": "On",
"Noisy": "Noisy",
"Invalid alias format": "Invalid alias format",
"'%(alias)s' is not a valid format for an alias": "'%(alias)s' is not a valid format for an alias",
"Invalid address format": "Invalid address format",
"'%(alias)s' is not a valid format for an address": "'%(alias)s' is not a valid format for an address",
"not specified": "not specified",
"not set": "not set",
"Remote addresses for this room:": "Remote addresses for this room:",
"Addresses": "Addresses",
"The main address for this room is": "The main address for this room is",
"Local addresses for this room:": "Local addresses for this room:",
"This room has no local addresses": "This room has no local addresses",
"New address (e.g. #foo:%(localDomain)s)": "New address (e.g. #foo:%(localDomain)s)",
"Invalid community ID": "Invalid community ID",
"'%(groupId)s' is not a valid community ID": "'%(groupId)s' is not a valid community ID",
"Flair": "Flair",
"Showing flair for these communities:": "Showing flair for these communities:",
"This room is not showing flair for any communities": "This room is not showing flair for any communities",
"New community ID (e.g. +foo:%(localDomain)s)": "New community ID (e.g. +foo:%(localDomain)s)",
"You have <a>enabled</a> URL previews by default.": "You have <a>enabled</a> URL previews by default.",
"You have <a>disabled</a> URL previews by default.": "You have <a>disabled</a> URL previews by default.",
"URL previews are enabled by default for participants in this room.": "URL previews are enabled by default for participants in this room.",
"URL previews are disabled by default for participants in this room.": "URL previews are disabled by default for participants in this room.",
"URL Previews": "URL Previews",
"Cannot add any more widgets": "Cannot add any more widgets",
"The maximum permitted number of widgets have already been added to this room.": "The maximum permitted number of widgets have already been added to this room.",
"Add a widget": "Add a widget",
Expand Down Expand Up @@ -410,11 +433,11 @@
"numbullet": "numbullet",
"Markdown is disabled": "Markdown is disabled",
"Markdown is enabled": "Markdown is enabled",
"Unpin Message": "Unpin Message",
"Jump to message": "Jump to message",
"No pinned messages.": "No pinned messages.",
"Loading...": "Loading...",
"Pinned Messages": "Pinned Messages",
"Unpin Message": "Unpin Message",
"Jump to message": "Jump to message",
"%(duration)ss": "%(duration)ss",
"%(duration)sm": "%(duration)sm",
"%(duration)sh": "%(duration)sh",
Expand Down Expand Up @@ -547,29 +570,6 @@
"Scroll to unread messages": "Scroll to unread messages",
"Jump to first unread message.": "Jump to first unread message.",
"Close": "Close",
"Invalid alias format": "Invalid alias format",
"'%(alias)s' is not a valid format for an alias": "'%(alias)s' is not a valid format for an alias",
"Invalid address format": "Invalid address format",
"'%(alias)s' is not a valid format for an address": "'%(alias)s' is not a valid format for an address",
"not specified": "not specified",
"not set": "not set",
"Remote addresses for this room:": "Remote addresses for this room:",
"Addresses": "Addresses",
"The main address for this room is": "The main address for this room is",
"Local addresses for this room:": "Local addresses for this room:",
"This room has no local addresses": "This room has no local addresses",
"New address (e.g. #foo:%(localDomain)s)": "New address (e.g. #foo:%(localDomain)s)",
"Invalid community ID": "Invalid community ID",
"'%(groupId)s' is not a valid community ID": "'%(groupId)s' is not a valid community ID",
"Flair": "Flair",
"Showing flair for these communities:": "Showing flair for these communities:",
"This room is not showing flair for any communities": "This room is not showing flair for any communities",
"New community ID (e.g. +foo:%(localDomain)s)": "New community ID (e.g. +foo:%(localDomain)s)",
"You have <a>enabled</a> URL previews by default.": "You have <a>enabled</a> URL previews by default.",
"You have <a>disabled</a> URL previews by default.": "You have <a>disabled</a> URL previews by default.",
"URL previews are enabled by default for participants in this room.": "URL previews are enabled by default for participants in this room.",
"URL previews are disabled by default for participants in this room.": "URL previews are disabled by default for participants in this room.",
"URL Previews": "URL Previews",
"Sunday": "Sunday",
"Monday": "Monday",
"Tuesday": "Tuesday",
Expand Down Expand Up @@ -614,6 +614,10 @@
"Code": "Code",
"Start authentication": "Start authentication",
"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",
"User name": "User name",
"Mobile phone number": "Mobile phone number",
Expand Down
1 change: 0 additions & 1 deletion src/i18n/strings/gl.json
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,6 @@
"Authentication check failed: incorrect password?": "Fallou a comprobación de autenticación: contrasinal incorrecto?",
"Failed to join room": "Non se puido unir a sala",
"Message Pinning": "Fixando mensaxe",
"Tag Panel": "Panel de etiquetas",
"Disable Emoji suggestions while typing": "Desactivar a suxestión de Emoji mentres escribe",
"Use compact timeline layout": "Utilizar a disposición compacta da liña temporal",
"Hide removed messages": "Ocultar mensaxes eliminadas",
Expand Down
1 change: 0 additions & 1 deletion src/i18n/strings/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -1175,7 +1175,6 @@
"To continue using the %(homeserverDomain)s homeserver you must review and agree to our terms and conditions.": "Per continuare a usare l'homeserver %(homeserverDomain)s devi leggere e accettare i nostri termini e condizioni.",
"Review terms and conditions": "Leggi i termini e condizioni",
"Muted Users": "Utenti silenziati",
"Message Replies": "Risposte",
"Message Pinning": "Messaggi appuntati",
"Mirror local video feed": "Feed video dai ripetitori locali",
"Replying": "Rispondere",
Expand Down