88 lines
3.0 KiB
Plaintext
88 lines
3.0 KiB
Plaintext
@using ZB.MOM.WW.ScadaBridge.CentralUI.Services
|
|
@inject IDataConnectionMoveService MoveService
|
|
|
|
@*
|
|
M9-T24b / T33b: body component for the "Move data connection" dialog hosted by
|
|
IDialogService.ShowAsync. Renders ONLY the site picker + action buttons inside
|
|
the host's .modal-body; the host owns the backdrop, header, and focus trap.
|
|
|
|
The body still injects IDataConnectionMoveService and dispatches the
|
|
MoveDataConnectionCommand through the guard-running ManagementActor path (NOT a
|
|
direct repository write) so the server's Designer gate and every move guard run.
|
|
A guard error is shown inline and the dialog STAYS OPEN; success closes the
|
|
dialog with Close(true) so the parent reloads the tree. Cancel resolves to false.
|
|
*@
|
|
@if (SiteOptions.Any())
|
|
{
|
|
<select class="form-select form-select-sm" @bind="_targetSiteId">
|
|
@foreach (var opt in SiteOptions)
|
|
{
|
|
<option value="@opt.Id">@opt.Label</option>
|
|
}
|
|
</select>
|
|
}
|
|
else
|
|
{
|
|
<div class="text-muted small">No other site is available to move this connection to.</div>
|
|
}
|
|
@if (!string.IsNullOrEmpty(_error))
|
|
{
|
|
<div class="text-danger small mt-2" data-test="move-connection-error">@_error</div>
|
|
}
|
|
|
|
<div class="modal-footer px-0 pb-0 mt-3">
|
|
<button class="btn btn-outline-secondary btn-sm" @onclick="() => Context.Cancel()" disabled="@_busy">Cancel</button>
|
|
<button class="btn btn-primary btn-sm" @onclick="Submit"
|
|
disabled="@(_busy || !SiteOptions.Any())">Move</button>
|
|
</div>
|
|
|
|
@code {
|
|
/// <summary>Host-supplied context: Close(true) on a successful move, Cancel on dismiss.</summary>
|
|
[Parameter] public DialogContext<bool> Context { get; set; } = default!;
|
|
[Parameter] public int ConnectionId { get; set; }
|
|
[Parameter] public string ConnectionName { get; set; } = string.Empty;
|
|
[Parameter] public IEnumerable<(int Id, string Label)> SiteOptions { get; set; } = Array.Empty<(int, string)>();
|
|
|
|
private int? _targetSiteId;
|
|
private string? _error;
|
|
private bool _busy;
|
|
|
|
protected override void OnInitialized()
|
|
{
|
|
// Default the picker to the first candidate site.
|
|
_targetSiteId = SiteOptions.Select(o => (int?)o.Id).FirstOrDefault();
|
|
}
|
|
|
|
private async Task Submit()
|
|
{
|
|
if (_targetSiteId is not int target || _busy) return;
|
|
|
|
_busy = true;
|
|
_error = null;
|
|
try
|
|
{
|
|
var result = await MoveService.MoveAsync(ConnectionId, target);
|
|
|
|
if (result.Success)
|
|
{
|
|
// Success closes the dialog; the parent's post-ShowAsync block toasts
|
|
// and reloads the tree.
|
|
Context.Close(true);
|
|
}
|
|
else
|
|
{
|
|
// Surface the server guard error inline; keep the dialog open.
|
|
_error = result.Error ?? "Move failed.";
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_error = $"Move failed: {ex.Message}";
|
|
}
|
|
finally
|
|
{
|
|
_busy = false;
|
|
}
|
|
}
|
|
}
|