feat(m9/T25): connection live-status indicators on the design page
This commit is contained in:
@@ -1,10 +1,14 @@
|
||||
@page "/design/connections"
|
||||
@page "/design/data-connections"
|
||||
@using ZB.MOM.WW.ScadaBridge.Security
|
||||
@using ZB.MOM.WW.ScadaBridge.CentralUI.Services
|
||||
@using ZB.MOM.WW.ScadaBridge.Commons.Entities.Sites
|
||||
@using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Repositories
|
||||
@using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums
|
||||
@attribute [Authorize(Policy = AuthorizationPolicies.RequireDesign)]
|
||||
@implements IDisposable
|
||||
@inject ISiteRepository SiteRepository
|
||||
@inject IConnectionHealthQueryService ConnectionHealthQuery
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IDialogService Dialog
|
||||
|
||||
@@ -80,6 +84,21 @@
|
||||
{
|
||||
<span class="tv-label" style="@labelStyle">@node.Label</span>
|
||||
<span class="badge bg-info ms-2">@node.Connection!.Protocol</span>
|
||||
var health = _connectionHealth.TryGetValue(node.Connection!.Id, out var h)
|
||||
? (ConnectionHealth?)h
|
||||
: null;
|
||||
@if (health is { } known)
|
||||
{
|
||||
<span class="badge @GetConnectionHealthBadge(known) ms-1"
|
||||
data-test="@($"conn-health-{node.Connection!.Id}")"
|
||||
aria-label="@($"Connection health: {known}")">@known</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="badge bg-secondary ms-1"
|
||||
data-test="@($"conn-health-{node.Connection!.Id}")"
|
||||
aria-label="Connection health: unknown">Unknown</span>
|
||||
}
|
||||
}
|
||||
<span class="tv-meta">
|
||||
<div class="dropdown dc-node-actions" @onclick:stopPropagation="true">
|
||||
@@ -184,11 +203,48 @@
|
||||
|
||||
private ToastNotification _toast = default!;
|
||||
|
||||
// M9-T25: live per-connection health, keyed by DataConnection.Id. Sourced from
|
||||
// the existing site→central health transport via IConnectionHealthQueryService
|
||||
// and refreshed on a ~10s poll, mirroring the Health dashboard's timer pattern.
|
||||
// A connection absent from the map renders an "Unknown" badge (tolerates a site
|
||||
// with no report yet — no crash).
|
||||
private IReadOnlyDictionary<int, ConnectionHealth> _connectionHealth =
|
||||
new Dictionary<int, ConnectionHealth>();
|
||||
private Timer? _healthTimer;
|
||||
private const int HealthRefreshSeconds = 10;
|
||||
|
||||
private bool HasSiteSelected => ResolveSelectedSiteId() != null;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await LoadDataAsync();
|
||||
await LoadConnectionHealthAsync();
|
||||
|
||||
// Poll the live health map on the same cadence as the Health dashboard.
|
||||
// Best-effort: a failed query leaves the prior map in place rather than
|
||||
// disturbing the tree.
|
||||
_healthTimer = new Timer(_ =>
|
||||
{
|
||||
InvokeAsync(async () =>
|
||||
{
|
||||
await LoadConnectionHealthAsync();
|
||||
StateHasChanged();
|
||||
});
|
||||
}, null, TimeSpan.FromSeconds(HealthRefreshSeconds), TimeSpan.FromSeconds(HealthRefreshSeconds));
|
||||
}
|
||||
|
||||
// Best-effort load of the connection-id → health map. A transient fault leaves
|
||||
// the existing badges untouched — health is advisory, never blocks the page.
|
||||
private async Task LoadConnectionHealthAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
_connectionHealth = await ConnectionHealthQuery.GetConnectionHealthAsync();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Keep the prior map; the next poll retries.
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadDataAsync()
|
||||
@@ -310,4 +366,22 @@
|
||||
_toast.ShowError($"Delete failed: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
// M9-T25: enum → Bootstrap badge class. Mirrors the Health dashboard's
|
||||
// GetConnectionHealthBadge (Components/Pages/Monitoring/Health.razor) so the
|
||||
// design page surfaces the same colour coding for the same status. Kept as a
|
||||
// small local mirror — the Health helper is a private page-local method, not a
|
||||
// shared component, so extracting it carries more risk than the duplication.
|
||||
private static string GetConnectionHealthBadge(ConnectionHealth health) => health switch
|
||||
{
|
||||
ConnectionHealth.Connected => "bg-success",
|
||||
ConnectionHealth.Connecting => "bg-warning text-dark",
|
||||
ConnectionHealth.Disconnected => "bg-danger",
|
||||
_ => "bg-secondary"
|
||||
};
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_healthTimer?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user