Finished refining the search page

This commit is contained in:
2026-03-09 16:47:28 -04:00
parent 28d90fcc18
commit 6da2183583
177 changed files with 653 additions and 96 deletions

View File

@@ -13,21 +13,6 @@
@bind-Value="SearchTerms"
/>
<MudExpansionPanel Text="Filter...">
<MudText Typo="Typo.caption">Choose which data the serach bar will search on:</MudText>
<MudDivider></MudDivider>
<MudRadioGroup T="ArchiveSearchFilterType" @bind-SelectedOption="SelectedFilter">
<MudRadio Option="ArchiveSearchFilterType.All" T="ArchiveSearchFilterType">All</MudRadio>
<MudRadio Option="ArchiveSearchFilterType.Tags" T="ArchiveSearchFilterType">Tags</MudRadio>
<MudRadio Option="ArchiveSearchFilterType.Defects" T="ArchiveSearchFilterType">Defects</MudRadio>
<MudRadio Option="ArchiveSearchFilterType.ListedNames" T="ArchiveSearchFilterType">Listed Names</MudRadio>
<MudRadio Option="ArchiveSearchFilterType.Title" T="ArchiveSearchFilterType">Title</MudRadio>
<MudRadio Option="ArchiveSearchFilterType.Description" T="ArchiveSearchFilterType">Description</MudRadio>
<MudRadio Option="ArchiveSearchFilterType.Filenames" T="ArchiveSearchFilterType">Filenames</MudRadio>
<MudRadio Option="ArchiveSearchFilterType.ArtifactTranscriptions" T="ArchiveSearchFilterType">Artifact Transcriptions</MudRadio>
</MudRadioGroup>
</MudExpansionPanel>
</Microsoft.AspNetCore.Components.Forms.EditForm>
@code {
[Parameter]
@@ -36,12 +21,6 @@
[Parameter]
public EventCallback<string> SearchTermsChanged { get; set; }
[Parameter]
public ArchiveSearchFilterType SelectedFilter { get; set; } = ArchiveSearchFilterType.All;
[Parameter]
public EventCallback<ArchiveSearchFilterType> SelectedFilterChanged { get; set; }
private async Task HandleSearchKeyDown(Microsoft.AspNetCore.Components.Web.KeyboardEventArgs args)
{
if (args.Key == "Enter")

View File

@@ -0,0 +1,105 @@
@using Microsoft.AspNetCore.Components.Web
@using MudBlazor
<MudExpansionPanel Text="Filter...">
<MudText Typo="Typo.caption">Choose which data the serach bar will search on:</MudText>
<MudDivider></MudDivider>
<MudRadioGroup
T="ArchiveSearchFilterType"
Value="SelectedFilter"
ValueChanged="OnSelectedFilterChanged"
>
<MudRadio Option="ArchiveSearchFilterType.All" T="ArchiveSearchFilterType">All</MudRadio>
<MudRadio Option="ArchiveSearchFilterType.Tags" T="ArchiveSearchFilterType">Tags</MudRadio>
<MudRadio Option="ArchiveSearchFilterType.Defects" T="ArchiveSearchFilterType">Defects</MudRadio>
<MudRadio Option="ArchiveSearchFilterType.ListedNames" T="ArchiveSearchFilterType">Listed Names</MudRadio>
<MudRadio Option="ArchiveSearchFilterType.Title" T="ArchiveSearchFilterType">Title</MudRadio>
<MudRadio Option="ArchiveSearchFilterType.Description" T="ArchiveSearchFilterType">Description</MudRadio>
<MudRadio Option="ArchiveSearchFilterType.Filenames" T="ArchiveSearchFilterType">Filenames</MudRadio>
<MudRadio Option="ArchiveSearchFilterType.ArtifactTranscriptions" T="ArchiveSearchFilterType">Artifact Transcriptions</MudRadio>
</MudRadioGroup>
<MudText Typo="Typo.caption">Filter artifacts by the first letter of their title</MudText>
<MudDivider/>
<MudSelect
Text="Title First Letter Filter"
T="string"
Value="SelectedTitlePrefix"
ValueChanged="OnSelectedTitlePrefixChanged"
Variant="Variant.Outlined">
@foreach (var value in TitlePrefixOptions)
{
<MudSelectItem Value="@value">@value</MudSelectItem>
}
</MudSelect>
<MudButton OnClick="ApplyFiltersClicked">Apply Filters</MudButton>
</MudExpansionPanel>
@code {
// Search parameters
[Parameter]
public ArchiveSearchFilterType SelectedFilter { get; set; } = ArchiveSearchFilterType.All;
[Parameter]
public EventCallback<ArchiveSearchFilterType> SelectedFilterChanged { get; set; }
// Filter parameters
[Parameter]
public string SelectedTitlePrefix { get; set; } = "";
[Parameter]
public EventCallback<string> SelectedTitlePrefixChanged { get; set; }
[Parameter]
public EventCallback<MouseEventArgs> ApplyFiltersClicked { get; set; }
[Parameter]
public IEnumerable<string> TitlePrefixOptions { get; set; } =
new List<string> {
"",
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
"l",
"m",
"n",
"o",
"p",
"q",
"r",
"s",
"t",
"u",
"v",
"w",
"x",
"y",
"z"
};
private async Task OnSelectedTitlePrefixChanged(string value)
{
SelectedTitlePrefix = value;
if (SelectedTitlePrefixChanged.HasDelegate)
{
await SelectedTitlePrefixChanged.InvokeAsync(value);
}
}
private async Task OnSelectedFilterChanged(ArchiveSearchFilterType filter)
{
SelectedFilter = filter;
if (SelectedFilterChanged.HasDelegate)
{
await SelectedFilterChanged.InvokeAsync(filter);
}
}
}

View File

@@ -1,6 +1,7 @@
@page "/search"
@page "/search/{SearchTerms}"
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.EntityFrameworkCore
@using Microsoft.Extensions.Logging
@using MudBlazor
@@ -16,14 +17,22 @@
@namespace OpenArchival.Blazor.ArchiveDisplay
<ArchiveSearchBar @bind-SelectedFilter="_selectedFilter"
SearchTermsChanged="OnSearchSubmittedAsync" />
<ArchiveSearchBar SearchTermsChanged="OnSearchSubmittedAsync"/>
<FilterSelectorComponent
@bind-SelectedFilter="_selectedFilter"
@bind-SelectedTitlePrefix="_selectedLetter"
ApplyFiltersClicked="OnApplyFilters"></FilterSelectorComponent>
@if (_totalResults > 0)
@if (_totalResults > 0 && !_allArtifactsMode)
{
<MudGrid Justify="Justify.FlexStart" Class="mt-1 ml-1 mb-2">
<MudText Typo="Typo.subtitle2" Class="my-2">@_totalResults results found</MudText>
<MudButton Class="ml-1" StartIcon="@Icons.Material.Filled.Clear" OnClick="OnClearResults" Variant="Variant.Filled" Color="Color.Primary" Size="Size.Small">Clear</MudButton>
<MudButton Class="ml-1"
StartIcon="@Icons.Material.Filled.Clear"
OnClick="@(args => OnClearResults(args, true, true))"
Variant="Variant.Filled"
Color="Color.Primary"
Size="Size.Small">Clear</MudButton>
</MudGrid>
}
@@ -42,13 +51,7 @@
<MudPagination Count="_totalPages" Selected="_currentPage" SelectedChanged="OnPageChangedAsync" />
</MudPaper>
}
else
{
@foreach (SearchPageSliderEntry entry in _sliderEntries)
{
<SearchPageSlider SliderEntry="entry"></SearchPageSlider>
}
}
@inject IDbContextFactory<ApplicationDbContext> ContextFactory;
@inject ILogger<SearchArchive> Logger;
@@ -59,26 +62,45 @@ else
private ArchiveSearchFilterType _selectedFilter = ArchiveSearchFilterType.All;
// Field to store the current filter logic
private Expression<Func<ArtifactGrouping, bool>> _currentFilterPredicate;
private List<ArtifactGrouping> _artifactGroupings { get; set; } = [];
private int _currentPage { get; set; } = 1;
private int _totalPages { get; set; } = 0;
private int _totalResults { get; set; } = 0;
private const int PageSize = 20;
private List<SearchPageSliderEntry> _sliderEntries { get; set; } = [];
// Field to store the current filter logic
private Expression<Func<ArtifactGrouping, bool>> _currentFilterPredicate;
private bool _allArtifactsMode = true;
private string? _selectedLetter;
protected override async Task OnParametersSetAsync()
{
if (!string.IsNullOrWhiteSpace(SearchTerms))
if (string.IsNullOrWhiteSpace(SearchTerms))
{
_allArtifactsMode = true;
await LoadPageAsync(1);
} else
{
_allArtifactsMode = false;
await PerformSearchAsync();
}
}
await using var context = await ContextFactory.CreateDbContextAsync();
_sliderEntries = await context.SearchPageSliderEntries.Include(e => e.FilterTags).ToListAsync();
private IQueryable<ArtifactGrouping> BuildFilterQuery(IQueryable<ArtifactGrouping> startingQuery)
{
// Filter
if (_currentFilterPredicate != null && !_allArtifactsMode)
{
startingQuery = startingQuery.Where(_currentFilterPredicate);
}
if (!string.IsNullOrWhiteSpace(_selectedLetter))
{
string likePattern = $"{_selectedLetter}%";
startingQuery = startingQuery.Where(artifact => EF.Functions.ILike(artifact.Title, likePattern));
}
return startingQuery;
}
/// <summary>
@@ -86,14 +108,20 @@ else
/// </summary>
private async Task OnSearchSubmittedAsync(string searchTerms)
{
await OnClearResults(null, false, true);
if (string.IsNullOrWhiteSpace(searchTerms))
{
OnClearResults(null);
// Tell the clear operation not to navigate back to the search page and refresh
_allArtifactsMode = true;
await PerformSearchAsync();
return;
}
SearchTerms = searchTerms;
NavigationManager.NavigateTo($"/search/{Uri.EscapeDataString(SearchTerms)}", replace: true);
_allArtifactsMode = false;
// This eventually calls LoadPageAsync
await PerformSearchAsync();
}
@@ -132,11 +160,6 @@ else
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(1);
}
@@ -151,29 +174,40 @@ else
/// </summary>
private async Task LoadPageAsync(int page)
{
_currentPage = page;
await using var context = await ContextFactory.CreateDbContextAsync();
IQueryable<ArtifactGrouping> query = context.ArtifactGroupings;
if (_currentFilterPredicate == null) // Don't run if no search has been performed
query = BuildFilterQuery(query);
// Select child data we want
query = query
.Include(x => x.ChildArtifactEntries)
.ThenInclude(x => x.Files);
// If we are showing all artifacts, then order results alphabetically
if (_allArtifactsMode)
{
return;
query = query.OrderBy(artifact => artifact.Title);
} else
{
query = query.OrderBy(artifact => artifact.Id);
}
await using var context = await ContextFactory.CreateDbContextAsync();
_totalResults = await query.CountAsync();
_totalPages = (int)Math.Ceiling(_totalResults / (double)PageSize);
_currentPage = page;
// The query uses the dynamically set filter predicate
_artifactGroupings = await context.ArtifactGroupings
.Where(_currentFilterPredicate)
.Include(x => x.ChildArtifactEntries)
.ThenInclude(x => x.Files)
.OrderBy(x => x.Id)
.Skip((_currentPage - 1) * PageSize)
.Take(PageSize)
.ToListAsync();
query = query
.Skip((_currentPage - 1) * PageSize)
.Take(PageSize);
_artifactGroupings = await query.ToListAsync();
StateHasChanged();
}
private void OnClearResults(Microsoft.AspNetCore.Components.Web.MouseEventArgs args)
private async Task OnClearResults(Microsoft.AspNetCore.Components.Web.MouseEventArgs args, bool navigate = true, bool resetFirstLetterFilter = false)
{
_totalResults = 0;
_artifactGroupings.Clear();
@@ -181,8 +215,28 @@ else
_totalPages = 0;
SearchTerms = "";
NavigationManager.NavigateTo("/search", replace: true);
if (navigate)
{
NavigationManager.NavigateTo("/search", replace: true);
}
if (resetFirstLetterFilter)
{
_selectedLetter = "";
}
StateHasChanged();
}
private async Task OnApplyFilters(MouseEventArgs args)
{
if (string.IsNullOrWhiteSpace(SearchTerms))
{
_allArtifactsMode = true;
} else
{
_allArtifactsMode = false;
}
await PerformSearchAsync();
}
}

