Skip to content

About

Spatie Laravel activity logs inside of Filament.

Resources

Stars

0 stars

Watchers

0 watching

Forks

 
 

Repository files navigation

Filament Activitylog

A Filament panel plugin for browsing and restoring activity records written by spatie/laravel-activitylog. The package provides:

  • A registered ActivitylogResource with list and view pages.
  • Table columns for log name, event, subject, causer, properties, and timestamp.
  • Date, event, and log-name filters.
  • Optional restore actions for changed records and soft-deleted subjects.
  • An ActivitylogRelationManager for showing a model's activities inside its resource.
  • Timeline actions for showing recent activity in a slide-over.
  • Translatable labels and callbacks for custom dates, resources, and display names.

Package identity: Composer package nocs/filament-activitylog; PHP namespace Rmsramos\Activitylog; plugin ID rmsramos/activitylog.

Compatibility

The package source declares these Composer constraints:

  • PHP ^8.2
  • illuminate/contracts ^11.0 || ^12.0 || ^13.0
  • spatie/laravel-activitylog ^4.12.3
  • spatie/laravel-package-tools ^1.16

The implementation uses Filament 4 APIs (Panel, Resource, Schema, Table, actions, and infolists). Install it in an application whose Filament version matches those APIs. Filament itself is not listed as a direct Composer requirement in this repository, so the host application must provide it.

Installation

composer require nocs/filament-activitylog
php artisan activitylog:install
php artisan migrate

The package install command publishes this package's config and starts by publishing Spatie's activitylog-migrations. It does not run migrations automatically; run php artisan migrate after installation.

To publish files manually:

php artisan vendor:publish --tag=activitylog-config
php artisan vendor:publish --tag=activitylog-views
php artisan vendor:publish --provider="Spatie\Activitylog\ActivitylogServiceProvider" --tag=activitylog-migrations

The service provider registers the filament-activitylog config, activitylog views, translations, and the CSS asset. Laravel package discovery registers Rmsramos\Activitylog\ActivitylogServiceProvider automatically.

Record activities with Spatie

This plugin displays records; it does not replace Spatie's logging configuration. Add LogsActivity to models that should create records:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Spatie\Activitylog\LogOptions;
use Spatie\Activitylog\Traits\LogsActivity;

class NewsItem extends Model
{
    use LogsActivity;

    protected $fillable = ['name', 'text'];

    public function getActivitylogOptions(): LogOptions
    {
        return LogOptions::defaults()->logOnly(['name', 'text']);
    }
}

See Spatie's documentation for global configuration, subject/causer relationships, properties, batching, and logging options.

Register the plugin

Add the plugin to each Filament panel that should expose activity logs:

namespace App\Providers\Filament;

use Filament\Panel;
use Filament\PanelProvider;
use Rmsramos\Activitylog\ActivitylogPlugin;

class AdminPanelProvider extends PanelProvider
{
    public function panel(Panel $panel): Panel
    {
        return $panel
            ->plugins([
                ActivitylogPlugin::make(),
            ]);
    }
}

ActivitylogPlugin::make() resolves the plugin from the container. Its ID is rmsramos/activitylog, and registration adds the configured resource to the panel.

Configuration

The published config/filament-activitylog.php contains:

return [
    'resources' => [
        'label' => 'Activity Log',
        'plural_label' => 'Activity Logs',
        'hide_restore_action' => false,
        'restore_action_label' => 'Restore',
        'hide_resource_action' => false,
        'hide_restore_model_action' => true,
        'resource_action_label' => 'View',
        'navigation_item' => true,
        'navigation_group' => null,
        'navigation_icon' => 'heroicon-o-shield-check',
        'navigation_sort' => null,
        'default_sort_column' => 'id',
        'default_sort_direction' => 'desc',
        'navigation_count_badge' => false,
        'resource' => \Rmsramos\Activitylog\Resources\ActivitylogResource::class,
    ],
    'date_format' => 'd/m/Y',
    'datetime_format' => 'd/m/Y H:i:s',
];

default_sort_column and default_sort_direction are passed directly to Filament's defaultSort(). The source default is id/desc; set created_at explicitly if that is the desired ordering.

Plugin API

All setters return the plugin and can be chained. Values accepting Closure are evaluated by Filament, so they may depend on the current panel/user.

