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">
212 class="btn btn-secondary mr-2"
213 disabled={this.state.loading}
215 {this.state.loading ? (
216 <svg class="icon icon-spinner spin">
217 <use xlinkHref="#icon-spinner"></use>
219 ) : this.props.community ? (
220 capitalizeFirstLetter(i18n.t('save'))
222 capitalizeFirstLetter(i18n.t('create'))
225 {this.props.community && (
228 class="btn btn-secondary"
229 onClick={linkEvent(this, this.handleCancel)}
241 handleCreateCommunitySubmit(i: CommunityForm, event: any) {
242 event.preventDefault();
243 i.state.loading = true;
244 if (i.props.community) {
245 WebSocketService.Instance.editCommunity(i.state.communityForm);
247 WebSocketService.Instance.createCommunity(i.state.communityForm);
252 handleCommunityNameChange(i: CommunityForm, event: any) {
253 i.state.communityForm.name = event.target.value;
257 handleCommunityTitleChange(i: CommunityForm, event: any) {
258 i.state.communityForm.title = event.target.value;
262 handleCommunityDescriptionChange(i: CommunityForm, event: any) {
263 i.state.communityForm.description = event.target.value;
267 handleCommunityCategoryChange(i: CommunityForm, event: any) {
268 i.state.communityForm.category_id = Number(event.target.value);
272 handleCommunityNsfwChange(i: CommunityForm, event: any) {
273 i.state.communityForm.nsfw = event.target.checked;
277 handleCancel(i: CommunityForm) {
281 parseMessage(msg: WebSocketJsonResponse) {
282 let res = wsJsonToRes(msg);
285 toast(i18n.t(msg.error), 'danger');
286 this.state.loading = false;
287 this.setState(this.state);
289 } else if (res.op == UserOperation.ListCategories) {
290 let data = res.data as ListCategoriesResponse;
291 this.state.categories = data.categories;
292 if (!this.props.community) {
293 this.state.communityForm.category_id = data.categories[0].id;
295 this.setState(this.state);
296 } else if (res.op == UserOperation.CreateCommunity) {
297 let data = res.data as CommunityResponse;
298 this.state.loading = false;
299 this.props.onCreate(data.community);
301 // TODO is this necessary
302 else if (res.op == UserOperation.EditCommunity) {
303 let data = res.data as CommunityResponse;
304 this.state.loading = false;
305 this.props.onEdit(data.community);
306 } else if (res.op == UserOperation.GetSite) {
307 let data = res.data as GetSiteResponse;
308 this.state.enable_nsfw = data.site.enable_nsfw;
309 this.setState(this.state);