diff --git a/app/Livewire/Project/Shared/Storages/Show.php b/app/Livewire/Project/Shared/Storages/Show.php
deleted file mode 100644
index c70ebc57fd..0000000000
--- a/app/Livewire/Project/Shared/Storages/Show.php
+++ /dev/null
@@ -1,201 +0,0 @@
- 'name',
- 'mountPath' => 'mount',
- 'hostPath' => 'host',
- ];
-
- protected function rules(): array
- {
- return [
- 'name' => ValidationPatterns::volumeNameRules(),
- 'mountPath' => ['required', 'string', 'regex:'.ValidationPatterns::DIRECTORY_PATH_PATTERN],
- 'hostPath' => ['nullable', 'string', 'regex:'.ValidationPatterns::DIRECTORY_PATH_PATTERN],
- 'isPreviewSuffixEnabled' => 'required|boolean',
- ];
- }
-
- protected function messages(): array
- {
- return array_merge(
- ValidationPatterns::volumeNameMessages(),
- [
- 'mountPath.regex' => 'Mount path must start with / and only contain safe path characters.',
- 'hostPath.regex' => 'Host path must start with / and only contain safe path characters.',
- ]
- );
- }
-
- /**
- * Sync data between component properties and model
- *
- * @param bool $toModel If true, sync FROM properties TO model. If false, sync FROM model TO properties.
- */
- private function syncData(bool $toModel = false): void
- {
- if ($toModel) {
- // Sync TO model (before save)
- $this->storage->name = $this->name;
- $this->storage->mount_path = $this->mountPath;
- $this->storage->host_path = $this->hostPath;
- $this->storage->is_preview_suffix_enabled = $this->isPreviewSuffixEnabled;
- } else {
- // Sync FROM model (on load/refresh)
- $this->name = $this->storage->name;
- $this->mountPath = $this->storage->mount_path;
- $this->hostPath = $this->storage->host_path;
- $this->isPreviewSuffixEnabled = $this->storage->is_preview_suffix_enabled ?? true;
- }
- }
-
- public function mount(): void
- {
- $this->syncData(false);
- $this->isReadOnly = $this->storage->shouldBeReadOnlyInUI();
- // PR deployment volume suffixes only apply to git-based applications.
- $this->supportsPreviewSuffix = $this->resource instanceof Application
- && $this->resource->git_based()
- && filled($this->resource->git_repository)
- && ! $this->isService;
- // Parent All batches badge/url; isolated embeds still hydrate themselves.
- if (! $this->backupMetaHydrated) {
- $this->refreshBackupStatus();
- }
- }
-
- #[On('refreshVolumeBackups')]
- public function refreshBackupStatus(): void
- {
- $backup = $this->storage->scheduledBackups()->first();
-
- $this->hasEnabledBackup = $backup?->enabled ?? false;
- $this->backupUrl = null;
-
- if (! $this->hasEnabledBackup || ! $this->resource instanceof Application) {
- return;
- }
-
- $this->resource->loadMissing('environment.project');
-
- $parameters = [
- 'project_uuid' => $this->resource->project()->uuid,
- 'environment_uuid' => $this->resource->environment->uuid,
- 'application_uuid' => $this->resource->uuid,
- ];
- $hasOtherBackups = ScheduledVolumeBackup::query()
- ->forApplication($this->resource)
- ->where('id', '!=', $backup->id)
- ->exists();
-
- $this->backupUrl = $hasOtherBackups
- ? route('project.application.backup.index', [...$parameters, 'search' => $this->storage->name])
- : route('project.application.backup.show', [...$parameters, 'backup_uuid' => $backup->uuid]);
- }
-
- public function openBackupModal(): void
- {
- $this->authorize('update', $this->resource);
- $this->showBackupModal = true;
- }
-
- #[On('modalClosed')]
- public function onModalClosed(): void
- {
- // Drop the nested Create component from the DOM after close to free snapshot weight.
- if ($this->showBackupModal) {
- $this->showBackupModal = false;
- }
- }
-
- public function instantSave(): void
- {
- $this->authorize('update', $this->resource);
- $this->validate();
-
- $this->syncData(true);
- $this->storage->save();
- $this->dispatch('success', 'Storage updated successfully');
- }
-
- public function submit()
- {
- $this->authorize('update', $this->resource);
-
- $this->validate();
- $this->syncData(true);
- $this->storage->save();
- $this->dispatch('success', 'Storage updated successfully');
- }
-
- public function delete($password, $selectedActions = [])
- {
- $this->authorize('update', $this->resource);
-
- if (! verifyPasswordConfirmation($password, $this)) {
- return 'The provided password is incorrect.';
- }
-
- if ($this->storage->scheduledBackups()->exists()) {
- $this->dispatch('error', 'Delete this volume backup schedule and its archives before deleting the volume.');
-
- return false;
- }
-
- $this->storage->delete();
- $this->dispatch('storageCountsChanged')->to(StorageComponent::class);
- $this->dispatch('configurationChanged');
-
- return true;
- }
-}
diff --git a/resources/views/livewire/project/shared/storages/all.blade.php b/resources/views/livewire/project/shared/storages/all.blade.php
index dbe21fd7b8..cfbc58972b 100644
--- a/resources/views/livewire/project/shared/storages/all.blade.php
+++ b/resources/views/livewire/project/shared/storages/all.blade.php
@@ -183,7 +183,7 @@
@if ($supportsPreviewSuffix)
PR suffix
-
diff --git a/resources/views/livewire/project/shared/storages/show.blade.php b/resources/views/livewire/project/shared/storages/show.blade.php
deleted file mode 100644
index 3662568087..0000000000
--- a/resources/views/livewire/project/shared/storages/show.blade.php
+++ /dev/null
@@ -1,156 +0,0 @@
-@php
- $showActionsColumn = $resource instanceof \App\Models\Application;
- $gridClass = match (true) {
- $supportsPreviewSuffix => 'volumes-table-grid-with-pr',
- $showActionsColumn => 'volumes-table-grid',
- default => 'volumes-table-grid-readonly',
- };
- $canUpdate = auth()->user()?->can('update', $resource) ?? false;
- $inputsReadonly = $isReadOnly || ! $canUpdate;
- $displayHostPath = filled($hostPath) ? $hostPath : '—';
-@endphp
-
-@if ($inputsReadonly)
- {{-- Read-only: plain data-table row (service / compose / no permission) --}}
-
-
-
-
Volume Name
-
-
{{ $name }}
- @if ($hasEnabledBackup)
- @if ($backupUrl)
-
- Backup
-
- @else
-
- Backup
-
- @endif
- @endif
-
-
-
-
- Source Path
-
- {{ $displayHostPath }}
-
-
-
-
- Destination Path
- {{ $mountPath }}
-
-
- @if ($supportsPreviewSuffix)
-
- PR suffix
- {{ $isPreviewSuffixEnabled ? 'Add suffix' : 'Share volume' }}
-
- @endif
-
- @if ($showActionsColumn)
-
- @if ($canUpdate)
- @if ($showBackupModal)
-
-
-
- @else
-
- Backup
-
- @endif
- @else
- —
- @endif
-
- @endif
-
-
-@else
- {{-- Editable volume row --}}
-
-@endif
diff --git a/tests/Feature/FileStorageMountPathTest.php b/tests/Feature/FileStorageMountPathTest.php
index 0b9e450a29..cd301c2557 100644
--- a/tests/Feature/FileStorageMountPathTest.php
+++ b/tests/Feature/FileStorageMountPathTest.php
@@ -4,7 +4,6 @@ use App\Jobs\ServerStorageSaveJob;
use App\Livewire\Project\Service\FileStorage;
use App\Livewire\Project\Service\Storage;
use App\Livewire\Project\Shared\Storages\All;
-use App\Livewire\Project\Shared\Storages\Show;
use App\Models\Application;
use App\Models\Environment;
use App\Models\InstanceSettings;
@@ -247,8 +246,8 @@ test('deleting a volume mount refreshes the configuration warning', function ()
'resource_type' => $database->getMorphClass(),
]);
- Livewire::test(Show::class, ['storage' => $volume, 'resource' => $database])
- ->call('delete', 'password')
+ Livewire::test(All::class, ['resource' => $database])
+ ->call('delete', $volume->id, 'password')
->assertDispatched('configurationChanged');
expect($volume->fresh())->toBeNull();
diff --git a/tests/Feature/PersistentStoragePerformanceTest.php b/tests/Feature/PersistentStoragePerformanceTest.php
index caad5822a1..6d1df54607 100644
--- a/tests/Feature/PersistentStoragePerformanceTest.php
+++ b/tests/Feature/PersistentStoragePerformanceTest.php
@@ -91,7 +91,7 @@ function createPerfApplicationWithVolumes(int $volumeCount = 5): array
return [$application, $firstVolume, $team];
}
-it('renders volume rows without nesting Livewire Show components', function () {
+it('renders volume rows inline without nested Livewire row components', function () {
[$application] = createPerfApplicationWithVolumes(5);
$html = Livewire::test(All::class, ['resource' => $application])->html();
@@ -100,7 +100,6 @@ it('renders volume rows without nesting Livewire Show components', function () {
->toContain('data-table')
->toContain('openBackupModal')
->toContain('wire:submit="submit(')
- ->not->toContain('livewire:project.shared.storages.show')
->not->toContain('shared-configure-volume-backup-');
});
diff --git a/tests/Feature/PersistentStorageVolumesLayoutTest.php b/tests/Feature/PersistentStorageVolumesLayoutTest.php
index d7ae4ba8c0..6546a00e31 100644
--- a/tests/Feature/PersistentStorageVolumesLayoutTest.php
+++ b/tests/Feature/PersistentStorageVolumesLayoutTest.php
@@ -141,7 +141,6 @@ function createApplicationWithVolume(array $applicationAttributes = [], array $v
it('renders volumes as a data table with shared column headers', function () {
$allView = file_get_contents(resource_path('views/livewire/project/shared/storages/all.blade.php'));
- $showView = file_get_contents(resource_path('views/livewire/project/shared/storages/show.blade.php'));
$storageView = file_get_contents(resource_path('views/livewire/project/service/storage.blade.php'));
expect($allView)
@@ -159,17 +158,10 @@ it('renders volumes as a data table with shared column headers', function () {
->toContain('data-table-row')
->toContain('volumes-mobile-label')
->not->toContain('table-badge table-badge-success')
- ->not->toContain('livewire:project.shared.storages.show')
->not->toContain('x-status-badge')
->not->toContain('font-mono')
->not->toContain('Service volume mounts are read-only here.');
- // Show remains available for isolated embeds/tests but is no longer nested from All.
- expect($showView)
- ->toContain('data-table-row')
- ->toContain('volumes-table-grid')
- ->not->toContain('font-mono');
-
// Service stack page: one settings-section card per compose service/resource.
expect($storageView)
->toContain('Str::headline($resource->name)')
@@ -434,16 +426,13 @@ it('hides PR deployment suffix for databases', function () {
});
it('uses a compact table badge for enabled backups instead of status-badge', function () {
- $showView = file_get_contents(resource_path('views/livewire/project/shared/storages/show.blade.php'));
+ $allView = file_get_contents(resource_path('views/livewire/project/shared/storages/all.blade.php'));
- expect($showView)
- ->toContain('table-badge-success')
+ expect($allView)
+ ->toContain("'table-badge-success' => \$hasS3Backup")
->toContain('Volume backup is enabled')
->not->toContain('x-status-badge')
->not->toContain('status="Backup enabled"');
-
- // Badge label is the short "Backup" text, not the old pill-with-label that broke the input row.
- expect(preg_match('/table-badge-success[^>]*>\s*Backup\s*', $showView))->toBeGreaterThan(0);
});
it('gates file storage PR suffix markup behind git_based applications', function () {
diff --git a/tests/Feature/VolumeBackupTest.php b/tests/Feature/VolumeBackupTest.php
index b24b45dcad..519b323f6b 100644
--- a/tests/Feature/VolumeBackupTest.php
+++ b/tests/Feature/VolumeBackupTest.php
@@ -8,7 +8,7 @@ use App\Livewire\Project\Application\Backup\Create as CreateScheduledVolumeBacku
use App\Livewire\Project\Service\FileStorage;
use App\Livewire\Project\Service\VolumeBackup\Create as CreateServiceVolumeBackup;
use App\Livewire\Project\Service\VolumeBackup\Index as ServiceVolumeBackupIndex;
-use App\Livewire\Project\Shared\Storages\Show;
+use App\Livewire\Project\Shared\Storages\All;
use App\Livewire\Project\Shared\Storages\VolumeBackups;
use App\Models\Application;
use App\Models\Environment;
@@ -483,11 +483,8 @@ it('shows the configure backup modal trigger inside the volume card instead of i
signInForVolumeBackups($this, $team);
[$application, $volume] = createVolumeBackupApplication($team);
- $component = Livewire::test(Show::class, [
- 'storage' => $volume,
- 'resource' => $application,
- ])
- ->set('isReadOnly', true)
+ $component = Livewire::test(All::class, ['resource' => $application])
+ ->set("forms.{$volume->id}.isReadOnly", true)
->assertSee('Backup')
->assertDontSee('Backups made while the application is writing');
@@ -497,6 +494,7 @@ it('shows the configure backup modal trigger inside the volume card instead of i
expect($html)
->toContain('Configure Volume Backup')
->toContain('data-table-row')
+ ->not->toContain('wire:submit="submit('.$volume->id.')"')
->toContain('Backup');
});
@@ -512,10 +510,10 @@ it('only shows the backup enabled badge for an enabled volume backup', function
'enabled' => false,
]);
- $component = Livewire::test(Show::class, [
- 'storage' => $volume,
- 'resource' => $application,
- ])->assertDontSee('table-badge-success', false);
+ $component = Livewire::test(All::class, ['resource' => $application])
+ ->assertDontSee('Volume backup is enabled');
+
+ expect($component->get("volumeBackupMeta.{$volume->id}.enabled"))->toBeFalse();
$backup->update(['enabled' => true]);
@@ -528,17 +526,10 @@ it('only shows the backup enabled badge for an enabled volume backup', function
$component
->dispatch('refreshVolumeBackups')
- ->assertSee('table-badge-success', false)
->assertSee('Volume backup is enabled')
->assertSee('href="'.$backupUrl.'"', false);
- Livewire::test(Show::class, [
- 'storage' => $volume,
- 'resource' => $application,
- 'isFirst' => false,
- ])
- ->assertSee('table-badge-success', false)
- ->assertSee('Volume backup is enabled');
+ expect($component->get("volumeBackupMeta.{$volume->id}.url"))->toBe($backupUrl);
});
it('links the backup enabled badge to a filtered backup list when the application has multiple schedules', function () {
@@ -564,11 +555,7 @@ it('links the backup enabled badge to a filtered backup list when the applicatio
'search' => $volume->name,
]);
- Livewire::test(Show::class, [
- 'storage' => $volume,
- 'resource' => $application,
- ])
- ->assertSee('table-badge-success', false)
+ Livewire::test(All::class, ['resource' => $application])
->assertSee('Volume backup is enabled')
->assertSee('href="'.$backupUrl.'"', false);
});