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