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;
27 interface CommunityFormState {
35 posting_restricted_to_mods?: boolean;
36 discussion_languages?: number[];
41 export class CommunityForm extends Component<
45 private id = `community-form-${randomStr()}`;
47 state: CommunityFormState = {
52 constructor(props: any, context: any) {
53 super(props, context);
55 this.handleCommunityDescriptionChange =
56 this.handleCommunityDescriptionChange.bind(this);
58 this.handleIconUpload = this.handleIconUpload.bind(this);
59 this.handleIconRemove = this.handleIconRemove.bind(this);
61 this.handleBannerUpload = this.handleBannerUpload.bind(this);
62 this.handleBannerRemove = this.handleBannerRemove.bind(this);
64 this.handleDiscussionLanguageChange =
65 this.handleDiscussionLanguageChange.bind(this);
67 const cv = this.props.community_view;
73 name: cv.community.name,
74 title: cv.community.title,
75 description: cv.community.description,
76 nsfw: cv.community.nsfw,
77 icon: cv.community.icon,
78 banner: cv.community.banner,
79 posting_restricted_to_mods: cv.community.posting_restricted_to_mods,
80 discussion_languages: this.props.communityLanguages,
88 <form onSubmit={linkEvent(this, this.handleCreateCommunitySubmit)}>
91 !this.props.loading &&
93 this.state.form.name ||
94 this.state.form.title ||
95 this.state.form.description
100 {!this.props.community_view && (
101 <div className="form-group row">
103 className="col-12 col-sm-2 col-form-label"
104 htmlFor="community-name"
108 className="position-absolute pointer unselectable ml-2 text-muted"
109 data-tippy-content={i18n.t("name_explain")}
111 <Icon icon="help-circle" classes="icon-inline" />
114 <div className="col-12 col-sm-10">
118 className="form-control"
119 value={this.state.form.name}
120 onInput={linkEvent(this, this.handleCommunityNameChange)}
124 title={i18n.t("community_reqs")}
129 <div className="form-group row">
131 className="col-12 col-sm-2 col-form-label"
132 htmlFor="community-title"
134 {i18n.t("display_name")}
136 className="position-absolute pointer unselectable ml-2 text-muted"
137 data-tippy-content={i18n.t("display_name_explain")}
139 <Icon icon="help-circle" classes="icon-inline" />
142 <div className="col-12 col-sm-10">
146 value={this.state.form.title}
147 onInput={linkEvent(this, this.handleCommunityTitleChange)}
148 className="form-control"
155 <div className="form-group row">
156 <label className="col-12 col-sm-2">{i18n.t("icon")}</label>
157 <div className="col-12 col-sm-10">
159 uploadTitle={i18n.t("upload_icon")}
160 imageSrc={this.state.form.icon}
161 onUpload={this.handleIconUpload}
162 onRemove={this.handleIconRemove}
167 <div className="form-group row">
168 <label className="col-12 col-sm-2">{i18n.t("banner")}</label>
169 <div className="col-12 col-sm-10">
171 uploadTitle={i18n.t("upload_banner")}
172 imageSrc={this.state.form.banner}
173 onUpload={this.handleBannerUpload}
174 onRemove={this.handleBannerRemove}
178 <div className="form-group row">
179 <label className="col-12 col-sm-2 col-form-label" htmlFor={this.id}>
182 <div className="col-12 col-sm-10">
184 initialContent={this.state.form.description}
185 placeholder={i18n.t("description")}
186 onContentChange={this.handleCommunityDescriptionChange}
187 hideNavigationWarnings
194 {this.props.enableNsfw && (
195 <div className="form-group row">
196 <legend className="col-form-label col-sm-2 pt-0">
199 <div className="col-10">
200 <div className="form-check">
202 className="form-check-input position-static"
205 checked={this.state.form.nsfw}
206 onChange={linkEvent(this, this.handleCommunityNsfwChange)}
212 <div className="form-group row">
213 <legend className="col-form-label col-6 pt-0">
214 {i18n.t("only_mods_can_post_in_community")}
216 <div className="col-6">
217 <div className="form-check">
219 className="form-check-input position-static"
220 id="community-only-mods-can-post"
222 checked={this.state.form.posting_restricted_to_mods}
225 this.handleCommunityPostingRestrictedToMods
232 allLanguages={this.props.allLanguages}
233 siteLanguages={this.props.siteLanguages}
235 selectedLanguageIds={this.state.form.discussion_languages}
237 onChange={this.handleDiscussionLanguageChange}
239 <div className="form-group row">
240 <div className="col-12">
243 className="btn btn-secondary mr-2"
244 disabled={this.props.loading}
246 {this.props.loading ? (
248 ) : this.props.community_view ? (
249 capitalizeFirstLetter(i18n.t("save"))
251 capitalizeFirstLetter(i18n.t("create"))
254 {this.props.community_view && (
257 className="btn btn-secondary"
258 onClick={linkEvent(this, this.handleCancel)}
269 handleCreateCommunitySubmit(i: CommunityForm, event: any) {
270 event.preventDefault();
271 i.setState({ submitted: true });
272 const cForm = i.state.form;
273 const auth = myAuthRequired();
275 const cv = i.props.community_view;
278 i.props.onUpsertCommunity({
279 community_id: cv.community.id,
281 description: cForm.description,
283 banner: cForm.banner,
285 posting_restricted_to_mods: cForm.posting_restricted_to_mods,
286 discussion_languages: cForm.discussion_languages,
290 if (cForm.title && cForm.name) {
291 i.props.onUpsertCommunity({
294 description: cForm.description,
296 banner: cForm.banner,
298 posting_restricted_to_mods: cForm.posting_restricted_to_mods,
299 discussion_languages: cForm.discussion_languages,
306 handleCommunityNameChange(i: CommunityForm, event: any) {
307 i.setState(s => ((s.form.name = event.target.value), s));
310 handleCommunityTitleChange(i: CommunityForm, event: any) {
311 i.setState(s => ((s.form.title = event.target.value), s));
314 handleCommunityDescriptionChange(val: string) {
315 this.setState(s => ((s.form.description = val), s));
318 handleCommunityNsfwChange(i: CommunityForm, event: any) {
319 i.setState(s => ((s.form.nsfw = event.target.checked), s));
322 handleCommunityPostingRestrictedToMods(i: CommunityForm, event: any) {
324 s => ((s.form.posting_restricted_to_mods = event.target.checked), s)
328 handleCancel(i: CommunityForm) {
329 i.props.onCancel?.();
332 handleIconUpload(url: string) {
333 this.setState(s => ((s.form.icon = url), s));
337 this.setState(s => ((s.form.icon = ""), s));
340 handleBannerUpload(url: string) {
341 this.setState(s => ((s.form.banner = url), s));
344 handleBannerRemove() {
345 this.setState(s => ((s.form.banner = ""), s));
348 handleDiscussionLanguageChange(val: number[]) {
349 this.setState(s => ((s.form.discussion_languages = val), s));