From 3504e39646325346599364c2336ec08052d9b290 Mon Sep 17 00:00:00 2001 From: Mekan1206 Date: Sun, 2 Aug 2026 22:37:59 +0500 Subject: [PATCH] Add bokshorn-it/filament-activity-timeline package for enhanced audit logging functionality. Update README to reflect new key package and improve localization for audit-related terms. Remove deprecated ActivityLogResource and related pages, integrating activity timeline features into existing resources. Update models to implement ProvidesActivityTitle for better activity tracking. --- README.md | 4 +- .../ActivityTimeline/AuditLogResource.php | 24 ++++ .../ActivityLogs/ActivityLogResource.php | 96 -------------- .../ActivityLogs/Pages/ListActivityLogs.php | 18 --- .../ActivityLogs/Pages/ViewActivityLog.php | 18 --- .../Schemas/ActivityLogInfolist.php | 45 ------- .../ActivityLogs/Tables/ActivityLogsTable.php | 119 ------------------ .../Resources/Bonuses/Pages/ViewBonus.php | 2 + .../Departments/Pages/ViewDepartment.php | 2 + .../Pages/ViewDisciplinaryReport.php | 2 + .../Pages/ViewEmployeeDocument.php | 2 + .../Employees/Pages/ViewEmployee.php | 12 ++ .../Explanations/Pages/ViewExplanation.php | 2 + .../Resources/Gifts/Pages/ViewGift.php | 2 + .../Positions/Pages/ViewPosition.php | 2 + .../Resources/Shifts/Pages/ViewShift.php | 2 + .../SickLeaves/Pages/ViewSickLeave.php | 2 + .../UnpaidLeaves/Pages/ViewUnpaidLeave.php | 2 + .../Vacations/Pages/ViewVacation.php | 2 + app/Models/Bonus.php | 3 +- app/Models/Concerns/LogsHrActivity.php | 26 ++++ app/Models/Department.php | 3 +- app/Models/DisciplinaryReport.php | 3 +- app/Models/Employee.php | 3 +- app/Models/EmployeeDocument.php | 3 +- app/Models/Explanation.php | 3 +- app/Models/Gift.php | 3 +- app/Models/Position.php | 3 +- app/Models/Shift.php | 3 +- app/Models/SickLeave.php | 3 +- app/Models/UnpaidLeave.php | 3 +- app/Models/Vacation.php | 3 +- app/Policies/ActivityPolicy.php | 92 ++++++++++++++ app/Providers/AppServiceProvider.php | 3 + app/Providers/Filament/AdminPanelProvider.php | 14 +++ composer.json | 1 + composer.lock | 70 ++++++++++- lang/en/changes.php | 50 ++++++++ lang/en/hr.php | 7 ++ lang/ru/changes.php | 50 ++++++++ lang/ru/hr.php | 7 ++ lang/tk/changes.php | 50 ++++++++ lang/tk/hr.php | 7 ++ resources/css/filament/admin/theme.css | 1 + tests/Feature/Filament/PanelAccessTest.php | 8 ++ tests/Feature/LocalizationTest.php | 6 +- 46 files changed, 472 insertions(+), 314 deletions(-) create mode 100644 app/Filament/ActivityTimeline/AuditLogResource.php delete mode 100644 app/Filament/Resources/ActivityLogs/ActivityLogResource.php delete mode 100644 app/Filament/Resources/ActivityLogs/Pages/ListActivityLogs.php delete mode 100644 app/Filament/Resources/ActivityLogs/Pages/ViewActivityLog.php delete mode 100644 app/Filament/Resources/ActivityLogs/Schemas/ActivityLogInfolist.php delete mode 100644 app/Filament/Resources/ActivityLogs/Tables/ActivityLogsTable.php create mode 100644 app/Policies/ActivityPolicy.php create mode 100644 lang/en/changes.php create mode 100644 lang/ru/changes.php create mode 100644 lang/tk/changes.php diff --git a/README.md b/README.md index b30bfea..383aa87 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Internal admin application for managing employee records, leave requests, discip **Stack:** Laravel 13, PHP 8.3+, Filament 5, SQLite (default) or MySQL, Vite + Tailwind 4. -**Key packages:** Filament Shield (RBAC), Language Switch, Spatie Activity Log, Maatwebsite Excel, DomPDF. +**Key packages:** Filament Shield (RBAC), Language Switch, Spatie Activity Log, Bokshorn IT Activity Timeline, Maatwebsite Excel, DomPDF. ## Requirements @@ -172,7 +172,7 @@ Seeded roles: `super_admin`, `administrator`, `hr_manager`, `supervisor`, `depar ### Audit trail - The `LogsHrActivity` concern on HR models logs changes to fillable fields via Spatie Activity Log -- The **Activity Log** resource provides a read-only audit viewer in the admin panel +- The **Audit Log** resource (via `bokshorn-it/filament-activity-timeline`) provides a read-only audit viewer with readable diffs and per-record timelines in the admin panel ### Localization diff --git a/app/Filament/ActivityTimeline/AuditLogResource.php b/app/Filament/ActivityTimeline/AuditLogResource.php new file mode 100644 index 0000000..fd78bcf --- /dev/null +++ b/app/Filament/ActivityTimeline/AuditLogResource.php @@ -0,0 +1,24 @@ + 'activity_log', + 'plural' => 'activity_logs', + 'navigation' => 'audit_log', + ]; + } +} diff --git a/app/Filament/Resources/ActivityLogs/ActivityLogResource.php b/app/Filament/Resources/ActivityLogs/ActivityLogResource.php deleted file mode 100644 index 15aaa76..0000000 --- a/app/Filament/Resources/ActivityLogs/ActivityLogResource.php +++ /dev/null @@ -1,96 +0,0 @@ - 'activity_log', - 'plural' => 'activity_logs', - 'navigation' => 'audit_log', - ]; - } - - protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedClipboardDocumentList; - - protected static string|UnitEnum|null $navigationGroup = NavigationGroup::System; - - protected static ?int $navigationSort = 3; - - protected static ?string $slug = 'activity-logs'; - - public static function form(Schema $schema): Schema - { - return $schema; - } - - public static function infolist(Schema $schema): Schema - { - return ActivityLogInfolist::configure($schema); - } - - public static function table(Table $table): Table - { - return ActivityLogsTable::configure($table); - } - - public static function getRelations(): array - { - return []; - } - - public static function getPages(): array - { - return [ - 'index' => ListActivityLogs::route('/'), - 'view' => ViewActivityLog::route('/{record}'), - ]; - } - - public static function canCreate(): bool - { - return false; - } - - public static function canEdit($record): bool - { - return false; - } - - public static function canDelete($record): bool - { - return false; - } - - public static function canForceDelete($record): bool - { - return false; - } - - public static function canRestore($record): bool - { - return false; - } -} diff --git a/app/Filament/Resources/ActivityLogs/Pages/ListActivityLogs.php b/app/Filament/Resources/ActivityLogs/Pages/ListActivityLogs.php deleted file mode 100644 index ac86581..0000000 --- a/app/Filament/Resources/ActivityLogs/Pages/ListActivityLogs.php +++ /dev/null @@ -1,18 +0,0 @@ -components([ - Section::make(__('hr.sections.activity_details')) - ->schema([ - TextEntry::make('created_at') - ->label(__('hr.fields.date')) - ->dateTime(), - TextEntry::make('description'), - TextEntry::make('event') - ->badge(), - TextEntry::make('log_name') - ->label(__('hr.fields.log_name')), - TextEntry::make('subject_type') - ->label(__('hr.fields.subject_type')) - ->formatStateUsing(fn (?string $state): string => $state ? class_basename($state) : '—'), - TextEntry::make('subject_id') - ->label(__('hr.fields.subject_id')), - TextEntry::make('causer.name') - ->label(__('hr.fields.causer')), - KeyValueEntry::make('properties.attributes') - ->label(__('hr.fields.changes')) - ->visible(fn ($record): bool => filled($record->properties['attributes'] ?? null)), - KeyValueEntry::make('properties.old') - ->label(__('hr.fields.previous_values')) - ->visible(fn ($record): bool => filled($record->properties['old'] ?? null)), - ]) - ->columns(2), - ]); - } -} diff --git a/app/Filament/Resources/ActivityLogs/Tables/ActivityLogsTable.php b/app/Filament/Resources/ActivityLogs/Tables/ActivityLogsTable.php deleted file mode 100644 index d1e2ee7..0000000 --- a/app/Filament/Resources/ActivityLogs/Tables/ActivityLogsTable.php +++ /dev/null @@ -1,119 +0,0 @@ -columns([ - TextColumn::make('created_at') - ->label(__('hr.fields.date')) - ->dateTime() - ->sortable(), - TextColumn::make('description') - ->label(__('hr.fields.description')) - ->searchable() - ->limit(50), - TextColumn::make('event') - ->label(__('hr.fields.event')) - ->badge() - ->searchable() - ->sortable(), - TextColumn::make('subject_type') - ->label(__('hr.fields.subject_type')) - ->formatStateUsing(fn (?string $state): string => $state ? class_basename($state) : '—') - ->searchable() - ->sortable(), - TextColumn::make('subject_id') - ->label(__('hr.fields.subject_id')) - ->sortable(), - TextColumn::make('causer.name') - ->label(__('hr.fields.causer')) - ->searchable() - ->sortable(), - TextColumn::make('log_name') - ->label(__('hr.fields.log_name')) - ->toggleable(isToggledHiddenByDefault: true), - ]) - ->defaultSort('created_at', 'desc') - ->filters([ - SelectFilter::make('subject_type') - ->label(__('hr.fields.subject_type')) - ->options([ - Employee::class => __('hr.audit.employee'), - Vacation::class => __('hr.audit.vacation'), - Bonus::class => __('hr.audit.bonus'), - DisciplinaryReport::class => __('hr.audit.disciplinary_report'), - Department::class => __('hr.audit.department'), - User::class => __('hr.audit.user'), - ]), - SelectFilter::make('event') - ->label(__('hr.fields.event')) - ->options(fn (): array => Activity::query() - ->whereNotNull('event') - ->distinct() - ->pluck('event', 'event') - ->all()), - SelectFilter::make('causer_id') - ->label(__('hr.fields.causer')) - ->options(fn (): array => User::query() - ->whereIn('id', Activity::query() - ->where('causer_type', User::class) - ->whereNotNull('causer_id') - ->distinct() - ->pluck('causer_id')) - ->orderBy('name') - ->pluck('name', 'id') - ->all()) - ->searchable() - ->query(fn (Builder $query, array $data): Builder => $query->when( - $data['value'] ?? null, - fn (Builder $query, $causerId): Builder => $query - ->where('causer_id', $causerId) - ->where('causer_type', User::class), - )), - Filter::make('created_at') - ->label(__('hr.fields.date')) - ->schema([ - DatePicker::make('from') - ->label(__('hr.fields.from')), - DatePicker::make('until') - ->label(__('hr.fields.until')), - ]) - ->query(function (Builder $query, array $data): Builder { - return $query - ->when( - $data['from'] ?? null, - fn (Builder $query, string $date): Builder => $query->whereDate('created_at', '>=', $date), - ) - ->when( - $data['until'] ?? null, - fn (Builder $query, string $date): Builder => $query->whereDate('created_at', '<=', $date), - ); - }), - ]) - ->recordActions([ - ViewAction::make(), - ]) - ->toolbarActions([]); - } -} diff --git a/app/Filament/Resources/Bonuses/Pages/ViewBonus.php b/app/Filament/Resources/Bonuses/Pages/ViewBonus.php index 5f2d664..ceb2b5d 100644 --- a/app/Filament/Resources/Bonuses/Pages/ViewBonus.php +++ b/app/Filament/Resources/Bonuses/Pages/ViewBonus.php @@ -3,6 +3,7 @@ namespace App\Filament\Resources\Bonuses\Pages; use App\Filament\Resources\Bonuses\BonusResource; +use BokshornIt\FilamentActivityTimeline\Actions\ActivityTimelineAction; use Filament\Actions\EditAction; use Filament\Resources\Pages\ViewRecord; @@ -13,6 +14,7 @@ class ViewBonus extends ViewRecord protected function getHeaderActions(): array { return [ + ActivityTimelineAction::make(), EditAction::make(), ]; } diff --git a/app/Filament/Resources/Departments/Pages/ViewDepartment.php b/app/Filament/Resources/Departments/Pages/ViewDepartment.php index 0476937..6708a4f 100644 --- a/app/Filament/Resources/Departments/Pages/ViewDepartment.php +++ b/app/Filament/Resources/Departments/Pages/ViewDepartment.php @@ -3,6 +3,7 @@ namespace App\Filament\Resources\Departments\Pages; use App\Filament\Resources\Departments\DepartmentResource; +use BokshornIt\FilamentActivityTimeline\Actions\ActivityTimelineAction; use Filament\Actions\EditAction; use Filament\Resources\Pages\ViewRecord; @@ -13,6 +14,7 @@ class ViewDepartment extends ViewRecord protected function getHeaderActions(): array { return [ + ActivityTimelineAction::make(), EditAction::make(), ]; } diff --git a/app/Filament/Resources/DisciplinaryReports/Pages/ViewDisciplinaryReport.php b/app/Filament/Resources/DisciplinaryReports/Pages/ViewDisciplinaryReport.php index ef3367e..bcf565d 100644 --- a/app/Filament/Resources/DisciplinaryReports/Pages/ViewDisciplinaryReport.php +++ b/app/Filament/Resources/DisciplinaryReports/Pages/ViewDisciplinaryReport.php @@ -3,6 +3,7 @@ namespace App\Filament\Resources\DisciplinaryReports\Pages; use App\Filament\Resources\DisciplinaryReports\DisciplinaryReportResource; +use BokshornIt\FilamentActivityTimeline\Actions\ActivityTimelineAction; use Filament\Actions\EditAction; use Filament\Resources\Pages\ViewRecord; @@ -13,6 +14,7 @@ class ViewDisciplinaryReport extends ViewRecord protected function getHeaderActions(): array { return [ + ActivityTimelineAction::make(), EditAction::make(), ]; } diff --git a/app/Filament/Resources/EmployeeDocuments/Pages/ViewEmployeeDocument.php b/app/Filament/Resources/EmployeeDocuments/Pages/ViewEmployeeDocument.php index f03c684..b93ec7c 100644 --- a/app/Filament/Resources/EmployeeDocuments/Pages/ViewEmployeeDocument.php +++ b/app/Filament/Resources/EmployeeDocuments/Pages/ViewEmployeeDocument.php @@ -3,6 +3,7 @@ namespace App\Filament\Resources\EmployeeDocuments\Pages; use App\Filament\Resources\EmployeeDocuments\EmployeeDocumentResource; +use BokshornIt\FilamentActivityTimeline\Actions\ActivityTimelineAction; use Filament\Actions\EditAction; use Filament\Resources\Pages\ViewRecord; @@ -13,6 +14,7 @@ class ViewEmployeeDocument extends ViewRecord protected function getHeaderActions(): array { return [ + ActivityTimelineAction::make(), EditAction::make(), ]; } diff --git a/app/Filament/Resources/Employees/Pages/ViewEmployee.php b/app/Filament/Resources/Employees/Pages/ViewEmployee.php index c824343..91d2705 100644 --- a/app/Filament/Resources/Employees/Pages/ViewEmployee.php +++ b/app/Filament/Resources/Employees/Pages/ViewEmployee.php @@ -7,6 +7,7 @@ namespace App\Filament\Resources\Employees\Pages; use App\Filament\Resources\Employees\EmployeeResource; use App\Filament\Resources\Employees\Widgets\EmployeeStatsWidget; use App\Filament\Support\ExportPdfAction; +use BokshornIt\FilamentActivityTimeline\Actions\ActivityTimelineAction; use Filament\Actions\EditAction; use Filament\Resources\Pages\ViewRecord; @@ -17,6 +18,17 @@ class ViewEmployee extends ViewRecord protected function getHeaderActions(): array { return [ + ActivityTimelineAction::make() + ->withRelations([ + 'vacations', + 'sickLeaves', + 'unpaidLeaves', + 'disciplinaryReports', + 'explanations', + 'bonuses', + 'gifts', + 'documents', + ]), ExportPdfAction::employeeProfile(), ExportPdfAction::employeeLeaveSummary(), EditAction::make(), diff --git a/app/Filament/Resources/Explanations/Pages/ViewExplanation.php b/app/Filament/Resources/Explanations/Pages/ViewExplanation.php index c02c476..fa0c034 100644 --- a/app/Filament/Resources/Explanations/Pages/ViewExplanation.php +++ b/app/Filament/Resources/Explanations/Pages/ViewExplanation.php @@ -3,6 +3,7 @@ namespace App\Filament\Resources\Explanations\Pages; use App\Filament\Resources\Explanations\ExplanationResource; +use BokshornIt\FilamentActivityTimeline\Actions\ActivityTimelineAction; use Filament\Actions\EditAction; use Filament\Resources\Pages\ViewRecord; @@ -13,6 +14,7 @@ class ViewExplanation extends ViewRecord protected function getHeaderActions(): array { return [ + ActivityTimelineAction::make(), EditAction::make(), ]; } diff --git a/app/Filament/Resources/Gifts/Pages/ViewGift.php b/app/Filament/Resources/Gifts/Pages/ViewGift.php index 6cc66aa..08f8e90 100644 --- a/app/Filament/Resources/Gifts/Pages/ViewGift.php +++ b/app/Filament/Resources/Gifts/Pages/ViewGift.php @@ -3,6 +3,7 @@ namespace App\Filament\Resources\Gifts\Pages; use App\Filament\Resources\Gifts\GiftResource; +use BokshornIt\FilamentActivityTimeline\Actions\ActivityTimelineAction; use Filament\Actions\EditAction; use Filament\Resources\Pages\ViewRecord; @@ -13,6 +14,7 @@ class ViewGift extends ViewRecord protected function getHeaderActions(): array { return [ + ActivityTimelineAction::make(), EditAction::make(), ]; } diff --git a/app/Filament/Resources/Positions/Pages/ViewPosition.php b/app/Filament/Resources/Positions/Pages/ViewPosition.php index 8cc9888..57f9b0d 100644 --- a/app/Filament/Resources/Positions/Pages/ViewPosition.php +++ b/app/Filament/Resources/Positions/Pages/ViewPosition.php @@ -3,6 +3,7 @@ namespace App\Filament\Resources\Positions\Pages; use App\Filament\Resources\Positions\PositionResource; +use BokshornIt\FilamentActivityTimeline\Actions\ActivityTimelineAction; use Filament\Actions\EditAction; use Filament\Resources\Pages\ViewRecord; @@ -13,6 +14,7 @@ class ViewPosition extends ViewRecord protected function getHeaderActions(): array { return [ + ActivityTimelineAction::make(), EditAction::make(), ]; } diff --git a/app/Filament/Resources/Shifts/Pages/ViewShift.php b/app/Filament/Resources/Shifts/Pages/ViewShift.php index 3c086e2..24ef101 100644 --- a/app/Filament/Resources/Shifts/Pages/ViewShift.php +++ b/app/Filament/Resources/Shifts/Pages/ViewShift.php @@ -3,6 +3,7 @@ namespace App\Filament\Resources\Shifts\Pages; use App\Filament\Resources\Shifts\ShiftResource; +use BokshornIt\FilamentActivityTimeline\Actions\ActivityTimelineAction; use Filament\Actions\EditAction; use Filament\Resources\Pages\ViewRecord; @@ -13,6 +14,7 @@ class ViewShift extends ViewRecord protected function getHeaderActions(): array { return [ + ActivityTimelineAction::make(), EditAction::make(), ]; } diff --git a/app/Filament/Resources/SickLeaves/Pages/ViewSickLeave.php b/app/Filament/Resources/SickLeaves/Pages/ViewSickLeave.php index 7d34377..d93a190 100644 --- a/app/Filament/Resources/SickLeaves/Pages/ViewSickLeave.php +++ b/app/Filament/Resources/SickLeaves/Pages/ViewSickLeave.php @@ -3,6 +3,7 @@ namespace App\Filament\Resources\SickLeaves\Pages; use App\Filament\Resources\SickLeaves\SickLeaveResource; +use BokshornIt\FilamentActivityTimeline\Actions\ActivityTimelineAction; use Filament\Actions\EditAction; use Filament\Resources\Pages\ViewRecord; @@ -13,6 +14,7 @@ class ViewSickLeave extends ViewRecord protected function getHeaderActions(): array { return [ + ActivityTimelineAction::make(), EditAction::make(), ]; } diff --git a/app/Filament/Resources/UnpaidLeaves/Pages/ViewUnpaidLeave.php b/app/Filament/Resources/UnpaidLeaves/Pages/ViewUnpaidLeave.php index c642517..687847f 100644 --- a/app/Filament/Resources/UnpaidLeaves/Pages/ViewUnpaidLeave.php +++ b/app/Filament/Resources/UnpaidLeaves/Pages/ViewUnpaidLeave.php @@ -3,6 +3,7 @@ namespace App\Filament\Resources\UnpaidLeaves\Pages; use App\Filament\Resources\UnpaidLeaves\UnpaidLeaveResource; +use BokshornIt\FilamentActivityTimeline\Actions\ActivityTimelineAction; use Filament\Actions\EditAction; use Filament\Resources\Pages\ViewRecord; @@ -13,6 +14,7 @@ class ViewUnpaidLeave extends ViewRecord protected function getHeaderActions(): array { return [ + ActivityTimelineAction::make(), EditAction::make(), ]; } diff --git a/app/Filament/Resources/Vacations/Pages/ViewVacation.php b/app/Filament/Resources/Vacations/Pages/ViewVacation.php index e1a8fd2..dbe5de2 100644 --- a/app/Filament/Resources/Vacations/Pages/ViewVacation.php +++ b/app/Filament/Resources/Vacations/Pages/ViewVacation.php @@ -3,6 +3,7 @@ namespace App\Filament\Resources\Vacations\Pages; use App\Filament\Resources\Vacations\VacationResource; +use BokshornIt\FilamentActivityTimeline\Actions\ActivityTimelineAction; use Filament\Actions\EditAction; use Filament\Resources\Pages\ViewRecord; @@ -13,6 +14,7 @@ class ViewVacation extends ViewRecord protected function getHeaderActions(): array { return [ + ActivityTimelineAction::make(), EditAction::make(), ]; } diff --git a/app/Models/Bonus.php b/app/Models/Bonus.php index ee4fb22..7b79cb9 100644 --- a/app/Models/Bonus.php +++ b/app/Models/Bonus.php @@ -6,12 +6,13 @@ namespace App\Models; use App\Enums\BonusType; use App\Models\Concerns\LogsHrActivity; +use BokshornIt\FilamentActivityTimeline\Contracts\ProvidesActivityTitle; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\SoftDeletes; -class Bonus extends Model +class Bonus extends Model implements ProvidesActivityTitle { use HasFactory; use LogsHrActivity; diff --git a/app/Models/Concerns/LogsHrActivity.php b/app/Models/Concerns/LogsHrActivity.php index cb96181..3228a7b 100644 --- a/app/Models/Concerns/LogsHrActivity.php +++ b/app/Models/Concerns/LogsHrActivity.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace App\Models\Concerns; +use BokshornIt\FilamentActivityTimeline\Contracts\ProvidesActivityTitle; use Spatie\Activitylog\LogOptions; use Spatie\Activitylog\Traits\LogsActivity; @@ -18,4 +19,29 @@ trait LogsHrActivity ->logOnlyDirty() ->dontSubmitEmptyLogs(); } + + public function activityTitle(): ?string + { + foreach (['full_name', 'name', 'title', 'gift_name', 'employee_number'] as $attribute) { + $value = $this->getAttribute($attribute); + + if (filled($value)) { + return (string) $value; + } + } + + if ($this->getAttribute('employee_id')) { + $employeeName = $this->relationLoaded('employee') + ? $this->employee?->full_name + : $this->employee()->value('full_name'); + + if (filled($employeeName)) { + return (string) $employeeName; + } + } + + $key = $this->getKey(); + + return $key !== null ? '#'.$key : null; + } } diff --git a/app/Models/Department.php b/app/Models/Department.php index 871851b..56f52a6 100644 --- a/app/Models/Department.php +++ b/app/Models/Department.php @@ -5,13 +5,14 @@ declare(strict_types=1); namespace App\Models; use App\Models\Concerns\LogsHrActivity; +use BokshornIt\FilamentActivityTimeline\Contracts\ProvidesActivityTitle; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\Str; -class Department extends Model +class Department extends Model implements ProvidesActivityTitle { use HasFactory; use LogsHrActivity; diff --git a/app/Models/DisciplinaryReport.php b/app/Models/DisciplinaryReport.php index e017d4d..30acfef 100644 --- a/app/Models/DisciplinaryReport.php +++ b/app/Models/DisciplinaryReport.php @@ -6,12 +6,13 @@ namespace App\Models; use App\Enums\DisciplinarySeverity; use App\Models\Concerns\LogsHrActivity; +use BokshornIt\FilamentActivityTimeline\Contracts\ProvidesActivityTitle; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\SoftDeletes; -class DisciplinaryReport extends Model +class DisciplinaryReport extends Model implements ProvidesActivityTitle { use HasFactory; use LogsHrActivity; diff --git a/app/Models/Employee.php b/app/Models/Employee.php index 75ff2dc..0aa5e27 100644 --- a/app/Models/Employee.php +++ b/app/Models/Employee.php @@ -7,13 +7,14 @@ namespace App\Models; use App\Enums\EmploymentStatus; use App\Enums\Gender; use App\Models\Concerns\LogsHrActivity; +use BokshornIt\FilamentActivityTimeline\Contracts\ProvidesActivityTitle; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; -class Employee extends Model +class Employee extends Model implements ProvidesActivityTitle { use HasFactory; use LogsHrActivity; diff --git a/app/Models/EmployeeDocument.php b/app/Models/EmployeeDocument.php index 23225f7..e7342c4 100644 --- a/app/Models/EmployeeDocument.php +++ b/app/Models/EmployeeDocument.php @@ -6,12 +6,13 @@ namespace App\Models; use App\Enums\DocumentType; use App\Models\Concerns\LogsHrActivity; +use BokshornIt\FilamentActivityTimeline\Contracts\ProvidesActivityTitle; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\SoftDeletes; -class EmployeeDocument extends Model +class EmployeeDocument extends Model implements ProvidesActivityTitle { use HasFactory; use LogsHrActivity; diff --git a/app/Models/Explanation.php b/app/Models/Explanation.php index 3dc13bf..cd1c0a3 100644 --- a/app/Models/Explanation.php +++ b/app/Models/Explanation.php @@ -5,12 +5,13 @@ declare(strict_types=1); namespace App\Models; use App\Models\Concerns\LogsHrActivity; +use BokshornIt\FilamentActivityTimeline\Contracts\ProvidesActivityTitle; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\SoftDeletes; -class Explanation extends Model +class Explanation extends Model implements ProvidesActivityTitle { use HasFactory; use LogsHrActivity; diff --git a/app/Models/Gift.php b/app/Models/Gift.php index df848ce..83b2775 100644 --- a/app/Models/Gift.php +++ b/app/Models/Gift.php @@ -5,12 +5,13 @@ declare(strict_types=1); namespace App\Models; use App\Models\Concerns\LogsHrActivity; +use BokshornIt\FilamentActivityTimeline\Contracts\ProvidesActivityTitle; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\SoftDeletes; -class Gift extends Model +class Gift extends Model implements ProvidesActivityTitle { use HasFactory; use LogsHrActivity; diff --git a/app/Models/Position.php b/app/Models/Position.php index 6a3a3d0..a5cf742 100644 --- a/app/Models/Position.php +++ b/app/Models/Position.php @@ -5,12 +5,13 @@ declare(strict_types=1); namespace App\Models; use App\Models\Concerns\LogsHrActivity; +use BokshornIt\FilamentActivityTimeline\Contracts\ProvidesActivityTitle; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; -class Position extends Model +class Position extends Model implements ProvidesActivityTitle { use HasFactory; use LogsHrActivity; diff --git a/app/Models/Shift.php b/app/Models/Shift.php index 22e5bbb..78bb4b8 100644 --- a/app/Models/Shift.php +++ b/app/Models/Shift.php @@ -5,13 +5,14 @@ declare(strict_types=1); namespace App\Models; use App\Models\Concerns\LogsHrActivity; +use BokshornIt\FilamentActivityTimeline\Contracts\ProvidesActivityTitle; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\Str; -class Shift extends Model +class Shift extends Model implements ProvidesActivityTitle { use HasFactory; use LogsHrActivity; diff --git a/app/Models/SickLeave.php b/app/Models/SickLeave.php index 7701ec3..ceb6b62 100644 --- a/app/Models/SickLeave.php +++ b/app/Models/SickLeave.php @@ -5,12 +5,13 @@ declare(strict_types=1); namespace App\Models; use App\Models\Concerns\LogsHrActivity; +use BokshornIt\FilamentActivityTimeline\Contracts\ProvidesActivityTitle; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\SoftDeletes; -class SickLeave extends Model +class SickLeave extends Model implements ProvidesActivityTitle { use HasFactory; use LogsHrActivity; diff --git a/app/Models/UnpaidLeave.php b/app/Models/UnpaidLeave.php index e0804a7..e1b7c4c 100644 --- a/app/Models/UnpaidLeave.php +++ b/app/Models/UnpaidLeave.php @@ -6,12 +6,13 @@ namespace App\Models; use App\Enums\ApprovalStatus; use App\Models\Concerns\LogsHrActivity; +use BokshornIt\FilamentActivityTimeline\Contracts\ProvidesActivityTitle; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\SoftDeletes; -class UnpaidLeave extends Model +class UnpaidLeave extends Model implements ProvidesActivityTitle { use HasFactory; use LogsHrActivity; diff --git a/app/Models/Vacation.php b/app/Models/Vacation.php index 0a1b996..872397e 100644 --- a/app/Models/Vacation.php +++ b/app/Models/Vacation.php @@ -7,12 +7,13 @@ namespace App\Models; use App\Enums\ApprovalStatus; use App\Enums\VacationType; use App\Models\Concerns\LogsHrActivity; +use BokshornIt\FilamentActivityTimeline\Contracts\ProvidesActivityTitle; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\SoftDeletes; -class Vacation extends Model +class Vacation extends Model implements ProvidesActivityTitle { use HasFactory; use LogsHrActivity; diff --git a/app/Policies/ActivityPolicy.php b/app/Policies/ActivityPolicy.php new file mode 100644 index 0000000..90395ba --- /dev/null +++ b/app/Policies/ActivityPolicy.php @@ -0,0 +1,92 @@ +canAccessAuditLog($user)) { + return true; + } + + return $user->can('ViewAny:Activity'); + } + + public function view(AuthUser $user, Activity $activity): bool + { + if ($this->canAccessAuditLog($user)) { + return true; + } + + return $user->can('View:Activity'); + } + + public function create(AuthUser $user): bool + { + return false; + } + + public function update(AuthUser $user, Activity $activity): bool + { + return false; + } + + public function delete(AuthUser $user, Activity $activity): bool + { + return false; + } + + public function deleteAny(AuthUser $user): bool + { + return false; + } + + public function forceDelete(AuthUser $user, Activity $activity): bool + { + return false; + } + + public function forceDeleteAny(AuthUser $user): bool + { + return false; + } + + public function restore(AuthUser $user, Activity $activity): bool + { + return false; + } + + public function restoreAny(AuthUser $user): bool + { + return false; + } + + public function replicate(AuthUser $user, Activity $activity): bool + { + return false; + } + + public function reorder(AuthUser $user): bool + { + return false; + } + + protected function canAccessAuditLog(AuthUser $user): bool + { + if (! $user instanceof User) { + return false; + } + + return $user->hasRole(['super_admin', 'administrator', 'hr_manager']); + } +} diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index cbccbf5..f4e1d06 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -22,6 +22,7 @@ use App\Observers\EmployeeDocumentObserver; use App\Observers\SickLeaveObserver; use App\Observers\UnpaidLeaveObserver; use App\Observers\VacationObserver; +use App\Policies\ActivityPolicy; use App\Policies\BonusPolicy; use App\Policies\DepartmentPolicy; use App\Policies\DisciplinaryReportPolicy; @@ -41,6 +42,7 @@ use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Gate; use Illuminate\Support\ServiceProvider; +use Spatie\Activitylog\Models\Activity; class AppServiceProvider extends ServiceProvider { @@ -70,6 +72,7 @@ class AppServiceProvider extends ServiceProvider Gate::policy(Gift::class, GiftPolicy::class); Gate::policy(EmployeeDocument::class, EmployeeDocumentPolicy::class); Gate::policy(User::class, UserPolicy::class); + Gate::policy(Activity::class, ActivityPolicy::class); Vacation::observe(VacationObserver::class); SickLeave::observe(SickLeaveObserver::class); diff --git a/app/Providers/Filament/AdminPanelProvider.php b/app/Providers/Filament/AdminPanelProvider.php index b5b05cb..93e7a53 100644 --- a/app/Providers/Filament/AdminPanelProvider.php +++ b/app/Providers/Filament/AdminPanelProvider.php @@ -5,8 +5,11 @@ declare(strict_types=1); namespace App\Providers\Filament; use App\Enums\NavigationGroup as NavigationGroupEnum; +use App\Filament\ActivityTimeline\AuditLogResource; use App\Filament\Pages\Dashboard; +use App\Models\User; use BezhanSalleh\FilamentShield\FilamentShieldPlugin; +use BokshornIt\FilamentActivityTimeline\ActivityTimelinePlugin; use Filament\FontProviders\GoogleFontProvider; use Filament\Http\Middleware\Authenticate; use Filament\Http\Middleware\AuthenticateSession; @@ -58,6 +61,17 @@ class AdminPanelProvider extends PanelProvider ->plugins([ FilamentShieldPlugin::make() ->navigationGroup(NavigationGroupEnum::System), + ActivityTimelinePlugin::make() + ->resource(AuditLogResource::class) + ->navigationGroup(fn (): string => NavigationGroupEnum::System->getLabel()) + ->navigationIcon('heroicon-o-clipboard-document-list') + ->navigationSort(3) + ->causerIcons([ + User::class => 'heroicon-m-user', + ]) + ->systemCauserIcon('heroicon-m-cog-6-tooth') + ->subjectLabelNamespace('hr.audit') + ->fieldLabelNamespace('changes'), ]) ->middleware([ EncryptCookies::class, diff --git a/composer.json b/composer.json index cc89112..101d507 100644 --- a/composer.json +++ b/composer.json @@ -10,6 +10,7 @@ "barryvdh/laravel-dompdf": "^3.1", "bezhansalleh/filament-language-switch": "^5.0", "bezhansalleh/filament-shield": "^4.3", + "bokshorn-it/filament-activity-timeline": "^1.1", "filament/filament": "^5.0", "laravel/framework": "^13.8", "laravel/tinker": "^3.0", diff --git a/composer.lock b/composer.lock index 4dd10b3..cbef2e4 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "be3c3ff78f2eaafd723ef2e5a6c235ca", + "content-hash": "fe3691444d10935e9897896d11e11add", "packages": [ { "name": "anourvalar/eloquent-serialize", @@ -558,6 +558,74 @@ ], "time": "2026-06-30T09:44:12+00:00" }, + { + "name": "bokshorn-it/filament-activity-timeline", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/Bokshorn-IT/filament-activity-timeline.git", + "reference": "be5f38398c2618c4757530d1f28984c6a4d427af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Bokshorn-IT/filament-activity-timeline/zipball/be5f38398c2618c4757530d1f28984c6a4d427af", + "reference": "be5f38398c2618c4757530d1f28984c6a4d427af", + "shasum": "" + }, + "require": { + "filament/filament": "^5.0", + "illuminate/contracts": "^12.0|^13.0", + "php": "^8.3", + "spatie/laravel-activitylog": "^4.12|^5.0", + "spatie/laravel-package-tools": "^1.92" + }, + "require-dev": { + "laravel/pint": "^1.27", + "orchestra/testbench": "^10.0|^11.0", + "pestphp/pest": "^4.0", + "pestphp/pest-plugin-laravel": "^4.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "BokshornIt\\FilamentActivityTimeline\\FilamentActivityTimelineServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "BokshornIt\\FilamentActivityTimeline\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Johannes Bokshorn", + "role": "Developer" + } + ], + "description": "A Filament plugin that turns spatie/laravel-activitylog into a readable audit trail: a record timeline, a filterable activity resource, and diffs that resolve enums, dates and foreign keys to human labels.", + "homepage": "https://github.com/Bokshorn-IT/filament-activity-timeline", + "keywords": [ + "activitylog", + "audit-trail", + "filament", + "filament-plugin", + "filamentphp", + "laravel", + "timeline" + ], + "support": { + "issues": "https://github.com/Bokshorn-IT/filament-activity-timeline/issues", + "security": "https://github.com/Bokshorn-IT/filament-activity-timeline/security/policy", + "source": "https://github.com/Bokshorn-IT/filament-activity-timeline" + }, + "time": "2026-07-28T23:08:55+00:00" + }, { "name": "brick/math", "version": "0.18.0", diff --git a/lang/en/changes.php b/lang/en/changes.php new file mode 100644 index 0000000..9c51466 --- /dev/null +++ b/lang/en/changes.php @@ -0,0 +1,50 @@ + 'Employee', + 'department_id' => 'Department', + 'position_id' => 'Position', + 'shift_id' => 'Shift', + 'employee_number' => 'Employee Number', + 'full_name' => 'Full Name', + 'national_id' => 'Nationality', + 'gender' => 'Gender', + 'birth_date' => 'Birth Date', + 'phone' => 'Phone', + 'address' => 'Address', + 'employment_status' => 'Employment Status', + 'hire_date' => 'Hire Date', + 'termination_date' => 'Termination Date', + 'notes' => 'Notes', + 'profile_photo_path' => 'Profile Photo', + 'status' => 'Status', + 'type' => 'Type', + 'start_date' => 'Start Date', + 'end_date' => 'End Date', + 'return_date' => 'Return Date', + 'days' => 'Days', + 'reason' => 'Reason', + 'attachment_path' => 'Attachment', + 'document_path' => 'Document', + 'approved_by' => 'Approved By', + 'approved_at' => 'Approved At', + 'bonus_date' => 'Bonus Date', + 'bonus_type' => 'Bonus Type', + 'amount' => 'Amount', + 'gift_date' => 'Gift Date', + 'gift_name' => 'Gift Name', + 'value' => 'Value', + 'document_type' => 'Document Type', + 'title' => 'Title', + 'file_path' => 'File', + 'uploaded_at' => 'Uploaded At', + 'severity' => 'Severity', + 'report_date' => 'Report Date', + 'description' => 'Description', + 'medical_institution' => 'Medical Institution', + 'name' => 'Name', + 'code' => 'Code', + 'is_active' => 'Active', +]; diff --git a/lang/en/hr.php b/lang/en/hr.php index b7f2f91..98b9649 100644 --- a/lang/en/hr.php +++ b/lang/en/hr.php @@ -186,6 +186,13 @@ return [ 'disciplinary_report' => 'Disciplinary Report', 'department' => 'Department', 'user' => 'User', + 'position' => 'Position', + 'shift' => 'Shift', + 'sick_leave' => 'Sick Leave', + 'unpaid_leave' => 'Unpaid Leave', + 'explanation' => 'Explanation', + 'gift' => 'Gift', + 'employee_document' => 'Employee Document', ], 'widgets' => [ diff --git a/lang/ru/changes.php b/lang/ru/changes.php new file mode 100644 index 0000000..ac79d33 --- /dev/null +++ b/lang/ru/changes.php @@ -0,0 +1,50 @@ + 'Сотрудник', + 'department_id' => 'Отдел', + 'position_id' => 'Должность', + 'shift_id' => 'Смена', + 'employee_number' => 'Табельный номер', + 'full_name' => 'ФИО', + 'national_id' => 'Национальность', + 'gender' => 'Пол', + 'birth_date' => 'Дата рождения', + 'phone' => 'Телефон', + 'address' => 'Адрес', + 'employment_status' => 'Статус занятости', + 'hire_date' => 'Дата приёма', + 'termination_date' => 'Дата увольнения', + 'notes' => 'Примечания', + 'profile_photo_path' => 'Фото профиля', + 'status' => 'Статус', + 'type' => 'Тип', + 'start_date' => 'Дата начала', + 'end_date' => 'Дата окончания', + 'return_date' => 'Дата возвращения', + 'days' => 'Дни', + 'reason' => 'Причина', + 'attachment_path' => 'Вложение', + 'document_path' => 'Документ', + 'approved_by' => 'Утвердил', + 'approved_at' => 'Дата утверждения', + 'bonus_date' => 'Дата премии', + 'bonus_type' => 'Тип премии', + 'amount' => 'Сумма', + 'gift_date' => 'Дата подарка', + 'gift_name' => 'Название подарка', + 'value' => 'Стоимость', + 'document_type' => 'Тип документа', + 'title' => 'Название', + 'file_path' => 'Файл', + 'uploaded_at' => 'Дата загрузки', + 'severity' => 'Серьёзность', + 'report_date' => 'Дата отчёта', + 'description' => 'Описание', + 'medical_institution' => 'Медицинское учреждение', + 'name' => 'Название', + 'code' => 'Код', + 'is_active' => 'Активен', +]; diff --git a/lang/ru/hr.php b/lang/ru/hr.php index e0230a5..6cb4053 100644 --- a/lang/ru/hr.php +++ b/lang/ru/hr.php @@ -186,6 +186,13 @@ return [ 'disciplinary_report' => 'Дисциплинарный отчёт', 'department' => 'Отдел', 'user' => 'Пользователь', + 'position' => 'Должность', + 'shift' => 'Смена', + 'sick_leave' => 'Больничный', + 'unpaid_leave' => 'Неоплачиваемый отпуск', + 'explanation' => 'Объяснительная', + 'gift' => 'Подарок', + 'employee_document' => 'Документ сотрудника', ], 'widgets' => [ diff --git a/lang/tk/changes.php b/lang/tk/changes.php new file mode 100644 index 0000000..3222e48 --- /dev/null +++ b/lang/tk/changes.php @@ -0,0 +1,50 @@ + 'Işgär', + 'department_id' => 'Bölüm', + 'position_id' => 'Wezipesi', + 'shift_id' => 'Smena', + 'employee_number' => 'Işgär belgisi', + 'full_name' => 'Doly ady', + 'national_id' => 'Raýatlygy', + 'gender' => 'Jyns', + 'birth_date' => 'Doglan senesi', + 'phone' => 'Telefon', + 'address' => 'Salgy', + 'employment_status' => 'Işe alnyş ýagdaýy', + 'hire_date' => 'Işe alnan senesi', + 'termination_date' => 'Işden boşadylan senesi', + 'notes' => 'Bellikler', + 'profile_photo_path' => 'Profil suraty', + 'status' => 'Ýagdaýy', + 'type' => 'Görnüşi', + 'start_date' => 'Başlanan senesi', + 'end_date' => 'Gutarýan senesi', + 'return_date' => 'Yzyna gelen senesi', + 'days' => 'Günler', + 'reason' => 'Sebäp', + 'attachment_path' => 'Goşmaça', + 'document_path' => 'Resminama', + 'approved_by' => 'Tassyklady', + 'approved_at' => 'Tassyklanan senesi', + 'bonus_date' => 'Baýrak senesi', + 'bonus_type' => 'Baýrak görnüşi', + 'amount' => 'Mukdary', + 'gift_date' => 'Sowgat senesi', + 'gift_name' => 'Sowgat ady', + 'value' => 'Bahasy', + 'document_type' => 'Resminama görnüşi', + 'title' => 'Ady', + 'file_path' => 'Faýl', + 'uploaded_at' => 'Ýüklenen senesi', + 'severity' => 'Agyrlygy', + 'report_date' => 'Hasabat senesi', + 'description' => 'Düşündiriş', + 'medical_institution' => 'Lukmançylyk edarasy', + 'name' => 'Ady', + 'code' => 'Kod', + 'is_active' => 'Işjeň', +]; diff --git a/lang/tk/hr.php b/lang/tk/hr.php index 5961345..5d00601 100644 --- a/lang/tk/hr.php +++ b/lang/tk/hr.php @@ -186,6 +186,13 @@ return [ 'disciplinary_report' => 'Terbiýe hasabaty', 'department' => 'Bölüm', 'user' => 'Ulanyjy', + 'position' => 'Wezipesi', + 'shift' => 'Smena', + 'sick_leave' => 'Kesel rugsady', + 'unpaid_leave' => 'Tölegsiz dynç alyş', + 'explanation' => 'Düşündiriş', + 'gift' => 'Sowgat', + 'employee_document' => 'Işgär resminamasy', ], 'widgets' => [ diff --git a/resources/css/filament/admin/theme.css b/resources/css/filament/admin/theme.css index 68bf707..059e505 100644 --- a/resources/css/filament/admin/theme.css +++ b/resources/css/filament/admin/theme.css @@ -3,3 +3,4 @@ @source '../../../../app/Filament/**/*'; @source '../../../../resources/views/filament/**/*'; @source '../../../../vendor/bezhansalleh/filament-language-switch/**'; +@source '../../../../vendor/bokshorn-it/filament-activity-timeline/resources/**/*.blade.php'; diff --git a/tests/Feature/Filament/PanelAccessTest.php b/tests/Feature/Filament/PanelAccessTest.php index 6a49d34..efbdc02 100644 --- a/tests/Feature/Filament/PanelAccessTest.php +++ b/tests/Feature/Filament/PanelAccessTest.php @@ -17,6 +17,14 @@ it('allows authenticated super admin users to access the admin panel', function ->assertSuccessful(); }); +it('allows authenticated super admin users to access the audit log page', function (): void { + $admin = createAdminUser(); + + $this->actingAs($admin) + ->get('/admin/activity-logs') + ->assertSuccessful(); +}); + it('redirects authenticated non-admin users without panel access', function (): void { seedRoles(); diff --git a/tests/Feature/LocalizationTest.php b/tests/Feature/LocalizationTest.php index 90180f5..ed2e9db 100644 --- a/tests/Feature/LocalizationTest.php +++ b/tests/Feature/LocalizationTest.php @@ -5,7 +5,7 @@ declare(strict_types=1); use App\Enums\EmploymentStatus; use App\Enums\Gender; use App\Enums\NavigationGroup; -use App\Filament\Resources\ActivityLogs\ActivityLogResource; +use App\Filament\ActivityTimeline\AuditLogResource; use App\Filament\Resources\Departments\DepartmentResource; use App\Models\User; use BezhanSalleh\LanguageSwitch\Events\LocaleChanged; @@ -68,11 +68,11 @@ it('returns translated filament navigation group labels at request time', functi it('returns translated filament resource navigation labels', function (): void { App::setLocale('tk'); - expect(ActivityLogResource::getNavigationLabel())->toBe('Audit žurnaly'); + expect(AuditLogResource::getNavigationLabel())->toBe('Audit žurnaly'); App::setLocale('ru'); - expect(ActivityLogResource::getNavigationLabel())->toBe('Журнал аудита'); + expect(AuditLogResource::getNavigationLabel())->toBe('Журнал аудита'); }); it('returns translated filament resource model labels', function (): void {