]> Untitled Git - lemmy.git/blob - ui/src/components/site-form.tsx
Merge branch 'feature/frontend-a11y' of https://github.com/richardj/lemmy into richar...
[lemmy.git] / ui / src / components / site-form.tsx
1 import { Component, linkEvent } from 'inferno';
2 import { Site, SiteForm as SiteFormI } from '../interfaces';
3 import { WebSocketService } from '../services';
4 import { capitalizeFirstLetter, randomStr, setupTribute } from '../utils';
5 import autosize from 'autosize';
6 import Tribute from 'tributejs/src/Tribute.js';
7 import { i18n } from '../i18next';
8 import { T } from 'inferno-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 tribute: Tribute;
23   private emptyState: SiteFormState = {
24     siteForm: {
25       enable_downvotes: true,
26       open_registration: true,
27       enable_nsfw: true,
28       name: null,
29     },
30     loading: false,
31   };
32
33   constructor(props: any, context: any) {
34     super(props, context);
35
36     this.tribute = setupTribute();
37     this.state = this.emptyState;
38
39     if (this.props.site) {
40       this.state.siteForm = {
41         name: this.props.site.name,
42         description: this.props.site.description,
43         enable_downvotes: this.props.site.enable_downvotes,
44         open_registration: this.props.site.open_registration,
45         enable_nsfw: this.props.site.enable_nsfw,
46       };
47     }
48   }
49
50   componentDidMount() {
51     var textarea: any = document.getElementById(this.id);
52     autosize(textarea);
53     this.tribute.attach(textarea);
54     textarea.addEventListener('tribute-replaced', () => {
55       this.state.siteForm.description = textarea.value;
56       this.setState(this.state);
57       autosize.update(textarea);
58     });
59   }
60
61   render() {
62     return (
63       <form onSubmit={linkEvent(this, this.handleCreateSiteSubmit)}>
64         <h5>{`${
65           this.props.site
66             ? capitalizeFirstLetter(i18n.t('edit'))
67             : capitalizeFirstLetter(i18n.t('name'))
68         } ${i18n.t('your_site')}`}</h5>
69         <div class="form-group row">
70           <label class="col-12 col-form-label" for="create-site-name">
71             { i18n.t('name') }
72           </label>
73           <div class="col-12">
74             <input
75               type="text"
76               id="create-site-name"
77               class="form-control"
78               value={this.state.siteForm.name}
79               onInput={linkEvent(this, this.handleSiteNameChange)}
80               required
81               minLength={3}
82               maxLength={20}
83             />
84           </div>
85         </div>
86         <div class="form-group row">
87           <label class="col-12 col-form-label" for="create-site-sidebar">
88             { i18n.t('sidebar') }
89           </label>
90           <div class="col-12">
91             <textarea
92               id={this.id}
93               value={this.state.siteForm.description}
94               id="create-site-sidebar"
95               onInput={linkEvent(this, this.handleSiteDescriptionChange)}
96               class="form-control"
97               rows={3}
98               maxLength={10000}
99             />
100           </div>
101         </div>
102         <div class="form-group row">
103           <div class="col-12">
104             <div class="form-check">
105               <input
106                 class="form-check-input"
107                 id="create-site-downvotes"
108                 type="checkbox"
109                 checked={this.state.siteForm.enable_downvotes}
110                 onChange={linkEvent(this, this.handleSiteEnableDownvotesChange)}
111               />
112               <label class="form-check-label" for="create-site-downvotes">
113                 { i18n.t('enable_downvotes') }
114               </label>
115             </div>
116           </div>
117         </div>
118         <div class="form-group row">
119           <div class="col-12">
120             <div class="form-check">
121               <input
122                 class="form-check-input"
123                 id="create-site-enable-nsfw"
124                 type="checkbox"
125                 checked={this.state.siteForm.enable_nsfw}
126                 onChange={linkEvent(this, this.handleSiteEnableNsfwChange)}
127               />
128               <label class="form-check-label" for="create-site-enable-nsfw">
129                 { i18n.t('enable_nsfw') }
130               </label>
131             </div>
132           </div>
133         </div>
134         <div class="form-group row">
135           <div class="col-12">
136             <div class="form-check">
137               <input
138                 class="form-check-input"
139                 id="create-site-open-registration"
140                 type="checkbox"
141                 checked={this.state.siteForm.open_registration}
142                 onChange={linkEvent(
143                   this,
144                   this.handleSiteOpenRegistrationChange
145                 )}
146               />
147               <label class="form-check-label" for="create-site-open-registration">
148                 { i18n.t('open_registration') }
149               </label>
150             </div>
151           </div>
152         </div>
153         <div class="form-group row">
154           <div class="col-12">
155             <button type="submit" class="btn btn-secondary mr-2">
156               {this.state.loading ? (
157                 <svg class="icon icon-spinner spin">
158                   <use xlinkHref="#icon-spinner"></use>
159                 </svg>
160               ) : this.props.site ? (
161                 capitalizeFirstLetter(i18n.t('save'))
162               ) : (
163                 capitalizeFirstLetter(i18n.t('create'))
164               )}
165             </button>
166             {this.props.site && (
167               <button
168                 type="button"
169                 class="btn btn-secondary"
170                 onClick={linkEvent(this, this.handleCancel)}
171               >
172                 { i18n.t('cancel') }
173               </button>
174             )}
175           </div>
176         </div>
177       </form>
178     );
179   }
180
181   handleCreateSiteSubmit(i: SiteForm, event: any) {
182     event.preventDefault();
183     i.state.loading = true;
184     if (i.props.site) {
185       WebSocketService.Instance.editSite(i.state.siteForm);
186     } else {
187       WebSocketService.Instance.createSite(i.state.siteForm);
188     }
189     i.setState(i.state);
190   }
191
192   handleSiteNameChange(i: SiteForm, event: any) {
193     i.state.siteForm.name = event.target.value;
194     i.setState(i.state);
195   }
196
197   handleSiteDescriptionChange(i: SiteForm, event: any) {
198     i.state.siteForm.description = event.target.value;
199     i.setState(i.state);
200   }
201
202   handleSiteEnableNsfwChange(i: SiteForm, event: any) {
203     i.state.siteForm.enable_nsfw = event.target.checked;
204     i.setState(i.state);
205   }
206
207   handleSiteOpenRegistrationChange(i: SiteForm, event: any) {
208     i.state.siteForm.open_registration = event.target.checked;
209     i.setState(i.state);
210   }
211
212   handleSiteEnableDownvotesChange(i: SiteForm, event: any) {
213     i.state.siteForm.enable_downvotes = event.target.checked;
214     i.setState(i.state);
215   }
216
217   handleCancel(i: SiteForm) {
218     i.props.onCancel();
219   }
220 }