mirror of
https://github.com/ChenQihan666/MyBlog-Next.git
synced 2026-08-14 11:29:33 +08:00
refactor: replace pagination logic with Astro built-in pagination (#376)
This commit is contained in:
committed by
GitHub
parent
70b2486293
commit
08b1676cdd
@@ -1,49 +1,43 @@
|
|||||||
---
|
---
|
||||||
|
import type { Page } from "astro";
|
||||||
import LinkButton from "./LinkButton.astro";
|
import LinkButton from "./LinkButton.astro";
|
||||||
|
import type { CollectionEntry } from "astro:content";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
currentPage: number;
|
page: Page<CollectionEntry<"blog">>;
|
||||||
totalPages: number;
|
|
||||||
prevUrl: string;
|
|
||||||
nextUrl: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { currentPage, totalPages, prevUrl, nextUrl } = Astro.props;
|
const { page } = Astro.props;
|
||||||
|
|
||||||
const prev = currentPage > 1 ? "" : "disabled";
|
|
||||||
const next = currentPage < totalPages ? "" : "disabled";
|
|
||||||
const isPrevDisabled = prev === "disabled";
|
|
||||||
const isNextDisabled = next === "disabled";
|
|
||||||
---
|
---
|
||||||
|
|
||||||
{
|
{
|
||||||
totalPages > 1 && (
|
page.lastPage > 1 && (
|
||||||
<nav class="pagination-wrapper" aria-label="Pagination">
|
<nav class="pagination-wrapper" aria-label="Pagination">
|
||||||
<LinkButton
|
<LinkButton
|
||||||
disabled={isPrevDisabled}
|
disabled={!page.url.prev}
|
||||||
href={prevUrl}
|
href={page.url.prev as string}
|
||||||
className={`mr-4 select-none ${prev}`}
|
className={`mr-4 select-none ${page.url.prev ? "" : "disabled"}`}
|
||||||
ariaLabel="Previous"
|
ariaLabel="Previous"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
class:list={[{ "disabled-svg": isPrevDisabled }]}
|
class:list={[{ "disabled-svg": !page.url.prev }]}
|
||||||
>
|
>
|
||||||
<path d="M12.707 17.293 8.414 13H18v-2H8.414l4.293-4.293-1.414-1.414L4.586 12l6.707 6.707z" />
|
<path d="M12.707 17.293 8.414 13H18v-2H8.414l4.293-4.293-1.414-1.414L4.586 12l6.707 6.707z" />
|
||||||
</svg>
|
</svg>
|
||||||
Prev
|
Prev
|
||||||
</LinkButton>
|
</LinkButton>
|
||||||
{currentPage} / {totalPages}
|
{page.currentPage} / {page.lastPage}
|
||||||
<LinkButton
|
<LinkButton
|
||||||
disabled={isNextDisabled}
|
disabled={!page.url.next}
|
||||||
href={nextUrl}
|
href={page.url.next as string}
|
||||||
className={`ml-4 select-none ${next}`}
|
className={`mx-4 select-none ${page.url.next ? "" : "disabled"}`}
|
||||||
ariaLabel="Next"
|
ariaLabel="Next"
|
||||||
>
|
>
|
||||||
Next
|
Next
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
class:list={[{ "disabled-svg": isNextDisabled }]}
|
class:list={[{ "disabled-svg": !page.url.next }]}
|
||||||
>
|
>
|
||||||
<path d="m11.293 17.293 1.414 1.414L19.414 12l-6.707-6.707-1.414 1.414L15.586 11H6v2h9.586z" />
|
<path d="m11.293 17.293 1.414 1.414L19.414 12l-6.707-6.707-1.414 1.414L15.586 11H6v2h9.586z" />
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
+7
-13
@@ -1,5 +1,4 @@
|
|||||||
---
|
---
|
||||||
import type { CollectionEntry } from "astro:content";
|
|
||||||
import Layout from "@layouts/Layout.astro";
|
import Layout from "@layouts/Layout.astro";
|
||||||
import Main from "@layouts/Main.astro";
|
import Main from "@layouts/Main.astro";
|
||||||
import Header from "@components/Header.astro";
|
import Header from "@components/Header.astro";
|
||||||
@@ -7,14 +6,14 @@ import Footer from "@components/Footer.astro";
|
|||||||
import Pagination from "@components/Pagination.astro";
|
import Pagination from "@components/Pagination.astro";
|
||||||
import Card from "@components/Card";
|
import Card from "@components/Card";
|
||||||
import { SITE } from "@config";
|
import { SITE } from "@config";
|
||||||
|
import type { Page } from "astro";
|
||||||
|
import type { CollectionEntry } from "astro:content";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
currentPage: number;
|
page: Page<CollectionEntry<"blog">>;
|
||||||
totalPages: number;
|
|
||||||
paginatedPosts: CollectionEntry<"blog">[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { currentPage, totalPages, paginatedPosts } = Astro.props;
|
const { page } = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout title={`Posts | ${SITE.title}`}>
|
<Layout title={`Posts | ${SITE.title}`}>
|
||||||
@@ -22,19 +21,14 @@ const { currentPage, totalPages, paginatedPosts } = Astro.props;
|
|||||||
<Main pageTitle="Posts" pageDesc="All the articles I've posted.">
|
<Main pageTitle="Posts" pageDesc="All the articles I've posted.">
|
||||||
<ul>
|
<ul>
|
||||||
{
|
{
|
||||||
paginatedPosts.map(({ data, slug }) => (
|
page.data.map(({ data, slug }) => (
|
||||||
<Card href={`/posts/${slug}/`} frontmatter={data} />
|
<Card href={`/posts/${slug}/`} frontmatter={data} />
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
</ul>
|
</ul>
|
||||||
</Main>
|
</Main>
|
||||||
|
|
||||||
<Pagination
|
<Pagination {page} />
|
||||||
{currentPage}
|
|
||||||
{totalPages}
|
|
||||||
prevUrl={`/posts${currentPage - 1 !== 1 ? "/" + (currentPage - 1) : ""}/`}
|
|
||||||
nextUrl={`/posts/${currentPage + 1}/`}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Footer noMarginTop={totalPages > 1} />
|
<Footer noMarginTop={page.lastPage > 1} />
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
---
|
---
|
||||||
import { type CollectionEntry } from "astro:content";
|
|
||||||
import Layout from "@layouts/Layout.astro";
|
import Layout from "@layouts/Layout.astro";
|
||||||
import Main from "@layouts/Main.astro";
|
import Main from "@layouts/Main.astro";
|
||||||
import Header from "@components/Header.astro";
|
import Header from "@components/Header.astro";
|
||||||
@@ -7,16 +6,16 @@ import Footer from "@components/Footer.astro";
|
|||||||
import Card from "@components/Card";
|
import Card from "@components/Card";
|
||||||
import Pagination from "@components/Pagination.astro";
|
import Pagination from "@components/Pagination.astro";
|
||||||
import { SITE } from "@config";
|
import { SITE } from "@config";
|
||||||
|
import type { Page } from "astro";
|
||||||
|
import type { CollectionEntry } from "astro:content";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
currentPage: number;
|
page: Page<CollectionEntry<"blog">>;
|
||||||
totalPages: number;
|
|
||||||
paginatedPosts: CollectionEntry<"blog">[];
|
|
||||||
tag: string;
|
tag: string;
|
||||||
tagName: string;
|
tagName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { currentPage, totalPages, paginatedPosts, tag, tagName } = Astro.props;
|
const { page, tag, tagName } = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout title={`Tag: ${tagName} | ${SITE.title}`}>
|
<Layout title={`Tag: ${tagName} | ${SITE.title}`}>
|
||||||
@@ -29,21 +28,14 @@ const { currentPage, totalPages, paginatedPosts, tag, tagName } = Astro.props;
|
|||||||
<h1 slot="title" transition:name={tag}>{`Tag:${tag}`}</h1>
|
<h1 slot="title" transition:name={tag}>{`Tag:${tag}`}</h1>
|
||||||
<ul>
|
<ul>
|
||||||
{
|
{
|
||||||
paginatedPosts.map(({ data, slug }) => (
|
page.data.map(({ data, slug }) => (
|
||||||
<Card href={`/posts/${slug}/`} frontmatter={data} />
|
<Card href={`/posts/${slug}/`} frontmatter={data} />
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
</ul>
|
</ul>
|
||||||
</Main>
|
</Main>
|
||||||
|
|
||||||
<Pagination
|
<Pagination {page} />
|
||||||
{currentPage}
|
|
||||||
{totalPages}
|
|
||||||
prevUrl={`/tags/${tag}${
|
|
||||||
currentPage - 1 !== 1 ? "/" + (currentPage - 1) : ""
|
|
||||||
}/`}
|
|
||||||
nextUrl={`/tags/${tag}/${currentPage + 1}/`}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Footer noMarginTop={totalPages > 1} />
|
<Footer noMarginTop={page.lastPage > 1} />
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
import { SITE } from "@config";
|
||||||
|
import Posts from "@layouts/Posts.astro";
|
||||||
|
import type { GetStaticPaths } from "astro";
|
||||||
|
import { getCollection } from "astro:content";
|
||||||
|
|
||||||
|
export const getStaticPaths = (async ({ paginate }) => {
|
||||||
|
const posts = await getCollection("blog", ({ data }) => !data.draft);
|
||||||
|
return paginate(posts, { pageSize: SITE.postPerPage });
|
||||||
|
}) satisfies GetStaticPaths;
|
||||||
|
|
||||||
|
const { page } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<Posts {page} />
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
import { SITE } from "@config";
|
||||||
|
import Posts from "@layouts/Posts.astro";
|
||||||
|
import type { GetStaticPaths } from "astro";
|
||||||
|
import { getCollection } from "astro:content";
|
||||||
|
|
||||||
|
export const getStaticPaths = (async ({ paginate }) => {
|
||||||
|
const posts = await getCollection("blog", ({ data }) => !data.draft);
|
||||||
|
return paginate(posts, { pageSize: SITE.postPerPage });
|
||||||
|
}) satisfies GetStaticPaths;
|
||||||
|
|
||||||
|
const { page } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<Posts {page} />
|
||||||
@@ -1,10 +1,6 @@
|
|||||||
---
|
---
|
||||||
import { type CollectionEntry, getCollection } from "astro:content";
|
import { type CollectionEntry, getCollection } from "astro:content";
|
||||||
import Posts from "@layouts/Posts.astro";
|
|
||||||
import PostDetails from "@layouts/PostDetails.astro";
|
import PostDetails from "@layouts/PostDetails.astro";
|
||||||
import getSortedPosts from "@utils/getSortedPosts";
|
|
||||||
import getPageNumbers from "@utils/getPageNumbers";
|
|
||||||
import getPagination from "@utils/getPagination";
|
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
post: CollectionEntry<"blog">;
|
post: CollectionEntry<"blog">;
|
||||||
@@ -18,24 +14,10 @@ export async function getStaticPaths() {
|
|||||||
props: { post },
|
props: { post },
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const pagePaths = getPageNumbers(posts.length).map(pageNum => ({
|
return postResult;
|
||||||
params: { slug: String(pageNum) },
|
|
||||||
}));
|
|
||||||
|
|
||||||
return [...postResult, ...pagePaths];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { slug } = Astro.params;
|
|
||||||
const { post } = Astro.props;
|
const { post } = Astro.props;
|
||||||
|
|
||||||
const posts = await getCollection("blog");
|
|
||||||
|
|
||||||
const sortedPosts = getSortedPosts(posts);
|
|
||||||
|
|
||||||
const pagination = getPagination({
|
|
||||||
posts: sortedPosts,
|
|
||||||
page: slug,
|
|
||||||
});
|
|
||||||
---
|
---
|
||||||
|
|
||||||
{post ? <PostDetails post={post} /> : <Posts {...pagination} />}
|
<PostDetails post={post} />
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
---
|
|
||||||
import { getCollection } from "astro:content";
|
|
||||||
import Posts from "@layouts/Posts.astro";
|
|
||||||
import getSortedPosts from "@utils/getSortedPosts";
|
|
||||||
import getPagination from "@utils/getPagination";
|
|
||||||
|
|
||||||
const posts = await getCollection("blog");
|
|
||||||
|
|
||||||
const sortedPosts = getSortedPosts(posts);
|
|
||||||
|
|
||||||
const pagination = getPagination({
|
|
||||||
posts: sortedPosts,
|
|
||||||
page: 1,
|
|
||||||
isIndex: true,
|
|
||||||
});
|
|
||||||
---
|
|
||||||
|
|
||||||
<Posts {...pagination} />
|
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
import { getCollection } from "astro:content";
|
||||||
|
import TagPosts from "@layouts/TagPosts.astro";
|
||||||
|
import getUniqueTags from "@utils/getUniqueTags";
|
||||||
|
import getPostsByTag from "@utils/getPostsByTag";
|
||||||
|
import type { GetStaticPathsOptions } from "astro";
|
||||||
|
import { SITE } from "@config";
|
||||||
|
|
||||||
|
export async function getStaticPaths({ paginate }: GetStaticPathsOptions) {
|
||||||
|
const posts = await getCollection("blog");
|
||||||
|
const tags = getUniqueTags(posts);
|
||||||
|
|
||||||
|
return tags.flatMap(({ tag, tagName }) => {
|
||||||
|
const tagPosts = getPostsByTag(posts, tag);
|
||||||
|
|
||||||
|
return paginate(tagPosts, {
|
||||||
|
params: { tag },
|
||||||
|
props: { tagName },
|
||||||
|
pageSize: SITE.postPerPage,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const params = Astro.params;
|
||||||
|
const { tag } = params;
|
||||||
|
const { page, tagName } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<TagPosts {page} {tag} {tagName} />
|
||||||
@@ -1,44 +1,29 @@
|
|||||||
---
|
---
|
||||||
import { type CollectionEntry, getCollection } from "astro:content";
|
import { getCollection } from "astro:content";
|
||||||
import TagPosts from "@layouts/TagPosts.astro";
|
import TagPosts from "@layouts/TagPosts.astro";
|
||||||
import getUniqueTags from "@utils/getUniqueTags";
|
import getUniqueTags from "@utils/getUniqueTags";
|
||||||
import getPostsByTag from "@utils/getPostsByTag";
|
import getPostsByTag from "@utils/getPostsByTag";
|
||||||
import getPageNumbers from "@utils/getPageNumbers";
|
import type { GetStaticPathsOptions } from "astro";
|
||||||
import getPagination from "@utils/getPagination";
|
import { SITE } from "@config";
|
||||||
|
|
||||||
export interface Props {
|
export async function getStaticPaths({ paginate }: GetStaticPathsOptions) {
|
||||||
post: CollectionEntry<"blog">;
|
|
||||||
tag: string;
|
|
||||||
tagName: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
|
||||||
const posts = await getCollection("blog");
|
const posts = await getCollection("blog");
|
||||||
|
|
||||||
const tags = getUniqueTags(posts);
|
const tags = getUniqueTags(posts);
|
||||||
|
|
||||||
return tags.flatMap(({ tag, tagName }) => {
|
return tags.flatMap(({ tag, tagName }) => {
|
||||||
const tagPosts = getPostsByTag(posts, tag);
|
const tagPosts = getPostsByTag(posts, tag);
|
||||||
const totalPages = getPageNumbers(tagPosts.length);
|
|
||||||
|
|
||||||
return totalPages.map(page => ({
|
return paginate(tagPosts, {
|
||||||
params: { tag, page },
|
params: { tag },
|
||||||
props: { tag, tagName },
|
props: { tagName },
|
||||||
}));
|
pageSize: SITE.postPerPage,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const { page } = Astro.params;
|
const params = Astro.params;
|
||||||
const { tag, tagName } = Astro.props;
|
const { tag } = params;
|
||||||
|
const { page, tagName } = Astro.props;
|
||||||
const posts = await getCollection("blog", ({ data }) => !data.draft);
|
|
||||||
|
|
||||||
const postsByTag = getPostsByTag(posts, tag);
|
|
||||||
|
|
||||||
const pagination = getPagination({
|
|
||||||
posts: postsByTag,
|
|
||||||
page,
|
|
||||||
});
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<TagPosts {...pagination} {tag} {tagName} />
|
<TagPosts {page} {tag} {tagName} />
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
---
|
|
||||||
import { getCollection } from "astro:content";
|
|
||||||
import TagPosts from "@layouts/TagPosts.astro";
|
|
||||||
import getPostsByTag from "@utils/getPostsByTag";
|
|
||||||
import getPagination from "@utils/getPagination";
|
|
||||||
import getUniqueTags from "@utils/getUniqueTags";
|
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
|
||||||
const posts = await getCollection("blog");
|
|
||||||
|
|
||||||
const tags = getUniqueTags(posts);
|
|
||||||
|
|
||||||
return tags.map(({ tag, tagName }) => {
|
|
||||||
return {
|
|
||||||
params: { tag },
|
|
||||||
props: { tag, tagName, posts },
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const { tag, tagName, posts } = Astro.props;
|
|
||||||
|
|
||||||
const postsByTag = getPostsByTag(posts, tag);
|
|
||||||
|
|
||||||
const pagination = getPagination({
|
|
||||||
posts: postsByTag,
|
|
||||||
page: 1,
|
|
||||||
isIndex: true,
|
|
||||||
});
|
|
||||||
---
|
|
||||||
|
|
||||||
<TagPosts {...pagination} {tag} {tagName} />
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
import { SITE } from "@config";
|
|
||||||
|
|
||||||
const getPageNumbers = (numberOfPosts: number) => {
|
|
||||||
const numberOfPages = numberOfPosts / Number(SITE.postPerPage);
|
|
||||||
|
|
||||||
let pageNumbers: number[] = [];
|
|
||||||
for (let i = 1; i <= Math.ceil(numberOfPages); i++) {
|
|
||||||
pageNumbers = [...pageNumbers, i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return pageNumbers;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default getPageNumbers;
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
import { SITE } from "@config";
|
|
||||||
import getPageNumbers from "./getPageNumbers";
|
|
||||||
|
|
||||||
interface GetPaginationProps<T> {
|
|
||||||
posts: T;
|
|
||||||
page: string | number;
|
|
||||||
isIndex?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const getPagination = <T>({
|
|
||||||
posts,
|
|
||||||
page,
|
|
||||||
isIndex = false,
|
|
||||||
}: GetPaginationProps<T[]>) => {
|
|
||||||
const totalPagesArray = getPageNumbers(posts.length);
|
|
||||||
const totalPages = totalPagesArray.length;
|
|
||||||
|
|
||||||
const currentPage = isIndex
|
|
||||||
? 1
|
|
||||||
: page && !isNaN(Number(page)) && totalPagesArray.includes(Number(page))
|
|
||||||
? Number(page)
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
const lastPost = isIndex ? SITE.postPerPage : currentPage * SITE.postPerPage;
|
|
||||||
const startPost = isIndex ? 0 : lastPost - SITE.postPerPage;
|
|
||||||
const paginatedPosts = posts.slice(startPost, lastPost);
|
|
||||||
|
|
||||||
return {
|
|
||||||
totalPages,
|
|
||||||
currentPage,
|
|
||||||
paginatedPosts,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default getPagination;
|
|
||||||
Reference in New Issue
Block a user