From 860d4d4be5eb7b1d4b13fcc31bf5fe3eafb01a33 Mon Sep 17 00:00:00 2001 From: Abijeet Date: Tue, 30 May 2017 09:02:47 +0530 Subject: [PATCH] #47 - Changes the way we are handling fetching of data for the comment section. --- app/Comment.php | 46 +++++++++++++------ app/Http/Controllers/CommentController.php | 19 ++++---- app/Repos/CommentRepo.php | 47 +++++++++++++++++--- resources/assets/js/controllers.js | 32 ++++++------- resources/assets/js/directives.js | 7 ++- resources/assets/sass/_comments.scss | 11 ++--- resources/views/comments/comments.blade.php | 12 ++--- resources/views/comments/list-item.blade.php | 16 +++---- routes/web.php | 3 +- 9 files changed, 119 insertions(+), 74 deletions(-) diff --git a/app/Comment.php b/app/Comment.php index 34abdcf29..8588982e5 100644 --- a/app/Comment.php +++ b/app/Comment.php @@ -1,12 +1,12 @@ belongsTo(User::class); } - public function getCommentsByPage($pageId, $commentId, $pageNum = 0, $limit = 0) { - + public function getPageComments($pageId) { $query = static::newQuery(); $query->join('users AS u', 'comments.created_by', '=', 'u.id'); $query->leftJoin('users AS u1', 'comments.updated_by', '=', 'u1.id'); $query->leftJoin('images AS i', 'i.id', '=', 'u.image_id'); - $query->selectRaw('comments.id, text, html, comments.created_by, comments.updated_by, comments.created_at, comments.updated_at, ' + $query->selectRaw('comments.id, text, html, comments.created_by, comments.updated_by, ' + . 'comments.created_at, comments.updated_at, comments.parent_id, ' . 'u.name AS created_by_name, u1.name AS updated_by_name, ' - . '(SELECT count(c.id) FROM bookstack.comments c WHERE c.parent_id = comments.id AND page_id = ?) AS cnt_sub_comments, i.url AS avatar ', - [$pageId]); - - if (empty($commentId)) { - $query->whereRaw('page_id = ? AND parent_id IS NULL', [$pageId]); - } else { - $query->whereRaw('page_id = ? AND parent_id = ?', [$pageId, $commentId]); - } + . 'i.url AS avatar '); + $query->whereRaw('page_id = ?', [$pageId]); $query->orderBy('created_at'); - return $query; + return $query->get(); + } + + public function getAllPageComments($pageId) { + return self::where('page_id', '=', $pageId)->with(['createdBy' => function($query) { + $query->select('id', 'name', 'image_id'); + }, 'updatedBy' => function($query) { + $query->select('id', 'name'); + }, 'createdBy.avatar' => function ($query) { + $query->select('id', 'path', 'url'); + }])->get(); + } + + public function getCommentById($commentId) { + return self::where('id', '=', $commentId)->with(['createdBy' => function($query) { + $query->select('id', 'name', 'image_id'); + }, 'updatedBy' => function($query) { + $query->select('id', 'name'); + }, 'createdBy.avatar' => function ($query) { + $query->select('id', 'path', 'url'); + }])->first(); } public function getCreatedAttribute() { @@ -72,4 +86,8 @@ class Comment extends Ownable ]; return $updated; } + + public function getSubCommentsAttribute() { + return $this->sub_comments; + } } diff --git a/app/Http/Controllers/CommentController.php b/app/Http/Controllers/CommentController.php index e1729bbee..29ccdf5a7 100644 --- a/app/Http/Controllers/CommentController.php +++ b/app/Http/Controllers/CommentController.php @@ -54,9 +54,12 @@ class CommentController extends Controller $respMsg = trans('entities.comment_updated'); } + $comment = $this->commentRepo->getCommentById($comment->id); + return response()->json([ 'status' => 'success', - 'message' => $respMsg + 'message' => $respMsg, + 'comment' => $comment ]); } @@ -64,11 +67,10 @@ class CommentController extends Controller public function destroy($id) { $comment = $this->comment->findOrFail($id); $this->checkOwnablePermission('comment-delete', $comment); - - // } - public function getCommentThread($pageId, $commentId = null) { + + public function getPageComments($pageId) { try { $page = $this->entityRepo->getById('page', $pageId, true); } catch (ModelNotFoundException $e) { @@ -85,12 +87,7 @@ class CommentController extends Controller $this->checkOwnablePermission('page-view', $page); - $comments = $this->commentRepo->getCommentsForPage($pageId, $commentId); - if (empty($commentId)) { - // requesting for parent level comments, send the total count as well. - $totalComments = $this->commentRepo->getCommentCount($pageId); - return response()->json(['success' => true, 'comments'=> $comments, 'total' => $totalComments]); - } - return response()->json(['success' => true, 'comments'=> $comments]); + $comments = $this->commentRepo->getPageComments($pageId); + return response()->json(['success' => true, 'comments'=> $comments['comments'], 'total' => $comments['total']]); } } diff --git a/app/Repos/CommentRepo.php b/app/Repos/CommentRepo.php index 7e4955d55..7d0c4ebd7 100644 --- a/app/Repos/CommentRepo.php +++ b/app/Repos/CommentRepo.php @@ -39,13 +39,48 @@ class CommentRepo { return $comment; } - public function getCommentsForPage($pageId, $commentId, $count = 20) { - // requesting parent comments - $query = $this->comment->getCommentsByPage($pageId, $commentId); - return $query->paginate($count); + public function getPageComments($pageId) { + $comments = $this->comment->getAllPageComments($pageId); + $index = []; + $totalComments = count($comments); + // normalizing the response. + foreach($comments as &$comment) { + $comment = $this->normalizeComment($comment); + $parentId = $comment->parent_id; + if (empty($parentId)) { + $index[$comment->id] = $comment; + continue; + } + + if (empty($index[$parentId])) { + // weird condition should not happen. + continue; + } + if (empty($index[$parentId]->sub_comments)) { + $index[$parentId]->sub_comments = []; + } + array_push($index[$parentId]->sub_comments, $comment); + $index[$comment->id] = $comment; + } + return [ + 'comments' => $comments, + 'total' => $totalComments + ]; } - public function getCommentCount($pageId) { - return $this->comment->where('page_id', '=', $pageId)->count(); + public function getCommentById($commentId) { + return $this->normalizeComment($this->comment->getCommentById($commentId)); + } + + private function normalizeComment($comment) { + if (empty($comment)) { + return; + } + $comment->createdBy->avatar_url = $comment->createdBy->getAvatar(50); + $comment->createdBy->profile_url = $comment->createdBy->getProfileUrl(); + if (!empty($comment->updatedBy)) { + $comment->updatedBy->profile_url = $comment->updatedBy->getProfileUrl(); + } + return $comment; } } \ No newline at end of file diff --git a/resources/assets/js/controllers.js b/resources/assets/js/controllers.js index 198089056..f64d7c038 100644 --- a/resources/assets/js/controllers.js +++ b/resources/assets/js/controllers.js @@ -714,10 +714,18 @@ module.exports = function (ngApp, events) { return events.emit('error', trans('error')); } if ($scope.isEdit) { - $scope.comment.html = commentHTML; + $scope.comment.html = resp.data.comment.html; + $scope.comment.text = resp.data.comment.text; + $scope.comment.updated = resp.data.comment.updated; + $scope.comment.updated_by = resp.data.comment.updated_by; $scope.$emit('evt.comment-success', $scope.comment.id); } else { $scope.comment.text = ''; + if ($scope.isReply === true && $scope.parent.sub_comments) { + $scope.parent.sub_comments.push(resp.data.comment); + } else { + $scope.$emit('evt.new-comment', resp.data.comment); + } $scope.$emit('evt.comment-success', null, true); } events.emit('success', trans(resp.data.message)); @@ -747,9 +755,14 @@ module.exports = function (ngApp, events) { $scope.errors = {}; // keep track of comment levels $scope.level = 1; - $scope.defaultAvatar = defaultAvatar; vm.totalCommentsStr = 'Loading...'; + $scope.$on('evt.new-comment', function (event, comment) { + // add the comment to the comment list. + vm.comments.push(comment); + event.stopPropagation(); + event.preventDefault(); + }); $timeout(function() { $http.get(window.baseUrl(`/ajax/page/${$scope.pageId}/comments/`)).then(resp => { @@ -757,7 +770,7 @@ module.exports = function (ngApp, events) { // TODO : Handle error return; } - vm.comments = resp.data.comments.data; + vm.comments = resp.data.comments; vm.totalComments = resp.data.total; // TODO : Fetch message from translate. if (vm.totalComments === 0) { @@ -770,21 +783,10 @@ module.exports = function (ngApp, events) { }, checkError('app')); }); - vm.loadSubComments = function(event, comment) { - event.preventDefault(); - $http.get(window.baseUrl(`/ajax/page/${$scope.pageId}/comments/${comment.id}/sub-comments`)).then(resp => { - if (!resp.data || resp.data.success !== true) { - return; - } - comment.is_loaded = true; - comment.comments = resp.data.comments.data; - }, checkError('app')); - }; - function checkError(errorGroupName) { $scope.errors[errorGroupName] = {}; return function(response) { - console.log(resp); + console.log(response); } } }]); diff --git a/resources/assets/js/directives.js b/resources/assets/js/directives.js index 6c556acc9..ff0f93cfa 100644 --- a/resources/assets/js/directives.js +++ b/resources/assets/js/directives.js @@ -825,10 +825,12 @@ module.exports = function (ngApp, events) { templateUrl: 'comment-reply.html', scope: { pageId: '=', - parentId: '=' + parentId: '=', + parent: '=' }, link: function (scope, element) { scope.isReply = true; + element.find('textarea').focus(); scope.$on('evt.comment-success', function (event) { // no need for the event to do anything more. event.stopPropagation(); @@ -849,6 +851,7 @@ module.exports = function (ngApp, events) { }, link: function (scope, element) { scope.isEdit = true; + element.find('textarea').focus(); scope.$on('evt.comment-success', function (event, commentId) { // no need for the event to do anything more. event.stopPropagation(); @@ -892,7 +895,7 @@ module.exports = function (ngApp, events) { function compileHtml($container, scope, isReply) { let lnkFunc = null; if (isReply) { - lnkFunc = $compile(''); + lnkFunc = $compile(''); } else { lnkFunc = $compile(''); } diff --git a/resources/assets/sass/_comments.scss b/resources/assets/sass/_comments.scss index 7d7cb486a..0328341c3 100644 --- a/resources/assets/sass/_comments.scss +++ b/resources/assets/sass/_comments.scss @@ -4,12 +4,7 @@ } .comment-box:last-child { - border-bottom: none; - } - .load-more-comments { - font-size: 0.8em; - margin-top: -1px; - margin-bottom: 6px; + border-bottom: 0px; } } .page-comment { @@ -42,11 +37,11 @@ } } - .comment-actions.has-border { + .comment-actions { border-bottom: 1px solid #DDD; } - .comment-actions.has-border:last-child { + .comment-actions:last-child { border-bottom: 0px; } diff --git a/resources/views/comments/comments.blade.php b/resources/views/comments/comments.blade.php index 8c4cb9860..93e7ebc05 100644 --- a/resources/views/comments/comments.blade.php +++ b/resources/views/comments/comments.blade.php @@ -4,13 +4,13 @@ -
+

