lemmy/ui/src/components/comment-form.tsx
Dessalines f81a7ad9ab Adding form_id to comment creates and edits.
- This adds a form_id to CreateComment, EditComment, and CommentResponse
- This is so any front end clients can add a randomly generated string,
  and know which comment they submitted, is the one they're getting
  back.
- This gets rid of all the weird complicated logic in handleFinished(),
  and should stop the comment forms getting cleared once and for all.
2020-07-21 10:56:41 -04:00

151 lines
4.4 KiB
TypeScript
Vendored

import { Component } from 'inferno';
import { Link } from 'inferno-router';
import { Subscription } from 'rxjs';
import { retryWhen, delay, take } from 'rxjs/operators';
import {
CommentNode as CommentNodeI,
CommentForm as CommentFormI,
WebSocketJsonResponse,
UserOperation,
CommentResponse,
} from '../interfaces';
import { capitalizeFirstLetter, wsJsonToRes } from '../utils';
import { WebSocketService, UserService } from '../services';
import { i18n } from '../i18next';
import { T } from 'inferno-i18next';
import { MarkdownTextArea } from './markdown-textarea';
interface CommentFormProps {
postId?: number;
node?: CommentNodeI;
onReplyCancel?(): any;
edit?: boolean;
disabled?: boolean;
focus?: boolean;
}
interface CommentFormState {
commentForm: CommentFormI;
buttonTitle: string;
finished: boolean;
}
export class CommentForm extends Component<CommentFormProps, CommentFormState> {
private subscription: Subscription;
private emptyState: CommentFormState = {
commentForm: {
auth: null,
content: null,
post_id: this.props.node
? this.props.node.comment.post_id
: this.props.postId,
creator_id: UserService.Instance.user
? UserService.Instance.user.id
: null,
},
buttonTitle: !this.props.node
? capitalizeFirstLetter(i18n.t('post'))
: this.props.edit
? capitalizeFirstLetter(i18n.t('save'))
: capitalizeFirstLetter(i18n.t('reply')),
finished: false,
};
constructor(props: any, context: any) {
super(props, context);
this.handleCommentSubmit = this.handleCommentSubmit.bind(this);
this.handleReplyCancel = this.handleReplyCancel.bind(this);
this.state = this.emptyState;
if (this.props.node) {
if (this.props.edit) {
this.state.commentForm.edit_id = this.props.node.comment.id;
this.state.commentForm.parent_id = this.props.node.comment.parent_id;
this.state.commentForm.content = this.props.node.comment.content;
this.state.commentForm.creator_id = this.props.node.comment.creator_id;
} else {
// A reply gets a new parent id
this.state.commentForm.parent_id = this.props.node.comment.id;
}
}
this.subscription = WebSocketService.Instance.subject
.pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
.subscribe(
msg => this.parseMessage(msg),
err => console.error(err),
() => console.log('complete')
);
}
componentWillUnmount() {
this.subscription.unsubscribe();
}
render() {
return (
<div class="mb-3">
{UserService.Instance.user ? (
<MarkdownTextArea
initialContent={this.state.commentForm.content}
buttonTitle={this.state.buttonTitle}
finished={this.state.finished}
replyType={!!this.props.node}
focus={this.props.focus}
disabled={this.props.disabled}
onSubmit={this.handleCommentSubmit}
onReplyCancel={this.handleReplyCancel}
/>
) : (
<div class="alert alert-light" role="alert">
<svg class="icon icon-inline mr-2">
<use xlinkHref="#icon-alert-triangle"></use>
</svg>
<T i18nKey="must_login" class="d-inline">
#
<Link class="alert-link" to="/login">
#
</Link>
</T>
</div>
)}
</div>
);
}
handleCommentSubmit(msg: { val: string; formId: string }) {
this.state.commentForm.content = msg.val;
this.state.commentForm.form_id = msg.formId;
if (this.props.edit) {
WebSocketService.Instance.editComment(this.state.commentForm);
} else {
WebSocketService.Instance.createComment(this.state.commentForm);
}
this.setState(this.state);
}
handleReplyCancel() {
this.props.onReplyCancel();
}
parseMessage(msg: WebSocketJsonResponse) {
let res = wsJsonToRes(msg);
// Only do the showing and hiding if logged in
if (UserService.Instance.user) {
if (
res.op == UserOperation.CreateComment ||
res.op == UserOperation.EditComment
) {
let data = res.data as CommentResponse;
// This only finishes this form, if the randomly generated form_id matches the one received
if (this.state.commentForm.form_id == data.form_id) {
this.setState({ finished: true });
}
}
}
}
}