From df3a37d6cbb16b2f28ddcb28c1fff7a30a053310 Mon Sep 17 00:00:00 2001 From: = Date: Wed, 13 May 2026 13:13:29 +0000 Subject: [PATCH] wip: refactor service connection components and add ConnectionProtocol and ConnectionProvider services - Renamed `ConnectedServicesService` to `ConnectedAppService` and adjusted related factories, DTOs, and forms. - Introduced `ConnectionProtocolService` and `ConnectionProviderService` for managing protocols and providers. - Updated Livewire forms to improve validation and allow real-time provider searches. - Added a `ConnectionStatus` field and related dropdown to service connection forms. - Enhanced form handling with new services, search functionality, and validation rules. - Refactored factory and DTO structure for better consistency and modularity. - Added service layer documentation and streamlined component data mappings. --- .../ConnectService/ConnectServiceData.php | 19 --------- app/Data/ConnectedApp/ConnectAppRequest.php | 23 +++++++++++ app/Factories/ConnectedAppFactory.php | 13 +++--- app/Livewire/Forms/README.md | 16 ++++++++ app/Livewire/Forms/StoreConnectedAppFrom.php | 20 +++++---- ...cesService.php => ConnectedAppService.php} | 6 +-- app/Services/ConnectionProtocolService.php | 30 ++++++++++++++ app/Services/ConnectionProviderService.php | 22 ++++++++++ art/STRUCTURE.md | 6 +++ .../pages/connected-apps/⚡create.blade.php | 41 +++++++++++++++++-- storage/debugbar/.gitignore | 2 + 11 files changed, 159 insertions(+), 39 deletions(-) delete mode 100644 app/Data/ConnectService/ConnectServiceData.php create mode 100644 app/Data/ConnectedApp/ConnectAppRequest.php create mode 100644 app/Livewire/Forms/README.md rename app/Services/{ConnectedServicesService.php => ConnectedAppService.php} (71%) create mode 100644 app/Services/ConnectionProtocolService.php create mode 100644 app/Services/ConnectionProviderService.php create mode 100644 art/STRUCTURE.md create mode 100644 storage/debugbar/.gitignore diff --git a/app/Data/ConnectService/ConnectServiceData.php b/app/Data/ConnectService/ConnectServiceData.php deleted file mode 100644 index fcc04d3..0000000 --- a/app/Data/ConnectService/ConnectServiceData.php +++ /dev/null @@ -1,19 +0,0 @@ - $data->name, - 'service_provider_id' => $data->serviceProviderId, - 'service_protocol_id' => $data->serviceProtocolId, + 'connection_provider_id' => $data->connectionProviderId, + 'connection_protocol_id' => $data->connectionProtocolId, 'logo_url' => $data->logoUrl, 'slug' => $data->slug, - 'service_status_id' => $data->statusId, + 'connection_status_id' => $data->statusId, ]; // Check if the staus is filled, if not select disconnected by default if (null === $data->statusId) { - $status = ConnectionStatusEnum::query() + $status = ConnectionStatus::query() ->where('name', '=', ConnectionStatusEnum::Disconnected->value) ->pluck('id'); $result['service_status_id'] = $status[0]; diff --git a/app/Livewire/Forms/README.md b/app/Livewire/Forms/README.md new file mode 100644 index 0000000..7b4bfdf --- /dev/null +++ b/app/Livewire/Forms/README.md @@ -0,0 +1,16 @@ +All the forms used in the application are stored here. + +Each form should validate the data before sending it to the server. +This is done by using the `validate` method. + +Validations that require the db, should not be live (realtime), +they should be done on the only once, preferably after the form is submitted. + +Form can be used to both create and update data. Name should start with: + +- `Store` for both cases - preferred +- `Create` for creating a new record +- `Update` for updating an existing record + +When handle both cases, use separate `save` and `update` methods. +Livewire form docs: https://livewire.laravel.com/docs/4.x/forms diff --git a/app/Livewire/Forms/StoreConnectedAppFrom.php b/app/Livewire/Forms/StoreConnectedAppFrom.php index fe9919b..9c39853 100644 --- a/app/Livewire/Forms/StoreConnectedAppFrom.php +++ b/app/Livewire/Forms/StoreConnectedAppFrom.php @@ -4,8 +4,8 @@ namespace App\Livewire\Forms; -use App\Data\ConnectService\ConnectServiceData; -use App\Services\ConnectedServicesService; +use App\Data\ConnectedApp\ConnectAppRequest; +use App\Services\ConnectedAppService; use Livewire\Attributes\Validate; use Livewire\Form; @@ -14,12 +14,15 @@ class StoreConnectedAppFrom extends Form #[Validate('required|string|max:255|min:3')] public string $name = ''; - #[Validate('required|numeric|min:1')] + #[Validate('required|numeric|min:1|exists:connection_providers,id')] public int $providerId = 0; - #[Validate('required|numeric|min:1')] + #[Validate('required|numeric|min:1|exists:connection_protocols,id')] public int $protocolId = 0; + #[Validate('required|numeric|min:1|exists:connection_statuses,id')] + public int $statusId = 0; + #[Validate('nullable|string|max:255|min:3')] public ?string $logoUrl = null; @@ -27,15 +30,16 @@ public function save(): void { $this->validate(); - $serviceData = new ConnectServiceData( + $serviceData = new ConnectAppRequest( name: $this->name, - serviceProviderId: $this->providerId, - serviceProtocolId: $this->protocolId, + connectionProviderId: $this->providerId, + connectionProtocolId: $this->protocolId, logoUrl: $this->logoUrl, slug: str($this->name)->slug()->toString(), + statusId: $this->statusId, ); - app(ConnectedServicesService::class)->create($serviceData); + app(ConnectedAppService::class)->create($serviceData); $this->reset(); } } diff --git a/app/Services/ConnectedServicesService.php b/app/Services/ConnectedAppService.php similarity index 71% rename from app/Services/ConnectedServicesService.php rename to app/Services/ConnectedAppService.php index 720cf22..8709483 100644 --- a/app/Services/ConnectedServicesService.php +++ b/app/Services/ConnectedAppService.php @@ -4,14 +4,14 @@ namespace App\Services; -use App\Data\ConnectService\ConnectServiceData; +use App\Data\ConnectedApp\ConnectAppRequest; use App\Factories\ConnectedAppFactory; use App\Models\ConnectedApp; use Illuminate\Support\Facades\DB; -final class ConnectedServicesService +final class ConnectedAppService { - public function create(ConnectServiceData $data): void + public function create(ConnectAppRequest $data): void { $data = app(ConnectedAppFactory::class)->createDataFromDto($data); DB::transaction( diff --git a/app/Services/ConnectionProtocolService.php b/app/Services/ConnectionProtocolService.php new file mode 100644 index 0000000..17df7d9 --- /dev/null +++ b/app/Services/ConnectionProtocolService.php @@ -0,0 +1,30 @@ + + */ + private Builder $builder; + + public function __construct( + ) { + $this->builder = ConnectionProtocol::query(); + } + + /** + * @return Collection + */ + public function getAll(): Collection + { + return $this->builder->get(); + } +} diff --git a/app/Services/ConnectionProviderService.php b/app/Services/ConnectionProviderService.php new file mode 100644 index 0000000..3e7412a --- /dev/null +++ b/app/Services/ConnectionProviderService.php @@ -0,0 +1,22 @@ + + */ + public function search(string $value): Collection + { + return ConnectionProvider::query() + ->whereLike('slug', "%{$value}%") + ->orWhereLike('name', "%{$value}%") + ->get(); + } +} diff --git a/art/STRUCTURE.md b/art/STRUCTURE.md new file mode 100644 index 0000000..c0ea8e1 --- /dev/null +++ b/art/STRUCTURE.md @@ -0,0 +1,6 @@ +## Service Layer + +Service layer should return DTO objects to application layer (Livewire Components, Forms, Views). +As Livewire sends whole properties to the component, any data returned from Repository should not be returned to the +components. +It's a critical security concern not to expose any sensitive data to the components. diff --git a/resources/views/pages/connected-apps/⚡create.blade.php b/resources/views/pages/connected-apps/⚡create.blade.php index 19f14b0..b00ae8f 100644 --- a/resources/views/pages/connected-apps/⚡create.blade.php +++ b/resources/views/pages/connected-apps/⚡create.blade.php @@ -3,6 +3,10 @@ use App\Livewire\Forms\StoreConnectedAppFrom; use App\Models\ConnectionProtocol; use App\Models\ConnectionProvider; +use App\Models\ConnectionStatus; +use App\Services\ConnectionProtocolService; +use App\Services\ConnectionProviderService; +use Illuminate\Database\Eloquent\Collection; use Livewire\Attributes\Computed; use Livewire\Component; use Livewire\Attributes\Title; @@ -18,15 +22,36 @@ public function providers() return ConnectionProvider::query()->get(); } + #[Computed] - public function protocols() + public function protocols(): Collection { - return ConnectionProtocol::query()->get()->map(function (ConnectionProtocol $protocol) { - $protocol->name = ucfirst($protocol->name); + $protocolService = app(ConnectionProtocolService::class); + + return $protocolService->getAll()->map(function (ConnectionProtocol $protocol) { + $protocol->name = strtoupper($protocol->name); return $protocol; }); } + /** + * @returns Collection + */ + #[Computed] + public function connectionStatuses(): Collection + { + return ConnectionStatus::query()->get()->map(function (ConnectionStatus $status) { + $status->name = ucfirst($status->name); + return $status; + }); + } + + public function searchProvider(string $name) + { + $providerService = app(ConnectionProviderService::class); + $this->providers = $providerService->search($name); + } + public function save() { $this->form->save(); @@ -54,6 +79,16 @@ public function save() :single="true" :options="$this->providers" searchable + search-function="searchProvider" + debounce="300" + /> +
Cancel diff --git a/storage/debugbar/.gitignore b/storage/debugbar/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/debugbar/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore