Handle Dokploy project composes in widget
This commit is contained in:
@@ -52,6 +52,7 @@ class DokployPlatformHealth extends Widget
|
|||||||
|
|
||||||
$applicationsPayload = Arr::get($project, 'applications', []);
|
$applicationsPayload = Arr::get($project, 'applications', []);
|
||||||
$applications = $this->formatApplications(is_array($applicationsPayload) ? $applicationsPayload : [], $client);
|
$applications = $this->formatApplications(is_array($applicationsPayload) ? $applicationsPayload : [], $client);
|
||||||
|
$composes = $this->formatProjectComposes($project, $client);
|
||||||
$services = $this->formatProjectServices($project);
|
$services = $this->formatProjectServices($project);
|
||||||
|
|
||||||
$results[] = [
|
$results[] = [
|
||||||
@@ -59,11 +60,13 @@ class DokployPlatformHealth extends Widget
|
|||||||
'project_id' => Arr::get($project, 'projectId', $projectId),
|
'project_id' => Arr::get($project, 'projectId', $projectId),
|
||||||
'name' => Arr::get($project, 'name') ?? Arr::get($project, 'projectName') ?? (string) $projectId,
|
'name' => Arr::get($project, 'name') ?? Arr::get($project, 'projectName') ?? (string) $projectId,
|
||||||
'description' => Arr::get($project, 'description'),
|
'description' => Arr::get($project, 'description'),
|
||||||
'status' => $this->deriveProjectStatus($applications, $services),
|
'status' => $this->deriveProjectStatus($applications, $services, $composes),
|
||||||
'applications' => $applications,
|
'applications' => $applications,
|
||||||
|
'composes' => $composes,
|
||||||
'services' => $services,
|
'services' => $services,
|
||||||
'updated_at' => Arr::get($project, 'updatedAt') ?? Arr::get($project, 'createdAt'),
|
'updated_at' => Arr::get($project, 'updatedAt') ?? Arr::get($project, 'createdAt'),
|
||||||
'applications_count' => count($applications),
|
'applications_count' => count($applications),
|
||||||
|
'composes_count' => count($composes),
|
||||||
'services_count' => count($services),
|
'services_count' => count($services),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -204,6 +207,52 @@ class DokployPlatformHealth extends Widget
|
|||||||
->all();
|
->all();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function formatProjectComposes(array $project, DokployClient $client): array
|
||||||
|
{
|
||||||
|
$composes = (array) Arr::get($project, 'compose', []);
|
||||||
|
|
||||||
|
return collect($composes)
|
||||||
|
->map(function (array $compose) use ($client) {
|
||||||
|
$composeId = Arr::get($compose, 'composeId') ?? Arr::get($compose, 'id');
|
||||||
|
$statusPayload = [];
|
||||||
|
$deployments = [];
|
||||||
|
|
||||||
|
if ($composeId) {
|
||||||
|
try {
|
||||||
|
$statusPayload = $client->composeStatus($composeId);
|
||||||
|
$deployments = $client->composeDeployments($composeId, 1);
|
||||||
|
} catch (\Throwable $exception) {
|
||||||
|
$statusPayload = [];
|
||||||
|
$deployments = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$composeDetails = Arr::get($statusPayload, 'compose', []);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'id' => $composeId,
|
||||||
|
'name' => Arr::get($compose, 'name')
|
||||||
|
?? Arr::get($compose, 'appName')
|
||||||
|
?? Arr::get($composeDetails, 'name')
|
||||||
|
?? Arr::get($composeDetails, 'appName')
|
||||||
|
?? $composeId,
|
||||||
|
'status' => Arr::get($compose, 'composeStatus')
|
||||||
|
?? Arr::get($compose, 'status')
|
||||||
|
?? Arr::get($composeDetails, 'composeStatus')
|
||||||
|
?? Arr::get($composeDetails, 'status')
|
||||||
|
?? 'unknown',
|
||||||
|
'last_deploy' => Arr::get($deployments, '0.createdAt')
|
||||||
|
?? Arr::get($deployments, '0.created_at')
|
||||||
|
?? Arr::get($compose, 'updatedAt')
|
||||||
|
?? Arr::get($composeDetails, 'updatedAt'),
|
||||||
|
'services' => $this->formatServices(Arr::get($statusPayload, 'services', [])),
|
||||||
|
];
|
||||||
|
})
|
||||||
|
->filter(fn (array $compose) => filled($compose['name']))
|
||||||
|
->values()
|
||||||
|
->all();
|
||||||
|
}
|
||||||
|
|
||||||
protected function normalizeServiceList(array $services, string $type, string $idKey, string $statusKey): array
|
protected function normalizeServiceList(array $services, string $type, string $idKey, string $statusKey): array
|
||||||
{
|
{
|
||||||
return collect($services)
|
return collect($services)
|
||||||
@@ -246,11 +295,12 @@ class DokployPlatformHealth extends Widget
|
|||||||
return $metrics;
|
return $metrics;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function deriveProjectStatus(array $applications, array $services): string
|
protected function deriveProjectStatus(array $applications, array $services, array $composes): string
|
||||||
{
|
{
|
||||||
$statuses = collect($applications)
|
$statuses = collect($applications)
|
||||||
->pluck('status')
|
->pluck('status')
|
||||||
->merge(collect($services)->pluck('status'))
|
->merge(collect($services)->pluck('status'))
|
||||||
|
->merge(collect($composes)->pluck('status'))
|
||||||
->filter()
|
->filter()
|
||||||
->map(fn ($status) => strtolower((string) $status))
|
->map(fn ($status) => strtolower((string) $status))
|
||||||
->values();
|
->values();
|
||||||
|
|||||||
@@ -83,6 +83,9 @@
|
|||||||
<x-filament::badge color="gray" :icon="Heroicon::RectangleStack">
|
<x-filament::badge color="gray" :icon="Heroicon::RectangleStack">
|
||||||
Apps: {{ $project['applications_count'] ?? 0 }}
|
Apps: {{ $project['applications_count'] ?? 0 }}
|
||||||
</x-filament::badge>
|
</x-filament::badge>
|
||||||
|
<x-filament::badge color="gray" :icon="Heroicon::ServerStack">
|
||||||
|
Composes: {{ $project['composes_count'] ?? 0 }}
|
||||||
|
</x-filament::badge>
|
||||||
<x-filament::badge color="gray" :icon="Heroicon::ServerStack">
|
<x-filament::badge color="gray" :icon="Heroicon::ServerStack">
|
||||||
Services: {{ $project['services_count'] ?? 0 }}
|
Services: {{ $project['services_count'] ?? 0 }}
|
||||||
</x-filament::badge>
|
</x-filament::badge>
|
||||||
@@ -158,6 +161,55 @@
|
|||||||
@endforelse
|
@endforelse
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div {{ $stacked }}>
|
||||||
|
<x-filament::badge color="gray" :icon="Heroicon::ServerStack">
|
||||||
|
Composes
|
||||||
|
</x-filament::badge>
|
||||||
|
|
||||||
|
@forelse($project['composes'] as $compose)
|
||||||
|
<div {{ $stacked }}>
|
||||||
|
<x-filament::badge
|
||||||
|
:color="$statusColors[$compose['status']] ?? 'gray'"
|
||||||
|
:icon="$statusIcons[$compose['status']] ?? Heroicon::QuestionMarkCircle"
|
||||||
|
>
|
||||||
|
{{ $compose['name'] ?? 'Compose' }}
|
||||||
|
@if(!empty($compose['status']))
|
||||||
|
({{ strtoupper($compose['status']) }})
|
||||||
|
@endif
|
||||||
|
</x-filament::badge>
|
||||||
|
|
||||||
|
<div {{ $detailsGrid }}>
|
||||||
|
@if(!empty($compose['id']))
|
||||||
|
<x-filament::badge color="gray" :icon="Heroicon::Identification">
|
||||||
|
{{ $compose['id'] }}
|
||||||
|
</x-filament::badge>
|
||||||
|
@endif
|
||||||
|
<x-filament::badge color="gray" :icon="Heroicon::Clock">
|
||||||
|
Last deploy:
|
||||||
|
{{ $compose['last_deploy'] ? \Illuminate\Support\Carbon::parse($compose['last_deploy'])->diffForHumans() : '—' }}
|
||||||
|
</x-filament::badge>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if(!empty($compose['services']))
|
||||||
|
<div {{ $serviceGrid }}>
|
||||||
|
@foreach($compose['services'] as $service)
|
||||||
|
<x-filament::badge
|
||||||
|
:color="$serviceColors[$service['status']] ?? 'gray'"
|
||||||
|
:icon="array_key_exists($service['status'] ?? '', $serviceColors) ? Heroicon::Server : Heroicon::QuestionMarkCircle"
|
||||||
|
>
|
||||||
|
{{ $service['name'] }}: {{ strtoupper($service['status'] ?? 'N/A') }}
|
||||||
|
</x-filament::badge>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
@empty
|
||||||
|
<x-filament::badge color="gray" :icon="Heroicon::QuestionMarkCircle">
|
||||||
|
No composes reported.
|
||||||
|
</x-filament::badge>
|
||||||
|
@endforelse
|
||||||
|
</div>
|
||||||
|
|
||||||
<div {{ $stacked }}>
|
<div {{ $stacked }}>
|
||||||
<x-filament::badge color="gray" :icon="Heroicon::ServerStack">
|
<x-filament::badge color="gray" :icon="Heroicon::ServerStack">
|
||||||
Services
|
Services
|
||||||
|
|||||||
@@ -40,6 +40,13 @@ class DokployPlatformHealthWidgetTest extends TestCase
|
|||||||
'branch' => 'main',
|
'branch' => 'main',
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
'compose' => [
|
||||||
|
[
|
||||||
|
'composeId' => 'cmp_1',
|
||||||
|
'name' => 'Main Compose',
|
||||||
|
'composeStatus' => 'done',
|
||||||
|
],
|
||||||
|
],
|
||||||
'redis' => [
|
'redis' => [
|
||||||
[
|
[
|
||||||
'redisId' => 'redis_1',
|
'redisId' => 'redis_1',
|
||||||
@@ -63,12 +70,37 @@ class DokployPlatformHealthWidgetTest extends TestCase
|
|||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$fakeClient->shouldReceive('composeStatus')
|
||||||
|
->with('cmp_1')
|
||||||
|
->andReturn([
|
||||||
|
'compose' => [
|
||||||
|
'name' => 'Main Compose',
|
||||||
|
'composeStatus' => 'done',
|
||||||
|
'updatedAt' => now()->toIso8601String(),
|
||||||
|
],
|
||||||
|
'services' => [
|
||||||
|
[
|
||||||
|
'serviceName' => 'web',
|
||||||
|
'status' => 'running',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$fakeClient->shouldReceive('composeDeployments')
|
||||||
|
->with('cmp_1', 1)
|
||||||
|
->andReturn([
|
||||||
|
[
|
||||||
|
'createdAt' => now()->toIso8601String(),
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
$this->app->instance(DokployClient::class, $fakeClient);
|
$this->app->instance(DokployClient::class, $fakeClient);
|
||||||
|
|
||||||
Livewire::test(DokployPlatformHealth::class)
|
Livewire::test(DokployPlatformHealth::class)
|
||||||
->assertStatus(200)
|
->assertStatus(200)
|
||||||
->assertSee('Core')
|
->assertSee('Core')
|
||||||
->assertSee('API')
|
->assertSee('API')
|
||||||
|
->assertSee('Main Compose')
|
||||||
->assertSee('Redis');
|
->assertSee('Redis');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user