|
|
@@ -1,241 +0,0 @@
|
|
|
-import React from 'react';
|
|
|
-import PropTypes from 'prop-types';
|
|
|
-
|
|
|
-import {
|
|
|
- Button,
|
|
|
-} from 'reactstrap';
|
|
|
-
|
|
|
-import { withTranslation } from 'react-i18next';
|
|
|
-
|
|
|
-import AppContainer from '~/client/services/AppContainer';
|
|
|
-import CommentContainer from '~/client/services/CommentContainer';
|
|
|
-import PageContainer from '~/client/services/PageContainer';
|
|
|
-
|
|
|
-import { withUnstatedContainers } from './UnstatedUtils';
|
|
|
-
|
|
|
-import CommentEditor from './PageComment/CommentEditor';
|
|
|
-import Comment from './PageComment/Comment';
|
|
|
-import DeleteCommentModal from './PageComment/DeleteCommentModal';
|
|
|
-import ReplayComments from './PageComment/ReplayComments';
|
|
|
-
|
|
|
-
|
|
|
-/**
|
|
|
- * Load data of comments and render the list of <Comment />
|
|
|
- *
|
|
|
- * @author Yuki Takei <yuki@weseek.co.jp>
|
|
|
- *
|
|
|
- * @export
|
|
|
- * @class PageComments
|
|
|
- * @extends {React.Component}
|
|
|
- */
|
|
|
-class PageComments extends React.Component {
|
|
|
-
|
|
|
- constructor(props) {
|
|
|
- super(props);
|
|
|
-
|
|
|
- this.state = {
|
|
|
- // for deleting comment
|
|
|
- commentToDelete: undefined,
|
|
|
- isDeleteConfirmModalShown: false,
|
|
|
- errorMessageForDeleting: undefined,
|
|
|
-
|
|
|
- showEditorIds: new Set(),
|
|
|
- };
|
|
|
-
|
|
|
- this.growiRenderer = this.props.appContainer.getRenderer('comment');
|
|
|
-
|
|
|
- this.init = this.init.bind(this);
|
|
|
- this.confirmToDeleteComment = this.confirmToDeleteComment.bind(this);
|
|
|
- this.deleteComment = this.deleteComment.bind(this);
|
|
|
- this.showDeleteConfirmModal = this.showDeleteConfirmModal.bind(this);
|
|
|
- this.closeDeleteConfirmModal = this.closeDeleteConfirmModal.bind(this);
|
|
|
- this.replyButtonClickedHandler = this.replyButtonClickedHandler.bind(this);
|
|
|
- this.editorCancelHandler = this.editorCancelHandler.bind(this);
|
|
|
- this.editorCommentHandler = this.editorCommentHandler.bind(this);
|
|
|
- this.resetEditor = this.resetEditor.bind(this);
|
|
|
- }
|
|
|
-
|
|
|
- componentWillMount() {
|
|
|
- this.init();
|
|
|
- }
|
|
|
-
|
|
|
- init() {
|
|
|
- if (!this.props.pageContainer.state.pageId) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- this.props.commentContainer.retrieveComments();
|
|
|
- }
|
|
|
-
|
|
|
- confirmToDeleteComment(comment) {
|
|
|
- this.setState({ commentToDelete: comment });
|
|
|
- this.showDeleteConfirmModal();
|
|
|
- }
|
|
|
-
|
|
|
- deleteComment() {
|
|
|
- const comment = this.state.commentToDelete;
|
|
|
-
|
|
|
- this.props.commentContainer.deleteComment(comment)
|
|
|
- .then(() => {
|
|
|
- this.closeDeleteConfirmModal();
|
|
|
- })
|
|
|
- .catch((err) => {
|
|
|
- this.setState({ errorMessageForDeleting: err.message });
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- showDeleteConfirmModal() {
|
|
|
- this.setState({ isDeleteConfirmModalShown: true });
|
|
|
- }
|
|
|
-
|
|
|
- closeDeleteConfirmModal() {
|
|
|
- this.setState({
|
|
|
- commentToDelete: undefined,
|
|
|
- isDeleteConfirmModalShown: false,
|
|
|
- errorMessageForDeleting: undefined,
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- replyButtonClickedHandler(commentId) {
|
|
|
- const ids = this.state.showEditorIds.add(commentId);
|
|
|
- this.setState({ showEditorIds: ids });
|
|
|
- }
|
|
|
-
|
|
|
- editorCancelHandler(commentId) {
|
|
|
- this.resetEditor(commentId);
|
|
|
- }
|
|
|
-
|
|
|
- editorCommentHandler(commentId) {
|
|
|
- this.resetEditor(commentId);
|
|
|
- }
|
|
|
-
|
|
|
- resetEditor(commentId) {
|
|
|
- this.setState((prevState) => {
|
|
|
- prevState.showEditorIds.delete(commentId);
|
|
|
- return {
|
|
|
- showEditorIds: prevState.showEditorIds,
|
|
|
- };
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- // get replies to specific comment object
|
|
|
- getRepliesFor(comment, allReplies) {
|
|
|
- const replyList = [];
|
|
|
- allReplies.forEach((reply) => {
|
|
|
- if (reply.replyTo === comment._id) {
|
|
|
- replyList.push(reply);
|
|
|
- }
|
|
|
- });
|
|
|
- return replyList;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * render Elements of Comment Thread
|
|
|
- *
|
|
|
- * @param {any} comment Comment Model Obj
|
|
|
- * @param {any} replies List of Reply Comment Model Obj
|
|
|
- *
|
|
|
- * @memberOf PageComments
|
|
|
- */
|
|
|
- renderThread(comment, replies) {
|
|
|
- const commentId = comment._id;
|
|
|
- const showEditor = this.state.showEditorIds.has(commentId);
|
|
|
- const isLoggedIn = this.props.appContainer.currentUser != null;
|
|
|
-
|
|
|
- let rootClassNames = 'page-comment-thread';
|
|
|
- if (replies.length === 0) {
|
|
|
- rootClassNames += ' page-comment-thread-no-replies';
|
|
|
- }
|
|
|
-
|
|
|
- return (
|
|
|
- <div key={commentId} className={rootClassNames}>
|
|
|
- <Comment
|
|
|
- comment={comment}
|
|
|
- deleteBtnClicked={this.confirmToDeleteComment}
|
|
|
- growiRenderer={this.growiRenderer}
|
|
|
- />
|
|
|
- {replies.length !== 0 && (
|
|
|
- <ReplayComments
|
|
|
- replyList={replies}
|
|
|
- deleteBtnClicked={this.confirmToDeleteComment}
|
|
|
- growiRenderer={this.growiRenderer}
|
|
|
- />
|
|
|
- )}
|
|
|
- { !showEditor && isLoggedIn && (
|
|
|
- <div className="text-right">
|
|
|
- <Button
|
|
|
- outline
|
|
|
- color="secondary"
|
|
|
- size="sm"
|
|
|
- className="btn-comment-reply"
|
|
|
- onClick={() => { return this.replyButtonClickedHandler(commentId) }}
|
|
|
- >
|
|
|
- <i className="icon-fw icon-action-undo"></i> Reply
|
|
|
- </Button>
|
|
|
- </div>
|
|
|
- )}
|
|
|
- { showEditor && (
|
|
|
- <div className="page-comment-reply-form ml-4 ml-sm-5 mr-3">
|
|
|
- <CommentEditor
|
|
|
- growiRenderer={this.growiRenderer}
|
|
|
- replyTo={commentId}
|
|
|
- onCancelButtonClicked={this.editorCancelHandler}
|
|
|
- onCommentButtonClicked={this.editorCommentHandler}
|
|
|
- />
|
|
|
- </div>
|
|
|
- )}
|
|
|
- </div>
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- render() {
|
|
|
- const topLevelComments = [];
|
|
|
- const allReplies = [];
|
|
|
- const comments = this.props.commentContainer.state.comments
|
|
|
- .slice().reverse(); // create shallow copy and reverse
|
|
|
-
|
|
|
- comments.forEach((comment) => {
|
|
|
- if (comment.replyTo === undefined) {
|
|
|
- // comment is not a reply
|
|
|
- topLevelComments.push(comment);
|
|
|
- }
|
|
|
- else {
|
|
|
- // comment is a reply
|
|
|
- allReplies.push(comment);
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- return (
|
|
|
- <div>
|
|
|
- { topLevelComments.map((topLevelComment) => {
|
|
|
- // get related replies
|
|
|
- const replies = this.getRepliesFor(topLevelComment, allReplies);
|
|
|
-
|
|
|
- return this.renderThread(topLevelComment, replies);
|
|
|
- }) }
|
|
|
-
|
|
|
- <DeleteCommentModal
|
|
|
- isShown={this.state.isDeleteConfirmModalShown}
|
|
|
- comment={this.state.commentToDelete}
|
|
|
- errorMessage={this.state.errorMessageForDeleting}
|
|
|
- cancel={this.closeDeleteConfirmModal}
|
|
|
- confirmedToDelete={this.deleteComment}
|
|
|
- />
|
|
|
- </div>
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Wrapper component for using unstated
|
|
|
- */
|
|
|
-const PageCommentsWrapper = withUnstatedContainers(PageComments, [AppContainer, PageContainer, CommentContainer]);
|
|
|
-
|
|
|
-PageComments.propTypes = {
|
|
|
- appContainer: PropTypes.instanceOf(AppContainer).isRequired,
|
|
|
- pageContainer: PropTypes.instanceOf(PageContainer).isRequired,
|
|
|
- commentContainer: PropTypes.instanceOf(CommentContainer).isRequired,
|
|
|
-};
|
|
|
-
|
|
|
-export default withTranslation()(PageCommentsWrapper);
|