@{{vm.totalCommentsStr}}

-
-
+
+
- +
-
-@include('comments/comment-reply', ['pageId' => $pageId]) \ No newline at end of file + @include('comments/comment-reply', ['pageId' => $pageId]) +
\ No newline at end of file diff --git a/resources/views/comments/list-item.blade.php b/resources/views/comments/list-item.blade.php index ca8b58625..46af1a862 100644 --- a/resources/views/comments/list-item.blade.php +++ b/resources/views/comments/list-item.blade.php @@ -1,28 +1,24 @@
- user avatar + user avatar
- @{{ ::comment.created_by_name }} + @{{ ::comment.created_by.name }}
-
+
- -
+
diff --git a/routes/web.php b/routes/web.php index 076bc8110..463e4e77b 100644 --- a/routes/web.php +++ b/routes/web.php @@ -123,8 +123,7 @@ Route::group(['middleware' => 'auth'], function () { Route::post('/ajax/page/{pageId}/comment/', 'CommentController@save'); Route::put('/ajax/page/{pageId}/comment/{commentId}', 'CommentController@save'); Route::delete('/ajax/comment/{id}', 'CommentController@destroy'); - Route::get('/ajax/page/{pageId}/comments/{commentId}/sub-comments', 'CommentController@getCommentThread'); - Route::get('/ajax/page/{pageId}/comments/', 'CommentController@getCommentThread'); + Route::get('/ajax/page/{pageId}/comments/', 'CommentController@getPageComments'); // Links Route::get('/link/{id}', 'PageController@redirectFromLink');