fix(centralui): marshal Audit Log LocationChanged handler through InvokeAsync

Code-review follow-ups on the same-page drill-in fix (3f1c0e5):
- Wrap HandleLocationChanged's body in InvokeAsync — LocationChanged can
  fire off the renderer's synchronization context.
- Document that a paramless /audit/log navigation intentionally preserves
  the last applied filter (drill-ins always carry query params).
This commit is contained in:
Joseph Doherty
2026-05-21 20:35:20 -04:00
parent 3f1c0e5018
commit afd81c32ef

View File

@@ -66,14 +66,19 @@ public partial class AuditLogPage : IDisposable
/// navigates to <c>/audit/log?executionId=…</c>). Reassigning /// navigates to <c>/audit/log?executionId=…</c>). Reassigning
/// <see cref="_currentFilter"/> to a fresh instance is what kicks the results /// <see cref="_currentFilter"/> to a fresh instance is what kicks the results
/// grid into reloading; we also close the drawer so the operator sees the /// grid into reloading; we also close the drawer so the operator sees the
/// newly filtered grid, and call <see cref="ComponentBase.StateHasChanged"/> /// newly filtered grid. The body is marshalled through
/// because this fires outside the normal render lifecycle. /// <see cref="ComponentBase.InvokeAsync(Action)"/> because
/// <see cref="NavigationManager.LocationChanged"/> can fire off the renderer's
/// synchronization context.
/// </summary> /// </summary>
private void HandleLocationChanged(object? sender, LocationChangedEventArgs e) private void HandleLocationChanged(object? sender, LocationChangedEventArgs e)
{ {
ApplyQueryStringFilters(); _ = InvokeAsync(() =>
_drawerOpen = false; {
StateHasChanged(); ApplyQueryStringFilters();
_drawerOpen = false;
StateHasChanged();
});
} }
public void Dispose() public void Dispose()
@@ -86,6 +91,10 @@ public partial class AuditLogPage : IDisposable
var uri = Navigation.ToAbsoluteUri(Navigation.Uri); var uri = Navigation.ToAbsoluteUri(Navigation.Uri);
var query = QueryHelpers.ParseQuery(uri.Query); var query = QueryHelpers.ParseQuery(uri.Query);
// A paramless navigation (e.g. clicking the "Audit Log" nav link while
// already here) intentionally preserves the last applied filter rather
// than clearing the grid: this method is a drill-in mechanism and every
// drill-in carries query params. The operator clears via the filter bar.
if (query.Count == 0) if (query.Count == 0)
{ {
return; return;