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,
89 className="community-form"
90 onSubmit={linkEvent(this, this.handleCreateCommunitySubmit)}
94 !this.props.loading &&
96 this.state.form.name ||
97 this.state.form.title ||
98 this.state.form.description
100 !this.state.submitted
103 {!this.props.community_view && (
104 <div className="mb-3 row">
106 className="col-12 col-sm-2 col-form-label"
107 htmlFor="community-name"
111 className="position-absolute pointer unselectable ms-2 text-muted"
112 data-tippy-content={i18n.t("name_explain")}
114 <Icon icon="help-circle" classes="icon-inline" />
117 <div className="col-12 col-sm-10">
121 className="form-control"
122 value={this.state.form.name}
123 onInput={linkEvent(this, this.handleCommunityNameChange)}
127 title={i18n.t("community_reqs")}
132 <div className="mb-3 row">
134 className="col-12 col-sm-2 col-form-label"
135 htmlFor="community-title"
137 {i18n.t("display_name")}
139 className="position-absolute pointer unselectable ms-2 text-muted"
140 data-tippy-content={i18n.t("display_name_explain")}
142 <Icon icon="help-circle" classes="icon-inline" />
145 <div className="col-12 col-sm-10">
149 value={this.state.form.title}
150 onInput={linkEvent(this, this.handleCommunityTitleChange)}
151 className="form-control"
158 <div className="mb-3 row">
159 <label className="col-12 col-sm-2 col-form-label">
162 <div className="col-12 col-sm-10">
164 uploadTitle={i18n.t("upload_icon")}
165 imageSrc={this.state.form.icon}
166 onUpload={this.handleIconUpload}
167 onRemove={this.handleIconRemove}
172 <div className="mb-3 row">
173 <label className="col-12 col-sm-2 col-form-label">
176 <div className="col-12 col-sm-10">
178 uploadTitle={i18n.t("upload_banner")}
179 imageSrc={this.state.form.banner}
180 onUpload={this.handleBannerUpload}
181 onRemove={this.handleBannerRemove}
185 <div className="mb-3 row">
186 <label className="col-12 col-sm-2 col-form-label" htmlFor={this.id}>
189 <div className="col-12 col-sm-10">
191 initialContent={this.state.form.description}
192 placeholder={i18n.t("description")}
193 onContentChange={this.handleCommunityDescriptionChange}
194 hideNavigationWarnings
201 {this.props.enableNsfw && (
202 <div className="mb-3 row">
203 <legend className="col-form-label col-sm-2 pt-0">
206 <div className="col-10">
207 <div className="form-check">
209 className="form-check-input position-static"
212 checked={this.state.form.nsfw}
213 onChange={linkEvent(this, this.handleCommunityNsfwChange)}
219 <div className="mb-3 row">
220 <legend className="col-form-label col-6 pt-0">
221 {i18n.t("only_mods_can_post_in_community")}
223 <div className="col-6">
224 <div className="form-check">
226 className="form-check-input position-static"
227 id="community-only-mods-can-post"
229 checked={this.state.form.posting_restricted_to_mods}
232 this.handleCommunityPostingRestrictedToMods
239 allLanguages={this.props.allLanguages}
240 siteLanguages={this.props.siteLanguages}
242 selectedLanguageIds={this.state.form.discussion_languages}
244 onChange={this.handleDiscussionLanguageChange}
246 <div className="mb-3 row">
247 <div className="col-12">
250 className="btn btn-secondary me-2"
251 disabled={this.props.loading}
253 {this.props.loading ? (
255 ) : this.props.community_view ? (
256 capitalizeFirstLetter(i18n.t("save"))
258 capitalizeFirstLetter(i18n.t("create"))
261 {this.props.community_view && (
264 className="btn btn-secondary"
265 onClick={linkEvent(this, this.handleCancel)}
276 handleCreateCommunitySubmit(i: CommunityForm, event: any) {
277 event.preventDefault();
278 i.setState({ submitted: true });
279 const cForm = i.state.form;
280 const auth = myAuthRequired();
282 const cv = i.props.community_view;
285 i.props.onUpsertCommunity({
286 community_id: cv.community.id,
288 description: cForm.description,
290 banner: cForm.banner,
292 posting_restricted_to_mods: cForm.posting_restricted_to_mods,
293 discussion_languages: cForm.discussion_languages,
297 if (cForm.title && cForm.name) {
298 i.props.onUpsertCommunity({
301 description: cForm.description,
303 banner: cForm.banner,
305 posting_restricted_to_mods: cForm.posting_restricted_to_mods,
306 discussion_languages: cForm.discussion_languages,
313 handleCommunityNameChange(i: CommunityForm, event: any) {
314 i.setState(s => ((s.form.name = event.target.value), s));
317 handleCommunityTitleChange(i: CommunityForm, event: any) {
318 i.setState(s => ((s.form.title = event.target.value), s));
321 handleCommunityDescriptionChange(val: string) {
322 this.setState(s => ((s.form.description = val), s));
325 handleCommunityNsfwChange(i: CommunityForm, event: any) {
326 i.setState(s => ((s.form.nsfw = event.target.checked), s));
329 handleCommunityPostingRestrictedToMods(i: CommunityForm, event: any) {
331 s => ((s.form.posting_restricted_to_mods = event.target.checked), s)
335 handleCancel(i: CommunityForm) {
336 i.props.onCancel?.();
339 handleIconUpload(url: string) {
340 this.setState(s => ((s.form.icon = url), s));
344 this.setState(s => ((s.form.icon = ""), s));
347 handleBannerUpload(url: string) {
348 this.setState(s => ((s.form.banner = url), s));
351 handleBannerRemove() {
352 this.setState(s => ((s.form.banner = ""), s));
355 handleDiscussionLanguageChange(val: number[]) {
356 this.setState(s => ((s.form.discussion_languages = val), s));