From b3b02a8cb6e9f083ec4d22687d0aadb507294aab Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Thu, 21 May 2026 05:08:50 -0400 Subject: [PATCH] fix(centralui): apply status/stuck query-string filters on the Site Calls page --- .../Pages/SiteCalls/SiteCallsReport.razor.cs | 65 +++++++++++++++++ .../Pages/SiteCallsReportPageTests.cs | 73 +++++++++++++++++++ 2 files changed, 138 insertions(+) diff --git a/src/ScadaLink.CentralUI/Components/Pages/SiteCalls/SiteCallsReport.razor.cs b/src/ScadaLink.CentralUI/Components/Pages/SiteCalls/SiteCallsReport.razor.cs index 079c009..c8f0a21 100644 --- a/src/ScadaLink.CentralUI/Components/Pages/SiteCalls/SiteCallsReport.razor.cs +++ b/src/ScadaLink.CentralUI/Components/Pages/SiteCalls/SiteCallsReport.razor.cs @@ -1,3 +1,5 @@ +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.WebUtilities; using Microsoft.Extensions.Logging; using ScadaLink.CentralUI.Components.Shared; using ScadaLink.Commons.Entities.Sites; @@ -26,11 +28,32 @@ namespace ScadaLink.CentralUI.Components.Pages.SiteCalls; /// a relay that never reaches the site is a transient transport condition, surfaced /// to the operator differently from a generic failure. /// +/// +/// +/// Query-string drill-in: the Health-dashboard Site Call KPI tiles deep-link here +/// with ?status=Parked (Parked tile) or ?stuck=true (Stuck tile). On +/// initialization those params seed / +/// BEFORE the first , so the first grid load is already +/// filtered and the filter card controls reflect the seeded values. Parsing is lax +/// — an absent, blank, or unrecognised value is silently dropped and the page loads +/// unfiltered, mirroring AuditLogPage's drill-in convention. +/// /// public partial class SiteCallsReport { private const int PageSize = 50; + [Inject] private NavigationManager Navigation { get; set; } = null!; + + // The Status filter binds. An unrecognised value leaves the filter unset. + var match = ValidStatuses.FirstOrDefault( + s => string.Equals(s, v?.Trim(), StringComparison.OrdinalIgnoreCase)); + if (match is not null) + { + _statusFilter = match; + } + } + + if (query.TryGetValue("stuck", out var stuckValues) + && bool.TryParse(stuckValues.ToString(), out var stuck)) + { + _stuckOnly = stuck; + } + } + /// Re-fetch the current page (Refresh button, and after a relay action). private async Task RefreshAll() { diff --git a/tests/ScadaLink.CentralUI.Tests/Pages/SiteCallsReportPageTests.cs b/tests/ScadaLink.CentralUI.Tests/Pages/SiteCallsReportPageTests.cs index e4fa93d..6dd2852 100644 --- a/tests/ScadaLink.CentralUI.Tests/Pages/SiteCallsReportPageTests.cs +++ b/tests/ScadaLink.CentralUI.Tests/Pages/SiteCallsReportPageTests.cs @@ -1,7 +1,9 @@ using System.Security.Claims; using Akka.Actor; using Bunit; +using Bunit.TestDoubles; using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Authorization; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging.Abstractions; @@ -411,6 +413,77 @@ public class SiteCallsReportPageTests : BunitContext }); } + // ───────────────────────────────────────────────────────────────────────── + // Query-string drill-in — the Health-dashboard Site Call KPI tiles deep-link + // here with ?status=Parked (Parked tile) and ?stuck=true (Stuck tile). The + // params must seed the filter BEFORE the first query so the initial grid load + // is already filtered, and the filter card controls must reflect the values. + // ───────────────────────────────────────────────────────────────────────── + + [Fact] + public void NavigateWithStatusParkedParam_LoadsGridPreFilteredToParked() + { + // The Parked KPI tile emits ?status=Parked — set the URI before render. + var nav = (BunitNavigationManager)Services.GetRequiredService(); + nav.NavigateTo("/site-calls/report?status=Parked"); + + var cut = Render(); + + cut.WaitForAssertion(() => + { + // The first (and only) query the page issues carries the Parked + // status filter — the grid load is pre-filtered, not unfiltered. + Assert.Single(_queryRequests); + Assert.Equal("Parked", _queryRequests[0].StatusFilter); + + // The Status