From e41c32d72bf5b0e9adeefb30ecd6468fc9ada565 Mon Sep 17 00:00:00 2001 From: Binon Date: Wed, 11 Mar 2026 12:02:06 +0000 Subject: [PATCH] Fixed the issue with filter combos --- .../Helpers/UtilityHelper.cs | 17 +++--- .../Helpers/Search/AzureSearchFacetHelper.cs | 58 ++++++++++++++----- .../AzureSearch/AzureSearchService.cs | 6 +- 3 files changed, 54 insertions(+), 27 deletions(-) diff --git a/LearningHub.Nhs.WebUI/Helpers/UtilityHelper.cs b/LearningHub.Nhs.WebUI/Helpers/UtilityHelper.cs index 1c2970a96..4c444cbcf 100644 --- a/LearningHub.Nhs.WebUI/Helpers/UtilityHelper.cs +++ b/LearningHub.Nhs.WebUI/Helpers/UtilityHelper.cs @@ -408,6 +408,9 @@ public static string GetFormattedAuthoredDate(string authoredDate) "MM/dd/yyyy HH:mm:ss", "yyyyMMdd", "yyyyMMdd HH:mm:ss", + "M/d/yyyy", + "M/d/yyyy h:mm:ss tt", + "M/d/yyyy h:mm tt", }; if (string.IsNullOrWhiteSpace(authoredDate)) @@ -415,19 +418,13 @@ public static string GetFormattedAuthoredDate(string authoredDate) return string.Empty; } - string displayDate = authoredDate; - - if (DateTime.TryParseExact( - authoredDate, - dateFormats, - CultureInfo.InvariantCulture, - DateTimeStyles.None, - out DateTime parsedDate)) + if (DateTime.TryParse(authoredDate, CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out var date) || + DateTime.TryParseExact(authoredDate, dateFormats, CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out date)) { - displayDate = parsedDate.ToString("dd MMM yyyy"); + return date.ToString("dd MMM yyyy"); } - return displayDate; + return authoredDate; } /// diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Helpers/Search/AzureSearchFacetHelper.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Helpers/Search/AzureSearchFacetHelper.cs index 6818b0ecb..066c6aae3 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Helpers/Search/AzureSearchFacetHelper.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Helpers/Search/AzureSearchFacetHelper.cs @@ -115,26 +115,54 @@ public static Facet[] MergeFacets( ? filteredFacets[facetKey].ToDictionary(f => f.Value?.ToString()?.ToLower() ?? "", f => (int)f.Count) : new Dictionary(); - facets[index++] = new Facet + var filters = facetGroup.Value.Select(f => { - Id = facetKey, - Filters = facetGroup.Value.Select(f => + var displayName = f.Value?.ToString()?.ToLower() ?? ""; + var isSelected = appliedValues.Any(av => av.Equals(f.Value?.ToString(), StringComparison.OrdinalIgnoreCase)); + + // Default to the unfiltered count. This is used when: + // - no filtered search has been performed, OR + // - the filter value is selected (keep count so the option remains visible for deselection), OR + // - this facet group itself has an applied filter (multi-select pattern: a group's own + // counts are not narrowed down by its own selections so the user can still pick other values). + // Only update counts using the filtered results when a filter from a DIFFERENT group + // is driving the narrowing of this group. + var count = (int)f.Count; + if (!isSelected && filteredFacets != null && !hasAppliedFilter) + { + count = filteredFacetValues.TryGetValue(displayName, out var filteredCount) ? filteredCount : 0; + } + + return new Filter { - var displayName = f.Value?.ToString()?.ToLower() ?? ""; - var isSelected = appliedValues.Any(av => av.Equals(f.Value?.ToString(), StringComparison.OrdinalIgnoreCase)); + DisplayName = displayName, + Count = count, + Selected = isSelected + }; + }).ToList(); - // Use filtered count if available and filter is not selected, otherwise use unfiltered count - var count = !isSelected && filteredFacetValues.ContainsKey(displayName) - ? filteredFacetValues[displayName] - : (int)f.Count; + // Ensure all selected filter values remain visible even if absent from the unfiltered + // baseline (e.g. a resource selected under a resource-level filter that yields no results). + foreach (var selectedValue in appliedValues) + { + var alreadyPresent = filters.Any(f => + f.DisplayName.Equals(selectedValue, StringComparison.OrdinalIgnoreCase)); - return new Filter + if (!alreadyPresent) + { + filters.Add(new Filter { - DisplayName = displayName, - Count = count, - Selected = isSelected - }; - }).ToArray() + DisplayName = selectedValue.ToLower(), + Count = 0, + Selected = true, + }); + } + } + + facets[index++] = new Facet + { + Id = facetKey, + Filters = filters.ToArray() }; } diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/AzureSearch/AzureSearchService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/AzureSearch/AzureSearchService.cs index 572c4d8ae..25a98541e 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/AzureSearch/AzureSearchService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/AzureSearch/AzureSearchService.cs @@ -866,12 +866,14 @@ private string MapToResourceType(string resourceType) private async Task>> GetUnfilteredFacetsAsync( string searchText, IDictionary> facets, - string? resourceAccessLevel, + string? resourceAccessLevel, CancellationToken cancellationToken) { var normalizedSearch = searchText?.ToLowerInvariant() ?? "*"; var accessLevelKey = resourceAccessLevel?.ToString() ?? "null"; - var cacheKey = $"AllFacets_{normalizedSearch}_ral_{accessLevelKey}"; + var cacheKey = $"Facets_{normalizedSearch}"; + if (!string.IsNullOrWhiteSpace(accessLevelKey)) + cacheKey += $"_{accessLevelKey.Replace("=", "_")}"; var cacheResponse = await this.cachingService.GetAsync>>(cacheKey);