7 import { Prompt } from "inferno-router";
11 GetFederatedInstancesResponse,
14 } from "lemmy-js-client";
15 import { i18n } from "../../i18next";
16 import { WebSocketService } from "../../services";
18 capitalizeFirstLetter,
23 import { Icon, Spinner } from "../common/icon";
24 import { ImageUploadForm } from "../common/image-upload-form";
25 import { LanguageSelect } from "../common/language-select";
26 import { ListingTypeSelect } from "../common/listing-type-select";
27 import { MarkdownTextArea } from "../common/markdown-textarea";
29 interface SiteFormProps {
30 siteRes: GetSiteResponse;
31 instancesRes?: GetFederatedInstancesResponse;
35 interface SiteFormState {
40 allowed_instances: string;
41 blocked_instances: string;
45 type InstanceKey = "allowed_instances" | "blocked_instances";
47 export class SiteForm extends Component<SiteFormProps, SiteFormState> {
48 state: SiteFormState = {
54 allowed_instances: "",
55 blocked_instances: "",
59 constructor(props: any, context: any) {
60 super(props, context);
62 this.handleSiteSidebarChange = this.handleSiteSidebarChange.bind(this);
63 this.handleSiteLegalInfoChange = this.handleSiteLegalInfoChange.bind(this);
64 this.handleSiteApplicationQuestionChange =
65 this.handleSiteApplicationQuestionChange.bind(this);
67 this.handleIconUpload = this.handleIconUpload.bind(this);
68 this.handleIconRemove = this.handleIconRemove.bind(this);
70 this.handleBannerUpload = this.handleBannerUpload.bind(this);
71 this.handleBannerRemove = this.handleBannerRemove.bind(this);
73 this.handleDefaultPostListingTypeChange =
74 this.handleDefaultPostListingTypeChange.bind(this);
76 this.handleDiscussionLanguageChange =
77 this.handleDiscussionLanguageChange.bind(this);
79 let site = this.props.siteRes.site_view.site;
80 let ls = this.props.siteRes.site_view.local_site;
81 let lsrl = this.props.siteRes.site_view.local_site_rate_limit;
86 sidebar: site.sidebar,
87 description: site.description,
88 enable_downvotes: ls.enable_downvotes,
89 registration_mode: ls.registration_mode,
90 enable_nsfw: ls.enable_nsfw,
91 community_creation_admin_only: ls.community_creation_admin_only,
94 require_email_verification: ls.require_email_verification,
95 application_question: ls.application_question,
96 private_instance: ls.private_instance,
97 default_theme: ls.default_theme,
98 default_post_listing_type: ls.default_post_listing_type,
99 legal_information: ls.legal_information,
100 application_email_admins: ls.application_email_admins,
101 reports_email_admins: ls.reports_email_admins,
102 hide_modlog_mod_names: ls.hide_modlog_mod_names,
103 discussion_languages: this.props.siteRes.discussion_languages,
104 slur_filter_regex: ls.slur_filter_regex,
105 actor_name_max_length: ls.actor_name_max_length,
106 rate_limit_message: lsrl.message,
107 rate_limit_message_per_second: lsrl.message_per_second,
108 rate_limit_comment: lsrl.comment,
109 rate_limit_comment_per_second: lsrl.comment_per_second,
110 rate_limit_image: lsrl.image,
111 rate_limit_image_per_second: lsrl.image_per_second,
112 rate_limit_post: lsrl.post,
113 rate_limit_post_per_second: lsrl.post_per_second,
114 rate_limit_register: lsrl.register,
115 rate_limit_register_per_second: lsrl.register_per_second,
116 rate_limit_search: lsrl.search,
117 rate_limit_search_per_second: lsrl.search_per_second,
118 federation_enabled: ls.federation_enabled,
119 federation_debug: ls.federation_debug,
120 federation_worker_count: ls.federation_worker_count,
121 captcha_enabled: ls.captcha_enabled,
122 captcha_difficulty: ls.captcha_difficulty,
124 this.props.instancesRes?.federated_instances?.allowed.map(
128 this.props.instancesRes?.federated_instances?.blocked.map(
136 async componentDidMount() {
137 this.setState({ themeList: await fetchThemeList() });
140 // Necessary to stop the loading
141 componentWillReceiveProps() {
142 this.setState({ loading: false });
145 componentDidUpdate() {
147 !this.state.loading &&
148 !this.props.siteRes.site_view.local_site.site_setup &&
149 (this.state.siteForm.name ||
150 this.state.siteForm.sidebar ||
151 this.state.siteForm.application_question ||
152 this.state.siteForm.description)
154 window.onbeforeunload = () => true;
156 window.onbeforeunload = null;
160 componentWillUnmount() {
161 window.onbeforeunload = null;
165 let siteSetup = this.props.siteRes.site_view.local_site.site_setup;
170 !this.state.loading &&
172 (this.state.siteForm.name ||
173 this.state.siteForm.sidebar ||
174 this.state.siteForm.application_question ||
175 this.state.siteForm.description)
177 message={i18n.t("block_leaving")}
179 <form onSubmit={linkEvent(this, this.handleCreateSiteSubmit)}>
182 ? capitalizeFirstLetter(i18n.t("save"))
183 : capitalizeFirstLetter(i18n.t("name"))
184 } ${i18n.t("your_site")}`}</h5>
185 <div className="form-group row">
186 <label className="col-12 col-form-label" htmlFor="create-site-name">
189 <div className="col-12">
192 id="create-site-name"
193 className="form-control"
194 value={this.state.siteForm.name}
195 onInput={linkEvent(this, this.handleSiteNameChange)}
202 <div className="form-group">
203 <label>{i18n.t("icon")}</label>
205 uploadTitle={i18n.t("upload_icon")}
206 imageSrc={this.state.siteForm.icon}
207 onUpload={this.handleIconUpload}
208 onRemove={this.handleIconRemove}
212 <div className="form-group">
213 <label>{i18n.t("banner")}</label>
215 uploadTitle={i18n.t("upload_banner")}
216 imageSrc={this.state.siteForm.banner}
217 onUpload={this.handleBannerUpload}
218 onRemove={this.handleBannerRemove}
221 <div className="form-group row">
222 <label className="col-12 col-form-label" htmlFor="site-desc">
223 {i18n.t("description")}
225 <div className="col-12">
228 className="form-control"
230 value={this.state.siteForm.description}
231 onInput={linkEvent(this, this.handleSiteDescChange)}
236 <div className="form-group row">
237 <label className="col-12 col-form-label">{i18n.t("sidebar")}</label>
238 <div className="col-12">
240 initialContent={this.state.siteForm.sidebar}
241 onContentChange={this.handleSiteSidebarChange}
242 hideNavigationWarnings
248 <div className="form-group row">
249 <label className="col-12 col-form-label">
250 {i18n.t("legal_information")}
252 <div className="col-12">
254 initialContent={this.state.siteForm.legal_information}
255 onContentChange={this.handleSiteLegalInfoChange}
256 hideNavigationWarnings
262 <div className="form-group row">
263 <div className="col-12">
264 <div className="form-check">
266 className="form-check-input"
267 id="create-site-downvotes"
269 checked={this.state.siteForm.enable_downvotes}
272 this.handleSiteEnableDownvotesChange
276 className="form-check-label"
277 htmlFor="create-site-downvotes"
279 {i18n.t("enable_downvotes")}
284 <div className="form-group row">
285 <div className="col-12">
286 <div className="form-check">
288 className="form-check-input"
289 id="create-site-enable-nsfw"
291 checked={this.state.siteForm.enable_nsfw}
292 onChange={linkEvent(this, this.handleSiteEnableNsfwChange)}
295 className="form-check-label"
296 htmlFor="create-site-enable-nsfw"
298 {i18n.t("enable_nsfw")}
303 <div className="form-group row">
304 <div className="col-12">
306 className="form-check-label mr-2"
307 htmlFor="create-site-registration-mode"
309 {i18n.t("registration_mode")}
312 id="create-site-registration-mode"
313 value={this.state.siteForm.registration_mode}
316 this.handleSiteRegistrationModeChange
318 className="custom-select w-auto"
320 <option value={"RequireApplication"}>
321 {i18n.t("require_registration_application")}
323 <option value={"Open"}>{i18n.t("open_registration")}</option>
324 <option value={"Closed"}>{i18n.t("close_registration")}</option>
328 {this.state.siteForm.registration_mode == "RequireApplication" && (
329 <div className="form-group row">
330 <label className="col-12 col-form-label">
331 {i18n.t("application_questionnaire")}
333 <div className="col-12">
335 initialContent={this.state.siteForm.application_question}
336 onContentChange={this.handleSiteApplicationQuestionChange}
337 hideNavigationWarnings
344 <div className="form-group row">
345 <div className="col-12">
346 <div className="form-check">
348 className="form-check-input"
349 id="create-site-community-creation-admin-only"
351 checked={this.state.siteForm.community_creation_admin_only}
354 this.handleSiteCommunityCreationAdminOnly
358 className="form-check-label"
359 htmlFor="create-site-community-creation-admin-only"
361 {i18n.t("community_creation_admin_only")}
366 <div className="form-group row">
367 <div className="col-12">
368 <div className="form-check">
370 className="form-check-input"
371 id="create-site-require-email-verification"
373 checked={this.state.siteForm.require_email_verification}
376 this.handleSiteRequireEmailVerification
380 className="form-check-label"
381 htmlFor="create-site-require-email-verification"
383 {i18n.t("require_email_verification")}
388 <div className="form-group row">
389 <div className="col-12">
390 <div className="form-check">
392 className="form-check-input"
393 id="create-site-application-email-admins"
395 checked={this.state.siteForm.application_email_admins}
398 this.handleSiteApplicationEmailAdmins
402 className="form-check-label"
403 htmlFor="create-site-email-admins"
405 {i18n.t("application_email_admins")}
410 <div className="form-group row">
411 <div className="col-12">
412 <div className="form-check">
414 className="form-check-input"
415 id="create-site-reports-email-admins"
417 checked={this.state.siteForm.reports_email_admins}
418 onChange={linkEvent(this, this.handleSiteReportsEmailAdmins)}
421 className="form-check-label"
422 htmlFor="create-site-reports-email-admins"
424 {i18n.t("reports_email_admins")}
429 <div className="form-group row">
430 <div className="col-12">
432 className="form-check-label mr-2"
433 htmlFor="create-site-default-theme"
438 id="create-site-default-theme"
439 value={this.state.siteForm.default_theme}
440 onChange={linkEvent(this, this.handleSiteDefaultTheme)}
441 className="custom-select w-auto"
443 <option value="browser">{i18n.t("browser_default")}</option>
444 {this.state.themeList?.map(theme => (
445 <option key={theme} value={theme}>
452 {this.props.showLocal && (
453 <form className="form-group row">
454 <label className="col-sm-3">{i18n.t("listing_type")}</label>
455 <div className="col-sm-9">
458 this.state.siteForm.default_post_listing_type ?? "Local"
461 showSubscribed={false}
462 onChange={this.handleDefaultPostListingTypeChange}
467 <div className="form-group row">
468 <div className="col-12">
469 <div className="form-check">
471 className="form-check-input"
472 id="create-site-private-instance"
474 checked={this.state.siteForm.private_instance}
475 onChange={linkEvent(this, this.handleSitePrivateInstance)}
478 className="form-check-label"
479 htmlFor="create-site-private-instance"
481 {i18n.t("private_instance")}
486 <div className="form-group row">
487 <div className="col-12">
488 <div className="form-check">
490 className="form-check-input"
491 id="create-site-hide-modlog-mod-names"
493 checked={this.state.siteForm.hide_modlog_mod_names}
494 onChange={linkEvent(this, this.handleSiteHideModlogModNames)}
497 className="form-check-label"
498 htmlFor="create-site-hide-modlog-mod-names"
500 {i18n.t("hide_modlog_mod_names")}
505 <div className="form-group row">
507 className="col-12 col-form-label"
508 htmlFor="create-site-slur-filter-regex"
510 {i18n.t("slur_filter_regex")}
512 <div className="col-12">
515 id="create-site-slur-filter-regex"
516 placeholder="(word1|word2)"
517 className="form-control"
518 value={this.state.siteForm.slur_filter_regex}
519 onInput={linkEvent(this, this.handleSiteSlurFilterRegex)}
525 allLanguages={this.props.siteRes.all_languages}
526 siteLanguages={this.props.siteRes.discussion_languages}
527 selectedLanguageIds={this.state.siteForm.discussion_languages}
529 onChange={this.handleDiscussionLanguageChange}
532 <div className="form-group row">
534 className="col-12 col-form-label"
535 htmlFor="create-site-actor-name"
537 {i18n.t("actor_name_max_length")}
539 <div className="col-12">
542 id="create-site-actor-name"
543 className="form-control"
545 value={this.state.siteForm.actor_name_max_length}
546 onInput={linkEvent(this, this.handleSiteActorNameMaxLength)}
550 <div className="form-group row">
551 <div className="col-12">
552 <div className="form-check">
554 className="form-check-input"
555 id="create-site-federation-enabled"
557 checked={this.state.siteForm.federation_enabled}
558 onChange={linkEvent(this, this.handleSiteFederationEnabled)}
561 className="form-check-label"
562 htmlFor="create-site-federation-enabled"
564 {i18n.t("federation_enabled")}
569 {this.state.siteForm.federation_enabled && (
571 <div className="form-group row">
572 {this.federatedInstanceSelect("allowed_instances")}
573 {this.federatedInstanceSelect("blocked_instances")}
575 <div className="form-group row">
576 <div className="col-12">
577 <div className="form-check">
579 className="form-check-input"
580 id="create-site-federation-debug"
582 checked={this.state.siteForm.federation_debug}
583 onChange={linkEvent(this, this.handleSiteFederationDebug)}
586 className="form-check-label"
587 htmlFor="create-site-federation-debug"
589 {i18n.t("federation_debug")}
594 <div className="form-group row">
596 className="col-12 col-form-label"
597 htmlFor="create-site-federation-worker-count"
599 {i18n.t("federation_worker_count")}
601 <div className="col-12">
604 id="create-site-federation-worker-count"
605 className="form-control"
607 value={this.state.siteForm.federation_worker_count}
610 this.handleSiteFederationWorkerCount
617 <div className="form-group row">
618 <div className="col-12">
619 <div className="form-check">
621 className="form-check-input"
622 id="create-site-captcha-enabled"
624 checked={this.state.siteForm.captcha_enabled}
625 onChange={linkEvent(this, this.handleSiteCaptchaEnabled)}
628 className="form-check-label"
629 htmlFor="create-site-captcha-enabled"
631 {i18n.t("captcha_enabled")}
636 {this.state.siteForm.captcha_enabled && (
637 <div className="form-group row">
638 <div className="col-12">
640 className="form-check-label mr-2"
641 htmlFor="create-site-captcha-difficulty"
643 {i18n.t("captcha_difficulty")}
646 id="create-site-captcha-difficulty"
647 value={this.state.siteForm.captcha_difficulty}
648 onChange={linkEvent(this, this.handleSiteCaptchaDifficulty)}
649 className="custom-select w-auto"
651 <option value="easy">{i18n.t("easy")}</option>
652 <option value="medium">{i18n.t("medium")}</option>
653 <option value="hard">{i18n.t("hard")}</option>
658 <div className="form-group row">
660 className="col-12 col-form-label"
661 htmlFor="create-site-rate-limit-message"
663 {i18n.t("rate_limit_message")}
665 <div className="col-12">
668 id="create-site-rate-limit-message"
669 className="form-control"
671 value={this.state.siteForm.rate_limit_message}
672 onInput={linkEvent(this, this.handleSiteRateLimitMessage)}
676 <div className="form-group row">
678 className="col-12 col-form-label"
679 htmlFor="create-site-rate-limit-message-per-second"
681 {i18n.t("per_second")}
683 <div className="col-12">
686 id="create-site-rate-limit-message-per-second"
687 className="form-control"
689 value={this.state.siteForm.rate_limit_message_per_second}
692 this.handleSiteRateLimitMessagePerSecond
697 <div className="form-group row">
699 className="col-12 col-form-label"
700 htmlFor="create-site-rate-limit-post"
702 {i18n.t("rate_limit_post")}
704 <div className="col-12">
707 id="create-site-rate-limit-post"
708 className="form-control"
710 value={this.state.siteForm.rate_limit_post}
711 onInput={linkEvent(this, this.handleSiteRateLimitPost)}
715 <div className="form-group row">
717 className="col-12 col-form-label"
718 htmlFor="create-site-rate-limit-post-per-second"
720 {i18n.t("per_second")}
722 <div className="col-12">
725 id="create-site-rate-limit-post-per-second"
726 className="form-control"
728 value={this.state.siteForm.rate_limit_post_per_second}
729 onInput={linkEvent(this, this.handleSiteRateLimitPostPerSecond)}
733 <div className="form-group row">
735 className="col-12 col-form-label"
736 htmlFor="create-site-rate-limit-register"
738 {i18n.t("rate_limit_register")}
740 <div className="col-12">
743 id="create-site-rate-limit-register"
744 className="form-control"
746 value={this.state.siteForm.rate_limit_register}
747 onInput={linkEvent(this, this.handleSiteRateLimitRegister)}
751 <div className="form-group row">
753 className="col-12 col-form-label"
754 htmlFor="create-site-rate-limit-register-per-second"
756 {i18n.t("per_second")}
758 <div className="col-12">
761 id="create-site-rate-limit-register-per-second"
762 className="form-control"
764 value={this.state.siteForm.rate_limit_register_per_second}
767 this.handleSiteRateLimitRegisterPerSecond
772 <div className="form-group row">
774 className="col-12 col-form-label"
775 htmlFor="create-site-rate-limit-image"
777 {i18n.t("rate_limit_image")}
779 <div className="col-12">
782 id="create-site-rate-limit-image"
783 className="form-control"
785 value={this.state.siteForm.rate_limit_image}
786 onInput={linkEvent(this, this.handleSiteRateLimitImage)}
790 <div className="form-group row">
792 className="col-12 col-form-label"
793 htmlFor="create-site-rate-limit-image-per-second"
795 {i18n.t("per_second")}
797 <div className="col-12">
800 id="create-site-rate-limit-image-per-second"
801 className="form-control"
803 value={this.state.siteForm.rate_limit_image_per_second}
806 this.handleSiteRateLimitImagePerSecond
811 <div className="form-group row">
813 className="col-12 col-form-label"
814 htmlFor="create-site-rate-limit-comment"
816 {i18n.t("rate_limit_comment")}
818 <div className="col-12">
821 id="create-site-rate-limit-comment"
822 className="form-control"
824 value={this.state.siteForm.rate_limit_comment}
825 onInput={linkEvent(this, this.handleSiteRateLimitComment)}
829 <div className="form-group row">
831 className="col-12 col-form-label"
832 htmlFor="create-site-rate-limit-comment-per-second"
834 {i18n.t("per_second")}
836 <div className="col-12">
839 id="create-site-rate-limit-comment-per-second"
840 className="form-control"
842 value={this.state.siteForm.rate_limit_comment_per_second}
845 this.handleSiteRateLimitCommentPerSecond
850 <div className="form-group row">
852 className="col-12 col-form-label"
853 htmlFor="create-site-rate-limit-search"
855 {i18n.t("rate_limit_search")}
857 <div className="col-12">
860 id="create-site-rate-limit-search"
861 className="form-control"
863 value={this.state.siteForm.rate_limit_search}
864 onInput={linkEvent(this, this.handleSiteRateLimitSearch)}
868 <div className="form-group row">
870 className="col-12 col-form-label"
871 htmlFor="create-site-rate-limit-search-per-second"
873 {i18n.t("per_second")}
875 <div className="col-12">
878 id="create-site-rate-limit-search-per-second"
879 className="form-control"
881 value={this.state.siteForm.rate_limit_search_per_second}
884 this.handleSiteRateLimitSearchPerSecond
890 <div className="form-group row">
891 <div className="col-12">
894 className="btn btn-secondary mr-2"
895 disabled={this.state.loading}
897 {this.state.loading ? (
900 capitalizeFirstLetter(i18n.t("save"))
902 capitalizeFirstLetter(i18n.t("create"))
912 federatedInstanceSelect(key: InstanceKey) {
913 const id = `create_site_${key}`;
914 const value = this.state.instance_select[key];
915 const selectedInstances = this.state.siteForm[key];
917 <div className="col-12 col-md-6">
918 <label className="col-form-label" htmlFor={id}>
921 <div className="d-flex justify-content-between align-items-center">
924 placeholder="instance.tld"
926 className="form-control"
928 onInput={linkEvent(key, this.handleInstanceTextChange)}
929 onKeyUp={linkEvent(key, this.handleInstanceEnterPress)}
933 className="btn btn-sm bg-success ml-2"
934 onClick={linkEvent(key, this.handleAddInstance)}
936 -1 /* Making this untabble because handling enter key in text input makes keyboard support for this button redundant */
939 <Icon icon="add" classes="icon-inline text-light m-auto" />
942 {selectedInstances && selectedInstances.length > 0 && (
943 <ul className="mt-3 list-unstyled w-100 d-flex flex-column justify-content-around align-items-center">
944 {selectedInstances.map(instance => (
947 className="my-1 w-100 w-md-75 d-flex align-items-center justify-content-between"
949 <label className="d-block m-0 w-100 " htmlFor={instance}>
950 <strong>{instance}</strong>
955 className="btn btn-sm bg-danger"
958 this.handleRemoveInstance
961 <Icon icon="x" classes="icon-inline text-light m-auto" />
971 handleInstanceTextChange(type: InstanceKey, event: any) {
972 this.setState(s => ({
975 ...s.instance_select,
976 [type]: event.target.value,
981 handleInstanceEnterPress(
983 event: InfernoKeyboardEvent<HTMLInputElement>
985 if (event.code.toLowerCase() === "enter") {
986 event.preventDefault();
988 this.handleAddInstance(key);
992 handleCreateSiteSubmit(i: SiteForm, event: any) {
993 event.preventDefault();
994 i.setState({ loading: true });
995 let auth = myAuth() ?? "TODO";
996 i.setState(s => ((s.siteForm.auth = auth), s));
997 if (i.props.siteRes.site_view.local_site.site_setup) {
998 WebSocketService.Instance.send(wsClient.editSite(i.state.siteForm));
1000 let sForm = i.state.siteForm;
1001 let form: CreateSite = {
1002 name: sForm.name ?? "My site",
1003 sidebar: sForm.sidebar,
1004 description: sForm.description,
1006 banner: sForm.banner,
1007 community_creation_admin_only: sForm.community_creation_admin_only,
1008 enable_nsfw: sForm.enable_nsfw,
1009 enable_downvotes: sForm.enable_downvotes,
1010 application_question: sForm.application_question,
1011 registration_mode: sForm.registration_mode,
1012 require_email_verification: sForm.require_email_verification,
1013 private_instance: sForm.private_instance,
1014 default_theme: sForm.default_theme,
1015 default_post_listing_type: sForm.default_post_listing_type,
1016 application_email_admins: sForm.application_email_admins,
1017 hide_modlog_mod_names: sForm.hide_modlog_mod_names,
1018 legal_information: sForm.legal_information,
1019 slur_filter_regex: sForm.slur_filter_regex,
1020 actor_name_max_length: sForm.actor_name_max_length,
1021 rate_limit_message: sForm.rate_limit_message,
1022 rate_limit_message_per_second: sForm.rate_limit_message_per_second,
1023 rate_limit_comment: sForm.rate_limit_comment,
1024 rate_limit_comment_per_second: sForm.rate_limit_comment_per_second,
1025 rate_limit_image: sForm.rate_limit_image,
1026 rate_limit_image_per_second: sForm.rate_limit_image_per_second,
1027 rate_limit_post: sForm.rate_limit_post,
1028 rate_limit_post_per_second: sForm.rate_limit_post_per_second,
1029 rate_limit_register: sForm.rate_limit_register,
1030 rate_limit_register_per_second: sForm.rate_limit_register_per_second,
1031 rate_limit_search: sForm.rate_limit_search,
1032 rate_limit_search_per_second: sForm.rate_limit_search_per_second,
1033 federation_enabled: sForm.federation_enabled,
1034 federation_debug: sForm.federation_debug,
1035 federation_worker_count: sForm.federation_worker_count,
1036 captcha_enabled: sForm.captcha_enabled,
1037 captcha_difficulty: sForm.captcha_difficulty,
1038 allowed_instances: sForm.allowed_instances,
1039 blocked_instances: sForm.blocked_instances,
1040 discussion_languages: sForm.discussion_languages,
1043 WebSocketService.Instance.send(wsClient.createSite(form));
1045 i.setState(i.state);
1048 handleAddInstance(key: InstanceKey) {
1049 const instance = this.state.instance_select[key].trim();
1050 if (!this.state.siteForm[key]?.includes(instance)) {
1051 this.setState(s => ({
1055 [key]: [...(s.siteForm[key] ?? []), instance],
1058 ...s.instance_select,
1063 const oppositeKey: InstanceKey =
1064 key === "allowed_instances" ? "blocked_instances" : "allowed_instances";
1065 if (this.state.siteForm[oppositeKey]?.includes(instance)) {
1066 this.handleRemoveInstance({ key: oppositeKey, instance });
1071 handleRemoveInstance({
1078 this.setState(s => ({
1082 [key]: s.siteForm[key]?.filter(i => i !== instance),
1087 handleSiteNameChange(i: SiteForm, event: any) {
1088 i.state.siteForm.name = event.target.value;
1089 i.setState(i.state);
1092 handleSiteSidebarChange(val: string) {
1093 this.setState(s => ((s.siteForm.sidebar = val), s));
1096 handleSiteLegalInfoChange(val: string) {
1097 this.setState(s => ((s.siteForm.legal_information = val), s));
1100 handleTaglineChange(i: SiteForm, index: number, val: string) {
1101 let taglines = i.state.siteForm.taglines;
1103 taglines[index] = val;
1104 i.setState(i.state);
1108 handleDeleteTaglineClick(
1111 event: InfernoMouseEvent<HTMLButtonElement>
1113 event.preventDefault();
1114 let taglines = i.state.siteForm.taglines;
1116 taglines.splice(index, 1);
1117 i.state.siteForm.taglines = undefined;
1118 i.setState(i.state);
1119 i.state.siteForm.taglines = taglines;
1120 i.setState(i.state);
1124 handleAddTaglineClick(
1126 event: InfernoMouseEvent<HTMLButtonElement>
1128 event.preventDefault();
1129 if (!i.state.siteForm.taglines) {
1130 i.state.siteForm.taglines = [];
1132 i.state.siteForm.taglines.push("");
1133 i.setState(i.state);
1136 handleSiteApplicationQuestionChange(val: string) {
1137 this.setState(s => ((s.siteForm.application_question = val), s));
1140 handleSiteDescChange(i: SiteForm, event: any) {
1141 i.state.siteForm.description = event.target.value;
1142 i.setState(i.state);
1145 handleSiteEnableNsfwChange(i: SiteForm, event: any) {
1146 i.state.siteForm.enable_nsfw = event.target.checked;
1147 i.setState(i.state);
1150 handleSiteRegistrationModeChange(i: SiteForm, event: any) {
1151 i.state.siteForm.registration_mode = event.target.value;
1152 i.setState(i.state);
1155 handleSiteCommunityCreationAdminOnly(i: SiteForm, event: any) {
1156 i.state.siteForm.community_creation_admin_only = event.target.checked;
1157 i.setState(i.state);
1160 handleSiteEnableDownvotesChange(i: SiteForm, event: any) {
1161 i.state.siteForm.enable_downvotes = event.target.checked;
1162 i.setState(i.state);
1165 handleSiteRequireEmailVerification(i: SiteForm, event: any) {
1166 i.state.siteForm.require_email_verification = event.target.checked;
1167 i.setState(i.state);
1170 handleSiteApplicationEmailAdmins(i: SiteForm, event: any) {
1171 i.state.siteForm.application_email_admins = event.target.checked;
1172 i.setState(i.state);
1175 handleSiteReportsEmailAdmins(i: SiteForm, event: any) {
1176 i.state.siteForm.reports_email_admins = event.target.checked;
1177 i.setState(i.state);
1180 handleSitePrivateInstance(i: SiteForm, event: any) {
1181 i.state.siteForm.private_instance = event.target.checked;
1182 i.setState(i.state);
1185 handleSiteHideModlogModNames(i: SiteForm, event: any) {
1186 i.state.siteForm.hide_modlog_mod_names = event.target.checked;
1187 i.setState(i.state);
1190 handleSiteDefaultTheme(i: SiteForm, event: any) {
1191 i.state.siteForm.default_theme = event.target.value;
1192 i.setState(i.state);
1195 handleIconUpload(url: string) {
1196 this.setState(s => ((s.siteForm.icon = url), s));
1199 handleIconRemove() {
1200 this.setState(s => ((s.siteForm.icon = ""), s));
1203 handleBannerUpload(url: string) {
1204 this.setState(s => ((s.siteForm.banner = url), s));
1207 handleBannerRemove() {
1208 this.setState(s => ((s.siteForm.banner = ""), s));
1211 handleSiteSlurFilterRegex(i: SiteForm, event: any) {
1212 i.setState(s => ((s.siteForm.slur_filter_regex = event.target.value), s));
1215 handleSiteActorNameMaxLength(i: SiteForm, event: any) {
1217 s => ((s.siteForm.actor_name_max_length = Number(event.target.value)), s)
1221 handleSiteRateLimitMessage(i: SiteForm, event: any) {
1223 s => ((s.siteForm.rate_limit_message = Number(event.target.value)), s)
1227 handleSiteRateLimitMessagePerSecond(i: SiteForm, event: any) {
1230 (s.siteForm.rate_limit_message_per_second = Number(event.target.value)),
1236 handleSiteRateLimitPost(i: SiteForm, event: any) {
1238 s => ((s.siteForm.rate_limit_post = Number(event.target.value)), s)
1242 handleSiteRateLimitPostPerSecond(i: SiteForm, event: any) {
1245 (s.siteForm.rate_limit_post_per_second = Number(event.target.value)), s
1250 handleSiteRateLimitImage(i: SiteForm, event: any) {
1252 s => ((s.siteForm.rate_limit_image = Number(event.target.value)), s)
1256 handleSiteRateLimitImagePerSecond(i: SiteForm, event: any) {
1259 (s.siteForm.rate_limit_image_per_second = Number(event.target.value)), s
1264 handleSiteRateLimitComment(i: SiteForm, event: any) {
1266 s => ((s.siteForm.rate_limit_comment = Number(event.target.value)), s)
1270 handleSiteRateLimitCommentPerSecond(i: SiteForm, event: any) {
1273 (s.siteForm.rate_limit_comment_per_second = Number(event.target.value)),
1279 handleSiteRateLimitSearch(i: SiteForm, event: any) {
1281 s => ((s.siteForm.rate_limit_search = Number(event.target.value)), s)
1285 handleSiteRateLimitSearchPerSecond(i: SiteForm, event: any) {
1288 (s.siteForm.rate_limit_search_per_second = Number(event.target.value)),
1294 handleSiteRateLimitRegister(i: SiteForm, event: any) {
1296 s => ((s.siteForm.rate_limit_register = Number(event.target.value)), s)
1300 handleSiteRateLimitRegisterPerSecond(i: SiteForm, event: any) {
1303 (s.siteForm.rate_limit_register_per_second = Number(
1311 handleSiteFederationEnabled(i: SiteForm, event: any) {
1312 i.state.siteForm.federation_enabled = event.target.checked;
1313 i.setState(i.state);
1316 handleSiteFederationDebug(i: SiteForm, event: any) {
1317 i.state.siteForm.federation_debug = event.target.checked;
1318 i.setState(i.state);
1321 handleSiteFederationWorkerCount(i: SiteForm, event: any) {
1324 (s.siteForm.federation_worker_count = Number(event.target.value)), s
1329 handleSiteCaptchaEnabled(i: SiteForm, event: any) {
1330 i.state.siteForm.captcha_enabled = event.target.checked;
1331 i.setState(i.state);
1334 handleSiteCaptchaDifficulty(i: SiteForm, event: any) {
1335 i.setState(s => ((s.siteForm.captcha_difficulty = event.target.value), s));
1338 handleDiscussionLanguageChange(val: number[]) {
1339 this.setState(s => ((s.siteForm.discussion_languages = val), s));
1342 handleDefaultPostListingTypeChange(val: ListingType) {
1343 this.setState(s => ((s.siteForm.default_post_listing_type = val), s));