]> Untitled Git - lemmy.git/blob - ui/src/components/login.tsx
Adding document titles.
[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   componentDidMount() {
52     document.title = "Login - Lemmy";
53   }
54
55   render() {
56     return (
57       <div class="container">
58         <div class="row">
59           <div class="col-12 col-lg-6 mb-4">
60             {this.loginForm()}
61           </div>
62           <div class="col-12 col-lg-6">
63             {this.registerForm()}
64           </div>
65         </div>
66       </div>
67     )
68   }
69
70   loginForm() {
71     return (
72       <div>
73         <form onSubmit={linkEvent(this, this.handleLoginSubmit)}>
74           <h5>Login</h5>
75           <div class="form-group row">
76             <label class="col-sm-2 col-form-label">Email or Username</label>
77             <div class="col-sm-10">
78               <input type="text" class="form-control" value={this.state.loginForm.username_or_email} onInput={linkEvent(this, this.handleLoginUsernameChange)} required minLength={3} />
79             </div>
80           </div>
81           <div class="form-group row">
82             <label class="col-sm-2 col-form-label">Password</label>
83             <div class="col-sm-10">
84               <input type="password" value={this.state.loginForm.password} onInput={linkEvent(this, this.handleLoginPasswordChange)} class="form-control" required />
85             </div>
86           </div>
87           <div class="form-group row">
88             <div class="col-sm-10">
89               <button type="submit" class="btn btn-secondary">{this.state.loginLoading ? 
90               <svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg> : 'Login'}</button>
91             </div>
92           </div>
93         </form>
94         Forgot your password or deleted your account? Reset your password. TODO
95       </div>
96     );
97   }
98   registerForm() {
99     return (
100       <form onSubmit={linkEvent(this, this.handleRegisterSubmit)}>
101         <h5>Sign Up</h5>
102         <div class="form-group row">
103           <label class="col-sm-2 col-form-label">Username</label>
104           <div class="col-sm-10">
105             <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_]+" />
106           </div>
107         </div>
108         <div class="form-group row">
109           <label class="col-sm-2 col-form-label">Email</label>
110           <div class="col-sm-10">
111             <input type="email" class="form-control" placeholder="Optional" value={this.state.registerForm.email} onInput={linkEvent(this, this.handleRegisterEmailChange)} minLength={3} />
112           </div>
113         </div>
114         <div class="form-group row">
115           <label class="col-sm-2 col-form-label">Password</label>
116           <div class="col-sm-10">
117             <input type="password" value={this.state.registerForm.password} onInput={linkEvent(this, this.handleRegisterPasswordChange)} class="form-control" required />
118           </div>
119         </div>
120         <div class="form-group row">
121           <label class="col-sm-2 col-form-label">Verify Password</label>
122           <div class="col-sm-10">
123             <input type="password" value={this.state.registerForm.password_verify} onInput={linkEvent(this, this.handleRegisterPasswordVerifyChange)} class="form-control" required />
124           </div>
125         </div>
126         <div class="form-group row">
127           <div class="col-sm-10">
128             <button type="submit" class="btn btn-secondary">{this.state.registerLoading ? 
129             <svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg> : 'Sign Up'}</button>
130
131           </div>
132         </div>
133       </form>
134     );
135   }
136
137   handleLoginSubmit(i: Login, event: any) {
138     event.preventDefault();
139     i.state.loginLoading = true;
140     i.setState(i.state);
141     WebSocketService.Instance.login(i.state.loginForm);
142   }
143
144   handleLoginUsernameChange(i: Login, event: any) {
145     i.state.loginForm.username_or_email = event.target.value;
146     i.setState(i.state);
147   }
148
149   handleLoginPasswordChange(i: Login, event: any) {
150     i.state.loginForm.password = event.target.value;
151     i.setState(i.state);
152   }
153
154   handleRegisterSubmit(i: Login, event: any) {
155     event.preventDefault();
156     i.state.registerLoading = true;
157     i.setState(i.state);
158     event.preventDefault();
159     WebSocketService.Instance.register(i.state.registerForm);
160   }
161
162   handleRegisterUsernameChange(i: Login, event: any) {
163     i.state.registerForm.username = event.target.value;
164     i.setState(i.state);
165   }
166
167   handleRegisterEmailChange(i: Login, event: any) {
168     i.state.registerForm.email = event.target.value;
169     i.setState(i.state);
170   }
171
172   handleRegisterPasswordChange(i: Login, event: any) {
173     i.state.registerForm.password = event.target.value;
174     i.setState(i.state);
175   }
176
177   handleRegisterPasswordVerifyChange(i: Login, event: any) {
178     i.state.registerForm.password_verify = event.target.value;
179     i.setState(i.state);
180   }
181
182   parseMessage(msg: any) {
183     let op: UserOperation = msgOp(msg);
184     if (msg.error) {
185       alert(msg.error);
186       this.state.loginLoading = false;
187       this.state.registerLoading = false;
188       this.setState(this.state);
189       return;
190     } else {
191       if (op == UserOperation.Register || op == UserOperation.Login) {
192         this.state.loginLoading = false;
193         this.state.registerLoading = false;
194         let res: LoginResponse = msg;
195         UserService.Instance.login(res);
196         this.props.history.push('/');
197       }
198     }
199   }
200 }