refactor: rename ScadaLink → ZB.MOM.WW.ScadaBridge (code + projects + namespaces)
Solution + 23 src projects + 26 test projects renamed; folders, csproj, namespaces, and ScadaLinkDbContext/ScadaBridgeDbContext class updated. ActorSystem "scadalink" → "scadabridge", Akka seed-node URLs migrated. SQL roles/logins, LDAP domains, CLI command name, and CLI config dir (~/.scadalink → ~/.scadabridge) also renamed. Build green; 5 Host.Tests fail awaiting SQL login rename in next commit. Pre-existing StaleTagMonitor timing flakes unchanged. Rename script committed at tools/rename-to-scadabridge.sh.
This commit is contained in:
+121
@@ -0,0 +1,121 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Types.Audit;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Pages.Audit;
|
||||
|
||||
/// <summary>
|
||||
/// Code-behind for the execution-chain tree page (Audit Log ParentExecutionId
|
||||
/// feature, Task 10). Route <c>/audit/execution-tree</c>, reached via the Audit
|
||||
/// Log drilldown drawer's "View execution chain" action with
|
||||
/// <c>?executionId={guid}</c>.
|
||||
///
|
||||
/// <para>
|
||||
/// On initialization the page parses <c>?executionId=</c> (lax-parsed, matching
|
||||
/// the Audit Log page's drill-in contract — an absent or unparseable value
|
||||
/// leaves the page in a guidance state and issues NO service call), then asks
|
||||
/// <see cref="ZB.MOM.WW.ScadaBridge.CentralUI.Services.IAuditLogQueryService.GetExecutionTreeAsync"/>
|
||||
/// for the whole chain. The flat <see cref="ExecutionTreeNode"/> list is handed
|
||||
/// to the recursive <c>ExecutionTree</c> component, which assembles + renders
|
||||
/// the tree.
|
||||
/// </para>
|
||||
///
|
||||
/// <para>
|
||||
/// The data path mirrors the Audit Log results grid: the page talks ONLY to the
|
||||
/// CentralUI <c>IAuditLogQueryService</c> facade, never <c>IAuditLogRepository</c>
|
||||
/// directly, so the page can be unit-tested with a substituted service.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public partial class ExecutionTreePage
|
||||
{
|
||||
[Inject] private NavigationManager Navigation { get; set; } = null!;
|
||||
|
||||
// The parsed ?executionId= value, or null when absent / unparseable.
|
||||
private Guid? _executionId;
|
||||
|
||||
// The flat chain returned by the query service; null until the load
|
||||
// completes (or when no id was supplied).
|
||||
private IReadOnlyList<ExecutionTreeNode>? _nodes;
|
||||
|
||||
private bool _loading;
|
||||
private string? _error;
|
||||
|
||||
// Execution-Tree Node Detail Modal feature (Task 4) — state backing the
|
||||
// <ExecutionDetailModal>. A double-click on a tree node sets
|
||||
// _modalExecutionId + flips _modalOpen true; the modal loads that
|
||||
// execution's audit rows on the closed → open transition. _modalOpen is the
|
||||
// visibility gate — _modalExecutionId is left intact across a close (it is
|
||||
// harmless while the modal is hidden and avoids a flicker if reopened).
|
||||
private Guid? _modalExecutionId;
|
||||
private bool _modalOpen;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
_executionId = ParseExecutionId();
|
||||
if (_executionId is null)
|
||||
{
|
||||
// No id — render guidance, do not touch the service.
|
||||
return;
|
||||
}
|
||||
|
||||
await LoadChainAsync(_executionId.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lax-parses <c>?executionId=</c>. Returns null when the param is absent or
|
||||
/// is not a valid <see cref="Guid"/> — the page then shows guidance instead
|
||||
/// of an error, consistent with the Audit Log page's drill-in handling.
|
||||
/// </summary>
|
||||
private Guid? ParseExecutionId()
|
||||
{
|
||||
var uri = Navigation.ToAbsoluteUri(Navigation.Uri);
|
||||
var query = QueryHelpers.ParseQuery(uri.Query);
|
||||
if (query.TryGetValue("executionId", out var values)
|
||||
&& Guid.TryParse(values.ToString(), out var parsed))
|
||||
{
|
||||
return parsed;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task LoadChainAsync(Guid executionId)
|
||||
{
|
||||
_loading = true;
|
||||
_error = null;
|
||||
try
|
||||
{
|
||||
_nodes = await AuditLogQueryService.GetExecutionTreeAsync(executionId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// A transient DB outage degrades this page to an error banner
|
||||
// rather than killing the circuit — the same defensive posture the
|
||||
// Audit Log grid takes around its query.
|
||||
_error = $"Could not load the execution chain: {ex.Message}";
|
||||
_nodes = null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised by <c>ExecutionTree</c> (bubbled up from a node double-click) with
|
||||
/// the activated node's <c>ExecutionId</c>. Opens the
|
||||
/// <c>ExecutionDetailModal</c> for that execution — the modal loads its
|
||||
/// audit rows on the closed → open transition.
|
||||
/// </summary>
|
||||
private void HandleNodeActivated(Guid executionId)
|
||||
{
|
||||
_modalExecutionId = executionId;
|
||||
_modalOpen = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised by <c>ExecutionDetailModal</c> when the user dismisses it. Flips
|
||||
/// the visibility gate closed; <see cref="_modalExecutionId"/> is left as-is.
|
||||
/// </summary>
|
||||
private void HandleModalClose() => _modalOpen = false;
|
||||
}
|
||||
Reference in New Issue
Block a user