Skip to content

Commit 8bdf948

Browse files
committed
Comments: Added archive endpoints, messages, Js actions and tests
1 parent e8f4418 commit 8bdf948

File tree

9 files changed

+155
-1
lines changed

9 files changed

+155
-1
lines changed

app/Activity/CommentRepo.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,33 @@ public function update(Comment $comment, string $html): Comment
5353
return $comment;
5454
}
5555

56+
57+
/**
58+
* Archive an existing comment.
59+
*/
60+
public function archive(Comment $comment): Comment
61+
{
62+
$comment->archived = true;
63+
$comment->save();
64+
65+
ActivityService::add(ActivityType::COMMENT_UPDATE, $comment);
66+
67+
return $comment;
68+
}
69+
70+
/**
71+
* Un-archive an existing comment.
72+
*/
73+
public function unarchive(Comment $comment): Comment
74+
{
75+
$comment->archived = false;
76+
$comment->save();
77+
78+
ActivityService::add(ActivityType::COMMENT_UPDATE, $comment);
79+
80+
return $comment;
81+
}
82+
5683
/**
5784
* Delete a comment from the system.
5885
*/

app/Activity/Controllers/CommentController.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,42 @@ public function update(Request $request, int $commentId)
7575
]);
7676
}
7777

78+
/**
79+
* Mark a comment as archived.
80+
*/
81+
public function archive(int $id)
82+
{
83+
$comment = $this->commentRepo->getById($id);
84+
if (!userCan('comment-update', $comment) && !userCan('comment-delete', $comment)) {
85+
$this->showPermissionError();
86+
}
87+
88+
$this->commentRepo->archive($comment);
89+
90+
return view('comments.comment', [
91+
'comment' => $comment,
92+
'readOnly' => false,
93+
]);
94+
}
95+
96+
/**
97+
* Unmark a comment as archived.
98+
*/
99+
public function unarchive(int $id)
100+
{
101+
$comment = $this->commentRepo->getById($id);
102+
if (!userCan('comment-update', $comment) && !userCan('comment-delete', $comment)) {
103+
$this->showPermissionError();
104+
}
105+
106+
$this->commentRepo->unarchive($comment);
107+
108+
return view('comments.comment', [
109+
'comment' => $comment,
110+
'readOnly' => false,
111+
]);
112+
}
113+
78114
/**
79115
* Delete a comment from the system.
80116
*/

lang/en/common.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
'create' => 'Create',
3131
'update' => 'Update',
3232
'edit' => 'Edit',
33+
'archive' => 'Archive',
34+
'unarchive' => 'Un-Archive',
3335
'sort' => 'Sort',
3436
'move' => 'Move',
3537
'copy' => 'Copy',

lang/en/entities.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,8 @@
402402
'comment_deleted_success' => 'Comment deleted',
403403
'comment_created_success' => 'Comment added',
404404
'comment_updated_success' => 'Comment updated',
405+
'comment_archive_success' => 'Comment archived',
406+
'comment_unarchive_success' => 'Comment un-archived',
405407
'comment_view' => 'View comment',
406408
'comment_jump_to_thread' => 'Jump to thread',
407409
'comment_delete_confirm' => 'Are you sure you want to delete this comment?',

resources/icons/archive.svg

Lines changed: 1 addition & 0 deletions
Loading

