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 '../interfaces';
6 import { WebSocketService } from '../services';
7 import { capitalizeFirstLetter, randomStr } from '../utils';
8 import { i18n } from '../i18next';
10 interface SiteFormProps {
11 site?: Site; // If a site is given, that means this is an edit
15 interface SiteFormState {
20 export class SiteForm extends Component<SiteFormProps, SiteFormState> {
21 private id = `site-form-${randomStr()}`;
22 private emptyState: SiteFormState = {
24 enable_downvotes: true,
25 open_registration: true,
34 constructor(props: any, context: any) {
35 super(props, context);
37 this.state = this.emptyState;
38 this.handleSiteDescriptionChange = this.handleSiteDescriptionChange.bind(
42 this.handleIconUpload = this.handleIconUpload.bind(this);
43 this.handleIconRemove = this.handleIconRemove.bind(this);
45 this.handleBannerUpload = this.handleBannerUpload.bind(this);
46 this.handleBannerRemove = this.handleBannerRemove.bind(this);
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,
61 // Necessary to stop the loading
62 componentWillReceiveProps() {
63 this.state.loading = false;
64 this.setState(this.state);
67 componentDidUpdate() {
69 !this.state.loading &&
71 (this.state.siteForm.name || this.state.siteForm.description)
73 window.onbeforeunload = () => true;
75 window.onbeforeunload = undefined;
79 componentWillUnmount() {
80 window.onbeforeunload = null;
88 !this.state.loading &&
90 (this.state.siteForm.name || this.state.siteForm.description)
92 message={i18n.t('block_leaving')}
94 <form onSubmit={linkEvent(this, this.handleCreateSiteSubmit)}>
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">
107 id="create-site-name"
109 value={this.state.siteForm.name}
110 onInput={linkEvent(this, this.handleSiteNameChange)}
117 <div class="form-group">
118 <label>{i18n.t('icon')}</label>
120 uploadTitle={i18n.t('upload_icon')}
121 imageSrc={this.state.siteForm.icon}
122 onUpload={this.handleIconUpload}
123 onRemove={this.handleIconRemove}
127 <div class="form-group">
128 <label>{i18n.t('banner')}</label>
130 uploadTitle={i18n.t('upload_banner')}
131 imageSrc={this.state.siteForm.banner}
132 onUpload={this.handleBannerUpload}
133 onRemove={this.handleBannerRemove}
136 <div class="form-group row">
137 <label class="col-12 col-form-label" htmlFor={this.id}>
142 initialContent={this.state.siteForm.description}
143 onContentChange={this.handleSiteDescriptionChange}
144 hideNavigationWarnings
148 <div class="form-group row">
150 <div class="form-check">
152 class="form-check-input"
153 id="create-site-downvotes"
155 checked={this.state.siteForm.enable_downvotes}
158 this.handleSiteEnableDownvotesChange
161 <label class="form-check-label" htmlFor="create-site-downvotes">
162 {i18n.t('enable_downvotes')}
167 <div class="form-group row">
169 <div class="form-check">
171 class="form-check-input"
172 id="create-site-enable-nsfw"
174 checked={this.state.siteForm.enable_nsfw}
175 onChange={linkEvent(this, this.handleSiteEnableNsfwChange)}
178 class="form-check-label"
179 htmlFor="create-site-enable-nsfw"
181 {i18n.t('enable_nsfw')}
186 <div class="form-group row">
188 <div class="form-check">
190 class="form-check-input"
191 id="create-site-open-registration"
193 checked={this.state.siteForm.open_registration}
196 this.handleSiteOpenRegistrationChange
200 class="form-check-label"
201 htmlFor="create-site-open-registration"
203 {i18n.t('open_registration')}
208 <div class="form-group row">
212 class="btn btn-secondary mr-2"
213 disabled={this.state.loading}
215 {this.state.loading ? (
216 <svg class="icon icon-spinner spin">
217 <use xlinkHref="#icon-spinner"></use>
219 ) : this.props.site ? (
220 capitalizeFirstLetter(i18n.t('save'))
222 capitalizeFirstLetter(i18n.t('create'))
225 {this.props.site && (
228 class="btn btn-secondary"
229 onClick={linkEvent(this, this.handleCancel)}
241 handleCreateSiteSubmit(i: SiteForm, event: any) {
242 event.preventDefault();
243 i.state.loading = true;
245 WebSocketService.Instance.editSite(i.state.siteForm);
247 WebSocketService.Instance.createSite(i.state.siteForm);
252 handleSiteNameChange(i: SiteForm, event: any) {
253 i.state.siteForm.name = event.target.value;
257 handleSiteDescriptionChange(val: string) {
258 this.state.siteForm.description = val;
259 this.setState(this.state);
262 handleSiteEnableNsfwChange(i: SiteForm, event: any) {
263 i.state.siteForm.enable_nsfw = event.target.checked;
267 handleSiteOpenRegistrationChange(i: SiteForm, event: any) {
268 i.state.siteForm.open_registration = event.target.checked;
272 handleSiteEnableDownvotesChange(i: SiteForm, event: any) {
273 i.state.siteForm.enable_downvotes = event.target.checked;
277 handleCancel(i: SiteForm) {
281 handleIconUpload(url: string) {
282 this.state.siteForm.icon = url;
283 this.setState(this.state);
287 this.state.siteForm.icon = '';
288 this.setState(this.state);
291 handleBannerUpload(url: string) {
292 this.state.siteForm.banner = url;
293 this.setState(this.state);
296 handleBannerRemove() {
297 this.state.siteForm.banner = '';
298 this.setState(this.state);