Skip to content

Commit d7cb5db

Browse files
authored
Added RenderableComment; Added pool option; (#13)
* Added renderable interface * Added L12 * Removed -dev * Added a proper way to rewrite the get comments function * Added pooling * Readme * Readme * Readme * Fixed test
1 parent 2f38dd0 commit d7cb5db

20 files changed

Lines changed: 461 additions & 85 deletions

.github/workflows/tests.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ jobs:
1212
fail-fast: true
1313
matrix:
1414
php: [8.3, 8.4]
15-
laravel: [11.*]
15+
laravel: [11.*, 12.*]
1616
include:
1717
- laravel: 11.*
1818
testbench: 9.*
19-
# - laravel: 12.*-dev
20-
# testbench: 10.*-dev
19+
- laravel: 12.*
20+
testbench: 10.*
2121

2222
name: Tests - PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }}
2323
steps:

README.md

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Commentions
1+
<h1 align="center">Commentions</h1>
22

33
![Laravel Supported Versions](https://img.shields.io/badge/laravel-10.x/11.x/12.x-green.svg)
44
[![run-tests](https://github.com/kirschbaum-development/commentions/actions/workflows/tests.yaml/badge.svg)](https://github.com/kirschbaum-development/commentions/actions/workflows/tests.yaml)
@@ -8,6 +8,8 @@
88

99
Commentions is a drop-in package for Filament that allows you to add comments to your resources. You can configure it so your users are mentionable in the comments, and it dispatches events so you can handle mentions in your own application however you like.
1010

11+
![](screenshots/comments.png)
12+
1113
## Installation
1214

1315
```bash
@@ -47,7 +49,9 @@ class Project extends Model implements Commentable
4749

4850
### Usage with Filament
4951

50-
1. And register the component in your Filament Infolists:
52+
There are a couple of ways to use Commentions with Filament.
53+
54+
1. Register the component in your Filament Infolists:
5155

5256
```php
5357
Infolists\Components\Section::make('Comments')
@@ -82,13 +86,11 @@ protected function getHeaderActions(): array
8286
}
8387
```
8488

85-
And that's it!
86-
87-
![](screenshots/comments.png)
89+
***
8890

8991
### Configuring the User model and the mentionables
9092

91-
If your `User` model lives in a different namespace than `App\Models\User`, you can configure it in the `config/commentions.php` file:
93+
If your `User` model lives in a different namespace than `App\Models\User`, you can configure it in `config/commentions.php`:
9294

9395
```php
9496
'commenter' => [
@@ -172,6 +174,41 @@ $comment->getMentioned()->each(function (Commenter $commenter) {
172174
});
173175
```
174176

177+
### Polling for new comments
178+
179+
Commentions supports polling for new comments. You can enable it by setting the `pollingEnabled` property to `true` and setting the `pollingInterval` property to the number of seconds between polls when you register the component.
180+
181+
```php
182+
Infolists\Components\Section::make('Comments')
183+
->schema([
184+
Livewire::make(Comments::class, [
185+
'pollingEnabled' => true,
186+
'pollingInterval' => 30, // optional, default is 60 seconds
187+
])
188+
]),
189+
```
190+
191+
### Rendering non-Comments in the list
192+
193+
Sometimes you might want to render non-Comments in the list of comments. For example, you might want to render when the status of a project is changed. For this, you can override the `getComments` method in your model, and return instances of the `Kirschbaum\Commentions\RenderableComment` data object.
194+
195+
```php
196+
use Kirschbaum\Commentions\RenderableComment;
197+
198+
public function getComments(): Collection
199+
{
200+
$statusHistory = $this->statusHistory()->get()->map(fn (StatusHistory $statusHistory) => new RenderableComment(
201+
authorName: $statusHistory->user->name,
202+
body: sprintf('Status changed from %s to %s', $statusHistory->old_status, $statusHistory->new_status),
203+
createdAt: $statusHistory->created_at,
204+
));
205+
206+
$comments = $this->comments()->latest()->with('author')->get();
207+
208+
return $statusHistory->merge($comments);
209+
}
210+
```
211+
175212
***
176213

177214
## Security

composer.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@
2626
"illuminate/support": "^11.0|^12.0",
2727
"illuminate/database": "^11.0|^12.0",
2828
"livewire/livewire": "^3.5",
29-
"filament/support": "^3.2"
29+
"filament/support": "^3.2",
30+
"filament/notifications": "^3.2",
31+
"filament/filament": "^3.2"
3032
},
3133
"extra": {
3234
"laravel": {

database/factories/CommentFactory.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ public function commentable(Commentable $commentable): self
3535
}
3636

3737
public function author(Commenter $author): self
38-
3938
{
4039
return $this->state(fn (array $attributes) => [
4140
'author_type' => $author->getMorphClass(),

resources/views/comment-list.blade.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
<div>
1+
<div
2+
@if ($pollingEnabled && $pollingInterval > 0)
3+
wire:poll.{{ $pollingInterval }}s
4+
@endif
5+
>
26
@if ($this->comments->isEmpty())
37
<div class="flex items-center justify-center p-6 text-center rounded-lg border border-dashed border-gray-300 dark:border-gray-700">
48
<div class="flex flex-col items-center gap-y-2">
@@ -16,7 +20,7 @@ class="w-8 h-8 text-gray-400 dark:text-gray-500"
1620

1721
@foreach ($this->comments as $comment)
1822
<livewire:commentions::comment
19-
:key="'comment-' . $comment->id"
23+
:key="'comment-' . $comment->getId()"
2024
:comment="$comment"
2125
:mentionables="$mentionables"
2226
/>

resources/views/comment.blade.php

Lines changed: 59 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,48 @@
1-
<div class="flex items-start gap-x-4 border p-4 rounded-lg shadow-sm mb-2" id="filament-comment-{{ $comment->id }}">
2-
<img
3-
src="{{ $comment->getAuthorAvatar() }}"
4-
alt="User Avatar"
5-
class="w-10 h-10 rounded-full mt-0.5 object-cover object-center"
6-
/>
1+
<div class="flex items-start gap-x-4 border p-4 rounded-lg shadow-sm mb-2" id="filament-comment-{{ $comment->getId() }}">
2+
@if ($avatar = $comment->getAuthorAvatar())
3+
<img
4+
src="{{ $comment->getAuthorAvatar() }}"
5+
alt="User Avatar"
6+
class="w-10 h-10 rounded-full mt-0.5 object-cover object-center"
7+
/>
8+
@else
9+
<div class="w-10 h-10 rounded-full mt-0.5 "></div>
10+
@endif
711

812
<div class="flex-1">
913
<div class="text-sm font-bold text-gray-900 dark:text-gray-100 flex justify-between items-center">
1014
<div>
11-
{{ $comment->author->name }}
15+
{{ $comment->getAuthorName() }}
1216
<span
1317
class="text-xs text-gray-500 dark:text-gray-300"
14-
title="Commented at {{ $comment->created_at->format('Y-m-d H:i:s') }}"
15-
>{{ $comment->created_at->diffForHumans() }}</span>
18+
title="Commented at {{ $comment->getCreatedAt()->format('Y-m-d H:i:s') }}"
19+
>{{ $comment->getCreatedAt()->diffForHumans() }}</span>
1620

17-
@if ($comment->updated_at->gt($comment->created_at))
21+
@if ($comment->getUpdatedAt()->gt($comment->getCreatedAt()))
1822
<span
1923
class="text-xs text-gray-300 ml-1"
20-
title="Edited at {{ $comment->updated_at->format('Y-m-d H:i:s') }}"
24+
title="Edited at {{ $comment->getUpdatedAt()->format('Y-m-d H:i:s') }}"
2125
>(edited)</span>
2226
@endif
2327
</div>
2428

25-
@if ($comment->isAuthor(Kirschbaum\Commentions\Config::resolveAuthenticatedUser()))
29+
@if ($comment->isComment() && $comment->canEdit())
2630
<div class="flex gap-x-1">
27-
<x-filament::icon-button
31+
{{-- <x-filament::icon-button
2832
icon="heroicon-s-pencil-square"
2933
wire:click="edit"
3034
size="xs"
3135
color="gray"
3236
/>
3337
34-
<x-filament::icon-button
35-
icon="heroicon-s-trash"
36-
wire:click="$dispatch('open-modal', { id: 'delete-comment-modal-{{ $comment->id }}' })"
37-
size="xs"
38-
color="gray"
39-
/>
38+
@if ($comment->canDelete())
39+
<x-filament::icon-button
40+
icon="heroicon-s-trash"
41+
wire:click="$dispatch('open-modal', { id: 'delete-comment-modal-{{ $comment->getId() }}' })"
42+
size="xs"
43+
color="gray"
44+
/>
45+
@endif --}}
4046
</div>
4147
@endif
4248
</div>
@@ -50,8 +56,8 @@ class="text-xs text-gray-300 ml-1"
5056
</div>
5157

5258
<div class="flex gap-x-2">
53-
<x-filament::button
54-
wire:click="updateComment({{ $comment->id }})"
59+
{{-- <x-filament::button
60+
wire:click="updateComment({{ $comment->getId() }})"
5561
size="sm"
5662
>
5763
Save
@@ -63,44 +69,45 @@ class="text-xs text-gray-300 ml-1"
6369
color="gray"
6470
>
6571
Cancel
66-
</x-filament::button>
72+
</x-filament::button> --}}
6773
</div>
6874
</div>
6975
@else
70-
<div class="mt-1 space-y-6 text-sm text-gray-800 dark:text-gray-200">{!! $comment->body_parsed !!}</div>
76+
<div class="mt-1 space-y-6 text-sm text-gray-800 dark:text-gray-200">{!! $comment->getParsedBody() !!}</div>
7177
@endif
7278
</div>
7379

74-
<x-filament::modal
75-
id="delete-comment-modal-{{ $comment->id }}"
76-
wire:model="showDeleteModal"
77-
width="sm"
78-
>
79-
<x-slot name="heading">
80-
Delete Comment
81-
</x-slot>
80+
@if ($comment->isComment() && $comment->canDelete())
81+
{{-- <x-filament::modal
82+
id="delete-comment-modal-{{ $comment->getId() }}"
83+
wire:model="showDeleteModal"
84+
width="sm"
85+
>
86+
<x-slot name="heading">
87+
Delete Comment
88+
</x-slot>
8289
83-
<div class="py-4">
84-
Are you sure you want to delete this comment? This action cannot be undone.
85-
</div>
86-
87-
<x-slot name="footer">
88-
<div class="flex justify-end gap-x-4">
89-
<x-filament::button
90-
wire:click="$dispatch('close-modal', { id: 'delete-comment-modal-{{ $comment->id }}' })"
91-
color="gray"
92-
>
93-
Cancel
94-
</x-filament::button>
95-
96-
<x-filament::button
97-
wire:click="delete"
98-
color="danger"
99-
>
100-
Delete
101-
</x-filament::button>
90+
<div class="py-4">
91+
Are you sure you want to delete this comment? This action cannot be undone.
10292
</div>
103-
</x-slot>
104-
</x-filament::modal>
10593
94+
<x-slot name="footer">
95+
<div class="flex justify-end gap-x-4">
96+
<x-filament::button
97+
wire:click="$dispatch('close-modal', { id: 'delete-comment-modal-{{ $comment->getId() }}' })"
98+
color="gray"
99+
>
100+
Cancel
101+
</x-filament::button>
102+
103+
<x-filament::button
104+
wire:click="delete"
105+
color="danger"
106+
>
107+
Delete
108+
</x-filament::button>
109+
</div>
110+
</x-slot>
111+
</x-filament::modal> --}}
112+
@endif
106113
</div>

resources/views/comments.blade.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,7 @@
3030
<livewire:commentions::comment-list
3131
:record="$record"
3232
:mentionables="$this->mentions"
33+
:polling-enabled="$this->pollingEnabled"
34+
:polling-interval="$this->pollingInterval"
3335
/>
3436
</div>

0 commit comments

Comments
 (0)