feat(m9/T24b): move-data-connection UI dialog + action

This commit is contained in:
Joseph Doherty
2026-06-18 11:45:53 -04:00
parent dbe51e5f25
commit 16cb078cd2
7 changed files with 530 additions and 0 deletions
@@ -42,6 +42,12 @@
<ToastNotification @ref="_toast" />
<MoveDataConnectionDialog @bind-IsVisible="_showMoveDialog"
ConnectionId="_moveConnectionId"
ConnectionName="@_moveConnectionName"
SiteOptions="MoveTargetSiteOptions()"
OnMoved="OnConnectionMoved" />
@if (_loading)
{
<LoadingSpinner IsLoading="true" />
@@ -124,6 +130,12 @@
Edit
</button>
</li>
<li>
<button class="dropdown-item"
@onclick="() => OpenMoveDialog(node.Connection!)">
Move to Site…
</button>
</li>
<li><hr class="dropdown-divider" /></li>
<li>
<button class="dropdown-item text-danger"
@@ -150,6 +162,10 @@
@onclick='() => NavigationManager.NavigateTo($"/design/connections/{node.Connection!.Id}/edit")'>
Edit
</button>
<button class="dropdown-item"
@onclick="() => OpenMoveDialog(node.Connection!)">
Move to Site…
</button>
<div class="dropdown-divider"></div>
<button class="dropdown-item text-danger"
@onclick="() => DeleteConnection(node.Connection!)">
@@ -409,6 +425,38 @@
}
}
// ── M9-T24b: Move connection to another site ──
// The dialog dispatches MoveDataConnectionCommand through the guard-running
// ManagementActor path (IDataConnectionMoveService) — NOT a direct repository
// write — so the server enforces the Designer gate and every move guard. The
// page only opens the dialog, supplies the candidate target sites (the current
// site excluded), and reloads the tree once the move succeeds.
private bool _showMoveDialog;
private int _moveConnectionId;
private int _moveConnectionSiteId;
private string _moveConnectionName = string.Empty;
private void OpenMoveDialog(DataConnection conn)
{
_moveConnectionId = conn.Id;
_moveConnectionSiteId = conn.SiteId;
_moveConnectionName = conn.Name;
_showMoveDialog = true;
}
// Candidate target sites for the move: every site EXCEPT the connection's
// current one. Sourced from the already-loaded tree roots (each root is a site).
private IEnumerable<(int Id, string Label)> MoveTargetSiteOptions() =>
_treeRoots
.Where(r => r.SiteId is int sid && sid != _moveConnectionSiteId)
.Select(r => (r.SiteId!.Value, r.Label));
private async Task OnConnectionMoved()
{
_toast.ShowSuccess($"Connection '{_moveConnectionName}' moved.");
await LoadDataAsync();
}
// M9-T25: enum → Bootstrap badge class. Mirrors the Health dashboard's
// GetConnectionHealthBadge (Components/Pages/Monitoring/Health.razor) so the
// design page surfaces the same colour coding for the same status. Kept as a