From 4b9f6beb376fc6b0c31af77d96ff0842bcdd53bc Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Wed, 7 Jun 2023 13:24:49 +0100 Subject: [PATCH] Comments: Updated to show as nested threads Initial functional implementation, a lot of tweaking and adapting to be done. --- app/Activity/CommentRepo.php | 24 +---- app/Activity/Tools/CommentTree.php | 102 ++++++++++++++++++ app/Entities/Controllers/PageController.php | 12 +-- resources/sass/_components.scss | 7 ++ .../views/comments/comment-branch.blade.php | 17 +++ resources/views/comments/comment.blade.php | 2 +- resources/views/comments/comments.blade.php | 10 +- resources/views/pages/show.blade.php | 4 +- 8 files changed, 143 insertions(+), 35 deletions(-) create mode 100644 app/Activity/Tools/CommentTree.php create mode 100644 resources/views/comments/comment-branch.blade.php diff --git a/app/Activity/CommentRepo.php b/app/Activity/CommentRepo.php index f16767fcf..2aabab79d 100644 --- a/app/Activity/CommentRepo.php +++ b/app/Activity/CommentRepo.php @@ -7,27 +7,14 @@ use BookStack\Entities\Models\Entity; use BookStack\Facades\Activity as ActivityService; use League\CommonMark\CommonMarkConverter; -/** - * Class CommentRepo. - */ class CommentRepo { - /** - * @var Comment - */ - protected $comment; - - public function __construct(Comment $comment) - { - $this->comment = $comment; - } - /** * Get a comment by ID. */ public function getById(int $id): Comment { - return $this->comment->newQuery()->findOrFail($id); + return Comment::query()->findOrFail($id); } /** @@ -36,7 +23,7 @@ class CommentRepo public function create(Entity $entity, string $text, ?int $parent_id): Comment { $userId = user()->id; - $comment = $this->comment->newInstance(); + $comment = new Comment(); $comment->text = $text; $comment->html = $this->commentToHtml($text); @@ -83,7 +70,7 @@ class CommentRepo 'allow_unsafe_links' => false, ]); - return $converter->convertToHtml($commentText); + return $converter->convert($commentText); } /** @@ -91,9 +78,8 @@ class CommentRepo */ protected function getNextLocalId(Entity $entity): int { - /** @var Comment $comment */ - $comment = $entity->comments(false)->orderBy('local_id', 'desc')->first(); + $currentMaxId = $entity->comments()->max('local_id'); - return ($comment->local_id ?? 0) + 1; + return $currentMaxId + 1; } } diff --git a/app/Activity/Tools/CommentTree.php b/app/Activity/Tools/CommentTree.php new file mode 100644 index 000000000..559edccf3 --- /dev/null +++ b/app/Activity/Tools/CommentTree.php @@ -0,0 +1,102 @@ +comments = $this->loadComments(); + $this->tree = $this->createTree($this->comments); + } + + public function enabled(): bool + { + return !setting('app-disable-comments'); + } + + public function empty(): bool + { + return count($this->tree) === 0; + } + + public function count(): int + { + return count($this->comments); + } + + public function get(): array + { + return $this->tree; + } + + /** + * @param Comment[] $comments + */ + protected function createTree(array $comments): array + { + $byId = []; + foreach ($comments as $comment) { + $byId[$comment->local_id] = $comment; + } + + $childMap = []; + foreach ($comments as $comment) { + $parent = $comment->parent_id; + if (is_null($parent) || !isset($byId[$parent])) { + $parent = 0; + } + + if (!isset($childMap[$parent])) { + $childMap[$parent] = []; + } + $childMap[$parent][] = $comment->local_id; + } + + $tree = []; + foreach ($childMap[0] as $childId) { + $tree[] = $this->createTreeForId($childId, 0, $byId, $childMap); + } + + return $tree; + } + + protected function createTreeForId(int $id, int $depth, array &$byId, array &$childMap): array + { + $childIds = $childMap[$id] ?? []; + $children = []; + + foreach ($childIds as $childId) { + $children[] = $this->createTreeForId($childId, $depth + 1, $byId, $childMap); + } + + return [ + 'comment' => $byId[$id], + 'depth' => $depth, + 'children' => $children, + ]; + } + + protected function loadComments(): array + { + if (!$this->enabled()) { + return []; + } + + return $this->page->comments() + ->with('createdBy') + ->get() + ->all(); + } +} diff --git a/app/Entities/Controllers/PageController.php b/app/Entities/Controllers/PageController.php index a6ef68dd7..e0444ecd2 100644 --- a/app/Entities/Controllers/PageController.php +++ b/app/Entities/Controllers/PageController.php @@ -3,6 +3,7 @@ namespace BookStack\Entities\Controllers; use BookStack\Activity\Models\View; +use BookStack\Activity\Tools\CommentTree; use BookStack\Entities\Models\Page; use BookStack\Entities\Repos\PageRepo; use BookStack\Entities\Tools\BookContents; @@ -140,15 +141,10 @@ class PageController extends Controller $pageContent = (new PageContent($page)); $page->html = $pageContent->render(); - $sidebarTree = (new BookContents($page->book))->getTree(); $pageNav = $pageContent->getNavigation($page->html); - // Check if page comments are enabled - $commentsEnabled = !setting('app-disable-comments'); - if ($commentsEnabled) { - $page->load(['comments.createdBy']); - } - + $sidebarTree = (new BookContents($page->book))->getTree(); + $commentTree = (new CommentTree($page)); $nextPreviousLocator = new NextPreviousContentLocator($page, $sidebarTree); View::incrementFor($page); @@ -159,7 +155,7 @@ class PageController extends Controller 'book' => $page->book, 'current' => $page, 'sidebarTree' => $sidebarTree, - 'commentsEnabled' => $commentsEnabled, + 'commentTree' => $commentTree, 'pageNav' => $pageNav, 'next' => $nextPreviousLocator->getNext(), 'previous' => $nextPreviousLocator->getPrevious(), diff --git a/resources/sass/_components.scss b/resources/sass/_components.scss index 1521e6eaa..bd85bb99f 100644 --- a/resources/sass/_components.scss +++ b/resources/sass/_components.scss @@ -704,6 +704,13 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group { } } +.comment-thread-indicator { + border-inline-start: 3px dotted #DDD; + @include lightDark(border-color, #DDD, #444); + margin-inline-start: $-xs; + width: $-l; +} + #tag-manager .drag-card { max-width: 500px; } diff --git a/resources/views/comments/comment-branch.blade.php b/resources/views/comments/comment-branch.blade.php new file mode 100644 index 000000000..d64dd4ade --- /dev/null +++ b/resources/views/comments/comment-branch.blade.php @@ -0,0 +1,17 @@ +
+
+ @include('comments.comment', ['comment' => $branch['comment']]) +
+ @if(count($branch['children']) > 0) +
+
+
+
+
+ @foreach($branch['children'] as $childBranch) + @include('comments.comment-branch', ['branch' => $childBranch]) + @endforeach +
+
+ @endif +
\ No newline at end of file diff --git a/resources/views/comments/comment.blade.php b/resources/views/comments/comment.blade.php index 6189c65d4..093e5a899 100644 --- a/resources/views/comments/comment.blade.php +++ b/resources/views/comments/comment.blade.php @@ -1,4 +1,4 @@ -
+
diff --git a/resources/views/comments/comments.blade.php b/resources/views/comments/comments.blade.php index 140d0d027..f50e3a218 100644 --- a/resources/views/comments/comments.blade.php +++ b/resources/views/comments/comments.blade.php @@ -8,8 +8,8 @@ aria-label="{{ trans('entities.comments') }}">
-
{{ trans_choice('entities.comment_count', count($page->comments), ['count' => count($page->comments)]) }}
- @if (count($page->comments) === 0 && userCan('comment-create-all')) +
{{ trans_choice('entities.comment_count', $commentTree->count(), ['count' => $commentTree->count()]) }}
+ @if ($commentTree->empty() && userCan('comment-create-all'))
@@ -18,15 +18,15 @@
- @foreach($page->comments as $comment) - @include('comments.comment', ['comment' => $comment]) + @foreach($commentTree->get() as $branch) + @include('comments.comment-branch', ['branch' => $branch]) @endforeach
@if(userCan('comment-create-all')) @include('comments.create') - @if (count($page->comments) > 0) + @if (!$commentTree->empty())
diff --git a/resources/views/pages/show.blade.php b/resources/views/pages/show.blade.php index 2cbc7fe47..fa6b1a2cd 100644 --- a/resources/views/pages/show.blade.php +++ b/resources/views/pages/show.blade.php @@ -27,7 +27,7 @@ @include('entities.sibling-navigation', ['next' => $next, 'previous' => $previous]) - @if ($commentsEnabled) + @if ($commentTree->enabled()) @if(($previous || $next))

@@ -35,7 +35,7 @@ @endif @endif