Files
larablog/app/Filament/Resources/Articles/RelationManagers/CommentsRelationManager.php
T
gouki 3cec4c5e18
CI / PHPUnit (PHP 8.3) (push) Failing after 4s
CI / PHPUnit (PHP 8.2) (push) Failing after 1m9s
CI / Deploy (manual gate) (push) Skipped
wip: article AI polish, category SEO fields, cover generator, membership plan seeder
2026-09-07 18:48:37 +00:00

126 lines
5.1 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Filament\Resources\Articles\RelationManagers;
use App\Filament\Support\AdminTable;
use App\Models\Comment;
use Filament\Actions\CreateAction;
use Filament\Actions\DeleteAction;
use Filament\Actions\DeleteBulkAction;
use Filament\Actions\EditAction;
use Filament\Forms\Components\DateTimePicker;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Resources\RelationManagers\RelationManager;
use Filament\Schemas\Schema;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Model;
class CommentsRelationManager extends RelationManager
{
protected static string $relationship = 'comments';
public static function getTitle(Model $ownerRecord, string $pageClass): string
{
return __('admin.nav.comments');
}
public function form(Schema $schema): Schema
{
return $schema
->components([
TextInput::make('author')
->label(__('admin.fields.author'))
->required(),
TextInput::make('url')
->label(__('admin.fields.url'))
->url(),
Textarea::make('content')
->label(__('admin.fields.content'))
->required()
->columnSpanFull(),
Select::make('moderation_status')
->label(__('admin.fields.moderation_status'))
->options([
Comment::STATUS_PENDING => __('admin.options.moderation.pending'),
Comment::STATUS_PENDING_AI => __('admin.options.moderation.pending_ai'),
Comment::STATUS_APPROVED => __('admin.options.moderation.approved'),
Comment::STATUS_REJECTED => __('admin.options.moderation.rejected'),
Comment::STATUS_NEEDS_HUMAN => __('admin.options.moderation.needs_human'),
])
->required()
->default(Comment::STATUS_PENDING),
DateTimePicker::make('published_at')
->label(__('admin.fields.published_at')),
]);
}
public function table(Table $table): Table
{
return $table
->recordTitleAttribute('author')
->columns([
TextColumn::make('author')
->label(__('admin.fields.author'))
->searchable(),
AdminTable::ellipsis(
TextColumn::make('content')
->label(__('admin.fields.content'))
->html()
->formatStateUsing(fn (?string $state): string => trim(html_entity_decode(strip_tags((string) $state), ENT_QUOTES | ENT_HTML5, 'UTF-8'))),
),
TextColumn::make('moderation_status')
->label(__('admin.fields.moderation_status'))
->badge(),
TextColumn::make('published_at')
->label(__('admin.fields.published_at'))
->dateTime()
->sortable(),
])
->filters([
SelectFilter::make('moderation_status')
->label(__('admin.fields.moderation_status'))
->options([
Comment::STATUS_PENDING => __('admin.options.moderation.pending'),
Comment::STATUS_PENDING_AI => __('admin.options.moderation.pending_ai'),
Comment::STATUS_APPROVED => __('admin.options.moderation.approved'),
Comment::STATUS_REJECTED => __('admin.options.moderation.rejected'),
Comment::STATUS_NEEDS_HUMAN => __('admin.options.moderation.needs_human'),
]),
])
->headerActions([
CreateAction::make()
->mutateFormDataUsing(function (array $data): array {
$data['published_at'] ??= now();
$data['moderation_status'] ??= Comment::STATUS_PENDING;
return $data;
})
->after(function (): void {
$this->getOwnerRecord()->increment('comments_count');
}),
])
->recordActions([
EditAction::make(),
DeleteAction::make()
->after(function (): void {
$this->getOwnerRecord()->decrement('comments_count');
}),
])
->toolbarActions([
DeleteBulkAction::make()
->after(function (): void {
$this->getOwnerRecord()->forceFill([
'comments_count' => $this->getOwnerRecord()->comments()->count(),
])->save();
}),
])
->defaultSort('published_at', 'desc');
}
}