1 import { None, Option, Some } from "@sniptt/monads";
2 import { Component, InfernoMouseEvent, linkEvent } from "inferno";
3 import { Prompt } from "inferno-router";
10 } from "lemmy-js-client";
11 import { i18n } from "../../i18next";
12 import { WebSocketService } from "../../services";
15 capitalizeFirstLetter,
19 import { Icon, Spinner } from "../common/icon";
20 import { ImageUploadForm } from "../common/image-upload-form";
21 import { LanguageSelect } from "../common/language-select";
22 import { ListingTypeSelect } from "../common/listing-type-select";
23 import { MarkdownTextArea } from "../common/markdown-textarea";
25 interface SiteFormProps {
26 siteRes: GetSiteResponse;
30 interface SiteFormState {
33 themeList: Option<string[]>;
36 export class SiteForm extends Component<SiteFormProps, SiteFormState> {
37 private emptyState: SiteFormState = {
38 siteForm: new EditSite({
39 enable_downvotes: None,
40 open_registration: None,
45 require_email_verification: None,
46 require_application: None,
47 application_question: None,
48 private_instance: None,
51 default_post_listing_type: None,
52 legal_information: None,
54 community_creation_admin_only: None,
55 application_email_admins: None,
56 hide_modlog_mod_names: None,
57 discussion_languages: None,
58 slur_filter_regex: None,
59 actor_name_max_length: None,
60 rate_limit_message: None,
61 rate_limit_message_per_second: None,
62 rate_limit_comment: None,
63 rate_limit_comment_per_second: None,
64 rate_limit_image: None,
65 rate_limit_image_per_second: None,
66 rate_limit_post: None,
67 rate_limit_post_per_second: None,
68 rate_limit_register: None,
69 rate_limit_register_per_second: None,
70 rate_limit_search: None,
71 rate_limit_search_per_second: None,
72 federation_enabled: None,
73 federation_debug: None,
74 federation_worker_count: None,
75 captcha_enabled: None,
76 captcha_difficulty: None,
77 allowed_instances: None,
78 blocked_instances: None,
86 constructor(props: any, context: any) {
87 super(props, context);
89 this.state = this.emptyState;
90 this.handleSiteSidebarChange = this.handleSiteSidebarChange.bind(this);
91 this.handleSiteLegalInfoChange = this.handleSiteLegalInfoChange.bind(this);
92 this.handleSiteApplicationQuestionChange =
93 this.handleSiteApplicationQuestionChange.bind(this);
95 this.handleIconUpload = this.handleIconUpload.bind(this);
96 this.handleIconRemove = this.handleIconRemove.bind(this);
98 this.handleBannerUpload = this.handleBannerUpload.bind(this);
99 this.handleBannerRemove = this.handleBannerRemove.bind(this);
101 this.handleDefaultPostListingTypeChange =
102 this.handleDefaultPostListingTypeChange.bind(this);
104 this.handleDiscussionLanguageChange =
105 this.handleDiscussionLanguageChange.bind(this);
107 let site = this.props.siteRes.site_view.site;
108 let ls = this.props.siteRes.site_view.local_site;
109 let lsrl = this.props.siteRes.site_view.local_site_rate_limit;
112 siteForm: new EditSite({
113 name: Some(site.name),
114 sidebar: site.sidebar,
115 description: site.description,
116 enable_downvotes: Some(ls.enable_downvotes),
117 open_registration: Some(ls.open_registration),
118 enable_nsfw: Some(ls.enable_nsfw),
119 community_creation_admin_only: Some(ls.community_creation_admin_only),
122 require_email_verification: Some(ls.require_email_verification),
123 require_application: Some(ls.require_application),
124 application_question: ls.application_question,
125 private_instance: Some(ls.private_instance),
126 default_theme: Some(ls.default_theme),
127 default_post_listing_type: Some(ls.default_post_listing_type),
128 legal_information: ls.legal_information,
129 application_email_admins: Some(ls.application_email_admins),
130 hide_modlog_mod_names: Some(ls.hide_modlog_mod_names),
131 discussion_languages: Some(this.props.siteRes.discussion_languages),
132 slur_filter_regex: ls.slur_filter_regex,
133 actor_name_max_length: Some(ls.actor_name_max_length),
134 rate_limit_message: Some(lsrl.message),
135 rate_limit_message_per_second: Some(lsrl.message_per_second),
136 rate_limit_comment: Some(lsrl.comment),
137 rate_limit_comment_per_second: Some(lsrl.comment_per_second),
138 rate_limit_image: Some(lsrl.image),
139 rate_limit_image_per_second: Some(lsrl.image_per_second),
140 rate_limit_post: Some(lsrl.post),
141 rate_limit_post_per_second: Some(lsrl.post_per_second),
142 rate_limit_register: Some(lsrl.register),
143 rate_limit_register_per_second: Some(lsrl.register_per_second),
144 rate_limit_search: Some(lsrl.search),
145 rate_limit_search_per_second: Some(lsrl.search_per_second),
146 federation_enabled: Some(ls.federation_enabled),
147 federation_debug: Some(ls.federation_debug),
148 federation_worker_count: Some(ls.federation_worker_count),
149 captcha_enabled: Some(ls.captcha_enabled),
150 captcha_difficulty: Some(ls.captcha_difficulty),
151 allowed_instances: this.props.siteRes.federated_instances.andThen(
154 blocked_instances: this.props.siteRes.federated_instances.andThen(
157 taglines: this.props.siteRes.taglines.map(x => x.map(y => y.content)),
163 async componentDidMount() {
164 this.setState({ themeList: Some(await fetchThemeList()) });
167 // Necessary to stop the loading
168 componentWillReceiveProps() {
169 this.setState({ loading: false });
172 componentDidUpdate() {
174 !this.state.loading &&
175 !this.props.siteRes.site_view.local_site.site_setup &&
176 (this.state.siteForm.name ||
177 this.state.siteForm.sidebar ||
178 this.state.siteForm.application_question ||
179 this.state.siteForm.description)
181 window.onbeforeunload = () => true;
183 window.onbeforeunload = undefined;
187 componentWillUnmount() {
188 window.onbeforeunload = null;
192 let siteSetup = this.props.siteRes.site_view.local_site.site_setup;
197 !this.state.loading &&
199 (this.state.siteForm.name ||
200 this.state.siteForm.sidebar ||
201 this.state.siteForm.application_question ||
202 this.state.siteForm.description)
204 message={i18n.t("block_leaving")}
206 <form onSubmit={linkEvent(this, this.handleCreateSiteSubmit)}>
209 ? capitalizeFirstLetter(i18n.t("save"))
210 : capitalizeFirstLetter(i18n.t("name"))
211 } ${i18n.t("your_site")}`}</h5>
212 <div className="form-group row">
213 <label className="col-12 col-form-label" htmlFor="create-site-name">
216 <div className="col-12">
219 id="create-site-name"
220 className="form-control"
221 value={toUndefined(this.state.siteForm.name)}
222 onInput={linkEvent(this, this.handleSiteNameChange)}
229 <div className="form-group">
230 <label>{i18n.t("icon")}</label>
232 uploadTitle={i18n.t("upload_icon")}
233 imageSrc={this.state.siteForm.icon}
234 onUpload={this.handleIconUpload}
235 onRemove={this.handleIconRemove}
239 <div className="form-group">
240 <label>{i18n.t("banner")}</label>
242 uploadTitle={i18n.t("upload_banner")}
243 imageSrc={this.state.siteForm.banner}
244 onUpload={this.handleBannerUpload}
245 onRemove={this.handleBannerRemove}
248 <div className="form-group row">
249 <label className="col-12 col-form-label" htmlFor="site-desc">
250 {i18n.t("description")}
252 <div className="col-12">
255 className="form-control"
257 value={toUndefined(this.state.siteForm.description)}
258 onInput={linkEvent(this, this.handleSiteDescChange)}
263 <div className="form-group row">
264 <label className="col-12 col-form-label">{i18n.t("sidebar")}</label>
265 <div className="col-12">
267 initialContent={this.state.siteForm.sidebar}
268 initialLanguageId={None}
272 onContentChange={this.handleSiteSidebarChange}
273 hideNavigationWarnings
279 <div className="form-group row">
280 <label className="col-12 col-form-label">
281 {i18n.t("legal_information")}
283 <div className="col-12">
285 initialContent={this.state.siteForm.legal_information}
286 initialLanguageId={None}
290 onContentChange={this.handleSiteLegalInfoChange}
291 hideNavigationWarnings
297 {this.state.siteForm.require_application.unwrapOr(false) && (
298 <div className="form-group row">
299 <label className="col-12 col-form-label">
300 {i18n.t("application_questionnaire")}
302 <div className="col-12">
304 initialContent={this.state.siteForm.application_question}
305 initialLanguageId={None}
309 onContentChange={this.handleSiteApplicationQuestionChange}
310 hideNavigationWarnings
317 <div className="form-group row">
318 <div className="col-12">
319 <div className="form-check">
321 className="form-check-input"
322 id="create-site-downvotes"
324 checked={toUndefined(this.state.siteForm.enable_downvotes)}
327 this.handleSiteEnableDownvotesChange
331 className="form-check-label"
332 htmlFor="create-site-downvotes"
334 {i18n.t("enable_downvotes")}
339 <div className="form-group row">
340 <div className="col-12">
341 <div className="form-check">
343 className="form-check-input"
344 id="create-site-enable-nsfw"
346 checked={toUndefined(this.state.siteForm.enable_nsfw)}
347 onChange={linkEvent(this, this.handleSiteEnableNsfwChange)}
350 className="form-check-label"
351 htmlFor="create-site-enable-nsfw"
353 {i18n.t("enable_nsfw")}
358 <div className="form-group row">
359 <div className="col-12">
360 <div className="form-check">
362 className="form-check-input"
363 id="create-site-open-registration"
365 checked={toUndefined(this.state.siteForm.open_registration)}
368 this.handleSiteOpenRegistrationChange
372 className="form-check-label"
373 htmlFor="create-site-open-registration"
375 {i18n.t("open_registration")}
380 <div className="form-group row">
381 <div className="col-12">
382 <div className="form-check">
384 className="form-check-input"
385 id="create-site-community-creation-admin-only"
387 checked={toUndefined(
388 this.state.siteForm.community_creation_admin_only
392 this.handleSiteCommunityCreationAdminOnly
396 className="form-check-label"
397 htmlFor="create-site-community-creation-admin-only"
399 {i18n.t("community_creation_admin_only")}
404 <div className="form-group row">
405 <div className="col-12">
406 <div className="form-check">
408 className="form-check-input"
409 id="create-site-require-email-verification"
411 checked={toUndefined(
412 this.state.siteForm.require_email_verification
416 this.handleSiteRequireEmailVerification
420 className="form-check-label"
421 htmlFor="create-site-require-email-verification"
423 {i18n.t("require_email_verification")}
428 <div className="form-group row">
429 <div className="col-12">
430 <div className="form-check">
432 className="form-check-input"
433 id="create-site-require-application"
435 checked={toUndefined(this.state.siteForm.require_application)}
436 onChange={linkEvent(this, this.handleSiteRequireApplication)}
439 className="form-check-label"
440 htmlFor="create-site-require-application"
442 {i18n.t("require_registration_application")}
447 <div className="form-group row">
448 <div className="col-12">
449 <div className="form-check">
451 className="form-check-input"
452 id="create-site-application-email-admins"
454 checked={toUndefined(
455 this.state.siteForm.application_email_admins
459 this.handleSiteApplicationEmailAdmins
463 className="form-check-label"
464 htmlFor="create-site-email-admins"
466 {i18n.t("application_email_admins")}
471 <div className="form-group row">
472 <div className="col-12">
474 className="form-check-label mr-2"
475 htmlFor="create-site-default-theme"
480 id="create-site-default-theme"
481 value={toUndefined(this.state.siteForm.default_theme)}
482 onChange={linkEvent(this, this.handleSiteDefaultTheme)}
483 className="custom-select w-auto"
485 <option value="browser">{i18n.t("browser_default")}</option>
486 {this.state.themeList.unwrapOr([]).map(theme => (
487 <option key={theme} value={theme}>
494 {this.props.showLocal && (
495 <form className="form-group row">
496 <label className="col-sm-3">{i18n.t("listing_type")}</label>
497 <div className="col-sm-9">
501 this.state.siteForm.default_post_listing_type.unwrapOr(
507 showSubscribed={false}
508 onChange={this.handleDefaultPostListingTypeChange}
513 <div className="form-group row">
514 <div className="col-12">
515 <div className="form-check">
517 className="form-check-input"
518 id="create-site-private-instance"
520 checked={toUndefined(this.state.siteForm.private_instance)}
521 onChange={linkEvent(this, this.handleSitePrivateInstance)}
524 className="form-check-label"
525 htmlFor="create-site-private-instance"
527 {i18n.t("private_instance")}
532 <div className="form-group row">
533 <div className="col-12">
534 <div className="form-check">
536 className="form-check-input"
537 id="create-site-hide-modlog-mod-names"
539 checked={toUndefined(
540 this.state.siteForm.hide_modlog_mod_names
542 onChange={linkEvent(this, this.handleSiteHideModlogModNames)}
545 className="form-check-label"
546 htmlFor="create-site-hide-modlog-mod-names"
548 {i18n.t("hide_modlog_mod_names")}
553 <div className="form-group row">
555 className="col-12 col-form-label"
556 htmlFor="create-site-slur-filter-regex"
558 {i18n.t("slur_filter_regex")}
560 <div className="col-12">
563 id="create-site-slur-filter-regex"
564 placeholder="(word1|word2)"
565 className="form-control"
566 value={toUndefined(this.state.siteForm.slur_filter_regex)}
567 onInput={linkEvent(this, this.handleSiteSlurFilterRegex)}
573 allLanguages={this.props.siteRes.all_languages}
574 siteLanguages={this.props.siteRes.discussion_languages}
575 selectedLanguageIds={this.state.siteForm.discussion_languages}
577 onChange={this.handleDiscussionLanguageChange}
580 <div className="form-group row">
582 className="col-12 col-form-label"
583 htmlFor="create-site-actor-name"
585 {i18n.t("actor_name_max_length")}
587 <div className="col-12">
590 id="create-site-actor-name"
591 className="form-control"
593 value={toUndefined(this.state.siteForm.actor_name_max_length)}
594 onInput={linkEvent(this, this.handleSiteActorNameMaxLength)}
598 <div className="form-group row">
599 <div className="col-12">
600 <div className="form-check">
602 className="form-check-input"
603 id="create-site-federation-enabled"
605 checked={toUndefined(this.state.siteForm.federation_enabled)}
606 onChange={linkEvent(this, this.handleSiteFederationEnabled)}
609 className="form-check-label"
610 htmlFor="create-site-federation-enabled"
612 {i18n.t("federation_enabled")}
617 {this.state.siteForm.federation_enabled.unwrapOr(false) && (
619 <div className="form-group row">
621 className="col-12 col-form-label"
622 htmlFor="create-site-allowed-instances"
624 {i18n.t("allowed_instances")}
626 <div className="col-12">
629 placeholder="instance1.tld,instance2.tld"
630 id="create-site-allowed-instances"
631 className="form-control"
632 value={this.instancesToString(
633 this.state.siteForm.allowed_instances
635 onInput={linkEvent(this, this.handleSiteAllowedInstances)}
639 <div className="form-group row">
641 className="col-12 col-form-label"
642 htmlFor="create-site-blocked-instances"
644 {i18n.t("blocked_instances")}
646 <div className="col-12">
649 placeholder="instance1.tld,instance2.tld"
650 id="create-site-blocked-instances"
651 className="form-control"
652 value={this.instancesToString(
653 this.state.siteForm.blocked_instances
655 onInput={linkEvent(this, this.handleSiteBlockedInstances)}
659 <div className="form-group row">
660 <div className="col-12">
661 <div className="form-check">
663 className="form-check-input"
664 id="create-site-federation-debug"
666 checked={toUndefined(
667 this.state.siteForm.federation_debug
669 onChange={linkEvent(this, this.handleSiteFederationDebug)}
672 className="form-check-label"
673 htmlFor="create-site-federation-debug"
675 {i18n.t("federation_debug")}
680 <div className="form-group row">
682 className="col-12 col-form-label"
683 htmlFor="create-site-federation-worker-count"
685 {i18n.t("federation_worker_count")}
687 <div className="col-12">
690 id="create-site-federation-worker-count"
691 className="form-control"
694 this.state.siteForm.federation_worker_count
698 this.handleSiteFederationWorkerCount
705 <div className="form-group row">
706 <div className="col-12">
707 <div className="form-check">
709 className="form-check-input"
710 id="create-site-captcha-enabled"
712 checked={toUndefined(this.state.siteForm.captcha_enabled)}
713 onChange={linkEvent(this, this.handleSiteCaptchaEnabled)}
716 className="form-check-label"
717 htmlFor="create-site-captcha-enabled"
719 {i18n.t("captcha_enabled")}
724 {this.state.siteForm.captcha_enabled.unwrapOr(false) && (
725 <div className="form-group row">
726 <div className="col-12">
728 className="form-check-label mr-2"
729 htmlFor="create-site-captcha-difficulty"
731 {i18n.t("captcha_difficulty")}
734 id="create-site-captcha-difficulty"
735 value={toUndefined(this.state.siteForm.captcha_difficulty)}
736 onChange={linkEvent(this, this.handleSiteCaptchaDifficulty)}
737 className="custom-select w-auto"
739 <option value="easy">{i18n.t("easy")}</option>
740 <option value="medium">{i18n.t("medium")}</option>
741 <option value="hard">{i18n.t("hard")}</option>
746 <div className="form-group row">
748 className="col-12 col-form-label"
749 htmlFor="create-site-rate-limit-message"
751 {i18n.t("rate_limit_message")}
753 <div className="col-12">
756 id="create-site-rate-limit-message"
757 className="form-control"
759 value={toUndefined(this.state.siteForm.rate_limit_message)}
760 onInput={linkEvent(this, this.handleSiteRateLimitMessage)}
764 <div className="form-group row">
766 className="col-12 col-form-label"
767 htmlFor="create-site-rate-limit-message-per-second"
769 {i18n.t("per_second")}
771 <div className="col-12">
774 id="create-site-rate-limit-message-per-second"
775 className="form-control"
778 this.state.siteForm.rate_limit_message_per_second
782 this.handleSiteRateLimitMessagePerSecond
787 <div className="form-group row">
789 className="col-12 col-form-label"
790 htmlFor="create-site-rate-limit-post"
792 {i18n.t("rate_limit_post")}
794 <div className="col-12">
797 id="create-site-rate-limit-post"
798 className="form-control"
800 value={toUndefined(this.state.siteForm.rate_limit_post)}
801 onInput={linkEvent(this, this.handleSiteRateLimitPost)}
805 <div className="form-group row">
807 className="col-12 col-form-label"
808 htmlFor="create-site-rate-limit-post-per-second"
810 {i18n.t("per_second")}
812 <div className="col-12">
815 id="create-site-rate-limit-post-per-second"
816 className="form-control"
819 this.state.siteForm.rate_limit_post_per_second
821 onInput={linkEvent(this, this.handleSiteRateLimitPostPerSecond)}
825 <div className="form-group row">
827 className="col-12 col-form-label"
828 htmlFor="create-site-rate-limit-register"
830 {i18n.t("rate_limit_register")}
832 <div className="col-12">
835 id="create-site-rate-limit-register"
836 className="form-control"
838 value={toUndefined(this.state.siteForm.rate_limit_register)}
839 onInput={linkEvent(this, this.handleSiteRateLimitRegister)}
843 <div className="form-group row">
845 className="col-12 col-form-label"
846 htmlFor="create-site-rate-limit-register-per-second"
848 {i18n.t("per_second")}
850 <div className="col-12">
853 id="create-site-rate-limit-register-per-second"
854 className="form-control"
857 this.state.siteForm.rate_limit_register_per_second
861 this.handleSiteRateLimitRegisterPerSecond
866 <div className="form-group row">
868 className="col-12 col-form-label"
869 htmlFor="create-site-rate-limit-image"
871 {i18n.t("rate_limit_image")}
873 <div className="col-12">
876 id="create-site-rate-limit-image"
877 className="form-control"
879 value={toUndefined(this.state.siteForm.rate_limit_image)}
880 onInput={linkEvent(this, this.handleSiteRateLimitImage)}
884 <div className="form-group row">
886 className="col-12 col-form-label"
887 htmlFor="create-site-rate-limit-image-per-second"
889 {i18n.t("per_second")}
891 <div className="col-12">
894 id="create-site-rate-limit-image-per-second"
895 className="form-control"
898 this.state.siteForm.rate_limit_image_per_second
902 this.handleSiteRateLimitImagePerSecond
907 <div className="form-group row">
909 className="col-12 col-form-label"
910 htmlFor="create-site-rate-limit-comment"
912 {i18n.t("rate_limit_comment")}
914 <div className="col-12">
917 id="create-site-rate-limit-comment"
918 className="form-control"
920 value={toUndefined(this.state.siteForm.rate_limit_comment)}
921 onInput={linkEvent(this, this.handleSiteRateLimitComment)}
925 <div className="form-group row">
927 className="col-12 col-form-label"
928 htmlFor="create-site-rate-limit-comment-per-second"
930 {i18n.t("per_second")}
932 <div className="col-12">
935 id="create-site-rate-limit-comment-per-second"
936 className="form-control"
939 this.state.siteForm.rate_limit_comment_per_second
943 this.handleSiteRateLimitCommentPerSecond
948 <div className="form-group row">
950 className="col-12 col-form-label"
951 htmlFor="create-site-rate-limit-search"
953 {i18n.t("rate_limit_search")}
955 <div className="col-12">
958 id="create-site-rate-limit-search"
959 className="form-control"
961 value={toUndefined(this.state.siteForm.rate_limit_search)}
962 onInput={linkEvent(this, this.handleSiteRateLimitSearch)}
966 <div className="form-group row">
968 className="col-12 col-form-label"
969 htmlFor="create-site-rate-limit-search-per-second"
971 {i18n.t("per_second")}
973 <div className="col-12">
976 id="create-site-rate-limit-search-per-second"
977 className="form-control"
980 this.state.siteForm.rate_limit_search_per_second
984 this.handleSiteRateLimitSearchPerSecond
989 <div className="form-group row">
990 <h5 className="col-12">{i18n.t("taglines")}</h5>
991 <div className="table-responsive col-12">
992 <table id="taglines_table" className="table table-sm table-hover">
993 <thead className="pointer"></thead>
995 {this.state.siteForm.taglines
997 .map((cv, index) => (
1001 initialContent={Some(cv)}
1002 initialLanguageId={None}
1006 onContentChange={s =>
1007 this.handleTaglineChange(this, index, s)
1009 hideNavigationWarnings
1010 allLanguages={this.props.siteRes.all_languages}
1012 this.props.siteRes.discussion_languages
1016 <td className="text-right">
1018 className="btn btn-link btn-animate text-muted"
1020 this.handleDeleteTaglineClick(this, index, e)
1022 data-tippy-content={i18n.t("delete")}
1023 aria-label={i18n.t("delete")}
1027 classes={`icon-inline text-danger`}
1036 className="btn btn-sm btn-secondary mr-2"
1037 onClick={e => this.handleAddTaglineClick(this, e)}
1039 {i18n.t("add_tagline")}
1043 <div className="form-group row">
1044 <div className="col-12">
1047 className="btn btn-secondary mr-2"
1048 disabled={this.state.loading}
1050 {this.state.loading ? (
1053 capitalizeFirstLetter(i18n.t("save"))
1055 capitalizeFirstLetter(i18n.t("create"))
1065 handleCreateSiteSubmit(i: SiteForm, event: any) {
1066 event.preventDefault();
1067 i.setState({ loading: true });
1068 i.setState(s => ((s.siteForm.auth = auth().unwrap()), s));
1069 if (i.props.siteRes.site_view.local_site.site_setup) {
1070 WebSocketService.Instance.send(wsClient.editSite(i.state.siteForm));
1072 let sForm = i.state.siteForm;
1073 let form = new CreateSite({
1074 name: sForm.name.unwrapOr("My site"),
1075 sidebar: sForm.sidebar,
1076 description: sForm.description,
1078 banner: sForm.banner,
1079 community_creation_admin_only: sForm.community_creation_admin_only,
1080 enable_nsfw: sForm.enable_nsfw,
1081 enable_downvotes: sForm.enable_downvotes,
1082 require_application: sForm.require_application,
1083 application_question: sForm.application_question,
1084 open_registration: sForm.open_registration,
1085 require_email_verification: sForm.require_email_verification,
1086 private_instance: sForm.private_instance,
1087 default_theme: sForm.default_theme,
1088 default_post_listing_type: sForm.default_post_listing_type,
1089 application_email_admins: sForm.application_email_admins,
1090 auth: auth().unwrap(),
1091 hide_modlog_mod_names: sForm.hide_modlog_mod_names,
1092 legal_information: sForm.legal_information,
1093 slur_filter_regex: sForm.slur_filter_regex,
1094 actor_name_max_length: sForm.actor_name_max_length,
1095 rate_limit_message: sForm.rate_limit_message,
1096 rate_limit_message_per_second: sForm.rate_limit_message_per_second,
1097 rate_limit_comment: sForm.rate_limit_comment,
1098 rate_limit_comment_per_second: sForm.rate_limit_comment_per_second,
1099 rate_limit_image: sForm.rate_limit_image,
1100 rate_limit_image_per_second: sForm.rate_limit_image_per_second,
1101 rate_limit_post: sForm.rate_limit_post,
1102 rate_limit_post_per_second: sForm.rate_limit_post_per_second,
1103 rate_limit_register: sForm.rate_limit_register,
1104 rate_limit_register_per_second: sForm.rate_limit_register_per_second,
1105 rate_limit_search: sForm.rate_limit_search,
1106 rate_limit_search_per_second: sForm.rate_limit_search_per_second,
1107 federation_enabled: sForm.federation_enabled,
1108 federation_debug: sForm.federation_debug,
1109 federation_worker_count: sForm.federation_worker_count,
1110 captcha_enabled: sForm.captcha_enabled,
1111 captcha_difficulty: sForm.captcha_difficulty,
1112 allowed_instances: sForm.allowed_instances,
1113 blocked_instances: sForm.blocked_instances,
1114 discussion_languages: sForm.discussion_languages,
1115 taglines: sForm.taglines,
1117 WebSocketService.Instance.send(wsClient.createSite(form));
1119 i.setState(i.state);
1122 instancesToString(opt: Option<string[]>): string {
1123 return opt.map(list => list.join(",")).unwrapOr("");
1126 handleSiteAllowedInstances(i: SiteForm, event: any) {
1127 let list = splitToList(event.target.value);
1128 i.setState(s => ((s.siteForm.allowed_instances = list), s));
1131 handleSiteBlockedInstances(i: SiteForm, event: any) {
1132 let list = splitToList(event.target.value);
1133 i.setState(s => ((s.siteForm.blocked_instances = list), s));
1136 handleSiteNameChange(i: SiteForm, event: any) {
1137 i.state.siteForm.name = Some(event.target.value);
1138 i.setState(i.state);
1141 handleSiteSidebarChange(val: string) {
1142 this.setState(s => ((s.siteForm.sidebar = Some(val)), s));
1145 handleSiteLegalInfoChange(val: string) {
1146 this.setState(s => ((s.siteForm.legal_information = Some(val)), s));
1149 handleTaglineChange(i: SiteForm, index: number, val: string) {
1150 i.state.siteForm.taglines.match({
1156 i.setState(i.state);
1159 handleDeleteTaglineClick(
1162 event: InfernoMouseEvent<HTMLButtonElement>
1164 event.preventDefault();
1165 if (i.state.siteForm.taglines.isSome()) {
1166 let taglines = i.state.siteForm.taglines.unwrap();
1167 taglines.splice(index, 1);
1168 i.state.siteForm.taglines = None; // force rerender of table rows
1169 i.setState(i.state);
1170 i.state.siteForm.taglines = Some(taglines);
1171 i.setState(i.state);
1175 handleAddTaglineClick(
1177 event: InfernoMouseEvent<HTMLButtonElement>
1179 event.preventDefault();
1180 if (i.state.siteForm.taglines.isNone()) {
1181 i.state.siteForm.taglines = Some([]);
1183 i.state.siteForm.taglines.unwrap().push("");
1184 i.setState(i.state);
1187 handleSiteApplicationQuestionChange(val: string) {
1188 this.setState(s => ((s.siteForm.application_question = Some(val)), s));
1191 handleSiteDescChange(i: SiteForm, event: any) {
1192 i.state.siteForm.description = Some(event.target.value);
1193 i.setState(i.state);
1196 handleSiteEnableNsfwChange(i: SiteForm, event: any) {
1197 i.state.siteForm.enable_nsfw = Some(event.target.checked);
1198 i.setState(i.state);
1201 handleSiteOpenRegistrationChange(i: SiteForm, event: any) {
1202 i.state.siteForm.open_registration = Some(event.target.checked);
1203 i.setState(i.state);
1206 handleSiteCommunityCreationAdminOnly(i: SiteForm, event: any) {
1207 i.state.siteForm.community_creation_admin_only = Some(event.target.checked);
1208 i.setState(i.state);
1211 handleSiteEnableDownvotesChange(i: SiteForm, event: any) {
1212 i.state.siteForm.enable_downvotes = Some(event.target.checked);
1213 i.setState(i.state);
1216 handleSiteRequireApplication(i: SiteForm, event: any) {
1217 i.state.siteForm.require_application = Some(event.target.checked);
1218 i.setState(i.state);
1221 handleSiteRequireEmailVerification(i: SiteForm, event: any) {
1222 i.state.siteForm.require_email_verification = Some(event.target.checked);
1223 i.setState(i.state);
1226 handleSiteApplicationEmailAdmins(i: SiteForm, event: any) {
1227 i.state.siteForm.application_email_admins = Some(event.target.checked);
1228 i.setState(i.state);
1231 handleSitePrivateInstance(i: SiteForm, event: any) {
1232 i.state.siteForm.private_instance = Some(event.target.checked);
1233 i.setState(i.state);
1236 handleSiteHideModlogModNames(i: SiteForm, event: any) {
1237 i.state.siteForm.hide_modlog_mod_names = Some(event.target.checked);
1238 i.setState(i.state);
1241 handleSiteDefaultTheme(i: SiteForm, event: any) {
1242 i.state.siteForm.default_theme = Some(event.target.value);
1243 i.setState(i.state);
1246 handleIconUpload(url: string) {
1247 this.setState(s => ((s.siteForm.icon = Some(url)), s));
1250 handleIconRemove() {
1251 this.setState(s => ((s.siteForm.icon = Some("")), s));
1254 handleBannerUpload(url: string) {
1255 this.setState(s => ((s.siteForm.banner = Some(url)), s));
1258 handleBannerRemove() {
1259 this.setState(s => ((s.siteForm.banner = Some("")), s));
1262 handleSiteSlurFilterRegex(i: SiteForm, event: any) {
1264 s => ((s.siteForm.slur_filter_regex = Some(event.target.value)), s)
1268 handleSiteActorNameMaxLength(i: SiteForm, event: any) {
1271 (s.siteForm.actor_name_max_length = Some(Number(event.target.value))), s
1276 handleSiteRateLimitMessage(i: SiteForm, event: any) {
1279 (s.siteForm.rate_limit_message = Some(Number(event.target.value))), s
1284 handleSiteRateLimitMessagePerSecond(i: SiteForm, event: any) {
1287 (s.siteForm.rate_limit_message_per_second = Some(
1288 Number(event.target.value)
1295 handleSiteRateLimitPost(i: SiteForm, event: any) {
1297 s => ((s.siteForm.rate_limit_post = Some(Number(event.target.value))), s)
1301 handleSiteRateLimitPostPerSecond(i: SiteForm, event: any) {
1304 (s.siteForm.rate_limit_post_per_second = Some(
1305 Number(event.target.value)
1312 handleSiteRateLimitImage(i: SiteForm, event: any) {
1314 s => ((s.siteForm.rate_limit_image = Some(Number(event.target.value))), s)
1318 handleSiteRateLimitImagePerSecond(i: SiteForm, event: any) {
1321 (s.siteForm.rate_limit_image_per_second = Some(
1322 Number(event.target.value)
1329 handleSiteRateLimitComment(i: SiteForm, event: any) {
1332 (s.siteForm.rate_limit_comment = Some(Number(event.target.value))), s
1337 handleSiteRateLimitCommentPerSecond(i: SiteForm, event: any) {
1340 (s.siteForm.rate_limit_comment_per_second = Some(
1341 Number(event.target.value)
1348 handleSiteRateLimitSearch(i: SiteForm, event: any) {
1351 (s.siteForm.rate_limit_search = Some(Number(event.target.value))), s
1356 handleSiteRateLimitSearchPerSecond(i: SiteForm, event: any) {
1359 (s.siteForm.rate_limit_search_per_second = Some(
1360 Number(event.target.value)
1367 handleSiteRateLimitRegister(i: SiteForm, event: any) {
1370 (s.siteForm.rate_limit_register = Some(Number(event.target.value))), s
1375 handleSiteRateLimitRegisterPerSecond(i: SiteForm, event: any) {
1378 (s.siteForm.rate_limit_register_per_second = Some(
1379 Number(event.target.value)
1386 handleSiteFederationEnabled(i: SiteForm, event: any) {
1387 i.state.siteForm.federation_enabled = Some(event.target.checked);
1388 i.setState(i.state);
1391 handleSiteFederationDebug(i: SiteForm, event: any) {
1392 i.state.siteForm.federation_debug = Some(event.target.checked);
1393 i.setState(i.state);
1396 handleSiteFederationWorkerCount(i: SiteForm, event: any) {
1399 (s.siteForm.federation_worker_count = Some(Number(event.target.value))),
1405 handleSiteCaptchaEnabled(i: SiteForm, event: any) {
1406 i.state.siteForm.captcha_enabled = Some(event.target.checked);
1407 i.setState(i.state);
1410 handleSiteCaptchaDifficulty(i: SiteForm, event: any) {
1412 s => ((s.siteForm.captcha_difficulty = Some(event.target.value)), s)
1416 handleDiscussionLanguageChange(val: number[]) {
1417 this.setState(s => ((s.siteForm.discussion_languages = Some(val)), s));
1420 handleDefaultPostListingTypeChange(val: ListingType) {
1423 (s.siteForm.default_post_listing_type = Some(
1424 ListingType[ListingType[val]]
1432 function splitToList(commaList: string): Option<string[]> {
1433 if (commaList !== "") {
1434 let list = commaList.trim().split(",");