@* Sql address picker (read-only v1):
1. Manual entry (ALWAYS available): pick the model (KeyValue / WideRow), then fill the
table + key/row-selector fields by hand. An operator without DriverOperator, or browsing a
server the AdminUI can't reach, authors a tag entirely from these fields.
2. (DriverOperator-gated) Live schema browse: schema → table → column tree on the left, the
picked column's type in the attribute side-panel on the right. Clicking a column leaf prefills
`table`, the value/column field, and the inferred `type`.
The picker's OUTPUT (CurrentAddress) is the composed per-tag `TagConfig` JSON blob — exactly the
shape SqlEquipmentTagParser.TryParse reads (design §5.2 / §5.3). Field names + the string `model`/
`type` enums are matched to the parser precisely; a mismatch would author fine and never read.
Credential hygiene: the optional ad-hoc connection string is SESSION-ONLY. It is merged into the
JSON handed to BrowserService.OpenAsync for THIS browse only and is NEVER written into the composed
TagConfig blob nor back into the driver config — there is no code path here that persists it. *@
@implements IAsyncDisposable
@using System.Text.Json.Nodes
@using ZB.MOM.WW.OtOpcUa.AdminUI.Browsing
@using ZB.MOM.WW.OtOpcUa.Commons.Browsing
@using ZB.MOM.WW.OtOpcUa.Core.Abstractions
@using ZB.MOM.WW.OtOpcUa.Driver.Sql
@using ZB.MOM.WW.OtOpcUa.Driver.Sql.Browser
@inject IBrowserSessionService BrowserService
@inject AuthenticationStateProvider AuthState
@inject IAuthorizationService AuthorizationService
KeyValue: one row per key. WideRow: many columns of one selected row.
Schema-qualified, e.g. dbo.TagValues.
Blank ⇒ inferred from the column.
@if (_model == "KeyValue")
{
Bound as a parameter — never interpolated.
}
else
{
The column this tag reads from the selected row.
@if (_selectorMode == "Where")
{
}
else
{
}
}
Source-timestamp column; blank ⇒ the driver stamps the poll time.
@if (_canOperate)
{
Leave blank to browse via the driver's connectionStringRef (resolved from
the AdminUI host's Sql__ConnectionStrings__<ref> env var). Paste a
literal only for a one-off browse — it is used for this session and never persisted.
@if (_attrsLoading)
{
}
else if (_attrsError is not null)
{
@_attrsError
}
else if (_attrs is null)
{
Pick a column leaf.
}
else if (_attrs.Count == 0)
{
Column no longer present.
}
else
{
@foreach (var a in _attrs)
{