feat: add delete confirmation modal for ConnectionProviders
- Introduced a Livewire-powered confirmation modal for deleting connection providers. - Updated `delete` method to support selected provider deletion and modal interaction. - Added `connectedApps` relationship to `ConnectionProvider` model for mass soft-deletes. - Refactored delete logic to handle associated connected apps during provider deletion. - Updated UI to include modal trigger and actions for enhanced user safety.
This commit is contained in:
parent
1c5ab498d7
commit
3c6e4bf4bd
@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\{Model, Relations\BelongsTo, SoftDeletes};
|
||||||
use Illuminate\Database\Eloquent\Attributes\Fillable;
|
use Illuminate\Database\Eloquent\Attributes\Fillable;
|
||||||
use Illuminate\Database\Eloquent\{Model, SoftDeletes};
|
|
||||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||||
|
|
||||||
#[Fillable([
|
#[Fillable([
|
||||||
@ -24,9 +24,9 @@ public function protocol(): HasOne
|
|||||||
return $this->hasOne(ConnectionProtocol::class, 'id', 'connection_protocol_id');
|
return $this->hasOne(ConnectionProtocol::class, 'id', 'connection_protocol_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function provider(): HasOne
|
public function provider(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->hasOne(ConnectionProvider::class, 'id', 'connection_provider_id');
|
return $this->belongsTo(ConnectionProvider::class, 'connection_provider_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function status(): HasOne
|
public function status(): HasOne
|
||||||
|
|||||||
@ -4,11 +4,16 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\{Model, Relations\HasMany, SoftDeletes};
|
||||||
use Illuminate\Database\Eloquent\Attributes\Fillable;
|
use Illuminate\Database\Eloquent\Attributes\Fillable;
|
||||||
use Illuminate\Database\Eloquent\{Model, SoftDeletes};
|
|
||||||
|
|
||||||
#[Fillable(['name', 'slug'])]
|
#[Fillable(['name', 'slug'])]
|
||||||
final class ConnectionProvider extends Model
|
final class ConnectionProvider extends Model
|
||||||
{
|
{
|
||||||
use SoftDeletes;
|
use SoftDeletes;
|
||||||
|
|
||||||
|
public function connectedApps(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(ConnectedApp::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,22 +58,31 @@ public function getAll(): PaginatedDataCollection
|
|||||||
public function update(string $slug, StoreConnectionProviderRequestData $data): void
|
public function update(string $slug, StoreConnectionProviderRequestData $data): void
|
||||||
{
|
{
|
||||||
DB::transaction(
|
DB::transaction(
|
||||||
fn () => ConnectionProvider::query()
|
fn() => ConnectionProvider::query()
|
||||||
->where('slug', $slug)
|
->where('slug', $slug)
|
||||||
->update($data->toArray())
|
->update($data->toArray())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Delete the connection provider and associated connected apps.
|
||||||
|
* @throws ModelNotFoundException when the connection provider is not found.
|
||||||
* @throws Throwable when an error occurs during the deletion.
|
* @throws Throwable when an error occurs during the deletion.
|
||||||
* @throws InvalidArgumentException when id is invalid
|
|
||||||
*/
|
*/
|
||||||
public function delete(string $slug): void
|
public function delete(string $slug): void
|
||||||
{
|
{
|
||||||
DB::transaction(
|
DB::transaction(
|
||||||
fn () => ConnectionProvider::query()
|
function () use ($slug): void {
|
||||||
|
$provider = ConnectionProvider::query()
|
||||||
->where('slug', $slug)
|
->where('slug', $slug)
|
||||||
->delete()
|
->firstOrFail();
|
||||||
|
|
||||||
|
// Note: This performs a mass soft-delete query.
|
||||||
|
// Model events for ConnectedApp will NOT fire.
|
||||||
|
$provider->connectedApps()->delete();
|
||||||
|
|
||||||
|
$provider->delete();
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,9 @@
|
|||||||
#[DataCollectionOf(TableHeader::class)]
|
#[DataCollectionOf(TableHeader::class)]
|
||||||
public DataCollection $headers;
|
public DataCollection $headers;
|
||||||
|
|
||||||
|
public bool $cnfModal = false;
|
||||||
|
public string $selectedProvider = '';
|
||||||
|
|
||||||
public function boot(ConnectionProviderService $service): void
|
public function boot(ConnectionProviderService $service): void
|
||||||
{
|
{
|
||||||
$this->service = $service;
|
$this->service = $service;
|
||||||
@ -45,13 +48,26 @@ public function edit(string $providerSlug): void
|
|||||||
$this->redirectRoute('apps.connectionProviders.edit', ['slug' => $providerSlug]);
|
$this->redirectRoute('apps.connectionProviders.edit', ['slug' => $providerSlug]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function delete(string $providerSlug): void
|
public function delete(): void
|
||||||
{
|
{
|
||||||
|
$this->cnfModal = false;
|
||||||
$this->attempt(
|
$this->attempt(
|
||||||
action: fn() => $this->service->delete($providerSlug),
|
action: function () {
|
||||||
successMessage: "Connection Provider deleted!"
|
$this->service->delete($this->selectedProvider);
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function showModal(string $providerSlug): void
|
||||||
|
{
|
||||||
|
$this->selectedProvider = $providerSlug;
|
||||||
|
$this->cnfModal = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function cancelModal(): void
|
||||||
|
{
|
||||||
|
$this->selectedProvider = '';
|
||||||
|
$this->cnfModal = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
?>
|
?>
|
||||||
@ -68,12 +84,23 @@ public function delete(string $providerSlug): void
|
|||||||
<div class="flex">
|
<div class="flex">
|
||||||
<x-mary-button icon="lucide.edit" wire:click="edit('{{$row->slug}}')" spinner="edit('{{$row->slug}}')"
|
<x-mary-button icon="lucide.edit" wire:click="edit('{{$row->slug}}')" spinner="edit('{{$row->slug}}')"
|
||||||
class="mr-2 btn-sm text-gray-500"/>
|
class="mr-2 btn-sm text-gray-500"/>
|
||||||
<x-mary-button icon="lucide.trash" wire:click="delete('{{$row->slug}}')"
|
<x-mary-button icon="lucide.trash" wire:click="showModal('{{$row->slug}}')"
|
||||||
spinner="delete('{{$row->slug}}')"
|
spinner="showModal('{{$row->slug}}')"
|
||||||
variant="danger"
|
variant="danger"
|
||||||
class="btn-sm btn-error btn-soft"/>
|
class="btn-sm btn-error btn-soft"/>
|
||||||
</div>
|
</div>
|
||||||
@endscope
|
@endscope
|
||||||
</x-mary-table>
|
</x-mary-table>
|
||||||
</x-shared.card>
|
</x-shared.card>
|
||||||
|
<x-mary-modal wire:model="cnfModal" title="Delete Confirmation" persistent separator>
|
||||||
|
<x-mary-alert title="This will delete all the connected apps of this provider."
|
||||||
|
icon="o-exclamation-triangle"
|
||||||
|
class="alert-warning"
|
||||||
|
/>
|
||||||
|
<x-slot:actions>
|
||||||
|
<x-mary-button label="Cancel" wire:click="cancelModal"/>
|
||||||
|
<x-mary-button label="Proceed" wire:click="delete" spinner="delete" class="btn-error"/>
|
||||||
|
</x-slot:actions>
|
||||||
|
</x-mary-modal>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user