From ce5555ca9f7c854286bdf2b3a134cd8e2ce5fc83 Mon Sep 17 00:00:00 2001
From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com>
Date: Wed, 1 Oct 2025 18:46:21 +0200
Subject: [PATCH] feat(storage): consolidate storage management into a single
component with enhanced UI
- Merged the storage management functionalities into the Storage component, replacing the previous Add component.
- Introduced new methods for submitting persistent volumes, file mounts, and directory mounts, improving code organization and maintainability.
- Enhanced the UI with modals for adding volumes, files, and directories, providing a more intuitive user experience.
- Updated validation rules and error handling for improved robustness during storage submissions.
- Removed deprecated Add component and associated views to streamline the codebase.
---
app/Livewire/Project/Service/Storage.php | 138 ++++++++++-
app/Livewire/Project/Shared/Storages/Add.php | 174 -------------
.../project/service/storage.blade.php | 233 +++++++++++++++++-
.../project/shared/storages/add.blade.php | 59 -----
4 files changed, 358 insertions(+), 246 deletions(-)
delete mode 100644 app/Livewire/Project/Shared/Storages/Add.php
delete mode 100644 resources/views/livewire/project/shared/storages/add.blade.php
diff --git a/app/Livewire/Project/Service/Storage.php b/app/Livewire/Project/Service/Storage.php
index fb7da1184..db171db24 100644
--- a/app/Livewire/Project/Service/Storage.php
+++ b/app/Livewire/Project/Service/Storage.php
@@ -14,6 +14,22 @@ class Storage extends Component
public $fileStorage;
+ public $isSwarm = false;
+
+ public string $name = '';
+
+ public string $mount_path = '';
+
+ public ?string $host_path = null;
+
+ public string $file_storage_path = '';
+
+ public ?string $file_storage_content = null;
+
+ public string $file_storage_directory_source = '';
+
+ public string $file_storage_directory_destination = '';
+
public function getListeners()
{
$teamId = auth()->user()->currentTeam()->id;
@@ -27,6 +43,18 @@ public function getListeners()
public function mount()
{
+ if (str($this->resource->getMorphClass())->contains('Standalone')) {
+ $this->file_storage_directory_source = database_configuration_dir()."/{$this->resource->uuid}";
+ } else {
+ $this->file_storage_directory_source = application_configuration_dir()."/{$this->resource->uuid}";
+ }
+
+ if ($this->resource->getMorphClass() === \App\Models\Application::class) {
+ if ($this->resource->destination->server->isSwarm()) {
+ $this->isSwarm = true;
+ }
+ }
+
$this->refreshStorages();
}
@@ -67,27 +95,123 @@ public function getDirectoryCountProperty()
return $this->directories->count();
}
- public function addNewVolume($data)
+ public function submitPersistentVolume()
{
try {
$this->authorize('update', $this->resource);
+ $this->validate([
+ 'name' => 'required|string',
+ 'mount_path' => 'required|string',
+ 'host_path' => $this->isSwarm ? 'required|string' : 'string|nullable',
+ ]);
+
+ $name = $this->resource->uuid.'-'.$this->name;
+
LocalPersistentVolume::create([
- 'name' => $data['name'],
- 'mount_path' => $data['mount_path'],
- 'host_path' => $data['host_path'],
+ 'name' => $name,
+ 'mount_path' => $this->mount_path,
+ 'host_path' => $this->host_path,
'resource_id' => $this->resource->id,
'resource_type' => $this->resource->getMorphClass(),
]);
$this->resource->refresh();
- $this->dispatch('success', 'Storage added successfully');
- $this->dispatch('clearAddStorage');
- $this->dispatch('refreshStorages');
+ $this->dispatch('success', 'Volume added successfully');
+ $this->dispatch('closeStorageModal', 'volume');
+ $this->clearForm();
+ $this->refreshStorages();
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
+ public function submitFileStorage()
+ {
+ try {
+ $this->authorize('update', $this->resource);
+
+ $this->validate([
+ 'file_storage_path' => 'required|string',
+ 'file_storage_content' => 'nullable|string',
+ ]);
+
+ $this->file_storage_path = trim($this->file_storage_path);
+ $this->file_storage_path = str($this->file_storage_path)->start('/')->value();
+
+ if ($this->resource->getMorphClass() === \App\Models\Application::class) {
+ $fs_path = application_configuration_dir().'/'.$this->resource->uuid.$this->file_storage_path;
+ } elseif (str($this->resource->getMorphClass())->contains('Standalone')) {
+ $fs_path = database_configuration_dir().'/'.$this->resource->uuid.$this->file_storage_path;
+ } else {
+ throw new \Exception('No valid resource type for file mount storage type!');
+ }
+
+ \App\Models\LocalFileVolume::create([
+ 'fs_path' => $fs_path,
+ 'mount_path' => $this->file_storage_path,
+ 'content' => $this->file_storage_content,
+ 'is_directory' => false,
+ 'resource_id' => $this->resource->id,
+ 'resource_type' => get_class($this->resource),
+ ]);
+
+ $this->dispatch('success', 'File mount added successfully');
+ $this->dispatch('closeStorageModal', 'file');
+ $this->clearForm();
+ $this->refreshStorages();
+ } catch (\Throwable $e) {
+ return handleError($e, $this);
+ }
+ }
+
+ public function submitFileStorageDirectory()
+ {
+ try {
+ $this->authorize('update', $this->resource);
+
+ $this->validate([
+ 'file_storage_directory_source' => 'required|string',
+ 'file_storage_directory_destination' => 'required|string',
+ ]);
+
+ $this->file_storage_directory_source = trim($this->file_storage_directory_source);
+ $this->file_storage_directory_source = str($this->file_storage_directory_source)->start('/')->value();
+ $this->file_storage_directory_destination = trim($this->file_storage_directory_destination);
+ $this->file_storage_directory_destination = str($this->file_storage_directory_destination)->start('/')->value();
+
+ \App\Models\LocalFileVolume::create([
+ 'fs_path' => $this->file_storage_directory_source,
+ 'mount_path' => $this->file_storage_directory_destination,
+ 'is_directory' => true,
+ 'resource_id' => $this->resource->id,
+ 'resource_type' => get_class($this->resource),
+ ]);
+
+ $this->dispatch('success', 'Directory mount added successfully');
+ $this->dispatch('closeStorageModal', 'directory');
+ $this->clearForm();
+ $this->refreshStorages();
+ } catch (\Throwable $e) {
+ return handleError($e, $this);
+ }
+ }
+
+ public function clearForm()
+ {
+ $this->name = '';
+ $this->mount_path = '';
+ $this->host_path = null;
+ $this->file_storage_path = '';
+ $this->file_storage_content = null;
+ $this->file_storage_directory_destination = '';
+
+ if (str($this->resource->getMorphClass())->contains('Standalone')) {
+ $this->file_storage_directory_source = database_configuration_dir()."/{$this->resource->uuid}";
+ } else {
+ $this->file_storage_directory_source = application_configuration_dir()."/{$this->resource->uuid}";
+ }
+ }
+
public function render()
{
return view('livewire.project.service.storage');
diff --git a/app/Livewire/Project/Shared/Storages/Add.php b/app/Livewire/Project/Shared/Storages/Add.php
deleted file mode 100644
index 006d41c14..000000000
--- a/app/Livewire/Project/Shared/Storages/Add.php
+++ /dev/null
@@ -1,174 +0,0 @@
- 'required|string',
- 'mount_path' => 'required|string',
- 'host_path' => 'string|nullable',
- 'file_storage_path' => 'string',
- 'file_storage_content' => 'nullable|string',
- 'file_storage_directory_source' => 'string',
- 'file_storage_directory_destination' => 'string',
- ];
-
- protected $listeners = ['clearAddStorage' => 'clear'];
-
- protected $validationAttributes = [
- 'name' => 'name',
- 'mount_path' => 'mount',
- 'host_path' => 'host',
- 'file_storage_path' => 'file storage path',
- 'file_storage_content' => 'file storage content',
- 'file_storage_directory_source' => 'file storage directory source',
- 'file_storage_directory_destination' => 'file storage directory destination',
- ];
-
- public function mount()
- {
- if (str($this->resource->getMorphClass())->contains('Standalone')) {
- $this->file_storage_directory_source = database_configuration_dir()."/{$this->resource->uuid}";
- } else {
- $this->file_storage_directory_source = application_configuration_dir()."/{$this->resource->uuid}";
- }
- $this->uuid = $this->resource->uuid;
- $this->parameters = get_route_parameters();
- if (data_get($this->parameters, 'application_uuid')) {
- $applicationUuid = $this->parameters['application_uuid'];
- $application = Application::where('uuid', $applicationUuid)->first();
- if (! $application) {
- abort(404);
- }
- if ($application->destination->server->isSwarm()) {
- $this->isSwarm = true;
- $this->rules['host_path'] = 'required|string';
- }
- }
- }
-
- public function submitFileStorage()
- {
- try {
- $this->authorize('update', $this->resource);
-
- $this->validate([
- 'file_storage_path' => 'string',
- 'file_storage_content' => 'nullable|string',
- ]);
-
- $this->file_storage_path = trim($this->file_storage_path);
- $this->file_storage_path = str($this->file_storage_path)->start('/')->value();
-
- if ($this->resource->getMorphClass() === \App\Models\Application::class) {
- $fs_path = application_configuration_dir().'/'.$this->resource->uuid.$this->file_storage_path;
- } elseif (str($this->resource->getMorphClass())->contains('Standalone')) {
- $fs_path = database_configuration_dir().'/'.$this->resource->uuid.$this->file_storage_path;
- } else {
- throw new \Exception('No valid resource type for file mount storage type!');
- }
-
- LocalFileVolume::create(
- [
- 'fs_path' => $fs_path,
- 'mount_path' => $this->file_storage_path,
- 'content' => $this->file_storage_content,
- 'is_directory' => false,
- 'resource_id' => $this->resource->id,
- 'resource_type' => get_class($this->resource),
- ],
- );
- $this->dispatch('refreshStorages');
- } catch (\Throwable $e) {
- return handleError($e, $this);
- }
- }
-
- public function submitFileStorageDirectory()
- {
- try {
- $this->authorize('update', $this->resource);
-
- $this->validate([
- 'file_storage_directory_source' => 'string',
- 'file_storage_directory_destination' => 'string',
- ]);
-
- $this->file_storage_directory_source = trim($this->file_storage_directory_source);
- $this->file_storage_directory_source = str($this->file_storage_directory_source)->start('/')->value();
- $this->file_storage_directory_destination = trim($this->file_storage_directory_destination);
- $this->file_storage_directory_destination = str($this->file_storage_directory_destination)->start('/')->value();
-
- LocalFileVolume::create(
- [
- 'fs_path' => $this->file_storage_directory_source,
- 'mount_path' => $this->file_storage_directory_destination,
- 'is_directory' => true,
- 'resource_id' => $this->resource->id,
- 'resource_type' => get_class($this->resource),
- ],
- );
- $this->dispatch('refreshStorages');
- } catch (\Throwable $e) {
- return handleError($e, $this);
- }
- }
-
- public function submitPersistentVolume()
- {
- try {
- $this->authorize('update', $this->resource);
-
- $this->validate([
- 'name' => 'required|string',
- 'mount_path' => 'required|string',
- 'host_path' => 'string|nullable',
- ]);
- $name = $this->uuid.'-'.$this->name;
- $this->dispatch('addNewVolume', [
- 'name' => $name,
- 'mount_path' => $this->mount_path,
- 'host_path' => $this->host_path,
- ]);
- } catch (\Throwable $e) {
- return handleError($e, $this);
- }
- }
-
- public function clear()
- {
- $this->name = '';
- $this->mount_path = '';
- $this->host_path = null;
- }
-}
diff --git a/resources/views/livewire/project/service/storage.blade.php b/resources/views/livewire/project/service/storage.blade.php
index 56a52a566..47ee99114 100644
--- a/resources/views/livewire/project/service/storage.blade.php
+++ b/resources/views/livewire/project/service/storage.blade.php
@@ -18,9 +18,230 @@
name, example: -pr-1" />
@if ($resource?->build_pack !== 'dockercompose')
@can('update', $resource)
-