]> Untitled Git - lemmy-ui.git/blob - src/shared/components/site-form.tsx
Running newer prettier.
[lemmy-ui.git] / src / shared / components / site-form.tsx
1 import { Component, linkEvent } from "inferno";
2 import { Prompt } from "inferno-router";
3 import { MarkdownTextArea } from "./markdown-textarea";
4 import { Spinner } from "./icon";
5 import { ImageUploadForm } from "./image-upload-form";
6 import { Site, EditSite } from "lemmy-js-client";
7 import { WebSocketService } from "../services";
8 import {
9   authField,
10   capitalizeFirstLetter,
11   randomStr,
12   wsClient,
13 } from "../utils";
14 import { i18n } from "../i18next";
15
16 interface SiteFormProps {
17   site?: Site; // If a site is given, that means this is an edit
18   onCancel?(): any;
19 }
20
21 interface SiteFormState {
22   siteForm: EditSite;
23   loading: boolean;
24 }
25
26 export class SiteForm extends Component<SiteFormProps, SiteFormState> {
27   private id = `site-form-${randomStr()}`;
28   private emptyState: SiteFormState = {
29     siteForm: {
30       enable_downvotes: true,
31       open_registration: true,
32       enable_nsfw: true,
33       name: null,
34       icon: null,
35       banner: null,
36       auth: authField(),
37     },
38     loading: false,
39   };
40
41   constructor(props: any, context: any) {
42     super(props, context);
43
44     this.state = this.emptyState;
45     this.handleSiteDescriptionChange = this.handleSiteDescriptionChange.bind(
46       this
47     );
48
49     this.handleIconUpload = this.handleIconUpload.bind(this);
50     this.handleIconRemove = this.handleIconRemove.bind(this);
51
52     this.handleBannerUpload = this.handleBannerUpload.bind(this);
53     this.handleBannerRemove = this.handleBannerRemove.bind(this);
54
55     if (this.props.site) {
56       this.state.siteForm = {
57         name: this.props.site.name,
58         description: this.props.site.description,
59         enable_downvotes: this.props.site.enable_downvotes,
60         open_registration: this.props.site.open_registration,
61         enable_nsfw: this.props.site.enable_nsfw,
62         icon: this.props.site.icon,
63         banner: this.props.site.banner,
64         auth: authField(),
65       };
66     }
67   }
68
69   // Necessary to stop the loading
70   componentWillReceiveProps() {
71     this.state.loading = false;
72     this.setState(this.state);
73   }
74
75   componentDidUpdate() {
76     if (
77       !this.state.loading &&
78       !this.props.site &&
79       (this.state.siteForm.name || this.state.siteForm.description)
80     ) {
81       window.onbeforeunload = () => true;
82     } else {
83       window.onbeforeunload = undefined;
84     }
85   }
86
87   componentWillUnmount() {
88     window.onbeforeunload = null;
89   }
90
91   render() {
92     return (
93       <>
94         <Prompt
95           when={
96             !this.state.loading &&
97             !this.props.site &&
98             (this.state.siteForm.name || this.state.siteForm.description)
99           }
100           message={i18n.t("block_leaving")}
101         />
102         <form onSubmit={linkEvent(this, this.handleCreateSiteSubmit)}>
103           <h5>{`${
104             this.props.site
105               ? capitalizeFirstLetter(i18n.t("save"))
106               : capitalizeFirstLetter(i18n.t("name"))
107           } ${i18n.t("your_site")}`}</h5>
108           <div class="form-group row">
109             <label class="col-12 col-form-label" htmlFor="create-site-name">
110               {i18n.t("name")}
111             </label>
112             <div class="col-12">
113               <input
114                 type="text"
115                 id="create-site-name"
116                 class="form-control"
117                 value={this.state.siteForm.name}
118                 onInput={linkEvent(this, this.handleSiteNameChange)}
119                 required
120                 minLength={3}
121                 maxLength={20}
122               />
123             </div>
124           </div>
125           <div class="form-group">
126             <label>{i18n.t("icon")}</label>
127             <ImageUploadForm
128               uploadTitle={i18n.t("upload_icon")}
129               imageSrc={this.state.siteForm.icon}
130               onUpload={this.handleIconUpload}
131               onRemove={this.handleIconRemove}
132               rounded
133             />
134           </div>
135           <div class="form-group">
136             <label>{i18n.t("banner")}</label>
137             <ImageUploadForm
138               uploadTitle={i18n.t("upload_banner")}
139               imageSrc={this.state.siteForm.banner}
140               onUpload={this.handleBannerUpload}
141               onRemove={this.handleBannerRemove}
142             />
143           </div>
144           <div class="form-group row">
145             <label class="col-12 col-form-label" htmlFor={this.id}>
146               {i18n.t("sidebar")}
147             </label>
148             <div class="col-12">
149               <MarkdownTextArea
150                 initialContent={this.state.siteForm.description}
151                 onContentChange={this.handleSiteDescriptionChange}
152                 hideNavigationWarnings
153               />
154             </div>
155           </div>
156           <div class="form-group row">
157             <div class="col-12">
158               <div class="form-check">
159                 <input
160                   class="form-check-input"
161                   id="create-site-downvotes"
162                   type="checkbox"
163                   checked={this.state.siteForm.enable_downvotes}
164                   onChange={linkEvent(
165                     this,
166                     this.handleSiteEnableDownvotesChange
167                   )}
168                 />
169                 <label class="form-check-label" htmlFor="create-site-downvotes">
170                   {i18n.t("enable_downvotes")}
171                 </label>
172               </div>
173             </div>
174           </div>
175           <div class="form-group row">
176             <div class="col-12">
177               <div class="form-check">
178                 <input
179                   class="form-check-input"
180                   id="create-site-enable-nsfw"
181                   type="checkbox"
182                   checked={this.state.siteForm.enable_nsfw}
183                   onChange={linkEvent(this, this.handleSiteEnableNsfwChange)}
184                 />
185                 <label
186                   class="form-check-label"
187                   htmlFor="create-site-enable-nsfw"
188                 >
189                   {i18n.t("enable_nsfw")}
190                 </label>
191               </div>
192             </div>
193           </div>
194           <div class="form-group row">
195             <div class="col-12">
196               <div class="form-check">
197                 <input
198                   class="form-check-input"
199                   id="create-site-open-registration"
200                   type="checkbox"
201                   checked={this.state.siteForm.open_registration}
202                   onChange={linkEvent(
203                     this,
204                     this.handleSiteOpenRegistrationChange
205                   )}
206                 />
207                 <label
208                   class="form-check-label"
209                   htmlFor="create-site-open-registration"
210                 >
211                   {i18n.t("open_registration")}
212                 </label>
213               </div>
214             </div>
215           </div>
216           <div class="form-group row">
217             <div class="col-12">
218               <button
219                 type="submit"
220                 class="btn btn-secondary mr-2"
221                 disabled={this.state.loading}
222               >
223                 {this.state.loading ? (
224                   <Spinner />
225                 ) : this.props.site ? (
226                   capitalizeFirstLetter(i18n.t("save"))
227                 ) : (
228                   capitalizeFirstLetter(i18n.t("create"))
229                 )}
230               </button>
231               {this.props.site && (
232                 <button
233                   type="button"
234                   class="btn btn-secondary"
235                   onClick={linkEvent(this, this.handleCancel)}
236                 >
237                   {i18n.t("cancel")}
238                 </button>
239               )}
240             </div>
241           </div>
242         </form>
243       </>
244     );
245   }
246
247   handleCreateSiteSubmit(i: SiteForm, event: any) {
248     event.preventDefault();
249     i.state.loading = true;
250     if (i.props.site) {
251       WebSocketService.Instance.send(wsClient.editSite(i.state.siteForm));
252     } else {
253       WebSocketService.Instance.send(wsClient.createSite(i.state.siteForm));
254     }
255     i.setState(i.state);
256   }
257
258   handleSiteNameChange(i: SiteForm, event: any) {
259     i.state.siteForm.name = event.target.value;
260     i.setState(i.state);
261   }
262
263   handleSiteDescriptionChange(val: string) {
264     this.state.siteForm.description = val;
265     this.setState(this.state);
266   }
267
268   handleSiteEnableNsfwChange(i: SiteForm, event: any) {
269     i.state.siteForm.enable_nsfw = event.target.checked;
270     i.setState(i.state);
271   }
272
273   handleSiteOpenRegistrationChange(i: SiteForm, event: any) {
274     i.state.siteForm.open_registration = event.target.checked;
275     i.setState(i.state);
276   }
277
278   handleSiteEnableDownvotesChange(i: SiteForm, event: any) {
279     i.state.siteForm.enable_downvotes = event.target.checked;
280     i.setState(i.state);
281   }
282
283   handleCancel(i: SiteForm) {
284     i.props.onCancel();
285   }
286
287   handleIconUpload(url: string) {
288     this.state.siteForm.icon = url;
289     this.setState(this.state);
290   }
291
292   handleIconRemove() {
293     this.state.siteForm.icon = "";
294     this.setState(this.state);
295   }
296
297   handleBannerUpload(url: string) {
298     this.state.siteForm.banner = url;
299     this.setState(this.state);
300   }
301
302   handleBannerRemove() {
303     this.state.siteForm.banner = "";
304     this.setState(this.state);
305   }
306 }