using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.Extensions.Logging; using MudBlazor; using Npgsql.EntityFrameworkCore.PostgreSQL; using NpgsqlTypes; using OpenArchival.DataAccess; using OpenArchival.DataAccess; using System; using System.Collections.Generic; using System.Drawing.Printing; using System.Linq; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Threading.Tasks; namespace OpenArchival.Blazor.ArchiveSearch; public enum ArchiveSearchFilterType { All, Tags, Defects, ListedNames, Title, Description, Filenames, ArtifactTranscriptions } public class ArtifactGroupingSearch { public int TotalResults { get; set; } public int TotalPages { get; set; } public int PageSize { get; set; } = 20; public int CurrentPage { get; set; } public List SearchResults { get; set; } = []; private string _searchTerms { get; set; } private IDbContextFactory _contextFactory { get; set; } private Expression> _currentFilterPredicate; private ArchiveSearchFilterType _selectedFilter = ArchiveSearchFilterType.All; public ArtifactGroupingSearch(IDbContextFactory contextFactory) { _contextFactory = contextFactory; } public async Task Search(string Terms, ArchiveSearchFilterType filter, int page = 1) { _searchTerms = Terms; _selectedFilter = filter; // Determine which filter expression to use based on the radio button selection switch (_selectedFilter) { case ArchiveSearchFilterType.Tags: _currentFilterPredicate = x => x.TagsSearchVector.Matches(_searchTerms); break; case ArchiveSearchFilterType.Title: _currentFilterPredicate = x => x.TitleSearchVector.Matches(_searchTerms); break; case ArchiveSearchFilterType.Description: _currentFilterPredicate = x => x.DescriptionSearchVector.Matches(_searchTerms); break; case ArchiveSearchFilterType.Defects: _currentFilterPredicate = x => x.DefectsSearchVector.Matches(_searchTerms); break; case ArchiveSearchFilterType.Filenames: _currentFilterPredicate = x => x.FilenamesSearchVector.Matches(_searchTerms); break; case ArchiveSearchFilterType.ArtifactTranscriptions: _currentFilterPredicate = x => x.FileContentSearchVector.Matches(_searchTerms); break; case ArchiveSearchFilterType.ListedNames: _currentFilterPredicate = x => x.ListedNamesSearchVector.Matches(_searchTerms); break; case ArchiveSearchFilterType.All: default: _currentFilterPredicate = x => x.AllSearchVector.Matches(_searchTerms); break; } // Get the total count using the chosen filter await using var context = await _contextFactory.CreateDbContextAsync(); TotalResults = await context.ArtifactGroupings.Where(_currentFilterPredicate).CountAsync(); TotalPages = (int)Math.Ceiling(TotalResults / (double)PageSize); // Load the first page with the chosen filter await LoadPageAsync(page); } public async Task LoadPageAsync(int page) { CurrentPage = page; if (_currentFilterPredicate == null) // Don't run if no search has been performed { return; } await using var context = await _contextFactory.CreateDbContextAsync(); // The query uses the dynamically set filter predicate SearchResults = await context.ArtifactGroupings .Where(_currentFilterPredicate) .Include(x => x.ChildArtifactEntries) .ThenInclude(x => x.Files) .Include(x=>x.Category) .OrderBy(x => x.Id) .Skip((CurrentPage - 1) * PageSize) .Take(PageSize) .ToListAsync(); } public void ClearResults() { SearchResults.Clear(); TotalResults = 0; TotalPages = 0; } }