diff --git a/Wave/Components/PageComponent.razor b/Wave/Components/PageComponent.razor new file mode 100644 index 0000000..72e486b --- /dev/null +++ b/Wave/Components/PageComponent.razor @@ -0,0 +1,24 @@ +@typeparam T + +@foreach (var item in Items) { + @ChildContent(item) +} + +@code { + [SupplyParameterFromQuery] + public int Page { get; set; } = 0; + + [Parameter] + public required RenderFragment ChildContent { get; set; } + [Parameter] + public required Func>> LoadCallback { get; set; } + + [Parameter] + public int ItemsPerPage { get; set; } = 10; + + private List Items { get; } = []; + + protected override async Task OnInitializedAsync() { + foreach (var i in await LoadCallback(Page * ItemsPerPage, ItemsPerPage)) Items.Add(i); + } +} diff --git a/Wave/Components/Pages/Home.razor b/Wave/Components/Pages/Home.razor index 02eb27b..cf2fd1b 100644 --- a/Wave/Components/Pages/Home.razor +++ b/Wave/Components/Pages/Home.razor @@ -4,13 +4,12 @@ @using Wave.Data @using Wave.Utilities -@rendermode InteractiveServer -@attribute [StreamRendering] @inject IOptions Customizations @inject IOptions Features @inject NavigationManager Navigation @inject IDbContextFactory ContextFactory; @inject IStringLocalizer Localizer +@inject IMessageDisplay Message @@ -62,100 +61,88 @@ } - - -@if (Busy) { -
- -
-} else { - @if (Articles.FirstOrDefault() is {} featured) { -
- -
-
-
-

- @featured.Title -

- @foreach (var category in featured.Categories.OrderBy(c => c.Color)) { - - @category.Name - - } -

-

-

- @featured.PublishDate.ToString("g")
- @featured.Body[..Math.Min(1000, featured.Body.Length)] +@if (Featured is {} featured) { +

+ +
+
+
+

+ @featured.Title +

+ @foreach (var category in featured.Categories.OrderBy(c => c.Color)) { + + @category.Name + + }

-
- -
+

+

+ @featured.PublishDate.ToString("g")
+ @featured.Body[..Math.Min(1000, featured.Body.Length)] +

+
+
- -
- } else { -

@Localizer["NoArticles_Title"]

-

@Localizer["NoArticles_Message"]

- } - - - @foreach (var article in Articles.Skip(1)) { - - } - +
+ +
+} else { +

@Localizer["NoArticles_Title"]

+

@Localizer["NoArticles_Message"]

} -@if (HasMore) { -
- + + + + + + +
+
+ « + + »
-} +
@code { [CascadingParameter(Name = "TitlePrefix")] private string TitlePrefix { get; set; } = default!; + [SupplyParameterFromQuery] + public int Page { get; set; } = 0; - private List
Articles { get; } = []; - private bool HasMore { get; set; } - private bool Busy { get; set; } = true; + private int TotalPages { get; set; } = 1; - protected override async Task OnAfterRenderAsync(bool firstRender) { - if (firstRender) { - try { - await using var context = await ContextFactory.CreateDbContextAsync(); + private Article? Featured { get; set; } - var query = context.Set
() - .Include(a => a.Author).Include(a => a.Categories) - .OrderByDescending(a => a.PublishDate); - var articles = await query.Take(11).ToListAsync(); - HasMore = (await query.CountAsync()) > 11; - Articles.AddRange(articles); - } finally { - Busy = false; - await InvokeAsync(StateHasChanged); - } - } - } - - private async Task More() { + protected override async Task OnInitializedAsync() { try { - Busy = HasMore = true; await using var context = await ContextFactory.CreateDbContextAsync(); var query = context.Set
() .Include(a => a.Author).Include(a => a.Categories) - .OrderByDescending(a => a.PublishDate) - .Skip(Articles.Count); - var articles = await query.Take(10).ToListAsync(); - Articles.AddRange(articles); - HasMore = (await query.CountAsync()) > 10; - } finally { - Busy = false; + .OrderByDescending(a => a.PublishDate).ThenBy(a => a.Id); + + Featured = await query.FirstOrDefaultAsync(); + TotalPages = (int) Math.Ceiling((await query.CountAsync() - 1) / 10.0); + } catch { + Message.ShowError(Localizer["Articles_Load_Error"]); } } + private async ValueTask> LoadArticles(int page, int count) { + try { + await using var context = await ContextFactory.CreateDbContextAsync(); + return await context.Set
() + .Include(a => a.Author).Include(a => a.Categories) + .OrderByDescending(a => a.PublishDate).ThenBy(a => a.Id) + .Skip(page + 1).Take(count).ToListAsync(); + } catch { + Message.ShowError(Localizer["Articles_Load_Error"]); + return []; + } + } } \ No newline at end of file