Giving a record a future date was recorded as "unpublished", and announced to webhooks as such. The history now compares before and after. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
129 lines
5.1 KiB
PHP
129 lines
5.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Filament\RelationManagers;
|
|
|
|
use App\Models\Revision;
|
|
use Filament\Actions\Action;
|
|
use Filament\Notifications\Notification;
|
|
use Filament\Resources\RelationManagers\RelationManager;
|
|
use Filament\Tables\Columns\TextColumn;
|
|
use Filament\Tables\Filters\SelectFilter;
|
|
use Filament\Tables\Table;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Support\Facades\Auth;
|
|
|
|
/**
|
|
* Who changed what, on the record it happened to.
|
|
*
|
|
* One class for every resource: the history of a page and the history of a
|
|
* testimonial differ only in what is in them.
|
|
*/
|
|
class RevisionsRelationManager extends RelationManager
|
|
{
|
|
protected static string $relationship = 'revisions';
|
|
|
|
public static function getTitle(Model $ownerRecord, string $pageClass): string
|
|
{
|
|
return __('panel.revisions.title');
|
|
}
|
|
|
|
public static function getBadge(Model $ownerRecord, string $pageClass): ?string
|
|
{
|
|
$count = $ownerRecord->revisions()->count();
|
|
|
|
return $count > 0 ? (string) $count : null;
|
|
}
|
|
|
|
public function table(Table $table): Table
|
|
{
|
|
return $table
|
|
->defaultSort('id', 'desc')
|
|
->modifyQueryUsing(fn ($query) => $query->with('user'))
|
|
->columns([
|
|
TextColumn::make('event')
|
|
->label(__('panel.revisions.fields.event'))
|
|
->badge()
|
|
->formatStateUsing(fn (string $state) => __("panel.revisions.events.{$state}"))
|
|
// Publishing is a separate permission because it is a
|
|
// bigger act than editing; it reads differently here too.
|
|
->color(fn (string $state) => match ($state) {
|
|
'published' => 'success',
|
|
'unpublished' => 'warning',
|
|
'scheduled' => 'info',
|
|
'created' => 'info',
|
|
'deleted', 'erased' => 'danger',
|
|
default => 'gray',
|
|
}),
|
|
|
|
TextColumn::make('user_name')
|
|
->label(__('panel.revisions.fields.author'))
|
|
->state(fn (Revision $record) => $record->author()),
|
|
|
|
TextColumn::make('changeset')
|
|
->label(__('panel.revisions.fields.fields'))
|
|
->state(fn (Revision $record) => $record->fields())
|
|
->badge()
|
|
->color('gray')
|
|
->limitList(4)
|
|
->placeholder('—'),
|
|
|
|
TextColumn::make('created_at')
|
|
->label(__('panel.revisions.fields.when'))
|
|
->since()
|
|
->dateTimeTooltip()
|
|
->sortable(),
|
|
])
|
|
->filters([
|
|
SelectFilter::make('event')
|
|
->label(__('panel.revisions.fields.event'))
|
|
->options(fn () => collect(['created', 'updated', 'published', 'scheduled', 'unpublished', 'deleted', 'restored', 'erased'])
|
|
->mapWithKeys(fn (string $e) => [$e => __("panel.revisions.events.{$e}")])
|
|
->all()),
|
|
])
|
|
->recordActions([
|
|
Action::make('diff')
|
|
->label(__('panel.revisions.actions.diff'))
|
|
->icon('heroicon-o-eye')
|
|
->modalHeading(fn (Revision $record) => __('panel.revisions.diff_heading', [
|
|
'author' => $record->author(),
|
|
'when' => $record->created_at?->isoFormat('LLL'),
|
|
]))
|
|
->modalSubmitAction(false)
|
|
->modalContent(fn (Revision $record) => view('filament.revisions.diff', [
|
|
'revision' => $record,
|
|
])),
|
|
|
|
Action::make('restore')
|
|
->label(__('panel.revisions.actions.restore'))
|
|
->icon('heroicon-o-arrow-uturn-left')
|
|
->color('warning')
|
|
->requiresConfirmation()
|
|
->modalDescription(__('panel.revisions.restore_confirm'))
|
|
->authorize(fn () => (bool) Auth::user()?->can('update', $this->getOwnerRecord()))
|
|
// Nothing to put back for a creation or a deletion, and
|
|
// the newest revision already is the current state.
|
|
->visible(fn (Revision $record) => filled($record->changeset)
|
|
&& $record->isNot($this->getOwnerRecord()->revisions()->first()))
|
|
->action(function (Revision $record): void {
|
|
$owner = $this->getOwnerRecord();
|
|
|
|
// Restoring is itself a change, so it lands in the
|
|
// history like any other — the way back is never lost.
|
|
$owner->forceFill($record->previousValues())->save();
|
|
|
|
Notification::make()
|
|
->title(__('panel.revisions.restored'))
|
|
->success()
|
|
->send();
|
|
}),
|
|
]);
|
|
}
|
|
|
|
public function isReadOnly(): bool
|
|
{
|
|
return true;
|
|
}
|
|
}
|