Files
lmxopcua/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Raw/RawNameDialog.razor
T
Joseph Doherty aef9ef8452 feat(adminui): B2 Wave-B integration — wire real /raw modals + dialogs + refresh
Replace RawTree's 22 stub handlers with the real Wave-B modals and 3 new
small dialogs, plus post-mutation subtree refresh:

- New dialogs: RawNameDialog (create/rename, RawPaths.ValidateSegment inline),
  RawConfirmDialog (deletes), RawDriverTypeDialog (New driver type+name picker,
  incl. Calculation).
- Configure driver/device -> DriverConfigModal/DeviceModal (edit); New device ->
  DeviceModal (create); Edit tag -> RawTagModal; Manual entry / CSV import/export
  -> the Raw*Modal surfaces; New folder/tag-group/group + New driver + Rename +
  Delete + Toggle -> IRawTreeService directly via the dialogs.
- Refresh: reload the container after create-under, the parent after item-level
  ops (parent found by searching the loaded tree; robust, non-throwing).
- Rename warnings + blocked-delete errors surfaced via the repurposed RawStubModal
  message surface. Browse device stays a placeholder (Wave C). Driver-level
  'Test connect' menu item removed (test-connect now lives on the device modal).

Claude-Session: https://claude.ai/code/session_01LVneM3eh1UtJxEisFXgmox
2026-07-16 03:38:32 -04:00

89 lines
3.5 KiB
Plaintext

@* Reusable name-input dialog for the /raw create + rename operations (New folder / New tag-group /
New group / Rename folder-driver-device-tag-group). Inline-validates the input as a RawPath segment
(RawPaths.ValidateSegment) before raising OnSubmit; a valid submit self-closes the dialog and the
caller runs the create/rename service call + surfaces any server-side error/warnings. Markup mirrors
the other /raw modal shells (RawStubModal). *@
@using ZB.MOM.WW.OtOpcUa.Commons.Types
@if (Visible)
{
<div class="modal-backdrop fade show" style="display:block"></div>
<div class="modal fade show" tabindex="-1" role="dialog" style="display:block">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">@Title</h5>
<button type="button" class="btn-close" aria-label="Close" @onclick="Cancel"></button>
</div>
<div class="modal-body">
<label class="form-label" for="raw-name-input">Name</label>
<input id="raw-name-input" class="form-control form-control-sm mono"
@bind="_value" @bind:event="oninput" @onkeydown="OnKeyDown"
placeholder="segment-name" />
<div class="form-text">A RawPath segment — no '/', no leading or trailing spaces.</div>
@if (_error is not null)
{
<div class="text-danger small mt-1">@_error</div>
}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary" @onclick="Cancel">Cancel</button>
<button type="button" class="btn btn-primary" @onclick="Submit">OK</button>
</div>
</div>
</div>
</div>
}
@code {
/// <summary>Whether the dialog is shown (supports <c>@bind-Visible</c>).</summary>
[Parameter] public bool Visible { get; set; }
/// <summary>Two-way visibility callback.</summary>
[Parameter] public EventCallback<bool> VisibleChanged { get; set; }
/// <summary>The dialog title (e.g. "New folder", "Rename driver").</summary>
[Parameter] public string Title { get; set; } = "Name";
/// <summary>The initial value seeded into the input on open (blank for create, current name for rename).</summary>
[Parameter] public string Value { get; set; } = "";
/// <summary>Raised with the validated name when the operator confirms. The dialog self-closes after.</summary>
[Parameter] public EventCallback<string> OnSubmit { get; set; }
private string _value = "";
private string? _error;
private bool _open; // seed the input once per open; preserve typing across unrelated re-renders
protected override void OnParametersSet()
{
if (!Visible) { _open = false; return; }
if (_open) { return; }
_open = true;
_value = Value ?? "";
_error = null;
}
private async Task Submit()
{
var err = RawPaths.ValidateSegment(_value);
if (err is not null) { _error = err; return; }
await OnSubmit.InvokeAsync(_value);
await Close();
}
private async Task OnKeyDown(KeyboardEventArgs e)
{
if (e.Key == "Enter") { await Submit(); }
}
private Task Cancel() => Close();
private async Task Close()
{
Visible = false;
_open = false;
await VisibleChanged.InvokeAsync(false);
}
}