]> Untitled Git - lemmy-ui.git/blob - src/shared/components/home/setup.tsx
Merge pull request #1089 from jwhitmarsh/fix/1039
[lemmy-ui.git] / src / shared / components / home / setup.tsx
1 import { Component, linkEvent } from "inferno";
2 import { Helmet } from "inferno-helmet";
3 import {
4   GetSiteResponse,
5   LoginResponse,
6   Register,
7   UserOperation,
8   wsJsonToRes,
9   wsUserOp,
10 } from "lemmy-js-client";
11 import { Subscription } from "rxjs";
12 import { delay, retryWhen, take } from "rxjs/operators";
13 import { i18n } from "../../i18next";
14 import { UserService, WebSocketService } from "../../services";
15 import { setIsoData, toast, wsClient } from "../../utils";
16 import { Spinner } from "../common/icon";
17 import { SiteForm } from "./site-form";
18
19 interface State {
20   form: {
21     username?: string;
22     email?: string;
23     password?: string;
24     password_verify?: string;
25     show_nsfw: boolean;
26     captcha_uuid?: string;
27     captcha_answer?: string;
28     honeypot?: string;
29     answer?: string;
30   };
31   doneRegisteringUser: boolean;
32   userLoading: boolean;
33   siteRes: GetSiteResponse;
34 }
35
36 export class Setup extends Component<any, State> {
37   private subscription: Subscription;
38   private isoData = setIsoData(this.context);
39
40   state: State = {
41     form: {
42       show_nsfw: true,
43     },
44     doneRegisteringUser: !!UserService.Instance.myUserInfo,
45     userLoading: false,
46     siteRes: this.isoData.site_res,
47   };
48
49   constructor(props: any, context: any) {
50     super(props, context);
51
52     this.subscription = WebSocketService.Instance.subject
53       .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
54       .subscribe(
55         msg => this.parseMessage(msg),
56         err => console.error(err),
57         () => console.log("complete")
58       );
59   }
60
61   componentWillUnmount() {
62     this.subscription.unsubscribe();
63   }
64
65   get documentTitle(): string {
66     return `${i18n.t("setup")} - Lemmy`;
67   }
68
69   render() {
70     return (
71       <div className="container-lg">
72         <Helmet title={this.documentTitle} />
73         <div className="row">
74           <div className="col-12 offset-lg-3 col-lg-6">
75             <h3>{i18n.t("lemmy_instance_setup")}</h3>
76             {!this.state.doneRegisteringUser ? (
77               this.registerUser()
78             ) : (
79               <SiteForm siteRes={this.state.siteRes} showLocal />
80             )}
81           </div>
82         </div>
83       </div>
84     );
85   }
86
87   registerUser() {
88     return (
89       <form onSubmit={linkEvent(this, this.handleRegisterSubmit)}>
90         <h5>{i18n.t("setup_admin")}</h5>
91         <div className="form-group row">
92           <label className="col-sm-2 col-form-label" htmlFor="username">
93             {i18n.t("username")}
94           </label>
95           <div className="col-sm-10">
96             <input
97               type="text"
98               className="form-control"
99               id="username"
100               value={this.state.form.username}
101               onInput={linkEvent(this, this.handleRegisterUsernameChange)}
102               required
103               minLength={3}
104               pattern="[a-zA-Z0-9_]+"
105             />
106           </div>
107         </div>
108         <div className="form-group row">
109           <label className="col-sm-2 col-form-label" htmlFor="email">
110             {i18n.t("email")}
111           </label>
112
113           <div className="col-sm-10">
114             <input
115               type="email"
116               id="email"
117               className="form-control"
118               placeholder={i18n.t("optional")}
119               value={this.state.form.email}
120               onInput={linkEvent(this, this.handleRegisterEmailChange)}
121               minLength={3}
122             />
123           </div>
124         </div>
125         <div className="form-group row">
126           <label className="col-sm-2 col-form-label" htmlFor="password">
127             {i18n.t("password")}
128           </label>
129           <div className="col-sm-10">
130             <input
131               type="password"
132               id="password"
133               value={this.state.form.password}
134               onInput={linkEvent(this, this.handleRegisterPasswordChange)}
135               className="form-control"
136               required
137               autoComplete="new-password"
138               minLength={10}
139               maxLength={60}
140             />
141           </div>
142         </div>
143         <div className="form-group row">
144           <label className="col-sm-2 col-form-label" htmlFor="verify-password">
145             {i18n.t("verify_password")}
146           </label>
147           <div className="col-sm-10">
148             <input
149               type="password"
150               id="verify-password"
151               value={this.state.form.password_verify}
152               onInput={linkEvent(this, this.handleRegisterPasswordVerifyChange)}
153               className="form-control"
154               required
155               autoComplete="new-password"
156               minLength={10}
157               maxLength={60}
158             />
159           </div>
160         </div>
161         <div className="form-group row">
162           <div className="col-sm-10">
163             <button type="submit" className="btn btn-secondary">
164               {this.state.userLoading ? <Spinner /> : i18n.t("sign_up")}
165             </button>
166           </div>
167         </div>
168       </form>
169     );
170   }
171
172   handleRegisterSubmit(i: Setup, event: any) {
173     event.preventDefault();
174     i.setState({ userLoading: true });
175     event.preventDefault();
176     const cForm = i.state.form;
177     if (cForm.username && cForm.password && cForm.password_verify) {
178       const form: Register = {
179         username: cForm.username,
180         password: cForm.password,
181         password_verify: cForm.password_verify,
182         email: cForm.email,
183         show_nsfw: cForm.show_nsfw,
184         captcha_uuid: cForm.captcha_uuid,
185         captcha_answer: cForm.captcha_answer,
186         honeypot: cForm.honeypot,
187         answer: cForm.answer,
188       };
189       WebSocketService.Instance.send(wsClient.register(form));
190     }
191   }
192
193   handleRegisterUsernameChange(i: Setup, event: any) {
194     i.state.form.username = event.target.value;
195     i.setState(i.state);
196   }
197
198   handleRegisterEmailChange(i: Setup, event: any) {
199     i.state.form.email = event.target.value;
200     i.setState(i.state);
201   }
202
203   handleRegisterPasswordChange(i: Setup, event: any) {
204     i.state.form.password = event.target.value;
205     i.setState(i.state);
206   }
207
208   handleRegisterPasswordVerifyChange(i: Setup, event: any) {
209     i.state.form.password_verify = event.target.value;
210     i.setState(i.state);
211   }
212
213   parseMessage(msg: any) {
214     const op = wsUserOp(msg);
215     if (msg.error) {
216       toast(i18n.t(msg.error), "danger");
217       this.setState({ userLoading: false });
218       return;
219     } else if (op == UserOperation.Register) {
220       const data = wsJsonToRes<LoginResponse>(msg);
221       this.setState({ userLoading: false });
222       UserService.Instance.login(data);
223       if (UserService.Instance.jwtInfo) {
224         this.setState({ doneRegisteringUser: true });
225       }
226     } else if (op == UserOperation.CreateSite) {
227       window.location.href = "/";
228     }
229   }
230 }