From 8642737a07745ece089158cd5ea676ab3616edf1 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Fri, 12 Dec 2025 00:10:57 +0800 Subject: [PATCH] :sparkles: Configurable post page --- DysonNetwork.Shared/Models/PublicationSite.cs | 8 +++- .../Customization/PostPageConfig.cs | 18 +++++++ DysonNetwork.Zone/Pages/Posts.cshtml | 35 ++++++-------- DysonNetwork.Zone/Pages/Posts.cshtml.cs | 47 ++++++++++++++----- .../Pages/Shared/_PostItem.cshtml | 3 +- .../Publication/PublicationSiteMiddleware.cs | 14 ++++++ 6 files changed, 87 insertions(+), 38 deletions(-) create mode 100644 DysonNetwork.Zone/Customization/PostPageConfig.cs diff --git a/DysonNetwork.Shared/Models/PublicationSite.cs b/DysonNetwork.Shared/Models/PublicationSite.cs index 75ff03b..5cbc232 100644 --- a/DysonNetwork.Shared/Models/PublicationSite.cs +++ b/DysonNetwork.Shared/Models/PublicationSite.cs @@ -59,7 +59,11 @@ public enum PublicationPageType /// The redirect mode allows user to create a shortcut for their own link. /// such as example.solian.page/rickroll -- DyZ 301 -> youtube.com/... /// - Redirect + Redirect, + /// + /// The Post Page type allows user render a list of posts based on the preconfigured filter. + /// + PostPage } public class SnPublicationPage : ModelBase @@ -72,4 +76,4 @@ public class SnPublicationPage : ModelBase public Guid SiteId { get; set; } [JsonIgnore] public SnPublicationSite Site { get; set; } = null!; -} \ No newline at end of file +} diff --git a/DysonNetwork.Zone/Customization/PostPageConfig.cs b/DysonNetwork.Zone/Customization/PostPageConfig.cs new file mode 100644 index 0000000..ccc190d --- /dev/null +++ b/DysonNetwork.Zone/Customization/PostPageConfig.cs @@ -0,0 +1,18 @@ +namespace DysonNetwork.Zone.Customization; + +// PostPage.Config -> filter +public class PostPageFilterConfig +{ + public List Types { get; set; } + public string? PubName { get; set; } + public string? OrderBy { get; set; } + public bool OrderDesc { get; set; } = true; +} + +// PostPage.Config -> layout +public class PostPageLayoutConfig +{ + public string? Title { get; set; } + public string? Description { get; set; } + public bool ShowPub { get; set; } = true; +} \ No newline at end of file diff --git a/DysonNetwork.Zone/Pages/Posts.cshtml b/DysonNetwork.Zone/Pages/Posts.cshtml index f2f98bc..6964b03 100644 --- a/DysonNetwork.Zone/Pages/Posts.cshtml +++ b/DysonNetwork.Zone/Pages/Posts.cshtml @@ -2,10 +2,9 @@ @model DysonNetwork.Zone.Pages.PostsModel @{ Layout = "_LayoutContained"; - const string defaultAvatar = "https://www.gravatar.com/avatar/00000000000000000000000000000000?d=mp"; - var pageTitle = "Posts"; - var pageDescription = "A collection of posts."; + var pageTitle = Model.LayoutConfig?.Title ?? "Posts"; + var pageDescription = Model.LayoutConfig?.Description ?? "A collection of posts."; string? ogImageUrl = null; var canonicalUrl = $"{Request.Scheme}://{Request.Host}{Request.Path}{Request.QueryString}"; var siteName = Model.Site?.Name ?? "Solar Network"; @@ -48,7 +47,7 @@

- Posts + @pageTitle

