OSDN Git Service

Controller::API::Comment: implement comment post
authorhylom <hylom@users.sourceforge.jp>
Sun, 30 Oct 2016 11:57:01 +0000 (20:57 +0900)
committerhylom <hylom@users.sourceforge.jp>
Sun, 30 Oct 2016 11:57:01 +0000 (20:57 +0900)
src/newslash_web/lib/Newslash/Web/Controller/API/Comment.pm
src/newslash_web/public/js/comments.js
src/newslash_web/templates/common/comment.html.tt2
src/newslash_web/templates/common/comment_form.html.tt2
src/newslash_web/templates/common/comments.html.tt2
src/newslash_web/templates/story/story.html.tt2

index c82c74a..a469284 100644 (file)
@@ -2,6 +2,7 @@ package Newslash::Web::Controller::API::Comment;
 use Mojo::Base 'Mojolicious::Controller';
 use Mojo::Util qw(dumper);
 use Mojo::JSON qw(decode_json encode_json);
+use Mojo::Date;
 
 sub post {
     my $c = shift;
@@ -42,24 +43,31 @@ EOT
         return;
     }
 
+    $data->{title} = $params->{title};
+    $data->{comment} = $params->{comment};
+    $data->{author} = $user->{nickname};
+    $data->{signature} = $user->{sig};
+    $data->{date} = Mojo::Date->new->to_datetime;
+
     if ($data->{action} eq 'preview') {
-        $data->{title} = $params->{title};
-        $data->{comment} = $params->{comment};
         $c->render(json => $data);
         return;
     }
     elsif ($params->{action} eq 'post') {
         my $cid = $comments->create($params, $user, $extra_params, $opts);
         if ($cid) {
-            $c->render(json => {type => "comment", id => $cid});
+            $data->{type} = "comment";
+            $data->{id} = $cid;
+            $data->{cid} = $cid;
+            $c->render(json => $data);
         }
         else {
+            warn $comments->last_error;
             if ($comments->last_errorno && $comments->last_errorno == 1062) { #ER_DUP_ENTRY
                 $c->rendered(409);
                 return;
             }
-            $c->render(json => { err => 1, message => $comments->last_error });
-            warn $comments->last_error;
+            $c->render(json => { error => 1, message => $comments->last_error });
             $c->rendered(500);
         }
     }
index 02c3fbb..0b381ac 100644 (file)
@@ -1,4 +1,4 @@
-/* commentst.js */
+/* comments.js */
 const comments = {};
 var vm;
 
@@ -8,6 +8,99 @@ Vue.component('comment-node', {
   //props: {comments: Object,},
 });
 