View File

@@ -14,7 +14,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("OpenArchival.Blazor.ArchiveDisplay")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+dde9ffcedb0cf584318d02205327e3d89d7f3dfb")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+28d90fcc181787153ef8aecbeca2762fc064854e")]
[assembly: System.Reflection.AssemblyProductAttribute("OpenArchival.Blazor.ArchiveDisplay")]
[assembly: System.Reflection.AssemblyTitleAttribute("OpenArchival.Blazor.ArchiveDisplay")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]

View File

@@ -1 +1 @@
7d6519dfeb6e1259b8c40f6702317d12d84d17be4efea1781a8f87834cbb8ad3
ab9d3b350c2be66241fd834534ad405ddf0602aa3828b2bc80e92b2ecc3f688c

View File

@@ -33,6 +33,10 @@ build_metadata.AdditionalFiles.CssScope =
build_metadata.AdditionalFiles.TargetPath = QXJjaGl2ZVNsaWRlckhvbWUucmF6b3I=
build_metadata.AdditionalFiles.CssScope =
[C:/Users/Vincent/Documents/dev/Open-Archival/OpenArchival.Blazor.ArchiveSearch/FilterSelectorComponent.razor]
build_metadata.AdditionalFiles.TargetPath = RmlsdGVyU2VsZWN0b3JDb21wb25lbnQucmF6b3I=
build_metadata.AdditionalFiles.CssScope =
[C:/Users/Vincent/Documents/dev/Open-Archival/OpenArchival.Blazor.ArchiveSearch/SearchArchive.razor]
build_metadata.AdditionalFiles.TargetPath = U2VhcmNoQXJjaGl2ZS5yYXpvcg==
build_metadata.AdditionalFiles.CssScope =

