]> Untitled Git - lemmy.git/blob - ui/src/components/login.tsx
Reworking some UI. Adding proper trending communities with hot rank.
[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   spamNada: string;
14 }
15
16
17 export class Login extends Component<any, State> {
18   private subscription: Subscription;
19
20   emptyState: State = {
21     loginForm: {
22       username_or_email: undefined,
23       password: undefined
24     },
25     registerForm: {
26       username: undefined,
27       password: undefined,
28       password_verify: undefined,
29       admin: false,
30       spam_timeri: undefined,
31     },
32     loginLoading: false,
33     registerLoading: false,
34     spamNada: undefined
35   }
36
37   constructor(props: any, context: any) {
38     super(props, context);
39
40     this.state = this.emptyState;
41
42     this.subscription = WebSocketService.Instance.subject
43     .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
44     .subscribe(
45       (msg) => this.parseMessage(msg),
46         (err) => console.error(err),
47         () => console.log("complete")
48     );
49   }
50
51   componentWillUnmount() {
52     this.subscription.unsubscribe();
53   }
54
55   componentDidMount() {
56     document.title = "Login - Lemmy";
57   }
58
59   render() {
60     return (
61       <div class="container">
62         <div class="row">
63           <div class="col-12 col-lg-6 mb-4">
64             {this.loginForm()}
65           </div>
66           <div class="col-12 col-lg-6">
67             {this.registerForm()}
68           </div>
69         </div>
70       </div>
71     )
72   }
73
74   loginForm() {
75     return (
76       <div>
77         <form onSubmit={linkEvent(this, this.handleLoginSubmit)}>
78           <h5>Login</h5>
79           <div class="form-group row">
80             <label class="col-sm-2 col-form-label">Email or Username</label>
81             <div class="col-sm-10">
82               <input type="text" class="form-control" value={this.state.loginForm.username_or_email} onInput={linkEvent(this, this.handleLoginUsernameChange)} required minLength={3} />
83             </div>
84           </div>
85           <div class="form-group row">
86             <label class="col-sm-2 col-form-label">Password</label>
87             <div class="col-sm-10">
88               <input type="password" value={this.state.loginForm.password} onInput={linkEvent(this, this.handleLoginPasswordChange)} class="form-control" required />
89             </div>
90           </div>
91           <div class="form-group row">
92             <div class="col-sm-10">
93               <button type="submit" class="btn btn-secondary">{this.state.loginLoading ? 
94               <svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg> : 'Login'}</button>
95             </div>
96           </div>
97         </form>
98         {/* Forgot your password or deleted your account? Reset your password. TODO */}
99       </div>
100     );
101   }
102   registerForm() {
103     return (
104       <form onSubmit={linkEvent(this, this.handleRegisterSubmit)}>
105         <h5>Sign Up</h5>
106         <input type="text" class="no-s-hows" value={this.state.spamNada} onInput={linkEvent(this, this.handleSpamNada)} />
107         <div class="form-group row">
108           <label class="col-sm-2 col-form-label">Username</label>
109           <div class="col-sm-10">
110             <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_]+" />
111           </div>
112         </div>
113         <div class="form-group row">
114           <label class="col-sm-2 col-form-label">Email</label>
115           <div class="col-sm-10">
116             <input type="email" class="form-control" placeholder="Optional" value={this.state.registerForm.email} onInput={linkEvent(this, this.handleRegisterEmailChange)} minLength={3} />
117           </div>
118         </div>
119         <div class="form-group row">
120           <label class="col-sm-2 col-form-label">Password</label>
121           <div class="col-sm-10">
122             <input type="password" value={this.state.registerForm.password} onInput={linkEvent(this, this.handleRegisterPasswordChange)} class="form-control" required />
123           </div>
124         </div>
125         <div class="form-group row">
126           <label class="col-sm-2 col-form-label">Verify Password</label>
127           <div class="col-sm-10">
128             <input type="password" value={this.state.registerForm.password_verify} onInput={linkEvent(this, this.handleRegisterPasswordVerifyChange)} class="form-control" required />
129           </div>
130         </div>
131         <input type="hidden" value={this.state.registerForm.spam_timeri} />
132         <div class="form-group row">
133           <div class="col-sm-10">
134             <button type="submit" class="btn btn-secondary">{this.state.registerLoading ? 
135             <svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg> : 'Sign Up'}</button>
136
137           </div>
138         </div>
139       </form>
140     );
141   }
142
143   handleLoginSubmit(i: Login, event: any) {
144     event.preventDefault();
145     i.state.loginLoading = true;
146     i.setState(i.state);
147     WebSocketService.Instance.login(i.state.loginForm);
148   }
149
150   handleLoginUsernameChange(i: Login, event: any) {
151     i.state.loginForm.username_or_email = event.target.value;
152     i.setState(i.state);
153   }
154
155   handleLoginPasswordChange(i: Login, event: any) {
156     i.state.loginForm.password = event.target.value;
157     i.setState(i.state);
158   }
159
160   handleRegisterSubmit(i: Login, event: any) {
161     event.preventDefault();
162     i.state.registerLoading = true;
163     i.setState(i.state);
164
165     let endTimer = new Date().getTime();
166     let elapsed = endTimer - i.state.registerForm.spam_timeri;
167
168     i.state.registerForm.spam_timeri = elapsed;
169     if (elapsed > 1423 && i.state.spamNada == undefined) {
170       WebSocketService.Instance.register(i.state.registerForm);
171     } else {
172       window.location.href = "https://github.com/dessalines/lemmy";
173     }
174   }
175
176   handleRegisterUsernameChange(i: Login, event: any) {
177     i.state.registerForm.username = event.target.value;
178     i.state.registerForm.spam_timeri = new Date().getTime();
179     i.setState(i.state);
180   }
181
182   handleSpamNada(i: Login, event: any) {
183     i.state.spamNada = event.target.value;
184     i.setState(i.state);
185   }
186
187   handleRegisterEmailChange(i: Login, event: any) {
188     i.state.registerForm.email = event.target.value;
189     i.setState(i.state);
190   }
191
192   handleRegisterPasswordChange(i: Login, event: any) {
193     i.state.registerForm.password = event.target.value;
194     i.setState(i.state);
195   }
196
197   handleRegisterPasswordVerifyChange(i: Login, event: any) {
198     i.state.registerForm.password_verify = event.target.value;
199     i.setState(i.state);
200   }
201
202   parseMessage(msg: any) {
203     let op: UserOperation = msgOp(msg);
204     if (msg.error) {
205       alert(msg.error);
206       this.state = this.emptyState;
207       this.setState(this.state);
208       return;
209     } else {
210       if (op == UserOperation.Login) {
211         this.state = this.emptyState;
212         this.setState(this.state);
213         let res: LoginResponse = msg;
214         UserService.Instance.login(res);
215         this.props.history.push('/');
216       } else if (op == UserOperation.Register) {
217         this.state = this.emptyState;
218         this.setState(this.state);
219         let res: LoginResponse = msg;
220         UserService.Instance.login(res);
221         this.props.history.push('/communities');
222       }
223     }
224   }
225
226 }