feat(central-ui): InstancePicker — combobox over the site's area tree
A shared Bootstrap-only combobox that replaces the flat instance <select> on Flow Debugger and Debug View (design docs/plans/2026-09-08-instance-picker-design.md, plan task 2): a text field over a dropdown panel hosting TreeView across the InstanceTreeBuilder forest, every area collapsed on open. Clicking an area row toggles it, clicking an instance row selects it, closes the panel and raises SelectedInstanceIdChanged. Outside clicks close through a transparent fixed backdrop — the same pattern TreeView uses for its context menu, so no JavaScript. A site change (new Areas/Instances references) closes the panel and clears the field when the selection no longer resolves; a parent-driven SelectedInstanceId change re-derives the field text while closed. ItemLabel customises row and field text (Debug View wants a "(State)" suffix) while search still matches UniqueName. TreeView gains one additive public ToggleExpanded(key) — the chevron's existing private toggle, exposed so a consumer whose own NodeContent owns the label click can toggle the branch. Search filtering and keyboard handling land in task 3; _filter/Rebuild() are in place for them. Claude-Session: https://claude.ai/code/session_01NcMG6xXdsJbmD2wYAgkK29
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
@*
|
||||
Instance Picker — a combobox whose dropdown is the site's area tree (design
|
||||
2026-09-08). The field shows the selected instance; the panel hosts the shared
|
||||
TreeView over InstanceTreeBuilder's forest with every area collapsed. Clicking an
|
||||
area row toggles it, clicking an instance row selects it and closes the panel.
|
||||
Bootstrap only, no JavaScript: the transparent fixed backdrop closes the panel on
|
||||
an outside click, the same pattern TreeView uses for its context menu.
|
||||
*@
|
||||
@namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Shared
|
||||
@using ZB.MOM.WW.ScadaBridge.Commons.Entities.Instances
|
||||
|
||||
<div class="ip-wrap position-relative" data-test="@($"{DataTestPrefix}-picker")">
|
||||
<div class="input-group input-group-sm">
|
||||
<input type="text" class="form-control" role="combobox" autocomplete="off"
|
||||
id="@_inputId" aria-autocomplete="list" aria-haspopup="tree"
|
||||
aria-expanded="@(_open ? "true" : "false")" aria-controls="@_panelId"
|
||||
placeholder="@Placeholder" disabled="@Disabled"
|
||||
data-test="@($"{DataTestPrefix}-input")"
|
||||
value="@_text" @onfocus="Open" />
|
||||
<button type="button" class="btn btn-outline-secondary" tabindex="-1" aria-label="Browse instances"
|
||||
disabled="@Disabled" data-test="@($"{DataTestPrefix}-toggle")" @onclick="Toggle">
|
||||
<i class="bi @(_open ? "bi-chevron-up" : "bi-chevron-down")"></i>
|
||||
</button>
|
||||
</div>
|
||||
@if (_open)
|
||||
{
|
||||
<div class="ip-backdrop" data-test="@($"{DataTestPrefix}-backdrop")" @onclick="Close"></div>
|
||||
<div class="ip-panel border rounded bg-body shadow-sm" id="@_panelId" data-test="@($"{DataTestPrefix}-panel")">
|
||||
<TreeView @ref="_tree" TItem="InstanceTreeNode" Items="_roots"
|
||||
ChildrenSelector="n => n.Children" HasChildrenSelector="n => n.HasChildren"
|
||||
KeySelector="n => n.Key" IndentPx="16">
|
||||
<NodeContent Context="node">
|
||||
<span class="tv-glyph"><i class="bi @(node.IsInstance ? "bi-box" : "bi-diagram-3")"></i></span>
|
||||
<span class="tv-label @(node.IsInstance ? "ip-instance" : "ip-area")" title="@node.Label"
|
||||
data-test="@($"{DataTestPrefix}-row")" data-instance-id="@(node.Instance?.Id)"
|
||||
@onclick="() => OnRowClickAsync(node)">@RowLabel(node)</span>
|
||||
</NodeContent>
|
||||
<EmptyContent><span class="text-muted fst-italic small px-2">@(_hasFilter ? "No instances match." : "No instances at this site.")</span></EmptyContent>
|
||||
</TreeView>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
Reference in New Issue
Block a user