feat: add edit post feature in blog posts (#384)

* feat: add edit post feature

* fix: remove edit button except on post detail pages

* docs: update site config docs for editPost

Resolves #191
---------

Co-authored-by: satnaing <satnaingdev@gmail.com>
This commit is contained in:
Patrick Wilson
2024-10-11 19:14:17 +08:00
committed by GitHub
parent cd417f5b7d
commit 0bc8eeeac8
6 changed files with 76 additions and 13 deletions
+38 -2
View File
@@ -1,11 +1,17 @@
import { LOCALE } from "@config"; import { LOCALE, SITE } from "@config";
import type { CollectionEntry } from "astro:content";
interface DatetimesProps { interface DatetimesProps {
pubDatetime: string | Date; pubDatetime: string | Date;
modDatetime: string | Date | undefined | null; modDatetime: string | Date | undefined | null;
} }
interface Props extends DatetimesProps { interface EditPostProps {
editPost?: CollectionEntry<"blog">["data"]["editPost"];
postId?: CollectionEntry<"blog">["id"];
}
interface Props extends DatetimesProps, EditPostProps {
size?: "sm" | "lg"; size?: "sm" | "lg";
className?: string; className?: string;
} }
@@ -15,6 +21,8 @@ export default function Datetime({
modDatetime, modDatetime,
size = "sm", size = "sm",
className = "", className = "",
editPost,
postId,
}: Props) { }: Props) {
return ( return (
<div <div
@@ -42,6 +50,7 @@ export default function Datetime({
pubDatetime={pubDatetime} pubDatetime={pubDatetime}
modDatetime={modDatetime} modDatetime={modDatetime}
/> />
{size === "lg" && <EditPost editPost={editPost} postId={postId} />}
</span> </span>
</div> </div>
); );
@@ -72,3 +81,30 @@ const FormattedDatetime = ({ pubDatetime, modDatetime }: DatetimesProps) => {
</> </>
); );
}; };
const EditPost = ({ editPost, postId }: EditPostProps) => {
let editPostUrl = editPost?.url ?? SITE?.editPost?.url ?? "";
const showEditPost = !editPost?.disabled && editPostUrl.length > 0;
const appendFilePath =
editPost?.appendFilePath ?? SITE?.editPost?.appendFilePath ?? false;
if (appendFilePath && postId) {
editPostUrl += `/${postId}`;
}
const editPostText = editPost?.text ?? SITE?.editPost?.text ?? "Edit";
return (
showEditPost && (
<>
<span aria-hidden="true"> | </span>
<a
className="hover:opacity-75"
href={editPostUrl}
rel="noopener noreferrer"
target="_blank"
>
{editPostText}
</a>
</>
)
);
};
+5
View File
@@ -11,6 +11,11 @@ export const SITE: Site = {
postPerIndex: 4, postPerIndex: 4,
postPerPage: 3, postPerPage: 3,
scheduledPostMargin: 15 * 60 * 1000, // 15 minutes scheduledPostMargin: 15 * 60 * 1000, // 15 minutes
editPost: {
url: "https://github.com/satnaing/astro-paper/edit/main/src/content/blog",
text: "Suggest Changes",
appendFilePath: true,
},
}; };
export const LOCALE = { export const LOCALE = {
@@ -33,13 +33,18 @@ export const SITE = {
lightAndDarkMode: true, lightAndDarkMode: true,
postPerPage: 3, postPerPage: 3,
scheduledPostMargin: 15 * 60 * 1000, // 15 minutes scheduledPostMargin: 15 * 60 * 1000, // 15 minutes
editPost: {
url: "https://github.com/satnaing/astro-paper/edit/main/src/content/blog",
text: "Suggest Changes",
appendFilePath: true,
},
}; };
``` ```
Here are SITE configuration options Here are SITE configuration options
| Options | Description | | Options | Description |
| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `website` | Your deployed website url | | `website` | Your deployed website url |
| `author` | Your name | | `author` | Your name |
| `desc` | Your site description. Useful for SEO and social media sharing. | | `desc` | Your site description. Useful for SEO and social media sharing. |
@@ -49,6 +54,7 @@ Here are SITE configuration options
| `postPerIndex` | The number of posts to be displayed at the home page under `Recent` section. | | `postPerIndex` | The number of posts to be displayed at the home page under `Recent` section. |
| `postPerPage` | You can specify how many posts will be displayed in each posts page. (eg: if you set SITE.postPerPage to 3, each page will only show 3 posts per page) | | `postPerPage` | You can specify how many posts will be displayed in each posts page. (eg: if you set SITE.postPerPage to 3, each page will only show 3 posts per page) |
| `scheduledPostMargin` | In Production mode, posts with a future `pubDatetime` will not be visible. However, if a post's `pubDatetime` is within the next 15 minutes, it will be visible. You can set `scheduledPostMargin` if you don't like the default 15 minutes margin. | | `scheduledPostMargin` | In Production mode, posts with a future `pubDatetime` will not be visible. However, if a post's `pubDatetime` is within the next 15 minutes, it will be visible. You can set `scheduledPostMargin` if you don't like the default 15 minutes margin. |
| `editPost` | This option allows users to suggest changes to a blog post by providing an edit link under blog post titles. This feature can be disabled by removing it from the `SITE` config. You can also set `appendFilePath` to `true` to automatically append the file path of the post to the url, directing users to the specific post they wish to edit. |
## Configuring locale ## Configuring locale
+8
View File
@@ -22,6 +22,14 @@ const blog = defineCollection({
.optional(), .optional(),
description: z.string(), description: z.string(),
canonicalURL: z.string().optional(), canonicalURL: z.string().optional(),
editPost: z
.object({
disabled: z.boolean().optional(),
url: z.string().optional(),
text: z.string().optional(),
appendFilePath: z.boolean().optional(),
})
.optional(),
}), }),
}); });
+3
View File
@@ -25,6 +25,7 @@ const {
pubDatetime, pubDatetime,
modDatetime, modDatetime,
tags, tags,
editPost,
} = post.data; } = post.data;
const { Content } = await post.render(); const { Content } = await post.render();
@@ -82,6 +83,8 @@ const nextPost =
modDatetime={modDatetime} modDatetime={modDatetime}
size="lg" size="lg"
className="my-2" className="my-2"
editPost={editPost}
postId={post.id}
/> />
<article id="article" class="prose mx-auto mt-8 max-w-3xl"> <article id="article" class="prose mx-auto mt-8 max-w-3xl">
<Content /> <Content />
+5
View File
@@ -11,6 +11,11 @@ export type Site = {
postPerIndex: number; postPerIndex: number;
postPerPage: number; postPerPage: number;
scheduledPostMargin: number; scheduledPostMargin: number;
editPost?: {
url?: URL["href"];
text?: string;
appendFilePath?: boolean;
};
}; };
export type SocialObjects = { export type SocialObjects = {