Make ForgotPassword UX slightly more user friendly
This commit is contained in:
parent
90a6f251c7
commit
b9604d1fb5
2 changed files with 31 additions and 3 deletions
|
@ -96,3 +96,10 @@ div.mx_AccessibleButton_kind_link.mx_Login_forgot {
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.mx_Login--spinner {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
align-content: center;
|
||||||
|
padding: 14px;
|
||||||
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||||
import { PASSWORD_MIN_SCORE } from '../../views/auth/RegistrationForm';
|
import { PASSWORD_MIN_SCORE } from '../../views/auth/RegistrationForm';
|
||||||
|
|
||||||
import { IValidationResult } from "../../views/elements/Validation";
|
import { IValidationResult } from "../../views/elements/Validation";
|
||||||
|
import InlineSpinner from '../../views/elements/InlineSpinner';
|
||||||
|
|
||||||
enum Phase {
|
enum Phase {
|
||||||
// Show the forgot password inputs
|
// Show the forgot password inputs
|
||||||
|
@ -66,13 +67,14 @@ interface IState {
|
||||||
serverDeadError: string;
|
serverDeadError: string;
|
||||||
|
|
||||||
passwordFieldValid: boolean;
|
passwordFieldValid: boolean;
|
||||||
|
currentHttpRequest?: Promise<any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@replaceableComponent("structures.auth.ForgotPassword")
|
@replaceableComponent("structures.auth.ForgotPassword")
|
||||||
export default class ForgotPassword extends React.Component<IProps, IState> {
|
export default class ForgotPassword extends React.Component<IProps, IState> {
|
||||||
private reset: PasswordReset;
|
private reset: PasswordReset;
|
||||||
|
|
||||||
state = {
|
state: IState = {
|
||||||
phase: Phase.Forgot,
|
phase: Phase.Forgot,
|
||||||
email: "",
|
email: "",
|
||||||
password: "",
|
password: "",
|
||||||
|
@ -148,8 +150,10 @@ export default class ForgotPassword extends React.Component<IProps, IState> {
|
||||||
console.error("onVerify called before submitPasswordReset!");
|
console.error("onVerify called before submitPasswordReset!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (this.state.currentHttpRequest) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.reset.checkEmailLinkClicked();
|
await this.handleHttpRequest(this.reset.checkEmailLinkClicked());
|
||||||
this.setState({ phase: Phase.Done });
|
this.setState({ phase: Phase.Done });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.showErrorDialog(err.message);
|
this.showErrorDialog(err.message);
|
||||||
|
@ -158,9 +162,10 @@ export default class ForgotPassword extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
private onSubmitForm = async (ev: React.FormEvent): Promise<void> => {
|
private onSubmitForm = async (ev: React.FormEvent): Promise<void> => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
if (this.state.currentHttpRequest) return;
|
||||||
|
|
||||||
// refresh the server errors, just in case the server came back online
|
// refresh the server errors, just in case the server came back online
|
||||||
await this.checkServerLiveliness(this.props.serverConfig);
|
await this.handleHttpRequest(this.checkServerLiveliness(this.props.serverConfig));
|
||||||
|
|
||||||
await this['password_field'].validate({ allowEmpty: false });
|
await this['password_field'].validate({ allowEmpty: false });
|
||||||
|
|
||||||
|
@ -221,6 +226,17 @@ export default class ForgotPassword extends React.Component<IProps, IState> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private handleHttpRequest<T = unknown>(request: Promise<T>): Promise<T> {
|
||||||
|
this.setState({
|
||||||
|
currentHttpRequest: request,
|
||||||
|
});
|
||||||
|
return request.finally(() => {
|
||||||
|
this.setState({
|
||||||
|
currentHttpRequest: undefined,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
renderForgot() {
|
renderForgot() {
|
||||||
const Field = sdk.getComponent('elements.Field');
|
const Field = sdk.getComponent('elements.Field');
|
||||||
|
|
||||||
|
@ -320,6 +336,9 @@ export default class ForgotPassword extends React.Component<IProps, IState> {
|
||||||
type="button"
|
type="button"
|
||||||
onClick={this.onVerify}
|
onClick={this.onVerify}
|
||||||
value={_t('I have verified my email address')} />
|
value={_t('I have verified my email address')} />
|
||||||
|
{ this.state.currentHttpRequest && (
|
||||||
|
<div className="mx_Login--spinner"><InlineSpinner w={64} h={64} /></div>)
|
||||||
|
}
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,6 +376,8 @@ export default class ForgotPassword extends React.Component<IProps, IState> {
|
||||||
case Phase.Done:
|
case Phase.Done:
|
||||||
resetPasswordJsx = this.renderDone();
|
resetPasswordJsx = this.renderDone();
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
resetPasswordJsx = <div className="mx_Login--spinner"><InlineSpinner w={64} h={64} /></div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
Loading…
Reference in a new issue