feat(adminui): #546 wire DriverStatusPanel into /hosts driver rows (collapsed expander)
DriverStatusPanel was orphaned — zero references repo-wide — so the Restart and Reconnect driver commands had NO reachable UI at all, despite working end to end over the new gRPC mesh transport. Nothing failed to build, test or deploy while that was true, which is why it went unnoticed. The panel is now reachable per driver row on /hosts, behind a per-row "Controls" expander that is collapsed by default: the table stays scannable, and only the opened panels hold snapshot-store subscriptions. Expansion state is a HashSet keyed by DriverInstanceId held on the page, so it survives the 5 s refresh that replaces every row record. Both rows are @key'd by instance id so the panel — which binds its DriverInstanceId once in OnInitializedAsync — can never be diffed onto a different driver. The panel's Enabled parameter is fed from real config rather than defaulted: HostsDriverInstanceInfo/HostsDriverRow now carry DriverInstance.Enabled, which LoadConfigAsync already had in hand. A snapshot with no matching configured instance is treated as enabled — the row exists only because live health arrived, so "Disabled — not deployed" would contradict the same row. The expander is visible to every AuthenticatedRead viewer; the panel self-gates only its Reconnect/Restart buttons on DriverOperator. A source-scan pin (HostsPanelWiringTests) asserts /hosts still renders the panel and still binds it to the row's own driver, cluster and enabled state — removing the tag would silently restore the orphaned state. Claude-Session: https://claude.ai/code/session_014WNM4vjoVksyyBraTXSZE1
This commit is contained in:
@@ -22,8 +22,9 @@ public sealed class HostsDriverViewTests
|
||||
private static HostsNodeInfo Node(string cluster, string node, string host = "h", int port = 4840) =>
|
||||
new(cluster, node, host, port);
|
||||
|
||||
private static HostsDriverInstanceInfo Instance(string instance, string cluster, string name, string type) =>
|
||||
new(instance, cluster, name, type);
|
||||
private static HostsDriverInstanceInfo Instance(
|
||||
string instance, string cluster, string name, string type, bool enabled = true) =>
|
||||
new(instance, cluster, name, type, enabled);
|
||||
|
||||
[Fact]
|
||||
public void Build_groups_two_clusters_with_their_nodes_and_snapshots()
|
||||
@@ -214,6 +215,38 @@ public sealed class HostsDriverViewTests
|
||||
row.DegradedHosts.ShouldBeEmpty();
|
||||
}
|
||||
|
||||
// ---- authored enabled-state (Gitea #546) ----
|
||||
|
||||
/// <summary>
|
||||
/// The authored enabled flag reaches the row, which forwards it to the row's
|
||||
/// <c>DriverStatusPanel</c>. Defaulting it to true would have the panel open a live
|
||||
/// subscription for an instance that was deliberately taken out of the deployment.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Build_carries_the_authored_enabled_flag_onto_the_row()
|
||||
{
|
||||
var groups = HostsDriverView.Build(
|
||||
[Snap("MAIN", "drv-a")],
|
||||
nodes: null,
|
||||
[Instance("drv-a", "MAIN", "Pump House Modbus", "Modbus", enabled: false)]);
|
||||
|
||||
groups.Single().Drivers.Single().Enabled.ShouldBeFalse();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A snapshot with no matching configured instance is treated as enabled. The row only exists
|
||||
/// because live health arrived for it, so rendering the panel's "Disabled — not deployed"
|
||||
/// notice would contradict the evidence on the same row.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void An_unmatched_driver_row_is_treated_as_enabled()
|
||||
{
|
||||
var row = HostsDriverView.Build([Snap("MAIN", "orphan")], nodes: null, instances: null)
|
||||
.Single().Drivers.Single();
|
||||
|
||||
row.Enabled.ShouldBeTrue();
|
||||
}
|
||||
|
||||
// ---- skipped tags (Gitea #541) ----
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user