Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions config/nested-comments.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<?php

use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;

return [
Expand Down Expand Up @@ -36,17 +35,6 @@
'allow-multiple-reactions' => env('ALLOW_MULTIPLE_REACTIONS', false), // Allow multiple reactions from the same user
'allow-guest-reactions' => env('ALLOW_GUEST_REACTIONS', false), // Allow guest users to react
'allow-guest-comments' => env('ALLOW_GUEST_COMMENTS', false), // Allow guest users to comment
'closures' => [
'getUserNameUsing' => fn (Authenticatable | Model $user) => $user->getAttribute('name'),
'getUserAvatarUsing' => fn (
Authenticatable | Model | string $user
) => app(\Coolsam\NestedComments\NestedComments::class)->geDefaultUserAvatar($user),
// 'getMentionsUsing' => fn (string $query) => app(\Coolsam\NestedComments\NestedComments::class)->getUserMentions($query), // Get mentions of all users in the DB
'getMentionsUsing' => fn (
string $query,
Model $commentable
) => app(\Coolsam\NestedComments\NestedComments::class)->getCurrentThreadUsers($query, $commentable),
],
'mentions' => [
'items-placeholder' => 'Search users by name or email address',
'empty-items-message' => 'No users found',
Expand Down
13 changes: 13 additions & 0 deletions resources/views/components/comment-card.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
@props([
'comment' => null,
])
@if ($comment?->getKey())
<livewire:nested-comments::comment-card
:key="$comment->getKey()"
:comment="$comment"
/>
@else
<p class="text-gray-500 dark:text-gray-400">
{{ __('No comment provided.') }}
</p>
@endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<x-dynamic-component :component="$getEntryWrapperView()" :entry="$entry">
<livewire:nested-comments::comment-card
:key="$entry->getKey()"
:comment="$getRecord()"
:user-avatar="$evaluateUserAvatar()"
:user-name="$evaluateUserName()"
/>
</x-dynamic-component>
6 changes: 3 additions & 3 deletions resources/views/livewire/comment-card.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
<div x-data="{showFullDate: false}" class="flex items-center space-x-2">
<x-filament::avatar
:src="$this->getAvatar()"
:alt="$this->comment->commentator"
:name="$this->comment->commentator"
:alt="$this->getCommentator()"
:name="$this->getCommentator()"
size="md"
:circular="false"
/>
<div x-on:mouseover="showFullDate = true" x-on:mouseout="showFullDate = false" class="cursor-pointer">
<p class="text-sm font-semibold text-gray-900 dark:text-white">
{{ $this->comment->commentator }}
{{ $this->getCommentator() }}
</p>
<p x-show="!showFullDate"
class="text-xs text-gray-500 dark:text-gray-400">
Expand Down
3 changes: 2 additions & 1 deletion resources/views/livewire/comments.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
@foreach($this->comments as $comment)
<livewire:nested-comments::comment-card
:key="$comment->getKey()"
:comment="$comment" />
:comment="$comment"
/>
@endforeach
<livewire:nested-comments::add-comment :commentable="$this->record" />
</x-filament::section>
55 changes: 53 additions & 2 deletions src/Concerns/HasComments.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,15 @@
use Coolsam\NestedComments\Models\Comment;
use Coolsam\NestedComments\NestedComments;
use Exception;
use FilamentTiptapEditor\Data\MentionItem;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Support\Collection;

use function auth;

/**
* @mixin Model
*/
Expand Down Expand Up @@ -97,7 +102,7 @@ public function editComment(Comment $comment, string $body, ?string $name = null
app(NestedComments::class)->setGuestName($name);
}

if (\auth()->check() && $comment->getAttribute('user_id') !== auth()->id()) {
if (auth()->check() && $comment->getAttribute('user_id') !== auth()->id()) {
throw new Exception('You are not authorized to edit this comment.');
}

Expand All @@ -123,7 +128,7 @@ public function deleteComment(Comment $comment): ?bool
throw new Exception('You must be logged in to edit your comment.');
}

if (\auth()->check() && $comment->getAttribute('user_id') !== auth()->id()) {
if (auth()->check() && $comment->getAttribute('user_id') !== auth()->id()) {
throw new Exception('You are not authorized to edit this comment.');
}

Expand All @@ -136,4 +141,50 @@ public function deleteComment(Comment $comment): ?bool

return $comment->delete();
}

final public function getUserNameUsing(Comment $comment): string
{
return $this->getUserName($comment->getAttribute('user'));
}

final public function getUserAvatarUsing(Comment $comment): ?string
{
$user = $comment->user ?? $comment->guest_name ?? 'Guest';

return $this->getUserAvatar($user);
}

public function getUserName(Model | Authenticatable | null $user): string
{
return app(NestedComments::class)->getUserName($user);
}

public function getUserAvatar(Model | Authenticatable | string | null $user): ?string
{
return app(NestedComments::class)->getDefaultUserAvatar($user);
}

/**
* @return array<int, MentionItem>
*/
public function getMentionsUsing(string $query): array
{
return $this->getMentionsQuery($query)
// ->where('username', 'like', "%{$query}%")
->take(50)
->get()
->map(function ($user) {
return new MentionItem(
id: $user->getKey(),
label: $this->getUserName($user),
image: $this->getUserAvatar($user),
roundedImage: true,
);
})->toArray();
}

public function getMentionsQuery(string $query): Builder
{
return app(NestedComments::class)->getUserMentionsQuery($query);
}
}
59 changes: 59 additions & 0 deletions src/Filament/Infolists/CommentCardEntry.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

namespace Coolsam\NestedComments\Filament\Infolists;

use Closure;
use Coolsam\NestedComments\Models\Comment;
use Coolsam\NestedComments\NestedComments;
use Filament\Infolists\Components\Entry;
use Illuminate\Database\Eloquent\Model;

class CommentCardEntry extends Entry
{
/** @phpstan-ignore-next-line */
protected string $view = 'nested-comments::filament.infolists.comment-card-entry';

protected bool | Closure $isLabelHidden = true;

protected string | Closure | null $userNameUsingClosure = null;

protected string | Closure | null $userAvatarUsingClosure = null;

protected array $columnSpan = ['default' => 'full'];

public static function make(?string $name = null): static
{
$name = $name ?? 'body';

return parent::make($name); // TODO: Change the autogenerated stub
}

public function getUserNameUsing(Closure | string | null $callback = null): static
{
$this->userNameUsingClosure = $callback;

return $this;
}

public function getUserAvatarUsing(Closure | string | null $callback = null): static
{
$this->userAvatarUsingClosure = $callback;

return $this;
}

public function evaluateUserAvatar(): ?string
{
return $this->evaluate($this->userAvatarUsingClosure
?? fn (Comment | Model $record) => app(NestedComments::class)
->getDefaultUserAvatar($record->getAttribute('user')
?? $record->getAttribute('guest_name') ?? 'Guest'));
}

public function evaluateUserName(): ?string
{
return $this->evaluate($this->userNameUsingClosure
?? fn (Comment | Model | null $record) => $record?->getAttribute('user')?->getAttribute('name')
?? $record->getAttribute('guest_name'));
}
}
30 changes: 23 additions & 7 deletions src/Livewire/AddComment.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

namespace Coolsam\NestedComments\Livewire;

use Coolsam\NestedComments\Concerns\HasComments;
use Coolsam\NestedComments\Models\Comment;
use Coolsam\NestedComments\NestedComments;
use Coolsam\NestedComments\NestedCommentsServiceProvider;
use Error;
use Exception;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Forms\Form;
Expand All @@ -30,10 +32,10 @@ class AddComment extends Component implements HasForms

public ?Comment $replyTo = null;

public function mount(?Model $commentable = null, ?Comment $replyTo = null): void
public function mount(?Model $commentable, ?Comment $replyTo): void
{
if (! $commentable) {
throw new \Error('The $commentable property is required.');
throw new Error('The $commentable property is required.');
}
$this->commentable = $commentable;
$this->replyTo = $replyTo;
Expand All @@ -43,15 +45,20 @@ public function mount(?Model $commentable = null, ?Comment $replyTo = null): voi
public function getCommentable(): Model
{
if (! $this->commentable) {
throw new \Error('The $commentable property is required.');
throw new Error('The $commentable property is required.');
}

return $this->commentable;
}

public function form(Form $form): Form
{
$mentionsClosure = config('nested-comments.closures.getMentionsUsing', fn (string $query, Model $commentable) => app(NestedComments::class)->getUserMentions($query));
/**
* @var Model<HasComments>|HasComments $commentable
*
* @phpstan-ignore-next-line
*/
$commentable = $this->getCommentable();

return $form
->schema([
Expand All @@ -61,7 +68,11 @@ public function form(Form $form): Form
->extraInputAttributes(['style' => 'min-height: 12rem;'])
->mentionItemsPlaceholder(config('nested-comments.mentions.items-placeholder', __('Search users by name or email address')))
->emptyMentionItemsMessage(config('nested-comments.mentions.empty-items-message', __('No users found')))
->getMentionItemsUsing(fn (string $query) => $mentionsClosure($query, $this->getCommentable()))
/**
* @phpstan-ignore-next-line
*/
->getMentionItemsUsing(fn (string $query) => $commentable->getMentionsUsing($query))
->maxContentWidth('full')
->required()
->autofocus(),
])
Expand All @@ -70,12 +81,17 @@ public function form(Form $form): Form
}

/**
* @throws \Exception
* @throws Exception
*/
public function create(): void
{
$data = $this->form->getState();

/**
* @var Model<HasComments>|HasComments $commentable
*
* @phpstan-ignore-next-line
*/
$commentable = $this->getCommentable();

/**
Expand Down
27 changes: 25 additions & 2 deletions src/Livewire/CommentCard.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,30 @@

use Coolsam\NestedComments\Models\Comment;
use Coolsam\NestedComments\NestedCommentsServiceProvider;
use Error;
use Filament\Support\Concerns\EvaluatesClosures;
use Livewire\Component;

class CommentCard extends Component
{
use EvaluatesClosures;

public ?Comment $comment = null;

public bool $showReplies = false;

public ?string $userAvatar = null;

public ?string $userName = null;

protected $listeners = [
'refresh' => 'refreshReplies',
];

public function mount(?Comment $comment = null): void
{
if (! $comment) {
throw new \Error('The $comment property is required.');
throw new Error('The $comment property is required.');
}

$this->comment = $comment;
Expand Down Expand Up @@ -48,6 +56,21 @@ public function getAvatar()
return '';
}

return call_user_func(config('nested-comments.closures.getUserAvatarUsing'), $this->comment->commentator);
/**
* @phpstan-ignore-next-line
*/
return $this->comment->commentable?->getUserAvatarUsing($this->comment);
}

public function getCommentator(): string
{
if (! $this->comment) {
return '';
}

/**
* @phpstan-ignore-next-line
*/
return $this->comment->commentable?->getUserNameUsing($this->comment);
}
}
1 change: 1 addition & 0 deletions src/Livewire/Comments.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class Comments extends Component
public function mount(): void
{
$this->comments = collect();

if (! $this->record) {
throw new \Error('Record model (Commentable) is required');
}
Expand Down
4 changes: 0 additions & 4 deletions src/Models/Comment.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ public function user(): BelongsTo

public function getCommentatorAttribute()
{
if ($this->user) {
return call_user_func(config('nested-comments.closures.getUserNameUsing'), $this->user);
}

return $this->getAttribute('guest_name');
}

Expand Down
Loading