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="mb-3 row">
103 className="col-12 col-sm-2 col-form-label"
104 htmlFor="community-name"
108 className="position-absolute pointer unselectable ms-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="mb-3 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 ms-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="mb-3 row">
156 <label className="col-12 col-sm-2 col-form-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="mb-3 row">
170 <label className="col-12 col-sm-2 col-form-label">
173 <div className="col-12 col-sm-10">
175 uploadTitle={i18n.t("upload_banner")}
176 imageSrc={this.state.form.banner}
177 onUpload={this.handleBannerUpload}
178 onRemove={this.handleBannerRemove}
182 <div className="mb-3 row">
183 <label className="col-12 col-sm-2 col-form-label" htmlFor={this.id}>
186 <div className="col-12 col-sm-10">
188 initialContent={this.state.form.description}
189 placeholder={i18n.t("description")}
190 onContentChange={this.handleCommunityDescriptionChange}
191 hideNavigationWarnings
198 {this.props.enableNsfw && (
199 <div className="mb-3 row">
200 <legend className="col-form-label col-sm-2 pt-0">
203 <div className="col-10">
204 <div className="form-check">
206 className="form-check-input position-static"
209 checked={this.state.form.nsfw}
210 onChange={linkEvent(this, this.handleCommunityNsfwChange)}
216 <div className="mb-3 row">
217 <legend className="col-form-label col-6 pt-0">
218 {i18n.t("only_mods_can_post_in_community")}
220 <div className="col-6">
221 <div className="form-check">
223 className="form-check-input position-static"
224 id="community-only-mods-can-post"
226 checked={this.state.form.posting_restricted_to_mods}
229 this.handleCommunityPostingRestrictedToMods
236 allLanguages={this.props.allLanguages}
237 siteLanguages={this.props.siteLanguages}
239 selectedLanguageIds={this.state.form.discussion_languages}
241 onChange={this.handleDiscussionLanguageChange}
243 <div className="mb-3 row">
244 <div className="col-12">
247 className="btn btn-secondary me-2"
248 disabled={this.props.loading}
250 {this.props.loading ? (
252 ) : this.props.community_view ? (
253 capitalizeFirstLetter(i18n.t("save"))
255 capitalizeFirstLetter(i18n.t("create"))
258 {this.props.community_view && (
261 className="btn btn-secondary"
262 onClick={linkEvent(this, this.handleCancel)}
273 handleCreateCommunitySubmit(i: CommunityForm, event: any) {
274 event.preventDefault();
275 i.setState({ submitted: true });
276 const cForm = i.state.form;
277 const auth = myAuthRequired();
279 const cv = i.props.community_view;
282 i.props.onUpsertCommunity({
283 community_id: cv.community.id,
285 description: cForm.description,
287 banner: cForm.banner,
289 posting_restricted_to_mods: cForm.posting_restricted_to_mods,
290 discussion_languages: cForm.discussion_languages,
294 if (cForm.title && cForm.name) {
295 i.props.onUpsertCommunity({
298 description: cForm.description,
300 banner: cForm.banner,
302 posting_restricted_to_mods: cForm.posting_restricted_to_mods,
303 discussion_languages: cForm.discussion_languages,
310 handleCommunityNameChange(i: CommunityForm, event: any) {
311 i.setState(s => ((s.form.name = event.target.value), s));
314 handleCommunityTitleChange(i: CommunityForm, event: any) {
315 i.setState(s => ((s.form.title = event.target.value), s));
318 handleCommunityDescriptionChange(val: string) {
319 this.setState(s => ((s.form.description = val), s));
322 handleCommunityNsfwChange(i: CommunityForm, event: any) {
323 i.setState(s => ((s.form.nsfw = event.target.checked), s));
326 handleCommunityPostingRestrictedToMods(i: CommunityForm, event: any) {
328 s => ((s.form.posting_restricted_to_mods = event.target.checked), s)
332 handleCancel(i: CommunityForm) {
333 i.props.onCancel?.();
336 handleIconUpload(url: string) {
337 this.setState(s => ((s.form.icon = url), s));
341 this.setState(s => ((s.form.icon = ""), s));
344 handleBannerUpload(url: string) {
345 this.setState(s => ((s.form.banner = url), s));
348 handleBannerRemove() {
349 this.setState(s => ((s.form.banner = ""), s));
352 handleDiscussionLanguageChange(val: number[]) {
353 this.setState(s => ((s.form.discussion_languages = val), s));