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, EditSite } from 'lemmy-js-client';
6 import { WebSocketService } from '../services';
13 import { i18n } from '../i18next';
15 interface SiteFormProps {
16 site?: Site; // If a site is given, that means this is an edit
20 interface SiteFormState {
25 export class SiteForm extends Component<SiteFormProps, SiteFormState> {
26 private id = `site-form-${randomStr()}`;
27 private emptyState: SiteFormState = {
29 enable_downvotes: true,
30 open_registration: true,
40 constructor(props: any, context: any) {
41 super(props, context);
43 this.state = this.emptyState;
44 this.handleSiteDescriptionChange = this.handleSiteDescriptionChange.bind(
48 this.handleIconUpload = this.handleIconUpload.bind(this);
49 this.handleIconRemove = this.handleIconRemove.bind(this);
51 this.handleBannerUpload = this.handleBannerUpload.bind(this);
52 this.handleBannerRemove = this.handleBannerRemove.bind(this);
54 if (this.props.site) {
55 this.state.siteForm = {
56 name: this.props.site.name,
57 description: this.props.site.description,
58 enable_downvotes: this.props.site.enable_downvotes,
59 open_registration: this.props.site.open_registration,
60 enable_nsfw: this.props.site.enable_nsfw,
61 icon: this.props.site.icon,
62 banner: this.props.site.banner,
68 // Necessary to stop the loading
69 componentWillReceiveProps() {
70 this.state.loading = false;
71 this.setState(this.state);
74 componentDidUpdate() {
76 !this.state.loading &&
78 (this.state.siteForm.name || this.state.siteForm.description)
80 window.onbeforeunload = () => true;
82 window.onbeforeunload = undefined;
86 componentWillUnmount() {
87 window.onbeforeunload = null;
95 !this.state.loading &&
97 (this.state.siteForm.name || this.state.siteForm.description)
99 message={i18n.t('block_leaving')}
101 <form onSubmit={linkEvent(this, this.handleCreateSiteSubmit)}>
104 ? capitalizeFirstLetter(i18n.t('save'))
105 : capitalizeFirstLetter(i18n.t('name'))
106 } ${i18n.t('your_site')}`}</h5>
107 <div class="form-group row">
108 <label class="col-12 col-form-label" htmlFor="create-site-name">
114 id="create-site-name"
116 value={this.state.siteForm.name}
117 onInput={linkEvent(this, this.handleSiteNameChange)}
124 <div class="form-group">
125 <label>{i18n.t('icon')}</label>
127 uploadTitle={i18n.t('upload_icon')}
128 imageSrc={this.state.siteForm.icon}
129 onUpload={this.handleIconUpload}
130 onRemove={this.handleIconRemove}
134 <div class="form-group">
135 <label>{i18n.t('banner')}</label>
137 uploadTitle={i18n.t('upload_banner')}
138 imageSrc={this.state.siteForm.banner}
139 onUpload={this.handleBannerUpload}
140 onRemove={this.handleBannerRemove}
143 <div class="form-group row">
144 <label class="col-12 col-form-label" htmlFor={this.id}>
149 initialContent={this.state.siteForm.description}
150 onContentChange={this.handleSiteDescriptionChange}
151 hideNavigationWarnings
155 <div class="form-group row">
157 <div class="form-check">
159 class="form-check-input"
160 id="create-site-downvotes"
162 checked={this.state.siteForm.enable_downvotes}
165 this.handleSiteEnableDownvotesChange
168 <label class="form-check-label" htmlFor="create-site-downvotes">
169 {i18n.t('enable_downvotes')}
174 <div class="form-group row">
176 <div class="form-check">
178 class="form-check-input"
179 id="create-site-enable-nsfw"
181 checked={this.state.siteForm.enable_nsfw}
182 onChange={linkEvent(this, this.handleSiteEnableNsfwChange)}
185 class="form-check-label"
186 htmlFor="create-site-enable-nsfw"
188 {i18n.t('enable_nsfw')}
193 <div class="form-group row">
195 <div class="form-check">
197 class="form-check-input"
198 id="create-site-open-registration"
200 checked={this.state.siteForm.open_registration}
203 this.handleSiteOpenRegistrationChange
207 class="form-check-label"
208 htmlFor="create-site-open-registration"
210 {i18n.t('open_registration')}
215 <div class="form-group row">
219 class="btn btn-secondary mr-2"
220 disabled={this.state.loading}
222 {this.state.loading ? (
223 <svg class="icon icon-spinner spin">
224 <use xlinkHref="#icon-spinner"></use>
226 ) : this.props.site ? (
227 capitalizeFirstLetter(i18n.t('save'))
229 capitalizeFirstLetter(i18n.t('create'))
232 {this.props.site && (
235 class="btn btn-secondary"
236 onClick={linkEvent(this, this.handleCancel)}
248 handleCreateSiteSubmit(i: SiteForm, event: any) {
249 event.preventDefault();
250 i.state.loading = true;
252 WebSocketService.Instance.send(wsClient.editSite(i.state.siteForm));
254 WebSocketService.Instance.send(wsClient.createSite(i.state.siteForm));
259 handleSiteNameChange(i: SiteForm, event: any) {
260 i.state.siteForm.name = event.target.value;
264 handleSiteDescriptionChange(val: string) {
265 this.state.siteForm.description = val;
266 this.setState(this.state);
269 handleSiteEnableNsfwChange(i: SiteForm, event: any) {
270 i.state.siteForm.enable_nsfw = event.target.checked;
274 handleSiteOpenRegistrationChange(i: SiteForm, event: any) {
275 i.state.siteForm.open_registration = event.target.checked;
279 handleSiteEnableDownvotesChange(i: SiteForm, event: any) {
280 i.state.siteForm.enable_downvotes = event.target.checked;
284 handleCancel(i: SiteForm) {
288 handleIconUpload(url: string) {
289 this.state.siteForm.icon = url;
290 this.setState(this.state);
294 this.state.siteForm.icon = '';
295 this.setState(this.state);
298 handleBannerUpload(url: string) {
299 this.state.siteForm.banner = url;
300 this.setState(this.state);
303 handleBannerRemove() {
304 this.state.siteForm.banner = '';
305 this.setState(this.state);