feat(centralui): Create saves bindings (upsert) and lands on Configure with a created/bound/bindError notice
Claude-Session: https://claude.ai/code/session_01G2GHPnbbKGvyyfbr2XBRVH
This commit is contained in:
+29
@@ -81,6 +81,28 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@* One-shot notice for an instance that just arrived from the Create page
|
||||||
|
(design 2026-08-21). Query-string only — nothing is persisted, so it
|
||||||
|
disappears on any later visit. *@
|
||||||
|
@if (Created == 1)
|
||||||
|
{
|
||||||
|
<div class="alert @(BindError is null ? "alert-success" : "alert-warning") py-2 small" data-test="configure-created-notice">
|
||||||
|
Instance created.
|
||||||
|
@if (BindError is not null)
|
||||||
|
{
|
||||||
|
<text>Bindings were NOT saved: @BindError — bind the groups below.</text>
|
||||||
|
}
|
||||||
|
else if (Bound is > 0)
|
||||||
|
{
|
||||||
|
<text>@Bound binding(s) saved. Test Bindings, then Deploy.</text>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<text>Bind the groups below, then Deploy.</text>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
@* Connection Bindings — grouped by module (design 2026-08-20). Rows come
|
@* Connection Bindings — grouped by module (design 2026-08-20). Rows come
|
||||||
from the flattened configuration so composed module members appear;
|
from the flattened configuration so composed module members appear;
|
||||||
each group header carries a connection + Object apply that rewrites
|
each group header carries a connection + Object apply that rewrites
|
||||||
@@ -710,6 +732,13 @@
|
|||||||
@code {
|
@code {
|
||||||
[Parameter] public int Id { get; set; }
|
[Parameter] public int Id { get; set; }
|
||||||
|
|
||||||
|
// Set by the Create Instance page's post-create redirect (design 2026-08-21):
|
||||||
|
// Created=1 always, then either the count of bindings saved or the error that
|
||||||
|
// stopped them being saved. Read-only display — never persisted.
|
||||||
|
[SupplyParameterFromQuery] public int? Created { get; set; }
|
||||||
|
[SupplyParameterFromQuery] public int? Bound { get; set; }
|
||||||
|
[SupplyParameterFromQuery] public string? BindError { get; set; }
|
||||||
|
|
||||||
private Instance? _instance;
|
private Instance? _instance;
|
||||||
private string _templateName = "";
|
private string _templateName = "";
|
||||||
private string _siteName = "";
|
private string _siteName = "";
|
||||||
|
|||||||
+40
-6
@@ -293,26 +293,60 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string user;
|
||||||
|
int id;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var user = await GetCurrentUserAsync();
|
user = await GetCurrentUserAsync();
|
||||||
var result = await InstanceService.CreateInstanceAsync(
|
var result = await InstanceService.CreateInstanceAsync(
|
||||||
_createName.Trim(), _createTemplateId, _createSiteId, _createAreaId == 0 ? null : _createAreaId, user);
|
_createName.Trim(), _createTemplateId, _createSiteId, _createAreaId == 0 ? null : _createAreaId, user);
|
||||||
if (result.IsSuccess)
|
if (result.IsFailure)
|
||||||
{
|
|
||||||
NavigationManager.NavigateTo("/deployment/topology");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
_formError = result.Error;
|
_formError = result.Error;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
id = result.Value.Id;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_formError = $"Create failed: {ex.Message}";
|
_formError = $"Create failed: {ex.Message}";
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// From here the instance EXISTS. Whatever the binding save does, land on
|
||||||
|
// Configure rather than leaving the operator on a stale create form —
|
||||||
|
// carrying any binding error in the query so it is visible there.
|
||||||
|
var bindings = _skipBindings || _previewError is not null
|
||||||
|
? (IReadOnlyList<ConnectionBinding>)Array.Empty<ConnectionBinding>()
|
||||||
|
: CreateBindingPlanner.BuildBindings(_groups, _inputs);
|
||||||
|
|
||||||
|
if (bindings.Count == 0)
|
||||||
|
{
|
||||||
|
NavigationManager.NavigateTo($"/deployment/instances/{id}/configure?created=1");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string? bindError = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var bind = await InstanceService.SetConnectionBindingsAsync(id, bindings, user);
|
||||||
|
if (bind.IsFailure) bindError = bind.Error;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// Network / actor timeout AFTER the instance was created.
|
||||||
|
bindError = ex.Message;
|
||||||
|
}
|
||||||
|
|
||||||
|
var query = bindError is null
|
||||||
|
? $"created=1&bound={bindings.Count}"
|
||||||
|
: $"created=1&bindError={Uri.EscapeDataString(Truncate(bindError, 300))}";
|
||||||
|
NavigationManager.NavigateTo($"/deployment/instances/{id}/configure?{query}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Keeps a failure message short enough to ride in the query string.</summary>
|
||||||
|
private static string Truncate(string s, int n) => s.Length <= n ? s : s[..n] + "…";
|
||||||
|
|
||||||
private void GoBack() => NavigationManager.NavigateTo("/deployment/topology");
|
private void GoBack() => NavigationManager.NavigateTo("/deployment/topology");
|
||||||
|
|
||||||
// CentralUI-024: delegates to the shared helper so the claim type stays
|
// CentralUI-024: delegates to the shared helper so the claim type stays
|
||||||
|
|||||||
Reference in New Issue
Block a user