feat(audit): M5.2 per-node stuck-count KPIs (T6) — repo per-node aggregation, actor message pair, CentralUI tiles

This commit is contained in:
Joseph Doherty
2026-06-16 21:34:14 -04:00
parent a07ff28f10
commit 209f368cb5
25 changed files with 840 additions and 6 deletions
@@ -58,3 +58,31 @@
{
<div class="text-muted small mb-3">Site Call KPIs unavailable: @ErrorMessage</div>
}
@* ── Per-node stuck/parked sub-table (T6: M5.2 per-node stuck-count KPIs) ── *@
@if (HasNodeBreakdown)
{
<div class="mb-3">
<div class="d-flex justify-content-between align-items-center mb-1">
<small class="text-muted">By node</small>
</div>
<table class="table table-sm table-borderless mb-0 site-call-kpi-node-table">
<thead class="table-light">
<tr>
<th class="small py-1">Node</th>
<th class="text-end small py-1">Stuck</th>
<th class="text-end small py-1">Parked</th>
</tr>
</thead>
<tbody>
@foreach (var n in PerNodeSnapshots!)
{
<tr @key="n.SourceNode">
<td class="small py-1"><code>@n.SourceNode</code></td>
<td class="text-end font-monospace small py-1 @(n.StuckCount > 0 ? "text-warning" : "")">@n.StuckCount</td>
<td class="text-end font-monospace small py-1 @(n.ParkedCount > 0 ? "text-danger" : "")">@n.ParkedCount</td>
</tr>
}
</tbody>
</table>
</div>
}
@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Components;
using ZB.MOM.WW.ScadaBridge.Commons.Messages.Audit;
using ZB.MOM.WW.ScadaBridge.Commons.Types.Audit;
namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Health;
@@ -59,6 +60,24 @@ public partial class SiteCallKpiTiles
/// </summary>
[Parameter] public string? ErrorMessage { get; set; }
/// <summary>
/// Optional per-node KPI breakdown (T6: M5.2 per-node stuck-count KPIs).
/// When non-null and non-empty, a compact node-level stuck/parked sub-table
/// is rendered below the main tiles. <c>null</c> means the parent has not
/// loaded it yet or has opted out — the sub-table is suppressed entirely.
/// </summary>
[Parameter] public IReadOnlyList<SiteCallNodeKpiSnapshot>? PerNodeSnapshots { get; set; }
/// <summary>
/// True when <see cref="PerNodeSnapshots"/> is a successful query result.
/// Used to suppress the sub-table on a load failure.
/// </summary>
[Parameter] public bool PerNodeAvailable { get; set; }
/// <summary>Whether the per-node sub-table has data to render.</summary>
internal bool HasNodeBreakdown =>
PerNodeAvailable && PerNodeSnapshots is { Count: > 0 };
// ── Buffered tile ───────────────────────────────────────────────────────
private string BufferedDisplay =>