mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-01 01:36:00 -04:00
Comments: Added read-only listing into page editor
This commit is contained in:
parent
ec775aec02
commit
9a2ef7ef44
@ -24,16 +24,10 @@ use Throwable;
|
|||||||
|
|
||||||
class PageController extends Controller
|
class PageController extends Controller
|
||||||
{
|
{
|
||||||
protected PageRepo $pageRepo;
|
public function __construct(
|
||||||
protected ReferenceFetcher $referenceFetcher;
|
protected PageRepo $pageRepo,
|
||||||
|
protected ReferenceFetcher $referenceFetcher
|
||||||
/**
|
) {
|
||||||
* PageController constructor.
|
|
||||||
*/
|
|
||||||
public function __construct(PageRepo $pageRepo, ReferenceFetcher $referenceFetcher)
|
|
||||||
{
|
|
||||||
$this->pageRepo = $pageRepo;
|
|
||||||
$this->referenceFetcher = $referenceFetcher;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace BookStack\Entities\Tools;
|
namespace BookStack\Entities\Tools;
|
||||||
|
|
||||||
|
use BookStack\Activity\Tools\CommentTree;
|
||||||
use BookStack\Entities\Models\Page;
|
use BookStack\Entities\Models\Page;
|
||||||
use BookStack\Entities\Repos\PageRepo;
|
use BookStack\Entities\Repos\PageRepo;
|
||||||
use BookStack\Entities\Tools\Markdown\HtmlToMarkdown;
|
use BookStack\Entities\Tools\Markdown\HtmlToMarkdown;
|
||||||
@ -9,19 +10,14 @@ use BookStack\Entities\Tools\Markdown\MarkdownToHtml;
|
|||||||
|
|
||||||
class PageEditorData
|
class PageEditorData
|
||||||
{
|
{
|
||||||
protected Page $page;
|
|
||||||
protected PageRepo $pageRepo;
|
|
||||||
protected string $requestedEditor;
|
|
||||||
|
|
||||||
protected array $viewData;
|
protected array $viewData;
|
||||||
protected array $warnings;
|
protected array $warnings;
|
||||||
|
|
||||||
public function __construct(Page $page, PageRepo $pageRepo, string $requestedEditor)
|
public function __construct(
|
||||||
{
|
protected Page $page,
|
||||||
$this->page = $page;
|
protected PageRepo $pageRepo,
|
||||||
$this->pageRepo = $pageRepo;
|
protected string $requestedEditor
|
||||||
$this->requestedEditor = $requestedEditor;
|
) {
|
||||||
|
|
||||||
$this->viewData = $this->build();
|
$this->viewData = $this->build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,6 +65,7 @@ class PageEditorData
|
|||||||
'draftsEnabled' => $draftsEnabled,
|
'draftsEnabled' => $draftsEnabled,
|
||||||
'templates' => $templates,
|
'templates' => $templates,
|
||||||
'editor' => $editorType,
|
'editor' => $editorType,
|
||||||
|
'comments' => new CommentTree($page),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,6 +371,7 @@ return [
|
|||||||
'comment_updated_success' => 'Comment updated',
|
'comment_updated_success' => 'Comment updated',
|
||||||
'comment_delete_confirm' => 'Are you sure you want to delete this comment?',
|
'comment_delete_confirm' => 'Are you sure you want to delete this comment?',
|
||||||
'comment_in_reply_to' => 'In reply to :commentId',
|
'comment_in_reply_to' => 'In reply to :commentId',
|
||||||
|
'comment_editor_explain' => 'Here are the comments that have been left on this page. Comments can be added & managed when viewing the saved page.',
|
||||||
|
|
||||||
// Revision
|
// Revision
|
||||||
'revision_delete_confirm' => 'Are you sure you want to delete this revision?',
|
'revision_delete_confirm' => 'Are you sure you want to delete this revision?',
|
||||||
|
@ -676,6 +676,7 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
|
|||||||
@include lightDark(background-color, #FFF, #222);
|
@include lightDark(background-color, #FFF, #222);
|
||||||
.content {
|
.content {
|
||||||
font-size: 0.666em;
|
font-size: 0.666em;
|
||||||
|
padding: $-m $-s;
|
||||||
p, ul, ol {
|
p, ul, ol {
|
||||||
font-size: $fs-m;
|
font-size: $fs-m;
|
||||||
margin: .5em 0;
|
margin: .5em 0;
|
||||||
@ -700,6 +701,7 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
|
|||||||
|
|
||||||
.comment-box .header {
|
.comment-box .header {
|
||||||
border-bottom: 1px solid #DDD;
|
border-bottom: 1px solid #DDD;
|
||||||
|
padding: $-s;
|
||||||
@include lightDark(border-color, #DDD, #000);
|
@include lightDark(border-color, #DDD, #000);
|
||||||
button {
|
button {
|
||||||
font-size: .8rem;
|
font-size: .8rem;
|
||||||
@ -710,6 +712,9 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
|
|||||||
.text-muted {
|
.text-muted {
|
||||||
color: #999;
|
color: #999;
|
||||||
}
|
}
|
||||||
|
.meta a, .meta span {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
.right-meta .text-muted {
|
.right-meta .text-muted {
|
||||||
opacity: .8;
|
opacity: .8;
|
||||||
}
|
}
|
||||||
@ -735,6 +740,24 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.comment-container-compact .comment-box {
|
||||||
|
.meta {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
padding: $-xs;
|
||||||
|
}
|
||||||
|
.right-meta {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
padding: $-xs $-s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.comment-container-compact .comment-thread-indicator {
|
||||||
|
width: $-m;
|
||||||
|
}
|
||||||
|
|
||||||
#tag-manager .drag-card {
|
#tag-manager .drag-card {
|
||||||
max-width: 500px;
|
max-width: 500px;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<div component="page-comment"
|
<div component="{{ $readOnly ? '' : 'page-comment' }}"
|
||||||
option:page-comment:comment-id="{{ $comment->id }}"
|
option:page-comment:comment-id="{{ $comment->id }}"
|
||||||
option:page-comment:comment-local-id="{{ $comment->local_id }}"
|
option:page-comment:comment-local-id="{{ $comment->local_id }}"
|
||||||
option:page-comment:comment-parent-id="{{ $comment->parent_id }}"
|
option:page-comment:comment-parent-id="{{ $comment->parent_id }}"
|
||||||
@ -6,12 +6,15 @@
|
|||||||
option:page-comment:deleted-text="{{ trans('entities.comment_deleted_success') }}"
|
option:page-comment:deleted-text="{{ trans('entities.comment_deleted_success') }}"
|
||||||
id="comment{{$comment->local_id}}"
|
id="comment{{$comment->local_id}}"
|
||||||
class="comment-box">
|
class="comment-box">
|
||||||
<div class="header p-s">
|
<div class="header">
|
||||||
<div class="flex-container-row justify-space-between wrap">
|
<div class="flex-container-row wrap items-center gap-x-xs">
|
||||||
<div class="meta text-muted flex-container-row items-center">
|
@if ($comment->createdBy)
|
||||||
|
<div>
|
||||||
|
<img width="50" src="{{ $comment->createdBy->getAvatar(50) }}" class="avatar block mx-xs" alt="{{ $comment->createdBy->name }}">
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
<div class="meta text-muted flex-container-row wrap items-center flex">
|
||||||
@if ($comment->createdBy)
|
@if ($comment->createdBy)
|
||||||
<img width="50" src="{{ $comment->createdBy->getAvatar(50) }}" class="avatar mx-xs" alt="{{ $comment->createdBy->name }}">
|
|
||||||
|
|
||||||
<a href="{{ $comment->createdBy->getProfileUrl() }}">{{ $comment->createdBy->getShortName(16) }}</a>
|
<a href="{{ $comment->createdBy->getProfileUrl() }}">{{ $comment->createdBy->getShortName(16) }}</a>
|
||||||
@else
|
@else
|
||||||
{{ trans('common.deleted_user') }}
|
{{ trans('common.deleted_user') }}
|
||||||
@ -25,6 +28,7 @@
|
|||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<div class="right-meta flex-container-row justify-flex-end items-center px-s">
|
<div class="right-meta flex-container-row justify-flex-end items-center px-s">
|
||||||
|
@if(!$readOnly && (userCan('comment-create-all') || userCan('comment-update', $comment) || userCan('comment-delete', $comment)))
|
||||||
<div class="actions mr-s">
|
<div class="actions mr-s">
|
||||||
@if(userCan('comment-create-all'))
|
@if(userCan('comment-create-all'))
|
||||||
<button refs="page-comment@reply-button" type="button" class="text-button text-muted hover-underline p-xs">@icon('reply') {{ trans('common.reply') }}</button>
|
<button refs="page-comment@reply-button" type="button" class="text-button text-muted hover-underline p-xs">@icon('reply') {{ trans('common.reply') }}</button>
|
||||||
@ -50,6 +54,7 @@
|
|||||||
•
|
•
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
@endif
|
||||||
<div>
|
<div>
|
||||||
<a class="bold text-muted" href="#comment{{$comment->local_id}}">#{{$comment->local_id}}</a>
|
<a class="bold text-muted" href="#comment{{$comment->local_id}}">#{{$comment->local_id}}</a>
|
||||||
</div>
|
</div>
|
||||||
@ -58,7 +63,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div refs="page-comment@content-container" class="content px-m py-s">
|
<div refs="page-comment@content-container" class="content">
|
||||||
@if ($comment->parent_id)
|
@if ($comment->parent_id)
|
||||||
<p class="comment-reply mb-xxs">
|
<p class="comment-reply mb-xxs">
|
||||||
<a class="text-muted text-small" href="#comment{{ $comment->parent_id }}">@icon('reply'){{ trans('entities.comment_in_reply_to', ['commentId' => '#' . $comment->parent_id]) }}</a>
|
<a class="text-muted text-small" href="#comment{{ $comment->parent_id }}">@icon('reply'){{ trans('entities.comment_in_reply_to', ['commentId' => '#' . $comment->parent_id]) }}</a>
|
||||||
@ -67,7 +72,7 @@
|
|||||||
{!! $comment->html !!}
|
{!! $comment->html !!}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if(userCan('comment-update', $comment))
|
@if(!$readOnly && userCan('comment-update', $comment))
|
||||||
<form novalidate refs="page-comment@form" hidden class="content pt-s px-s block">
|
<form novalidate refs="page-comment@form" hidden class="content pt-s px-s block">
|
||||||
<div class="form-group description-input">
|
<div class="form-group description-input">
|
||||||
<textarea refs="page-comment@input" name="markdown" rows="3" placeholder="{{ trans('entities.comment_placeholder') }}">{{ $comment->text }}</textarea>
|
<textarea refs="page-comment@input" name="markdown" rows="3" placeholder="{{ trans('entities.comment_placeholder') }}">{{ $comment->text }}</textarea>
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
<div refs="page-comments@commentContainer" class="comment-container">
|
<div refs="page-comments@commentContainer" class="comment-container">
|
||||||
@foreach($commentTree->get() as $branch)
|
@foreach($commentTree->get() as $branch)
|
||||||
@include('comments.comment-branch', ['branch' => $branch])
|
@include('comments.comment-branch', ['branch' => $branch, 'readOnly' => false])
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -7,6 +7,9 @@
|
|||||||
<button type="button" refs="editor-toolbox@tab-button" data-tab="files" title="{{ trans('entities.attachments') }}">@icon('attach')</button>
|
<button type="button" refs="editor-toolbox@tab-button" data-tab="files" title="{{ trans('entities.attachments') }}">@icon('attach')</button>
|
||||||
@endif
|
@endif
|
||||||
<button type="button" refs="editor-toolbox@tab-button" data-tab="templates" title="{{ trans('entities.templates') }}">@icon('template')</button>
|
<button type="button" refs="editor-toolbox@tab-button" data-tab="templates" title="{{ trans('entities.templates') }}">@icon('template')</button>
|
||||||
|
@if($comments->enabled())
|
||||||
|
<button type="button" refs="editor-toolbox@tab-button" data-tab="comments" title="{{ trans('entities.comments') }}">@icon('comment')</button>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div refs="editor-toolbox@tab-content" data-tab-content="tags" class="toolbox-tab-content">
|
<div refs="editor-toolbox@tab-content" data-tab-content="tags" class="toolbox-tab-content">
|
||||||
@ -26,7 +29,10 @@
|
|||||||
<div class="px-l">
|
<div class="px-l">
|
||||||
@include('pages.parts.template-manager', ['page' => $page, 'templates' => $templates])
|
@include('pages.parts.template-manager', ['page' => $page, 'templates' => $templates])
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@if($comments->enabled())
|
||||||
|
@include('pages.parts.toolbox-comments')
|
||||||
|
@endif
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
15
resources/views/pages/parts/toolbox-comments.blade.php
Normal file
15
resources/views/pages/parts/toolbox-comments.blade.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<div refs="editor-toolbox@tab-content" data-tab-content="comments" class="toolbox-tab-content">
|
||||||
|
<h4>{{ trans('entities.comments') }}</h4>
|
||||||
|
|
||||||
|
<div class="comment-container-compact px-l">
|
||||||
|
<p class="text-muted small mb-m">
|
||||||
|
{{ trans('entities.comment_editor_explain') }}
|
||||||
|
</p>
|
||||||
|
@foreach($comments->get() as $branch)
|
||||||
|
@include('comments.comment-branch', ['branch' => $branch, 'readOnly' => true])
|
||||||
|
@endforeach
|
||||||
|
@if($comments->empty())
|
||||||
|
<p class="italic text-muted">{{ trans('common.no_items') }}</p>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -135,4 +135,14 @@ class CommentTest extends TestCase
|
|||||||
$respHtml->assertElementCount('.comment-branch', 4);
|
$respHtml->assertElementCount('.comment-branch', 4);
|
||||||
$respHtml->assertElementContains('.comment-branch .comment-branch', 'My nested comment');
|
$respHtml->assertElementContains('.comment-branch .comment-branch', 'My nested comment');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_comments_are_visible_in_the_page_editor()
|
||||||
|
{
|
||||||
|
$page = $this->entities->page();
|
||||||
|
|
||||||
|
$this->asAdmin()->postJson("/comment/$page->id", ['text' => 'My great comment to see in the editor']);
|
||||||
|
|
||||||
|
$respHtml = $this->withHtml($this->get($page->getUrl('/edit')));
|
||||||
|
$respHtml->assertElementContains('.comment-box .content', 'My great comment to see in the editor');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user