1 import { Component } from 'inferno';
2 import { Link } from 'inferno-router';
3 import { Subscription } from 'rxjs';
4 import { retryWhen, delay, take } from 'rxjs/operators';
6 CommentNode as CommentNodeI,
7 CommentForm as CommentFormI,
11 } from '../interfaces';
12 import { capitalizeFirstLetter, wsJsonToRes } from '../utils';
13 import { WebSocketService, UserService } from '../services';
14 import { i18n } from '../i18next';
15 import { T } from 'inferno-i18next';
16 import { MarkdownTextArea } from './markdown-textarea';
18 interface CommentFormProps {
21 onReplyCancel?(): any;
27 interface CommentFormState {
28 commentForm: CommentFormI;
33 export class CommentForm extends Component<CommentFormProps, CommentFormState> {
34 private subscription: Subscription;
35 private emptyState: CommentFormState = {
39 post_id: this.props.node
40 ? this.props.node.comment.post_id
42 creator_id: UserService.Instance.user
43 ? UserService.Instance.user.id
46 buttonTitle: !this.props.node
47 ? capitalizeFirstLetter(i18n.t('post'))
49 ? capitalizeFirstLetter(i18n.t('save'))
50 : capitalizeFirstLetter(i18n.t('reply')),
54 constructor(props: any, context: any) {
55 super(props, context);
57 this.handleCommentSubmit = this.handleCommentSubmit.bind(this);
58 this.handleReplyCancel = this.handleReplyCancel.bind(this);
60 this.state = this.emptyState;
62 if (this.props.node) {
63 if (this.props.edit) {
64 this.state.commentForm.edit_id = this.props.node.comment.id;
65 this.state.commentForm.parent_id = this.props.node.comment.parent_id;
66 this.state.commentForm.content = this.props.node.comment.content;
67 this.state.commentForm.creator_id = this.props.node.comment.creator_id;
69 // A reply gets a new parent id
70 this.state.commentForm.parent_id = this.props.node.comment.id;
74 this.subscription = WebSocketService.Instance.subject
75 .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
77 msg => this.parseMessage(msg),
78 err => console.error(err),
79 () => console.log('complete')
83 componentWillUnmount() {
84 this.subscription.unsubscribe();
90 {UserService.Instance.user ? (
92 initialContent={this.state.commentForm.content}
93 buttonTitle={this.state.buttonTitle}
94 finished={this.state.finished}
95 replyType={!!this.props.node}
96 focus={this.props.focus}
97 disabled={this.props.disabled}
98 onSubmit={this.handleCommentSubmit}
99 onReplyCancel={this.handleReplyCancel}
102 <div class="alert alert-light" role="alert">
103 <svg class="icon icon-inline mr-2">
104 <use xlinkHref="#icon-alert-triangle"></use>
106 <T i18nKey="must_login" class="d-inline">
108 <Link class="alert-link" to="/login">
118 handleFinished(op: UserOperation, data: CommentResponse) {
120 this.props.node !== undefined && data.comment.parent_id !== null;
122 +!(data.comment.parent_id !== null) ^ +(this.props.node !== undefined);
125 (data.comment.creator_id == UserService.Instance.user.id &&
126 ((op == UserOperation.CreateComment &&
127 // If its a reply, make sure parent child match
129 data.comment.parent_id == this.props.node.comment.id) ||
130 // Otherwise, check the XOR of the two
131 (!isReply && xor))) ||
132 // If its a comment edit, only check that its from your user, and that its a
135 (data.comment.creator_id == UserService.Instance.user.id &&
136 op == UserOperation.EditComment &&
137 data.comment.content)
139 this.state.finished = true;
140 this.setState(this.state);
144 handleCommentSubmit(val: string) {
145 this.state.commentForm.content = val;
146 if (this.props.edit) {
147 WebSocketService.Instance.editComment(this.state.commentForm);
149 WebSocketService.Instance.createComment(this.state.commentForm);
151 this.setState(this.state);
154 handleReplyCancel() {
155 this.props.onReplyCancel();
158 parseMessage(msg: WebSocketJsonResponse) {
159 let res = wsJsonToRes(msg);
161 // Only do the showing and hiding if logged in
162 if (UserService.Instance.user) {
163 if (res.op == UserOperation.CreateComment) {
164 let data = res.data as CommentResponse;
165 this.handleFinished(res.op, data);
166 } else if (res.op == UserOperation.EditComment) {
167 let data = res.data as CommentResponse;
168 this.handleFinished(res.op, data);