]> Untitled Git - lemmy.git/blob - ui/src/components/login.tsx
Merge branch 'replies' into dev
[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 { LoginForm, RegisterForm, LoginResponse, UserOperation } from '../interfaces';
5 import { WebSocketService, UserService } from '../services';
6 import { msgOp } from '../utils';
7
8 interface State {
9   loginForm: LoginForm;
10   registerForm: RegisterForm;
11   loginLoading: boolean;
12   registerLoading: boolean;
13 }
14
15 let emptyState: State = {
16   loginForm: {
17     username_or_email: undefined,
18     password: undefined
19   },
20   registerForm: {
21     username: undefined,
22     password: undefined,
23     password_verify: undefined,
24     admin: false,
25   },
26   loginLoading: false,
27   registerLoading: false
28 }
29
30 export class Login extends Component<any, State> {
31   private subscription: Subscription;
32
33   constructor(props: any, context: any) {
34     super(props, context);
35
36     this.state = emptyState;
37
38     this.subscription = WebSocketService.Instance.subject
39     .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
40     .subscribe(
41       (msg) => this.parseMessage(msg),
42         (err) => console.error(err),
43         () => console.log("complete")
44     );
45   }
46
47   componentWillUnmount() {
48     this.subscription.unsubscribe();
49   }
50
51   render() {
52     return (
53       <div class="container">
54         <div class="row">
55           <div class="col-12 col-lg-6 mb-4">
56             {this.loginForm()}
57           </div>
58           <div class="col-12 col-lg-6">
59             {this.registerForm()}
60           </div>
61         </div>
62       </div>
63     )
64   }
65
66   loginForm() {
67     return (
68       <div>
69         <form onSubmit={linkEvent(this, this.handleLoginSubmit)}>
70           <h5>Login</h5>
71           <div class="form-group row">
72             <label class="col-sm-2 col-form-label">Email or Username</label>
73             <div class="col-sm-10">
74               <input type="text" class="form-control" value={this.state.loginForm.username_or_email} onInput={linkEvent(this, this.handleLoginUsernameChange)} required minLength={3} />
75             </div>
76           </div>
77           <div class="form-group row">
78             <label class="col-sm-2 col-form-label">Password</label>
79             <div class="col-sm-10">
80               <input type="password" value={this.state.loginForm.password} onInput={linkEvent(this, this.handleLoginPasswordChange)} class="form-control" required />
81             </div>
82           </div>
83           <div class="form-group row">
84             <div class="col-sm-10">
85               <button type="submit" class="btn btn-secondary">{this.state.loginLoading ? 
86               <svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg> : 'Login'}</button>
87             </div>
88           </div>
89         </form>
90         Forgot your password or deleted your account? Reset your password. TODO
91       </div>
92     );
93   }
94   registerForm() {
95     return (
96       <form onSubmit={linkEvent(this, this.handleRegisterSubmit)}>
97         <h5>Sign Up</h5>
98         <div class="form-group row">
99           <label class="col-sm-2 col-form-label">Username</label>
100           <div class="col-sm-10">
101             <input type="text" class="form-control" value={this.state.registerForm.username} onInput={linkEvent(this, this.handleRegisterUsernameChange)} required minLength={3} maxLength={20} pattern="[a-zA-Z0-9_]+" />
102           </div>
103         </div>
104         <div class="form-group row">
105           <label class="col-sm-2 col-form-label">Email</label>
106           <div class="col-sm-10">
107             <input type="email" class="form-control" placeholder="Optional" value={this.state.registerForm.email} onInput={linkEvent(this, this.handleRegisterEmailChange)} minLength={3} />
108           </div>
109         </div>
110         <div class="form-group row">
111           <label class="col-sm-2 col-form-label">Password</label>
112           <div class="col-sm-10">
113             <input type="password" value={this.state.registerForm.password} onInput={linkEvent(this, this.handleRegisterPasswordChange)} class="form-control" required />
114           </div>
115         </div>
116         <div class="form-group row">
117           <label class="col-sm-2 col-form-label">Verify Password</label>
118           <div class="col-sm-10">
119             <input type="password" value={this.state.registerForm.password_verify} onInput={linkEvent(this, this.handleRegisterPasswordVerifyChange)} class="form-control" required />
120           </div>
121         </div>
122         <div class="form-group row">
123           <div class="col-sm-10">
124             <button type="submit" class="btn btn-secondary">{this.state.registerLoading ? 
125             <svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg> : 'Sign Up'}</button>
126
127           </div>
128         </div>
129       </form>
130     );
131   }
132
133   handleLoginSubmit(i: Login, event: any) {
134     event.preventDefault();
135     i.state.loginLoading = true;
136     i.setState(i.state);
137     WebSocketService.Instance.login(i.state.loginForm);
138   }
139
140   handleLoginUsernameChange(i: Login, event: any) {
141     i.state.loginForm.username_or_email = event.target.value;
142     i.setState(i.state);
143   }
144
145   handleLoginPasswordChange(i: Login, event: any) {
146     i.state.loginForm.password = event.target.value;
147     i.setState(i.state);
148   }
149
150   handleRegisterSubmit(i: Login, event: any) {
151     event.preventDefault();
152     i.state.registerLoading = true;
153     i.setState(i.state);
154     event.preventDefault();
155     WebSocketService.Instance.register(i.state.registerForm);
156   }
157
158   handleRegisterUsernameChange(i: Login, event: any) {
159     i.state.registerForm.username = event.target.value;
160     i.setState(i.state);
161   }
162
163   handleRegisterEmailChange(i: Login, event: any) {
164     i.state.registerForm.email = event.target.value;
165     i.setState(i.state);
166   }
167
168   handleRegisterPasswordChange(i: Login, event: any) {
169     i.state.registerForm.password = event.target.value;
170     i.setState(i.state);
171   }
172
173   handleRegisterPasswordVerifyChange(i: Login, event: any) {
174     i.state.registerForm.password_verify = event.target.value;
175     i.setState(i.state);
176   }
177
178   parseMessage(msg: any) {
179     let op: UserOperation = msgOp(msg);
180     if (msg.error) {
181       alert(msg.error);
182       this.state.loginLoading = false;
183       this.state.registerLoading = false;
184       this.setState(this.state);
185       return;
186     } else {
187       if (op == UserOperation.Register || op == UserOperation.Login) {
188         this.state.loginLoading = false;
189         this.state.registerLoading = false;
190         let res: LoginResponse = msg;
191         UserService.Instance.login(res);
192         this.props.history.push('/');
193       }
194     }
195   }
196 }