Files
lmxopcua/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Raw/RawConfirmDialog.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

74 lines
2.6 KiB
Plaintext

@* Reusable confirm dialog for the /raw destructive operations (delete folder / driver / device /
tag-group / tag). Raises OnConfirm when the operator confirms; the caller runs the delete service
call and surfaces any UnsMutationResult.Error (a blocked delete names its blocker) via a follow-up
message. Markup mirrors the other /raw modal shells. *@
@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">
<p class="mb-0">@Message</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary" @onclick="Cancel" disabled="@_busy">Cancel</button>
<button type="button" class="btn btn-danger" @onclick="Confirm" disabled="@_busy">
@if (_busy) { <span class="spinner-border spinner-border-sm me-1"></span> }
@ConfirmLabel
</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. "Delete driver").</summary>
[Parameter] public string Title { get; set; } = "Confirm";
/// <summary>The confirmation body message.</summary>
[Parameter] public string Message { get; set; } = "";
/// <summary>The confirm-button label.</summary>
[Parameter] public string ConfirmLabel { get; set; } = "Delete";
/// <summary>Raised when the operator confirms. The dialog awaits it, then self-closes.</summary>
[Parameter] public EventCallback OnConfirm { get; set; }
private bool _busy;
private async Task Confirm()
{
_busy = true;
try
{
await OnConfirm.InvokeAsync();
}
finally
{
_busy = false;
}
await Close();
}
private Task Cancel() => Close();
private async Task Close()
{
Visible = false;
await VisibleChanged.InvokeAsync(false);
}
}