1 import { Component, linkEvent } from 'inferno';
2 import { Prompt } from 'inferno-router';
3 import { Subscription } from 'rxjs';
4 import { retryWhen, delay, take } from 'rxjs/operators';
6 CommunityForm as CommunityFormI,
9 ListCategoriesResponse,
12 WebSocketJsonResponse,
13 } from '../interfaces';
14 import { WebSocketService } from '../services';
17 capitalizeFirstLetter,
22 import Tribute from 'tributejs/src/Tribute.js';
23 import autosize from 'autosize';
24 import { i18n } from '../i18next';
26 import { Community } from '../interfaces';
28 interface CommunityFormProps {
29 community?: Community; // If a community is given, that means this is an edit
31 onCreate?(community: Community): any;
32 onEdit?(community: Community): any;
35 interface CommunityFormState {
36 communityForm: CommunityFormI;
37 categories: Array<Category>;
42 export class CommunityForm extends Component<
46 private id = `community-form-${randomStr()}`;
47 private tribute: Tribute;
48 private subscription: Subscription;
50 private emptyState: CommunityFormState = {
62 constructor(props: any, context: any) {
63 super(props, context);
65 this.tribute = setupTribute();
66 this.state = this.emptyState;
68 if (this.props.community) {
69 this.state.communityForm = {
70 name: this.props.community.name,
71 title: this.props.community.title,
72 category_id: this.props.community.category_id,
73 description: this.props.community.description,
74 edit_id: this.props.community.id,
75 nsfw: this.props.community.nsfw,
80 this.subscription = WebSocketService.Instance.subject
81 .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
83 msg => this.parseMessage(msg),
84 err => console.error(err),
85 () => console.log('complete')
88 WebSocketService.Instance.listCategories();
89 WebSocketService.Instance.getSite();
93 var textarea: any = document.getElementById(this.id);
95 this.tribute.attach(textarea);
96 textarea.addEventListener('tribute-replaced', () => {
97 this.state.communityForm.description = textarea.value;
98 this.setState(this.state);
99 autosize.update(textarea);
103 componentWillUnmount() {
104 this.subscription.unsubscribe();
112 !this.state.loading &&
113 (this.state.communityForm.name ||
114 this.state.communityForm.title ||
115 this.state.communityForm.description)
117 message={i18n.t('block_leaving')}
119 <form onSubmit={linkEvent(this, this.handleCreateCommunitySubmit)}>
120 <div class="form-group row">
121 <label class="col-12 col-form-label" htmlFor="community-name">
129 value={this.state.communityForm.name}
130 onInput={linkEvent(this, this.handleCommunityNameChange)}
135 title={i18n.t('community_reqs')}
140 <div class="form-group row">
141 <label class="col-12 col-form-label" htmlFor="community-title">
148 value={this.state.communityForm.title}
149 onInput={linkEvent(this, this.handleCommunityTitleChange)}
157 <div class="form-group row">
158 <label class="col-12 col-form-label" htmlFor={this.id}>
164 value={this.state.communityForm.description}
165 onInput={linkEvent(this, this.handleCommunityDescriptionChange)}
172 <div class="form-group row">
173 <label class="col-12 col-form-label" htmlFor="community-category">
179 id="community-category"
180 value={this.state.communityForm.category_id}
181 onInput={linkEvent(this, this.handleCommunityCategoryChange)}
183 {this.state.categories.map(category => (
184 <option value={category.id}>{category.name}</option>
190 {this.state.enable_nsfw && (
191 <div class="form-group row">
193 <div class="form-check">
195 class="form-check-input"
198 checked={this.state.communityForm.nsfw}
199 onChange={linkEvent(this, this.handleCommunityNsfwChange)}
201 <label class="form-check-label" htmlFor="community-nsfw">
208 <div class="form-group row">
210 <button type="submit" class="btn btn-secondary mr-2">
211 {this.state.loading ? (
212 <svg class="icon icon-spinner spin">
213 <use xlinkHref="#icon-spinner"></use>
215 ) : this.props.community ? (
216 capitalizeFirstLetter(i18n.t('save'))
218 capitalizeFirstLetter(i18n.t('create'))
221 {this.props.community && (
224 class="btn btn-secondary"
225 onClick={linkEvent(this, this.handleCancel)}
237 handleCreateCommunitySubmit(i: CommunityForm, event: any) {
238 event.preventDefault();
239 i.state.loading = true;
240 if (i.props.community) {
241 WebSocketService.Instance.editCommunity(i.state.communityForm);
243 WebSocketService.Instance.createCommunity(i.state.communityForm);
248 handleCommunityNameChange(i: CommunityForm, event: any) {
249 i.state.communityForm.name = event.target.value;
253 handleCommunityTitleChange(i: CommunityForm, event: any) {
254 i.state.communityForm.title = event.target.value;
258 handleCommunityDescriptionChange(i: CommunityForm, event: any) {
259 i.state.communityForm.description = event.target.value;
263 handleCommunityCategoryChange(i: CommunityForm, event: any) {
264 i.state.communityForm.category_id = Number(event.target.value);
268 handleCommunityNsfwChange(i: CommunityForm, event: any) {
269 i.state.communityForm.nsfw = event.target.checked;
273 handleCancel(i: CommunityForm) {
277 parseMessage(msg: WebSocketJsonResponse) {
278 let res = wsJsonToRes(msg);
281 toast(i18n.t(msg.error), 'danger');
282 this.state.loading = false;
283 this.setState(this.state);
285 } else if (res.op == UserOperation.ListCategories) {
286 let data = res.data as ListCategoriesResponse;
287 this.state.categories = data.categories;
288 if (!this.props.community) {
289 this.state.communityForm.category_id = data.categories[0].id;
291 this.setState(this.state);
292 } else if (res.op == UserOperation.CreateCommunity) {
293 let data = res.data as CommunityResponse;
294 this.state.loading = false;
295 this.props.onCreate(data.community);
297 // TODO is this necessary
298 else if (res.op == UserOperation.EditCommunity) {
299 let data = res.data as CommunityResponse;
300 this.state.loading = false;
301 this.props.onEdit(data.community);
302 } else if (res.op == UserOperation.GetSite) {
303 let data = res.data as GetSiteResponse;
304 this.state.enable_nsfw = data.site.enable_nsfw;
305 this.setState(this.state);