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";
6 import { authField, capitalizeFirstLetter, wsClient } from "../../utils";
7 import { Spinner } from "../common/icon";
8 import { ImageUploadForm } from "../common/image-upload-form";
9 import { MarkdownTextArea } from "../common/markdown-textarea";
11 interface SiteFormProps {
12 site?: Site; // If a site is given, that means this is an edit
16 interface SiteFormState {
21 export class SiteForm extends Component<SiteFormProps, SiteFormState> {
22 private emptyState: SiteFormState = {
24 enable_downvotes: true,
25 open_registration: true,
30 require_email_verification: null,
31 require_application: null,
32 application_question: null,
33 private_instance: null,
39 constructor(props: any, context: any) {
40 super(props, context);
42 this.state = this.emptyState;
43 this.handleSiteSidebarChange = this.handleSiteSidebarChange.bind(this);
44 this.handleSiteApplicationQuestionChange =
45 this.handleSiteApplicationQuestionChange.bind(this);
47 this.handleIconUpload = this.handleIconUpload.bind(this);
48 this.handleIconRemove = this.handleIconRemove.bind(this);
50 this.handleBannerUpload = this.handleBannerUpload.bind(this);
51 this.handleBannerRemove = this.handleBannerRemove.bind(this);
53 if (this.props.site) {
54 let site = this.props.site;
55 this.state.siteForm = {
57 sidebar: site.sidebar,
58 description: site.description,
59 enable_downvotes: site.enable_downvotes,
60 open_registration: site.open_registration,
61 enable_nsfw: site.enable_nsfw,
62 community_creation_admin_only: site.community_creation_admin_only,
65 require_email_verification: site.require_email_verification,
66 require_application: site.require_application,
67 application_question: site.application_question,
68 private_instance: site.private_instance,
74 // Necessary to stop the loading
75 componentWillReceiveProps() {
76 this.state.loading = false;
77 this.setState(this.state);
80 componentDidUpdate() {
82 !this.state.loading &&
84 (this.state.siteForm.name ||
85 this.state.siteForm.sidebar ||
86 this.state.siteForm.application_question ||
87 this.state.siteForm.description)
89 window.onbeforeunload = () => true;
91 window.onbeforeunload = undefined;
95 componentWillUnmount() {
96 window.onbeforeunload = null;
104 !this.state.loading &&
106 (this.state.siteForm.name ||
107 this.state.siteForm.sidebar ||
108 this.state.siteForm.application_question ||
109 this.state.siteForm.description)
111 message={i18n.t("block_leaving")}
113 <form onSubmit={linkEvent(this, this.handleCreateSiteSubmit)}>
116 ? capitalizeFirstLetter(i18n.t("save"))
117 : capitalizeFirstLetter(i18n.t("name"))
118 } ${i18n.t("your_site")}`}</h5>
119 <div class="form-group row">
120 <label class="col-12 col-form-label" htmlFor="create-site-name">
126 id="create-site-name"
128 value={this.state.siteForm.name}
129 onInput={linkEvent(this, this.handleSiteNameChange)}
136 <div class="form-group">
137 <label>{i18n.t("icon")}</label>
139 uploadTitle={i18n.t("upload_icon")}
140 imageSrc={this.state.siteForm.icon}
141 onUpload={this.handleIconUpload}
142 onRemove={this.handleIconRemove}
146 <div class="form-group">
147 <label>{i18n.t("banner")}</label>
149 uploadTitle={i18n.t("upload_banner")}
150 imageSrc={this.state.siteForm.banner}
151 onUpload={this.handleBannerUpload}
152 onRemove={this.handleBannerRemove}
155 <div class="form-group row">
156 <label class="col-12 col-form-label" htmlFor="site-desc">
157 {i18n.t("description")}
164 value={this.state.siteForm.description}
165 onInput={linkEvent(this, this.handleSiteDescChange)}
170 <div class="form-group row">
171 <label class="col-12 col-form-label">{i18n.t("sidebar")}</label>
174 initialContent={this.state.siteForm.sidebar}
175 onContentChange={this.handleSiteSidebarChange}
176 hideNavigationWarnings
180 {this.state.siteForm.require_application && (
181 <div class="form-group row">
182 <label class="col-12 col-form-label">
183 {i18n.t("application_questionnaire")}
187 initialContent={this.state.siteForm.application_question}
188 onContentChange={this.handleSiteApplicationQuestionChange}
189 hideNavigationWarnings
194 <div class="form-group row">
196 <div class="form-check">
198 class="form-check-input"
199 id="create-site-downvotes"
201 checked={this.state.siteForm.enable_downvotes}
204 this.handleSiteEnableDownvotesChange
207 <label class="form-check-label" htmlFor="create-site-downvotes">
208 {i18n.t("enable_downvotes")}
213 <div class="form-group row">
215 <div class="form-check">
217 class="form-check-input"
218 id="create-site-enable-nsfw"
220 checked={this.state.siteForm.enable_nsfw}
221 onChange={linkEvent(this, this.handleSiteEnableNsfwChange)}
224 class="form-check-label"
225 htmlFor="create-site-enable-nsfw"
227 {i18n.t("enable_nsfw")}
232 <div class="form-group row">
234 <div class="form-check">
236 class="form-check-input"
237 id="create-site-open-registration"
239 checked={this.state.siteForm.open_registration}
242 this.handleSiteOpenRegistrationChange
246 class="form-check-label"
247 htmlFor="create-site-open-registration"
249 {i18n.t("open_registration")}
254 <div class="form-group row">
256 <div class="form-check">
258 class="form-check-input"
259 id="create-site-community-creation-admin-only"
261 checked={this.state.siteForm.community_creation_admin_only}
264 this.handleSiteCommunityCreationAdminOnly
268 class="form-check-label"
269 htmlFor="create-site-community-creation-admin-only"
271 {i18n.t("community_creation_admin_only")}
276 <div class="form-group row">
278 <div class="form-check">
280 class="form-check-input"
281 id="create-site-require-email-verification"
283 checked={this.state.siteForm.require_email_verification}
286 this.handleSiteRequireEmailVerification
290 class="form-check-label"
291 htmlFor="create-site-require-email-verification"
293 {i18n.t("require_email_verification")}
298 <div class="form-group row">
300 <div class="form-check">
302 class="form-check-input"
303 id="create-site-require-application"
305 checked={this.state.siteForm.require_application}
306 onChange={linkEvent(this, this.handleSiteRequireApplication)}
309 class="form-check-label"
310 htmlFor="create-site-require-application"
312 {i18n.t("require_registration_application")}
317 <div class="form-group row">
319 <div class="form-check">
321 class="form-check-input"
322 id="create-site-private-instance"
324 checked={this.state.siteForm.private_instance}
325 onChange={linkEvent(this, this.handleSitePrivateInstance)}
328 class="form-check-label"
329 htmlFor="create-site-private-instance"
331 {i18n.t("private_instance")}
336 <div class="form-group row">
340 class="btn btn-secondary mr-2"
341 disabled={this.state.loading}
343 {this.state.loading ? (
345 ) : this.props.site ? (
346 capitalizeFirstLetter(i18n.t("save"))
348 capitalizeFirstLetter(i18n.t("create"))
351 {this.props.site && (
354 class="btn btn-secondary"
355 onClick={linkEvent(this, this.handleCancel)}
367 handleCreateSiteSubmit(i: SiteForm, event: any) {
368 event.preventDefault();
369 i.state.loading = true;
371 WebSocketService.Instance.send(wsClient.editSite(i.state.siteForm));
373 let form: CreateSite = {
374 name: i.state.siteForm.name || "My site",
377 WebSocketService.Instance.send(wsClient.createSite(form));
382 handleSiteNameChange(i: SiteForm, event: any) {
383 i.state.siteForm.name = event.target.value;
387 handleSiteSidebarChange(val: string) {
388 this.state.siteForm.sidebar = val;
389 this.setState(this.state);
392 handleSiteApplicationQuestionChange(val: string) {
393 this.state.siteForm.application_question = val;
394 this.setState(this.state);
397 handleSiteDescChange(i: SiteForm, event: any) {
398 i.state.siteForm.description = event.target.value;
402 handleSiteEnableNsfwChange(i: SiteForm, event: any) {
403 i.state.siteForm.enable_nsfw = event.target.checked;
407 handleSiteOpenRegistrationChange(i: SiteForm, event: any) {
408 i.state.siteForm.open_registration = event.target.checked;
412 handleSiteCommunityCreationAdminOnly(i: SiteForm, event: any) {
413 i.state.siteForm.community_creation_admin_only = event.target.checked;
417 handleSiteEnableDownvotesChange(i: SiteForm, event: any) {
418 i.state.siteForm.enable_downvotes = event.target.checked;
422 handleSiteRequireApplication(i: SiteForm, event: any) {
423 i.state.siteForm.require_application = event.target.checked;
427 handleSiteRequireEmailVerification(i: SiteForm, event: any) {
428 i.state.siteForm.require_email_verification = event.target.checked;
432 handleSitePrivateInstance(i: SiteForm, event: any) {
433 i.state.siteForm.private_instance = event.target.checked;
437 handleCancel(i: SiteForm) {
441 handleIconUpload(url: string) {
442 this.state.siteForm.icon = url;
443 this.setState(this.state);
447 this.state.siteForm.icon = "";
448 this.setState(this.state);
451 handleBannerUpload(url: string) {
452 this.state.siteForm.banner = url;
453 this.setState(this.state);
456 handleBannerRemove() {
457 this.state.siteForm.banner = "";
458 this.setState(this.state);