request-password-reset.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. import React from 'react'; // jshint ignore:line
  2. import ReactDOM from 'react-dom'; // jshint ignore:line
  3. import misago from 'misago/index';
  4. import Button from 'misago/components/button'; // jshint ignore:line
  5. import Form from 'misago/components/form';
  6. import ajax from 'misago/services/ajax';
  7. import snackbar from 'misago/services/snackbar';
  8. import * as validators from 'misago/utils/validators';
  9. import showBannedPage from 'misago/utils/banned-page';
  10. export class RequestResetForm extends Form {
  11. constructor(props) {
  12. super(props);
  13. this.state = {
  14. 'isLoading': false,
  15. 'email': '',
  16. 'validators': {
  17. 'email': [
  18. validators.email()
  19. ]
  20. }
  21. };
  22. }
  23. clean() {
  24. if (this.isValid()) {
  25. return true;
  26. } else {
  27. snackbar.error(gettext("Enter a valid email address."));
  28. return false;
  29. }
  30. }
  31. send() {
  32. return ajax.post(misago.get('SEND_PASSWORD_RESET_API'), {
  33. 'email': this.state.email
  34. });
  35. }
  36. handleSuccess(apiResponse) {
  37. this.props.callback(apiResponse);
  38. }
  39. handleError(rejection) {
  40. if (['inactive_user', 'inactive_admin'].indexOf(rejection.code) > -1) {
  41. this.props.showInactivePage(rejection);
  42. } else if (rejection.status === 403 && rejection.ban) {
  43. showBannedPage(rejection.ban);
  44. } else {
  45. snackbar.apiError(rejection);
  46. }
  47. }
  48. render() {
  49. /* jshint ignore:start */
  50. return <div className="well well-form well-form-request-password-reset">
  51. <form onSubmit={this.handleSubmit}>
  52. <div className="form-group">
  53. <div className="control-input">
  54. <input type="text" className="form-control"
  55. placeholder={gettext("Your e-mail address")}
  56. disabled={this.state.isLoading}
  57. onChange={this.bindInput('email')}
  58. value={this.state.email} />
  59. </div>
  60. </div>
  61. <Button className="btn-primary btn-block"
  62. loading={this.state.isLoading}>
  63. {gettext("Send link")}
  64. </Button>
  65. </form>
  66. </div>;
  67. /* jshint ignore:end */
  68. }
  69. }
  70. export class LinkSent extends React.Component {
  71. getMessage() {
  72. return interpolate(gettext("Reset password link was sent to %(email)s"), {
  73. email: this.props.user.email
  74. }, true);
  75. }
  76. render() {
  77. /* jshint ignore:start */
  78. return <div className="well well-form well-form-request-password-reset well-done">
  79. <div className="done-message">
  80. <div className="message-icon">
  81. <span className="material-icon">
  82. check
  83. </span>
  84. </div>
  85. <div className="message-body">
  86. <p>
  87. {this.getMessage()}
  88. </p>
  89. </div>
  90. <button type="button" className="btn btn-primary btn-block"
  91. onClick={this.props.callback}>
  92. {gettext("Request another link")}
  93. </button>
  94. </div>
  95. </div>;
  96. /* jshint ignore:end */
  97. }
  98. }
  99. export class AccountInactivePage extends React.Component {
  100. getActivateButton() {
  101. if (this.props.activation === 'inactive_user') {
  102. /* jshint ignore:start */
  103. return <p>
  104. <a href={misago.get('REQUEST_ACTIVATION_URL')}>
  105. {gettext("Activate your account.")}
  106. </a>
  107. </p>;
  108. /* jshint ignore:end */
  109. } else {
  110. return null;
  111. }
  112. }
  113. render() {
  114. /* jshint ignore:start */
  115. return <div className="page page-message page-message-info page-forgotten-password-inactive">
  116. <div className="container">
  117. <div className="message-panel">
  118. <div className="message-icon">
  119. <span className="material-icon">
  120. info_outline
  121. </span>
  122. </div>
  123. <div className="message-body">
  124. <p className="lead">
  125. {gettext("Your account is inactive.")}
  126. </p>
  127. <p>
  128. {this.props.message}
  129. </p>
  130. {this.getActivateButton()}
  131. </div>
  132. </div>
  133. </div>
  134. </div>;
  135. /* jshint ignore:end */
  136. }
  137. }
  138. export default class extends React.Component {
  139. constructor(props) {
  140. super(props);
  141. this.state = {
  142. complete: false
  143. };
  144. }
  145. /* jshint ignore:start */
  146. complete = (apiResponse) => {
  147. this.setState({
  148. complete: apiResponse
  149. });
  150. };
  151. reset = () => {
  152. this.setState({
  153. complete: false
  154. });
  155. };
  156. showInactivePage(apiResponse) {
  157. ReactDOM.render(
  158. <AccountInactivePage activation={apiResponse.code}
  159. message={apiResponse.detail} />,
  160. document.getElementById('page-mount')
  161. );
  162. }
  163. /* jshint ignore:end */
  164. render() {
  165. /* jshint ignore:start */
  166. if (this.state.complete) {
  167. return <LinkSent user={this.state.complete} callback={this.reset} />;
  168. } else {
  169. return <RequestResetForm callback={this.complete}
  170. showInactivePage={this.showInactivePage} />;
  171. };
  172. /* jshint ignore:end */
  173. }
  174. }