Yuki Takei 6 лет назад
Родитель
Сommit
1b09ae46e8

+ 25 - 29
src/client/js/components/PageComment/Comment.jsx

@@ -155,6 +155,18 @@ class Comment extends React.Component {
 
   }
 
+  renderReply(reply) {
+    return (
+      <div key={reply._id} className="page-comment-reply">
+        <CommentWrapper
+          comment={reply}
+          deleteBtnClicked={this.props.deleteBtnClicked}
+          growiRenderer={this.props.growiRenderer}
+        />
+      </div>
+    );
+  }
+
   renderReplies() {
     const isLayoutTypeGrowi = this.state.isLayoutTypeGrowi;
     let replyList = this.props.replyList;
@@ -177,16 +189,7 @@ class Comment extends React.Component {
     const hiddenReplies = replyList.slice(0, replyList.length - 2);
 
     const toggleElements = hiddenReplies.map((reply) => {
-      return (
-        <div key={reply._id} className="col-xs-offset-1 col-xs-11 col-sm-offset-1 col-sm-11 col-md-offset-1 col-md-11 col-lg-offset-1 col-lg-11">
-          <CommentWrapper
-            comment={reply}
-            deleteBtnClicked={this.props.deleteBtnClicked}
-            growiRenderer={this.props.growiRenderer}
-            replyList={[]}
-          />
-        </div>
-      );
+      return this.renderReply(reply);
     });
 
     const toggleBlock = (
@@ -196,24 +199,15 @@ class Comment extends React.Component {
     );
 
     const shownBlock = shownReplies.map((reply) => {
-      return (
-        <div key={reply._id} className="col-xs-offset-1 col-xs-11 col-sm-offset-1 col-sm-11 col-md-offset-1 col-md-11 col-lg-offset-1 col-lg-11">
-          <CommentWrapper
-            comment={reply}
-            deleteBtnClicked={this.props.deleteBtnClicked}
-            growiRenderer={this.props.growiRenderer}
-            replyList={[]}
-          />
-        </div>
-      );
+      return this.renderReply(reply);
     });
 
     return (
-      <div>
+      <React.Fragment>
         {toggleBlock}
         {toggleOlder}
         {shownBlock}
-      </div>
+      </React.Fragment>
     );
   }
 
@@ -236,7 +230,8 @@ class Comment extends React.Component {
     );
 
     return (
-      <div>
+      <React.Fragment>
+
         <div className={rootClassName}>
           <UserPicture user={creator} />
           <div className="page-comment-main">
@@ -257,12 +252,10 @@ class Comment extends React.Component {
             </div>
           </div>
         </div>
-        <div className="container-fluid">
-          <div className="row">
-            {this.renderReplies()}
-          </div>
-        </div>
-      </div>
+
+        {this.renderReplies()}
+
+      </React.Fragment>
     );
   }
 
@@ -284,5 +277,8 @@ Comment.propTypes = {
   deleteBtnClicked: PropTypes.func.isRequired,
   replyList: PropTypes.array,
 };
+Comment.defaultProps = {
+  replyList: [],
+};
 
 export default CommentWrapper;

+ 46 - 73
src/client/js/components/PageComments.jsx

@@ -110,10 +110,10 @@ class PageComments extends React.Component {
     });
   }
 
