Refactor deployment index view for improved layout and functionality

- Rearranged the table header to display 'Application' and 'Environment' in a more logical order.
- Made the 'Application' and 'Environment' sections clickable, linking to their respective configuration and resource pages.
- Removed unnecessary status time display and streamlined the deployment information presentation.
- Enhanced the overall structure for better readability and user experience.
This commit is contained in:
Ilias Ism 2025-12-12 09:19:06 +01:00
parent 0621a1ad92
commit 09f8992af1
2 changed files with 102 additions and 50 deletions

View file

@ -3,6 +3,7 @@
namespace App\Livewire\Deployment;
use App\Enums\ApplicationDeploymentStatus;
use App\Models\Application;
use App\Models\ApplicationDeploymentQueue;
use App\Models\GithubApp;
use App\Models\GitlabApp;
@ -22,6 +23,8 @@ class Index extends Component
public ?int $selectedServerId = null;
public ?string $selectedApplicationId = null;
public ?int $selectedSourceId = null;
public ?string $selectedSourceType = null;
@ -33,6 +36,7 @@ class Index extends Component
protected $queryString = [
'selectedProjectId' => ['except' => ''],
'selectedServerId' => ['except' => ''],
'selectedApplicationId' => ['except' => ''],
'selectedSourceId' => ['except' => ''],
'selectedSourceType' => ['except' => ''],
'selectedStatus' => ['except' => ''],
@ -70,6 +74,11 @@ class Index extends Component
$query->where('application_deployment_queues.server_id', $this->selectedServerId);
}
// Filter by application
if ($this->selectedApplicationId) {
$query->where('applications.uuid', $this->selectedApplicationId);
}
// Filter by source
if ($this->selectedSourceId && $this->selectedSourceType) {
$query->where('applications.source_id', $this->selectedSourceId)
@ -99,6 +108,11 @@ class Index extends Component
$this->resetPage();
}
public function updatedSelectedApplicationId()
{
$this->resetPage();
}
public function updatedSelectedSourceId()
{
$this->resetPage();
@ -113,6 +127,7 @@ class Index extends Component
{
$this->selectedProjectId = null;
$this->selectedServerId = null;
$this->selectedApplicationId = null;
$this->selectedSourceId = null;
$this->selectedSourceType = null;
$this->selectedStatus = null;
@ -150,6 +165,27 @@ class Index extends Component
->toArray();
}
// Get applications that have deployments (only show applications with actual deployments)
// Uses same join pattern as loadDeployments() to avoid type mismatch
$applicationUuids = ApplicationDeploymentQueue::query()
->join('applications', function ($join) {
$join->on(DB::raw('CAST(application_deployment_queues.application_id AS INTEGER)'), '=', 'applications.id');
})
->join('environments', 'applications.environment_id', '=', 'environments.id')
->join('projects', 'environments.project_id', '=', 'projects.id')
->where('projects.team_id', $teamId)
->whereNull('applications.deleted_at')
->distinct('applications.uuid')
->pluck('applications.uuid')
->toArray();
$applications = [];
if (! empty($applicationUuids)) {
$applications = Application::whereIn('uuid', $applicationUuids)
->pluck('name', 'uuid')
->toArray();
}
// Get sources (GitHub/GitLab apps) from applications with deployments
// Applications use polymorphic relationships for sources, so we need to handle
// both GithubApp and GitlabApp types
@ -224,6 +260,7 @@ class Index extends Component
return [
'projects' => $projects,
'servers' => $servers,
'applications' => $applications,
'sources' => $sources,
'statuses' => $statuses,
];
@ -239,6 +276,11 @@ class Index extends Component
return count($this->getFilterOptionsProperty()['servers']) > 1;
}
public function getShouldShowApplicationFilterProperty(): bool
{
return count($this->getFilterOptionsProperty()['applications']) > 1;
}
public function getShouldShowSourceFilterProperty(): bool
{
return count($this->getFilterOptionsProperty()['sources']) > 1;
@ -327,6 +369,7 @@ class Index extends Component
'isPolling' => $this->isPolling,
'shouldShowProjectFilter' => $this->shouldShowProjectFilter,
'shouldShowServerFilter' => $this->shouldShowServerFilter,
'shouldShowApplicationFilter' => $this->shouldShowApplicationFilter,
'shouldShowSourceFilter' => $this->shouldShowSourceFilter,
]);
}

View file

