This package allows you to easily integrate beautiful timelines into your Filament app, including outside the admin panel, allowing you to display timelines with minimal effort. The package integrates Spatie Activitylog into Filament and it works out-of-the-box with the underlying activitylog. Therefore, this package is great way to get a premium activitylog in your app for new projects, but also for existing projects that already have recorded events using the Spatie Activitylog.
The package supports both form & infolist components, includes special actions for tables & pages, and allows you to easily extend the timelime with additional actions.
The timeline component will work out-of-the-box in any Filament form or infolist, also outside the admin panel. It looks like this:
As you see in the above image, placing the timeline inside a Section
works really well. The timeline looks great in dark mode also:
Another option would be to place the timeline directly on the page. This makes the timeline feel more 'supplemental' to the main content of the page:
All icons & colors in the timeline are fully customizable. You can also add actions to the timeline, including actions that can open modals. The actions will be displayed beneath each item in the timeline:
If you hover over a timestamp, you can see the exact date & time of the activity:
Next, you can also allow your users to search through the timeline. The searching is done all in the browser, so this will feel super-snappy 👌
The timeline has automatic support for displaying activities that were logged in batches (e.g. activities related to each other). These batches are by default shown as an indented, compact sub-timeline, but still connected to the main timeline.
However, you can also choose to display the batch inline with the main timeline. The items will now be merged with the main timeline:
The timeline also comes with a special compact design, which is especially useful when you have many activities. As you can see, the timeline is re-designed to occopy less space:
Of course, this looks great in dark mode as well:
If you want to limit the space used by the timeline even more, you can set a maximum height. The timeline will then become scrollable if the content exceeds the maximum height.
If there are no activities logged yet, the timeline will display an empty state. You can style the empty state as you wish, by providing a custom text, custom description and custom icon:
The package also provides a nice Timeline action that you can use in your tables & pages. For example, the page action can be placed in the getHeaderActions()
method, on the top-level or in an ActionGroup
:
The action also has a special version for use in tables:
Thank you for purchasing the Activitylog Pro plugin for Filament!
We tried to make the plugin as easy-to-install and versatile as possible. Nevertheless, if you still have a question or a feature request, please send an e-mail to support@ralphjsmit.com.
Before starting the further installation, you should already have the Spatie Activitylog package installed according to the Spatie Activitylog installation guide.
If you already have the Spatie Activitylog installed in your project and already recorded data, you can immediately proceed to the next step.
The package is supported on Laravel 10 or higher and Filament V3.
To install the package you should add the following lines to your composer.json
file in the repositories
key in order to get access to the private package:
{ "repositories": [ { "type": "composer", "url": "https://satis.ralphjsmit.com" } ]}
If you have one of my other premium packages installed already, then you don't need to repeat these lines.
Next, you should require the package via the command line. You will be prompted for your username (which is your e-mail) and your password (which is your license key, e.g. 8c21df8f-6273-4932-b4ba-8bcc723ef500
).
composer require ralphjsmit/laravel-filament-activitylog # You can also publish the translations if wanted:php artisan vendor:publish --tag="filament-activitylog-translations"
If you are installing the package in a Filament V2 installation, you should require the version
^0.1
.
tailwind.config.js
(required)For all panels that you want to use the package in, make sure that you have created a Filament custom theme. Next, for each theme, you need to add the following line to the tailwind.config.js
file:
content: [ // Your other files './vendor/ralphjsmit/laravel-filament-activitylog/resources/**/*.blade.php',],
If you are using the plugin outside the admin panel, then make sure to include the above line in the tailwind.config.js
's that are used to generate the CSS for the Livewire components where you will use the timeline in.
The Filament Activitylog Pro package works in all forms, tables & infolists, irrespective of whether you also have a Filament panel or not. This means that you can nicely include the Activitylog in your app, anywhere you want and wherever you have a form, table or infolist.
If you do decide to use the Filament Activitylog package in a panel, then you should register the plugin in the $panel
providers that you want to use the plugin in:
use RalphJSmit\Filament\Activitylog\FilamentActivitylog; $panel ->plugin(FilamentActivitylog::make())
There currently are no configuration methods on the plugin itself. However, it is best practice in Filament V3 to register plugins in the panels that a plugin is used in. Also, if it ever becomes necessary in the future to add per-panel configuration methods to the plugin, then I will be able to do so without needing a breaking change.
In general, the underlying spatie/laravel-activitylog
package allows two things:
For information about logging model events and how to set it up, see the Spatie documentation. I would recommend to enable logging these model events first, and using them as the basis of your timelines.
When logging custom activities, there are four main properties relevant to each activity log:
null
when no user was logged.created
, updated
, deleted
, restored
, but can also be custom events like published
, unpublished
, archived
, verified
, etc.It is required to always include an event name in the activity. For example, let's say that we want to log a 'published'
event on a Post
model. We can do this as follows:
$post = Post::find(1);$johnDoe = User::firstWhere('email', 'johndoe@example.com'); $post->touched('published_at'); activity() ->performedOn($post) ->causedBy($johnDoe) // Not necessary if there is an authenticated user. ->event('published') ->log('published'); // Keep log description identical to the event name, OR provide a custom description.
By default, this will show an item in the timeline with the following description:
John Doe published the post.
The name of the causer is automatically inferred from the causer model using following steps:
Filament\Models\Contracts\FilamentUser
contract, then the getFilamentName()
method will be used.name
, then this attribute will be used.first_name
and/or last_name
, then these attributes will be used.Alternatively, if you want to override the above logic, you can use the ->causerName()
and ->causerNames()
methods:
Timeline::make() ->causerName(User::class, fn (User $causer) => ...) ->causerNames([ User::class => fn (User $causer) => ..., ])
If you want to display a fallback causer name when the causer_type
/causer_id
columns are null
, you can pass null
as the first argument to the ->causerName()
method. This will allow you to use "System" or "Application" as fallback causer name for actions not attached to a user:
Timeline::make() ->causerName(null, 'System')
You can make the causer name a link by providing a closure to the ->causerUrl()
method. If your system has multiple types of causers, make sure to handle each type in the closure:
Timeline::make() ->causerUrl(function (User $causer) { return UserResource::getUrl('edit', ['record' => $causer]); })
Usually, the description of the activity (the string passed to the ->log('...')
method) will be the same as the event name. If that is the case, then the package will automatically construct a nice human-readable string.
If you want to log a custom description instead, you can do that as well:
activity() ->performedOn($post) ->event('published') ->log('This is a custom description');
Keep in mind though that this description is stored directly in the database and therefore also not translatable. If you want to use a custom description that is translatable, use the ->eventDescription()
method on the component instead (see below).
If you want, you can use inline markdown to apply formatting like bold or italic.
The Spatie Activitylog package allows you to log activity in batches. You can consider a batch as a group of actions that are performed together in one go. Each timeline can display the batches and the linked activities.
You can start a new batch as follows:
LogBatch::startBatch(); $post->touch('published_at');$post->tweet()->create(['content' => 'Check out my new blog post ✍️']);$post->draftPosts->each(fn (DraftPost $draftPost) => $draftPost->delete()); LogBatch::endBatch();
You can also start and end a batch using a closure, similar to a database transaction:
LogBatch::withinBatch(function () { // ...});
This is the basics about batches, but there are some gotchas relating to e.g. queue jobs. You can read more about that in the documentation.
The timeline form component can be used in your forms to display a timeline of the activities related to the current form record. The timeline will automatically be filled with the activities that happened to the current Eloquent model:
use RalphJSmit\Filament\Activitylog\Forms\Components\Timeline; Timeline::make() ->label('History'),
In general, you don't have data yet on pages where you create an item. Therefore, by default, the timeline will hide itself on pages where $operation === 'create'
, so you don't need to manually hide the timeline on create pages. If you still want to show it, just pass ->visible(true)
to the component.
If the timeline is empty (meaning that there are no activities yet displayed), then the timeline will display an empty state, which you can also customize (see below).
By default, the timeline component will display only the activities relating to the current Eloquent model in the form. If you want to also display activities for related Eloquent models, you may use the ->withRelations()
method. This method will automatically include activities for related models that are linked to the current model.
For example, say that we are editing a Customer
model, and each customer can have one or more related Address
'es using a hasMany ->addresses()
relationship. We can now display the creation and changes of the related address models also in the timeline:
Timeline::make() ->withRelations(['addresses']) // Display all address activities with a home icon, regardless of the type of event. ->itemIcon('*', 'heroicon-o-home-modern', [Address::class])
If the timeline detects that an item is for a related model, it will automatically update the text used like "John Doe added related address Main St. 123, NYC." or "John Doe updated related address Main St. 123, NYC street to Main St..".
NB: currently there is one caveat to be aware of. If a related model (like an address) is at any point not currently related to the current Eloquent model anymore, the previous activities would disappear from the timeline. So if an address is transferred to another customer, the activities for that address would disappear entirely from the timeline of the original customer.
By default, the plugin will try to identify the related model by a title attribute. First, it is checked if the model implements the Filament\Support\Contracts\HasName
or Filament\Support\Contracts\HasLabel
interfaces. If yes, then these will be next. Next, it will be checked if the model has the attributes name
, title
or label
. If yes, then these will be used. If still no result found, then the message will be generic ("John Doe updated a related post" instead of "John Doe updated related post Current Post Title").
You can provide custom attributes to use as title using the following methods:
Timeline::make() ->recordTitleAttribute(Post::class, 'id') ->recordTitleAttributes([ Post::class => 'id', Address::class => 'display_summary', ]) ->getRecordTitleUsing(Post::class, fn (Post $post) => $post->id) ->getRecordTitleUsing(Address::class, fn (Address $address) => "{$address->city}, {$address->state}")])
You can also limit the Addresses for which we will retrieve activity items:
Timeline::make() ->withRelations([ 'addresses' => function (HasMany $relation) { return $relation->where('type', AddressType::Shipping); } ]),
By default, each item in the timeline will be a small, gray dot. You can customize the icon and color of each item using the ->itemIcon()
and ->itemIconColor()
methods.
use Spatie\Activitylog\Models\Activity; Timeline::make() // You can let the package inject both the actual `Activity` Eloquent model, or just the string/nullable event name: ->itemIcon('created', 'heroicon-o-plus-circle') ->itemIcon('deleted', 'heroicon-o-trash') ->itemIcons([ 'created' => fn (Activity $activity) => $activity->causer->isAdmin() ? 'heroicon-o-plus' : 'heroicon-o-plus-small', 'deleted' => 'heroicon-o-trash', ]) ->itemIconColor('created', 'info') ->itemIconColor('deleted', 'danger') ->itemIconColors([ 'created' => 'info', 'deleted' => 'danger', ]),
Tip: generally, in a single timeline, it is nice to use a combination of both items with and without an icon. For example, you could consider giving "major" activity events an icon, like 'created' or 'deleted', whereas you could leave other events (like 'updated') without an icon.
Instead of strings, you can also pass custom closures. You can let the package inject both the actual Activity
Eloquent model, or just the string/nullable event name:
use Spatie\Activitylog\Models\Activity; Timeline::make() ->itemIcon('created', fn (string $event, Activity $activity) => /** */) ->itemIconColor('created', fn (string $event, Activity $activity) => /** */)
You can also scope the icons & colors to specific Eloquent models. This can be useful in cases where you have a timeline with activities for multiple types of Eloquent models (e.g. when working with batches), and you only want to apply a certain icon or color to one or more particular models.
Timeline::make() ->itemIcon('created', 'heroicon-o-plus-circle', [Post::class]) // Either array of classes or a single class. ->itemIconColor('created', 'success', Post::class)
If you want, you can add a badge after the event description. You can provide a badge based on the event name using the ->itemBadge()
method. A badge color can be provided using the ->itemBadgeColor()
method:
use Filament\Support\Colors\Color; Timeline::make() ->itemBadge('email_sent', function (Activity $activity) { $status = Status::tryFrom($activity->getExtraProperty('status')); return $status->getLabel(); }) ->itemBadges([ 'email_sent' => fn () => ..., 'created' => 'New', ]) ->itemBadgeColor('email_sent', function (Activity $activity) { $status = Status::tryFrom($activity->getExtraProperty('status')); return match ($status) { Status::Bounce => 'danger', Status::Complaint => 'danger', Status::Reject => Color::Orange, Status::RenderingFailure => Color::Orange, Status::Send => Color::Cyan, Status::DeliveryDelay => Color::Sky, Status::Delivery => Color::Blue, Status::Open => Color::Violet, Status::Click => Color::Purple, default => 'gray', }; }) ->itemBadgeColors([ 'email_sent' => fn () => ..., 'created' => 'info', ])
You can also scope the badges for events to specific Eloquent models. This can be useful in cases where you have a timeline with activities for multiple types of Eloquent models (e.g. when working with batches), and you only want to apply a certain icon or color to one or more particular models.
Timeline::make() ->itemBadge('created', 'New', [Post::class]) // Either array of classes or a single class. ->itemBadgeColor('created', 'success', Post::class)
You can customize the time format used in the timestamp tooltip by using the ->itemDateTimeFormat()
method. The default format is M jS, Y H:i:s
. You can also specify a timezone to convert the timestamps to using ->itemDateTimeTimezone()
.
Timeline::make() ->itemDateTimeFormat('Y-m-d H:i') ->itemDateTimeTimezone(fn () => auth()->user()->timezone)
These are also great candidates for global configuration (see below).
You can easily add actions to the timeline using the ->itemActions()
method. This method allows you to specify the event name and provide an array of actions that will be displayed beneath each item in the timeline.
The below example shows how to add actions for the 'published'
event on a Post
model:
use Filament\Forms; Timeline::make() ->itemActions('published', [ Forms\Components\Actions\Action::make('view_url_in_search_console') ->label('Open Google Search Console') ->icon('heroicon-m-magnifying-glass') ->url(fn (Post $post) => "https://search.google.com/...."), Forms\Components\Actions\Action::make('create_tweet') ->label('Send Tweet') ->icon('heroicon-m-megaphone') ->hidden(fn (Post $post) => $post->tweeted_at !== null) ->form([ Forms\Components\Textarea::make('content') ->label('Tweet') ->helperText('Max. 280 characters') ->maxLength(280) ->required() ]) ->action(function (Post $post, array $data) { // Send tweet... $post->touch('tweeted_at'); // Of course, we will also log a new activity to the timeline :) activity() ->performedOn($post) ->causedBy(auth()->user()) ->event('tweeted') ->log('tweeted'); Notification::make() ->title('Tweet sent') ->body('Let\'s hope our followers like it as much as we do 🙏') ->success() ->send(); }) ]) ]),
If you are mixing timeline items for multiple Eloquent models and you need access to the current underlying Spatie Activitylog model, you can use the $arguments['activity_id']
parameter:
Timeline::make() ->itemActions('published', [ Forms\Components\Actions\Action::make('edit') ->fillForm(function (array $arguments) { $activity = Activity::find($arguments['activity_id']); // ... }) ->form([ Forms\Components\TextInput::make('title') ]) ->action(function (array $arguments, array $data) { $activity = Activity::find($arguments['activity_id']); // ... }) ]),
If you want to globally provide icons, colors and actions, you can make use of the Filament configureUsing()
method. When working globally with timelines, it is generally very handy to scope the configuration to specific models:
Timeline::configureUsing(function (Timeline $timeline) { return $timeline ->itemIcons([ // Applies to all Eloquent models... 'created' => 'heroicon-o-plus-circle', 'deleted' => 'heroicon-o-trash', ]) ->itemIcon('created', 'heroicon-o-pencil', [Post::class, GlossaryItem::class]) // Applies only to `Post` and `GlossaryItem` model. ->itemIcon('created', null, User::class) // Disables icon for the `User` model. ->itemIconColors([ 'created' => 'info', 'deleted' => 'danger', ]) ->itemActions( event: 'published', actions: [ // ... ], subjectScopes: [Post::class], )});
These globals are kept as defaults. If you provide a custom override on any individual timeline, then that value will override the global defaults.
By default, the Filament Activitylog package will generate a nice description for you based on the event name and whether or not there's a causer name (see above). If you want to override the description for individual events, you can do so via the ->eventDescription()
method:
Timeline::make() ->eventDescription('published', 'Post is now shared with the world 🌎') // Instead of: John Doe published the post.
You can scope the custom descriptions also to specific Eloquent models:
use App\Models\Post; Timeline::make() ->eventDescription('published', 'Post is now shared with the world 🌎', [Post::class]) // Apply description only to `Post` models and not to `Tweet` models.
You can also set descriptions in bulk:
use Spatie\Activitylog\Models\Activity; Timeline::make() ->eventDescriptions( descriptions: [ 'created' => fn (Activity $activity) => "{$activity->causer->full_name} started a draft post", 'published' => 'Post is now shared with the world 🌎', ], subjectScopes: [Post::class] )
If you want to still make use of the description generation service provided by the package, but still modify part of the description, you can use the ->modifyEventDescriptionUsing()
method:
use Spatie\Activitylog\Models\Activity; Timeline::make() ->modifyEventDescriptionUsing(function (string $eventDescription, Activity $activity, string $recordTitle, ?string $causerName, ?string $changesSummary) { return "{$eventDescription} for {$recordTitle}"; ])
If you have enabled the logging of changed attributes, the timeline will automatically display changed attributes in the description for the updated
event. For example, consider the following changed attributes:
[ 'title' => 'New title', 'some_boolean' => true, 'some_date' => Carbon::parse('2024-01-01 10:00'),]
The package will automatically generate a description like this:
[Causer name] updated title to New title, some boolean to true and some date to 2024-01-01 10:00.
As you can see, the package automatically formats the values of the attributes in a human-readable way. Strings are kept, booleans are converted to 'true'
/'false'
in text, arrays are converted to JSON, enums are converted to either their name or to the getLabel()
method if you implemented the Filament\Support\Contracts\HasLabel
interface and dates are converted to a better format.
If you have custom casts on your Eloquent, then the Spatie Activitylog will automatically log updates to casted attributes. However, the way these values are stored in the database or displayed might not always work immediately satisfactory out-of-the-box.
First, in order to make the cast formatting work better, make sure that all attributes with custom casts are in the useAttributeRawValues()
method in the getActivityLogOptions()
:
class Order extends Model{ use LogsActivity; protected $casts = [ 'status' => SomeEnum::class, // Simple enum casts or other native Laravel casts will work right away. 'amount' => MoneyCast::class, // Custom casts should be added in the `useAttributeRawValues()` array. ]; public function getActivitylogOptions(): LogOptions { return LogOptions::defaults() ->useAttributeRawValues(['amount']) ->logAll(); }}
Explanation: for example, consider that you have an arrayable
Money
object as a cast on your Eloquent model. By default, Spatie Activitylog will store the value from the arrayable Money object as a change (so an array as JSON). However, it could be that the database actually contains just an integer value and not a JSON array. Therefore, it is recommended to store custom casts as raw values in the database.
Next, the above should work to automatically cast model values to the correct types. Next, you can provide custom callbacks to format specific attributes in the timeline before they appear:
Timeline::make() ->attributeLabel('amount', 'purchase amount') ->attributeValue('amount', fn (?Money $value) => $value?->formatWithoutZeroes()) // Make sure to also account for `null` values...
You can also use the attributeValues()
to provide an array of formatting callbacks:
Timeline::make() ->attributeValues([ 'amount' => fn (?Money $value) => $value?->formatWithoutZeroes(), // ... ]),
These methods can also be scoped to specific Eloquent models if you prefer, similar to the other methods in the package. This can be handy when configuring these callbacks globally.
Alternatively, it can also be handy sometimes to provide a formatting callback for a specific cast class. For example, if you have a Money
object in multiple models on different attribute names. You can use the attributeCast()
method to provide a formatting calback that will receive the value:
Timeline::make() ->attributeCast(MoneyCast::class, fn (?Money $value) => $value?->formatWithoutZeroes()),
This method can come in handy when globally configuring the timeline:
Timeline::configureUsing(function (Timeline $timeline) { return $timeline->attributeCast(MoneyCast::class, fn (?Money $value) => $value?->formatWithoutZeroes());})
Again, you may also use the attributeCasts()
method to provide formatting callbacks using an array:
Timeline::make() ->attributeCasts([ MoneyCast::class => fn (?Money $value) => $value?->formatWithoutZeroes()), CurrencyCast::class => fn (?Currency $value) => $value?->code()), ]),
By default, the descriptions for an updated
event does only mention the values that the attributes are changed to, and not the values from which they came. This is to save time and usually it is also less relevant. In case you would like to display the old values in the description, you can use the ->changesSummaryOldAttributeValues()
method:
Timeline::make() ->changesSummaryOldAttributeValues()
Sometimes the changed attribute values can be very long or you have a preference not to include the new values that attributes were updated to in the description. In that case, use the ->changesSummaryAttributeValues()
method to hide attribute values in the generated descriptions and changes summary:
Timeline::make() ->changesSummaryAttributeValues(false)
For getting the human-readable names of the attributes, the package will first automatically and intelligently check whether there is any other form component on the page that has a custom label for this attribute. For example, if you have a DatePicker::make('some_date')->label('Published at')
, then the package will automatically use the label 'published at'
.
You can also provide custom labels for attributes by using the ->attributeLabel()
or ->attributeLabels()
method:
Timeline::make() ->attributeLabel('some_date', 'published at') ->attributeLabel('some_date', fn () => 'published at') ->attributeLabels([ 'some_boolean' => 'is hidden from SEO', ]),
Finally, if there is still no attribute label found, the package will automatically try to convert the attribute name to a human-readable label. For example, some_date
will be converted to some date
.
By default, when creating descriptions the package will automatically generate model labels based on the Eloquent model. If you use the timeline in a panel, it will also first check if there's an associated resource. If yes, then the ResourceName::getModelLabel()
method is used as the model label.
The resulting model label is then lower-cased and used inside the automatically generated descriptions. If you want to provide a custom model label, or if the lower-casing doesn't work for you (e.g. in languages like German), then you can use the ->modelLabel()
and ->modelLabels()
method:
Timeline::make() ->modelLabel(User::class, 'Benutzer') ->modelLabels([ Post::class => 'Beitrag', ]),
By default, if the package detects that an event belongs to a batch, it will display the batch in a compact, inline timeline. The inline timeline will be 'connected' to the "main" timeline. This looks nice and can be very useful to your users to view related events together.
If you don't have the room for an inline timeline, you can also opt to display the batch inline. This means that the activity items from the batch will be shown inline with the main timeline items, just as if the items from the batch was part of the main timeline.
Timeline::make() ->inlineBatches(),
By default, the package will automatically retrieve all activity items from the batch that have a subject. You can however modify the query used to retrieve these items using the ->modifyBatchActivitiesQueryUsing()
using:
Timeline::make() ->modifyBatchActivitiesQueryUsing(function (Builder $query, Activity $activity, string $batchUuid) { return $query->whereIn('event', ['deleted', 'restored']); })
You can also choose to override the query entirely:
Timeline::make() ->getBatchActivitiesUsing(function (Activity $activity, string $batchUuid) { return Activity::forBatch($batchUuid)->get(); })
When the timeline is empty, it will show an empty state (similar to how the empty state looks in Filament tables). You can customize the empty state using the following methods:
Timeline::make() ->emptyStateHeading('No history') ->emptyStateDescription('Nothing has happened to this Eloquent model.') ->emptyStateIcon('heroicon-o-bars-arrow-down'),
By default, the timeline has a very nice design, but with a larger number of activities it can take up a lot of space. To solve this, you can opt to make use of the ->compact()
option, which will provide a more compact design:
Timeline::make() ->compact(),
If you want to make all timelines compact by default, you can configure that globally:
Timeline::configureUsing(fn (Timeline $timeline) => $timeline->compact());
If you use a compact timeline, it generally looks better to use icons from the heroicons-m-
set instead of the heroicons-o-
set, because the Heroicon Mini versions are designed for smaller sizes. On compact timelines, the package will automatically convert icons from the heroicons-o-
set to the heroicons-m-
set, and vice-versa on non-compact timelines.
If you want to disable this, you can do so passing false
to the ->convertHeroicons()
method:
Timeline::make() ->convertHeroicons(false),
Timeline::configureUsing(fn (Timeline $timeline) => $timeline->convertHeroicons(false));
If you have many activities in your timeline, you might want to make the timeline searchable:
Timeline::make() ->searchable(),
This will display a small text input above the timeline. Whenever a user types a search query in the input, it will look through the descriptions of all activities using JavaScript, and only display the activities that match the search query.
If you have a timeline with many activities, you might want to define a maximum height for the timeline. This will make the timeline scrollable:
Timeline::make() ->maxHeight() // Default 500px ->maxHeight(800) // 800 px ->maxHeight('50vh') // Any CSS value
By default, the timeline will assume that your current Eloquent model has the LogsActivity
trait. In that case, your model has an ->activities()
relationship and the timeline assumes that you want to display these activities. If you want to filter the activities being shown, you can use the ->modifyActivitiesQueryUsing()
method:
Timeline::make() ->modifyActivitiesQueryUsing(function (Builder $query) { return $query->where('log_name', 'notifications'); }),
If you want override the activities logic entirely for determining which activities to display, you can provide a custom callback to the ->getActivitiesUsing()
method available on all the components:
Timeline::make() ->getActivitiesUsing(function () { return Activity::get(); // Provide the activities as you wish. }),
It would be recommended to first try the
->modifyActivitiesQueryUsing()
if possible and only then use the->getActivitiesUsing()
method.
Usually the design of the timeline will be clear enough to the user what it represents, so hiding the label will make the end result cleaner. You can hide the label using the ->hiddenLabel()
method:
Timeline::make() ->hiddenLabel(),
The timeline component is also available as an infolist component. The Timeline
infolist component will function exactly the same as the form Timeline
component, and therefore will also have all the same methods as the timeline in the form:
use RalphJSmit\Filament\Activitylog\Infolists\Components\Timeline; Timeline::make() ->itemIcon('created', 'heroicon-o-plus') ->itemIconColor('created', 'info') ->itemActions('published', [ // ... ]) ->eventDescription('published', 'Post is now shared with the world 🌎') ->emptyStateHeading('No history') // ...
When adding actions to timelines in infolists, you should logically use Filament\Infolists\Components\Actions\Action
as action classes instead of the Filament\Forms\Components\Actions\Action
class.
You can use the RalphJSmit\Filament\Activitylog\Actions\TimelineAction
action in your pages to display a button that will open the timeline of the record in a modal slideover:
class EditPost extends EditRecord{ // ... public function getHeaderActions(): array { return [ RalphJSmit\Filament\Activitylog\Actions\TimelineAction::make(), ]; }}
Of course, you can chain any of the methods available on the default action component to tweak the action to your liking.
The timeline in the slide-over is displayed using an infolist Timeline
component. You can customize the component by passing a callback to the modifyTimelineUsing()
method:
TimelineAction::make() ->modifyTimelineUsing(function (Timeline $timeline) { return $timeline->compact()->searchable(); }),
You can use the RalphJSmit\Filament\Activitylog\Tables\Actions\TimelineAction
action in your tables to display a button that will open the timeline of the record in a modal slideover:
$table ->actions([ RalphJSmit\Filament\Activitylog\Tables\Actions\TimelineAction::make() ]);
The timeline in the slide-over is displayed using an infolist Timeline
component. You can customize the component by passing a callback to the modifyTimelineUsing()
method:
TimelineAction::make() ->modifyTimelineUsing(function (Timeline $timeline) { return $timeline->compact()->searchable(); }),
I hope this package will be useful to you! If you have any ideas or suggestions on how to make it more useful, please let me know (support@ralphjsmit.com).
If you have a question, bug or feature request, please e-mail me at support@ralphjsmit.com or tag @ralphjsmit on #activitylog-pro on the Filament Discord. Love to hear from you!