Method Purpose
resource(string $class) Replace the resource registered by the plugin.
`label(string Closure $label)/pluralLabel(...)`
`resourceActionLabel(string Closure $label)`
`isResourceActionHidden(bool Closure $hidden)`
`isRestoreActionHidden(bool Closure $hidden)`
`isRestoreModelActionHidden(bool Closure $hidden)`
`navigationItem(bool Closure $show = true)`
`navigationGroup(string Closure
navigationIcon(string $icon) / navigationSort(int $order) Set navigation icon/order.
navigationCountBadge(bool $show = true) Show the current activity count as a badge.
`authorize(bool Closure $callback = true)`
dateParser(?Closure $parser) Replace the default Carbon::parse() parser.
`dateFormat(string Closure
`datetimeFormat(string Closure
customizeDatetimeColumn(Closure $callback) Transform the created-at TextColumn.
customizeDatePicker(Closure $callback) Transform the two date-picker fields.
`translateSubject(string Closure
`translateLogKey(string Closure

Example:

ActivitylogPlugin::make()
    ->label('Log')
    ->pluralLabel('Logs')
    ->navigationGroup('Administration')
    ->navigationIcon('heroicon-o-shield-check')
    ->navigationSort(3)
    ->navigationCountBadge(true)
    ->authorize(fn () => auth()->user()?->can('viewActivityLog') === true)
    ->dateFormat('Y-m-d')
    ->datetimeFormat('Y-m-d H:i:s');

Authorization and policies

ActivitylogResource::canAccess() first checks whether the configured activity model has a policy with viewAny; when it does, the policy decides access. Otherwise it uses the plugin's authorize() callback. A callback that returns false prevents access.

For policy-driven access, register a policy for the configured activity model (normally Spatie\Activitylog\Models\Activity):

Gate::policy(\Spatie\Activitylog\Models\Activity::class, \App\Policies\ActivityPolicy::class);

Subject-resource view links additionally check the subject resource's update ability. Configure policies for the subject models if those links should be available.

Activity resource

The default resource is Rmsramos\Activitylog\Resources\ActivitylogResource, at slug activitylogs. It uses the configured Spatie activity model (config('activitylog.activity_model', Activity::class)) and registers:

  • ListActivitylog at /
  • ViewActivitylog at /{record}

The list query eager-loads subject (including soft-deleted subjects when supported) and causer.

Table columns

  • Log name: searchable, sortable, and rendered as a badge.
  • Event: searchable, sortable, translated, and colored (created, updated, deleted, restored, or a fallback color).
  • Subject: displays the model basename and ID; marks soft-deleted or missing subjects. It is hidden inside the relation manager.
  • Causer: displays firstname plus name when present; otherwise an em dash.
  • Properties: rendered by the package view and toggleable (hidden by default).
  • Created at: searchable, sortable, and formatted with datetimeFormat().

The built-in filters are a created-at range, a distinct-event select, and a distinct-log-name select.

Custom resource

Extend or replace the resource when you need custom columns, forms, pages, or permissions:

namespace App\Filament\Resources;

use Rmsramos\Activitylog\Resources\ActivitylogResource as BaseActivitylogResource;

class ActivitylogResource extends BaseActivitylogResource
{
    // Override table(), form(), getPages(), or authorization methods as needed.
}

Register it:

ActivitylogPlugin::make()->resource(\App\Filament\Resources\ActivitylogResource::class)

If you override getPages(), point the routes at page classes whose resource is your custom resource.

Restore behavior

There are two distinct restore paths:

  1. Restore activity attributes (restoreActivity($key)): reads properties.old, updates the subject inside activity()->withoutLogs(), then writes a new restored activity containing the prior/new properties.
  2. Restore a soft-deleted subject (restoreSubjectFromSoftDelete($record)): available only for a deleted activity whose subject supports trashed() and restore(), is currently trashed, and passes the subject's restore policy check. It runs in a database transaction, restores without logging the model's internal event, and writes a restored activity with restore metadata.

To expose soft-delete restoration, enable Spatie's soft-deleted subject support and turn on the plugin action:

// config/activitylog.php
'subject_returns_soft_deleted_models' => true,

// panel provider
ActivitylogPlugin::make()->isRestoreModelActionHidden(false)

The default is to hide this action. Restoration notifications are sent for missing records, missing properties, policy failures, success, and exceptions.

Relation manager

For a model using LogsActivity, add the relation manager to its Filament resource:

use Rmsramos\Activitylog\RelationManagers\ActivitylogRelationManager;

public static function getRelations(): array
{
    return [ActivitylogRelationManager::class];
}

The manager expects the relationship name activities, uses description as its record title, reuses the activity resource form/table, and exposes a ViewAction. Ensure the model has Spatie's activities relationship available.

Timeline actions

Two action classes share the same implementation:

  • ActivityLogTimelineTableAction — use in a table's actions.
  • ActivityLogTimelineSimpleAction — use anywhere a Filament action is accepted.
use Rmsramos\Activitylog\Actions\ActivityLogTimelineTableAction;

public static function table(Table $table): Table
{
    return $table->actions([
        ActivityLogTimelineTableAction::make('Activities'),
    ]);
}

The action opens a slide-over with the ten newest matching activities by default. It eager-loads subject and causer, includes soft-deleted subjects where supported, and renders event, causer, subject, description, properties, log name, and relative timestamp.

Timeline action API

Method Purpose
withRelations(?array $relations) Include activity subjects from the owner's named relationships. The action supports normal relationships and BelongsToMany.
limit(?int $limit = 10) Limit returned activities; null removes the limit if supported by the query builder.
`query(Closure Builder
modifyQueryUsing(Closure $callback) Modify the final builder before get().
activitiesUsing(Closure $callback) Supply a collection directly instead of querying.
modifyTitleUsing(Closure $callback) Customize timeline titles.
shouldModifyTitleUsing(Closure $callback) Decide when the title callback runs.
getTimelineIcons() / getTimelineIconColors() Read the event-to-icon and event-to-color maps used by the timeline view. The current source does not expose public setters for these maps.

The default event maps in source are created → heroicon-m-plus/success, updated → heroicon-m-pencil-square/warning, deleted → heroicon-m-trash/danger, and restored → heroicon-m-arrow-uturn-left/info.

Example:

ActivityLogTimelineTableAction::make('Activities')
    ->withRelations(['profile', 'address'])
    ->limit(30);

The current source stores default icon and color maps internally and exposes them through getTimelineIcons() and getTimelineIconColors(), but does not provide fluent setters for changing them.

Custom activity resources

When an activity subject is a wrapper/translation model rather than the model represented by a Filament resource, use HasCustomActivityResource and implement getFilamentActualResourceModel($record):

use Rmsramos\Activitylog\Traits\HasCustomActivityResource;

class TranslatableActivitySubject extends Model
{
    use HasCustomActivityResource;

    public function getFilamentActualResourceModel($record): Model
    {
        return $record->subject->translatable->resourceModel;
    }
}

The resource uses this model for subject URLs and update authorization. Without the trait, it derives a resource name by kebab-casing the subject class basename and pluralizing it.

Localization and dates

Translations ship under resources/lang for the locales present in the repository, including English, Brazilian Portuguese, German, Spanish, French, Persian, Arabic, Portuguese, Hebrew, Dutch, Latvian, and other locale variants. Set the application's locale normally; package strings use the activitylog:: translation namespace.

Subject names and property keys can be adapted to application language files:

ActivitylogPlugin::make()
    ->translateSubject(fn (string $label) => __("activity.subjects.{$label}"))
    ->translateLogKey(fn (string $key) => __("activity.fields.{$key}"));

For calendars or user-specific formatting:

ActivitylogPlugin::make()
    ->dateParser(fn ($date) => auth()->user()->isJalaliCalendar()
        ? \Morilog\Jalali\Jalalian::fromDateTime($date)
        : \Carbon\Carbon::parse($date))
    ->dateFormat(fn () => auth()->user()->getFilamentDateFormat())
    ->datetimeFormat(fn () => auth()->user()->getFilamentDateTimeFormat())
    ->customizeDatetimeColumn(fn ($column) => $column->when(
        auth()->user()->isJalaliCalendar(),
        fn ($column) => $column->jalaliDateTime(),
    ))
    ->customizeDatePicker(fn ($field) => $field->when(
        auth()->user()->isJalaliCalendar(),
        fn ($field) => $field->jalali(),
    ));

The date parser must return an object supporting format(). Invalid property date values are left unchanged by timeline formatting.

Development and verification

This repository contains no tests/ directory or automated test suite. Available Composer checks are:

composer install
composer analyse   # PHPStan
composer test      # Pest; currently has no repository tests
composer format    # Laravel Pint
composer build     # package discovery and Testbench workbench build

The only GitHub Actions workflow currently present is fix-php-code-style-issues.yml. It runs Laravel Pint on pushes that change PHP files and may commit formatting changes. CI does not currently run the PHPStan, Pest, or build commands above; run them locally when changing package behavior.

Source map

For a class-by-class inventory and source-derived behavior notes, see SOURCE-MAP.md.

Contributing and security

Please open issues and pull requests in the repository. Do not report security vulnerabilities in a public issue; use the repository's GitHub security policy.

License

MIT. See LICENSE.md.

About

Spatie Laravel activity logs inside of Filament.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages