thettler/filament-activity-viewer
A Filament plugin for browsing activity logs inside your admin panel. Inspect model changes recorded by spatie/laravel-activitylog, filter by event, subject, or causer, and review old and new values in a clean, native-looking interface.
Install and wire up in under five minutes. The package is a Filament plugin that surfaces spatie/laravel-activitylog records inside a panel, so start by confirming both halves are present:
composer require thettler/filament-activity-viewer
php artisan vendor:publish --provider="Spatie\Activitylog\ActivitylogServiceProvider" --tag="activitylog-migrations"
php artisan migrate
Then register the plugin on the panel you actually want the audit trail in — not AdminPanelProvider by reflex, but the panel whose users need to see who changed what:
public function panel(Panel $panel): Panel
{
return $panel
// ...
->plugin(ActivityViewerPlugin::make());
}
Where to look first. Because this is a 0.0.x package, the source is more trustworthy than the docs. Read, in order: README.md, src/*Plugin.php (the registration entry point and any ->navigationGroup() / ->authorize() style builder methods), then composer.json for the Filament major it supports. Anything the README doesn't cover is usually a fluent setter on the plugin class.
First real use case. Don't start with a global "all activity" page — start narrow. Add LogsActivity to one model you already care about, log created/updated with logOnly(['status', 'assignee_id']), make a change in the UI, and confirm it appears. That single loop validates migrations, the plugin registration, the panel, and your trait config all at once. Only then widen to a full audit page.
Log deliberately, not exhaustively. The viewer is only as useful as what you feed it. logOnly() / logExcept() keep the properties payload readable — logging every attribute turns the detail view into a wall of noise and bloats the table.
use Spatie\Activitylog\Traits\LogsActivity;
class Order extends Model
{
use LogsActivity;
protected static $logOnlyDirty = true;
protected static $logAttributes = ['status', 'total', 'assignee_id'];
}
Attach a meaningful causer. In HTTP requests auth()->user() is picked up automatically, but queued jobs, console commands, and webhooks will silently produce causer_id = null rows. Wrap those paths with Activity::tapActivity() or ->causedBy($user) so the audit trail doesn't have holes exactly where the risky automated work happens.
Use the viewer in context, not just as a directory. The high-value pattern is per-record history: a relation manager or header action on the Order/User/Invoice resource that shows activity filtered to subject_type + subject_id. If the package ships a resource-only page, a small custom Filament page or modal action that reuses its table columns gets you the contextual view.
Scope to the tenant. For multi-tenant panels, filter the table by the causer's tenant (or a tenant_id you stamp into properties) — do this via a modifyQueryUsing() hook where the package exposes one, or a base query override. An unscoped audit page leaks other tenants' data by design.
Treat it as an incident tool. The day-to-day usage is usually reactive: "who changed this field and when." Optimise for that with a date-range filter defaulting to the last 7 days, search on description, and an event filter (created/updated/deleted). Pre-selecting sensible filters matters more than any extra feature.
Schedule pruning early. Activity tables grow fast. A weekly activitylog:clean (or a model-level ->where('created_at', '<', now()->subMonths(6))->delete()) belongs in routes/console.php from day one, with a retention window that matches your compliance obligations.
0.0.x means no backwards-compatibility promise. Pin the exact version ("thettler/filament-activity-viewer": "0.0.2") and read the diff before bumping. The v0.0.2 release notes are empty apart from a compare link — the commit diff is the only documentation of what changed, so review https://github.com/thettler/filament-activity-viewer/compare/v0.0.1...v0.0.2 before upgrading. Absent a meaningful changelog, assume nothing about stability.composer.json before you plan anything around it.Relation::enforceMorphMap(), historical rows keep storing the FQCN unless you've always used aliases — you'll see subject types that don't resolve and empty detail views on old records. Align the log config before you accumulate data.activity_log ships with indexes on subject and causer, but ordering by created_at across a large table is the common slow path. Add a created_at index if the page lags; eager-load causer to avoid N+1 on the list.canView() check — activity logs contain exactly the data you don't want broadly readable.php artisan filament:clear-cached-components / optimize:clear), plugin registered on the correct panel, migrations actually run on the right connection, and activitylog.enabled not disabled in config.0.0.x dependency, a local override of published views will drift on every release.How can I help you explore Laravel packages today?