feat: implement reattach and delete functionality for unused drives with UI updates

This commit is contained in:
2025-12-05 04:34:09 -05:00
parent dfb1de9abf
commit adc4632e24
2 changed files with 338 additions and 3 deletions

View File

@@ -103,6 +103,9 @@
<h3 class="text-lg font-semibold">Storage Quota</h3>
<p class="text-sm text-base/60 mt-1">
{{ number_format($totalAllocatedStorage, 1) }} GB used of {{ number_format($maxAllowedStorage, 1) }} GB allocated
@if(count($unusedDrives) > 0)
<span class="text-warning">(includes detached drives)</span>
@endif
</p>
</div>
<div class="flex items-center gap-2">
@@ -301,6 +304,62 @@
</div>
@endif
</div>
<!-- Detached/Unused Drives -->
@if(count($unusedDrives) > 0)
<div class="bg-background-secondary border border-neutral rounded-lg overflow-hidden">
<div class="p-5 border-b border-neutral">
<div class="flex items-center gap-2">
<x-ri-eject-line class="size-5 text-warning" />
<h3 class="text-lg font-semibold">Detached Drives</h3>
</div>
<p class="text-sm text-base/60 mt-1">These drives have been detached but their data is preserved. You can reattach them or delete them permanently.</p>
</div>
<div class="divide-y divide-neutral">
@foreach($unusedDrives as $unusedKey => $unusedDrive)
<div class="p-4 hover:bg-background/50 transition-colors">
<div class="flex flex-col lg:flex-row lg:items-center justify-between gap-4">
<div class="flex items-start gap-4">
<div class="flex items-center justify-center w-10 h-10 rounded-lg bg-warning/10 flex-shrink-0">
<x-ri-hard-drive-2-line class="size-5 text-warning" />
</div>
<div class="min-w-0">
<div class="flex items-center gap-2 flex-wrap">
<h4 class="font-semibold text-base">{{ $unusedDrive['label'] }}</h4>
<span class="px-2 py-0.5 text-xs font-medium rounded bg-warning/20 text-warning">{{ $unusedKey }}</span>
@if(isset($unusedDrive['size_formatted']))
<span class="px-2 py-0.5 text-xs font-medium rounded bg-info/20 text-info">{{ $unusedDrive['size_formatted'] }}</span>
@endif
</div>
<div class="flex flex-wrap gap-x-4 gap-y-1 mt-1 text-xs text-base/60">
<span class="truncate max-w-[200px]" title="{{ $unusedDrive['volume'] }}">{{ $unusedDrive['volume'] }}</span>
@if(isset($unusedDrive['storage']))
<span>Storage: {{ $unusedDrive['storage'] }}</span>
@endif
</div>
</div>
</div>
<div class="flex items-center gap-2 flex-shrink-0">
<button wire:click="openReattachModal('{{ $unusedKey }}')"
class="inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-lg border border-success/50 bg-success/10 text-success hover:bg-success/20 transition-colors">
<x-ri-link class="size-3.5" />
Reattach
</button>
<button wire:click="deleteUnusedDrive('{{ $unusedKey }}')"
wire:confirm="Are you sure you want to permanently delete this detached drive? This action cannot be undone."
class="inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-lg border border-danger/50 bg-danger/10 text-danger hover:bg-danger/20 transition-colors">
<x-ri-delete-bin-line class="size-3.5" />
Delete
</button>
</div>
</div>
</div>
@endforeach
</div>
</div>
@endif
</div>
<!-- Add Drive Modal -->
@@ -711,4 +770,120 @@
</div>
</div>
@endif
<!-- Reattach Drive Modal -->
@if($showReattachModal)
<div class="fixed inset-0 z-50 overflow-y-auto">
<div class="fixed inset-0 bg-black/50 transition-opacity"></div>
<div class="flex min-h-full items-center justify-center p-4">
<div class="relative w-full max-w-lg transform overflow-hidden rounded-xl bg-background border border-neutral shadow-xl transition-all">
<div class="flex items-center justify-between p-5 border-b border-neutral">
<h3 class="text-lg font-semibold">Reattach Drive</h3>
<button wire:click="closeReattachModal" class="text-foreground-secondary hover:text-foreground transition-colors">
<x-ri-close-line class="size-5" />
</button>
</div>
<div class="p-5 space-y-4">
@if($reattachingDriveKey && isset($unusedDrives[$reattachingDriveKey]))
<div class="bg-background-secondary rounded-lg p-3 border border-neutral">
<div class="flex items-center gap-3">
<div class="p-2 rounded-lg bg-info/10">
<x-ri-hard-drive-3-line class="size-5 text-info" />
</div>
<div>
<p class="text-sm font-medium">{{ $reattachingDriveKey }}</p>
<p class="text-xs text-foreground-secondary">
{{ $unusedDrives[$reattachingDriveKey]['size_formatted'] ?? 'Unknown size' }}
</p>
</div>
</div>
</div>
@endif
<div>
<label class="block text-sm font-medium mb-2">Target Bus</label>
<select wire:model="reattachTargetBus"
class="w-full px-4 py-2 text-sm rounded-lg border border-neutral bg-background focus:outline-none focus:ring-2 focus:ring-primary/50">
<option value="">Select bus type...</option>
<optgroup label="IDE (Max: 4)">
@for($i = 0; $i <= 3; $i++)
@php
$key = "ide{$i}";
$isUsed = isset($drives[$key]);
@endphp
<option value="{{ $key }}" @if($isUsed) disabled @endif>
ide{{ $i }} @if($isUsed) (In use) @endif
</option>
@endfor
</optgroup>
<optgroup label="SATA (Max: 6)">
@for($i = 0; $i <= 5; $i++)
@php
$key = "sata{$i}";
$isUsed = isset($drives[$key]);
@endphp
<option value="{{ $key }}" @if($isUsed) disabled @endif>
sata{{ $i }} @if($isUsed) (In use) @endif
</option>
@endfor
</optgroup>
<optgroup label="SCSI (Max: 31)">
@for($i = 0; $i <= 30; $i++)
@php
$key = "scsi{$i}";
$isUsed = isset($drives[$key]);
@endphp
<option value="{{ $key }}" @if($isUsed) disabled @endif>
scsi{{ $i }} @if($isUsed) (In use) @endif
</option>
@endfor
</optgroup>
<optgroup label="VirtIO (Max: 16)">
@for($i = 0; $i <= 15; $i++)
@php
$key = "virtio{$i}";
$isUsed = isset($drives[$key]);
@endphp
<option value="{{ $key }}" @if($isUsed) disabled @endif>
virtio{{ $i }} @if($isUsed) (In use) @endif
</option>
@endfor
</optgroup>
</select>
</div>
<div class="flex items-start gap-2 p-3 rounded-lg bg-info/10 border border-info/30 text-info text-sm">
<x-ri-information-line class="size-4 flex-shrink-0 mt-0.5" />
<div>
<p>This will reattach the drive to the selected bus position.</p>
</div>
</div>
@if($status && $status->status !== 'stopped')
<div class="flex items-center gap-2 p-3 rounded-lg bg-danger/10 border border-danger/30 text-danger text-sm">
<x-ri-error-warning-line class="size-4 flex-shrink-0" />
<span>VM must be stopped to reattach drives.</span>
</div>
@endif
</div>
<div class="flex justify-end gap-3 p-5 border-t border-neutral">
<button wire:click="closeReattachModal"
class="px-4 py-2 text-sm font-medium rounded-lg border border-neutral bg-background hover:bg-background-secondary transition-colors">
Cancel
</button>
<button wire:click="reattachDrive"
wire:loading.attr="disabled"
class="px-4 py-2 text-sm font-medium rounded-lg bg-primary text-white hover:bg-primary/90 disabled:opacity-50 transition-colors"
@if(!$reattachTargetBus || ($status && $status->status !== 'stopped')) disabled @endif>
<x-loading target="reattachDrive" />
<span wire:loading.remove wire:target="reattachDrive">Reattach Drive</span>
<span wire:loading wire:target="reattachDrive">Reattaching...</span>
</button>
</div>
</div>
</div>
</div>
@endif
</x-proxmox::layout>