Add bulk update IP action for allocations

Co-authored-by: notAreYouScared <1757840+notAreYouScared@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2025-10-28 13:03:56 +00:00
parent 031487552c
commit e2a75f278d
3 changed files with 132 additions and 0 deletions

View File

@ -3,6 +3,7 @@
namespace App\Filament\Admin\Resources\Nodes\RelationManagers;
use App\Filament\Admin\Resources\Servers\Pages\CreateServer;
use App\Filament\Components\Actions\BulkUpdateAllocationIpAction;
use App\Models\Allocation;
use App\Models\Node;
use App\Services\Allocations\AssignmentService;
@ -120,6 +121,9 @@ class AllocationsRelationManager extends RelationManager
->action(fn (array $data, AssignmentService $service) => $service->handle($this->getOwnerRecord(), $data)),
])
->groupedBulkActions([
BulkUpdateAllocationIpAction::make()
->availableIps($this->getOwnerRecord()->ipAddresses())
->authorize(fn () => user()?->can('update', $this->getOwnerRecord())),
DeleteBulkAction::make()
->authorize(fn () => user()?->can('update', $this->getOwnerRecord())),
]);

View File

@ -0,0 +1,117 @@
<?php
namespace App\Filament\Components\Actions;
use App\Models\Allocation;
use Filament\Actions\Action;
use Filament\Actions\BulkAction;
use Filament\Forms\Components\Select;
use Filament\Notifications\Notification;
use Illuminate\Database\Eloquent\Collection;
class BulkUpdateAllocationIpAction extends BulkAction
{
public static function getDefaultName(): ?string
{
return 'bulk_update_ip';
}
protected function setUp(): void
{
parent::setUp();
$this->label(trans('admin/node.bulk_update_ip'));
$this->icon('tabler-replace');
$this->color('warning');
$this->requiresConfirmation();
$this->modalHeading(trans('admin/node.bulk_update_ip'));
$this->modalDescription(trans('admin/node.bulk_update_ip_description'));
$this->modalIconColor('warning');
$this->modalSubmitActionLabel(trans('admin/node.update_ip'));
$this->schema(function (Collection $records) {
// Get unique IPs from selected allocations
$currentIps = $records->pluck('ip')->unique()->values()->all();
// Get available IPs from the node (we need access to the owner record)
// This will be set dynamically when the action is used
$availableIps = $this->getAvailableIps();
return [
Select::make('old_ip')
->label(trans('admin/node.old_ip'))
->options(array_combine($currentIps, $currentIps))
->required()
->helperText(trans('admin/node.old_ip_help'))
->live(),
Select::make('new_ip')
->label(trans('admin/node.new_ip'))
->options(fn () => array_combine($availableIps, $availableIps))
->required()
->helperText(trans('admin/node.new_ip_help'))
->different('old_ip'),
];
});
$this->action(function (Collection $records, array $data) {
$oldIp = $data['old_ip'];
$newIp = $data['new_ip'];
// Filter records to only those with the old IP
$recordsToUpdate = $records->filter(fn (Allocation $allocation) => $allocation->ip === $oldIp);
if ($recordsToUpdate->count() === 0) {
Notification::make()
->title(trans('admin/node.no_allocations_to_update'))
->warning()
->send();
return;
}
$updated = 0;
$failed = 0;
/** @var Allocation $allocation */
foreach ($recordsToUpdate as $allocation) {
try {
$allocation->update(['ip' => $newIp]);
$updated++;
} catch (\Exception $exception) {
$failed++;
report($exception);
}
}
Notification::make()
->title(trans('admin/node.ip_updated', ['count' => $updated, 'total' => $recordsToUpdate->count()]))
->body($failed > 0 ? trans('admin/node.ip_update_failed', ['count' => $failed]) : null)
->status($failed > 0 ? 'warning' : 'success')
->persistent()
->send();
});
$this->deselectRecordsAfterCompletion();
}
protected array $availableIps = [];
public function availableIps(array $ips): static
{
$this->availableIps = $ips;
return $this;
}
protected function getAvailableIps(): array
{
return $this->availableIps;
}
}

View File

@ -121,4 +121,15 @@ return [
'title' => 'Cloudflare Issue',
'body' => 'Your Node is not accessible by Cloudflare',
],
'bulk_update_ip' => 'Bulk Update IP',
'bulk_update_ip_description' => 'Replace an old IP address with a new one for selected allocations. This is useful when a node\'s IP address changes.',
'update_ip' => 'Update IP',
'old_ip' => 'Old IP Address',
'old_ip_help' => 'Select the IP address you want to replace.',
'new_ip' => 'New IP Address',
'new_ip_help' => 'Select the new IP address to use.',
'no_allocations_to_update' => 'No allocations with the selected old IP address were found.',
'ip_updated' => 'Successfully updated :count of :total allocation(s).',
'ip_update_failed' => ':count allocation(s) failed to update.',
];