diff --git a/app/Filament/Resources/EmulatorResource/RelationManagers/EmulatorReleasesRelationManager.php b/app/Filament/Resources/EmulatorResource/RelationManagers/EmulatorReleasesRelationManager.php index 20d128ce8..01ef49214 100644 --- a/app/Filament/Resources/EmulatorResource/RelationManagers/EmulatorReleasesRelationManager.php +++ b/app/Filament/Resources/EmulatorResource/RelationManagers/EmulatorReleasesRelationManager.php @@ -25,9 +25,16 @@ public function form(Form $form): Form { return $form ->schema([ - Forms\Components\TextInput::make('title') - ->required() - ->maxLength(255), + Forms\Components\TextInput::make('version'), + + Forms\Components\DatePicker::make('created_at') + ->label('Release Date') + ->native(false) + ->date(), + + Forms\Components\Toggle::make('stable'), + + Forms\Components\Toggle::make('minimum'), ]); } @@ -54,13 +61,17 @@ public function table(Table $table): Table ->alignCenter(), ]) ->filters([ - + Tables\Filters\TrashedFilter::make(), ]) ->headerActions([ - + Tables\Actions\CreateAction::make(), ]) ->actions([ - + Tables\Actions\ActionGroup::make([ + Tables\Actions\EditAction::make(), + Tables\Actions\DeleteAction::make(), + Tables\Actions\RestoreAction::make(), + ]), ]) ->defaultSort(function (Builder $query): Builder { return $query->orderByDesc('created_at'); diff --git a/app/Filament/Resources/EmulatorResource/RelationManagers/SystemsRelationManager.php b/app/Filament/Resources/EmulatorResource/RelationManagers/SystemsRelationManager.php index 8a7802f1a..b24be2984 100644 --- a/app/Filament/Resources/EmulatorResource/RelationManagers/SystemsRelationManager.php +++ b/app/Filament/Resources/EmulatorResource/RelationManagers/SystemsRelationManager.php @@ -35,19 +35,25 @@ public function form(Form $form): Form public function table(Table $table): Table { return $table - ->recordTitleAttribute('title') + ->recordTitleAttribute('name_full') ->columns([ Tables\Columns\ImageColumn::make('icon_url') ->label('') ->size(config('media.icon.sm.width')), + Tables\Columns\TextColumn::make('ID') ->label('ID') ->sortable() - ->searchable(), + ->searchable(query: function (Builder $query, string $search): Builder { + return $query->where('Console.ID', 'like', "%{$search}%"); + }), + Tables\Columns\TextColumn::make('name_full') ->label('Full name') ->description(fn (System $record): ?string => $record->name_short) - ->searchable() + ->searchable(query: function (Builder $query, string $search): Builder { + return $query->where('Console.name_full', 'like', "%{$search}%"); + }) ->sortable() ->grow(true), ]) @@ -55,10 +61,11 @@ public function table(Table $table): Table ]) ->headerActions([ - + Tables\Actions\AttachAction::make() + ->preloadRecordSelect(), ]) ->actions([ - + Tables\Actions\DetachAction::make(), ]) ->defaultSort(function (Builder $query): Builder { return $query->orderBy('name_full'); diff --git a/app/Models/Emulator.php b/app/Models/Emulator.php index 76e0199fb..06decb5a8 100644 --- a/app/Models/Emulator.php +++ b/app/Models/Emulator.php @@ -6,11 +6,14 @@ use App\Support\Database\Eloquent\BaseModel; use App\Support\Database\Eloquent\BasePivot; +use Fico7489\Laravel\Pivot\Traits\PivotEventTrait; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Support\Collection; +use Illuminate\Support\Facades\Auth; use Spatie\Activitylog\LogOptions; use Spatie\Activitylog\Traits\LogsActivity; use Spatie\EloquentSortable\SortableTrait; @@ -21,9 +24,18 @@ class Emulator extends BaseModel implements HasMedia { + /* + * Framework Traits + */ use SoftDeletes; use SortableTrait; + + /* + * Providers Traits + */ + use PivotEventTrait; use InteractsWithMedia; + use LogsActivity { LogsActivity::activities as auditLog; } @@ -38,6 +50,46 @@ class Emulator extends BaseModel implements HasMedia 'source_url', ]; + public static function boot() + { + parent::boot(); + + static::pivotAttached(function ($model, $relationName, $pivotIds, $pivotIdsAttributes) { + if ($relationName === 'systems') { + /** @var User $user */ + $user = Auth::user(); + + activity()->causedBy($user)->performedOn($model) + ->withProperty('old', [$relationName => null]) + ->withProperty('attributes', [$relationName => (new Collection($pivotIds)) + ->map(fn ($pivotId) => [ + 'id' => $pivotId, + 'attributes' => $pivotIdsAttributes[$pivotId], + ]), + ]) + ->event('pivotAttached') + ->log('pivotAttached'); + } + }); + + static::pivotDetached(function ($model, $relationName, $pivotIds) { + if ($relationName === 'systems') { + /** @var User $user */ + $user = Auth::user(); + + activity()->causedBy($user)->performedOn($model) + ->withProperty('old', [$relationName => (new Collection($pivotIds)) + ->map(fn ($pivotId) => [ + 'id' => $pivotId, + ]), + ]) + ->withProperty('attributes', [$relationName => null]) + ->event('pivotDetached') + ->log('pivotDetached'); + } + }); + } + // audit activity log public function getActivitylogOptions(): LogOptions @@ -89,7 +141,7 @@ public function registerMediaCollections(): void */ public function systems(): BelongsToMany { - return $this->belongsToMany(System::class, 'system_emulators') + return $this->belongsToMany(System::class, 'system_emulators', 'emulator_id', 'system_id') ->using(BasePivot::class) ->withTimestamps(); } diff --git a/app/Models/EmulatorRelease.php b/app/Models/EmulatorRelease.php index eefb262c5..e731dea14 100644 --- a/app/Models/EmulatorRelease.php +++ b/app/Models/EmulatorRelease.php @@ -8,6 +8,8 @@ use App\Support\Database\Eloquent\BaseModel; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\SoftDeletes; +use Spatie\Activitylog\LogOptions; +use Spatie\Activitylog\Traits\LogsActivity; use Spatie\MediaLibrary\HasMedia; use Spatie\MediaLibrary\InteractsWithMedia; @@ -17,6 +19,10 @@ class EmulatorRelease extends BaseModel implements HasMedia use InteractsWithMedia; use HasStabilityFlags; + use LogsActivity { + LogsActivity::activities as auditLog; + } + protected $table = 'emulator_releases'; protected $fillable = [ @@ -25,6 +31,7 @@ class EmulatorRelease extends BaseModel implements HasMedia 'notes', 'stable', 'version', + 'created_at', ]; protected $with = [ @@ -32,6 +39,35 @@ class EmulatorRelease extends BaseModel implements HasMedia 'media', ]; + protected static function booted() + { + static::saving(function (EmulatorRelease $release) { + if ($release->minimum) { + // Set all other releases for this emulator to not be the minimum. + // There can only be one minimum. + static::where('emulator_id', $release->emulator_id) + ->where('id', '!=', $release->id) + ->update(['minimum' => false]); + } + }); + } + + // audit activity log + + public function getActivitylogOptions(): LogOptions + { + return LogOptions::defaults() + ->logOnly([ + 'emulator_id', + 'version', + 'stable', + 'minimum', + 'notes', + ]) + ->logOnlyDirty() + ->dontSubmitEmptyLogs(); + } + // == media public function registerMediaCollections(): void diff --git a/app/Models/User.php b/app/Models/User.php index cf6f94ed0..2466c1c77 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -32,6 +32,7 @@ use Illuminate\Notifications\Notifiable; use Illuminate\Support\Carbon; use Illuminate\Support\Collection; +use Illuminate\Support\Facades\Auth; use Jenssegers\Optimus\Optimus; use Laravel\Scout\Searchable; use Spatie\Activitylog\LogOptions; @@ -219,7 +220,9 @@ public static function boot() static::pivotAttached(function ($model, $relationName, $pivotIds, $pivotIdsAttributes) { if ($relationName === 'roles') { - activity()->causedBy(auth()->user())->performedOn($model) + $user = Auth::user(); + + activity()->causedBy($user)->performedOn($model) ->withProperty('old', [$relationName => null]) ->withProperty('attributes', [$relationName => (new Collection($pivotIds)) ->map(fn ($pivotId) => [ @@ -234,7 +237,9 @@ public static function boot() static::pivotDetached(function ($model, $relationName, $pivotIds) { if ($relationName === 'roles') { - activity()->causedBy(auth()->user())->performedOn($model) + $user = Auth::user(); + + activity()->causedBy($user)->performedOn($model) ->withProperty('old', [$relationName => (new Collection($pivotIds)) ->map(fn ($pivotId) => [ 'id' => $pivotId, diff --git a/app/Policies/EmulatorReleasePolicy.php b/app/Policies/EmulatorReleasePolicy.php index cbeb39be6..26518852c 100644 --- a/app/Policies/EmulatorReleasePolicy.php +++ b/app/Policies/EmulatorReleasePolicy.php @@ -66,6 +66,13 @@ public function restore(User $user, EmulatorRelease $emulatorRelease): bool ]); } + public function restoreAny(User $user): bool + { + return $user->hasAnyRole([ + Role::RELEASE_MANAGER, + ]); + } + public function forceDelete(User $user, EmulatorRelease $emulatorRelease): bool { return $user->hasAnyRole([