Просмотр исходного кода

Merge pull request #413 from weseek/feat/Markdown-editor-for-comment-mizobuchi

Feat/markdown editor for comment mizobuchi
Sou Mizobuchi 7 лет назад
Родитель
Сommit
003d3fc2aa

+ 0 - 27
lib/views/layout-growi/widget/comments.html

@@ -19,34 +19,7 @@
     </div>
 
     {% if page and not page.isDeleted() %}
-    <form class="form page-comment-form" id="page-comment-form" onsubmit="return false;">
-      <div class="comment-form">
-        <div class="comment-form-user">
-            <img src="{{ user|picture }}" class="picture img-circle" width="25" alt="{{ user.name }}" title="{{ user.name }}" />
-        </div>
-        <div class="comment-form-main">
-          <div class="comment-write" id="comment-write">
-            <textarea class="comment-form-comment form-control" id="comment-form-comment" name="commentForm[comment]"
-                required placeholder="Write comments here..." {% if not user %}disabled{% endif %}></textarea>
-            <input type="checkbox" id="comment-form-is-markdown" name="commentForm[is_markdown]" value="1"> Markdown<br>
-          </div>
-          <div class="comment-submit">
-            <input type="hidden" name="_csrf" value="{{ csrf() }}">
-            <input type="hidden" name="commentForm[page_id]" value="{{ page._id.toString() }}">
-            <input type="hidden" name="commentForm[revision_id]" value="{{ revision._id.toString() }}">
-            <div class="pull-right">
-              <span class="text-danger" id="comment-form-message"></span>
-              <button type="submit" id="comment-form-button" class="fcbtn btn btn-sm btn-outline btn-rounded btn-primary btn-1b" {% if not user %}disabled{% endif %}>
-                Comment
-              </button>
-            </div>
-            <div class="clearfix"></div>
-          </div>
-        </div>
-      </div>
-    </form>
     <div id="page-comment-write"></div>
-    <div id="page-comment-form-behavior"></div>
     {% endif %}
 
   </div>

+ 9 - 7
resource/js/app.js