-  // adds replies to specific comment object
-  addRepliesToComments(comment, replies) {
+  // get replies to specific comment object
+  getRepliesFor(comment, allReplies) {
     const replyList = [];
-    replies.forEach((reply) => {
+    allReplies.forEach((reply) => {
       if (reply.replyTo === comment._id) {
         replyList.push(reply);
       }
@@ -122,68 +122,49 @@ class PageComments extends React.Component {
   }
 
   /**
-   * generate Elements of Comment
+   * render Elements of Comment Thread
    *
-   * @param {any} comments Array of Comment Model Obj
+   * @param {any} comment Comment Model Obj
+   * @param {any} replies List of Reply Comment Model Obj
    *
    * @memberOf PageComments
    */
-  generateCommentElements(comments, replies) {
-    return comments.map((comment) => {
+  renderThread(comment, replies) {
+    const commentId = comment._id;
+    const showEditor = this.state.showEditorIds.has(commentId);
+    const username = this.props.appContainer.me;
 
-      const commentId = comment._id;
-      const showEditor = this.state.showEditorIds.has(commentId);
-      const username = this.props.appContainer.me;
-
-      const replyList = this.addRepliesToComments(comment, replies);
-
-      return (
-        <div key={commentId}>
-          <Comment
-            comment={comment}
-            deleteBtnClicked={this.confirmToDeleteComment}
+    return (
+      <div key={commentId} className="mb-5">
+        <Comment
+          comment={comment}
+          deleteBtnClicked={this.confirmToDeleteComment}
+          growiRenderer={this.growiRenderer}
+          replyList={replies}
+        />
+        { !showEditor && username && (
+          <Button
+            bsStyle="default"
+            className="btn btn-outline btn-default btn-sm"
+            onClick={() => { return this.replyButtonClickedHandler(commentId) }}
+          >
+            <i className="icon-fw icon-action-redo"></i> Reply
+          </Button>
+        )}
+        { showEditor && (
+          <CommentEditor
             growiRenderer={this.growiRenderer}
-            replyList={replyList}
+            replyTo={commentId}
+            commentButtonClickedHandler={this.commentButtonClickedHandler}
           />
-          <div className="container-fluid">
-            <div className="row">
-              <div className="col-xs-offset-1 col-xs-11 col-sm-offset-1 col-sm-11 col-md-offset-1 col-md-11 col-lg-offset-1 col-lg-11">
-                { !showEditor && (
-                  <div>
-                    { username
-                    && (
-                      <div className="col-xs-offset-6 col-sm-offset-6 col-md-offset-6 col-lg-offset-6">
-                        <Button
-                          bsStyle="primary"
-                          className="fcbtn btn btn-outline btn-rounded btn-xxs"
-                          onClick={() => { return this.replyButtonClickedHandler(commentId) }}
-                        >
-                          Reply <i className="fa fa-mail-reply"></i>
-                        </Button>
-                      </div>
-                    )
-                  }
-                  </div>
-                )}
-                { showEditor && (
-                  <CommentEditor
-                    growiRenderer={this.growiRenderer}
-                    replyTo={commentId}
-                    commentButtonClickedHandler={this.commentButtonClickedHandler}
-                  />
-                )}
-              </div>
-            </div>
-          </div>
-          <br />
-        </div>
-      );
-    });
+        )}
+      </div>
+    );
   }
 
   render() {
-    const currentComments = [];
-    const currentReplies = [];
+    const topLevelComments = [];
+    const allReplies = [];
 
     let comments = this.props.commentContainer.state.comments;
     if (this.state.isLayoutTypeGrowi) {
@@ -193,31 +174,23 @@ class PageComments extends React.Component {
 
     comments.forEach((comment) => {
       if (comment.replyTo === undefined) {
-      // comment is not a reply
-        currentComments.push(comment);
+        // comment is not a reply
+        topLevelComments.push(comment);
       }
       else {
-      // comment is a reply
-        currentReplies.push(comment);
+        // comment is a reply
+        allReplies.push(comment);
       }
     });
 
-    // generate elements
-    const currentElements = this.generateCommentElements(currentComments, currentReplies);
-
-    // generate blocks
-    const currentBlock = (
-      <div className="page-comments-list-current" id="page-comments-list-current">
-        {currentElements}
-      </div>
-    );
-
-    // layout blocks
-    const commentsElements = (<div>{currentBlock}</div>);
-
     return (
       <div>
-        {commentsElements}
+        { topLevelComments.map((topLevelComment) => {
+          // get related replies
+          const replies = this.getRepliesFor(topLevelComment, allReplies);
+
+          return this.renderThread(topLevelComment, replies);
+        }) }
 
         <DeleteCommentModal
           isShown={this.state.isDeleteConfirmModalShown}

+ 0 - 10
src/client/styles/scss/_comment.scss

@@ -46,13 +46,3 @@
     }
   }
 }
-
-.btn-xxs {
-  display: inline-flex;
-  align-items: center;
-  justify-content: center;
-  width: 50px;
-  height: 10px;
-  font-size: 11px;
-  border-radius: 1px;
-}

+ 6 - 2
src/client/styles/scss/_comment_growi.scss

@@ -2,8 +2,7 @@
   %comment-section {
     position: relative;
     padding: 1em;
-    margin-bottom: 1em;
-    margin-left: 4.5em;
+    margin: 1em 0 0.2em 4.5em;
     // screen-xs
     @media (max-width: $screen-xs) {
       margin-left: 3.5em;
@@ -85,6 +84,11 @@
     }
   }
 
+  .page-comment-reply {
+    margin-right: 15px;
+    margin-left: 6em;
+  }
+
   // show when hover
   .page-comment-main:hover > .page-comment-control {
     display: block;

+ 1 - 2
src/client/styles/scss/_comment_kibela.scss

@@ -3,8 +3,7 @@
   %comment-section {
     position: relative;
     padding: 1em;
-    margin-bottom: 1em; // screen-xs
-    margin-left: 4.5em;
+    margin: 1em 0 0.2em 4.5em;
     @media (max-width: $screen-xs) {
       margin-left: 3.5em;
     } // speech balloon