fix release version 1.11.0
This commit is contained in:
@@ -1,92 +0,0 @@
|
||||
import { Typography } from "@/components/typography";
|
||||
import { buttonVariants } from "@/components/ui/button";
|
||||
import { Author, getAllBlogStaticPaths, getBlogForSlug } from "@/lib/markdown";
|
||||
import { ArrowLeftIcon } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { notFound } from "next/navigation";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||
import { formatDate } from "@/lib/utils";
|
||||
import { ScrollToTop } from "@/components/scroll-to-top";
|
||||
|
||||
type PageProps = {
|
||||
params: { slug: string };
|
||||
};
|
||||
|
||||
export async function generateMetadata({ params: { slug } }: PageProps) {
|
||||
const res = await getBlogForSlug(slug);
|
||||
if (!res) return null;
|
||||
const { frontmatter } = res;
|
||||
return {
|
||||
title: frontmatter.title,
|
||||
description: frontmatter.description,
|
||||
};
|
||||
}
|
||||
|
||||
export async function generateStaticParams() {
|
||||
const val = await getAllBlogStaticPaths();
|
||||
if (!val) return [];
|
||||
return val.map((it) => ({ slug: it }));
|
||||
}
|
||||
|
||||
export default async function BlogPage({ params: { slug } }: PageProps) {
|
||||
const res = await getBlogForSlug(slug);
|
||||
if (!res) notFound();
|
||||
return (
|
||||
<div className="lg:w-[60%] sm:[95%] md:[75%] mx-auto">
|
||||
<Link
|
||||
className={buttonVariants({
|
||||
variant: "link",
|
||||
className: "!mx-0 !px-0 mb-7 !-ml-1 ",
|
||||
})}
|
||||
href="/blog"
|
||||
>
|
||||
<ArrowLeftIcon className="w-4 h-4 mr-1.5" /> Back to blog
|
||||
</Link>
|
||||
<div className="flex flex-col gap-3 pb-7 w-full mb-2">
|
||||
<p className="text-muted-foreground text-sm">
|
||||
{formatDate(res.frontmatter.date)}
|
||||
</p>
|
||||
<h1 className="sm:text-4xl text-3xl font-extrabold">
|
||||
{res.frontmatter.title}
|
||||
</h1>
|
||||
<div className="mt-6 flex flex-col gap-3">
|
||||
<p className="text-sm text-muted-foreground">Posted by</p>
|
||||
<Authors authors={res.frontmatter.authors} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="!w-full">
|
||||
<Typography>{res.content}</Typography>
|
||||
</div>
|
||||
<ScrollToTop />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Authors({ authors }: { authors: Author[] }) {
|
||||
return (
|
||||
<div className="flex items-center gap-8 flex-wrap">
|
||||
{authors.map((author) => {
|
||||
return (
|
||||
<Link
|
||||
href={author.handleUrl}
|
||||
className="flex items-center gap-2"
|
||||
key={author.username}
|
||||
>
|
||||
<Avatar className="w-10 h-10">
|
||||
<AvatarImage src={author.avatar} />
|
||||
<AvatarFallback>
|
||||
{author.username.slice(0, 2).toUpperCase()}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="">
|
||||
<p className="text-sm font-medium">{author.username}</p>
|
||||
<p className="font-code text-[13px] text-muted-foreground">
|
||||
@{author.handle}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
import { PropsWithChildren } from "react";
|
||||
|
||||
export default function BlogLayout({ children }: PropsWithChildren) {
|
||||
return (
|
||||
<div className="flex flex-col items-start justify-center pt-8 pb-10 w-full mx-auto">
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||
import { Author, BlogMdxFrontmatter, getAllBlogs } from "@/lib/markdown";
|
||||
import { formatDate2, stringToDate } from "@/lib/utils";
|
||||
import { getMetadata } from "@/app/layout";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { AuroraText } from "@/components/ui/aurora";
|
||||
import { ShineBorder } from "@/components/ui/shine-border";
|
||||
import docuConfig from "@/docu.json";
|
||||
|
||||
export const metadata = getMetadata({
|
||||
title: "Blog",
|
||||
description: "Discover the latest updates, tutorials, and insights on DocuBook.",
|
||||
});
|
||||
const { meta } = docuConfig;
|
||||
export default async function BlogIndexPage() {
|
||||
const blogs = (await getAllBlogs()).sort(
|
||||
(a, b) => stringToDate(b.date).getTime() - stringToDate(a.date).getTime()
|
||||
);
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center px-2 py-8 text-center sm:py-36">
|
||||
<div className="w-full max-w-[800px] pb-8">
|
||||
<AuroraText className="text-lg"># Stay Informed, Stay Ahead</AuroraText>
|
||||
<h1 className="mb-4 text-2xl font-bold sm:text-5xl">
|
||||
Blog Posts
|
||||
</h1>
|
||||
<p className="mb-8 sm:text-xl text-muted-foreground">
|
||||
Explore updates, tips, and deep dives from the {meta.title}.
|
||||
</p>
|
||||
</div>
|
||||
<div className="text-left grid md:grid-cols-3 sm:grid-cols-2 grid-cols-1 sm:gap-8 gap-4 my-6">
|
||||
{blogs.map((blog) => (
|
||||
<BlogCard {...blog} slug={blog.slug} key={blog.slug} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function BlogCard({
|
||||
date,
|
||||
title,
|
||||
description,
|
||||
slug,
|
||||
cover,
|
||||
authors,
|
||||
}: BlogMdxFrontmatter & { slug: string }) {
|
||||
return (
|
||||
<Link
|
||||
href={`/blog/${slug}`}
|
||||
className="flex flex-col gap-2 items-start border rounded-md max-h-[420px] min-h-[420px]"
|
||||
>
|
||||
<div className="w-full">
|
||||
<Image
|
||||
src={cover}
|
||||
alt={title}
|
||||
width={400}
|
||||
height={150}
|
||||
quality={80}
|
||||
className="w-full rounded-md object-cover h-[200px]"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col items-start px-3 py-3 gap-2 mb-auto">
|
||||
<h3 className="text-md font-semibold line-clamp-2">{title}</h3>
|
||||
<p className="text-sm text-muted-foreground line-clamp-3">{description}</p>
|
||||
</div>
|
||||
<div className="flex items-center justify-between w-full px-3 mb-6">
|
||||
<p className="text-[13px] text-muted-foreground">
|
||||
Published on {formatDate2(date)}
|
||||
</p>
|
||||
<AvatarGroup users={authors} />
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
function AvatarGroup({ users, max = 4 }: { users: Author[]; max?: number }) {
|
||||
const displayUsers = users.slice(0, max);
|
||||
const remainingUsers = Math.max(users.length - max, 0);
|
||||
|
||||
return (
|
||||
<div className="flex items-center">
|
||||
{displayUsers.map((user, index) => (
|
||||
<Avatar
|
||||
key={user.username}
|
||||
className={`inline-block border-2 w-9 h-9 border-background ${
|
||||
index !== 0 ? "-ml-3" : ""
|
||||
} `}
|
||||
>
|
||||
<AvatarImage src={user.avatar} alt={user.username} />
|
||||
<AvatarFallback>
|
||||
{user.username.slice(0, 2).toUpperCase()}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
))}
|
||||
{remainingUsers > 0 && (
|
||||
<Avatar className="-ml-3 inline-block border-2 border-background hover:translate-y-1 transition-transform">
|
||||
<AvatarFallback>+{remainingUsers}</AvatarFallback>
|
||||
</Avatar>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
export default function ChangelogLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<div className="flex items-start gap-8">
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
import { Suspense } from "react";
|
||||
import { getChangelogEntries } from "@/lib/changelog";
|
||||
import { VersionEntry } from "@/components/changelog/version-entry";
|
||||
import { VersionToc } from "@/components/changelog/version-toc";
|
||||
import { FloatingVersionToc } from "@/components/changelog/floating-version";
|
||||
|
||||
export default async function ChangelogPage() {
|
||||
const entries = await getChangelogEntries();
|
||||
|
||||
return (
|
||||
<div className="flex items-start">
|
||||
<Suspense fallback={<div className="lg:flex hidden flex-[1.5]" />}>
|
||||
<VersionToc
|
||||
versions={entries.map(({ version, date }) => ({ version, date }))}
|
||||
/>
|
||||
</Suspense>
|
||||
|
||||
<main className="flex-1 md:flex-[5.25] min-w-0 max-w-[800px]">
|
||||
<div className="relative">
|
||||
<div className="absolute left-0 top-0 h-full w-px bg-border md:block hidden" />
|
||||
<div className="md:px-12 md:py-8 max-md:py-10">
|
||||
{entries.map((entry, index) => (
|
||||
<section
|
||||
id={`version-${entry.version}`}
|
||||
key={entry.version}
|
||||
className="scroll-mt-20" // Tambahkan margin atas saat scroll
|
||||
>
|
||||
<VersionEntry {...entry} isLast={index === entries.length - 1} />
|
||||
</section>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
{/* Floating TOC for smaller screens */}
|
||||
{entries.length > 0 && (
|
||||
<FloatingVersionToc
|
||||
versions={entries.map(({ version, date }) => ({ version, date }))}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -8,7 +8,6 @@ import EditThisPage from "@/components/edit-on-github";
|
||||
import { formatDate2 } from "@/lib/utils";
|
||||
import docuConfig from "@/docu.json";
|
||||
import MobToc from "@/components/mob-toc";
|
||||
import { ScrollToTop } from "@/components/scroll-to-top";
|
||||
|
||||
const { meta } = docuConfig;
|
||||
|
||||
@@ -78,11 +77,9 @@ export default async function DocsPage({ params: { slug = [] } }: PageProps) {
|
||||
|
||||
return (
|
||||
<div className="flex items-start gap-10">
|
||||
<div className="flex-[4.5] pt-10">
|
||||
<div className="flex-[4.5] pt-4 lg:pt-10">
|
||||
<MobToc tocs={tocs} />
|
||||
<DocsBreadcrumb paths={slug} />
|
||||
<div className="mb-8">
|
||||
<MobToc tocs={tocs} />
|
||||
</div>
|
||||
<Typography>
|
||||
<h1 className="text-3xl !-mt-0.5">{title}</h1>
|
||||
<p className="-mt-4 text-muted-foreground text-[16.5px]">{description}</p>
|
||||
@@ -101,7 +98,6 @@ export default async function DocsPage({ params: { slug = [] } }: PageProps) {
|
||||
</div>
|
||||
<Pagination pathname={pathName} />
|
||||
</Typography>
|
||||
<ScrollToTop />
|
||||
</div>
|
||||
<Toc path={pathName} />
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Leftbar } from "@/components/leftbar";
|
||||
import { MDXProviderWrapper } from "@/components/markdown/mdx-provider";
|
||||
|
||||
export default function DocsLayout({
|
||||
children,
|
||||
@@ -9,10 +8,8 @@ export default function DocsLayout({
|
||||
return (
|
||||
<div className="flex items-start gap-8">
|
||||
<Leftbar key="leftbar" />
|
||||
<div className="flex-[5.25]">
|
||||
<MDXProviderWrapper>
|
||||
{children}
|
||||
</MDXProviderWrapper>
|
||||
<div className="flex-[5.25] p-4">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -15,7 +15,7 @@ export default function Home() {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center px-2 py-8 text-center sm:py-36">
|
||||
<Link
|
||||
href="/changelog"
|
||||
href="/docs/getting-started/changelog"
|
||||
className="mb-5 sm:text-lg flex items-center gap-2 underline underline-offset-4 sm:-mt-12"
|
||||
>
|
||||
<div className="z-10 flex min-h-10 items-center justify-center max-[800px]:mt-10">
|
||||
@@ -25,7 +25,7 @@ export default function Home() {
|
||||
)}
|
||||
>
|
||||
<AnimatedShinyText className="inline-flex items-center justify-center px-4 py-1 transition ease-out hover:text-neutral-100 hover:duration-300 hover:dark:text-neutral-200">
|
||||
<span>🚀 New Version - Release v1.9.0</span>
|
||||
<span>🚀 New Version - Release v1.11.0</span>
|
||||
<ArrowRightIcon className="ml-1 size-3 transition-transform duration-300 ease-in-out group-hover:translate-x-0.5" />
|
||||
</AnimatedShinyText>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user