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
22 interface SiteFormState {
28 export class SiteForm extends Component<SiteFormProps, SiteFormState> {
29 private emptyState: SiteFormState = {
31 enable_downvotes: true,
32 open_registration: true,
37 require_email_verification: null,
38 require_application: null,
39 application_question: null,
40 private_instance: null,
42 auth: authField(false),
48 constructor(props: any, context: any) {
49 super(props, context);
51 this.state = this.emptyState;
52 this.handleSiteSidebarChange = this.handleSiteSidebarChange.bind(this);
53 this.handleSiteApplicationQuestionChange =
54 this.handleSiteApplicationQuestionChange.bind(this);
56 this.handleIconUpload = this.handleIconUpload.bind(this);
57 this.handleIconRemove = this.handleIconRemove.bind(this);
59 this.handleBannerUpload = this.handleBannerUpload.bind(this);
60 this.handleBannerRemove = this.handleBannerRemove.bind(this);
62 if (this.props.site) {
63 let site = this.props.site;
64 this.state.siteForm = {
66 sidebar: site.sidebar,
67 description: site.description,
68 enable_downvotes: site.enable_downvotes,
69 open_registration: site.open_registration,
70 enable_nsfw: site.enable_nsfw,
71 community_creation_admin_only: site.community_creation_admin_only,
74 require_email_verification: site.require_email_verification,
75 require_application: site.require_application,
76 application_question: site.application_question,
77 private_instance: site.private_instance,
78 default_theme: site.default_theme,
79 auth: authField(false),
84 async componentDidMount() {
85 this.state.themeList = await fetchThemeList();
86 this.setState(this.state);
89 // Necessary to stop the loading
90 componentWillReceiveProps() {
91 this.state.loading = false;
92 this.setState(this.state);
95 componentDidUpdate() {
97 !this.state.loading &&
99 (this.state.siteForm.name ||
100 this.state.siteForm.sidebar ||
101 this.state.siteForm.application_question ||
102 this.state.siteForm.description)
104 window.onbeforeunload = () => true;
106 window.onbeforeunload = undefined;
110 componentWillUnmount() {
111 window.onbeforeunload = null;
119 !this.state.loading &&
121 (this.state.siteForm.name ||
122 this.state.siteForm.sidebar ||
123 this.state.siteForm.application_question ||
124 this.state.siteForm.description)
126 message={i18n.t("block_leaving")}
128 <form onSubmit={linkEvent(this, this.handleCreateSiteSubmit)}>
131 ? capitalizeFirstLetter(i18n.t("save"))
132 : capitalizeFirstLetter(i18n.t("name"))
133 } ${i18n.t("your_site")}`}</h5>
134 <div class="form-group row">
135 <label class="col-12 col-form-label" htmlFor="create-site-name">
141 id="create-site-name"
143 value={this.state.siteForm.name}
144 onInput={linkEvent(this, this.handleSiteNameChange)}
151 <div class="form-group">
152 <label>{i18n.t("icon")}</label>
154 uploadTitle={i18n.t("upload_icon")}
155 imageSrc={this.state.siteForm.icon}
156 onUpload={this.handleIconUpload}
157 onRemove={this.handleIconRemove}
161 <div class="form-group">
162 <label>{i18n.t("banner")}</label>
164 uploadTitle={i18n.t("upload_banner")}
165 imageSrc={this.state.siteForm.banner}
166 onUpload={this.handleBannerUpload}
167 onRemove={this.handleBannerRemove}
170 <div class="form-group row">
171 <label class="col-12 col-form-label" htmlFor="site-desc">
172 {i18n.t("description")}
179 value={this.state.siteForm.description}
180 onInput={linkEvent(this, this.handleSiteDescChange)}
185 <div class="form-group row">
186 <label class="col-12 col-form-label">{i18n.t("sidebar")}</label>
189 initialContent={this.state.siteForm.sidebar}
190 onContentChange={this.handleSiteSidebarChange}
191 hideNavigationWarnings
195 {this.state.siteForm.require_application && (
196 <div class="form-group row">
197 <label class="col-12 col-form-label">
198 {i18n.t("application_questionnaire")}
202 initialContent={this.state.siteForm.application_question}
203 onContentChange={this.handleSiteApplicationQuestionChange}
204 hideNavigationWarnings
209 <div class="form-group row">
211 <div class="form-check">
213 class="form-check-input"
214 id="create-site-downvotes"
216 checked={this.state.siteForm.enable_downvotes}
219 this.handleSiteEnableDownvotesChange
222 <label class="form-check-label" htmlFor="create-site-downvotes">
223 {i18n.t("enable_downvotes")}
228 <div class="form-group row">
230 <div class="form-check">
232 class="form-check-input"
233 id="create-site-enable-nsfw"
235 checked={this.state.siteForm.enable_nsfw}
236 onChange={linkEvent(this, this.handleSiteEnableNsfwChange)}
239 class="form-check-label"
240 htmlFor="create-site-enable-nsfw"
242 {i18n.t("enable_nsfw")}
247 <div class="form-group row">
249 <div class="form-check">
251 class="form-check-input"
252 id="create-site-open-registration"
254 checked={this.state.siteForm.open_registration}
257 this.handleSiteOpenRegistrationChange
261 class="form-check-label"
262 htmlFor="create-site-open-registration"
264 {i18n.t("open_registration")}
269 <div class="form-group row">
271 <div class="form-check">
273 class="form-check-input"
274 id="create-site-community-creation-admin-only"
276 checked={this.state.siteForm.community_creation_admin_only}
279 this.handleSiteCommunityCreationAdminOnly
283 class="form-check-label"
284 htmlFor="create-site-community-creation-admin-only"
286 {i18n.t("community_creation_admin_only")}
291 <div class="form-group row">
293 <div class="form-check">
295 class="form-check-input"
296 id="create-site-require-email-verification"
298 checked={this.state.siteForm.require_email_verification}
301 this.handleSiteRequireEmailVerification
305 class="form-check-label"
306 htmlFor="create-site-require-email-verification"
308 {i18n.t("require_email_verification")}
313 <div class="form-group row">
315 <div class="form-check">
317 class="form-check-input"
318 id="create-site-require-application"
320 checked={this.state.siteForm.require_application}
321 onChange={linkEvent(this, this.handleSiteRequireApplication)}
324 class="form-check-label"
325 htmlFor="create-site-require-application"
327 {i18n.t("require_registration_application")}
332 <div class="form-group row">
335 class="form-check-label mr-2"
336 htmlFor="create-site-default-theme"
341 id="create-site-default-theme"
342 value={this.state.siteForm.default_theme}
343 onChange={linkEvent(this, this.handleSiteDefaultTheme)}
344 class="custom-select w-auto"
346 <option value="browser">{i18n.t("browser_default")}</option>
347 {this.state.themeList.map(theme => (
348 <option value={theme}>{theme}</option>
353 <div class="form-group row">
355 <div class="form-check">
357 class="form-check-input"
358 id="create-site-private-instance"
360 value={this.state.siteForm.default_theme}
361 onChange={linkEvent(this, this.handleSitePrivateInstance)}
364 class="form-check-label"
365 htmlFor="create-site-private-instance"
367 {i18n.t("private_instance")}
372 <div class="form-group row">
376 class="btn btn-secondary mr-2"
377 disabled={this.state.loading}
379 {this.state.loading ? (
381 ) : this.props.site ? (
382 capitalizeFirstLetter(i18n.t("save"))
384 capitalizeFirstLetter(i18n.t("create"))
387 {this.props.site && (
390 class="btn btn-secondary"
391 onClick={linkEvent(this, this.handleCancel)}
403 handleCreateSiteSubmit(i: SiteForm, event: any) {
404 event.preventDefault();
405 i.state.loading = true;
407 WebSocketService.Instance.send(wsClient.editSite(i.state.siteForm));
410 let form: CreateSite = {
411 name: i.state.siteForm.name || "My site",
414 WebSocketService.Instance.send(wsClient.createSite(form));
419 handleSiteNameChange(i: SiteForm, event: any) {
420 i.state.siteForm.name = event.target.value;
424 handleSiteSidebarChange(val: string) {
425 this.state.siteForm.sidebar = val;
426 this.setState(this.state);
429 handleSiteApplicationQuestionChange(val: string) {
430 this.state.siteForm.application_question = val;
431 this.setState(this.state);
434 handleSiteDescChange(i: SiteForm, event: any) {
435 i.state.siteForm.description = event.target.value;
439 handleSiteEnableNsfwChange(i: SiteForm, event: any) {
440 i.state.siteForm.enable_nsfw = event.target.checked;
444 handleSiteOpenRegistrationChange(i: SiteForm, event: any) {
445 i.state.siteForm.open_registration = event.target.checked;
449 handleSiteCommunityCreationAdminOnly(i: SiteForm, event: any) {
450 i.state.siteForm.community_creation_admin_only = event.target.checked;
454 handleSiteEnableDownvotesChange(i: SiteForm, event: any) {
455 i.state.siteForm.enable_downvotes = event.target.checked;
459 handleSiteRequireApplication(i: SiteForm, event: any) {
460 i.state.siteForm.require_application = event.target.checked;
464 handleSiteRequireEmailVerification(i: SiteForm, event: any) {
465 i.state.siteForm.require_email_verification = event.target.checked;
469 handleSitePrivateInstance(i: SiteForm, event: any) {
470 i.state.siteForm.private_instance = event.target.checked;
474 handleSiteDefaultTheme(i: SiteForm, event: any) {
475 i.state.siteForm.default_theme = event.target.value;
479 handleCancel(i: SiteForm) {
483 handleIconUpload(url: string) {
484 this.state.siteForm.icon = url;
485 this.setState(this.state);
489 this.state.siteForm.icon = "";
490 this.setState(this.state);
493 handleBannerUpload(url: string) {
494 this.state.siteForm.banner = url;
495 this.setState(this.state);
498 handleBannerRemove() {
499 this.state.siteForm.banner = "";
500 this.setState(this.state);