From 262ad8981a5257535c1f5e6109ff078b012501cb Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Thu, 6 Aug 2026 18:15:58 +0200 Subject: [PATCH] feat(ui): unify status summaries, tooltips, and resource headings Add shared status-summary and icon-tooltip components and wire them into application, service, and database headings, breadcrumbs, and previews. Badge production and PR domain links, prefer helper popups below the trigger, keep full wire targets for button loading, and cover the UI with feature tests. --- .../components/applications/links.blade.php | 20 +- .../views/components/forms/button.blade.php | 4 +- resources/views/components/helper.blade.php | 10 +- .../views/components/icon-tooltip.blade.php | 67 +++++++ .../resources/breadcrumbs.blade.php | 4 + .../server/status-summary.blade.php | 26 +-- .../views/components/status-summary.blade.php | 94 ++++++++++ resources/views/layouts/base.blade.php | 1 + .../project/application/domains.blade.php | 159 +++++++++------- .../project/application/general.blade.php | 6 +- .../project/application/heading.blade.php | 16 +- .../project/application/previews.blade.php | 173 ++++++++++++------ .../project/application/status.blade.php | 20 +- .../project/database/heading.blade.php | 8 +- .../project/database/status.blade.php | 20 +- .../project/service/configuration.blade.php | 6 +- .../project/service/domains.blade.php | 28 +++ .../project/service/heading.blade.php | 44 +++-- .../project/service/resource-card.blade.php | 26 ++- .../livewire/project/service/status.blade.php | 20 +- .../service/volume-backup/index.blade.php | 11 +- .../project/shared/storages/all.blade.php | 15 +- tests/Feature/ApplicationDomainsTest.php | 28 ++- .../ApplicationInternalAccessSectionTest.php | 5 +- .../DatabasePersistentStorageLayoutTest.php | 3 +- tests/Feature/FormsButtonLoadingTest.php | 4 +- tests/Feature/GlobalIconTooltipTest.php | 15 ++ tests/Feature/HelperInfoButtonTest.php | 17 +- tests/Feature/PreviewStatusSummaryTest.php | 76 ++++++++ .../ResourceHeadingUnifiedNavbarTest.php | 40 +++- .../Feature/ServerNavbarStatusLayoutTest.php | 12 +- ...erviceComposeResourcesViewSwitcherTest.php | 13 ++ .../ServiceDatabaseVerticalNavigationTest.php | 9 + tests/Feature/ServiceDomainsTest.php | 11 ++ tests/Feature/StatusBadgeComponentsTest.php | 3 +- 35 files changed, 749 insertions(+), 265 deletions(-) create mode 100644 resources/views/components/icon-tooltip.blade.php create mode 100644 resources/views/components/status-summary.blade.php create mode 100644 tests/Feature/GlobalIconTooltipTest.php create mode 100644 tests/Feature/PreviewStatusSummaryTest.php diff --git a/resources/views/components/applications/links.blade.php b/resources/views/components/applications/links.blade.php index 647dc1ab9..fa9a88119 100644 --- a/resources/views/components/applications/links.blade.php +++ b/resources/views/components/applications/links.blade.php @@ -45,6 +45,10 @@ @if (data_get($fqdn, 'domain')) @foreach (explode(',', data_get($fqdn, 'domain')) as $domain) + + Production + {{ getFqdnWithoutPort($domain) }} @endforeach @@ -54,6 +58,10 @@ @if (data_get($application, 'fqdn')) @foreach (str(data_get($application, 'fqdn'))->explode(',') as $fqdn) + + Production + {{ getFqdnWithoutPort($fqdn) }} @endforeach @@ -66,7 +74,11 @@ @foreach (explode(',', data_get($fqdn, 'domain')) as $domain) - PR{{ data_get($preview, 'pull_request_id') }} | {{ getFqdnWithoutPort($domain) }} + + PR #{{ data_get($preview, 'pull_request_id') }} + + {{ getFqdnWithoutPort($domain) }} @endforeach @endif @@ -77,7 +89,11 @@ @if (data_get($preview, 'fqdn')) - PR{{ data_get($preview, 'pull_request_id') }} | {{ data_get($preview, 'fqdn') }} + + PR #{{ data_get($preview, 'pull_request_id') }} + + {{ getFqdnWithoutPort(data_get($preview, 'fqdn')) }} @endif @endforeach diff --git a/resources/views/components/forms/button.blade.php b/resources/views/components/forms/button.blade.php index 86423eb9d..7a061dc45 100644 --- a/resources/views/components/forms/button.blade.php +++ b/resources/views/components/forms/button.blade.php @@ -9,9 +9,9 @@ $loadingTarget = null; if ($showLoadingIndicator) { if (filled($wireClickValue)) { - $loadingTarget = trim(explode('(', (string) $wireClickValue, 2)[0]); + $loadingTarget = trim((string) $wireClickValue); } elseif ($hasExplicitWireTarget) { - $loadingTarget = trim(explode('(', (string) $wireTargetValue, 2)[0]); + $loadingTarget = trim((string) $wireTargetValue); } } diff --git a/resources/views/components/helper.blade.php b/resources/views/components/helper.blade.php index fb6364973..15a5055c3 100644 --- a/resources/views/components/helper.blade.php +++ b/resources/views/components/helper.blade.php @@ -54,11 +54,11 @@ const triggerRect = trigger.getBoundingClientRect(); const popupRect = popup.getBoundingClientRect(); const padding = 8; - let top = triggerRect.top - popupRect.height - padding; + let top = triggerRect.bottom + padding; let left = triggerRect.right - popupRect.width; - if (top < padding) { - top = triggerRect.bottom + padding; + if (top + popupRect.height > window.innerHeight - padding) { + top = triggerRect.top - popupRect.height - padding; } left = Math.min(Math.max(padding, left), window.innerWidth - popupRect.width - padding); @@ -68,11 +68,11 @@ } }" @pointerdown.window="closeWhenPointerIsOutside($event)" @keydown.window.escape="close" @resize.window="open && position()" @scroll.window="open && position()" - {{ $attributes->merge(['class' => 'relative z-10 inline-block align-middle']) }}> + {{ $attributes->merge(['class' => 'relative inline-block align-middle']) }}> {{-- button (not div) so label-for associations do not steal the click on mobile --}} + @endif +
{{ $server->isSentinelLive() ? 'In sync' : 'Out of sync' }} @endif - @if ($server->proxySet()) - - @endif
diff --git a/resources/views/components/status-summary.blade.php b/resources/views/components/status-summary.blade.php new file mode 100644 index 000000000..4cea3b594 --- /dev/null +++ b/resources/views/components/status-summary.blade.php @@ -0,0 +1,94 @@ +@props(['status', 'title' => 'Application status', 'containerName' => 'Container']) + +@php + $rawStatus = str((string) $status)->lower()->trim()->value(); + $statusParts = explode(':', $rawStatus); + $containerStatus = $statusParts[0] ?? 'unknown'; + $healthStatus = $statusParts[1] ?? null; + $monitoringExcluded = in_array('excluded', $statusParts, true); + + if ($healthStatus === null && preg_match('/^([^()]+)\(([^)]+)\)$/', $rawStatus, $matches)) { + $containerStatus = trim($matches[1]); + $healthStatus = trim($matches[2]); + } + + $containerLabel = str($containerStatus ?: 'unknown')->headline()->value(); + $healthLabel = match (true) { + $monitoringExcluded => 'Monitoring disabled', + $healthStatus === 'healthy' => 'Healthy', + $healthStatus === 'unhealthy' => 'Unhealthy', + $healthStatus === 'starting' => 'Starting', + default => 'Not configured', + }; + + $containerType = match (true) { + str($containerStatus)->startsWith('running') => 'success', + str($containerStatus)->startsWith(['starting', 'restarting']) => 'warning', + default => 'error', + }; + + $healthType = match (true) { + $monitoringExcluded => 'warning', + $healthStatus === 'healthy' => 'success', + $healthStatus === 'unhealthy' => 'error', + default => 'warning', + }; + + [$summaryLabel, $summaryType] = match (true) { + $containerType === 'error' => [$containerLabel, 'error'], + $healthType === 'error' => ['Degraded', 'error'], + $containerType === 'warning' => [$containerLabel, 'warning'], + $monitoringExcluded => ["{$containerLabel} (monitoring disabled)", 'warning'], + $healthStatus === 'starting' => ["{$containerLabel} (health check starting)", 'warning'], + $healthType === 'warning' => ["{$containerLabel} (no health check)", 'warning'], + default => [$containerLabel, 'success'], + }; +@endphp + +
+ + $summaryType === 'success', + 'bg-warning' => $summaryType === 'warning', + 'bg-error' => $summaryType === 'error', + ])> + {{ $summaryLabel }} + + + + + + +
diff --git a/resources/views/layouts/base.blade.php b/resources/views/layouts/base.blade.php index 38ee3264a..02f6ecf1a 100644 --- a/resources/views/layouts/base.blade.php +++ b/resources/views/layouts/base.blade.php @@ -97,6 +97,7 @@ +