diff --git a/app/Filament/Admin/Actions/MergeBulkAction.php b/app/Filament/Admin/Actions/MergeBulkAction.php deleted file mode 100644 index 87a179a..0000000 --- a/app/Filament/Admin/Actions/MergeBulkAction.php +++ /dev/null @@ -1,70 +0,0 @@ -label(__('actions.merge.multiple.label')); - - $this->modalHeading(fn () => __('actions.merge.multiple.modal.heading', ['label' => $this->getPluralModelLabel()])); - - $this->modalSubmitActionLabel(__('actions.merge.multiple.modal.actions.merge.label')); - - $this->successNotificationTitle(__('actions.merge.multiple.notifications.merged.title')); - - $this->color('warning'); - - $this->outlined(); - - // $this->icon(FilamentIcon::resolve('actions::merge-action') ?? 'heroicon-m-trash'); - - $this->requiresConfirmation(); - - $this->modalIcon(FilamentIcon::resolve('actions::merge-action.modal') ?? 'heroicon-o-trash'); - - $this->action(function () { - $this->process(static function (Collection $records) { - $keep = $records - ->sortBy('id') - ->first(); - - $records = $records->reject(fn (Model $record) => $record->is($keep)); - - $data = $keep->toArray(); - - $records->each(function (Model $record) use (&$data) { - $data = array_merge_recursive($data, $record->toArray()); - }); - - $keep->update($data); - - // TODO: handle relationships - - $records->each->delete(); - }); - - $this->success(); - }); - - $this->deselectRecordsAfterCompletion(); - } -} diff --git a/app/Filament/Admin/Resources/LocationResource.php b/app/Filament/Admin/Resources/LocationResource.php index 2c5f3ad..cde7926 100644 --- a/app/Filament/Admin/Resources/LocationResource.php +++ b/app/Filament/Admin/Resources/LocationResource.php @@ -4,7 +4,7 @@ namespace App\Filament\Admin\Resources; -use App\Filament\Admin\Actions\MergeBulkAction; +use App\Filament\Admin\Resources\LocationResource\Actions\MergeLocationsBulkAction; use App\Filament\Admin\Resources\LocationResource\Pages; use App\Models\Location; use Filament\Forms\Components\TextInput; @@ -47,7 +47,7 @@ public static function form(Form $form): Form TextInput::make('name') ->label(__('app.field.name')) ->columnSpanFull() - ->maxLength(200) + ->maxLength(100) ->required(), ]); } @@ -64,6 +64,9 @@ public static function table(Table $table): Table TextColumn::make('name') ->label(__('app.field.name')) + ->lineClamp(2) + ->limit(100) + ->wrap() ->searchable() ->sortable(), ]) @@ -77,7 +80,7 @@ public static function table(Table $table): Table ]), ]) ->bulkActions([ - MergeBulkAction::make(), + MergeLocationsBulkAction::make(), ]); } diff --git a/app/Filament/Admin/Resources/LocationResource/Actions/MergeLocationsBulkAction.php b/app/Filament/Admin/Resources/LocationResource/Actions/MergeLocationsBulkAction.php new file mode 100644 index 0000000..20f98a2 --- /dev/null +++ b/app/Filament/Admin/Resources/LocationResource/Actions/MergeLocationsBulkAction.php @@ -0,0 +1,94 @@ +label(__('actions.merge.multiple.label')); + + $this->modalHeading(fn () => __('actions.merge.multiple.modal.heading', ['label' => $this->getPluralModelLabel()])); + + $this->modalSubmitActionLabel(__('actions.merge.multiple.modal.actions.merge.label')); + + $this->successNotificationTitle(__('actions.merge.multiple.notifications.merged.title')); + + $this->color('warning'); + + $this->outlined(); + + $this->icon(FilamentIcon::resolve('actions::merge-action') ?? 'majestic-git-pull-line'); + + $this->requiresConfirmation(); + + $this->modalIcon(FilamentIcon::resolve('actions::merge-action.modal') ?? 'majestic-git-pull-line'); + + $this->action(function (Collection $records) { + $keep = $records + ->sortBy('id') + ->first(); + + $records = $records->reject(fn (Model $record) => $record->is($keep)); + + $name = data_get($keep->toArray(), 'name'); + + $records->each(function (Model $record) use (&$name) { + $name = array_merge_recursive($name, data_get($record->toArray(), 'name')); + }); + + $name = collect($name) + ->map(function (array | string $items) { + if (\is_array($items)) { + return collect($items) + ->unique() + ->join(', '); + } + + return $items; + }) + ->toArray(); + + DB::transaction(function () use ($records, $keep, $name) { + $keep->replaceTranslations('name', $name) + ->save(); + + Organization::query() + ->whereIn('location_id', $records->pluck('id')) + ->get() + ->each->update(['location_id' => $keep->id]); + + Shelter::query() + ->whereIn('location_id', $records->pluck('id')) + ->get() + ->each->update(['location_id' => $keep->id]); + + $records->each->delete(); + }); + + $this->success(); + }); + + $this->deselectRecordsAfterCompletion(); + } +} diff --git a/app/Filament/Admin/Resources/OrganizationResource.php b/app/Filament/Admin/Resources/OrganizationResource.php index d84f602..21ac51d 100644 --- a/app/Filament/Admin/Resources/OrganizationResource.php +++ b/app/Filament/Admin/Resources/OrganizationResource.php @@ -88,6 +88,9 @@ public static function table(Table $table): Table TextColumn::make('location.name') ->label(__('app.field.location')) + ->lineClamp(2) + ->limit(100) + ->wrap() ->searchable() ->sortable(), diff --git a/app/Filament/Admin/Resources/OrganizationResource/RelationManagers/SheltersRelationManager.php b/app/Filament/Admin/Resources/OrganizationResource/RelationManagers/SheltersRelationManager.php index 759f860..df4f954 100644 --- a/app/Filament/Admin/Resources/OrganizationResource/RelationManagers/SheltersRelationManager.php +++ b/app/Filament/Admin/Resources/OrganizationResource/RelationManagers/SheltersRelationManager.php @@ -45,6 +45,9 @@ public function table(Table $table): Table TextColumn::make('location.name') ->label(__('app.field.location')) + ->lineClamp(2) + ->limit(100) + ->wrap() ->searchable() ->sortable(), diff --git a/app/Models/Location.php b/app/Models/Location.php index dff4836..e20ae47 100644 --- a/app/Models/Location.php +++ b/app/Models/Location.php @@ -8,6 +8,8 @@ use Database\Factories\LocationFactory; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\SoftDeletes; use Spatie\Translatable\HasTranslations; class Location extends Model @@ -16,6 +18,7 @@ class Location extends Model use HasFactory; use HasTranslations; use LogsActivity; + use SoftDeletes; protected static string $factory = LocationFactory::class; @@ -26,4 +29,14 @@ class Location extends Model public array $translatable = [ 'name', ]; + + public function organizations(): HasMany + { + return $this->hasMany(Organization::class); + } + + public function shelters(): HasMany + { + return $this->hasMany(Shelter::class); + } } diff --git a/database/migrations/0001_01_04_000006_add_deleted_at_column_to_locations_table.php b/database/migrations/0001_01_04_000006_add_deleted_at_column_to_locations_table.php new file mode 100644 index 0000000..8933501 --- /dev/null +++ b/database/migrations/0001_01_04_000006_add_deleted_at_column_to_locations_table.php @@ -0,0 +1,17 @@ +timestamp('deleted_at')->nullable(); + }); + } +}; diff --git a/tests/Feature/Admin/LocationsTest.php b/tests/Feature/Admin/LocationsTest.php index 98b4397..edd7f3d 100644 --- a/tests/Feature/Admin/LocationsTest.php +++ b/tests/Feature/Admin/LocationsTest.php @@ -4,7 +4,7 @@ namespace Tests\Feature\Admin; -use App\Filament\Admin\Actions\MergeBulkAction; +use App\Filament\Admin\Resources\LocationResource\Actions\MergeLocationsBulkAction; use App\Filament\Admin\Resources\LocationResource\Pages\ManageLocations; use App\Models\Location; use App\Models\User; @@ -87,7 +87,7 @@ public function superadmins_can_bulk_merge_two_locations(): void Livewire::test(ManageLocations::class) ->assertCountTableRecords(2) - ->callTableBulkAction(MergeBulkAction::class, $locations->pluck('id')) + ->callTableBulkAction(MergeLocationsBulkAction::class, $locations->pluck('id')) ->assertHasNoTableActionErrors() ->assertCountTableRecords(1) ->assertSeeText($locations->pluck('name')->join(', '));