1 import { Component, linkEvent } from "inferno";
2 import { Prompt } from "inferno-router";
3 import { CreateSite, EditSite, Site } from "lemmy-js-client";
4 import { i18n } from "../../i18next";
5 import { WebSocketService } from "../../services";
12 import { Spinner } from "../common/icon";
13 import { ImageUploadForm } from "../common/image-upload-form";
14 import { MarkdownTextArea } from "../common/markdown-textarea";
16 interface SiteFormProps {
17 site?: Site; // If a site is given, that means this is an edit
21 interface SiteFormState {
26 export class SiteForm extends Component<SiteFormProps, SiteFormState> {
27 private emptyState: SiteFormState = {
29 enable_downvotes: true,
30 open_registration: true,
35 require_email_verification: null,
36 require_application: null,
37 application_question: null,
38 private_instance: null,
45 constructor(props: any, context: any) {
46 super(props, context);
48 this.state = this.emptyState;
49 this.handleSiteSidebarChange = this.handleSiteSidebarChange.bind(this);
50 this.handleSiteApplicationQuestionChange =
51 this.handleSiteApplicationQuestionChange.bind(this);
53 this.handleIconUpload = this.handleIconUpload.bind(this);
54 this.handleIconRemove = this.handleIconRemove.bind(this);
56 this.handleBannerUpload = this.handleBannerUpload.bind(this);
57 this.handleBannerRemove = this.handleBannerRemove.bind(this);
59 if (this.props.site) {
60 let site = this.props.site;
61 this.state.siteForm = {
63 sidebar: site.sidebar,
64 description: site.description,
65 enable_downvotes: site.enable_downvotes,
66 open_registration: site.open_registration,
67 enable_nsfw: site.enable_nsfw,
68 community_creation_admin_only: site.community_creation_admin_only,
71 require_email_verification: site.require_email_verification,
72 require_application: site.require_application,
73 application_question: site.application_question,
74 private_instance: site.private_instance,
75 default_theme: site.default_theme,
81 // Necessary to stop the loading
82 componentWillReceiveProps() {
83 this.state.loading = false;
84 this.setState(this.state);
87 componentDidUpdate() {
89 !this.state.loading &&
91 (this.state.siteForm.name ||
92 this.state.siteForm.sidebar ||
93 this.state.siteForm.application_question ||
94 this.state.siteForm.description)
96 window.onbeforeunload = () => true;
98 window.onbeforeunload = undefined;
102 componentWillUnmount() {
103 window.onbeforeunload = null;
111 !this.state.loading &&
113 (this.state.siteForm.name ||
114 this.state.siteForm.sidebar ||
115 this.state.siteForm.application_question ||
116 this.state.siteForm.description)
118 message={i18n.t("block_leaving")}
120 <form onSubmit={linkEvent(this, this.handleCreateSiteSubmit)}>
123 ? capitalizeFirstLetter(i18n.t("save"))
124 : capitalizeFirstLetter(i18n.t("name"))
125 } ${i18n.t("your_site")}`}</h5>
126 <div class="form-group row">
127 <label class="col-12 col-form-label" htmlFor="create-site-name">
133 id="create-site-name"
135 value={this.state.siteForm.name}
136 onInput={linkEvent(this, this.handleSiteNameChange)}
143 <div class="form-group">
144 <label>{i18n.t("icon")}</label>
146 uploadTitle={i18n.t("upload_icon")}
147 imageSrc={this.state.siteForm.icon}
148 onUpload={this.handleIconUpload}
149 onRemove={this.handleIconRemove}
153 <div class="form-group">
154 <label>{i18n.t("banner")}</label>
156 uploadTitle={i18n.t("upload_banner")}
157 imageSrc={this.state.siteForm.banner}
158 onUpload={this.handleBannerUpload}
159 onRemove={this.handleBannerRemove}
162 <div class="form-group row">
163 <label class="col-12 col-form-label" htmlFor="site-desc">
164 {i18n.t("description")}
171 value={this.state.siteForm.description}
172 onInput={linkEvent(this, this.handleSiteDescChange)}
177 <div class="form-group row">
178 <label class="col-12 col-form-label">{i18n.t("sidebar")}</label>
181 initialContent={this.state.siteForm.sidebar}
182 onContentChange={this.handleSiteSidebarChange}
183 hideNavigationWarnings
187 {this.state.siteForm.require_application && (
188 <div class="form-group row">
189 <label class="col-12 col-form-label">
190 {i18n.t("application_questionnaire")}
194 initialContent={this.state.siteForm.application_question}
195 onContentChange={this.handleSiteApplicationQuestionChange}
196 hideNavigationWarnings
201 <div class="form-group row">
203 <div class="form-check">
205 class="form-check-input"
206 id="create-site-downvotes"
208 checked={this.state.siteForm.enable_downvotes}
211 this.handleSiteEnableDownvotesChange
214 <label class="form-check-label" htmlFor="create-site-downvotes">
215 {i18n.t("enable_downvotes")}
220 <div class="form-group row">
222 <div class="form-check">
224 class="form-check-input"
225 id="create-site-enable-nsfw"
227 checked={this.state.siteForm.enable_nsfw}
228 onChange={linkEvent(this, this.handleSiteEnableNsfwChange)}
231 class="form-check-label"
232 htmlFor="create-site-enable-nsfw"
234 {i18n.t("enable_nsfw")}
239 <div class="form-group row">
241 <div class="form-check">
243 class="form-check-input"
244 id="create-site-open-registration"
246 checked={this.state.siteForm.open_registration}
249 this.handleSiteOpenRegistrationChange
253 class="form-check-label"
254 htmlFor="create-site-open-registration"
256 {i18n.t("open_registration")}
261 <div class="form-group row">
263 <div class="form-check">
265 class="form-check-input"
266 id="create-site-community-creation-admin-only"
268 checked={this.state.siteForm.community_creation_admin_only}
271 this.handleSiteCommunityCreationAdminOnly
275 class="form-check-label"
276 htmlFor="create-site-community-creation-admin-only"
278 {i18n.t("community_creation_admin_only")}
283 <div class="form-group row">
285 <div class="form-check">
287 class="form-check-input"
288 id="create-site-require-email-verification"
290 checked={this.state.siteForm.require_email_verification}
293 this.handleSiteRequireEmailVerification
297 class="form-check-label"
298 htmlFor="create-site-require-email-verification"
300 {i18n.t("require_email_verification")}
305 <div class="form-group row">
307 <div class="form-check">
309 class="form-check-input"
310 id="create-site-require-application"
312 checked={this.state.siteForm.require_application}
313 onChange={linkEvent(this, this.handleSiteRequireApplication)}
316 class="form-check-label"
317 htmlFor="create-site-require-application"
319 {i18n.t("require_registration_application")}
324 <div class="form-group row">
327 class="form-check-label mr-2"
328 htmlFor="create-site-default-theme"
333 id="create-site-default-theme"
334 value={this.state.siteForm.default_theme}
335 onChange={linkEvent(this, this.handleSiteDefaultTheme)}
336 class="custom-select w-auto"
338 <option value="browser">{i18n.t("browser_default")}</option>
339 {themes.map(theme => (
340 <option value={theme}>{theme}</option>
345 <div class="form-group row">
347 <div class="form-check">
349 class="form-check-input"
350 id="create-site-private-instance"
352 value={this.state.siteForm.default_theme}
353 onChange={linkEvent(this, this.handleSitePrivateInstance)}
356 class="form-check-label"
357 htmlFor="create-site-private-instance"
359 {i18n.t("private_instance")}
364 <div class="form-group row">
368 class="btn btn-secondary mr-2"
369 disabled={this.state.loading}
371 {this.state.loading ? (
373 ) : this.props.site ? (
374 capitalizeFirstLetter(i18n.t("save"))
376 capitalizeFirstLetter(i18n.t("create"))
379 {this.props.site && (
382 class="btn btn-secondary"
383 onClick={linkEvent(this, this.handleCancel)}
395 handleCreateSiteSubmit(i: SiteForm, event: any) {
396 event.preventDefault();
397 i.state.loading = true;
399 WebSocketService.Instance.send(wsClient.editSite(i.state.siteForm));
401 let form: CreateSite = {
402 name: i.state.siteForm.name || "My site",
405 WebSocketService.Instance.send(wsClient.createSite(form));
410 handleSiteNameChange(i: SiteForm, event: any) {
411 i.state.siteForm.name = event.target.value;
415 handleSiteSidebarChange(val: string) {
416 this.state.siteForm.sidebar = val;
417 this.setState(this.state);
420 handleSiteApplicationQuestionChange(val: string) {
421 this.state.siteForm.application_question = val;
422 this.setState(this.state);
425 handleSiteDescChange(i: SiteForm, event: any) {
426 i.state.siteForm.description = event.target.value;
430 handleSiteEnableNsfwChange(i: SiteForm, event: any) {
431 i.state.siteForm.enable_nsfw = event.target.checked;
435 handleSiteOpenRegistrationChange(i: SiteForm, event: any) {
436 i.state.siteForm.open_registration = event.target.checked;
440 handleSiteCommunityCreationAdminOnly(i: SiteForm, event: any) {
441 i.state.siteForm.community_creation_admin_only = event.target.checked;
445 handleSiteEnableDownvotesChange(i: SiteForm, event: any) {
446 i.state.siteForm.enable_downvotes = event.target.checked;
450 handleSiteRequireApplication(i: SiteForm, event: any) {
451 i.state.siteForm.require_application = event.target.checked;
455 handleSiteRequireEmailVerification(i: SiteForm, event: any) {
456 i.state.siteForm.require_email_verification = event.target.checked;
460 handleSitePrivateInstance(i: SiteForm, event: any) {
461 i.state.siteForm.private_instance = event.target.checked;
465 handleSiteDefaultTheme(i: SiteForm, event: any) {
466 i.state.siteForm.default_theme = event.target.value;
470 handleCancel(i: SiteForm) {
474 handleIconUpload(url: string) {
475 this.state.siteForm.icon = url;
476 this.setState(this.state);
480 this.state.siteForm.icon = "";
481 this.setState(this.state);
484 handleBannerUpload(url: string) {
485 this.state.siteForm.banner = url;
486 this.setState(this.state);
489 handleBannerRemove() {
490 this.state.siteForm.banner = "";
491 this.setState(this.state);