resources/js/components/page-comment.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export class PageComment extends Component {
88
protected commentLocalId: string;
99
protected deletedText: string;
1010
protected updatedText: string;
11+
protected archiveText: string;
1112

1213
protected wysiwygEditor: any = null;
1314
protected wysiwygLanguage: string;
@@ -20,14 +21,16 @@ export class PageComment extends Component {
2021
protected editButton: HTMLElement;
2122
protected deleteButton: HTMLElement;
2223
protected replyButton: HTMLElement;
24+
protected archiveButton: HTMLElement;
2325
protected input: HTMLInputElement;
2426

2527
setup() {
2628
// Options
2729
this.commentId = this.$opts.commentId;
2830
this.commentLocalId = this.$opts.commentLocalId;
2931
this.deletedText = this.$opts.deletedText;
30-
this.updatedText = this.$opts.updatedText;
32+
this.deletedText = this.$opts.deletedText;
33+
this.archiveText = this.$opts.archiveText;
3134

3235
// Editor reference and text options
3336
this.wysiwygLanguage = this.$opts.wysiwygLanguage;
@@ -41,6 +44,7 @@ export class PageComment extends Component {
4144
this.editButton = this.$refs.editButton;
4245
this.deleteButton = this.$refs.deleteButton;
4346
this.replyButton = this.$refs.replyButton;
47+
this.archiveButton = this.$refs.archiveButton;
4448
this.input = this.$refs.input as HTMLInputElement;
4549

4650
this.setupListeners();
@@ -63,6 +67,10 @@ export class PageComment extends Component {
6367
if (this.deleteButton) {
6468
this.deleteButton.addEventListener('click', this.delete.bind(this));
6569
}
70+
71+
if (this.archiveButton) {
72+
this.archiveButton.addEventListener('click', this.archive.bind(this));
73+
}
6674
}
6775

6876
protected toggleEditMode(show: boolean) : void {
@@ -126,6 +134,15 @@ export class PageComment extends Component {
126134
window.$events.success(this.deletedText);
127135
}
128136

137+
protected async archive(): Promise<void> {
138+
this.showLoading();
139+
const isArchived = this.archiveButton.dataset.isArchived === 'true';
140+
141+
await window.$http.put(`/comment/${this.commentId}/${isArchived ? 'unarchive' : 'archive'}`);
142+
this.$emit('archive');
143+
window.$events.success(this.archiveText);
144+
}
145+
129146
protected showLoading(): HTMLElement {
130147
const loading = getLoading();
131148
loading.classList.add('px-l');

resources/views/comments/comment.blade.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
option:page-comment:comment-local-id="{{ $comment->local_id }}"
77
option:page-comment:updated-text="{{ trans('entities.comment_updated_success') }}"
88
option:page-comment:deleted-text="{{ trans('entities.comment_deleted_success') }}"
9+
option:page-comment:archive-text="{{ $comment->archived ? trans('entities.comment_unarchive_success') : trans('entities.comment_archive_success') }}"
910
option:page-comment:wysiwyg-language="{{ $locale->htmlLang() }}"
1011
option:page-comment:wysiwyg-text-direction="{{ $locale->htmlDirection() }}"
1112
id="comment{{$comment->local_id}}"
@@ -37,6 +38,12 @@ class="comment-box">
3738
@if(userCan('comment-create-all'))
3839
<button refs="page-comment@reply-button" type="button" class="text-button text-muted hover-underline text-small p-xs">@icon('reply') {{ trans('common.reply') }}</button>
3940
@endif
41+
@if(userCan('comment-update', $comment) || userCan('comment-delete', $comment))
42+
<button refs="page-comment@archive-button"
43+
type="button"
44+
data-is-archived="{{ $comment->archived ? 'true' : 'false' }}"
45+
class="text-button text-muted hover-underline text-small p-xs">@icon('archive') {{ trans('common.' . ($comment->archived ? 'unarchive' : 'archive')) }}</button>
46+
@endif
4047
@if(userCan('comment-update', $comment))
4148
<button refs="page-comment@edit-button" type="button" class="text-button text-muted hover-underline text-small p-xs">@icon('edit') {{ trans('common.edit') }}</button>
4249
@endif

routes/web.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@
179179

180180
// Comments
181181
Route::post('/comment/{pageId}', [ActivityControllers\CommentController::class, 'savePageComment']);
182+
Route::put('/comment/{id}/archive', [ActivityControllers\CommentController::class, 'archive']);
183+
Route::put('/comment/{id}/unarchive', [ActivityControllers\CommentController::class, 'unarchive']);
182184
Route::put('/comment/{id}', [ActivityControllers\CommentController::class, 'update']);
183185
Route::delete('/comment/{id}', [ActivityControllers\CommentController::class, 'destroy']);
184186

tests/Entity/CommentTest.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,66 @@ public function test_comment_delete()
106106
$this->assertActivityExists(ActivityType::COMMENT_DELETE);
107107
}
108108

109+
public function test_comment_archive_and_unarchive()
110+
{
111+
$this->asAdmin();
112+
$page = $this->entities->page();
113+
114+
$comment = Comment::factory()->make();
115+
$page->comments()->save($comment);
116+
$comment->refresh();
117+
118+
$this->put("/comment/$comment->id/archive");
119+
120+
$this->assertDatabaseHas('comments', [
121+
'id' => $comment->id,
122+
'archived' => true,
123+
]);
124+
125+
$this->assertActivityExists(ActivityType::COMMENT_UPDATE);
126+
127+
$this->put("/comment/$comment->id/unarchive");
128+
129+
$this->assertDatabaseHas('comments', [
130+
'id' => $comment->id,
131+
'archived' => false,
132+
]);
133+
134+
$this->assertActivityExists(ActivityType::COMMENT_UPDATE);
135+
}
136+
137+
public function test_archive_endpoints_require_delete_or_edit_permissions()
138+
{
139+
$viewer = $this->users->viewer();
140+
$page = $this->entities->page();
141+
142+
$comment = Comment::factory()->make();
143+
$page->comments()->save($comment);
144+
$comment->refresh();
145+
146+
$endpoints = ["/comment/$comment->id/archive", "/comment/$comment->id/unarchive"];
147+
148+
foreach ($endpoints as $endpoint) {
149+
$resp = $this->actingAs($viewer)->put($endpoint);
150+
$this->assertPermissionError($resp);
151+
}
152+
153+
$this->permissions->grantUserRolePermissions($viewer, ['comment-delete-all']);
154+
155+
foreach ($endpoints as $endpoint) {
156+
$resp = $this->actingAs($viewer)->put($endpoint);
157+
$resp->assertOk();
158+
}
159+
160+
$this->permissions->removeUserRolePermissions($viewer, ['comment-delete-all']);
161+
$this->permissions->grantUserRolePermissions($viewer, ['comment-update-all']);
162+
163+
foreach ($endpoints as $endpoint) {
164+
$resp = $this->actingAs($viewer)->put($endpoint);
165+
$resp->assertOk();
166+
}
167+
}
168+
109169
public function test_scripts_cannot_be_injected_via_comment_html()
110170
{
111171
$page = $this->entities->page();

0 commit comments

Comments
 (0)