Files
ScadaBridge/src/ScadaLink.CentralUI/Components/Pages/Audit/AuditLogPage.razor.cs
T
Joseph Doherty ae4480e7aa feat(ui): AuditDrilldownDrawer with JSON/SQL render, cURL, drill-back, redaction badges (#23 M7)
Implements Bundle C (M7-T4 through M7-T8) of the Audit Log #23 M7
Central UI work: a right-side off-canvas drawer that opens from
AuditResultsGrid row clicks and renders one AuditEvent in full.

Cohesive single-component delivery:
- Read-only fields stacked (form-layout memory): Channel/Kind, Status,
  HttpStatus, Target, Actor, Source* provenance, CorrelationId,
  OccurredAtUtc, IngestedAtUtc, DurationMs.
- Channel-aware body renderer: DbOutbound {sql, parameters} payloads
  render a code-block with CSS-only .language-sql class plus a
  parameter <dl>; other channels JSON-pretty-print when parseable and
  fall back to verbatim <pre>.
- Redaction badges on Request/Response when the body contains the
  <redacted> or <redacted: redactor error> sentinels.
- Copy-as-cURL (API channels only) builds a curl command from Target
  + optional {method, headers, body} RequestSummary JSON and writes
  it via navigator.clipboard.writeText.
- Show-all-events drill-back navigates to /audit/log?correlationId={id}
  when the event carries a CorrelationId.
- Close button + backdrop-click both raise OnClose.

AuditLogPage wires Event/IsOpen/OnClose; row clicks now open the
drawer (HandleRowSelected pins _selectedEvent + _drawerOpen=true).

11 bUnit tests cover field rendering, JSON pretty-print, verbatim
fallback, SQL block, conditional buttons, redaction badges,
navigation drill-back, and clipboard interop. No third-party UI
libraries: Bootstrap offcanvas + scoped razor.css only.
2026-05-20 20:13:33 -04:00

44 lines
1.6 KiB
C#

using ScadaLink.Commons.Entities.Audit;
using ScadaLink.Commons.Types.Audit;
namespace ScadaLink.CentralUI.Components.Pages.Audit;
/// <summary>
/// Code-behind for the central Audit Log page (#23 M7). Bundle B (M7-T2 + M7-T3)
/// wires up <c>AuditFilterBar</c> and <c>AuditResultsGrid</c>: the page owns the
/// active <see cref="AuditLogQueryFilter"/> and re-pushes a fresh instance to the
/// grid on every Apply (the grid uses reference identity as its "reload"
/// trigger). Row clicks land in <see cref="HandleRowSelected"/> — Bundle C wires
/// this to the drilldown drawer; for now it is a no-op seam so test stubs do
/// not error.
/// </summary>
public partial class AuditLogPage
{
private AuditLogQueryFilter? _currentFilter;
private AuditEvent? _selectedEvent;
private bool _drawerOpen;
private void HandleFilterChanged(AuditLogQueryFilter filter)
{
// Always reassign — the grid keys reloads on reference change, so even a
// chip-for-chip identical filter must allocate a fresh instance.
_currentFilter = filter;
}
private void HandleRowSelected(AuditEvent row)
{
// Bundle C: a grid row click hands us the full AuditEvent. We pin it as
// the selected row and open the drilldown drawer — the drawer is fully
// presentational so we do not need to refetch the row.
_selectedEvent = row;
_drawerOpen = true;
}
private void HandleDrawerClose()
{
// We deliberately keep _selectedEvent set so re-opening (e.g. via the
// grid) shows the same row instantly without a re-render flicker.
_drawerOpen = false;
}
}