1 import { Component, linkEvent } from 'inferno';
2 import { Prompt } from 'inferno-router';
3 import { Subscription } from 'rxjs';
11 } from 'lemmy-js-client';
12 import { UserService, WebSocketService } from '../services';
15 capitalizeFirstLetter,
21 import { i18n } from '../i18next';
23 import { MarkdownTextArea } from './markdown-textarea';
24 import { ImageUploadForm } from './image-upload-form';
26 interface CommunityFormProps {
27 community_view?: CommunityView; // If a community is given, that means this is an edit
28 categories: Category[];
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 = {
51 category_id: this.props.categories[0].id,
55 auth: UserService.Instance.authField(),
60 constructor(props: any, context: any) {
61 super(props, context);
63 this.state = this.emptyState;
65 this.handleCommunityDescriptionChange = this.handleCommunityDescriptionChange.bind(
69 this.handleIconUpload = this.handleIconUpload.bind(this);
70 this.handleIconRemove = this.handleIconRemove.bind(this);
72 this.handleBannerUpload = this.handleBannerUpload.bind(this);
73 this.handleBannerRemove = this.handleBannerRemove.bind(this);
75 let cv = this.props.community_view;
77 this.state.communityForm = {
78 name: cv.community.name,
79 title: cv.community.title,
80 category_id: cv.category.id,
81 description: cv.community.description,
82 nsfw: cv.community.nsfw,
83 icon: cv.community.icon,
84 banner: cv.community.banner,
85 auth: UserService.Instance.authField(),
89 this.parseMessage = this.parseMessage.bind(this);
90 this.subscription = wsSubscribe(this.parseMessage);
93 // TODO this should be checked out
94 componentDidUpdate() {
96 !this.state.loading &&
97 (this.state.communityForm.name ||
98 this.state.communityForm.title ||
99 this.state.communityForm.description)
101 window.onbeforeunload = () => true;
103 window.onbeforeunload = undefined;
107 componentWillUnmount() {
108 this.subscription.unsubscribe();
109 window.onbeforeunload = null;
117 !this.state.loading &&
118 (this.state.communityForm.name ||
119 this.state.communityForm.title ||
120 this.state.communityForm.description)
122 message={i18n.t('block_leaving')}
124 <form onSubmit={linkEvent(this, this.handleCreateCommunitySubmit)}>
125 {!this.props.community_view && (
126 <div class="form-group row">
127 <label class="col-12 col-form-label" htmlFor="community-name">
130 class="pointer unselectable ml-2 text-muted"
131 data-tippy-content={i18n.t('name_explain')}
133 <svg class="icon icon-inline">
134 <use xlinkHref="#icon-help-circle"></use>
143 value={this.state.communityForm.name}
144 onInput={linkEvent(this, this.handleCommunityNameChange)}
149 title={i18n.t('community_reqs')}
154 <div class="form-group row">
155 <label class="col-12 col-form-label" htmlFor="community-title">
156 {i18n.t('display_name')}
158 class="pointer unselectable ml-2 text-muted"
159 data-tippy-content={i18n.t('display_name_explain')}
161 <svg class="icon icon-inline">
162 <use xlinkHref="#icon-help-circle"></use>
170 value={this.state.communityForm.title}
171 onInput={linkEvent(this, this.handleCommunityTitleChange)}
179 <div class="form-group">
180 <label>{i18n.t('icon')}</label>
182 uploadTitle={i18n.t('upload_icon')}
183 imageSrc={this.state.communityForm.icon}
184 onUpload={this.handleIconUpload}
185 onRemove={this.handleIconRemove}
189 <div class="form-group">
190 <label>{i18n.t('banner')}</label>
192 uploadTitle={i18n.t('upload_banner')}
193 imageSrc={this.state.communityForm.banner}
194 onUpload={this.handleBannerUpload}
195 onRemove={this.handleBannerRemove}
198 <div class="form-group row">
199 <label class="col-12 col-form-label" htmlFor={this.id}>
204 initialContent={this.state.communityForm.description}
205 onContentChange={this.handleCommunityDescriptionChange}
209 <div class="form-group row">
210 <label class="col-12 col-form-label" htmlFor="community-category">
216 id="community-category"
217 value={this.state.communityForm.category_id}
218 onInput={linkEvent(this, this.handleCommunityCategoryChange)}
220 {this.props.categories.map(category => (
221 <option value={category.id}>{category.name}</option>
227 {this.props.enableNsfw && (
228 <div class="form-group row">
230 <div class="form-check">
232 class="form-check-input"
235 checked={this.state.communityForm.nsfw}
236 onChange={linkEvent(this, this.handleCommunityNsfwChange)}
238 <label class="form-check-label" htmlFor="community-nsfw">
245 <div class="form-group row">
249 class="btn btn-secondary mr-2"
250 disabled={this.state.loading}
252 {this.state.loading ? (
253 <svg class="icon icon-spinner spin">
254 <use xlinkHref="#icon-spinner"></use>
256 ) : this.props.community_view ? (
257 capitalizeFirstLetter(i18n.t('save'))
259 capitalizeFirstLetter(i18n.t('create'))
262 {this.props.community_view && (
265 class="btn btn-secondary"
266 onClick={linkEvent(this, this.handleCancel)}
278 handleCreateCommunitySubmit(i: CommunityForm, event: any) {
279 event.preventDefault();
280 i.state.loading = true;
281 if (i.props.community_view) {
282 let form: EditCommunity = {
283 ...i.state.communityForm,
284 edit_id: i.props.community_view.community.id,
286 WebSocketService.Instance.client.editCommunity(form);
288 WebSocketService.Instance.client.createCommunity(i.state.communityForm);
293 handleCommunityNameChange(i: CommunityForm, event: any) {
294 i.state.communityForm.name = event.target.value;
298 handleCommunityTitleChange(i: CommunityForm, event: any) {
299 i.state.communityForm.title = event.target.value;
303 handleCommunityDescriptionChange(val: string) {
304 this.state.communityForm.description = val;
305 this.setState(this.state);
308 handleCommunityCategoryChange(i: CommunityForm, event: any) {
309 i.state.communityForm.category_id = Number(event.target.value);
313 handleCommunityNsfwChange(i: CommunityForm, event: any) {
314 i.state.communityForm.nsfw = event.target.checked;
318 handleCancel(i: CommunityForm) {
322 handleIconUpload(url: string) {
323 this.state.communityForm.icon = url;
324 this.setState(this.state);
328 this.state.communityForm.icon = '';
329 this.setState(this.state);
332 handleBannerUpload(url: string) {
333 this.state.communityForm.banner = url;
334 this.setState(this.state);
337 handleBannerRemove() {
338 this.state.communityForm.banner = '';
339 this.setState(this.state);
342 parseMessage(msg: any) {
343 let op = wsUserOp(msg);
345 toast(i18n.t(msg.error), 'danger');
346 this.state.loading = false;
347 this.setState(this.state);
349 } else if (op == UserOperation.CreateCommunity) {
350 let data = wsJsonToRes<CommunityResponse>(msg).data;
351 this.state.loading = false;
352 this.props.onCreate(data.community_view);
353 } else if (op == UserOperation.EditCommunity) {
354 let data = wsJsonToRes<CommunityResponse>(msg).data;
355 this.state.loading = false;
356 this.props.onEdit(data.community_view);