Sfoglia il codice sorgente

Merge pull request #1645 from weseek/fix/Intermediate-comments-cannot-be-viewed

Fix/Refactor comment.jsx
Yuki Takei 6 anni fa
parent
commit
2da2d4a8ca

+ 59 - 73
src/client/js/components/PageComment/Comment.jsx

@@ -16,6 +16,7 @@ import RevisionBody from '../Page/RevisionBody';
 import UserPicture from '../User/UserPicture';
 import UserPicture from '../User/UserPicture';
 import Username from '../User/Username';
 import Username from '../User/Username';
 import CommentEditor from './CommentEditor';
 import CommentEditor from './CommentEditor';
+import CommentControl from './CommentControl';
 
 
 /**
 /**
  *
  *
@@ -25,7 +26,7 @@ import CommentEditor from './CommentEditor';
  * @class Comment
  * @class Comment
  * @extends {React.Component}
  * @extends {React.Component}
  */
  */
-class Comment extends React.Component {
+class Comment extends React.PureComponent {
 
 
   constructor(props) {
   constructor(props) {
     super(props);
     super(props);
@@ -33,7 +34,7 @@ class Comment extends React.Component {
     this.state = {
     this.state = {
       html: '',
       html: '',
       isOlderRepliesShown: false,
       isOlderRepliesShown: false,
-      showReEditorIds: new Set(),
+      isReEdit: false,
     };
     };
 
 
     this.growiRenderer = this.props.appContainer.getRenderer('comment');
     this.growiRenderer = this.props.appContainer.getRenderer('comment');
@@ -42,23 +43,39 @@ class Comment extends React.Component {
     this.isCurrentRevision = this.isCurrentRevision.bind(this);
     this.isCurrentRevision = this.isCurrentRevision.bind(this);
     this.getRootClassName = this.getRootClassName.bind(this);
     this.getRootClassName = this.getRootClassName.bind(this);
     this.getRevisionLabelClassName = this.getRevisionLabelClassName.bind(this);
     this.getRevisionLabelClassName = this.getRevisionLabelClassName.bind(this);
+    this.editBtnClickedHandler = this.editBtnClickedHandler.bind(this);
     this.deleteBtnClickedHandler = this.deleteBtnClickedHandler.bind(this);
     this.deleteBtnClickedHandler = this.deleteBtnClickedHandler.bind(this);
     this.renderText = this.renderText.bind(this);
     this.renderText = this.renderText.bind(this);
     this.renderHtml = this.renderHtml.bind(this);
     this.renderHtml = this.renderHtml.bind(this);
     this.commentButtonClickedHandler = this.commentButtonClickedHandler.bind(this);
     this.commentButtonClickedHandler = this.commentButtonClickedHandler.bind(this);
   }
   }
 
 
-  componentWillMount() {
-    this.renderHtml(this.props.comment.comment);
+
+  initCurrentRenderingContext() {
+    this.currentRenderingContext = {
+      markdown: this.props.comment.comment,
+    };
   }
   }
 
 
-  componentWillReceiveProps(nextProps) {
-    this.renderHtml(nextProps.comment.comment);
+  componentDidMount() {
+    this.initCurrentRenderingContext();
+    this.renderHtml();
   }
   }
 
 
-  // not used
-  setMarkdown(markdown) {
-    this.renderHtml(markdown);
+  componentDidUpdate(prevProps) {
+    const { comment: prevComment } = prevProps;
+    const { comment } = this.props;
+
+    // render only when props.markdown is updated
+    if (comment !== prevComment) {
+      this.initCurrentRenderingContext();
+      this.renderHtml();
+      return;
+    }
+
+    const { interceptorManager } = this.props.appContainer;
+
+    interceptorManager.process('postRenderCommentHtml', this.currentRenderingContext);
   }
   }
 
 
   checkPermissionToControlComment() {
   checkPermissionToControlComment() {
@@ -99,18 +116,12 @@ class Comment extends React.Component {
       this.isCurrentRevision() ? 'label-primary' : 'label-default'}`;
       this.isCurrentRevision() ? 'label-primary' : 'label-default'}`;
   }
   }
 
 
-  editBtnClickedHandler(commentId) {
-    const ids = this.state.showReEditorIds.add(commentId);
-    this.setState({ showReEditorIds: ids });
+  editBtnClickedHandler() {
+    this.setState({ isReEdit: !this.state.isReEdit });
   }
   }
 
 
-  commentButtonClickedHandler(commentId) {
-    this.setState((prevState) => {
-      prevState.showReEditorIds.delete(commentId);
-      return {
-        showReEditorIds: prevState.showReEditorIds,
-      };
-    });
+  commentButtonClickedHandler() {
+    this.editBtnClickedHandler();
   }
   }
 
 
   deleteBtnClickedHandler() {
   deleteBtnClickedHandler() {
@@ -142,35 +153,23 @@ class Comment extends React.Component {
     });
     });
   }
   }
 
 
-  renderHtml(markdown) {
-    const context = {
-      markdown,
-    };
-
-    const growiRenderer = this.props.growiRenderer;
-    const interceptorManager = this.props.appContainer.interceptorManager;
-    interceptorManager.process('preRenderComment', context)
-      .then(() => { return interceptorManager.process('prePreProcess', context) })
-      .then(() => {
-        context.markdown = growiRenderer.preProcess(context.markdown);
-      })
-      .then(() => { return interceptorManager.process('postPreProcess', context) })
-      .then(() => {
-        const parsedHTML = growiRenderer.process(context.markdown);
-        context.parsedHTML = parsedHTML;
-      })
-      .then(() => { return interceptorManager.process('prePostProcess', context) })
-      .then(() => {
-        context.parsedHTML = growiRenderer.postProcess(context.parsedHTML);
-      })
-      .then(() => { return interceptorManager.process('postPostProcess', context) })
-      .then(() => { return interceptorManager.process('preRenderCommentHtml', context) })
-      .then(() => {
-        this.setState({ html: context.parsedHTML });
-      })
-      // process interceptors for post rendering
-      .then(() => { return interceptorManager.process('postRenderCommentHtml', context) });
-
+  async renderHtml() {
+
+    const { growiRenderer, appContainer } = this.props;
+    const { interceptorManager } = appContainer;
+    const context = this.currentRenderingContext;
+
+    await interceptorManager.process('preRenderComment', context);
+    await interceptorManager.process('prePreProcess', context);
+    context.markdown = await growiRenderer.preProcess(context.markdown);
+    await interceptorManager.process('postPreProcess', context);
+    context.parsedHTML = await growiRenderer.process(context.markdown);
+    await interceptorManager.process('prePostProcess', context);
+    context.parsedHTML = await growiRenderer.postProcess(context.parsedHTML);
+    await interceptorManager.process('postPostProcess', context);
+    await interceptorManager.process('preRenderCommentHtml', context);
+    this.setState({ html: context.parsedHTML });
+    await interceptorManager.process('postRenderCommentHtml', context);
   }
   }
 
 
   renderReply(reply) {
   renderReply(reply) {
@@ -223,32 +222,20 @@ class Comment extends React.Component {
 
 
     return (
     return (
       <React.Fragment>
       <React.Fragment>
-        { areThereHiddenReplies && (
+        {areThereHiddenReplies && (
           <div className="page-comments-hidden-replies">
           <div className="page-comments-hidden-replies">
             <Collapse in={this.state.isOlderRepliesShown}>
             <Collapse in={this.state.isOlderRepliesShown}>
               <div>{hiddenElements}</div>
               <div>{hiddenElements}</div>
             </Collapse>
             </Collapse>
             <div className="text-center">{toggleButton}</div>
             <div className="text-center">{toggleButton}</div>
           </div>
           </div>
-        ) }
+        )}
 
 
         {shownElements}
         {shownElements}
       </React.Fragment>
       </React.Fragment>
     );
     );
   }
   }
 
 
-  renderCommentControl(comment) {
-    return (
-      <div className="page-comment-control">
-        <button type="button" className="btn btn-link p-2" onClick={() => { this.editBtnClickedHandler(comment._id) }}>
-          <i className="ti-pencil"></i>
-        </button>
-        <button type="button" className="btn btn-link p-2 mr-2" onClick={this.deleteBtnClickedHandler}>
-          <i className="ti-close"></i>
-        </button>
-      </div>
-    );
-  }
 
 
   render() {
   render() {
     const comment = this.props.comment;
     const comment = this.props.comment;
@@ -259,8 +246,6 @@ class Comment extends React.Component {
     const updatedAt = new Date(comment.updatedAt);
     const updatedAt = new Date(comment.updatedAt);
     const isEdited = createdAt < updatedAt;
     const isEdited = createdAt < updatedAt;
 
 
-    const showReEditor = this.state.showReEditorIds.has(commentId);
-
     const rootClassName = this.getRootClassName(comment);
     const rootClassName = this.getRootClassName(comment);
     const commentDate = formatDistanceStrict(createdAt, new Date());
     const commentDate = formatDistanceStrict(createdAt, new Date());
     const commentBody = isMarkdown ? this.renderRevisionBody() : this.renderText(comment.comment);
     const commentBody = isMarkdown ? this.renderRevisionBody() : this.renderText(comment.comment);
@@ -284,7 +269,7 @@ class Comment extends React.Component {
     return (
     return (
       <React.Fragment>
       <React.Fragment>
 
 
-        {showReEditor ? (
+        {this.state.isReEdit ? (
           <CommentEditor
           <CommentEditor
             growiRenderer={this.growiRenderer}
             growiRenderer={this.growiRenderer}
             currentCommentId={commentId}
             currentCommentId={commentId}
@@ -305,18 +290,19 @@ class Comment extends React.Component {
                 <OverlayTrigger overlay={commentDateTooltip} placement="bottom">
                 <OverlayTrigger overlay={commentDateTooltip} placement="bottom">
                   <span><a href={`#${commentId}`}>{commentDate}</a></span>
                   <span><a href={`#${commentId}`}>{commentDate}</a></span>
                 </OverlayTrigger>
                 </OverlayTrigger>
-                { isEdited && (
-                  <OverlayTrigger overlay={editedDateTooltip} placement="bottom">
-                    <span>&nbsp;(edited)</span>
-                  </OverlayTrigger>
-                ) }
+                {isEdited && (
+                <OverlayTrigger overlay={editedDateTooltip} placement="bottom">
+                  <span>&nbsp;(edited)</span>
+                </OverlayTrigger>
+                  )}
                 <span className="ml-2"><a className={revisionLavelClassName} href={revHref}>{revFirst8Letters}</a></span>
                 <span className="ml-2"><a className={revisionLavelClassName} href={revHref}>{revFirst8Letters}</a></span>
               </div>
               </div>
-              { this.checkPermissionToControlComment() && this.renderCommentControl(comment) }
+              {this.checkPermissionToControlComment()
+                  && <CommentControl onClickDeleteBtn={this.deleteBtnClickedHandler} onClickEditBtn={this.editBtnClickedHandler} />}
             </div>
             </div>
           </div>
           </div>
-        )
-      }
+          )
+        }
         {this.renderReplies()}
         {this.renderReplies()}
 
 
       </React.Fragment>
       </React.Fragment>

+ 24 - 0
src/client/js/components/PageComment/CommentControl.jsx

@@ -0,0 +1,24 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+
+const CommentControl = (props) => {
+  return (
+    <div className="page-comment-control">
+      <button type="button" className="btn btn-link p-2" onClick={props.onClickEditBtn}>
+        <i className="ti-pencil"></i>
+      </button>
+      <button type="button" className="btn btn-link p-2 mr-2" onClick={props.onClickDeleteBtn}>
+        <i className="ti-close"></i>
+      </button>
+    </div>
+  );
+};
+
+CommentControl.propTypes = {
+
+  onClickEditBtn: PropTypes.func.isRequired,
+  onClickDeleteBtn: PropTypes.func.isRequired,
+};
+
+export default CommentControl;