Add central Audit Trail viewer in Filament admin
Features: - AuditResource with table listing all audit logs - ViewAudit page showing detailed changes with diff table - Filters: date range, user, model type, event type - Search by user name - Auto-refresh every 60 seconds - Dark mode support for changes view - Fixed audits migration with proper schema - Added audit.view permission (admin only by default) Files: - src/app/Models/Audit.php - src/app/Filament/Resources/AuditResource.php - src/app/Filament/Resources/AuditResource/Pages/ - src/resources/views/filament/infolists/entries/audit-changes.blade.php - Updated audits migration with full schema
This commit is contained in:
111
src/app/Models/Audit.php
Normal file
111
src/app/Models/Audit.php
Normal file
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
|
||||
class Audit extends Model
|
||||
{
|
||||
protected $table = 'audits';
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
protected $casts = [
|
||||
'old_values' => 'array',
|
||||
'new_values' => 'array',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the user that performed the action.
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the auditable model.
|
||||
*/
|
||||
public function auditable(): MorphTo
|
||||
{
|
||||
return $this->morphTo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the event badge color.
|
||||
*/
|
||||
public function getEventColorAttribute(): string
|
||||
{
|
||||
return match ($this->event) {
|
||||
'created' => 'success',
|
||||
'updated' => 'warning',
|
||||
'deleted' => 'danger',
|
||||
'restored' => 'info',
|
||||
default => 'gray',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a human-readable model name.
|
||||
*/
|
||||
public function getModelNameAttribute(): string
|
||||
{
|
||||
$class = class_basename($this->auditable_type);
|
||||
return preg_replace('/(?<!^)[A-Z]/', ' $0', $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get formatted changes for display.
|
||||
*/
|
||||
public function getFormattedChangesAttribute(): array
|
||||
{
|
||||
$changes = [];
|
||||
$oldValues = $this->old_values ?? [];
|
||||
$newValues = $this->new_values ?? [];
|
||||
|
||||
$allKeys = array_unique(array_merge(array_keys($oldValues), array_keys($newValues)));
|
||||
|
||||
foreach ($allKeys as $key) {
|
||||
$old = $oldValues[$key] ?? null;
|
||||
$new = $newValues[$key] ?? null;
|
||||
|
||||
if ($old !== $new) {
|
||||
$changes[] = [
|
||||
'field' => $key,
|
||||
'old' => $this->formatValue($old),
|
||||
'new' => $this->formatValue($new),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $changes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a value for display.
|
||||
*/
|
||||
protected function formatValue($value): string
|
||||
{
|
||||
if (is_null($value)) {
|
||||
return '(empty)';
|
||||
}
|
||||
|
||||
if (is_bool($value)) {
|
||||
return $value ? 'Yes' : 'No';
|
||||
}
|
||||
|
||||
if (is_array($value)) {
|
||||
return json_encode($value);
|
||||
}
|
||||
|
||||
$stringValue = (string) $value;
|
||||
|
||||
if (strlen($stringValue) > 100) {
|
||||
return substr($stringValue, 0, 100) . '...';
|
||||
}
|
||||
|
||||
return $stringValue;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user