fix(adminui): stale-open guards, validation summaries, key-delete confirm, error boundary (#604)
Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
@rendermode RenderMode.InteractiveServer
|
||||
@using ZB.MOM.WW.OtOpcUa.Configuration.Entities
|
||||
@using ZB.MOM.WW.OtOpcUa.Core.Authorization
|
||||
@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Raw
|
||||
@inject IApiKeyAdminService Keys
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
@@ -104,7 +105,7 @@
|
||||
@(k.Enabled ? "Revoke" : "Re-enable")
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-danger"
|
||||
@onclick="() => DeleteAsync(k.ApiKeyId)" disabled="@_busy">Delete</button>
|
||||
@onclick="() => RequestDelete(k)" disabled="@_busy">Delete</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -114,6 +115,9 @@
|
||||
}
|
||||
</section>
|
||||
|
||||
<RawConfirmDialog @bind-Visible="_confirmDeleteVisible" Title="Delete API key"
|
||||
Message="@_confirmDeleteMessage" OnConfirm="ConfirmDeleteAsync" />
|
||||
|
||||
@code {
|
||||
private IReadOnlyList<ApiKey>? _keys;
|
||||
private string _newName = "";
|
||||
@@ -123,6 +127,12 @@
|
||||
private string? _error;
|
||||
private bool _busy;
|
||||
|
||||
// Delete is irreversible (the key stops authenticating at once), so it goes through a confirm dialog
|
||||
// that names the key rather than firing from the row button.
|
||||
private bool _confirmDeleteVisible;
|
||||
private string? _confirmDeleteId;
|
||||
private string _confirmDeleteMessage = "";
|
||||
|
||||
protected override async Task OnInitializedAsync() => await ReloadAsync();
|
||||
|
||||
private async Task ReloadAsync()
|
||||
@@ -183,6 +193,19 @@
|
||||
finally { _busy = false; }
|
||||
}
|
||||
|
||||
private void RequestDelete(ApiKey key)
|
||||
{
|
||||
_confirmDeleteId = key.ApiKeyId;
|
||||
_confirmDeleteMessage =
|
||||
$"Permanently delete API key '{key.Name}' ({key.ApiKeyId})? Clients using it will stop authenticating immediately. This cannot be undone.";
|
||||
_confirmDeleteVisible = true;
|
||||
}
|
||||
|
||||
private async Task ConfirmDeleteAsync()
|
||||
{
|
||||
if (_confirmDeleteId is { } id) { await DeleteAsync(id); }
|
||||
}
|
||||
|
||||
private async Task DeleteAsync(string apiKeyId)
|
||||
{
|
||||
_busy = true;
|
||||
|
||||
@@ -34,6 +34,7 @@ else
|
||||
{
|
||||
<EditForm Model="_form" OnValidSubmit="SubmitAsync" FormName="clusterEdit">
|
||||
<DataAnnotationsValidator />
|
||||
<ValidationSummary class="alert alert-danger py-2 px-3" />
|
||||
<section class="panel rise" style="animation-delay:.02s">
|
||||
<div class="panel-head">Identity</div>
|
||||
<div style="padding:1rem">
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
<EditForm Model="_form" OnValidSubmit="SubmitAsync" FormName="newCluster">
|
||||
<DataAnnotationsValidator />
|
||||
<ValidationSummary class="alert alert-danger py-2 px-3" />
|
||||
<section class="panel rise" style="animation-delay:.02s">
|
||||
<div class="panel-head">Identity</div>
|
||||
<div style="padding:1rem">
|
||||
|
||||
@@ -31,6 +31,7 @@ else
|
||||
{
|
||||
<EditForm Model="_form" OnValidSubmit="SubmitAsync" FormName="scriptEdit">
|
||||
<DataAnnotationsValidator />
|
||||
<ValidationSummary class="alert alert-danger py-2 px-3" />
|
||||
<section class="panel rise">
|
||||
<div class="panel-head">Identity</div>
|
||||
<div style="padding:1rem">
|
||||
|
||||
Reference in New Issue
Block a user