diff --git a/src/webapp.jsx b/src/webapp.jsx index 01629795..2c579ebc 100644 --- a/src/webapp.jsx +++ b/src/webapp.jsx @@ -1270,7 +1270,8 @@ class LoginView extends React.Component {
- + + Forgot password?
@@ -1382,7 +1383,7 @@ class CreateAccountView extends React.PureComponent {
- +
@@ -1458,6 +1459,51 @@ class AvatarUpload extends React.Component { }; /* END Account registration */ + +/* BEGIN PasswordResetView: a password reset form */ +class PasswordResetView extends React.PureComponent { + constructor(props) { + super(props); + + this.state = { + email: '', + }; + + this.handleSubmit = this.handleSubmit.bind(this); + this.handleEmailChange = this.handleEmailChange.bind(this); + } + + handleSubmit(e) { + e.preventDefault(); + this.props.onSubmit("email", this.state.email.trim()); + } + + handleEmailChange(e) { + this.setState({email: e.target.value}); + } + + render() { + return ( +
+

Email with instructions for resetting your password will be sent + to the following email address:

+ +
+ +
+
+ ); + } +} + +/* END PasswordResetView */ + + /* BEGIN Tinode config panel */ class SettingsView extends React.PureComponent { constructor(props) { @@ -1622,6 +1668,10 @@ class SidepanelView extends React.Component { title = "Confirm Credentials"; onCancel = this.props.onCancel; break; + case 'reset': + title = "Reset Password"; + onCancel = this.props.onCancel; + break; default:; }; return ( @@ -1702,6 +1752,9 @@ class SidepanelView extends React.Component { onCancel={this.props.onCancel} onError={this.props.onError} /> : + view === 'reset' ? + : null}
); @@ -4342,6 +4395,7 @@ class TinodeWeb extends React.Component { this.handleHideInfoView = this.handleHideInfoView.bind(this); this.handleMemberUpdateRequest = this.handleMemberUpdateRequest.bind(this); this.handleValidateCredentialsRequest = this.handleValidateCredentialsRequest.bind(this); + this.handlePasswordResetRequest = this.handlePasswordResetRequest.bind(this); } getBlankState() { @@ -4491,7 +4545,7 @@ class TinodeWeb extends React.Component { var hash = parseUrlHash(window.location.hash); if (hash.path && hash.path.length > 0) { // Left-side panel selector. - if (['register','settings','edit','cred','newtpk','contacts',''].includes(hash.path[0])) { + if (['register','settings','edit','cred','reset','newtpk','contacts',''].includes(hash.path[0])) { this.setState({sidePanelSelected: hash.path[0]}); } else { console.log("Unknown sidepanel view", hash.path[0]); @@ -5229,6 +5283,24 @@ class TinodeWeb extends React.Component { this.doLogin(null, null, {meth: cred, resp: code}); } + handlePasswordResetRequest(method, value) { + if (this.tinode.isConnected()) { + this.tinode.resetAuthSecret("basic", method, value) + .catch((err) => { + this.handleError(err.message, "err"); + }); + } else { + this.tinode.connect() + .then(() => { + this.tinode.resetAuthSecret("basic", method, value) + }) + .catch((err) => { + // Socket error + this.handleError(err.message, "err"); + }); + } + } + render() { return (
@@ -5286,6 +5358,7 @@ class TinodeWeb extends React.Component { onCancel={this.handleSidepanelCancel} onError={this.handleError} onValidateCredentials={this.handleValidateCredentialsRequest} + onPasswordReset={this.handlePasswordResetRequest} onInitFind={this.tnInitFind} searchResults={this.state.searchResults}