Fixed bug where deletes of artifact groupings would not cascade
This commit is contained in:
166
OpenArchival.Blazor.Blog/SearchBlog.razor
Normal file
166
OpenArchival.Blazor.Blog/SearchBlog.razor
Normal file
@@ -0,0 +1,166 @@
|
||||
@page "/articles/search"
|
||||
@page "/articles/search/{SearchTerms}"
|
||||
|
||||
@using Microsoft.EntityFrameworkCore
|
||||
@using Microsoft.Extensions.Logging
|
||||
@using MudBlazor
|
||||
@using OpenArchival.DataAccess
|
||||
@using System.Linq
|
||||
@using System.Text.RegularExpressions
|
||||
@using System.Net
|
||||
|
||||
<BlogPostSearchBar @ref="_searchBar"
|
||||
@bind-SelectedFilter="_selectedFilter"
|
||||
SearchTermsChanged="PerformSearchAsyncCallback" />
|
||||
@{
|
||||
if (_showMostRecent && PostSearch.TotalResults > 0)
|
||||
{
|
||||
<MudGrid Justify="Justify.FlexStart" Class="mt-1 ml-1 mb-2">
|
||||
<MudText Typo="Typo.h6" Color="Color.Primary">Most Recent Posts:</MudText>
|
||||
</MudGrid>
|
||||
}
|
||||
else if (PostSearch.TotalResults > 0)
|
||||
{
|
||||
<MudGrid Justify="Justify.FlexStart" Class="mt-1 ml-1 mb-2">
|
||||
<MudText Typo="Typo.subtitle2" Class="my-2">@PostSearch.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>
|
||||
</MudGrid>
|
||||
}
|
||||
}
|
||||
|
||||
@if (PostSearch.SearchResults.Count > 0)
|
||||
{
|
||||
<MudGrid>
|
||||
@foreach (var post in PostSearch.SearchResults)
|
||||
{
|
||||
<MudItem xs="12" sm="6" md="4" lg="4">
|
||||
<MudLink Href="@($"/articles/{post.Id}")" Target="_blank" Style="text-decoration: none; color: inherit;">
|
||||
<MudCard Style="@($"height: {Math.Floor(400 * 0.7)}px; display: flex; flex-direction: column;")">
|
||||
|
||||
@if (post.MainPhoto != null)
|
||||
{
|
||||
<MudCardMedia Image="@($"/api/files/{post.MainPhoto.Id}")" Style="height: 100%;" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudCardMedia Image="/images/placeholder.png" Style="height: 100%;" /> }
|
||||
|
||||
<MudCardContent Style=@($"flex-grow: 1; overflow-y: clip; height:{Math.Floor(400 * 0.3)}px;")>
|
||||
<MudText Typo="Typo.h5">@post.Title</MudText>
|
||||
<MudText Typo="Typo.body2">@CreateContentSnippet(post.Content)</MudText>
|
||||
</MudCardContent>
|
||||
</MudCard>
|
||||
</MudLink>
|
||||
</MudItem>
|
||||
}
|
||||
</MudGrid>
|
||||
|
||||
<MudPaper Class="d-flex justify-center py-2 mt-4" Elevation="0">
|
||||
<MudPagination Count="PostSearch.TotalPages"
|
||||
Selected="PostSearch.CurrentPage"
|
||||
SelectedChanged="OnPageChangedAsync" />
|
||||
</MudPaper>
|
||||
}
|
||||
|
||||
@inject IDbContextFactory<ApplicationDbContext> ContextFactory;
|
||||
@inject ILogger<SearchBlog> Logger;
|
||||
@inject NavigationManager NavigationManager;
|
||||
@inject BlogPostSearch PostSearch;
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public string SearchTerms { get; set; } = "";
|
||||
|
||||
private BlogSearchFilterType _selectedFilter = BlogSearchFilterType.All;
|
||||
private BlogPostSearchBar _searchBar = default!;
|
||||
|
||||
// List for the "no results" slider display
|
||||
private List<SearchPageSliderEntry> _sliderEntries { get; set; } = [];
|
||||
|
||||
private bool _showMostRecent = true;
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
// This runs when the page loads, checking for search terms in the URL
|
||||
if (string.IsNullOrWhiteSpace(SearchTerms))
|
||||
{
|
||||
await PostSearch.Search("", _selectedFilter, 1);
|
||||
_showMostRecent = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
await PostSearch.Search(SearchTerms, _selectedFilter, 1);
|
||||
_showMostRecent = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is called by the SearchBar component's 'SearchTermsChanged' event.
|
||||
/// </summary>
|
||||
private async Task PerformSearchAsyncCallback(string searchTerms)
|
||||
{
|
||||
if (string.IsNullOrEmpty(searchTerms))
|
||||
{
|
||||
_showMostRecent = true;
|
||||
} else
|
||||
{
|
||||
_showMostRecent = false;
|
||||
}
|
||||
|
||||
SearchTerms = searchTerms; // Update the page's parameter
|
||||
|
||||
// Update the URL to reflect the new search
|
||||
NavigationManager.NavigateTo($"/articles/search/{Uri.EscapeDataString(searchTerms)}", replace: true);
|
||||
|
||||
// Perform the search (always start on page 1)
|
||||
await PostSearch.Search(searchTerms, _selectedFilter, 1);
|
||||
|
||||
StateHasChanged(); // Re-render the page with results
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is called by the MudPagination's 'SelectedChanged' event.
|
||||
/// </summary>
|
||||
private async Task OnPageChangedAsync(int page)
|
||||
{
|
||||
// Load the specific page using the service
|
||||
await PostSearch.LoadPageAsync(page);
|
||||
StateHasChanged(); // Re-render with the new page's data
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the search results and state.
|
||||
/// </summary>
|
||||
private void OnClearResults()
|
||||
{
|
||||
PostSearch.ClearResults();
|
||||
SearchTerms = "";
|
||||
|
||||
// Navigate back to the base search page
|
||||
NavigationManager.NavigateTo("/articles/search", replace: true);
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
public static string CreateContentSnippet(string html, int maxLength = 150)
|
||||
{
|
||||
if (string.IsNullOrEmpty(html))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
// Strip HTML tags
|
||||
string plainText = Regex.Replace(html, @"<[^>]+>", string.Empty);
|
||||
|
||||
// Decode HTML entities
|
||||
plainText = WebUtility.HtmlDecode(plainText).Trim();
|
||||
|
||||
if (plainText.Length > maxLength)
|
||||
{
|
||||
return plainText.Substring(0, maxLength) + "...";
|
||||
}
|
||||
|
||||
return plainText;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user