From f066fb9c80260a69006a0001dcbff6d3359983e2 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Thu, 8 Oct 2026 17:34:58 -0400 Subject: [PATCH] feat(adminui): /fleet shows 'Applied (degraded)', /deployments 'Sealed (degraded)' (#601) Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe --- .../Components/Pages/Deployments.razor | 9 ++++--- .../Components/Pages/Fleet.razor | 25 ++++++++++++------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Deployments.razor b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Deployments.razor index 69fd15ba..01df5ffd 100644 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Deployments.razor +++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Deployments.razor @@ -57,7 +57,8 @@ @Short(d.DeploymentId) @DisplayText.Abbreviate(d.RevisionHash, 12) - @d.Status + @* #601: Sealed + a reason = sealed with a degraded address-space apply on some node(s). *@ + @(d.Status == DeploymentStatus.Sealed && !string.IsNullOrEmpty(d.FailureReason) ? "Sealed (degraded)" : d.Status.ToString()) @d.CreatedBy @d.CreatedAtUtc.ToString("u") @(d.SealedAtUtc?.ToString("u") ?? "—") @@ -77,7 +78,8 @@ DeploymentStatus Status, string CreatedBy, DateTime CreatedAtUtc, - DateTime? SealedAtUtc); + DateTime? SealedAtUtc, + string? FailureReason); private IReadOnlyList _deployments = Array.Empty(); private bool _busy; @@ -102,7 +104,8 @@ d.Status, d.CreatedBy, d.CreatedAtUtc, - d.SealedAtUtc)) + d.SealedAtUtc, + d.FailureReason)) .Take(50) .ToListAsync(); diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Fleet.razor b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Fleet.razor index 6e91c695..76cd5db1 100644 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Fleet.razor +++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Fleet.razor @@ -88,7 +88,7 @@ else @role } - @StatusLabel(r.Status) + @StatusLabel(r.Status, r.FailureReason) @(r.AppliedAtUtc?.ToString("u") ?? "—") @(r.StartedAtUtc?.ToString("u") ?? "—") @(string.IsNullOrEmpty(r.FailureReason) ? "" : DisplayText.Abbreviate(r.FailureReason, 80)) @@ -184,15 +184,22 @@ else } } - private static string StatusChipClass(NodeDeploymentStatus? status) => status switch - { - NodeDeploymentStatus.Applied => "chip-ok", - NodeDeploymentStatus.Applying => "chip-caution", - NodeDeploymentStatus.Failed => "chip-alert", - _ => "chip-idle", - }; + // #601 — an Applied row carrying a reason is a DEGRADED apply (the node runs the revision but its address + // space may be partial); it must not render as the same green chip as a clean apply. + private static bool IsDegraded(NodeDeploymentStatus? status, string? failureReason) => + status is { } s && ZB.MOM.WW.OtOpcUa.ControlPlane.Coordinators.ConfigPublishCoordinator.IsDegraded(s, failureReason); - private static string StatusLabel(NodeDeploymentStatus? status) => status?.ToString() ?? "waiting"; + private static string StatusChipClass(NodeDeploymentStatus? status, string? failureReason) => + IsDegraded(status, failureReason) ? "chip-caution" : status switch + { + NodeDeploymentStatus.Applied => "chip-ok", + NodeDeploymentStatus.Applying => "chip-caution", + NodeDeploymentStatus.Failed => "chip-alert", + _ => "chip-idle", + }; + + private static string StatusLabel(NodeDeploymentStatus? status, string? failureReason) => + IsDegraded(status, failureReason) ? "Applied (degraded)" : status?.ToString() ?? "waiting"; public async ValueTask DisposeAsync() {