Add draft functionality for pages

This commit is contained in:
tfmurad
2025-10-14 12:07:37 +06:00
parent ea3e56e1ec
commit 603af67eeb
16 changed files with 102 additions and 105 deletions
+13 -20
View File
@@ -1,6 +1,15 @@
import { glob } from "astro/loaders";
import { defineCollection, z } from "astro:content";
const commonFields = {
title: z.string(),
description: z.string(),
meta_title: z.string().optional(),
date: z.date().optional(),
image: z.string().optional(),
draft: z.boolean(),
};
// Post collection schema
const blogCollection = defineCollection({
loader: glob({ pattern: "**/*.{md,mdx}", base: "src/content/blog" }),
@@ -21,11 +30,7 @@ const blogCollection = defineCollection({
const authorsCollection = defineCollection({
loader: glob({ pattern: "**/*.{md,mdx}", base: "src/content/authors" }),
schema: z.object({
title: z.string(),
meta_title: z.string().optional(),
email: z.string().optional(),
image: z.string().optional(),
description: z.string().optional(),
...commonFields,
social: z
.array(
z
@@ -45,11 +50,7 @@ const authorsCollection = defineCollection({
const pagesCollection = defineCollection({
loader: glob({ pattern: "**/*.{md,mdx}", base: "src/content/pages" }),
schema: z.object({
title: z.string(),
meta_title: z.string().optional(),
description: z.string().optional(),
image: z.string().optional(),
draft: z.boolean().optional(),
...commonFields,
}),
});
@@ -57,11 +58,7 @@ const pagesCollection = defineCollection({
const aboutCollection = defineCollection({
loader: glob({ pattern: "**/*.{md,mdx}", base: "src/content/about" }),
schema: z.object({
title: z.string(),
meta_title: z.string().optional(),
description: z.string().optional(),
image: z.string().optional(),
draft: z.boolean().optional(),
...commonFields,
}),
});
@@ -69,11 +66,7 @@ const aboutCollection = defineCollection({
const contactCollection = defineCollection({
loader: glob({ pattern: "**/*.{md,mdx}", base: "src/content/contact" }),
schema: z.object({
title: z.string(),
meta_title: z.string().optional(),
description: z.string().optional(),
image: z.string().optional(),
draft: z.boolean().optional(),
...commonFields,
}),
});
+2
View File
@@ -2,4 +2,6 @@
title: "Authors"
meta_title: ""
description: "this is meta description"
image: ""
draft: false
---
+2
View File
@@ -2,4 +2,6 @@
title: "Blog Posts"
meta_title: ""
description: "this is meta description"
image: ""
draft: false
---
+2 -1
View File
@@ -1,6 +1,7 @@
---
title: "Contact"
meta_title: ""
description: "this is meta description"
meta_title: ""
image: ""
draft: false
---
+3 -2
View File
@@ -133,7 +133,8 @@ window.addEventListener("load", (e) => {
### Button
<Button label="Button" link="#" style="solid" />
<Button label="Solid" link="#" style="solid" />
<Button label="Outline" link="#" style="outline" />
---
@@ -243,7 +244,7 @@ Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
### Youtube video
<Youtube client:load id="C0DPdy98e4c" title="Play:Youtube"/>
<Youtube client:load id="C0DPdy98e4c" title="Play:Youtube" />
---
+1 -1
View File
@@ -14,7 +14,7 @@ const Youtube = ({
}, []);
// @ts-ignore
return <lite-youtube videoid={id} videotitle={title} {...rest} />;
return <lite-youtube className="rounded-lg" videoid={id} videotitle={title} {...rest} />;
};
export default Youtube;
+21 -7
View File
@@ -1,6 +1,7 @@
---
import {
getCollection,
getEntry,
type CollectionEntry,
type CollectionKey,
} from "astro:content";
@@ -16,15 +17,28 @@ type PageData = {
export const getSinglePage = async <C extends CollectionKey>(
collectionName: C
): Promise<CollectionEntry<C>[]> => {
const allPages = await getCollection(collectionName);
const allPages = await getCollection(
collectionName,
({ data, id }) => !(data as PageData)?.draft && !id.startsWith("-")
);
return allPages;
};
const removeIndex = allPages.filter((data) => data.id.match(/^(?!-)/));
export const getListPage = async <C extends CollectionKey>(
collectionName: C,
documentId: "-index" | string
): Promise<CollectionEntry<C>> => {
const data = (await getEntry(
collectionName,
documentId
)) as CollectionEntry<C> | null;
const removeDrafts = removeIndex.filter((data) => {
const pageData = data.data as PageData;
return pageData.draft !== true;
});
if (!data) {
throw new Error(
`No page found for the collection: ${collectionName} with filename: ${documentId}`
);
}
return removeDrafts;
return data;
};
---
+9 -5
View File
@@ -1,13 +1,17 @@
---
import ImageMod from "@/components/ImageMod.astro";
import Base from "@/layouts/Base.astro";
import { getListPage } from "@/lib/contentParser.astro";
import { markdownify } from "@/lib/utils/textConverter";
import type { CollectionEntry } from "astro:content";
import { getEntry, render } from "astro:content";
import { render } from "astro:content";
const about = (await getEntry("about", "-index")) as CollectionEntry<"about">;
const { Content } = await render(about);
const { title, description, meta_title, image } = about.data;
const aboutIndex = await getListPage("about", "-index");
const { Content } = await render(aboutIndex);
const { title, description, meta_title, image } = aboutIndex.data;
if (aboutIndex.data.draft) {
return Astro.redirect("/404");
}
---
<Base
+7 -8
View File
@@ -1,17 +1,16 @@
---
import AuthorCard from "@/components/AuthorCard.astro";
import Base from "@/layouts/Base.astro";
import { getSinglePage } from "@/lib/contentParser.astro";
import { getListPage, getSinglePage } from "@/lib/contentParser.astro";
import PageHeader from "@/partials/PageHeader.astro";
import { getEntry, type CollectionEntry } from "astro:content";
const COLLECTION_FOLDER = "authors";
const authorIndex = await getListPage("authors", "-index");
const authorIndex = (await getEntry(
COLLECTION_FOLDER,
"-index"
)) as CollectionEntry<"authors">;
const authors = await getSinglePage(COLLECTION_FOLDER);
if (authorIndex.data.draft) {
return Astro.redirect("/404");
}
const authors = await getSinglePage("authors");
---
<Base title={authorIndex.data.title}>
+5 -7
View File
@@ -3,20 +3,18 @@ import BlogCard from "@/components/BlogCard.astro";
import Pagination from "@/components/Pagination.astro";
import config from "@/config/config.json";
import Base from "@/layouts/Base.astro";
import { getSinglePage } from "@/lib/contentParser.astro";
import { getListPage, getSinglePage } from "@/lib/contentParser.astro";
import { getAllTaxonomy, getTaxonomy } from "@/lib/taxonomyParser.astro";
import { sortByDate } from "@/lib/utils/sortFunctions";
import PageHeader from "@/partials/PageHeader.astro";
import PostSidebar from "@/partials/PostSidebar.astro";
import type { CollectionEntry } from "astro:content";
import { getEntry } from "astro:content";
const BLOG_FOLDER = "blog";
const postIndex = (await getEntry(
BLOG_FOLDER,
"-index"
)) as CollectionEntry<"blog">;
const postIndex = await getListPage(BLOG_FOLDER, "-index");
if (postIndex.data.draft) {
return Astro.redirect("/404");
}
const posts = await getSinglePage(BLOG_FOLDER);
const allCategories = await getAllTaxonomy(BLOG_FOLDER, "categories");
const categories = await getTaxonomy(BLOG_FOLDER, "categories");
+7 -7
View File
@@ -3,21 +3,21 @@ import BlogCard from "@/components/BlogCard.astro";
import Pagination from "@/components/Pagination.astro";
import config from "@/config/config.json";
import Base from "@/layouts/Base.astro";
import { getSinglePage } from "@/lib/contentParser.astro";
import { getListPage, getSinglePage } from "@/lib/contentParser.astro";
import { getAllTaxonomy, getTaxonomy } from "@/lib/taxonomyParser.astro";
import { sortByDate } from "@/lib/utils/sortFunctions";
import PageHeader from "@/partials/PageHeader.astro";
import PostSidebar from "@/partials/PostSidebar.astro";
import type { CollectionEntry } from "astro:content";
import { getEntry } from "astro:content";
const BLOG_FOLDER = "blog";
const { slug } = Astro.params;
const postIndex = (await getEntry(
BLOG_FOLDER,
"-index"
)) as CollectionEntry<"blog">;
const postIndex = await getListPage(BLOG_FOLDER, "-index");
if (postIndex.data.draft) {
return Astro.redirect("/404");
}
const posts = await getSinglePage(BLOG_FOLDER);
const allCategories = await getAllTaxonomy(BLOG_FOLDER, "categories");
const categories = await getTaxonomy(BLOG_FOLDER, "categories");
+10 -7
View File
@@ -1,16 +1,16 @@
---
import config from "@/config/config.json";
import Base from "@/layouts/Base.astro";
import { getListPage } from "@/lib/contentParser.astro";
import PageHeader from "@/partials/PageHeader.astro";
import { getEntry } from "astro:content";
import type { CollectionEntry } from "astro:content";
const contact = (await getEntry(
"contact",
"-index"
)) as CollectionEntry<"contact">;
const contactIndex = await getListPage("contact", "-index");
const { contact_form_action }: { contact_form_action: string } = config.params;
const { title, description, meta_title, image } = contact.data;
const { title, description, meta_title, image } = contactIndex.data;
if (contactIndex.data.draft) {
return Astro.redirect("/404");
}
---
<Base
@@ -35,6 +35,7 @@ const { title, description, meta_title, image } = contact.data;
class="form-input"
placeholder="John Doe"
type="text"
required
/>
</div>
<div class="mb-6">
@@ -47,6 +48,7 @@ const { title, description, meta_title, image } = contact.data;
class="form-input"
placeholder="john.doe@email.com"
type="email"
required
/>
</div>
<div class="mb-6">
@@ -58,6 +60,7 @@ const { title, description, meta_title, image } = contact.data;
name="message"
class="form-input"
placeholder="Message goes here..."
required
rows="8"></textarea>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
+5 -28
View File
@@ -1,40 +1,17 @@
---
import ImageMod from "@/components/ImageMod.astro";
import Base from "@/layouts/Base.astro";
import { getListPage } from "@/lib/contentParser.astro";
import { markdownify } from "@/lib/utils/textConverter";
import CallToAction from "@/partials/CallToAction.astro";
import Testimonial from "@/partials/Testimonial.astro";
import type { Button, Feature } from "@/types";
import type { CollectionEntry } from "astro:content";
import { getEntry } from "astro:content";
import { FaCheck } from "react-icons/fa";
interface Homepage {
banner: {
title: string;
content: string;
image: string;
button: Button;
};
features: Feature[];
}
const homepage = await getListPage("homepage", "-index");
const call_to_action = await getListPage("ctaSection", "call-to-action");
const testimonial = await getListPage("testimonialSection", "testimonial");
const homepage = (await getEntry(
"homepage",
"-index"
)) as CollectionEntry<"homepage">;
const testimonial = (await getEntry(
"testimonialSection",
"testimonial"
)) as CollectionEntry<"testimonialSection">;
const call_to_action = (await getEntry(
"ctaSection",
"call-to-action"
)) as CollectionEntry<"ctaSection">;
const { banner, features } = homepage.data as Homepage;
const { banner, features } = homepage.data;
---
<Base>
+4
View File
@@ -57,3 +57,7 @@ code {
blockquote > p {
@apply my-0!;
}
button {
@apply cursor-pointer;
}