Enhance Proxmox views with improved loading states and UI updates

- Updated serverplaceholder.blade.php to enhance loading skeletons for server details.
- Added navigation breadcrumbs to statistics, subdomain, and system views for better user experience.
- Improved loading indicators for CPU, network, memory, and disk charts in statistics.blade.php.
- Refined storage.blade.php layout with section dividers and improved drive display, including bus type indicators and quota usage.
- Enhanced VNC and Xterm popups with a new header design, loading animations, and reconnect functionality.
- Added error handling for VNC and Xterm connections to inform users when unable to connect.
This commit is contained in:
2026-02-24 19:51:46 -05:00
parent af62a16354
commit 16cd5f05de
40 changed files with 1423 additions and 475 deletions

View File

@@ -514,18 +514,40 @@ class Storage extends Component
*/
public function addDrive(): void
{
// Validate bus type against allowed values to prevent config key injection
if (!array_key_exists($this->newDriveBus, $this->busTypes)) {
$this->notify('Invalid bus type selected.', 'error');
return;
}
// Validate cache mode against allowed values to prevent config value injection
$allowedCaches = array_column($this->cacheOptions, 'value');
if (!in_array($this->newDriveCache, $allowedCaches, true)) {
$this->notify('Invalid cache mode selected.', 'error');
return;
}
// Validate AIO type against allowed values to prevent config value injection
$allowedAios = array_column($this->aioOptions, 'value');
if (!in_array($this->newDriveAio, $allowedAios, true)) {
$this->notify('Invalid async IO type selected.', 'error');
return;
}
// Validate size
if ($this->newDriveSize < 1) {
$this->notify('Drive size must be at least 1 GB.', 'error');
return;
}
// Check storage quota
$newTotal = $this->totalAllocatedStorage + $this->newDriveSize;
if ($newTotal > $this->maxAllowedStorage) {
$remaining = $this->maxAllowedStorage - $this->totalAllocatedStorage;
$this->notify("Adding this drive would exceed your storage quota. You have {$remaining} GB remaining.", 'error');
return;
// Check storage quota (skip if no limit is set, i.e. maxAllowedStorage is 0)
if ($this->maxAllowedStorage > 0) {
$newTotal = $this->totalAllocatedStorage + $this->newDriveSize;
if ($newTotal > $this->maxAllowedStorage) {
$remaining = max(0, $this->maxAllowedStorage - $this->totalAllocatedStorage);
$this->notify("Adding this drive would exceed your storage quota. You have {$remaining} GB remaining.", 'error');
return;
}
}
// Get next available index
@@ -644,6 +666,20 @@ class Storage extends Component
return;
}
// Validate cache mode against allowed values to prevent config value injection
$allowedCaches = array_column($this->cacheOptions, 'value');
if (!in_array($this->editDriveCache, $allowedCaches, true)) {
$this->notify('Invalid cache mode selected.', 'error');
return;
}
// Validate AIO type against allowed values to prevent config value injection
$allowedAios = array_column($this->aioOptions, 'value');
if (!in_array($this->editDriveAio, $allowedAios, true)) {
$this->notify('Invalid async IO type selected.', 'error');
return;
}
$drive = $this->drives[$this->editingDriveKey];
$busType = $drive['bus'];
@@ -840,6 +876,12 @@ class Storage extends Component
$drive = $this->drives[$this->movingDriveKey];
$targetBus = $this->moveDriveTargetBus;
// Validate target bus type against allowed values
if (!array_key_exists($targetBus, $this->busTypes)) {
$this->notify('Invalid target bus type.', 'error');
return;
}
// Prevent moving to the same bus type
if ($drive['bus'] === $targetBus) {
$this->notify('Drive is already on the ' . $this->busTypes[$targetBus]['label'] . ' bus.', 'error');
@@ -1080,6 +1122,12 @@ class Storage extends Component
$unusedDrive = $this->unusedDrives[$this->reattachingDriveKey];
$targetBus = $this->reattachTargetBus;
// Validate target bus type against allowed values
if (!array_key_exists($targetBus, $this->busTypes)) {
$this->notify('Invalid target bus type.', 'error');
return;
}
// Reattaching doesn't add new storage — unused drives are already counted in totalAllocatedStorage.
// Only block if total storage strictly exceeds the quota (which would indicate a data inconsistency).
if ($this->totalAllocatedStorage > $this->maxAllowedStorage && $this->maxAllowedStorage > 0) {
@@ -1209,6 +1257,13 @@ class Storage extends Component
*/
public function saveScsiController(): void
{
// Validate SCSI controller type against allowed values
$allowedControllers = array_column($this->scsiControllerOptions, 'value');
if (!in_array($this->scsiControllerType, $allowedControllers, true)) {
$this->notify('Invalid SCSI controller type.', 'error');
return;
}
if ($this->scsiControllerType === $this->originalScsiControllerType) {
$this->notify('No changes to save.', 'info');
return;