return $this->belongsTo(User::class);
}
- public function getParentCommentsByPage($pageId, $pageNum = 0, $limit = 0) {
- $data = ['pageId' => $pageId];
+ public function getCommentsByPage($pageId, $commentId, $pageNum = 0, $limit = 0) {
+
$query = static::newQuery();
$query->join('users AS u', 'comments.created_by', '=', 'u.id');
$query->leftJoin('users AS u1', 'comments.updated_by', '=', 'u1.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]);
- $query->whereRaw('page_id = ? AND parent_id IS NULL', [$pageId]);
+
+ if (empty($commentId)) {
+ $query->whereRaw('page_id = ? AND parent_id IS NULL', [$pageId]);
+ } else {
+ $query->whereRaw('page_id = ? AND parent_id = ?', [$pageId, $commentId]);
+ }
$query->orderBy('created_at');
return $query;
}
$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(array('success' => true, 'comments'=> $comments, 'total' => $totalComments));
+ }
return response()->json(array('success' => true, 'comments'=> $comments));
}
}
return $comment;
}
- public function getCommentsForPage($pageId, $commentId, $count = 20) {
- if (empty($commentId)) {
- // requesting parent comments
- $query = $this->comment->getParentCommentsByPage($pageId);
- return $query->paginate($count);
- } else {
- // requesting the child comments.
- return Comment::whereRaw("page_id = $pageId AND parent_id = $commentId")->get();
- }
+ public function getCommentsForPage($pageId, $commentId, $count = 20) {
+ // requesting parent comments
+ $query = $this->comment->getCommentsByPage($pageId, $commentId);
+ return $query->paginate($count);
+ }
+
+ public function getCommentCount($pageId) {
+ return $this->comment->where('page_id', '=', $pageId)->count();
}
}
\ No newline at end of file
+'use strict';
+
const argv = require('yargs').argv;
const gulp = require('gulp'),
plumber = require('gulp-plumber');
}
$timeout(function() {
- console.log($scope.pageId);
$http.get(window.baseUrl(`/ajax/page/${$scope.pageId}/comments/`)).then(resp => {
if (!resp.data || resp.data.success !== true) {
// TODO : Handle error
return;
- }
+ }
vm.comments = resp.data.comments.data;
- vm.totalComments = resp.data.comments.total;
+ vm.totalComments = resp.data.total;
+ // TODO : Fetch message from translate.
if (vm.totalComments === 0) {
vm.totalCommentsStr = 'No comments found.';
} else if (vm.totalComments === 1) {
}, checkError('app'));
});
+ vm.loadSubComments = function(event, comment) {
+ event.preventDefault();
+ $http.get(window.baseUrl(`/ajax/page/${$scope.pageId}/comments/${comment.id}/sub-comments`)).then(resp => {
+ console.log(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) {
}
}
}]);
+
+ ngApp.directive('commentReply', ['$timeout', function ($timeout) {
+ return {
+ restrict: 'E',
+ templateUrl: 'comment-reply.html',
+ scope: {
+
+ },
+ link: function (scope, element, attr) {
+
+ }
+ }
+
+ }]);
+ ngApp.directive('commentReplyLink', ['$document', '$compile', function ($document, $compile) {
+ return {
+ link: function (scope, element, attr) {
+ element.on('$destroy', function () {
+ element.off('click');
+ scope.$destroy();
+ });
+
+ element.on('click', function () {
+ var $container = element.parents('.comment-box').first();
+ if (!$container.length) {
+ console.error('commentReplyLink directive should be placed inside a container with class comment-box!');
+ return;
+ }
+ if (attr.noCommentReplyDupe) {
+ removeDupe();
+ }
+ var compiledHTML = $compile('<comment-reply></comment-reply>')(scope);
+ $container.append(compiledHTML);
+ });
+ }
+ };
+
+
+ function removeDupe() {
+ let $existingElement = $document.find('comment-reply');
+ if (!$existingElement.length) {
+ return;
+ }
+
+ $existingElement.remove();
+ }
+ }]);
};
-@section('head')
- <script src="{{ baseUrl("/libs/simplemde/simplemde.min.js") }}"></script>
-@stop
-
-<div class="comment-editor" ng-controller="CommentAddController as vm">
+<div class="comment-editor" ng-controller="CommentAddController as vm" ng-cloak>
<form novalidate>
<div simple-markdown-input smd-model="comment.newComment" smd-get-content="getCommentHTML" smd-clear="clearInput">
<textarea name="markdown" rows="3"
--- /dev/null
+<!-- TODO :: needs to be merged with add.blade.php -->
+<form novalidate>
+ <div simple-markdown-input smd-model="comment.newComment" smd-get-content="getCommentHTML" smd-clear="clearInput">
+ <textarea name="markdown" rows="3"
+ @if($errors->has('markdown')) class="neg" @endif>@if(isset($model) ||
+ old('markdown')){{htmlspecialchars( old('markdown') ? old('markdown') : ($model->markdown === '' ? $model->html : $model->markdown))}}@endif</textarea>
+ </div>
+ <input type="hidden" ng-model="pageId" name="comment.pageId" value="{{$pageId}}" ng-init="comment.pageId = {{$pageId }}">
+ <button type="submit" class="button pos" ng-click="vm.saveComment()">Save</button>
+</form>
\ No newline at end of file
--- /dev/null
+@section('head')
+ <script src="{{ baseUrl("/libs/simplemde/simplemde.min.js") }}"></script>
+@stop
+<script type="text/ng-template" id="comment-list-item.html">
+ @include('comments/list-item')
+</script>
+<script type="text/ng-template" id="comment-reply.html">
+ @include('comments/comment-reply')
+</script>
+<div ng-controller="CommentListController as vm" ng-init="pageId = <?= $page->id ?>" class="comments-list" ng-cloak>
+<h3>@{{vm.totalCommentsStr}}</h3>
+<hr>
+ <div class="comment-box" ng-repeat="comment in vm.comments track by comment.id">
+ <div ng-include src="'comment-list-item.html'">
+
+ </div>
+ </div>
+</div>
+@include('comments/add', ['pageId' => $pageId])
\ No newline at end of file
<div class='page-comment'>
<div class="user-image">
- <img ng-src="@{{defaultAvatar}}" alt="user avatar">
+ <img ng-src="@{{::defaultAvatar}}" alt="user avatar">
</div>
<div class="comment-container">
<div class="comment-header">
@{{ ::comment.created_by_name }}
</div>
- <div ng-bind-html="comment.html" class="comment-body">
+ <div ng-bind-html="::comment.html" class="comment-body">
</div>
<div class="comment-actions">
<ul>
- <li><a href="#">Reply</a></li>
+ <li><a href="#" comment-reply-link no-comment-reply-dupe="true">Reply</a></li>
<li><a href="#">@{{::comment.created_at}}</a></li>
</ul>
</div>
- </div>
+ <a href="#" ng-click="vm.loadSubComments($event, comment, $index)" class="load-more-comments" ng-if="comment.cnt_sub_comments > 0 && !comment.is_loaded">
+ Load @{{::comment.cnt_sub_comments}} more comment(s)
+ </a>
+ <div class="comment-box" ng-repeat="comment in comments = comment.comments track by comment.id">
+ <div ng-include src="'comment-list-item.html'">
+ </div>
+ </div>
+ </div>
</div>
\ No newline at end of file
+++ /dev/null
-<div ng-controller="CommentListController as vm" ng-init="pageId = <?= $page->id ?>" class="comments-list" ng-cloak>
-<h3>@{{vm.totalCommentsStr}}</h3>
-<hr>
- <div class="comment-box" ng-repeat="comment in vm.comments track by comment.id">
- @include('comments/list-item')
- </div>
-</div>
-@include('comments/add', ['pageId' => $pageId])
<div class="container">
<div class="row">
<div class="col-md-9">
- @include('pages/comments', ['pageId' => $page->id])
+ @include('comments/comments', ['pageId' => $page->id])
</div>
</div>
</div>