1 import { Component, linkEvent } from 'inferno';
2 import { Prompt } from 'inferno-router';
3 import { Subscription } from 'rxjs';
11 } from 'lemmy-js-client';
12 import { WebSocketService } from '../services';
15 capitalizeFirstLetter,
23 import { i18n } from '../i18next';
25 import { MarkdownTextArea } from './markdown-textarea';
26 import { ImageUploadForm } from './image-upload-form';
28 interface CommunityFormProps {
29 community_view?: CommunityView; // If a community is given, that means this is an edit
30 categories: Category[];
32 onCreate?(community: CommunityView): any;
33 onEdit?(community: CommunityView): any;
37 interface CommunityFormState {
38 communityForm: CreateCommunity;
42 export class CommunityForm extends Component<
46 private id = `community-form-${randomStr()}`;
47 private subscription: Subscription;
49 private emptyState: CommunityFormState = {
53 category_id: this.props.categories[0].id,
62 constructor(props: any, context: any) {
63 super(props, context);
65 this.state = this.emptyState;
67 this.handleCommunityDescriptionChange = this.handleCommunityDescriptionChange.bind(
71 this.handleIconUpload = this.handleIconUpload.bind(this);
72 this.handleIconRemove = this.handleIconRemove.bind(this);
74 this.handleBannerUpload = this.handleBannerUpload.bind(this);
75 this.handleBannerRemove = this.handleBannerRemove.bind(this);
77 let cv = this.props.community_view;
79 this.state.communityForm = {
80 name: cv.community.name,
81 title: cv.community.title,
82 category_id: cv.category.id,
83 description: cv.community.description,
84 nsfw: cv.community.nsfw,
85 icon: cv.community.icon,
86 banner: cv.community.banner,
91 this.parseMessage = this.parseMessage.bind(this);
92 this.subscription = wsSubscribe(this.parseMessage);
95 // TODO this should be checked out
96 componentDidUpdate() {
98 !this.state.loading &&
99 (this.state.communityForm.name ||
100 this.state.communityForm.title ||
101 this.state.communityForm.description)
103 window.onbeforeunload = () => true;
105 window.onbeforeunload = undefined;
109 componentWillUnmount() {
110 this.subscription.unsubscribe();
111 window.onbeforeunload = null;
119 !this.state.loading &&
120 (this.state.communityForm.name ||
121 this.state.communityForm.title ||
122 this.state.communityForm.description)
124 message={i18n.t('block_leaving')}
126 <form onSubmit={linkEvent(this, this.handleCreateCommunitySubmit)}>
127 {!this.props.community_view && (
128 <div class="form-group row">
129 <label class="col-12 col-form-label" htmlFor="community-name">
132 class="pointer unselectable ml-2 text-muted"
133 data-tippy-content={i18n.t('name_explain')}
135 <svg class="icon icon-inline">
136 <use xlinkHref="#icon-help-circle"></use>
145 value={this.state.communityForm.name}
146 onInput={linkEvent(this, this.handleCommunityNameChange)}
151 title={i18n.t('community_reqs')}
156 <div class="form-group row">
157 <label class="col-12 col-form-label" htmlFor="community-title">
158 {i18n.t('display_name')}
160 class="pointer unselectable ml-2 text-muted"
161 data-tippy-content={i18n.t('display_name_explain')}
163 <svg class="icon icon-inline">
164 <use xlinkHref="#icon-help-circle"></use>
172 value={this.state.communityForm.title}
173 onInput={linkEvent(this, this.handleCommunityTitleChange)}
181 <div class="form-group">
182 <label>{i18n.t('icon')}</label>
184 uploadTitle={i18n.t('upload_icon')}
185 imageSrc={this.state.communityForm.icon}
186 onUpload={this.handleIconUpload}
187 onRemove={this.handleIconRemove}
191 <div class="form-group">
192 <label>{i18n.t('banner')}</label>
194 uploadTitle={i18n.t('upload_banner')}
195 imageSrc={this.state.communityForm.banner}
196 onUpload={this.handleBannerUpload}
197 onRemove={this.handleBannerRemove}
200 <div class="form-group row">
201 <label class="col-12 col-form-label" htmlFor={this.id}>
206 initialContent={this.state.communityForm.description}
207 onContentChange={this.handleCommunityDescriptionChange}
211 <div class="form-group row">
212 <label class="col-12 col-form-label" htmlFor="community-category">
218 id="community-category"
219 value={this.state.communityForm.category_id}
220 onInput={linkEvent(this, this.handleCommunityCategoryChange)}
222 {this.props.categories.map(category => (
223 <option value={category.id}>{category.name}</option>
229 {this.props.enableNsfw && (
230 <div class="form-group row">
232 <div class="form-check">
234 class="form-check-input"
237 checked={this.state.communityForm.nsfw}
238 onChange={linkEvent(this, this.handleCommunityNsfwChange)}
240 <label class="form-check-label" htmlFor="community-nsfw">
247 <div class="form-group row">
251 class="btn btn-secondary mr-2"
252 disabled={this.state.loading}
254 {this.state.loading ? (
255 <svg class="icon icon-spinner spin">
256 <use xlinkHref="#icon-spinner"></use>
258 ) : this.props.community_view ? (
259 capitalizeFirstLetter(i18n.t('save'))
261 capitalizeFirstLetter(i18n.t('create'))
264 {this.props.community_view && (
267 class="btn btn-secondary"
268 onClick={linkEvent(this, this.handleCancel)}
280 handleCreateCommunitySubmit(i: CommunityForm, event: any) {
281 event.preventDefault();
282 i.state.loading = true;
283 if (i.props.community_view) {
284 let form: EditCommunity = {
285 ...i.state.communityForm,
286 edit_id: i.props.community_view.community.id,
288 WebSocketService.Instance.send(wsClient.editCommunity(form));
290 WebSocketService.Instance.send(
291 wsClient.createCommunity(i.state.communityForm)
297 handleCommunityNameChange(i: CommunityForm, event: any) {
298 i.state.communityForm.name = event.target.value;
302 handleCommunityTitleChange(i: CommunityForm, event: any) {
303 i.state.communityForm.title = event.target.value;
307 handleCommunityDescriptionChange(val: string) {
308 this.state.communityForm.description = val;
309 this.setState(this.state);
312 handleCommunityCategoryChange(i: CommunityForm, event: any) {
313 i.state.communityForm.category_id = Number(event.target.value);
317 handleCommunityNsfwChange(i: CommunityForm, event: any) {
318 i.state.communityForm.nsfw = event.target.checked;
322 handleCancel(i: CommunityForm) {
326 handleIconUpload(url: string) {
327 this.state.communityForm.icon = url;
328 this.setState(this.state);
332 this.state.communityForm.icon = '';
333 this.setState(this.state);
336 handleBannerUpload(url: string) {
337 this.state.communityForm.banner = url;
338 this.setState(this.state);
341 handleBannerRemove() {
342 this.state.communityForm.banner = '';
343 this.setState(this.state);
346 parseMessage(msg: any) {
347 let op = wsUserOp(msg);
349 toast(i18n.t(msg.error), 'danger');
350 this.state.loading = false;
351 this.setState(this.state);
353 } else if (op == UserOperation.CreateCommunity) {
354 let data = wsJsonToRes<CommunityResponse>(msg).data;
355 this.state.loading = false;
356 this.props.onCreate(data.community_view);
357 } else if (op == UserOperation.EditCommunity) {
358 let data = wsJsonToRes<CommunityResponse>(msg).data;
359 this.state.loading = false;
360 this.props.onEdit(data.community_view);