mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-11-24 11:52:34 +01:00
#47 - Adds functionality to display child comments. Also has some code towards the reply functionality.
This commit is contained in:
parent
d447355a61
commit
c3ea0d333e
@ -34,8 +34,8 @@ class Comment extends Ownable
|
||||
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');
|
||||
@ -44,7 +44,12 @@ class Comment extends Ownable
|
||||
. '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;
|
||||
}
|
||||
|
@ -85,7 +85,11 @@ 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(array('success' => true, 'comments'=> $comments, 'total' => $totalComments));
|
||||
}
|
||||
return response()->json(array('success' => true, 'comments'=> $comments));
|
||||
}
|
||||
}
|
||||
|
@ -38,14 +38,13 @@ class CommentRepo {
|
||||
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();
|
||||
}
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
const argv = require('yargs').argv;
|
||||
const gulp = require('gulp'),
|
||||
plumber = require('gulp-plumber');
|
||||
|
@ -731,14 +731,14 @@ module.exports = function (ngApp, events) {
|
||||
}
|
||||
|
||||
$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) {
|
||||
@ -749,6 +749,18 @@ 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 => {
|
||||
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) {
|
||||
|
@ -865,5 +865,52 @@ module.exports = function (ngApp, events) {
|
||||
}
|
||||
}
|
||||
}]);
|
||||
|
||||
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();
|
||||
}
|
||||
}]);
|
||||
};
|
||||
|
@ -1,8 +1,4 @@
|
||||
@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"
|
||||
|
10
resources/views/comments/comment-reply.blade.php
Normal file
10
resources/views/comments/comment-reply.blade.php
Normal file
@ -0,0 +1,10 @@
|
||||
<!-- 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>
|
19
resources/views/comments/comments.blade.php
Normal file
19
resources/views/comments/comments.blade.php
Normal file
@ -0,0 +1,19 @@
|
||||
@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])
|
@ -1,19 +1,26 @@
|
||||
<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>
|
@ -1,8 +0,0 @@
|
||||
<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])
|
@ -113,7 +113,7 @@
|
||||
<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>
|
||||
|
Loading…
Reference in New Issue
Block a user