using Elternbeirat.Contracts; using Elternbeirat.PocketBase; using Elternbeirat.Web.Shared; using Microsoft.AspNetCore.Components; namespace Elternbeirat.Web.Features.Pages; public partial class ContentPage { [LoggerMessage( Level = LogLevel.Error, Message = "Could not load page '{Slug}' from PocketBase; content source is unavailable.")] private static partial void LogSourceUnavailable( ILogger logger, string slug, Exception exception); [Parameter] public string Slug { get; set; } = string.Empty; [Inject] private PocketBaseClient PocketBase { get; set; } = null!; [Inject] private ILogger Logger { get; set; } = null!; [Inject] private NavigationManager Navigation { get; set; } = null!; [CascadingParameter] private HttpContext? HttpContext { get; set; } private Page? _page; // Set when the content source could not be reached or read. The markup then // shows a "temporarily unavailable" note instead of a not-found page, matching // the 503 this sets on the response. private bool _unavailable; // The page body rendered from Markdown to HTML, ready to emit as a // MarkupString in the markup. private MarkupString Body => (MarkupString)Markdown.ToHtml(_page?.Body); protected override async Task OnParametersSetAsync() { try { var pages = await PocketBase.GetPagesAsync(HttpContext?.RequestAborted ?? CancellationToken.None); _page = pages.FirstOrDefault( page => string.Equals(page.Slug, Slug, StringComparison.OrdinalIgnoreCase)); } catch (PocketBaseUnavailableException exception) { // The site works, its data store is down: 503, not 404. LogSourceUnavailable(Logger, Slug, exception); _unavailable = true; SourceUnavailable.SetStatus(HttpContext); return; } if (_page is null) { // The source answered, but there is no page with this slug: a genuine 404. Navigation.NotFound(); } } }