+Vue.component('comment-form', {
+  template: '#comment-form-template',
+  props: {reply: Object,},
+  methods: {
+    hideReplyForm: function (reply) {
+      reply.showForm = 0;
+    },
+    showPreview: function (reply) {
+      const data = {
+        title: reply.rawTitle,
+        comment: reply.rawComment,
+        discussion_id: vm.discussion_id,
+        stoid: vm.stoid,
+        pid: reply.pid,
+        action: 'preview',
+      }
+      this.$http.post(vm.endPoint, data).then(
+        (response) => { // success
+          reply.subject = response.body.title;
+          reply.comment = response.body.comment;
+          reply.author = response.body.author;
+          reply.date = response.body.date;
+          reply.signature = response.body.signature;
+          reply.showForm = false;
+          reply.showPreview = true;
+        },
+        (response) => { // fail
+          if (response.body.message) {
+            reply.message = response.body.message;
+          }
+        }
+      );
+    },
+    leavePreview: function (reply) {
+      reply.showForm = true;
+      reply.showPreview = false;
+    },
+    postComment: function (reply) {
+      const data = {
+        title: reply.rawTitle,
+        comment: reply.rawComment,
+        discussion_id: vm.discussion_id,
+        stoid: vm.stoid,
+        pid: reply.pid,
+        action: 'post',
+      }
+      this.$http.post(vm.endPoint, data).then(
+        (response) => { // success
+          reply.message = "success!";
+          reply.showForm = true;
+          reply.showPreview = false;
+        },
+        (response) => { // fail
+          if (response.body.message) {
+            reply.message = response.body.message;
+          }
+        }
+      );
+    },
+  },
+});
+
+Vue.component('comment', {
+  template: '#comment-template',
+  props: {comment: Object,},
+});
+
+comments.blankReply = function blankReply () {
+  return {
+    rawTitle: '',
+    rawComment: '',
+    subject: '',
+    comment: '',
+    author: '',
+    date: '',
+    cid: '',
+    signature: '',
+    pid: 0,
+    showForm: 0,
+    showPreview: 0,
+    message: '',
+  };
+}
+
+comments.initializeComments = function initializeComments (comments, params) {
+  comments.forEach(comment => {
+    comment.enableReply = params.enableReply;
+    comment.reply = this.blankReply();
+    comment.reply.rawTitle = 'Re:' + comment.subject;
+    comment.reply.pid = comment.cid;
+  });
+}
+
 comments.run = function run (params) {
   const data = {
     type: params.type,
@@ -15,19 +108,28 @@ comments.run = function run (params) {
     sid: params.sid,
     discussion_id: params.discussion_id,
     comments: params.comments,
+    endPoint: "/api/v1/comment",
+    enableReply: params.enableReply,
+    rootReply: this.blankReply(),
   };
+  data.rootReply.showForm = params.enableReply;
 
   const computed = {};
-  const methods = {};
-  const endPoint = "/api/v1/comment?discussion_id=" + data.discussion_id;
-
+  const methods = {
+    showReplyForm: function (reply) {
+      console.log(reply);
+      reply.showForm = 1;
+    },
+  };
+  const getUrl = "/api/v1/comment?discussion_id=" + data.discussion_id;
   vm = new Vue({el: params.el,
                 data: data,
                 computed: computed,
                 methods: methods,
                 created: function () {
-                  this.$http.get(endPoint).then(
+                  this.$http.get(getUrl).then(
                     (resp) => { // success
+                      comments.initializeComments(resp.body.comments, params);
                       this.comments = resp.body.comments;
                     },
                     (resp) => { // fail
index ccadb26..7056eac 100644 (file)
@@ -15,6 +15,6 @@
   <div class="body contents-text" v-html="comment.comment">[% comment.comment %]</div>
   <footer>
     <div class="signature" v-text="comment.signature">[% comment.signature %]</div>
-    <div>[ここに返信]</div>
+    <button v-if="comment.enableReply" v-on:click="showReplyForm(comment.reply)">ここに返信</button>
   </footer>
 </section>
index 17ac8c8..93c87e6 100644 (file)
@@ -1,22 +1,23 @@
-<form id="post-comment" v-show="show_form">
+<form id="post-comment" v-if="reply.showForm">
+  <div v-text="reply.message"></div>
   <p class="form-group">
     <label for="post-title">コメントタイトル:</label>
-    <input id="post-title" type="text" class="form-control" name="title" v-model="title" placeholder="タイトル" />
+    <input id="post-title" type="text" class="form-control" name="title" v-model="reply.rawTitle" placeholder="タイトル" />
   </p>
     <label for="post-introtext">コメント本文:</label>
-    <textarea id="post-introtext" name="introtext" class="form-control" v-model="introtext" placeholder="本文をここに記述してください" ></textarea>
+    <textarea id="post-introtext" name="introtext" class="form-control" v-model="reply.rawComment" placeholder="本文をここに記述してください" ></textarea>
   </p>
   <p>
-    <button type="submit" class="btn btn-default" v-on:click.prevent="show_preview">投稿確認</button>
+    <button type="submit" class="btn btn-default" v-on:click.prevent="showPreview(reply)">投稿確認</button>
     <button type="reset" class="btn">リセット</button>
+    <button class="btn" v-on:click.prevent="hideReplyForm(reply)">キャンセル</button>
   </p>
 </form>
 
-<form id="post-submit" v-show="show_submit">
+<form id="post-submit" v-if="reply.showPreview">
   <p>
-    <button type="submit" class="btn btn-default" v-on:click.prevent="post_submission">投稿</button>
-    <button type="button" class="btn" v-on:click="leave_preview">戻る</button>
+    <comment :comment="reply"></comment>
+    <button type="submit" class="btn btn-default" v-on:click.prevent="postComment(reply)">投稿</button>
+    <button type="button" class="btn" v-on:click="leavePreview(reply)">戻る</button>
   </p>
 </form>
-
-</div><!-- #post-comment -->
index 776d1e0..01eb138 100644 (file)
@@ -1,7 +1,18 @@
+<script type="text/x-template" id="comment-template">
+  [%- INCLUDE common/comment comment={} -%]
+</script>
+
+<script type="text/x-template" id="comment-form-template">
+  <div class="comment-form">
+    [%- INCLUDE common/comment_form -%]
+  </div>
+</script>
+
 <script type="text/x-template" id="comment-node-template">
   <li v-for="comment in comments">
-    [%- INCLUDE common/comment comment={} -%]
+    <comment :comment="comment"></comment>
     <ol>
+      <li><comment-form :reply="comment.reply"></comment-form></li>
       <comment-node :comments="comment.children">
       </comment-node>
     </ol>
     <li v-for="comment in comments" v-if="comment.pid == 0">
       [%- INCLUDE common/comment comment={} -%]
       <ol>
+        <li><comment-form :reply="comment.reply"></comment-form></li>
         <comment-node :comments="comment.children">
         </comment-node>
       </ol>
     </li>
+    <comment-form :reply="rootReply"></comment-form>
   </ol>
+
 </div>
 
 <script src="/js/comments.js" ></script>
                      type: "story",
                      stoid: [% story.stoid %],
                      sid: "[% story.sid %]",
-                     discussion_id: [% story.discussion %]});
-  /*
-    var endPoint = "/api/v1/comment?discussion_id=[% story.discussion %]";
-    $.getJSON(endPoint, function (data) {
-      comments.run({ el: "#comments",
-                     type: "story",
-                     stoid: [% story.stoid %],
-                     sid: "[% story.sid %]",
                      discussion_id: [% story.discussion %],
-                     comments: data.comments,
-      });
+                     enableReply: [% IF story.is_archived == 'no' %]1[% ELSE %]0[% END %],
+  
   });
-  */
   });
 </script>
index ff34561..f14b5b2 100644 (file)
@@ -29,9 +29,4 @@
 [%#- INCLUDE common/comments_nojs -%]
 [%- INCLUDE common/comments -%]
 
-<div id="comment_form">
-  [%- INCLUDE common/comment_form %]
-</div>
-
-
 [% END %]