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';
27 import { Icon, Spinner } from './icon';
29 interface CommunityFormProps {
30 community_view?: CommunityView; // If a community is given, that means this is an edit
31 categories: Category[];
33 onCreate?(community: CommunityView): any;
34 onEdit?(community: CommunityView): any;
38 interface CommunityFormState {
39 communityForm: CreateCommunity;
43 export class CommunityForm extends Component<
47 private id = `community-form-${randomStr()}`;
48 private subscription: Subscription;
50 private emptyState: CommunityFormState = {
54 category_id: this.props.categories[0].id,
58 auth: authField(false),
63 constructor(props: any, context: any) {
64 super(props, context);
66 this.state = this.emptyState;
68 this.handleCommunityDescriptionChange = this.handleCommunityDescriptionChange.bind(
72 this.handleIconUpload = this.handleIconUpload.bind(this);
73 this.handleIconRemove = this.handleIconRemove.bind(this);
75 this.handleBannerUpload = this.handleBannerUpload.bind(this);
76 this.handleBannerRemove = this.handleBannerRemove.bind(this);
78 let cv = this.props.community_view;
80 this.state.communityForm = {
81 name: cv.community.name,
82 title: cv.community.title,
83 category_id: cv.category.id,
84 description: cv.community.description,
85 nsfw: cv.community.nsfw,
86 icon: cv.community.icon,
87 banner: cv.community.banner,
92 this.parseMessage = this.parseMessage.bind(this);
93 this.subscription = wsSubscribe(this.parseMessage);
96 // TODO this should be checked out
97 componentDidUpdate() {
99 !this.state.loading &&
100 (this.state.communityForm.name ||
101 this.state.communityForm.title ||
102 this.state.communityForm.description)
104 window.onbeforeunload = () => true;
106 window.onbeforeunload = undefined;
110 componentWillUnmount() {
111 this.subscription.unsubscribe();
112 window.onbeforeunload = null;
120 !this.state.loading &&
121 (this.state.communityForm.name ||
122 this.state.communityForm.title ||
123 this.state.communityForm.description)
125 message={i18n.t('block_leaving')}
127 <form onSubmit={linkEvent(this, this.handleCreateCommunitySubmit)}>
128 {!this.props.community_view && (
129 <div class="form-group row">
130 <label class="col-12 col-form-label" htmlFor="community-name">
133 class="pointer unselectable ml-2 text-muted"
134 data-tippy-content={i18n.t('name_explain')}
136 <Icon icon="help-circle" classes="icon-inline" />
144 value={this.state.communityForm.name}
145 onInput={linkEvent(this, this.handleCommunityNameChange)}
150 title={i18n.t('community_reqs')}
155 <div class="form-group row">
156 <label class="col-12 col-form-label" htmlFor="community-title">
157 {i18n.t('display_name')}
159 class="pointer unselectable ml-2 text-muted"
160 data-tippy-content={i18n.t('display_name_explain')}
162 <Icon icon="help-circle" classes="icon-inline" />
169 value={this.state.communityForm.title}
170 onInput={linkEvent(this, this.handleCommunityTitleChange)}
178 <div class="form-group">
179 <label>{i18n.t('icon')}</label>
181 uploadTitle={i18n.t('upload_icon')}
182 imageSrc={this.state.communityForm.icon}
183 onUpload={this.handleIconUpload}
184 onRemove={this.handleIconRemove}
188 <div class="form-group">
189 <label>{i18n.t('banner')}</label>
191 uploadTitle={i18n.t('upload_banner')}
192 imageSrc={this.state.communityForm.banner}
193 onUpload={this.handleBannerUpload}
194 onRemove={this.handleBannerRemove}
197 <div class="form-group row">
198 <label class="col-12 col-form-label" htmlFor={this.id}>
203 initialContent={this.state.communityForm.description}
204 onContentChange={this.handleCommunityDescriptionChange}
208 <div class="form-group row">
209 <label class="col-12 col-form-label" htmlFor="community-category">
215 id="community-category"
216 value={this.state.communityForm.category_id}
217 onInput={linkEvent(this, this.handleCommunityCategoryChange)}
219 {this.props.categories.map(category => (
220 <option value={category.id}>{category.name}</option>
226 {this.props.enableNsfw && (
227 <div class="form-group row">
229 <div class="form-check">
231 class="form-check-input"
234 checked={this.state.communityForm.nsfw}
235 onChange={linkEvent(this, this.handleCommunityNsfwChange)}
237 <label class="form-check-label" htmlFor="community-nsfw">
244 <div class="form-group row">
248 class="btn btn-secondary mr-2"
249 disabled={this.state.loading}
251 {this.state.loading ? (
253 ) : this.props.community_view ? (
254 capitalizeFirstLetter(i18n.t('save'))
256 capitalizeFirstLetter(i18n.t('create'))
259 {this.props.community_view && (
262 class="btn btn-secondary"
263 onClick={linkEvent(this, this.handleCancel)}
275 handleCreateCommunitySubmit(i: CommunityForm, event: any) {
276 event.preventDefault();
277 i.state.loading = true;
278 if (i.props.community_view) {
279 let form: EditCommunity = {
280 ...i.state.communityForm,
281 community_id: i.props.community_view.community.id,
283 WebSocketService.Instance.send(wsClient.editCommunity(form));
285 WebSocketService.Instance.send(
286 wsClient.createCommunity(i.state.communityForm)
292 handleCommunityNameChange(i: CommunityForm, event: any) {
293 i.state.communityForm.name = event.target.value;
297 handleCommunityTitleChange(i: CommunityForm, event: any) {
298 i.state.communityForm.title = event.target.value;
302 handleCommunityDescriptionChange(val: string) {
303 this.state.communityForm.description = val;
304 this.setState(this.state);
307 handleCommunityCategoryChange(i: CommunityForm, event: any) {
308 i.state.communityForm.category_id = Number(event.target.value);
312 handleCommunityNsfwChange(i: CommunityForm, event: any) {
313 i.state.communityForm.nsfw = event.target.checked;
317 handleCancel(i: CommunityForm) {
321 handleIconUpload(url: string) {
322 this.state.communityForm.icon = url;
323 this.setState(this.state);
327 this.state.communityForm.icon = '';
328 this.setState(this.state);
331 handleBannerUpload(url: string) {
332 this.state.communityForm.banner = url;
333 this.setState(this.state);
336 handleBannerRemove() {
337 this.state.communityForm.banner = '';
338 this.setState(this.state);
341 parseMessage(msg: any) {
342 let op = wsUserOp(msg);
344 toast(i18n.t(msg.error), 'danger');
345 this.state.loading = false;
346 this.setState(this.state);
348 } else if (op == UserOperation.CreateCommunity) {
349 let data = wsJsonToRes<CommunityResponse>(msg).data;
350 this.state.loading = false;
351 this.props.onCreate(data.community_view);
352 } else if (op == UserOperation.EditCommunity) {
353 let data = wsJsonToRes<CommunityResponse>(msg).data;
354 this.state.loading = false;
355 this.props.onEdit(data.community_view);