1 import { Component, linkEvent } from "inferno";
7 } from "lemmy-js-client";
8 import { i18n } from "../../i18next";
9 import { capitalizeFirstLetter, myAuthRequired, randomStr } from "../../utils";
10 import { Icon, Spinner } from "../common/icon";
11 import { ImageUploadForm } from "../common/image-upload-form";
12 import { LanguageSelect } from "../common/language-select";
13 import { MarkdownTextArea } from "../common/markdown-textarea";
14 import NavigationPrompt from "../common/navigation-prompt";
16 interface CommunityFormProps {
17 community_view?: CommunityView; // If a community is given, that means this is an edit
18 allLanguages: Language[];
19 siteLanguages: number[];
20 communityLanguages?: number[];
22 onUpsertCommunity(form: CreateCommunity | EditCommunity): void;
26 interface CommunityFormState {
34 posting_restricted_to_mods?: boolean;
35 discussion_languages?: number[];
41 export class CommunityForm extends Component<
45 private id = `community-form-${randomStr()}`;
47 state: CommunityFormState = {
53 constructor(props: any, context: any) {
54 super(props, context);
56 this.handleCommunityDescriptionChange =
57 this.handleCommunityDescriptionChange.bind(this);
59 this.handleIconUpload = this.handleIconUpload.bind(this);
60 this.handleIconRemove = this.handleIconRemove.bind(this);
62 this.handleBannerUpload = this.handleBannerUpload.bind(this);
63 this.handleBannerRemove = this.handleBannerRemove.bind(this);
65 this.handleDiscussionLanguageChange =
66 this.handleDiscussionLanguageChange.bind(this);
68 const cv = this.props.community_view;
74 name: cv.community.name,
75 title: cv.community.title,
76 description: cv.community.description,
77 nsfw: cv.community.nsfw,
78 icon: cv.community.icon,
79 banner: cv.community.banner,
80 posting_restricted_to_mods: cv.community.posting_restricted_to_mods,
81 discussion_languages: this.props.communityLanguages,
90 <form onSubmit={linkEvent(this, this.handleCreateCommunitySubmit)}>
93 !this.state.loading &&
95 this.state.form.name ||
96 this.state.form.title ||
97 this.state.form.description
102 {!this.props.community_view && (
103 <div className="form-group row">
105 className="col-12 col-sm-2 col-form-label"
106 htmlFor="community-name"
110 className="position-absolute pointer unselectable ml-2 text-muted"
111 data-tippy-content={i18n.t("name_explain")}
113 <Icon icon="help-circle" classes="icon-inline" />
116 <div className="col-12 col-sm-10">
120 className="form-control"
121 value={this.state.form.name}
122 onInput={linkEvent(this, this.handleCommunityNameChange)}
126 title={i18n.t("community_reqs")}
131 <div className="form-group row">
133 className="col-12 col-sm-2 col-form-label"
134 htmlFor="community-title"
136 {i18n.t("display_name")}
138 className="position-absolute pointer unselectable ml-2 text-muted"
139 data-tippy-content={i18n.t("display_name_explain")}
141 <Icon icon="help-circle" classes="icon-inline" />
144 <div className="col-12 col-sm-10">
148 value={this.state.form.title}
149 onInput={linkEvent(this, this.handleCommunityTitleChange)}
150 className="form-control"
157 <div className="form-group row">
158 <label className="col-12 col-sm-2">{i18n.t("icon")}</label>
159 <div className="col-12 col-sm-10">
161 uploadTitle={i18n.t("upload_icon")}
162 imageSrc={this.state.form.icon}
163 onUpload={this.handleIconUpload}
164 onRemove={this.handleIconRemove}
169 <div className="form-group row">
170 <label className="col-12 col-sm-2">{i18n.t("banner")}</label>
171 <div className="col-12 col-sm-10">
173 uploadTitle={i18n.t("upload_banner")}
174 imageSrc={this.state.form.banner}
175 onUpload={this.handleBannerUpload}
176 onRemove={this.handleBannerRemove}
180 <div className="form-group row">
181 <label className="col-12 col-sm-2 col-form-label" htmlFor={this.id}>
184 <div className="col-12 col-sm-10">
186 initialContent={this.state.form.description}
187 placeholder={i18n.t("description")}
188 onContentChange={this.handleCommunityDescriptionChange}
189 hideNavigationWarnings
196 {this.props.enableNsfw && (
197 <div className="form-group row">
198 <legend className="col-form-label col-sm-2 pt-0">
201 <div className="col-10">
202 <div className="form-check">
204 className="form-check-input position-static"
207 checked={this.state.form.nsfw}
208 onChange={linkEvent(this, this.handleCommunityNsfwChange)}
214 <div className="form-group row">
215 <legend className="col-form-label col-6 pt-0">
216 {i18n.t("only_mods_can_post_in_community")}
218 <div className="col-6">
219 <div className="form-check">
221 className="form-check-input position-static"
222 id="community-only-mods-can-post"
224 checked={this.state.form.posting_restricted_to_mods}
227 this.handleCommunityPostingRestrictedToMods
234 allLanguages={this.props.allLanguages}
235 siteLanguages={this.props.siteLanguages}
237 selectedLanguageIds={this.state.form.discussion_languages}
239 onChange={this.handleDiscussionLanguageChange}
241 <div className="form-group row">
242 <div className="col-12">
245 className="btn btn-secondary mr-2"
246 disabled={this.state.loading}
248 {this.state.loading ? (
250 ) : this.props.community_view ? (
251 capitalizeFirstLetter(i18n.t("save"))
253 capitalizeFirstLetter(i18n.t("create"))
256 {this.props.community_view && (
259 className="btn btn-secondary"
260 onClick={linkEvent(this, this.handleCancel)}
271 handleCreateCommunitySubmit(i: CommunityForm, event: any) {
272 event.preventDefault();
273 i.setState({ loading: true, submitted: true });
274 const cForm = i.state.form;
275 const auth = myAuthRequired();
277 const cv = i.props.community_view;
280 i.props.onUpsertCommunity({
281 community_id: cv.community.id,
283 description: cForm.description,
285 banner: cForm.banner,
287 posting_restricted_to_mods: cForm.posting_restricted_to_mods,
288 discussion_languages: cForm.discussion_languages,
292 if (cForm.title && cForm.name) {
293 i.props.onUpsertCommunity({
296 description: cForm.description,
298 banner: cForm.banner,
300 posting_restricted_to_mods: cForm.posting_restricted_to_mods,
301 discussion_languages: cForm.discussion_languages,
308 handleCommunityNameChange(i: CommunityForm, event: any) {
309 i.setState(s => ((s.form.name = event.target.value), s));
312 handleCommunityTitleChange(i: CommunityForm, event: any) {
313 i.setState(s => ((s.form.title = event.target.value), s));
316 handleCommunityDescriptionChange(val: string) {
317 this.setState(s => ((s.form.description = val), s));
320 handleCommunityNsfwChange(i: CommunityForm, event: any) {
321 i.setState(s => ((s.form.nsfw = event.target.checked), s));
324 handleCommunityPostingRestrictedToMods(i: CommunityForm, event: any) {
326 s => ((s.form.posting_restricted_to_mods = event.target.checked), s)
330 handleCancel(i: CommunityForm) {
331 i.props.onCancel?.();
334 handleIconUpload(url: string) {
335 this.setState(s => ((s.form.icon = url), s));
339 this.setState(s => ((s.form.icon = ""), s));
342 handleBannerUpload(url: string) {
343 this.setState(s => ((s.form.banner = url), s));
346 handleBannerRemove() {
347 this.setState(s => ((s.form.banner = ""), s));
350 handleDiscussionLanguageChange(val: number[]) {
351 this.setState(s => ((s.form.discussion_languages = val), s));