1 import { Component, linkEvent } from "inferno";
2 import { Prompt } from "inferno-router";
9 } from "lemmy-js-client";
10 import { Subscription } from "rxjs";
11 import { i18n } from "../../i18next";
12 import { UserService, WebSocketService } from "../../services";
15 capitalizeFirstLetter,
23 import { Icon, Spinner } from "../common/icon";
24 import { ImageUploadForm } from "../common/image-upload-form";
25 import { MarkdownTextArea } from "../common/markdown-textarea";
27 interface CommunityFormProps {
28 community_view?: CommunityView; // If a community is given, that means this is an edit
30 onCreate?(community: CommunityView): any;
31 onEdit?(community: CommunityView): any;
35 interface CommunityFormState {
36 communityForm: CreateCommunity;
40 export class CommunityForm extends Component<
44 private id = `community-form-${randomStr()}`;
45 private subscription: Subscription;
47 private emptyState: CommunityFormState = {
54 auth: authField(false),
59 constructor(props: any, context: any) {
60 super(props, context);
62 this.state = this.emptyState;
64 this.handleCommunityDescriptionChange =
65 this.handleCommunityDescriptionChange.bind(this);
67 this.handleIconUpload = this.handleIconUpload.bind(this);
68 this.handleIconRemove = this.handleIconRemove.bind(this);
70 this.handleBannerUpload = this.handleBannerUpload.bind(this);
71 this.handleBannerRemove = this.handleBannerRemove.bind(this);
73 let cv = this.props.community_view;
75 this.state.communityForm = {
76 name: cv.community.name,
77 title: cv.community.title,
78 description: cv.community.description,
79 nsfw: cv.community.nsfw,
80 icon: cv.community.icon,
81 banner: cv.community.banner,
86 this.parseMessage = this.parseMessage.bind(this);
87 this.subscription = wsSubscribe(this.parseMessage);
90 // TODO this should be checked out
91 componentDidUpdate() {
93 !this.state.loading &&
94 (this.state.communityForm.name ||
95 this.state.communityForm.title ||
96 this.state.communityForm.description)
98 window.onbeforeunload = () => true;
100 window.onbeforeunload = undefined;
104 componentWillUnmount() {
105 this.subscription.unsubscribe();
106 window.onbeforeunload = null;
114 !this.state.loading &&
115 (this.state.communityForm.name ||
116 this.state.communityForm.title ||
117 this.state.communityForm.description)
119 message={i18n.t("block_leaving")}
121 <form onSubmit={linkEvent(this, this.handleCreateCommunitySubmit)}>
122 {!this.props.community_view && (
123 <div class="form-group row">
125 class="col-12 col-sm-2 col-form-label"
126 htmlFor="community-name"
130 class="position-absolute pointer unselectable ml-2 text-muted"
131 data-tippy-content={i18n.t("name_explain")}
133 <Icon icon="help-circle" classes="icon-inline" />
136 <div class="col-12 col-sm-10">
141 value={this.state.communityForm.name}
142 onInput={linkEvent(this, this.handleCommunityNameChange)}
146 title={i18n.t("community_reqs")}
151 <div class="form-group row">
153 class="col-12 col-sm-2 col-form-label"
154 htmlFor="community-title"
156 {i18n.t("display_name")}
158 class="position-absolute pointer unselectable ml-2 text-muted"
159 data-tippy-content={i18n.t("display_name_explain")}
161 <Icon icon="help-circle" classes="icon-inline" />
164 <div class="col-12 col-sm-10">
168 value={this.state.communityForm.title}
169 onInput={linkEvent(this, this.handleCommunityTitleChange)}
177 <div class="form-group row">
178 <label class="col-12 col-sm-2">{i18n.t("icon")}</label>
179 <div class="col-12 col-sm-10">
181 uploadTitle={i18n.t("upload_icon")}
182 imageSrc={this.state.communityForm.icon}
183 onUpload={this.handleIconUpload}
184 onRemove={this.handleIconRemove}
189 <div class="form-group row">
190 <label class="col-12 col-sm-2">{i18n.t("banner")}</label>
191 <div class="col-12 col-sm-10">
193 uploadTitle={i18n.t("upload_banner")}
194 imageSrc={this.state.communityForm.banner}
195 onUpload={this.handleBannerUpload}
196 onRemove={this.handleBannerRemove}
200 <div class="form-group row">
201 <label class="col-12 col-sm-2 col-form-label" htmlFor={this.id}>
204 <div class="col-12 col-sm-10">
206 initialContent={this.state.communityForm.description}
207 onContentChange={this.handleCommunityDescriptionChange}
212 {this.props.enableNsfw && (
213 <div class="form-group row">
214 <legend class="col-form-label col-sm-2 pt-0">
218 <div class="form-check">
220 class="form-check-input position-static"
223 checked={this.state.communityForm.nsfw}
224 onChange={linkEvent(this, this.handleCommunityNsfwChange)}
230 <div class="form-group row">
234 class="btn btn-secondary mr-2"
235 disabled={this.state.loading}
237 {this.state.loading ? (
239 ) : this.props.community_view ? (
240 capitalizeFirstLetter(i18n.t("save"))
242 capitalizeFirstLetter(i18n.t("create"))
245 {this.props.community_view && (
248 class="btn btn-secondary"
249 onClick={linkEvent(this, this.handleCancel)}
261 handleCreateCommunitySubmit(i: CommunityForm, event: any) {
262 event.preventDefault();
263 i.state.loading = true;
264 if (i.props.community_view) {
265 let form: EditCommunity = {
266 ...i.state.communityForm,
267 community_id: i.props.community_view.community.id,
269 WebSocketService.Instance.send(wsClient.editCommunity(form));
271 WebSocketService.Instance.send(
272 wsClient.createCommunity(i.state.communityForm)
278 handleCommunityNameChange(i: CommunityForm, event: any) {
279 i.state.communityForm.name = event.target.value;
283 handleCommunityTitleChange(i: CommunityForm, event: any) {
284 i.state.communityForm.title = event.target.value;
288 handleCommunityDescriptionChange(val: string) {
289 this.state.communityForm.description = val;
290 this.setState(this.state);
293 handleCommunityNsfwChange(i: CommunityForm, event: any) {
294 i.state.communityForm.nsfw = event.target.checked;
298 handleCancel(i: CommunityForm) {
302 handleIconUpload(url: string) {
303 this.state.communityForm.icon = url;
304 this.setState(this.state);
308 this.state.communityForm.icon = "";
309 this.setState(this.state);
312 handleBannerUpload(url: string) {
313 this.state.communityForm.banner = url;
314 this.setState(this.state);
317 handleBannerRemove() {
318 this.state.communityForm.banner = "";
319 this.setState(this.state);
322 parseMessage(msg: any) {
323 let op = wsUserOp(msg);
326 toast(i18n.t(msg.error), "danger");
327 this.state.loading = false;
328 this.setState(this.state);
330 } else if (op == UserOperation.CreateCommunity) {
331 let data = wsJsonToRes<CommunityResponse>(msg).data;
332 this.state.loading = false;
333 this.props.onCreate(data.community_view);
336 let community = data.community_view.community;
337 let person = UserService.Instance.myUserInfo.local_user_view.person;
338 UserService.Instance.myUserInfo.follows.push({
342 UserService.Instance.myUserInfo.moderates.push({
346 } else if (op == UserOperation.EditCommunity) {
347 let data = wsJsonToRes<CommunityResponse>(msg).data;
348 this.state.loading = false;
349 this.props.onEdit(data.community_view);
350 let community = data.community_view.community;
352 let followFound = UserService.Instance.myUserInfo.follows.findIndex(
353 f => f.community.id == community.id
356 UserService.Instance.myUserInfo.follows[followFound].community =
360 let moderatesFound = UserService.Instance.myUserInfo.moderates.findIndex(
361 f => f.community.id == community.id
363 if (moderatesFound) {
364 UserService.Instance.myUserInfo.moderates[moderatesFound].community =