chore(admin): activity logs (#1197)

This commit is contained in:
Kyrch
2026-05-07 21:33:57 -03:00
committed by GitHub
parent f5e098875f
commit a3f1a8c7e3
40 changed files with 428 additions and 896 deletions
@@ -5,7 +5,7 @@ declare(strict_types=1);
namespace App\Actions\Storage\Admin\Dump; namespace App\Actions\Storage\Admin\Dump;
use App\Concerns\Repositories\Admin\ReconcilesDumpRepositories; use App\Concerns\Repositories\Admin\ReconcilesDumpRepositories;
use App\Models\Admin\ActionLog; use App\Models\Admin\Activity;
use App\Models\Admin\Announcement; use App\Models\Admin\Announcement;
use App\Models\Admin\Dump; use App\Models\Admin\Dump;
use App\Models\Admin\Feature; use App\Models\Admin\Feature;
@@ -27,7 +27,8 @@ class DumpAdminAction extends DumpAction
{ {
return [ return [
'action_events', // Nova events 'action_events', // Nova events
ActionLog::TABLE, 'action_logs',
Activity::TABLE,
Announcement::TABLE, Announcement::TABLE,
Dump::TABLE, Dump::TABLE,
Feature::TABLE, Feature::TABLE,
@@ -1,86 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Concerns\Filament\ActionLogs;
use App\Models\Admin\ActionLog;
use Filament\Actions\Action;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
use Throwable;
trait HasActionLogs
{
protected string $batchId = '';
protected ?ActionLog $actionLog = null;
protected ?Model $recordLog = null;
protected ?Model $parentRecordLog = null;
protected ?Model $pivot = null;
public function createBatchId(): string
{
$this->batchId = Str::orderedUuid()->__toString();
return $this->batchId;
}
public function createActionLog(Action $action, Model $record, ?bool $shouldCreateNewBatchId = true): void
{
if ($shouldCreateNewBatchId) {
$this->createBatchId();
}
$this->recordLog = $record;
$actionLog = ActionLog::modelActioned(
$this->batchId,
$action,
$this->recordLog,
);
$this->actionLog = $actionLog;
}
public function updateLog(Model $relatedModel, Model $pivot): void
{
$this->actionLog->update([
ActionLog::ATTRIBUTE_TARGET_TYPE => $relatedModel->getMorphClass(),
ActionLog::ATTRIBUTE_TARGET_ID => $relatedModel->getKey(),
ActionLog::ATTRIBUTE_MODEL_TYPE => $pivot->getMorphClass(),
ActionLog::ATTRIBUTE_MODEL_ID => $pivot->getKey(),
]);
}
public function failedLog(Throwable|string|null $exception): void
{
$this->actionLog->failed($exception);
// Filament notifications
if ($this instanceof Action) {
$this->failureNotificationTitle(Str::limit($exception, 200));
$this->failure();
}
}
public function finishedLog(): void
{
if (($actionLog = $this->actionLog) && ! $this->hasFailedLog()) {
$actionLog->finished();
// Filament notifications
if ($this instanceof Action) {
$this->success();
}
}
}
public function batchFinishedLog(): void
{
$this->actionLog->batchFinished();
}
public function hasFailedLog(): bool
{
return $this->actionLog->hasFailed();
}
}
@@ -1,48 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Concerns\Filament\ActionLogs;
use App\Filament\RelationManagers\BaseRelationManager;
use App\Models\Admin\ActionLog;
use Filament\Actions\Action;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
trait HasPivotActionLogs
{
public function pivotActionLog(string $actionName, BaseRelationManager $livewire, Model $record, ?Action $action = null): void
{
$ownerRecord = $livewire->getOwnerRecord();
$relation = $livewire->getRelationship();
if ($relation instanceof BelongsToMany) {
ActionLog::modelPivot(
$actionName,
$ownerRecord,
$record,
$record->getRelationValue($relation->getPivotAccessor()) ?? $record,
$action,
);
}
}
public function associateActionLog(string $actionName, BaseRelationManager $livewire, Model $record, Action $action): void
{
$ownerRecord = $livewire->getOwnerRecord();
$relation = $livewire->getRelationship();
if ($relation instanceof HasMany) {
ActionLog::modelAssociated(
$actionName,
$ownerRecord,
$record,
$action,
);
}
}
}
@@ -1,16 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Concerns\Filament\ActionLogs;
use App\Models\Admin\ActionLog;
use Illuminate\Database\Eloquent\Relations\MorphMany;
trait ModelHasActionLogs
{
public function actionlogs(): MorphMany
{
return $this->morphMany(ActionLog::class, 'actionable');
}
}
+66
View File
@@ -0,0 +1,66 @@
<?php
declare(strict_types=1);
namespace App\Concerns\Filament;
use App\Enums\Models\Admin\ActivityStatus;
use App\Models\Admin\Activity;
use Filament\Actions\Action;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
use Spatie\Activitylog\Contracts\Activity as ContractsActivity;
use Throwable;
trait HasActivityLogs
{
protected ?Activity $activity = null;
public function createActivityLog(Action $action, Model $record): void
{
/** @phpstan-ignore-next-line */
$this->activity = activity()
->performedOn($record)
->withProperties($action->getData())
->tap(function (Activity $activity): void {
$activity->status = ActivityStatus::RUNNING;
})
->event($action->getLabel())
->log('actioned');
}
public function failedLog(Throwable|string|null $exception): void
{
$this->activity?->update([
Activity::ATTRIBUTE_STATUS => ActivityStatus::FAILED,
Activity::ATTRIBUTE_EXCEPTION => Str::limit($exception, 200),
Activity::ATTRIBUTE_FINISHED_AT => now(),
]);
// Filament notifications
if ($this instanceof Action) {
$this->failureNotificationTitle(Str::limit($exception, 200));
$this->failure();
}
}
public function finishedLog(): void
{
if (! $this->hasFailedLog()) {
$this->activity?->update([
Activity::ATTRIBUTE_STATUS => ActivityStatus::FINISHED,
Activity::ATTRIBUTE_FINISHED_AT => now(),
]);
// Filament notifications
if ($this instanceof Action) {
$this->success();
}
}
}
public function hasFailedLog(): bool
{
return $this->activity?->status === ActivityStatus::FAILED;
}
}
@@ -9,7 +9,7 @@ use Filament\Support\Colors\Color;
use Filament\Support\Contracts\HasColor; use Filament\Support\Contracts\HasColor;
use Filament\Support\Contracts\HasLabel; use Filament\Support\Contracts\HasLabel;
enum ActionLogStatus: int implements HasColor, HasLabel enum ActivityStatus: int implements HasColor, HasLabel
{ {
use LocalizesName; use LocalizesName;
@@ -25,9 +25,9 @@ enum ActionLogStatus: int implements HasColor, HasLabel
public function getColor(): string|array public function getColor(): string|array
{ {
return match ($this) { return match ($this) {
ActionLogStatus::RUNNING => Color::Amber, ActivityStatus::RUNNING => Color::Amber,
ActionLogStatus::FAILED => 'danger', ActivityStatus::FAILED => 'danger',
ActionLogStatus::FINISHED => 'success', ActivityStatus::FINISHED => 'success',
}; };
} }
} }
+1 -7
View File
@@ -4,8 +4,6 @@ declare(strict_types=1);
namespace App\Exceptions; namespace App\Exceptions;
use App\Models\Admin\ActionLog;
use Filament\Facades\Filament;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Throwable; use Throwable;
@@ -27,10 +25,6 @@ class Handler extends ExceptionHandler
*/ */
public function register(): void public function register(): void
{ {
$this->reportable(function (Throwable $e): void { $this->reportable(function (Throwable $e): void {});
if (Filament::isServing() && $this->shouldReport($e)) {
ActionLog::updateCurrentActionLogToFailed($e);
}
});
} }
} }
+1 -13
View File
@@ -4,10 +4,8 @@ declare(strict_types=1);
namespace App\Filament\Actions\Base; namespace App\Filament\Actions\Base;
use App\Concerns\Filament\ActionLogs\HasPivotActionLogs;
use App\Filament\Components\Fields\Select; use App\Filament\Components\Fields\Select;
use App\Filament\RelationManagers\BaseRelationManager; use App\Filament\RelationManagers\BaseRelationManager;
use App\Models\Admin\ActionLog;
use App\Models\Wiki\Image; use App\Models\Wiki\Image;
use Filament\Actions\AttachAction as BaseAttachAction; use Filament\Actions\AttachAction as BaseAttachAction;
use Filament\Facades\Filament; use Filament\Facades\Filament;
@@ -20,8 +18,6 @@ use Illuminate\Support\Str;
class AttachAction extends BaseAttachAction class AttachAction extends BaseAttachAction
{ {
use HasPivotActionLogs;
protected function setUp(): void protected function setUp(): void
{ {
parent::setUp(); parent::setUp();
@@ -56,13 +52,7 @@ class AttachAction extends BaseAttachAction
if ($this->shouldShowCreateOption($model)) { if ($this->shouldShowCreateOption($model)) {
return $select return $select
->createOptionForm(fn (Schema $schema) => Filament::getModelResource($model)::form($schema)->getComponents()) ->createOptionForm(fn (Schema $schema) => Filament::getModelResource($model)::form($schema)->getComponents())
->createOptionUsing(function (array $data) use ($model) { ->createOptionUsing(fn (array $data) => $model::query()->create($data)->getKey());
$created = $model::query()->create($data);
ActionLog::modelCreated($created);
return $created->getKey();
});
} }
return $select; return $select;
@@ -72,8 +62,6 @@ class AttachAction extends BaseAttachAction
$action->getRecordSelect(), $action->getRecordSelect(),
...$livewire->getPivotComponents(), ...$livewire->getPivotComponents(),
]); ]);
$this->after(fn (BaseRelationManager $livewire, Model $record, AttachAction $action) => $this->pivotActionLog('Attach', $livewire, $record, $action));
} }
/** /**
@@ -4,23 +4,18 @@ declare(strict_types=1);
namespace App\Filament\Actions\Base; namespace App\Filament\Actions\Base;
use App\Concerns\Filament\ActionLogs\HasPivotActionLogs;
use App\Filament\RelationManagers\BaseRelationManager; use App\Filament\RelationManagers\BaseRelationManager;
use App\Filament\Resources\Base\BaseListResources; use App\Filament\Resources\Base\BaseListResources;
use App\Filament\Resources\Base\BaseManageResources; use App\Filament\Resources\Base\BaseManageResources;
use App\Models\Admin\ActionLog;
use Filament\Actions\CreateAction as BaseCreateAction; use Filament\Actions\CreateAction as BaseCreateAction;
use Filament\Facades\Filament; use Filament\Facades\Filament;
use Filament\Schemas\Schema; use Filament\Schemas\Schema;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\Gate;
class CreateAction extends BaseCreateAction class CreateAction extends BaseCreateAction
{ {
use HasPivotActionLogs;
protected function setUp(): void protected function setUp(): void
{ {
parent::setUp(); parent::setUp();
@@ -38,20 +33,6 @@ class CreateAction extends BaseCreateAction
return null; return null;
}); });
$this->after(function (BaseManageResources|BaseListResources|BaseRelationManager $livewire, Model $record, CreateAction $action): void {
if ($livewire instanceof BaseListResources) {
ActionLog::modelCreated($record);
}
if ($livewire instanceof BaseRelationManager) {
$relationship = $livewire->getRelationship();
if ($relationship instanceof HasMany) {
$this->associateActionLog('Create and Associate', $livewire, $record, $action);
}
}
});
$this->visible(function (BaseManageResources|BaseListResources|BaseRelationManager $livewire, string $model): bool { $this->visible(function (BaseManageResources|BaseListResources|BaseRelationManager $livewire, string $model): bool {
if ($livewire instanceof BaseRelationManager && $livewire->getRelationship() instanceof BelongsToMany) { if ($livewire instanceof BaseRelationManager && $livewire->getRelationship() instanceof BelongsToMany) {
return false; return false;
@@ -5,7 +5,6 @@ declare(strict_types=1);
namespace App\Filament\Actions\Base; namespace App\Filament\Actions\Base;
use App\Actions\Http\Api\List\Playlist\Track\DestroyTrackAction; use App\Actions\Http\Api\List\Playlist\Track\DestroyTrackAction;
use App\Models\Admin\ActionLog;
use App\Models\List\Playlist\PlaylistTrack; use App\Models\List\Playlist\PlaylistTrack;
use Filament\Actions\DeleteAction as BaseDeleteAction; use Filament\Actions\DeleteAction as BaseDeleteAction;
use Filament\Support\Icons\Heroicon; use Filament\Support\Icons\Heroicon;
@@ -36,8 +35,6 @@ class DeleteAction extends BaseDeleteAction
return (bool) $result; return (bool) $result;
}); });
$this->after(fn (Model $record): ActionLog => ActionLog::modelDeleted($record));
$this->authorize(true); $this->authorize(true);
} }
} }
@@ -4,13 +4,11 @@ declare(strict_types=1);
namespace App\Filament\Actions\Base; namespace App\Filament\Actions\Base;
use App\Concerns\Filament\ActionLogs\HasPivotActionLogs;
use App\Filament\RelationManagers\BaseRelationManager; use App\Filament\RelationManagers\BaseRelationManager;
use App\Filament\Resources\Base\BaseListResources; use App\Filament\Resources\Base\BaseListResources;
use App\Filament\Resources\Base\BaseManageResources; use App\Filament\Resources\Base\BaseManageResources;
use App\Filament\Resources\Base\BaseViewResource; use App\Filament\Resources\Base\BaseViewResource;
use Filament\Actions\DetachAction as BaseDetachAction; use Filament\Actions\DetachAction as BaseDetachAction;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\Gate;
@@ -18,8 +16,6 @@ use Illuminate\Support\Str;
class DetachAction extends BaseDetachAction class DetachAction extends BaseDetachAction
{ {
use HasPivotActionLogs;
protected function setUp(): void protected function setUp(): void
{ {
parent::setUp(); parent::setUp();
@@ -54,13 +50,5 @@ class DetachAction extends BaseDetachAction
}); });
$this->authorize(true); $this->authorize(true);
$this->after(function (BaseRelationManager $livewire, Model $record): void {
$relationship = $livewire->getRelationship();
if ($relationship instanceof BelongsToMany) {
$this->pivotActionLog('Detach', $livewire, $record);
}
});
} }
} }
-17
View File
@@ -4,26 +4,19 @@ declare(strict_types=1);
namespace App\Filament\Actions\Base; namespace App\Filament\Actions\Base;
use App\Concerns\Filament\ActionLogs\HasActionLogs;
use App\Concerns\Filament\ActionLogs\HasPivotActionLogs;
use App\Filament\RelationManagers\BaseRelationManager; use App\Filament\RelationManagers\BaseRelationManager;
use App\Filament\Resources\Base\BaseListResources; use App\Filament\Resources\Base\BaseListResources;
use App\Filament\Resources\Base\BaseManageResources; use App\Filament\Resources\Base\BaseManageResources;
use App\Filament\Resources\Base\BaseViewResource; use App\Filament\Resources\Base\BaseViewResource;
use App\Models\Admin\ActionLog;
use Filament\Actions\EditAction as BaseEditAction; use Filament\Actions\EditAction as BaseEditAction;
use Filament\Schemas\Schema; use Filament\Schemas\Schema;
use Filament\Support\Enums\IconSize; use Filament\Support\Enums\IconSize;
use Filament\Support\Icons\Heroicon; use Filament\Support\Icons\Heroicon;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\Gate;
class EditAction extends BaseEditAction class EditAction extends BaseEditAction
{ {
use HasActionLogs;
use HasPivotActionLogs;
protected function setUp(): void protected function setUp(): void
{ {
parent::setUp(); parent::setUp();
@@ -38,16 +31,6 @@ class EditAction extends BaseEditAction
...($livewire instanceof BaseRelationManager ? $livewire->getPivotComponents() : []), ...($livewire instanceof BaseRelationManager ? $livewire->getPivotComponents() : []),
]); ]);
$this->after(function (BaseListResources|BaseViewResource|BaseManageResources|BaseRelationManager $livewire, Model $record, EditAction $action): void {
if ($livewire instanceof BaseListResources || $livewire instanceof BaseViewResource) {
ActionLog::modelUpdated($record);
}
if ($livewire instanceof BaseRelationManager && $livewire->getRelationship() instanceof BelongsToMany) {
$this->pivotActionLog('Update Attached', $livewire, $record, $action);
}
});
$this->beforeFormFilled(function (Model $record): void { $this->beforeFormFilled(function (Model $record): void {
Gate::authorize('update', $record); Gate::authorize('update', $record);
}); });
@@ -7,7 +7,6 @@ namespace App\Filament\Actions\Base;
use App\Filament\RelationManagers\BaseRelationManager; use App\Filament\RelationManagers\BaseRelationManager;
use App\Filament\Resources\Base\BaseListResources; use App\Filament\Resources\Base\BaseListResources;
use App\Filament\Resources\Base\BaseManageResources; use App\Filament\Resources\Base\BaseManageResources;
use App\Models\Admin\ActionLog;
use Filament\Actions\ReplicateAction as BaseReplicateAction; use Filament\Actions\ReplicateAction as BaseReplicateAction;
use Filament\Facades\Filament; use Filament\Facades\Filament;
use Filament\Schemas\Schema; use Filament\Schemas\Schema;
@@ -22,7 +21,5 @@ class ReplicateAction extends BaseReplicateAction
$this->schema(fn (Schema $schema, BaseListResources|BaseManageResources|BaseRelationManager $livewire): array => $livewire->form($schema)->getComponents()); $this->schema(fn (Schema $schema, BaseListResources|BaseManageResources|BaseRelationManager $livewire): array => $livewire->form($schema)->getComponents());
$this->successRedirectUrl(fn (Model $replica) => Filament::getModelResource($replica)::getUrl('view', ['record' => $replica])); $this->successRedirectUrl(fn (Model $replica) => Filament::getModelResource($replica)::getUrl('view', ['record' => $replica]));
$this->after(fn (Model $replica): ActionLog => ActionLog::modelCreated($replica));
} }
} }
@@ -5,7 +5,6 @@ declare(strict_types=1);
namespace App\Filament\Actions\Base; namespace App\Filament\Actions\Base;
use App\Contracts\Models\SoftDeletable; use App\Contracts\Models\SoftDeletable;
use App\Models\Admin\ActionLog;
use Filament\Actions\RestoreAction as BaseRestoreAction; use Filament\Actions\RestoreAction as BaseRestoreAction;
use Filament\Support\Icons\Heroicon; use Filament\Support\Icons\Heroicon;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
@@ -33,8 +32,6 @@ class RestoreAction extends BaseRestoreAction
return $record->trashed(); return $record->trashed();
}); });
$this->after(fn (Model $record): ActionLog => ActionLog::modelRestored($record));
$this->using(function (Model&SoftDeletable $record): bool { $this->using(function (Model&SoftDeletable $record): bool {
Gate::authorize('restore', $record); Gate::authorize('restore', $record);
+10 -4
View File
@@ -4,7 +4,8 @@ declare(strict_types=1);
namespace App\Filament\Actions; namespace App\Filament\Actions;
use App\Concerns\Filament\ActionLogs\HasActionLogs; use App\Concerns\Filament\HasActivityLogs;
use App\Enums\Models\Admin\ActivityStatus;
use App\Filament\RelationManagers\BaseRelationManager; use App\Filament\RelationManagers\BaseRelationManager;
use App\Filament\Resources\Base\BaseViewResource; use App\Filament\Resources\Base\BaseViewResource;
use Filament\Actions\Action; use Filament\Actions\Action;
@@ -15,7 +16,7 @@ use Illuminate\Support\Str;
abstract class BaseAction extends Action abstract class BaseAction extends Action
{ {
use HasActionLogs; use HasActivityLogs;
public static function getDefaultName(): ?string public static function getDefaultName(): ?string
{ {
@@ -32,10 +33,10 @@ abstract class BaseAction extends Action
$this->before(function (BaseAction $action, mixed $livewire): void { $this->before(function (BaseAction $action, mixed $livewire): void {
if ($livewire instanceof BaseRelationManager) { if ($livewire instanceof BaseRelationManager) {
$this->createActionLog($action, $livewire->getOwnerRecord()); $this->createActivityLog($action, $livewire->getOwnerRecord());
$livewire->dispatch('updateAllRelationManager'); $livewire->dispatch('updateAllRelationManager');
} elseif (($record = $this->getRecord()) instanceof Model) { } elseif (($record = $this->getRecord()) instanceof Model) {
$this->createActionLog($action, $record); $this->createActivityLog($action, $record);
} }
}); });
@@ -44,6 +45,11 @@ abstract class BaseAction extends Action
return; return;
} }
$this->activity?->update([
'status' => ActivityStatus::FINISHED,
'finished_at' => now(),
]);
$this->finishedLog(); $this->finishedLog();
if ($livewire instanceof BaseViewResource || $livewire instanceof BaseRelationManager) { if ($livewire instanceof BaseViewResource || $livewire instanceof BaseRelationManager) {
@@ -6,9 +6,7 @@ namespace App\Filament\Actions\Storage;
use App\Contracts\Actions\Storage\StorageAction as BaseStorageAction; use App\Contracts\Actions\Storage\StorageAction as BaseStorageAction;
use App\Filament\Actions\BaseAction; use App\Filament\Actions\BaseAction;
use App\Filament\RelationManagers\BaseRelationManager;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
abstract class StorageAction extends BaseAction abstract class StorageAction extends BaseAction
{ {
@@ -57,22 +55,5 @@ abstract class StorageAction extends BaseAction
} }
$this->afterStorageAction($record, $data); $this->afterStorageAction($record, $data);
$livewire = $this->getLivewire();
if ($livewire instanceof BaseRelationManager && $record instanceof Model) {
$relation = $livewire->getRelationship();
$pivot = $record;
if ($relation instanceof BelongsToMany) {
$pivotClass = $relation->getPivotClass();
$pivot = $pivotClass::query()
->where($livewire->getOwnerRecord()->getKeyName(), $livewire->getOwnerRecord()->getKey())
->where($record->getKeyName(), $record->getKey())
->first();
}
$this->updateLog($record, $pivot);
}
} }
} }
@@ -4,15 +4,11 @@ declare(strict_types=1);
namespace App\Filament\BulkActions\Base; namespace App\Filament\BulkActions\Base;
use App\Concerns\Filament\ActionLogs\HasActionLogs;
use Filament\Actions\DeleteBulkAction as BaseDeleteBulkAction; use Filament\Actions\DeleteBulkAction as BaseDeleteBulkAction;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\Gate;
class DeleteBulkAction extends BaseDeleteBulkAction class DeleteBulkAction extends BaseDeleteBulkAction
{ {
use HasActionLogs;
protected function setUp(): void protected function setUp(): void
{ {
parent::setUp(); parent::setUp();
@@ -22,12 +18,5 @@ class DeleteBulkAction extends BaseDeleteBulkAction
$this->authorize(true); $this->authorize(true);
$this->before(fn (string $model) => Gate::authorize('forceDeleteAny', $model)); $this->before(fn (string $model) => Gate::authorize('forceDeleteAny', $model));
$this->after(function (DeleteBulkAction $action, Collection $records): void {
foreach ($records as $record) {
$this->createActionLog($action, $record);
$this->finishedLog();
}
});
} }
} }
@@ -4,15 +4,11 @@ declare(strict_types=1);
namespace App\Filament\BulkActions\Base; namespace App\Filament\BulkActions\Base;
use App\Concerns\Filament\ActionLogs\HasActionLogs;
use Filament\Actions\DetachBulkAction as BaseDetachBulkAction; use Filament\Actions\DetachBulkAction as BaseDetachBulkAction;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\Gate;
class DetachBulkAction extends BaseDetachBulkAction class DetachBulkAction extends BaseDetachBulkAction
{ {
use HasActionLogs;
protected function setUp(): void protected function setUp(): void
{ {
parent::setUp(); parent::setUp();
@@ -22,12 +18,5 @@ class DetachBulkAction extends BaseDetachBulkAction
$this->authorize(true); $this->authorize(true);
$this->before(fn (string $model) => Gate::authorize('forceDeleteAny', $model)); $this->before(fn (string $model) => Gate::authorize('forceDeleteAny', $model));
$this->after(function (DetachBulkAction $action, Collection $records): void {
foreach ($records as $record) {
$this->createActionLog($action, $record);
$this->finishedLog();
}
});
} }
} }
@@ -4,14 +4,11 @@ declare(strict_types=1);
namespace App\Filament\BulkActions\Base; namespace App\Filament\BulkActions\Base;
use App\Concerns\Filament\ActionLogs\HasActionLogs;
use Filament\Actions\ForceDeleteBulkAction as BaseForceDeleteBulkAction; use Filament\Actions\ForceDeleteBulkAction as BaseForceDeleteBulkAction;
use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\Gate;
class ForceDeleteBulkAction extends BaseForceDeleteBulkAction class ForceDeleteBulkAction extends BaseForceDeleteBulkAction
{ {
use HasActionLogs;
protected function setUp(): void protected function setUp(): void
{ {
parent::setUp(); parent::setUp();
@@ -4,15 +4,11 @@ declare(strict_types=1);
namespace App\Filament\BulkActions\Base; namespace App\Filament\BulkActions\Base;
use App\Concerns\Filament\ActionLogs\HasActionLogs;
use Filament\Actions\RestoreBulkAction as BaseRestoreBulkAction; use Filament\Actions\RestoreBulkAction as BaseRestoreBulkAction;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\Gate;
class RestoreBulkAction extends BaseRestoreBulkAction class RestoreBulkAction extends BaseRestoreBulkAction
{ {
use HasActionLogs;
protected function setUp(): void protected function setUp(): void
{ {
parent::setUp(); parent::setUp();
@@ -22,12 +18,5 @@ class RestoreBulkAction extends BaseRestoreBulkAction
$this->authorize(true); $this->authorize(true);
$this->before(fn (string $model) => Gate::authorize('restoreAny', $model)); $this->before(fn (string $model) => Gate::authorize('restoreAny', $model));
$this->after(function (RestoreBulkAction $action, Collection $records): void {
foreach ($records as $record) {
$this->createActionLog($action, $record);
$this->finishedLog();
}
});
} }
} }
@@ -4,7 +4,6 @@ declare(strict_types=1);
namespace App\Filament\BulkActions; namespace App\Filament\BulkActions;
use App\Concerns\Filament\ActionLogs\HasActionLogs;
use Filament\Actions\BulkAction; use Filament\Actions\BulkAction;
use Filament\Support\Enums\Width; use Filament\Support\Enums\Width;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@@ -14,22 +13,12 @@ use Illuminate\Support\Collection;
*/ */
abstract class BaseBulkAction extends BulkAction abstract class BaseBulkAction extends BulkAction
{ {
use HasActionLogs;
protected function setUp(): void protected function setUp(): void
{ {
parent::setUp(); parent::setUp();
$this->requiresConfirmation(); $this->requiresConfirmation();
$this->before(function (BaseBulkAction $action, Collection $records): void {
foreach ($records as $record) {
$this->createActionLog($action, $record, false);
}
});
$this->after(fn () => $this->batchFinishedLog());
$this->modalWidth(Width::FourExtraLarge); $this->modalWidth(Width::FourExtraLarge);
$this->action(fn (Collection $records, array $data) => $this->handle($records, $data)); $this->action(fn (Collection $records, array $data) => $this->handle($records, $data));
@@ -44,11 +44,7 @@ class VideoDiscordNotificationBulkAction extends BaseBulkAction
$action = new DiscordVideoNotificationActionAction(); $action = new DiscordVideoNotificationActionAction();
$result = $action->handle($videos, $data); $action->handle($videos, $data);
if ($result->hasFailed()) {
$this->failedLog($result->getMessage());
}
} }
/** /**
@@ -34,10 +34,6 @@ abstract class StorageBulkAction extends BaseBulkAction
$action->then($storageResults); $action->then($storageResults);
$actionResult = $storageResults->toActionResult(); $actionResult = $storageResults->toActionResult();
if ($actionResult->hasFailed()) {
$this->failedLog($actionResult->getMessage());
}
} }
} }
} }
@@ -5,23 +5,28 @@ declare(strict_types=1);
namespace App\Filament\RelationManagers\Base; namespace App\Filament\RelationManagers\Base;
use App\Filament\RelationManagers\BaseRelationManager; use App\Filament\RelationManagers\BaseRelationManager;
use App\Filament\Resources\Admin\ActionLogResource; use App\Filament\Resources\Admin\ActivityResource;
use App\Filament\Resources\BaseResource; use App\Filament\Resources\BaseResource;
use App\Models\Admin\ActionLog; use App\Models\Admin\Activity;
use Filament\Tables\Table; use Filament\Tables\Table;
class ActionLogRelationManager extends BaseRelationManager class ActivityRelationManager extends BaseRelationManager
{ {
protected static string $relationship = 'actionlogs'; protected static string $relationship = 'activities';
protected static ?string $recordTitleAttribute = ActionLog::ATTRIBUTE_ID; protected static ?string $recordTitleAttribute = Activity::ATTRIBUTE_ID;
/** /**
* The resource of the relation manager. * The resource of the relation manager.
* *
* @var class-string<BaseResource>|null * @var class-string<BaseResource>|null
*/ */
protected static ?string $relatedResource = ActionLogResource::class; protected static ?string $relatedResource = ActivityResource::class;
public static function isLazy(): true
{
return true;
}
public function table(Table $table): Table public function table(Table $table): Table
{ {
@@ -1,13 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Filament\Resources\Admin\ActionLog\Pages;
use App\Filament\Resources\Admin\ActionLogResource;
use App\Filament\Resources\Base\BaseManageResources;
class ManageActionLogs extends BaseManageResources
{
protected static string $resource = ActionLogResource::class;
}
@@ -0,0 +1,13 @@
<?php
declare(strict_types=1);
namespace App\Filament\Resources\Admin\Activity\Pages;
use App\Filament\Resources\Admin\ActivityResource;
use App\Filament\Resources\Base\BaseManageResources;
class ManageActivities extends BaseManageResources
{
protected static string $resource = ActivityResource::class;
}
@@ -6,17 +6,16 @@ namespace App\Filament\Resources\Admin;
use App\Enums\Auth\Role; use App\Enums\Auth\Role;
use App\Enums\Filament\NavigationGroup; use App\Enums\Filament\NavigationGroup;
use App\Enums\Models\Admin\ActionLogStatus; use App\Enums\Models\Admin\ActivityStatus;
use App\Filament\Actions\Base\ViewAction; use App\Filament\Actions\Base\ViewAction;
use App\Filament\Components\Columns\BelongsToColumn; use App\Filament\Components\Columns\BelongsToColumn;
use App\Filament\Components\Columns\TextColumn; use App\Filament\Components\Columns\TextColumn;
use App\Filament\Components\Filters\DateFilter;
use App\Filament\Components\Infolist\BelongsToEntry; use App\Filament\Components\Infolist\BelongsToEntry;
use App\Filament\Components\Infolist\TextEntry; use App\Filament\Components\Infolist\TextEntry;
use App\Filament\Resources\Admin\ActionLog\Pages\ManageActionLogs; use App\Filament\Resources\Admin\Activity\Pages\ManageActivities;
use App\Filament\Resources\Auth\UserResource; use App\Filament\Resources\Auth\UserResource;
use App\Filament\Resources\BaseResource; use App\Filament\Resources\BaseResource;
use App\Models\Admin\ActionLog; use App\Models\Admin\Activity;
use App\Models\Auth\User; use App\Models\Auth\User;
use App\Models\BaseModel; use App\Models\BaseModel;
use Filament\Facades\Filament; use Filament\Facades\Filament;
@@ -29,27 +28,26 @@ use Filament\Support\Enums\TextSize;
use Filament\Support\Icons\Heroicon; use Filament\Support\Icons\Heroicon;
use Filament\Tables\Filters\SelectFilter; use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table; use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str; use Illuminate\Support\Str;
class ActionLogResource extends BaseResource class ActivityResource extends BaseResource
{ {
/** /**
* The model the resource corresponds to. * The model the resource corresponds to.
* *
* @var class-string<Model>|null * @var class-string<Model>|null
*/ */
protected static ?string $model = ActionLog::class; protected static ?string $model = Activity::class;
public static function getModelLabel(): string public static function getModelLabel(): string
{ {
return __('filament.resources.singularLabel.action_log'); return __('filament.resources.singularLabel.activity');
} }
public static function getPluralModelLabel(): string public static function getPluralModelLabel(): string
{ {
return __('filament.resources.label.action_logs'); return __('filament.resources.label.activities');
} }
public static function getNavigationGroup(): NavigationGroup public static function getNavigationGroup(): NavigationGroup
@@ -69,18 +67,7 @@ class ActionLogResource extends BaseResource
public static function getRecordTitleAttribute(): string public static function getRecordTitleAttribute(): string
{ {
return ActionLog::ATTRIBUTE_NAME; return Activity::ATTRIBUTE_NAME;
}
public static function getEloquentQuery(): Builder
{
$query = parent::getEloquentQuery();
// Necessary to prevent lazy loading when loading related resources
return $query->with([
ActionLog::RELATION_USER,
ActionLog::RELATION_TARGET,
]);
} }
public static function form(Schema $schema): Schema public static function form(Schema $schema): Schema
@@ -88,10 +75,10 @@ class ActionLogResource extends BaseResource
return $schema return $schema
->components([ ->components([
// TODO: JSON values are not being displayed // TODO: JSON values are not being displayed
KeyValue::make(ActionLog::ATTRIBUTE_FIELDS) KeyValue::make(Activity::ATTRIBUTE_PROPERTIES)
->label(__('filament.fields.action_log.fields.name')) ->label(__('filament.fields.activity.fields.name'))
->keyLabel(__('filament.fields.action_log.fields.keys')) ->keyLabel(__('filament.fields.activity.fields.keys'))
->valueLabel(__('filament.fields.action_log.fields.values')) ->valueLabel(__('filament.fields.activity.fields.values'))
->columnSpanFull() ->columnSpanFull()
->hidden(fn ($state): bool => is_null($state)) ->hidden(fn ($state): bool => is_null($state))
->formatStateUsing(fn (?array $state) => collect($state)->mapWithKeys(function ($value, $key): array { ->formatStateUsing(fn (?array $state) => collect($state)->mapWithKeys(function ($value, $key): array {
@@ -102,8 +89,8 @@ class ActionLogResource extends BaseResource
return [$key => blank($value) ? '-' : $value]; return [$key => blank($value) ? '-' : $value];
})->toArray()), })->toArray()),
Textarea::make(ActionLog::ATTRIBUTE_EXCEPTION) Textarea::make(Activity::ATTRIBUTE_EXCEPTION)
->label(__('filament.fields.action_log.exception')) ->label(__('filament.fields.activity.exception'))
->disabled() ->disabled()
->columnSpanFull(), ->columnSpanFull(),
]); ]);
@@ -114,30 +101,30 @@ class ActionLogResource extends BaseResource
return parent::table($table) return parent::table($table)
->recordUrl('') ->recordUrl('')
->columns([ ->columns([
TextColumn::make(ActionLog::ATTRIBUTE_ID) TextColumn::make(Activity::ATTRIBUTE_ID)
->label(__('filament.fields.base.id')), ->label(__('filament.fields.base.id')),
TextColumn::make(ActionLog::ATTRIBUTE_NAME) TextColumn::make(Activity::ATTRIBUTE_NAME)
->label(__('filament.fields.action_log.name')) ->label(__('filament.fields.activity.name'))
->searchable(), ->searchable(),
BelongsToColumn::make(ActionLog::RELATION_USER, UserResource::class), BelongsToColumn::make(Activity::RELATION_USER, UserResource::class),
TextColumn::make(ActionLog::ATTRIBUTE_TARGET) TextColumn::make(Activity::RELATION_RELATED)
->label(__('filament.fields.action_log.target')) ->label(__('filament.fields.activity.target'))
->formatStateUsing(fn ($state): string => Str::headline(class_basename($state)).': '.$state->getName()), ->formatStateUsing(fn ($state): string => Str::headline(class_basename($state)).': '.$state->getName()),
TextColumn::make(ActionLog::ATTRIBUTE_STATUS) TextColumn::make(Activity::ATTRIBUTE_STATUS)
->label(__('filament.fields.action_log.status')) ->label(__('filament.fields.activity.status'))
->formatStateUsing(fn (ActionLogStatus $state): ?string => $state->localize()) ->formatStateUsing(fn (ActivityStatus $state): ?string => $state->localize())
->badge(), ->badge(),
TextColumn::make(BaseModel::ATTRIBUTE_CREATED_AT) TextColumn::make(BaseModel::ATTRIBUTE_CREATED_AT)
->label(__('filament.fields.action_log.happened_at')) ->label(__('filament.fields.activity.happened_at'))
->dateTime(), ->dateTime(),
TextColumn::make(ActionLog::ATTRIBUTE_FINISHED_AT) TextColumn::make(Activity::ATTRIBUTE_FINISHED_AT)
->label(__('filament.fields.action_log.finished_at')) ->label(__('filament.fields.activity.finished_at'))
->dateTime(), ->dateTime(),
]); ]);
} }
@@ -146,33 +133,33 @@ class ActionLogResource extends BaseResource
{ {
return $schema return $schema
->components([ ->components([
TextEntry::make(ActionLog::ATTRIBUTE_NAME) TextEntry::make(Activity::ATTRIBUTE_NAME)
->label(__('filament.fields.action_log.name')) ->label(__('filament.fields.activity.name'))
->formatStateUsing(fn ($state): string => ucfirst((string) $state)), ->formatStateUsing(fn ($state): string => ucfirst((string) $state)),
BelongsToEntry::make(ActionLog::RELATION_USER, UserResource::class), BelongsToEntry::make(Activity::RELATION_USER, UserResource::class),
TextEntry::make(ActionLog::ATTRIBUTE_TARGET) TextEntry::make(Activity::RELATION_RELATED)
->label(__('filament.fields.action_log.target')) ->label(__('filament.fields.activity.target'))
->formatStateUsing(fn ($state): string => class_basename($state).': '.$state->getName()), ->formatStateUsing(fn ($state): string => class_basename($state).': '.$state->getName()),
TextEntry::make(ActionLog::ATTRIBUTE_STATUS) TextEntry::make(Activity::ATTRIBUTE_STATUS)
->label(__('filament.fields.action_log.status')) ->label(__('filament.fields.activity.status'))
->formatStateUsing(fn (ActionLogStatus $state): ?string => $state->localize()) ->formatStateUsing(fn (ActivityStatus $state): ?string => $state->localize())
->badge(), ->badge(),
TextEntry::make(BaseModel::ATTRIBUTE_CREATED_AT) TextEntry::make(BaseModel::ATTRIBUTE_CREATED_AT)
->label(__('filament.fields.action_log.happened_at')) ->label(__('filament.fields.activity.happened_at'))
->dateTime(), ->dateTime(),
TextEntry::make(ActionLog::ATTRIBUTE_FINISHED_AT) TextEntry::make(Activity::ATTRIBUTE_FINISHED_AT)
->label(__('filament.fields.action_log.finished_at')) ->label(__('filament.fields.activity.finished_at'))
->dateTime(), ->dateTime(),
KeyValueEntry::make(ActionLog::ATTRIBUTE_FIELDS) KeyValueEntry::make(Activity::ATTRIBUTE_PROPERTIES)
->label(__('filament.fields.action_log.fields.name')) ->label(__('filament.fields.activity.fields.name'))
->keyLabel(__('filament.fields.action_log.fields.keys')) ->keyLabel(__('filament.fields.activity.fields.keys'))
->valueLabel(__('filament.fields.action_log.fields.values')) ->valueLabel(__('filament.fields.activity.fields.values'))
->columnSpanFull() ->columnSpanFull()
->hidden(fn ($state): bool => is_null($state)) ->hidden(fn ($state): bool => is_null($state))
->formatStateUsing(fn (?array $state) => collect($state)->mapWithKeys(function ($value, $key): array { ->formatStateUsing(fn (?array $state) => collect($state)->mapWithKeys(function ($value, $key): array {
@@ -183,8 +170,8 @@ class ActionLogResource extends BaseResource
return [$key => blank($value) ? '-' : $value]; return [$key => blank($value) ? '-' : $value];
})->toArray()), })->toArray()),
TextEntry::make(ActionLog::ATTRIBUTE_EXCEPTION) TextEntry::make(Activity::ATTRIBUTE_EXCEPTION)
->label(__('filament.fields.action_log.exception')) ->label(__('filament.fields.activity.exception'))
->columnSpanFull() ->columnSpanFull()
->size(TextSize::Large), ->size(TextSize::Large),
]) ])
@@ -197,15 +184,9 @@ class ActionLogResource extends BaseResource
public static function getFilters(): array public static function getFilters(): array
{ {
return [ return [
SelectFilter::make(ActionLog::ATTRIBUTE_STATUS) SelectFilter::make(Activity::ATTRIBUTE_STATUS)
->label(__('filament.fields.action_log.status')) ->label(__('filament.fields.activity.status'))
->options(ActionLogStatus::class), ->options(ActivityStatus::class),
DateFilter::make(BaseModel::ATTRIBUTE_CREATED_AT)
->label(__('filament.fields.action_log.happened_at')),
DateFilter::make(ActionLog::ATTRIBUTE_FINISHED_AT)
->label(__('filament.fields.action_log.finished_at')),
]; ];
} }
@@ -270,7 +251,7 @@ class ActionLogResource extends BaseResource
public static function getPages(): array public static function getPages(): array
{ {
return [ return [
'index' => ManageActionLogs::route('/'), 'index' => ManageActivities::route('/'),
]; ];
} }
} }
+2 -2
View File
@@ -15,7 +15,7 @@ use App\Filament\Actions\Base\ViewAction;
use App\Filament\BulkActions\Base\DeleteBulkAction; use App\Filament\BulkActions\Base\DeleteBulkAction;
use App\Filament\BulkActions\Base\ForceDeleteBulkAction; use App\Filament\BulkActions\Base\ForceDeleteBulkAction;
use App\Filament\BulkActions\Base\RestoreBulkAction; use App\Filament\BulkActions\Base\RestoreBulkAction;
use App\Filament\RelationManagers\Base\ActionLogRelationManager; use App\Filament\RelationManagers\Base\ActivityRelationManager;
use App\Models\BaseModel; use App\Models\BaseModel;
use Filament\Actions\Action; use Filament\Actions\Action;
use Filament\Actions\ActionGroup; use Filament\Actions\ActionGroup;
@@ -169,7 +169,7 @@ abstract class BaseResource extends Resource
public static function getBaseRelations(): array public static function getBaseRelations(): array
{ {
return [ return [
ActionLogRelationManager::class, ActivityRelationManager::class,
AuditsRelationManager::class, AuditsRelationManager::class,
]; ];
} }
-409
View File
@@ -1,409 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Models\Admin;
use App\Constants\ModelConstants;
use App\Contracts\Models\Nameable;
use App\Discord\DiscordEmbedField;
use App\Enums\Models\Admin\ActionLogStatus;
use App\Models\Auth\User;
use App\Models\BaseModel;
use App\Observers\Admin\ActionLogObserver;
use Filament\Actions\Action;
use Filament\Facades\Filament;
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
use Illuminate\Database\Eloquent\Attributes\Table;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\Relations\Pivot;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Str;
use Throwable;
/**
* @property int $id
* @property string $batch_id
* @property string $name
* @property string $actionable_type
* @property int $actionable_id
* @property string $target_type
* @property int $target_id
* @property string $model_type
* @property int $model_id
* @property string|null $exception
* @property array|null $fields
* @property Carbon|null $finished_at
* @property ActionLogStatus $status
* @property Model $target
* @property int|null $user_id
* @property User|null $user
*/
#[ObservedBy(ActionLogObserver::class)]
#[Table(ActionLog::TABLE, ActionLog::ATTRIBUTE_ID)]
class ActionLog extends Model implements Nameable
{
final public const string TABLE = 'action_logs';
final public const string ATTRIBUTE_ID = 'id';
final public const string ATTRIBUTE_BATCH_ID = 'batch_id';
final public const string ATTRIBUTE_NAME = 'name';
final public const string ATTRIBUTE_USER = 'user_id';
final public const string ATTRIBUTE_ACTIONABLE = 'actionable';
final public const string ATTRIBUTE_ACTIONABLE_TYPE = 'actionable_type';
final public const string ATTRIBUTE_ACTIONABLE_ID = 'actionable_id';
final public const string ATTRIBUTE_TARGET = 'target';
final public const string ATTRIBUTE_TARGET_TYPE = 'target_type';
final public const string ATTRIBUTE_TARGET_ID = 'target_id';
final public const string ATTRIBUTE_MODEL_TYPE = 'model_type';
final public const string ATTRIBUTE_MODEL_ID = 'model_id';
final public const string ATTRIBUTE_FIELDS = 'fields';
final public const string ATTRIBUTE_STATUS = 'status';
final public const string ATTRIBUTE_EXCEPTION = 'exception';
final public const string ATTRIBUTE_FINISHED_AT = 'finished_at';
final public const string RELATION_USER = 'user';
final public const string RELATION_TARGET = 'target';
/**
* The attributes that are mass assignable.
*
* @var list<string>
*/
protected $fillable = [
ActionLog::ATTRIBUTE_BATCH_ID,
ActionLog::ATTRIBUTE_NAME,
ActionLog::ATTRIBUTE_USER,
ActionLog::ATTRIBUTE_ACTIONABLE_TYPE,
ActionLog::ATTRIBUTE_ACTIONABLE_ID,
ActionLog::ATTRIBUTE_TARGET_TYPE,
ActionLog::ATTRIBUTE_TARGET_ID,
ActionLog::ATTRIBUTE_MODEL_TYPE,
ActionLog::ATTRIBUTE_MODEL_ID,
ActionLog::ATTRIBUTE_FIELDS,
ActionLog::ATTRIBUTE_STATUS,
ActionLog::ATTRIBUTE_EXCEPTION,
ActionLog::ATTRIBUTE_FINISHED_AT,
];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
ActionLog::ATTRIBUTE_FIELDS => 'array',
ActionLog::ATTRIBUTE_STATUS => ActionLogStatus::class,
];
}
/**
* When an exception is thrown, the current action logs should be handled.
*/
public static function updateCurrentActionLogToFailed(Throwable $e): void
{
if ($actionLog = Session::get('currentActionLog')) {
ActionLog::query()
->where(ActionLog::ATTRIBUTE_BATCH_ID, $actionLog)
->where(ActionLog::ATTRIBUTE_STATUS, ActionLogStatus::RUNNING->value)
->update([
ActionLog::ATTRIBUTE_STATUS => ActionLogStatus::FAILED->value,
ActionLog::ATTRIBUTE_EXCEPTION => $e->__toString(),
ActionLog::ATTRIBUTE_FINISHED_AT => Date::now(),
]);
}
}
public function getName(): string
{
return Str::of($this->name)
->append(' - ')
->append($this->target()->getName())
->__toString();
}
public function actionable(): MorphTo
{
return $this->morphTo();
}
/**
* Get the target of the action for user interface linking.
*/
public function target(): MorphTo|BaseModel
{
return $this->morphTo()
->withTrashed();
}
/**
* @return BelongsTo<User, $this>
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class, ActionLog::ATTRIBUTE_USER);
}
/**
* Get the user id for the action log.
*/
public static function getUserId(): int
{
return Filament::auth()->id();
}
/**
* Register an action log for a model created.
*/
public static function modelCreated(Model $model): ActionLog
{
return ActionLog::query()->create([
ActionLog::ATTRIBUTE_BATCH_ID => Str::orderedUuid()->__toString(),
ActionLog::ATTRIBUTE_USER => ActionLog::getUserId(),
ActionLog::ATTRIBUTE_NAME => 'Create',
ActionLog::ATTRIBUTE_ACTIONABLE_TYPE => $model->getMorphClass(),
ActionLog::ATTRIBUTE_ACTIONABLE_ID => $model->getKey(),
ActionLog::ATTRIBUTE_TARGET_TYPE => $model->getMorphClass(),
ActionLog::ATTRIBUTE_TARGET_ID => $model->getKey(),
ActionLog::ATTRIBUTE_MODEL_TYPE => $model->getMorphClass(),
ActionLog::ATTRIBUTE_MODEL_ID => $model->getKey(),
ActionLog::ATTRIBUTE_FIELDS => static::getFields($model->getAttributes(), $model),
ActionLog::ATTRIBUTE_STATUS => ActionLogStatus::FINISHED->value,
ActionLog::ATTRIBUTE_FINISHED_AT => Date::now(),
]);
}
/**
* Register an action log for a model updated.
*/
public static function modelUpdated(Model $model): ActionLog
{
return ActionLog::query()->create([
ActionLog::ATTRIBUTE_BATCH_ID => Str::orderedUuid()->__toString(),
ActionLog::ATTRIBUTE_USER => ActionLog::getUserId(),
ActionLog::ATTRIBUTE_NAME => 'Update',
ActionLog::ATTRIBUTE_ACTIONABLE_TYPE => $model->getMorphClass(),
ActionLog::ATTRIBUTE_ACTIONABLE_ID => $model->getKey(),
ActionLog::ATTRIBUTE_TARGET_TYPE => $model->getMorphClass(),
ActionLog::ATTRIBUTE_TARGET_ID => $model->getKey(),
ActionLog::ATTRIBUTE_MODEL_TYPE => $model->getMorphClass(),
ActionLog::ATTRIBUTE_MODEL_ID => $model->getKey(),
ActionLog::ATTRIBUTE_FIELDS => static::getFields($model->getChanges(), $model),
ActionLog::ATTRIBUTE_STATUS => ActionLogStatus::FINISHED->value,
ActionLog::ATTRIBUTE_FINISHED_AT => Date::now(),
]);
}
/**
* Register an action log for a model deleted.
*/
public static function modelDeleted(Model $model): ActionLog
{
return ActionLog::modelSoftDeleted('Delete', $model);
}
/**
* Register an action log for a model restored.
*/
public static function modelRestored(Model $model): ActionLog
{
return ActionLog::modelSoftDeleted('Restore', $model);
}
/**
* Register an action log for a model that is soft-deleted.
*/
public static function modelSoftDeleted(string $actionName, Model $model): ActionLog
{
return ActionLog::query()->create([
ActionLog::ATTRIBUTE_BATCH_ID => Str::orderedUuid()->__toString(),
ActionLog::ATTRIBUTE_USER => ActionLog::getUserId(),
ActionLog::ATTRIBUTE_NAME => $actionName,
ActionLog::ATTRIBUTE_ACTIONABLE_TYPE => $model->getMorphClass(),
ActionLog::ATTRIBUTE_ACTIONABLE_ID => $model->getKey(),
ActionLog::ATTRIBUTE_TARGET_TYPE => $model->getMorphClass(),
ActionLog::ATTRIBUTE_TARGET_ID => $model->getKey(),
ActionLog::ATTRIBUTE_MODEL_TYPE => $model->getMorphClass(),
ActionLog::ATTRIBUTE_MODEL_ID => $model->getKey(),
ActionLog::ATTRIBUTE_FIELDS => static::getFields($model->getAttributes(), $model),
ActionLog::ATTRIBUTE_STATUS => ActionLogStatus::FINISHED->value,
ActionLog::ATTRIBUTE_FINISHED_AT => Date::now(),
]);
}
/**
* Register an action log for a model attached.
*/
public static function modelPivot(string $actionName, Model $related, Model $parent, Model $pivot, ?Action $action = null): ActionLog
{
$data = $action?->getData();
return ActionLog::query()->create([
ActionLog::ATTRIBUTE_BATCH_ID => Str::orderedUuid()->__toString(),
ActionLog::ATTRIBUTE_USER => ActionLog::getUserId(),
ActionLog::ATTRIBUTE_NAME => $actionName,
ActionLog::ATTRIBUTE_ACTIONABLE_TYPE => $related->getMorphClass(),
ActionLog::ATTRIBUTE_ACTIONABLE_ID => $related->getKey(),
ActionLog::ATTRIBUTE_TARGET_TYPE => $parent->getMorphClass(),
ActionLog::ATTRIBUTE_TARGET_ID => $parent->getKey(),
ActionLog::ATTRIBUTE_MODEL_TYPE => $pivot->getMorphClass(),
ActionLog::ATTRIBUTE_MODEL_ID => $pivot instanceof Pivot ? null : $pivot->getKey(),
ActionLog::ATTRIBUTE_FIELDS => $data ? static::getFields($data) : static::getFields($pivot->getAttributes(), $pivot),
ActionLog::ATTRIBUTE_STATUS => ActionLogStatus::FINISHED->value,
ActionLog::ATTRIBUTE_FINISHED_AT => Date::now(),
]);
}
/**
* Register an action log for a model associated (HasMany).
*/
public static function modelAssociated(string $actionName, Model $related, Model $parent, Action $action): ActionLog
{
return ActionLog::query()->create([
ActionLog::ATTRIBUTE_BATCH_ID => Str::orderedUuid()->__toString(),
ActionLog::ATTRIBUTE_USER => ActionLog::getUserId(),
ActionLog::ATTRIBUTE_NAME => $actionName,
ActionLog::ATTRIBUTE_ACTIONABLE_TYPE => $related->getMorphClass(),
ActionLog::ATTRIBUTE_ACTIONABLE_ID => $related->getKey(),
ActionLog::ATTRIBUTE_TARGET_TYPE => $parent->getMorphClass(),
ActionLog::ATTRIBUTE_TARGET_ID => $parent->getKey(),
ActionLog::ATTRIBUTE_MODEL_TYPE => $related->getMorphClass(),
ActionLog::ATTRIBUTE_MODEL_ID => $related->getKey(),
ActionLog::ATTRIBUTE_FIELDS => static::getFields($action->getData()),
ActionLog::ATTRIBUTE_STATUS => ActionLogStatus::FINISHED->value,
ActionLog::ATTRIBUTE_FINISHED_AT => Date::now(),
]);
}
/**
* Register an action log for when a model has an action executed.
*/
public static function modelActioned(string $batchId, Action $action, Model $model): ActionLog
{
return ActionLog::query()->create([
ActionLog::ATTRIBUTE_BATCH_ID => $batchId,
ActionLog::ATTRIBUTE_USER => ActionLog::getUserId(),
ActionLog::ATTRIBUTE_NAME => $action->getLabel(),
ActionLog::ATTRIBUTE_ACTIONABLE_TYPE => $model->getMorphClass(),
ActionLog::ATTRIBUTE_ACTIONABLE_ID => $model->getKey(),
ActionLog::ATTRIBUTE_TARGET_TYPE => $model->getMorphClass(),
ActionLog::ATTRIBUTE_TARGET_ID => $model->getKey(),
ActionLog::ATTRIBUTE_MODEL_TYPE => $model->getMorphClass(),
ActionLog::ATTRIBUTE_MODEL_ID => $model->getKey(),
ActionLog::ATTRIBUTE_FIELDS => static::getFields($action->getData()),
ActionLog::ATTRIBUTE_STATUS => ActionLogStatus::RUNNING->value,
]);
}
/**
* Update the all the models status of a batch to running.
*/
public function batchRunning(): void
{
$this->query()->where(ActionLog::ATTRIBUTE_BATCH_ID, $this->batch_id)
->whereNotIn(ActionLog::ATTRIBUTE_STATUS, [ActionLogStatus::FINISHED->value, ActionLogStatus::FAILED->value])
->update([
ActionLog::ATTRIBUTE_STATUS => ActionLogStatus::RUNNING->value,
]);
}
/**
* Update the all the models status of a batch to finished.
*/
public function batchFinished(): void
{
$this->query()->where(ActionLog::ATTRIBUTE_BATCH_ID, $this->batch_id)
->whereNotIn(ActionLog::ATTRIBUTE_STATUS, [ActionLogStatus::FINISHED->value, ActionLogStatus::FAILED->value])
->update([
ActionLog::ATTRIBUTE_STATUS => ActionLogStatus::FINISHED->value,
ActionLog::ATTRIBUTE_FINISHED_AT => Date::now(),
]);
}
/**
* Update the all the models status of a batch to failed.
*/
public function batchFailed(Throwable|string|null $exception = null): void
{
$this->query()->where(ActionLog::ATTRIBUTE_BATCH_ID, $this->batch_id)
->whereNotIn(ActionLog::ATTRIBUTE_STATUS, [ActionLogStatus::FINISHED->value, ActionLogStatus::FAILED->value])
->update([
ActionLog::ATTRIBUTE_STATUS => ActionLogStatus::FAILED->value,
ActionLog::ATTRIBUTE_EXCEPTION => $exception ? $exception->__toString() : null,
ActionLog::ATTRIBUTE_FINISHED_AT => Date::now(),
]);
}
/**
* Update the model status to finished.
*/
public function finished(): void
{
$this->updateStatus(ActionLogStatus::FINISHED);
}
/**
* Update the model status to failed.
*/
public function failed(Throwable|string|null $exception = null): void
{
$this->updateStatus(ActionLogStatus::FAILED, $exception);
}
/**
* Check if the model status is failed.
*/
public function hasFailed(): bool
{
return $this->status === ActionLogStatus::FAILED;
}
/**
* Update the status of a given action event.
*/
public function updateStatus(ActionLogStatus $status, Throwable|string|null $exception = null): void
{
if ($exception instanceof Throwable) {
$exception = $exception->__toString();
}
$this->update([
ActionLog::ATTRIBUTE_STATUS => $status->value,
ActionLog::ATTRIBUTE_EXCEPTION => $exception,
ActionLog::ATTRIBUTE_FINISHED_AT => Date::now(),
]);
}
/**
* Format the fields to store.
*/
protected static function getFields(array $fields, ?Model $model = null): array
{
return collect($fields)
->forget(Model::CREATED_AT)
->forget(Model::UPDATED_AT)
->forget(ModelConstants::ATTRIBUTE_DELETED_AT)
->map(function ($value, $key) use ($model): string {
if ($model instanceof Model) {
if (in_array($key, $model->getHidden())) {
return DiscordEmbedField::DEFAULT_FIELD_VALUE;
}
return DiscordEmbedField::formatEmbedFieldValue($model->getAttribute($key));
}
return DiscordEmbedField::formatEmbedFieldValue($value);
})
->toArray();
}
}
+47
View File
@@ -0,0 +1,47 @@
<?php
declare(strict_types=1);
namespace App\Models\Admin;
use App\Enums\Models\Admin\ActivityStatus;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Spatie\Activitylog\Models\Activity as BaseActivity;
/**
* @property ActivityStatus|null $status
*/
class Activity extends BaseActivity
{
final public const string TABLE = 'activity_log';
final public const string ATTRIBUTE_ID = 'id';
final public const string ATTRIBUTE_EXCEPTION = 'exception';
final public const string ATTRIBUTE_FINISHED_AT = 'finished_at';
final public const string ATTRIBUTE_NAME = 'event';
final public const string ATTRIBUTE_PROPERTIES = 'properties';
final public const string ATTRIBUTE_RELATED_ID = 'related_id';
final public const string ATTRIBUTE_STATUS = 'status';
final public const string RELATION_RELATED = 'related';
final public const string RELATION_USER = 'causer';
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
...parent::casts(),
Activity::ATTRIBUTE_FINISHED_AT => 'datetime',
Activity::ATTRIBUTE_STATUS => ActivityStatus::class,
];
}
public function related(): MorphTo
{
return $this->morphTo();
}
}
+5 -5
View File
@@ -14,7 +14,7 @@ use App\Events\Auth\User\UserCreated;
use App\Events\Auth\User\UserDeleted; use App\Events\Auth\User\UserDeleted;
use App\Events\Auth\User\UserRestored; use App\Events\Auth\User\UserRestored;
use App\Events\Auth\User\UserUpdated; use App\Events\Auth\User\UserUpdated;
use App\Models\Admin\ActionLog; use App\Models\Admin\Activity;
use App\Models\List\ExternalProfile; use App\Models\List\ExternalProfile;
use App\Models\List\Playlist; use App\Models\List\Playlist;
use App\Models\User\Like; use App\Models\User\Like;
@@ -229,13 +229,13 @@ class User extends Authenticatable implements Auditable, FilamentUser, HasAvatar
} }
/** /**
* Get the action logs that the user has executed. * Get the activities that the user has executed.
* *
* @return HasMany<ActionLog, $this> * @return MorphMany<Activity, $this>
*/ */
public function actionlogs(): HasMany public function activities(): MorphMany
{ {
return $this->hasMany(ActionLog::class, ActionLog::ATTRIBUTE_USER); return $this->morphMany(Activity::class, 'causer');
} }
/** /**
+8 -3
View File
@@ -4,10 +4,11 @@ declare(strict_types=1);
namespace App\Models; namespace App\Models;
use App\Concerns\Filament\ActionLogs\ModelHasActionLogs;
use App\Contracts\Models\HasSubtitle; use App\Contracts\Models\HasSubtitle;
use App\Contracts\Models\Nameable; use App\Contracts\Models\Nameable;
use App\Models\Admin\Activity;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\Config;
use Illuminate\Support\Str; use Illuminate\Support\Str;
@@ -18,8 +19,6 @@ use Illuminate\Support\Str;
*/ */
abstract class BaseModel extends Model implements HasSubtitle, Nameable abstract class BaseModel extends Model implements HasSubtitle, Nameable
{ {
use ModelHasActionLogs;
/** /**
* The storage format of the model's date columns. * The storage format of the model's date columns.
* *
@@ -42,4 +41,10 @@ abstract class BaseModel extends Model implements HasSubtitle, Nameable
$this->setConnection(Config::get($connectionKey)); $this->setConnection(Config::get($connectionKey));
} }
} }
/** @return MorphMany<Activity, $this> */
public function activities(): MorphMany
{
return $this->morphMany(Activity::class, 'subject');
}
} }
-32
View File
@@ -1,32 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Observers\Admin;
use App\Enums\Models\Admin\ActionLogStatus;
use App\Models\Admin\ActionLog;
use Illuminate\Support\Facades\Session;
class ActionLogObserver
{
/**
* Handle the ActionLog "creating" event.
*/
public function creating(ActionLog $actionLog): void
{
if ($actionLog->status === ActionLogStatus::RUNNING) {
Session::put('currentActionLog', $actionLog->batch_id);
}
}
/**
* Handle the ActionLog "updating" event.
*/
public function updating(ActionLog $actionLog): void
{
if ($actionLog->status === ActionLogStatus::RUNNING) {
Session::put('currentActionLog', $actionLog->batch_id);
}
}
}
+1
View File
@@ -53,6 +53,7 @@
"propaganistas/laravel-disposable-email": "^2.4.27", "propaganistas/laravel-disposable-email": "^2.4.27",
"spatie/db-dumper": "^3.8.3", "spatie/db-dumper": "^3.8.3",
"spatie/eloquent-sortable": "^5.0.1", "spatie/eloquent-sortable": "^5.0.1",
"spatie/laravel-activitylog": "^5.0",
"spatie/laravel-permission": "^6.25.0", "spatie/laravel-permission": "^6.25.0",
"staudenmeir/belongs-to-through": "^2.18", "staudenmeir/belongs-to-through": "^2.18",
"staudenmeir/eloquent-has-many-deep": "^1.22.1", "staudenmeir/eloquent-has-many-deep": "^1.22.1",
Generated
+94 -1
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "6755161c85626cab15eacc8869e6836d", "content-hash": "069560ab509c56cc16fc63007f65e7af",
"packages": [ "packages": [
{ {
"name": "awcodes/recently", "name": "awcodes/recently",
@@ -8925,6 +8925,99 @@
], ],
"time": "2024-05-17T09:06:10+00:00" "time": "2024-05-17T09:06:10+00:00"
}, },
{
"name": "spatie/laravel-activitylog",
"version": "5.0.0",
"source": {
"type": "git",
"url": "https://github.com/spatie/laravel-activitylog.git",
"reference": "0e00fe74fd071cc572a045459f6d4c9de33130bd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/spatie/laravel-activitylog/zipball/0e00fe74fd071cc572a045459f6d4c9de33130bd",
"reference": "0e00fe74fd071cc572a045459f6d4c9de33130bd",
"shasum": ""
},
"require": {
"illuminate/config": "^12.0 || ^13.0",
"illuminate/database": "^12.0 || ^13.0",
"illuminate/support": "^12.0 || ^13.0",
"php": "^8.4",
"spatie/laravel-package-tools": "^1.6.3"
},
"require-dev": {
"ext-json": "*",
"larastan/larastan": "^3.0",
"laravel/pint": "^1.29",
"orchestra/testbench": "^10.0 || ^11.0",
"pestphp/pest": "^4.0"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Spatie\\Activitylog\\ActivitylogServiceProvider"
]
}
},
"autoload": {
"files": [
"src/helpers.php"
],
"psr-4": {
"Spatie\\Activitylog\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Freek Van der Herten",
"email": "freek@spatie.be",
"homepage": "https://spatie.be",
"role": "Developer"
},
{
"name": "Sebastian De Deyne",
"email": "sebastian@spatie.be",
"homepage": "https://spatie.be",
"role": "Developer"
},
{
"name": "Tom Witkowski",
"email": "dev.gummibeer@gmail.com",
"homepage": "https://gummibeer.de",
"role": "Developer"
}
],
"description": "A very simple activity logger to monitor the users of your website or application",
"homepage": "https://github.com/spatie/activitylog",
"keywords": [
"activity",
"laravel",
"log",
"spatie",
"user"
],
"support": {
"issues": "https://github.com/spatie/laravel-activitylog/issues",
"source": "https://github.com/spatie/laravel-activitylog/tree/5.0.0"
},
"funding": [
{
"url": "https://spatie.be/open-source/support-us",
"type": "custom"
},
{
"url": "https://github.com/spatie",
"type": "github"
}
],
"time": "2026-03-25T10:04:54+00:00"
},
{ {
"name": "spatie/laravel-package-tools", "name": "spatie/laravel-package-tools",
"version": "1.93.0", "version": "1.93.0",
+75
View File
@@ -0,0 +1,75 @@
<?php
declare(strict_types=1);
use App\Models\Admin\Activity;
use Spatie\Activitylog\Actions\CleanActivityLogAction;
use Spatie\Activitylog\Actions\LogActivityAction;
return [
/*
* If set to false, no activities will be saved to the database.
*/
'enabled' => env('ACTIVITYLOG_ENABLED', true),
/*
* When the clean command is executed, all recording activities older than
* the number of days specified here will be deleted.
*/
'clean_after_days' => 365,
/*
* If no log name is passed to the activity() helper
* we use this default log name.
*/
'default_log_name' => 'default',
/*
* You can specify an auth driver here that gets user models.
* If this is null we'll use the current Laravel auth driver.
*/
'default_auth_driver' => null,
/*
* If set to true, the subject relationship on activities
* will include soft deleted models.
*/
'include_soft_deleted_subjects' => false,
/*
* This model will be used to log activity.
* It should implement the Spatie\Activitylog\Contracts\Activity interface
* and extend Illuminate\Database\Eloquent\Model.
*/
'activity_model' => Activity::class,
/*
* These attributes will be excluded from logging for all models.
* Model-specific exclusions via logExcept() are merged with these.
*/
'default_except_attributes' => [],
/*
* When enabled, activities are buffered in memory and inserted in a
* single bulk query after the response has been sent to the client.
* This can significantly reduce the number of database queries when
* many activities are logged during a single request.
*
* Only enable this if your application logs a high volume of activities
* per request. Buffered activities will not have an ID until the
* buffer is flushed.
*/
'buffer' => [
'enabled' => env('ACTIVITYLOG_BUFFER_ENABLED', false),
],
/*
* These action classes can be overridden to customize how activities
* are logged and cleaned. Your custom classes must extend the originals.
*/
'actions' => [
'log_activity' => LogActivityAction::class,
'clean_log' => CleanActivityLogAction::class,
],
];
@@ -1,39 +0,0 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
if (! Schema::hasTable('action_logs')) {
Schema::create('action_logs', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('batch_id');
$table->unsignedBigInteger('user_id')->nullable();
$table->foreign('user_id')->references('id')->on('users')->nullOnDelete();
$table->string('name');
$table->morphs('actionable');
$table->morphs('target');
$table->string('model_type');
$table->uuid('model_id')->nullable();
$table->integer('status')->nullable();
$table->json('fields')->nullable();
$table->text('exception')->nullable();
$table->timestamps(6);
$table->timestamp('finished_at', 6)->nullable();
$table->index(['batch_id', 'model_type', 'model_id']);
});
}
}
};
@@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
if (! Schema::hasTable('activity_log')) {
Schema::create('activity_log', function (Blueprint $table) {
$table->id();
$table->string('log_name')->nullable()->index();
$table->text('description');
$table->nullableMorphs('subject', 'subject');
$table->nullableMorphs('related', 'related');
$table->string('event')->nullable();
$table->nullableMorphs('causer', 'causer');
$table->json('attribute_changes')->nullable();
$table->json('properties')->nullable();
$table->integer('status')->nullable();
$table->text('exception')->nullable();
$table->timestamps(6);
$table->timestamp('finished_at', 6)->nullable();
});
}
}
};
+5 -5
View File
@@ -2,7 +2,7 @@
declare(strict_types=1); declare(strict_types=1);
use App\Enums\Models\Admin\ActionLogStatus; use App\Enums\Models\Admin\ActivityStatus;
use App\Enums\Models\List\ExternalEntryStatus; use App\Enums\Models\List\ExternalEntryStatus;
use App\Enums\Models\List\ExternalProfileSite; use App\Enums\Models\List\ExternalProfileSite;
use App\Enums\Models\List\ExternalProfileVisibility; use App\Enums\Models\List\ExternalProfileVisibility;
@@ -20,10 +20,10 @@ use App\Enums\Models\Wiki\VideoSource;
use App\Enums\Pivots\Document\PageRoleType; use App\Enums\Pivots\Document\PageRoleType;
return [ return [
ActionLogStatus::class => [ ActivityStatus::class => [
ActionLogStatus::RUNNING->name => 'Running', ActivityStatus::RUNNING->name => 'Running',
ActionLogStatus::FAILED->name => 'Failed', ActivityStatus::FAILED->name => 'Failed',
ActionLogStatus::FINISHED->name => 'Finished', ActivityStatus::FINISHED->name => 'Finished',
], ],
AnimeFormat::class => [ AnimeFormat::class => [
AnimeFormat::TV->name => 'TV', AnimeFormat::TV->name => 'TV',
+3 -3
View File
@@ -515,7 +515,7 @@ return [
], ],
], ],
'fields' => [ 'fields' => [
'action_log' => [ 'activity' => [
'name' => 'Name', 'name' => 'Name',
'target' => 'Target', 'target' => 'Target',
'status' => 'Status', 'status' => 'Status',
@@ -1015,7 +1015,7 @@ return [
], ],
'resources' => [ 'resources' => [
'label' => [ 'label' => [
'action_logs' => 'Action Logs', 'activities' => 'Activities',
'anime_theme_entries' => 'Anime Theme Entries', 'anime_theme_entries' => 'Anime Theme Entries',
'anime_themes' => 'Anime Themes', 'anime_themes' => 'Anime Themes',
'anime' => 'Anime', 'anime' => 'Anime',
@@ -1051,7 +1051,7 @@ return [
'videos' => 'Videos', 'videos' => 'Videos',
], ],
'singularLabel' => [ 'singularLabel' => [
'action_log' => 'Action Log', 'activity' => 'Activity',
'anime_theme_entry' => 'Anime Theme Entry', 'anime_theme_entry' => 'Anime Theme Entry',
'anime_theme' => 'Anime Theme', 'anime_theme' => 'Anime Theme',
'anime' => 'Anime', 'anime' => 'Anime',