feat(ui/topology): open instance in Debug View from context menu

Adds a Debug View item to the instance context menu on /deployment/topology
that navigates to /deployment/debug-view with siteId and instanceId query
parameters; the page now auto-connects when those are present (falling
back to the existing localStorage auto-reconnect otherwise). Disabled for
non-Enabled instances since debug streaming only targets enabled ones.

Also fixes a latent NRE in DebugView.OnInitializedAsync: the toast ref
isn't bound yet during init, so transient load failures are now stashed
and surfaced from OnAfterRenderAsync where the toast is ready.
This commit is contained in:
Joseph Doherty
2026-05-13 13:41:20 -04:00
parent 733679a376
commit 3f37584728
2 changed files with 34 additions and 1 deletions

View File

@@ -247,6 +247,9 @@
@code {
private const int MaxRows = 200;
[SupplyParameterFromQuery] public int? SiteId { get; set; }
[SupplyParameterFromQuery] public int? InstanceId { get; set; }
private List<Site> _sites = new();
private List<Instance> _siteInstances = new();
private int _selectedSiteId;
@@ -287,6 +290,8 @@
private DebugStreamSession? _session;
private ToastNotification _toast = default!;
private string? _initError;
protected override async Task OnInitializedAsync()
{
try
@@ -295,7 +300,7 @@
}
catch (Exception ex)
{
_toast.ShowError($"Failed to load sites: {ex.Message}");
_initError = $"Failed to load sites: {ex.Message}";
}
_loading = false;
}
@@ -304,6 +309,29 @@
{
if (!firstRender) return;
if (_initError != null)
{
_toast.ShowError(_initError);
_initError = null;
}
if (SiteId is > 0 && InstanceId is > 0)
{
_selectedSiteId = SiteId.Value;
await LoadInstancesForSite();
if (_siteInstances.Any(i => i.Id == InstanceId.Value))
{
_selectedInstanceId = InstanceId.Value;
await Connect();
}
else
{
_toast.ShowError("Requested instance is not available for debug streaming.");
}
StateHasChanged();
return;
}
var storedSiteId = await JS.InvokeAsync<string>("localStorage.getItem", "debugView.siteId");
var storedInstanceId = await JS.InvokeAsync<string>("localStorage.getItem", "debugView.instanceId");

View File

@@ -452,6 +452,11 @@
@onclick='() => NavigationManager.NavigateTo($"/deployment/instances/{inst.Id}/configure")'>
Configure
</button>
<button class="dropdown-item"
@onclick='() => NavigationManager.NavigateTo($"/deployment/debug-view?siteId={node.SiteId}&instanceId={inst.Id}")'
disabled="@(inst.State != InstanceState.Enabled)">
Debug View
</button>
<button class="dropdown-item" @onclick="() => ShowDiff(inst)"
disabled="@(_actionInProgress || inst.State == InstanceState.NotDeployed)">Diff</button>
<button class="dropdown-item" @onclick="() => OpenMoveInstanceDialog(node)">Move to Area…</button>