Merge branch 'worktree-agent-a24fb696f5eee22f2' into feat/instance-picker

This commit is contained in:
Joseph Doherty
2026-09-08 09:45:25 -04:00
3 changed files with 106 additions and 16 deletions
@@ -61,14 +61,12 @@
</div>
<div class="col-md-2">
<label class="form-label form-label-sm">Instance</label>
<select class="form-select form-select-sm" data-test="flow-instance-select"
@bind="_selectedInstanceId" @bind:after="OnInstanceChangedAsync" disabled="@(_running || _selectedSiteId == 0)">
<option value="0">— choose —</option>
@foreach (var i in _instances)
{
<option value="@i.Id">@i.UniqueName</option>
}
</select>
@* A site can hold hundreds of instances, so this is the shared area-tree
combobox, not a flat list (design 2026-09-08). _areas/_instances are
loaded once per site — the picker treats a new list as a site change. *@
<InstancePicker Areas="_areas" Instances="_instances"
SelectedInstanceId="_selectedInstanceId" SelectedInstanceIdChanged="OnInstancePickedAsync"
Disabled="@(_running || _selectedSiteId == 0)" DataTestPrefix="flow-instance" />
</div>
<div class="col-md-3">
<label class="form-label form-label-sm">Script</label>
@@ -111,7 +111,17 @@ public partial class FlowDebugger : ComponentBase, IDisposable
private List<ApiMethod> _methods = [];
private List<Site> _sites = [];
/// <summary>
/// The selected site's instances, feeding the <c>InstancePicker</c> alongside
/// <see cref="_areas"/>. The picker compares both by REFERENCE — a new list object is read
/// as "the site changed" and closes its panel — so they are assigned exactly once per site
/// load (<see cref="LoadInstancesAsync"/>) and never rebuilt on a render path.
/// </summary>
private List<Instance> _instances = [];
/// <summary>The selected site's areas; the picker nests them into its tree. See <see cref="_instances"/>.</summary>
private List<Area> _areas = [];
private List<FlowScriptOption> _scripts = [];
private int _selectedMethodId;
@@ -411,9 +421,27 @@ public partial class FlowDebugger : ComponentBase, IDisposable
private async Task LoadInstancesAsync()
{
_instances = _selectedSiteId > 0
? (await TemplateEngineRepository.GetInstancesBySiteIdAsync(_selectedSiteId)).OrderBy(i => i.UniqueName, StringComparer.OrdinalIgnoreCase).ToList()
: [];
if (_selectedSiteId <= 0)
{
_instances = [];
_areas = [];
return;
}
_instances = (await TemplateEngineRepository.GetInstancesBySiteIdAsync(_selectedSiteId))
.OrderBy(i => i.UniqueName, StringComparer.OrdinalIgnoreCase).ToList();
// The picker nests these itself (InstanceTreeBuilder), so order does not matter here.
_areas = (await TemplateEngineRepository.GetAreasBySiteIdAsync(_selectedSiteId)).ToList();
}
/// <summary>
/// The picker raises the id rather than binding a &lt;select&gt;, so the page applies it
/// before running the same change handler the old dropdown used.
/// </summary>
private async Task OnInstancePickedAsync(int id)
{
_selectedInstanceId = id;
await OnInstanceChangedAsync();
}
/// <summary>The instance's scripts, from its flattened configuration (canonical names, effective triggers).</summary>