98 lines
3.5 KiB
PHP
98 lines
3.5 KiB
PHP
<?php
|
|
|
|
namespace App\Livewire\Admin;
|
|
|
|
use App\Models\Datacenter;
|
|
use Illuminate\Validation\Rule;
|
|
use Livewire\Attributes\Validate;
|
|
use LivewireUI\Modal\ModalComponent;
|
|
|
|
/**
|
|
* Edit a datacenter's name and location in a modal (avoids the row-height jump
|
|
* of inline editing). The code is immutable — it is referenced by hosts. Country
|
|
* is picked from a list so it can't be mistyped.
|
|
*/
|
|
class EditDatacenter extends ModalComponent
|
|
{
|
|
public string $uuid = '';
|
|
|
|
public string $code = '';
|
|
|
|
#[Validate('required|string|max:255')]
|
|
public string $name = '';
|
|
|
|
public string $location = '';
|
|
|
|
/** The location present when the modal opened — a pre-curation free-form value. */
|
|
public string $originalLocation = '';
|
|
|
|
/**
|
|
* Whether new hosts and orders may still be placed here.
|
|
*
|
|
* The column and the scope existed; the form did not offer it, so a
|
|
* datacenter could be created and never switched off again — the one
|
|
* lifecycle action a location actually needs.
|
|
*/
|
|
public bool $active = true;
|
|
|
|
public function mount(string $uuid): void
|
|
{
|
|
$this->authorize('datacenters.manage'); // modals are reachable without the route middleware
|
|
$dc = Datacenter::query()->where('uuid', $uuid)->firstOrFail();
|
|
$this->uuid = $uuid;
|
|
$this->code = $dc->code;
|
|
$this->name = $dc->name;
|
|
$this->location = (string) $dc->location;
|
|
$this->originalLocation = (string) $dc->location;
|
|
$this->active = (bool) $dc->active;
|
|
}
|
|
|
|
public function save()
|
|
{
|
|
$this->authorize('datacenters.manage');
|
|
|
|
// Accept the configured countries plus the record's own legacy value, so a
|
|
// datacenter created before the curated list can still be edited. The
|
|
// legacy value is read from the DB — never from the client-hydrated
|
|
// property, which could be forged to whitelist an arbitrary location.
|
|
$dc = Datacenter::query()->where('uuid', $this->uuid)->firstOrFail();
|
|
$allowed = array_keys((array) config('countries'));
|
|
if ($dc->location) {
|
|
$allowed[] = $dc->location;
|
|
}
|
|
$data = $this->validate([
|
|
'name' => 'required|string|max:255',
|
|
'location' => ['nullable', Rule::in($allowed)], // array form — a legacy value may contain commas
|
|
'active' => 'boolean',
|
|
]);
|
|
|
|
// Only on the transition, and compared against what is STORED: an
|
|
// already-inactive location would otherwise announce that it had just
|
|
// been switched off every time its name was edited.
|
|
$justDeactivated = $dc->active && ! $data['active'];
|
|
$hostsLeftRunning = $justDeactivated ? $dc->hosts()->count() : 0;
|
|
|
|
Datacenter::query()->where('uuid', $this->uuid)->update([
|
|
'name' => $data['name'],
|
|
'location' => $data['location'] ?: null,
|
|
'active' => $data['active'],
|
|
]);
|
|
|
|
// One message, not two. Both go through the same toast, and the second
|
|
// replaces the first — so the generic "saved" would swallow the only
|
|
// sentence that says the hosts there are still running.
|
|
$this->dispatch('notify', message: $hostsLeftRunning > 0
|
|
? __('datacenters.deactivated_with_hosts', ['n' => $hostsLeftRunning])
|
|
: __('datacenters.updated'));
|
|
|
|
return $this->redirectRoute('admin.datacenters', navigate: true);
|
|
}
|
|
|
|
public function render()
|
|
{
|
|
return view('livewire.admin.edit-datacenter', [
|
|
'countries' => config('countries'),
|
|
]);
|
|
}
|
|
}
|