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) - - - +
+
+ + + Add + + + + + + +
+ + {{-- Volume Modal --}} + + + {{-- File Modal --}} + + + {{-- Directory Modal --}} + +
@endcan @endif @@ -51,19 +272,19 @@ diff --git a/resources/views/livewire/project/shared/storages/add.blade.php b/resources/views/livewire/project/shared/storages/add.blade.php deleted file mode 100644 index 20155e661..000000000 --- a/resources/views/livewire/project/shared/storages/add.blade.php +++ /dev/null @@ -1,59 +0,0 @@ -
-
-
-

Volume Mount

-
Docker Volumes mounted to the container.
-
- @if ($isSwarm) -
Swarm Mode detected: You need to set a shared volume (EFS/NFS/etc) on all the worker nodes if you - would - like to use a persistent volumes.
- @endif -
- - @if ($isSwarm) - - @else - - @endif - - - Add - -
- -
-
-
-

File Mount

-
Actual file mounted from the host system to the container.
-
-
- - - - Add - -
-
-
-
-

Directory Mount

-
Directory mounted from the host system to the container.
-
-
- - - - Add - -
-
-