diff --git a/app/Livewire/Project/Shared/Logs.php b/app/Livewire/Project/Shared/Logs.php index 4c9b882dcf..1add0bb6a0 100644 --- a/app/Livewire/Project/Shared/Logs.php +++ b/app/Livewire/Project/Shared/Logs.php @@ -213,7 +213,7 @@ class Logs extends Component /** * @return array{ - * deployments: list, + * deployments: list, * services: list, * deployment: string, * service: string, diff --git a/app/Support/RuntimeLogTargets.php b/app/Support/RuntimeLogTargets.php index d8454098d2..45bdc42329 100644 --- a/app/Support/RuntimeLogTargets.php +++ b/app/Support/RuntimeLogTargets.php @@ -17,7 +17,7 @@ class RuntimeLogTargets /** * @param list>}> $servers * @return array{ - * deployments: list, + * deployments: list, * services: list, * deployment: string, * service: string, @@ -50,7 +50,7 @@ class RuntimeLogTargets $sources = self::sourcesFor($groups[$chosenKey]); return [ - 'deployments' => $groupDeployments ? self::deploymentOptions($deploymentIds) : [], + 'deployments' => $groupDeployments ? self::deploymentOptions($deploymentIds, $containers) : [], 'services' => self::serviceOptions($groups), 'deployment' => $chosenDeployment, 'service' => count($groups) > 1 ? $chosenKey : '', @@ -204,18 +204,37 @@ class RuntimeLogTargets } /** + * Deployments show the same status dot and caption as services, for all their containers. + * * @param list $ids - * @return list + * @param list $containers + * @return list */ - private static function deploymentOptions(array $ids): array + private static function deploymentOptions(array $ids, array $containers): array { - return array_map(fn (string $id): array => [ - 'value' => $id, - 'label' => $id === '0' ? 'Production' : 'PR #'.$id, - 'labelClass' => $id === '0' - ? 'deployment-badge deployment-badge-production' - : 'deployment-badge deployment-badge-preview', - ], $ids); + return array_map(function (string $id) use ($containers): array { + $states = array_column(array_filter( + $containers, + fn (array $container): bool => $container['deployment'] === $id, + ), 'state'); + + return self::statusOption($id, $id === '0' ? 'Production' : 'PR #'.$id, $states); + }, $ids); + } + + /** + * @param list $states + * @return array{value: string, label: string, dot: string, state?: string} + */ + private static function statusOption(string $value, string $label, array $states): array + { + $option = ['value' => $value, 'label' => $label, 'dot' => self::serviceDot($states)]; + $state = self::serviceStateLabel($states); + if ($state !== null) { + $option['state'] = $state; + } + + return $option; } /** @@ -261,16 +280,7 @@ class RuntimeLogTargets { $options = []; foreach ($groups as $key => $containers) { - $states = array_column($containers, 'state'); - $option = [ - 'value' => $key, - 'label' => $key, - 'dot' => self::serviceDot($states), - ]; - $state = self::serviceStateLabel($states); - if ($state !== null) { - $option['state'] = $state; - } + $option = self::statusOption($key, $key, array_column($containers, 'state')); if (count($containers) > 1) { $option['description'] = count($containers).' containers'; } diff --git a/resources/views/components/forms/listbox.blade.php b/resources/views/components/forms/listbox.blade.php index a7f1012835..06b68b3dbe 100644 --- a/resources/views/components/forms/listbox.blade.php +++ b/resources/views/components/forms/listbox.blade.php @@ -4,7 +4,7 @@ 'label' => null, 'helper' => null, 'required' => false, - 'options' => [], // list of ['value' => ..., 'label' => ..., 'description' => ?string, 'disabled' => bool, 'dot' => ?string, 'state' => ?string, 'labelClass' => ?string] + 'options' => [], // list of ['value' => ..., 'label' => ..., 'description' => ?string, 'disabled' => bool, 'dot' => ?string, 'state' => ?string] 'placeholder' => 'Select…', 'emptyText' => 'No options available.', 'live' => false, @@ -236,7 +236,7 @@ :aria-expanded="open" @if ($tooltip) :title="title" @endif> - {{ $multiple ? $multipleLabel : '' }} + {{ $multiple ? $multipleLabel : '' }} - + @@ -364,7 +364,7 @@ - + diff --git a/tests/Unit/Support/RuntimeLogTargetsTest.php b/tests/Unit/Support/RuntimeLogTargetsTest.php index a8fb7ca8cd..878bddbc12 100644 --- a/tests/Unit/Support/RuntimeLogTargetsTest.php +++ b/tests/Unit/Support/RuntimeLogTargetsTest.php @@ -29,16 +29,16 @@ function runtimeLogTargets(array $servers, string $deployment = '0', string $ser it('orders production ahead of newer previews and uses the top bar pills', function () { $targets = runtimeLogTargets([ runtimeLogServer('primary', 'Primary', [ - runtimeLogContainer('app-pr-7', 'coolify.pullRequestId=7,com.docker.compose.service=web'), + runtimeLogContainer('app-pr-7', 'coolify.pullRequestId=7,com.docker.compose.service=web', 'exited'), runtimeLogContainer('app', 'coolify.pullRequestId=0,com.docker.compose.service=web'), runtimeLogContainer('app-pr-42', 'coolify.pullRequestId=42,com.docker.compose.service=web'), ]), ]); expect($targets['deployments'])->toBe([ - ['value' => '0', 'label' => 'Production', 'labelClass' => 'deployment-badge deployment-badge-production'], - ['value' => '42', 'label' => 'PR #42', 'labelClass' => 'deployment-badge deployment-badge-preview'], - ['value' => '7', 'label' => 'PR #7', 'labelClass' => 'deployment-badge deployment-badge-preview'], + ['value' => '0', 'label' => 'Production', 'dot' => 'success'], + ['value' => '42', 'label' => 'PR #42', 'dot' => 'success'], + ['value' => '7', 'label' => 'PR #7', 'dot' => 'error', 'state' => 'Stopped'], ]) ->and($targets['deployment'])->toBe('0') ->and($targets['service'])->toBe('')