@@ -131,13 +131,15 @@ Object.keys(componentMappings).forEach((key) => {
 // render comment form
 const writeCommentElem = document.getElementById('page-comment-write');
 if (writeCommentElem) {
-  ReactDOM.render(<CommentForm />, writeCommentElem);
-}
-
-// render components with refs to another component
-const elem = document.getElementById('page-comment-form-behavior');
-if (elem) {
-  ReactDOM.render(<PageCommentFormBehavior crowi={crowi} pageComments={componentInstances['page-comments-list']} />, elem);
+  const pageCommentsElem = componentInstances['page-comments-list'];
+  const postCompleteHandler = (comment) => {
+    if (pageCommentsElem != null) {
+      pageCommentsElem.retrieveData();
+    }
+  };
+  ReactDOM.render(
+    <CommentForm crowi={crowi} pageId={pageId} revisionId={pageRevisionId} onPostComplete={postCompleteHandler} />,
+    writeCommentElem);
 }
 
 /*

+ 67 - 21
resource/js/components/PageComment/CommentForm.js

@@ -18,39 +18,85 @@ export default class CommentForm extends React.Component {
     super(props);
 
     this.state = {
-      value: ''
+      comment: '',
+      isMarkdown: false,
     };
+
+    this.updateState = this.updateState.bind(this);
+    this.postComment = this.postComment.bind(this);
   }
 
-  render() {
+  updateState(event) {
+    const target = event.target;
+    const value = target.type === 'checkbox' ? target.checked : target.value;
+    const name = target.name;
 
+    this.setState({
+      [name]: value
+    });
+  }
+
+  /**
+   * Load data of comments and rerender <PageComments />
+   */
+  postComment(event) {
+    event.preventDefault();
+    this.props.crowi.apiPost('/comments.add', {
+      commentForm: {
+        comment: this.state.comment,
+        _csrf: this.props.crowi.csrfToken,
+        page_id: this.props.pageId,
+        revision_id: this.props.revisionId,
+        is_markdown: this.state.isMarkdown,
+      }
+    })
+      .then((res) => {
+        if (this.props.onPostComplete != null) {
+          this.props.onPostComplete(res.comment);
+        }
+        this.setState({
+          comment: '',
+          isMarkdown: false,
+        });
+      });
+  }
+
+  render() {
+    //{% if not user %}disabled{% endif %}をtextareaとbuttonに追加
+    // denounce/throttle
     return (
-      <div className="comment-form">
-        <div className="comment-form-user">
-        </div>
-        <div className="comment-form-main">
-          <div className="comment-write">
-            <textarea className="comment-form-comment form-control" id="comment-form-comment" name="commentForm[comment]" required placeholder="Write comments here..." >
-            </textarea>
-            <div className="form-check">
-            <input type="checkbox" className="form-check-input" id="checkbox-markdown" />
-              <label className="form-check-label" htmlFor="checkbox-markdown">Markdown</label>
-            </div>
-          </div>
-          <div className="comment-submit">
-            <div className="pull-right">
-              <Button bsStyle="primary" className="fcbtn btn btn-sm btn-primary btn-outline btn-rounded btn-1b">
-                  Comment
-              </Button>
+      <div>
+        <form className="form page-comment-form" id="page-comment-form" onSubmit={this.postComment}>
+          <div className="comment-form">
+            <div className="comment-form-user">
+              <img src="{{ user|picture }}" className="picture img-circle" width="25" alt="{{ user.name }}" title="{{ user.name }}" />
             </div>
-            <div className="clearfix">
+            <div className="comment-form-main">
+              <div className="comment-write" id="comment-write">
+                <textarea className="comment-form-comment form-control" id="comment-form-comment" name="comment"
+                  required placeholder="Write comments here..." value={this.state.comment} onChange={this.updateState}></textarea>
+                <input type="checkbox" id="comment-form-is-markdown" name="isMarkdown" checked={this.state.isMarkdown} value="1" onChange={this.updateState} /> Markdown<br />
+              </div>
+              <div className="comment-submit">
+                <div className="pull-right">
+                  <span className="text-danger" id="comment-form-message"></span>
+                  <button type="submit" value="Submit" id="comment-form-button" className="fcbtn btn btn-sm btn-outline btn-rounded btn-primary btn-1b">
+                    Comment
+                  </button>
+                </div>
+                <div className="clearfix"></div>
+              </div>
             </div>
           </div>
-        </div>
+        </form>
       </div>
     );
   }
 }
 
 CommentForm.propTypes = {
+  crowi: PropTypes.object.isRequired,
+  onPostComplete: PropTypes.func,
+  pageId: PropTypes.string,
+  revisionId: PropTypes.string,
 };

+ 15 - 11
resource/js/components/PageComments.js

@@ -47,6 +47,8 @@ export default class PageComments extends React.Component {
     if (pageId) {
       this.init();
     }
+
+    this.retrieveData = this.retrieveData.bind(this);
   }
 
   init() {
@@ -54,21 +56,23 @@ export default class PageComments extends React.Component {
       return ;
     }
 
-    const pageId = this.props.pageId;
-
     const layoutType = this.props.crowi.getConfig()['layoutType'];
     this.setState({isLayoutTypeGrowi: 'crowi-plus' === layoutType || 'growi' === layoutType});
 
-    // get data (desc order array)
-    this.props.crowi.apiGet('/comments.get', {page_id: pageId})
-    .then(res => {
-      if (res.ok) {
-        this.setState({comments: res.comments});
-      }
-    }).catch(err => {
-
-    });
+    this.retrieveData();
+  }
 
+  /**
+   * Load data of comments and store them in state
+   */
+  retrieveData() {
+    // get data (desc order array)
+    this.props.crowi.apiGet('/comments.get', {page_id: this.props.pageId})
+      .then(res => {
+        if (res.ok) {
+          this.setState({comments: res.comments});
+        }
+      });
   }
 
   confirmToDeleteComment(comment) {