@@ -75,8 +74,8 @@
@{ const int maxPagesToShow = 5; // e.g., 2 before, current, 2 after - var startPage = Math.Max(1, Model.CurrentPage - (maxPagesToShow / 2)); - var endPage = Math.Min(Model.TotalPages, Model.CurrentPage + (maxPagesToShow / 2)); + var startPage = Math.Max(1, Model.Index - (maxPagesToShow / 2)); + var endPage = Math.Min(Model.TotalPages, Model.Index + (maxPagesToShow / 2)); // Adjust startPage and endPage to ensure exactly maxPagesToShow are shown if possible if (endPage - startPage + 1 < maxPagesToShow) @@ -92,15 +91,14 @@ } } - « + « @if (startPage > 1) { + class="join-item btn @(1 == Model.Index ? "btn-active" : "")"> 1 @if (startPage > 2) @@ -111,11 +109,8 @@ @for (var idx = startPage; idx <= endPage; idx++) { - var pageIdx = idx; - - @pageIdx + + @idx } @@ -125,16 +120,14 @@ { ... } - + @Model.TotalPages } - » + »
} diff --git a/DysonNetwork.Zone/Pages/Posts.cshtml.cs b/DysonNetwork.Zone/Pages/Posts.cshtml.cs index 9c64d6e..1d48b1e 100644 --- a/DysonNetwork.Zone/Pages/Posts.cshtml.cs +++ b/DysonNetwork.Zone/Pages/Posts.cshtml.cs @@ -1,6 +1,7 @@ using DysonNetwork.Shared.Models; using DysonNetwork.Shared.Proto; using DysonNetwork.Shared.Registry; +using DysonNetwork.Zone.Customization; using DysonNetwork.Zone.Publication; using Microsoft.AspNetCore.Mvc; // Add this using statement @@ -15,34 +16,54 @@ public class PostsModel( MarkdownConverter markdownConverter ) : PageModel { - [FromQuery] public bool ShowAll { get; set; } = false; - public SnPublicationSite? Site { get; set; } public SnPublisher? Publisher { get; set; } public List Posts { get; set; } = []; public int TotalCount { get; set; } - public int CurrentPage { get; set; } + public int Index { get; set; } public int PageSize { get; set; } = 10; public int TotalPages => (int)Math.Ceiling(TotalCount / (double)PageSize); - public async Task OnGetAsync(int currentPage = 1) - { - Site = HttpContext.Items[PublicationSiteMiddleware.SiteContextKey] as SnPublicationSite; - CurrentPage = currentPage; + public PostPageFilterConfig? FilterConfig { get; set; } + public PostPageLayoutConfig? LayoutConfig { get; set; } - Publisher = await rps.GetPublisher(id: Site!.PublisherId.ToString()); + public async Task OnGetAsync(int index = 1) + { + FilterConfig = HttpContext.Items["PostPage_FilterConfig"] as PostPageFilterConfig; + LayoutConfig = HttpContext.Items["PostPage_LayoutConfig"] as PostPageLayoutConfig; + Site = HttpContext.Items[PublicationSiteMiddleware.SiteContextKey] as SnPublicationSite; + Index = index; + + Publisher = FilterConfig?.PubName is not null + ? await rps.GetPublisher(FilterConfig.PubName) + : await rps.GetPublisher(id: Site!.PublisherId.ToString()); var request = new ListPostsRequest { - OrderBy = "date", - OrderDesc = true, + OrderBy = FilterConfig?.OrderBy, + OrderDesc = FilterConfig?.OrderDesc ?? true, PageSize = PageSize, - PageToken = ((CurrentPage - 1) * PageSize).ToString(), - PublisherId = Site!.PublisherId.ToString() + PageToken = ((Index - 1) * PageSize).ToString(), + PublisherId = Publisher!.Id.ToString() }; - if (!ShowAll) request.Types_.Add(DysonNetwork.Shared.Proto.PostType.Article); + if (FilterConfig?.Types is not null) + { + foreach (var type in FilterConfig.Types) + { + request.Types_.Add(type switch + { + 0 => DysonNetwork.Shared.Proto.PostType.Moment, + 1 => DysonNetwork.Shared.Proto.PostType.Article, + _ => DysonNetwork.Shared.Proto.PostType.Unspecified, + }); + } + } + else + { + request.Types_.Add(DysonNetwork.Shared.Proto.PostType.Article); + } var response = await postClient.ListPostsAsync(request); diff --git a/DysonNetwork.Zone/Pages/Shared/_PostItem.cshtml b/DysonNetwork.Zone/Pages/Shared/_PostItem.cshtml index fc0411d..10a8cea 100644 --- a/DysonNetwork.Zone/Pages/Shared/_PostItem.cshtml +++ b/DysonNetwork.Zone/Pages/Shared/_PostItem.cshtml @@ -80,8 +80,7 @@
Posted on @Model.CreatedAt.ToDateTimeOffset().ToString("yyyy-MM-dd")
- +
diff --git a/DysonNetwork.Zone/Publication/PublicationSiteMiddleware.cs b/DysonNetwork.Zone/Publication/PublicationSiteMiddleware.cs index 639fb40..7528c49 100644 --- a/DysonNetwork.Zone/Publication/PublicationSiteMiddleware.cs +++ b/DysonNetwork.Zone/Publication/PublicationSiteMiddleware.cs @@ -1,5 +1,7 @@ using System.Text.Json; using DysonNetwork.Shared.Models; +using DysonNetwork.Shared.Proto; +using DysonNetwork.Zone.Customization; using DysonNetwork.Zone.Pages.Dynamic; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Mvc; @@ -76,6 +78,18 @@ public class PublicationSiteMiddleware(RequestDelegate next) when page.Config.TryGetValue("target", out var tgt) && tgt is JsonElement redirectUrl: context.Response.Redirect(redirectUrl.ToString()); return; + case PublicationPageType.PostPage: + PostPageFilterConfig? filterConfig = null; + if (page.Config.TryGetValue("filter", out var filter) && filter is JsonElement filterJson) + filterConfig = filterJson.Deserialize(GrpcTypeHelper.SerializerOptions); + PostPageLayoutConfig? layoutConfig = null; + if (page.Config.TryGetValue("layout", out var layout) && layout is JsonElement layoutJson) + layoutConfig = layoutJson.Deserialize(GrpcTypeHelper.SerializerOptions); + context.Items["PostPage_LayoutConfig"] = layoutConfig; + context.Items["PostPage_FilterConfig"] = filterConfig; + context.Request.Path = "/Posts"; + await next(context); + return; default: throw new ArgumentOutOfRangeException(); }