Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 75 additions & 26 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
<div class="filament-hidden">

![header](./.github/resources/pxlrbt-activity-log.png)

</div>
![header](./.github/resources/header.png)

# Filament Activity Log

Expand All @@ -11,15 +7,10 @@
![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/pxlrbt/filament-activity-log/code-style.yml?branch=main&label=Code%20style&style=flat-square)
[![Total Downloads](https://img.shields.io/packagist/dt/pxlrbt/filament-activity-log.svg)](https://packagist.org/packages/pxlrbt/filament-activity-log)

This package adds pages to the Filament Admin panel to view the activity log generated by [`spatie/laravel-activitylog`](https://github.com/spatie/laravel-activitylog).

This package adds a page to the Filament Admin panel to view the activity log generated by [`spatie/laravel-activitylog`](https://github.com/spatie/laravel-activitylog).

<div class="filament-hidden">

![Screenshot](./.github/resources/screenshot.png)

</div>

## Installation

| Plugin Version | Filament Version | Activitylog | PHP Version |
Expand All @@ -31,14 +22,14 @@ This package adds a page to the Filament Admin panel to view the activity log ge

Install via Composer.

**Requires PHP 8.0 and Filament 2.0**
**Requires PHP 8.1, Filament 4.0 or 5.0, and spatie/laravel-activitylog 4.7 or 5.0**

```bash
composer require pxlrbt/filament-activity-log
```

> **Warning**
> This plugin only offers a page to show activities related to your model. You need [`spatie/laravel-activitylog`](https://github.com/spatie/laravel-activitylog) installed and configured for it to work. It is important you are using the `LogsActivity` trait as per [Spatie's docs](https://spatie.be/docs/laravel-activitylog/v5/advanced-usage/logging-model-events) for this work as we use the `->activitiesAsSubject()` method of the trait.
> This plugin offers two pages: one listing activities **on a subject** (use `ListActivitiesBySubject`) and one listing activities **caused by** a record such as a user (use `ListActivitiesByCauser`). You need [`spatie/laravel-activitylog`](https://github.com/spatie/laravel-activitylog) installed and configured for it to work. The subject page uses the `LogsActivity` trait's `activitiesAsSubject()` relation; the causer page uses the `CausesActivity` trait's `activitiesAsCauser()` relation.

## Filament v4 Upgrade
Make sure you have a custom theme, add this line and recompile: `@import '../../../../vendor/pxlrbt/filament-activity-log/resources/css/styles.css';`
Expand All @@ -47,23 +38,47 @@ Make sure you have a custom theme, add this line and recompile: `@import '../../

Make sure you use a **custom theme** and the vendor folder for this plugins is published, so that it includes the Tailwind CSS classes.

### Create a page
## Listing activities for a subject

![Screenshot](./.github/resources/screenshot.png)

Use `ListActivitiesBySubject` to show all activities recorded **on** a record (e.g. every change to an order).

### Setup spatie/laravel-activitylog

Make sure your resource model uses the `LogsActivity` trait.

```php
<?php

use Spatie\Activitylog\Models\Concerns\LogsActivity;

Create the page inside your resources `Pages/` directory. Replace `OrderResource` with your resource.
class Order extends Model
{
use LogsActivity;
}
```

### Create a ListActivitiesBySubject page

Create the page inside your resource's `Pages/` directory. Replace `OrderResource` with your resource.

```php
<?php

namespace App\Filament\Resources\OrderResource\Pages;
namespace App\Filament\Resources\Orders\Pages;

use pxlrbt\FilamentActivityLog\Pages\ListActivities;
use pxlrbt\FilamentActivityLog\Pages\ListActivitiesBySubject;

class ListOrderActivities extends ListActivities
class ListOrderActivities extends ListActivitiesBySubject
{
protected static string $resource = OrderResource::class;
}
```

> **Note**
> The legacy class `ListActivities` is kept as an abstract alias of `ListActivitiesBySubject`, so existing subclasses continue to work.

### Register the page

Add the page to your resource's `getPages()` method.
Expand All @@ -80,27 +95,61 @@ public static function getPages(): array
}
```

### Link to your page

Use a Filament action to link to your from your table or page.
## Listing activities caused by a record

Use `ListActivitiesByCauser` to show all activities a record (typically a user) has caused across every subject. Each row links to the affected subject's resource when one is registered.

### Setup spatie/laravel-activitylog

Make sure your user model uses the `CausesActivity` trait.

```php
$table->actions([
Action::make('activities')->url(fn ($record) => YourResource::getUrl('activities', ['record' => $record]))
]);
<?php

use Spatie\Activitylog\Models\Concerns\CausesActivity;

class User extends Authenticatable implements FilamentUser
{
use CausesActivity;
}
```

### Adjust your model to log activities
### Create a ListActivitiesByCauser page

Create the page inside your `UserResource`'s `Pages/` directory.

```php
class Order extends Model
<?php

namespace App\Filament\Resources\Users\Pages;

use pxlrbt\FilamentActivityLog\Pages\ListActivitiesByCauser;

class ListUserActivities extends ListActivitiesByCauser
{
use LogsActivity;
protected static string $resource = UserResource::class;
}
```

See https://spatie.be/docs/laravel-activitylog/v5/advanced-usage/logging-model-events for more information on the topic.

### Register the page

Add the page to your resource's `getPages()` method.

```php
public static function getPages(): array
{
return [
'index' => Pages\ListUsers::route('/'),
'create' => Pages\CreateUser::route('/create'),
'activities' => Pages\ListUserActivities::route('/{record}/activities'),
'edit' => Pages\EditUser::route('/{record}/edit'),
];
}
```

## Contributing

If you want to contribute to this packages, you may want to test it in a real Filament project:
Expand Down
107 changes: 107 additions & 0 deletions resources/views/pages/list-activities-by-causer.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<x-filament-panels::page>
<div class="space-y-6">
@foreach($this->getActivities() as $activityItem)

@php
/* @var \Spatie\Activitylog\Models\Activity $activityItem */
$changes = $activityItem->attribute_changes ?? collect();
$resource = $this->getSubjectResource($activityItem->subject_type);
@endphp

<div @class([
'p-2 space-y-2 bg-white rounded-xl shadow',
'dark:border-gray-600 dark:bg-gray-800',
])>
<div class="p-2">
<div class="flex justify-between">
<div class="flex flex-col text-start">
<span class="font-bold">
@if ($resource)
{{ $resource::getModelLabel() }}:
@if ($activityItem->subject && $resource::hasRecordTitle())
@php
$url = $activityItem->subject->exists
? $resource::getUrl('edit', ['record' => $activityItem->subject])
: null;
@endphp
@if ($url)
<a href="{{ $url }}" class="underline">{{ $resource::getRecordTitle($activityItem->subject) }}</a>
@else
{{ $resource::getRecordTitle($activityItem->subject) }}
@endif
@else
{{ $activityItem->subject_id }}
@endif
@else
{{ $activityItem->subject_type }}: {{ $activityItem->subject_id }}
@endif
</span>
<span class="text-xs text-gray-500">
{{ __('filament-activity-log::activities.events.' . $activityItem->event) }} {{ $activityItem->created_at->format(__('filament-activity-log::activities.default_datetime_format')) }}
</span>
</div>
</div>
</div>

@if ($changes->isNotEmpty())
<table class="fi-ta-table w-full overflow-hidden text-sm">
<thead>
<th class="fi-ta-header-cell">
{{ __('filament-activity-log::activities.table.field') }}
</th>
<th class="fi-ta-header-cell">
{{ __('filament-activity-log::activities.table.old') }}
</th>
<th class="fi-ta-header-cell">
{{ __('filament-activity-log::activities.table.new') }}
</th>
</thead>

<tbody>
@foreach (data_get($changes, 'attributes', []) as $field => $change)
@php
$oldValue = data_get($changes, "old.{$field}", '');
$newValue = data_get($changes, "attributes.{$field}", '');
@endphp
<tr
@class([
'fi-ta-row',
'bg-gray-100/30' => $loop->even
])
>
<td class="fi-ta-cell px-4 py-2 align-top sm:first-of-type:ps-6 sm:last-of-type:pe-6" width="20%">
{{ $this->getFieldLabel($resource, $field) }}
</td>
<td width="40%" class="fi-ta-cell px-4 py-2 align-top break-all whitespace-normal">
@if(is_array($oldValue))
<pre class="text-xs text-gray-500">{{ json_encode($oldValue, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) }}</pre>
@elseif (is_bool($oldValue))
<span class="text-xs text-gray-500">{{ $oldValue ? 'true' : 'false' }}</span>
@else
{{ $oldValue }}
@endif
</td>
<td width="40%" class="fi-ta-cell px-4 py-2 align-top break-all whitespace-normal">
@if (is_bool($newValue))
<span class="text-xs text-gray-500">{{ $newValue ? 'true' : 'false' }}</span>
@elseif(is_array($newValue))
<pre class="text-xs text-gray-500">{{ json_encode($newValue, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) }}</pre>
@else
{{ $newValue }}
@endif
</td>
</tr>
@endforeach
</tbody>
</table>
@endif
</div>
@endforeach

<x-filament::pagination
currentPageOptionProperty="recordsPerPage"
:page-options="$this->getRecordsPerPageSelectOptions()"
:paginator="$this->getActivities()"
/>
</div>
</x-filament-panels::page>
Loading
Loading