feat(ui): AuditResultsGrid + AuditLogQueryService with keyset paging (#23 M7)
Adds the results grid + query facade for the central Audit Log page (#23 M7-T3): * IAuditLogQueryService / AuditLogQueryService — CentralUI facade over IAuditLogRepository.QueryAsync so the grid can be tested with a stubbed query source. Default page size is 100; callers can override per call. * AuditResultsGrid.razor + .razor.cs — Blazor Server component (Bootstrap only, no third-party UI libs). Renders the 10 columns from Component-AuditLog.md §10 (OccurredAtUtc, Site, Channel, Kind, Status, Target, Actor, DurationMs, HttpStatus, ErrorMessage). Keyset-paged via the last visible row's (OccurredAtUtc, EventId) as the cursor; Next-page button disabled when the current page is short (no count query). Row clicks emit OnRowSelected(AuditEvent) for Bundle C's drilldown drawer. Status badges are colour-coded (Delivered=green; Failed/Parked/Discarded =red; other=gray). Error messages truncated to 80 chars with full text on hover. * Column model framework: a ColumnOrder [Parameter] reorders columns by stable string keys; unknown keys are dropped. M7 scope decision (in the class doc): the framework is in place but drag-reorder / resize UX is not implemented — M7.x can add persisted-per-user reordering without rewriting the column model. * AuditLogPage wired: hosts AuditFilterBar + AuditResultsGrid, threads the filter through and stubs OnRowSelected for Bundle C. * AuditLogQueryService registered as scoped in AddCentralUI. * Tests: 4 grid bUnit tests (10 columns rendered, next-page cursor carries last row, row click raises callback, badge classes for Failed vs Delivered), 2 service tests (filter+paging pass-through, default page size of 100). AuditLogPageScaffoldTests updated to provide the new ISiteRepository + IAuditLogQueryService stubs the page now resolves.
This commit is contained in:
@@ -1,12 +1,32 @@
|
||||
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-T1). The Bundle A
|
||||
/// scaffold has no behaviour — the filter bar and results grid arrive in
|
||||
/// Bundle B (M7-T2..M7-T7). Keeping the partial class in place now lets
|
||||
/// later bundles add injected services and event handlers without
|
||||
/// touching the route or page-title markup.
|
||||
/// 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 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)
|
||||
{
|
||||
// Reserved for Bundle C (drilldown drawer). Intentionally left empty: the
|
||||
// grid still raises the event, but we do nothing with it yet.
|
||||
_ = row;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user