@ -56,6 +56,26 @@
</x-dropdown>
@endif
@if ($shouldShowApplicationFilter)
<x-dropdown>
<x-slot:title>
{{ $selectedApplicationId ? ($filterOptions['applications'][$selectedApplicationId] ?? 'All Applications') : 'All Applications' }}
</x-slot:title>
<div class="flex flex-col">
<button wire:click="$set('selectedApplicationId', null)"
class="dropdown-item {{ !$selectedApplicationId ? 'bg-neutral-100 dark:bg-coolgray-100' : '' }}">
All Applications
</button>
@foreach ($filterOptions['applications'] as $uuid => $name)
<button wire:click="$set('selectedApplicationId', '{{ $uuid }}')"
class="dropdown-item {{ $selectedApplicationId === $uuid ? 'bg-neutral-100 dark:bg-coolgray-100' : '' }}">
{{ $name }}
</button>
@endforeach
</div>
</x-dropdown>
@endif
@if ($shouldShowSourceFilter)
<x-dropdown>
<x-slot:title>
@ -94,7 +114,7 @@
</div>
</x-dropdown>
@if ($selectedProjectId || $selectedServerId || $selectedSourceId || $selectedStatus)
@if ($selectedProjectId || $selectedServerId || $selectedApplicationId || $selectedSourceId || $selectedStatus)
<button wire:click="clearFilters"
class="px-3 py-1.5 text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white">
Clear filters
@ -107,11 +127,10 @@
{{-- Table Header --}}
<div class="flex items-center gap-4 px-4 py-2 border-b border-neutral-300 dark:border-coolgray-200 bg-neutral-50 dark:bg-coolgray-200 text-xs font-medium text-gray-600 dark:text-gray-400 uppercase tracking-wider">
<div class="w-20 flex-shrink-0">ID</div>
<div class="w-32 flex-shrink-0">Environment</div>
<div class="w-40 flex-shrink-0">Status</div>
<div class="flex-1 min-w-0">Application</div>
<div class="min-w-0 flex-1">Commit</div>
<div class="w-48 flex-shrink-0 text-right">Created</div>
<div class="flex-1 min-w-0">Application</div>
<div class="w-32 flex-shrink-0">Environment</div>
</div>
@forelse ($deployments as $deployment)
@ -124,8 +143,6 @@
// Format deployment ID for display (first 9 characters)
$shortId = substr($deployment->deployment_uuid, 0, 9);
$status = $deployment->status;
$statusUpdatedAt = $deployment->updated_at;
$statusTimeAgo = $statusUpdatedAt->diffForHumans(['short' => true]);
// Determine if deployment is actively running (needs polling/logs)
$isActive = in_array($status, ['in_progress', 'queued']);
@ -173,26 +190,6 @@
@endif
</div>
{{-- Environment Badge -- Clickable to environment page --}}
<div class="flex items-center gap-2 w-32 flex-shrink-0 whitespace-nowrap">
@if ($environment && $project)
<a href="{{ route('project.resource.index', [
'project_uuid' => $project->uuid,
'environment_uuid' => $environment->uuid
]) }}"
class="px-2 py-0.5 text-xs font-medium rounded bg-neutral-100 dark:bg-coolgray-100 text-gray-700 dark:text-gray-300 whitespace-nowrap hover:bg-neutral-200 dark:hover:bg-coolgray-200 transition-colors">
{{ ucfirst($environment->name) }}
</a>
@if ($isCurrent)
<span class="w-2 h-2 rounded-full bg-blue-500 flex-shrink-0" title="Current deployment"></span>
@endif
@elseif ($environment)
<span class="px-2 py-0.5 text-xs font-medium rounded bg-neutral-100 dark:bg-coolgray-100 text-gray-700 dark:text-gray-300 whitespace-nowrap">
{{ ucfirst($environment->name) }}
</span>
@endif
</div>
{{-- Status -- Not clickable --}}
<div class="flex items-center gap-2 w-40 flex-shrink-0 whitespace-nowrap">
@if ($isActive)
@ -203,27 +200,6 @@
<span class="text-sm font-medium {{ $statusConfig['textColor'] }} whitespace-nowrap">
{{ $statusConfig['text'] }}
</span>
<span class="text-xs text-gray-500 dark:text-gray-400 whitespace-nowrap">
{{ $statusTimeAgo }}
</span>
</div>
{{-- Application Info -- Clickable to application configuration page --}}
<div class="flex items-center gap-2 flex-1 min-w-0">
@if ($project && $environment && $application)
<a href="{{ route('project.application.configuration', [
'project_uuid' => $project->uuid,
'environment_uuid' => $environment->uuid,
'application_uuid' => $application->uuid
]) }}"
class="font-medium text-sm dark:text-white truncate hover:text-gray-900 dark:hover:text-gray-200 hover:underline">
{{ $application->name }}
</a>
@else
<span class="font-medium text-sm dark:text-white truncate">
{{ $application->name }}
</span>
@endif
</div>
{{-- Commit Info -- Clickable to GitHub commit page --}}
@ -249,9 +225,42 @@
@endif
</div>
{{-- Metadata -- Not clickable --}}
<div class="flex items-center gap-2 text-sm text-gray-600 dark:text-gray-400 w-48 flex-shrink-0 justify-end whitespace-nowrap">
<span class="whitespace-nowrap">{{ $deployment->created_at->diffForHumans(['short' => true]) }}</span>
{{-- Application Info -- Clickable to application configuration page --}}
<div class="flex items-center gap-2 flex-1 min-w-0">
@if ($project && $environment && $application)
<a href="{{ route('project.application.configuration', [
'project_uuid' => $project->uuid,
'environment_uuid' => $environment->uuid,
'application_uuid' => $application->uuid
]) }}"
class="font-medium text-sm dark:text-white truncate hover:text-gray-900 dark:hover:text-gray-200 hover:underline">
{{ $application->name }}
</a>
@else
<span class="font-medium text-sm dark:text-white truncate">
{{ $application->name }}
</span>
@endif
</div>
{{-- Environment Badge -- Clickable to environment page --}}
<div class="flex items-center gap-2 w-32 flex-shrink-0 whitespace-nowrap">
@if ($environment && $project)
<a href="{{ route('project.resource.index', [
'project_uuid' => $project->uuid,
'environment_uuid' => $environment->uuid
]) }}"
class="px-2 py-0.5 text-xs font-medium rounded bg-neutral-100 dark:bg-coolgray-100 text-gray-700 dark:text-gray-300 whitespace-nowrap hover:bg-neutral-200 dark:hover:bg-coolgray-200 transition-colors">
{{ ucfirst($environment->name) }}
</a>
@if ($isCurrent)
<span class="w-2 h-2 rounded-full bg-blue-500 flex-shrink-0" title="Current deployment"></span>
@endif
@elseif ($environment)
<span class="px-2 py-0.5 text-xs font-medium rounded bg-neutral-100 dark:bg-coolgray-100 text-gray-700 dark:text-gray-300 whitespace-nowrap">
{{ ucfirst($environment->name) }}
</span>
@endif
</div>
{{-- Expand/Collapse Button for Logs --}}