@using ZB.MOM.WW.ScadaBridge.Commons.Types
@using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums
@*
M10 residual: body component for the template "Add / Edit Attribute" dialog
hosted by IDialogService.ShowAsync. Renders ONLY the form fields + action
buttons inside the host's .modal-body; the host owns the backdrop, header,
focus trap, Escape, and focus restoration.
Mirrors MoveDataConnectionDialog: the save round-trip runs from inside the
body, a failure is shown INLINE and the dialog STAYS OPEN, and success closes
with Close(true) so the page toasts and reloads. The actual persistence stays
on the page (TemplateEdit owns TemplateService + the inherited-member rules)
and is reached through the OnSaveAsync delegate, which returns null on success
or the error message to display.
*@
@if (Editing)
{
Data type is fixed once the attribute is created.
}
@if (_dataType == DataType.List)
{
@* List VALUE stays editable when editing; only DataType/ElementDataType are server-fixed (ShowElementType hides the type select on edit). *@
}
else
{
}
@if (_error != null)
{
@_error
}
@code {
/// Host-supplied context: Close(true) on a successful save, Cancel on dismiss.
[Parameter, EditorRequired] public DialogContext Context { get; set; } = default!;
/// True when editing an existing attribute (name + data type become read-only).
[Parameter] public bool Editing { get; set; }
[Parameter] public string InitialName { get; set; } = string.Empty;
[Parameter] public string? InitialValue { get; set; }
[Parameter] public DataType InitialDataType { get; set; }
[Parameter] public DataType InitialElementDataType { get; set; } = DataType.String;
[Parameter] public IReadOnlyList InitialListRows { get; set; } = Array.Empty();
[Parameter] public bool InitialIsLocked { get; set; }
[Parameter] public string? InitialDataSourceRef { get; set; }
///
/// Persists the draft. Returns null on success (the dialog closes with
/// true) or the message to render inline, leaving the dialog open.
///
[Parameter, EditorRequired] public Func> OnSaveAsync { get; set; } = default!;
private string _name = string.Empty;
private string? _value;
private DataType _dataType;
private DataType _elementDataType = DataType.String;
private List _listRows = new();
private bool _isLocked;
private string? _dataSourceRef;
private string? _error;
private bool _busy;
protected override void OnInitialized()
{
_name = InitialName;
_value = InitialValue;
_dataType = InitialDataType;
_elementDataType = InitialElementDataType;
_listRows = InitialListRows.ToList();
_isLocked = InitialIsLocked;
_dataSourceRef = InitialDataSourceRef;
}
// Switching the data type clears stale list state so a List ⇄ scalar
// toggle never carries the other mode's value into the submit.
private void OnDataTypeChanged(ChangeEventArgs e)
{
if (!Enum.TryParse((string?)e.Value, out var dt) || dt == _dataType) return;
_dataType = dt;
if (dt == DataType.List)
{
_value = null;
_listRows = new();
if (!AttributeValueCodec.IsValidElementType(_elementDataType))
_elementDataType = DataType.String;
}
else
{
_listRows = new();
}
}
private async Task Submit()
{
if (_busy) return;
_error = null;
if (string.IsNullOrWhiteSpace(_name)) { _error = "Name is required."; return; }
_busy = true;
try
{
var draft = new AttributeDraft(
_name,
_dataType,
_elementDataType,
_listRows.ToList(),
_value,
_dataSourceRef,
_isLocked);
var error = await OnSaveAsync(draft);
if (error == null)
{
Context.Close(true);
}
else
{
_error = error;
}
}
finally
{
_busy = false;
}
}
///
/// The authored attribute as submitted. The page resolves the stored value
/// (list encoding + validation for ) and performs
/// the add/update, so this record carries the raw form state only.
///
/// Attribute name (ignored on edit — the stored name is fixed).
/// Selected data type (fixed on edit).
/// Element scalar type; meaningful only for a List attribute.
/// Per-element string rows; meaningful only for a List attribute.
/// Scalar value; meaningful only for a non-List attribute.
/// Tag path binding, or null.
/// Whether instances may override the attribute.
public sealed record AttributeDraft(
string Name,
DataType DataType,
DataType ElementDataType,
List ListRows,
string? Value,
string? DataSourceRef,
bool IsLocked);
}