]> Untitled Git - lemmy.git/blob - ui/src/components/login.tsx
Halfway done with email, not fully working yet.
[lemmy.git] / ui / src / components / login.tsx
1 import { Component, linkEvent } from 'inferno';
2 import { Subscription } from 'rxjs';
3 import { retryWhen, delay, take } from 'rxjs/operators';
4 import {
5   LoginForm,
6   RegisterForm,
7   LoginResponse,
8   UserOperation,
9   PasswordResetForm,
10 } from '../interfaces';
11 import { WebSocketService, UserService } from '../services';
12 import { msgOp } from '../utils';
13 import { i18n } from '../i18next';
14 import { T } from 'inferno-i18next';
15
16 interface State {
17   loginForm: LoginForm;
18   registerForm: RegisterForm;
19   loginLoading: boolean;
20   registerLoading: boolean;
21 }
22
23 export class Login extends Component<any, State> {
24   private subscription: Subscription;
25
26   emptyState: State = {
27     loginForm: {
28       username_or_email: undefined,
29       password: undefined,
30     },
31     registerForm: {
32       username: undefined,
33       password: undefined,
34       password_verify: undefined,
35       admin: false,
36       show_nsfw: false,
37     },
38     loginLoading: false,
39     registerLoading: false,
40   };
41
42   constructor(props: any, context: any) {
43     super(props, context);
44
45     this.state = this.emptyState;
46
47     this.subscription = WebSocketService.Instance.subject
48       .pipe(
49         retryWhen(errors =>
50           errors.pipe(
51             delay(3000),
52             take(10)
53           )
54         )
55       )
56       .subscribe(
57         msg => this.parseMessage(msg),
58         err => console.error(err),
59         () => console.log('complete')
60       );
61   }
62
63   componentWillUnmount() {
64     this.subscription.unsubscribe();
65   }
66
67   componentDidMount() {
68     document.title = `${i18n.t('login')} - ${
69       WebSocketService.Instance.site.name
70     }`;
71   }
72
73   render() {
74     return (
75       <div class="container">
76         <div class="row">
77           <div class="col-12 col-lg-6 mb-4">{this.loginForm()}</div>
78           <div class="col-12 col-lg-6">{this.registerForm()}</div>
79         </div>
80       </div>
81     );
82   }
83
84   loginForm() {
85     return (
86       <div>
87         <form onSubmit={linkEvent(this, this.handleLoginSubmit)}>
88           <h5>Login</h5>
89           <div class="form-group row">
90             <label class="col-sm-2 col-form-label">
91               <T i18nKey="email_or_username">#</T>
92             </label>
93             <div class="col-sm-10">
94               <input
95                 type="text"
96                 class="form-control"
97                 value={this.state.loginForm.username_or_email}
98                 onInput={linkEvent(this, this.handleLoginUsernameChange)}
99                 required
100                 minLength={3}
101               />
102             </div>
103           </div>
104           <div class="form-group row">
105             <label class="col-sm-2 col-form-label">
106               <T i18nKey="password">#</T>
107             </label>
108             <div class="col-sm-10">
109               <input
110                 type="password"
111                 value={this.state.loginForm.password}
112                 onInput={linkEvent(this, this.handleLoginPasswordChange)}
113                 class="form-control"
114                 required
115               />
116               <div
117                 onClick={linkEvent(this, this.handlePasswordReset)}
118                 class="pointer d-inline-block float-right text-muted small font-weight-bold"
119               >
120                 <T i18nKey="forgot_password">#</T>
121               </div>
122             </div>
123           </div>
124           <div class="form-group row">
125             <div class="col-sm-10">
126               <button type="submit" class="btn btn-secondary">
127                 {this.state.loginLoading ? (
128                   <svg class="icon icon-spinner spin">
129                     <use xlinkHref="#icon-spinner"></use>
130                   </svg>
131                 ) : (
132                   i18n.t('login')
133                 )}
134               </button>
135             </div>
136           </div>
137         </form>
138       </div>
139     );
140   }
141   registerForm() {
142     return (
143       <form onSubmit={linkEvent(this, this.handleRegisterSubmit)}>
144         <h5>
145           <T i18nKey="sign_up">#</T>
146         </h5>
147         <div class="form-group row">
148           <label class="col-sm-2 col-form-label">
149             <T i18nKey="username">#</T>
150           </label>
151           <div class="col-sm-10">
152             <input
153               type="text"
154               class="form-control"
155               value={this.state.registerForm.username}
156               onInput={linkEvent(this, this.handleRegisterUsernameChange)}
157               required
158               minLength={3}
159               maxLength={20}
160               pattern="[a-zA-Z0-9_]+"
161             />
162           </div>
163         </div>
164         <div class="form-group row">
165           <label class="col-sm-2 col-form-label">
166             <T i18nKey="email">#</T>
167           </label>
168           <div class="col-sm-10">
169             <input
170               type="email"
171               class="form-control"
172               placeholder={i18n.t('optional')}
173               value={this.state.registerForm.email}
174               onInput={linkEvent(this, this.handleRegisterEmailChange)}
175               minLength={3}
176             />
177           </div>
178         </div>
179         <div class="form-group row">
180           <label class="col-sm-2 col-form-label">
181             <T i18nKey="password">#</T>
182           </label>
183           <div class="col-sm-10">
184             <input
185               type="password"
186               value={this.state.registerForm.password}
187               onInput={linkEvent(this, this.handleRegisterPasswordChange)}
188               class="form-control"
189               required
190             />
191           </div>
192         </div>
193         <div class="form-group row">
194           <label class="col-sm-2 col-form-label">
195             <T i18nKey="verify_password">#</T>
196           </label>
197           <div class="col-sm-10">
198             <input
199               type="password"
200               value={this.state.registerForm.password_verify}
201               onInput={linkEvent(this, this.handleRegisterPasswordVerifyChange)}
202               class="form-control"
203               required
204             />
205           </div>
206         </div>
207         <div class="form-group row">
208           <div class="col-sm-10">
209             <div class="form-check">
210               <input
211                 class="form-check-input"
212                 type="checkbox"
213                 checked={this.state.registerForm.show_nsfw}
214                 onChange={linkEvent(this, this.handleRegisterShowNsfwChange)}
215               />
216               <label class="form-check-label">
217                 <T i18nKey="show_nsfw">#</T>
218               </label>
219             </div>
220           </div>
221         </div>
222         <div class="form-group row">
223           <div class="col-sm-10">
224             <button type="submit" class="btn btn-secondary">
225               {this.state.registerLoading ? (
226                 <svg class="icon icon-spinner spin">
227                   <use xlinkHref="#icon-spinner"></use>
228                 </svg>
229               ) : (
230                 i18n.t('sign_up')
231               )}
232             </button>
233           </div>
234         </div>
235       </form>
236     );
237   }
238
239   handleLoginSubmit(i: Login, event: any) {
240     event.preventDefault();
241     i.state.loginLoading = true;
242     i.setState(i.state);
243     WebSocketService.Instance.login(i.state.loginForm);
244   }
245
246   handleLoginUsernameChange(i: Login, event: any) {
247     i.state.loginForm.username_or_email = event.target.value;
248     i.setState(i.state);
249   }
250
251   handleLoginPasswordChange(i: Login, event: any) {
252     i.state.loginForm.password = event.target.value;
253     i.setState(i.state);
254   }
255
256   handleRegisterSubmit(i: Login, event: any) {
257     event.preventDefault();
258     i.state.registerLoading = true;
259     i.setState(i.state);
260
261     WebSocketService.Instance.register(i.state.registerForm);
262   }
263
264   handleRegisterUsernameChange(i: Login, event: any) {
265     i.state.registerForm.username = event.target.value;
266     i.setState(i.state);
267   }
268
269   handleRegisterEmailChange(i: Login, event: any) {
270     i.state.registerForm.email = event.target.value;
271     i.setState(i.state);
272   }
273
274   handleRegisterPasswordChange(i: Login, event: any) {
275     i.state.registerForm.password = event.target.value;
276     i.setState(i.state);
277   }
278
279   handleRegisterPasswordVerifyChange(i: Login, event: any) {
280     i.state.registerForm.password_verify = event.target.value;
281     i.setState(i.state);
282   }
283
284   handleRegisterShowNsfwChange(i: Login, event: any) {
285     i.state.registerForm.show_nsfw = event.target.checked;
286     i.setState(i.state);
287   }
288
289   handlePasswordReset(i: Login) {
290     let resetForm: PasswordResetForm = {
291       email: i.state.loginForm.username_or_email,
292     };
293     WebSocketService.Instance.passwordReset(resetForm);
294   }
295
296   parseMessage(msg: any) {
297     let op: UserOperation = msgOp(msg);
298     if (msg.error) {
299       alert(i18n.t(msg.error));
300       this.state = this.emptyState;
301       this.setState(this.state);
302       return;
303     } else {
304       if (op == UserOperation.Login) {
305         this.state = this.emptyState;
306         this.setState(this.state);
307         let res: LoginResponse = msg;
308         UserService.Instance.login(res);
309         this.props.history.push('/');
310       } else if (op == UserOperation.Register) {
311         this.state = this.emptyState;
312         this.setState(this.state);
313         let res: LoginResponse = msg;
314         UserService.Instance.login(res);
315         this.props.history.push('/communities');
316       } else if (op == UserOperation.PasswordReset) {
317         alert(i18n.t('reset_password_mail_sent'));
318       }
319     }
320   }
321 }