View File

@@ -1 +1 @@
{"GlobalPropertiesHash":"aRofDjUlJNR7DrcyY3bug3knhmcqWrgI2xOcjq6Z3Gw=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["O9m64vDuGZ/IoFpay/iK5k0qq4O/PUcBGa3YQlcc3MM=","/6saXqMqjso1MoN6X5/1WpaXx/sFqlAait0UDg2RADw=","I0N9Khq8NSO7hQzFbWOVcrUUe0HilHePEhEjkiPhMbw=","s9LgwrtQwlqlg29AQY1X3CxfLRa3gCFqFHIzFdfxevw=","a4l9eGA7\u002B\u002BZ8KGxWZm/kexxp3lwNIpQlICyyT39PnDA="],"CachedAssets":{},"CachedCopyCandidates":{}}
{"GlobalPropertiesHash":"aRofDjUlJNR7DrcyY3bug3knhmcqWrgI2xOcjq6Z3Gw=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["O9m64vDuGZ/IoFpay/iK5k0qq4O/PUcBGa3YQlcc3MM=","vGYaI2x3bnwOMRs33zLY4lfsqre8r3HgLyYetwyjqG4=","ZmQmcqFyfcky0zhEAuRUqUK613wUszcCTaQSydi8ZSI=","3wlVB4/c0kE/xG7SIkL2Z9S9actV94iXWgKmXg0ymrs=","cYg0XngZ22OosKiPAz/lNRofR4HiKjt/rTyNG6i/21M=","a4l9eGA7\u002B\u002BZ8KGxWZm/kexxp3lwNIpQlICyyT39PnDA="],"CachedAssets":{},"CachedCopyCandidates":{}}

View File

@@ -1 +1 @@
{"GlobalPropertiesHash":"0cOxJaGoxsCc+BnwFr7/pfRM7mZBxaAniBLb3gSOucw=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["O9m64vDuGZ/IoFpay/iK5k0qq4O/PUcBGa3YQlcc3MM=","/6saXqMqjso1MoN6X5/1WpaXx/sFqlAait0UDg2RADw=","I0N9Khq8NSO7hQzFbWOVcrUUe0HilHePEhEjkiPhMbw=","s9LgwrtQwlqlg29AQY1X3CxfLRa3gCFqFHIzFdfxevw=","a4l9eGA7\u002B\u002BZ8KGxWZm/kexxp3lwNIpQlICyyT39PnDA="],"CachedAssets":{},"CachedCopyCandidates":{}}
{"GlobalPropertiesHash":"0cOxJaGoxsCc+BnwFr7/pfRM7mZBxaAniBLb3gSOucw=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["O9m64vDuGZ/IoFpay/iK5k0qq4O/PUcBGa3YQlcc3MM=","vGYaI2x3bnwOMRs33zLY4lfsqre8r3HgLyYetwyjqG4=","ZmQmcqFyfcky0zhEAuRUqUK613wUszcCTaQSydi8ZSI=","3wlVB4/c0kE/xG7SIkL2Z9S9actV94iXWgKmXg0ymrs=","cYg0XngZ22OosKiPAz/lNRofR4HiKjt/rTyNG6i/21M=","a4l9eGA7\u002B\u002BZ8KGxWZm/kexxp3lwNIpQlICyyT39PnDA="],"CachedAssets":{},"CachedCopyCandidates":{}}

View File

@@ -1 +1 @@
{"GlobalPropertiesHash":"IK8shjOKTVCmiSDhFNy2cRHHb49KGLFZOBBXGeHXucQ=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["O9m64vDuGZ/IoFpay/iK5k0qq4O/PUcBGa3YQlcc3MM=","/6saXqMqjso1MoN6X5/1WpaXx/sFqlAait0UDg2RADw=","I0N9Khq8NSO7hQzFbWOVcrUUe0HilHePEhEjkiPhMbw=","s9LgwrtQwlqlg29AQY1X3CxfLRa3gCFqFHIzFdfxevw=","a4l9eGA7\u002B\u002BZ8KGxWZm/kexxp3lwNIpQlICyyT39PnDA="],"CachedAssets":{},"CachedCopyCandidates":{}}
{"GlobalPropertiesHash":"IK8shjOKTVCmiSDhFNy2cRHHb49KGLFZOBBXGeHXucQ=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["O9m64vDuGZ/IoFpay/iK5k0qq4O/PUcBGa3YQlcc3MM=","vGYaI2x3bnwOMRs33zLY4lfsqre8r3HgLyYetwyjqG4=","ZmQmcqFyfcky0zhEAuRUqUK613wUszcCTaQSydi8ZSI=","3wlVB4/c0kE/xG7SIkL2Z9S9actV94iXWgKmXg0ymrs=","cYg0XngZ22OosKiPAz/lNRofR4HiKjt/rTyNG6i/21M=","a4l9eGA7\u002B\u002BZ8KGxWZm/kexxp3lwNIpQlICyyT39PnDA="],"CachedAssets":{},"CachedCopyCandidates":{}}

View File

@@ -310,3 +310,39 @@ C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.ArtifactGroupin
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.DataAccess\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.CustomComponents\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.FileViewer\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.ArtifactGroupingDisplay\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.DataAccess\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.CustomComponents\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.FileViewer\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.ArtifactGroupingDisplay\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.DataAccess\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.CustomComponents\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.FileViewer\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.ArtifactGroupingDisplay\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.DataAccess\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.CustomComponents\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.FileViewer\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.ArtifactGroupingDisplay\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.DataAccess\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.CustomComponents\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.FileViewer\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.ArtifactGroupingDisplay\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.DataAccess\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.CustomComponents\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.FileViewer\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.ArtifactGroupingDisplay\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.DataAccess\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.CustomComponents\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.FileViewer\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.ArtifactGroupingDisplay\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.DataAccess\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.CustomComponents\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.FileViewer\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.ArtifactGroupingDisplay\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.DataAccess\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.CustomComponents\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.FileViewer\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.ArtifactGroupingDisplay\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.DataAccess\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.CustomComponents\obj\Debug\net9.0\staticwebassets.build.json
C:\Users\Vincent\Documents\dev\Open-Archival\OpenArchival.Blazor.FileViewer\obj\Debug\net9.0\staticwebassets.build.json