feat: move categories to directus
This commit is contained in:
@@ -1,8 +1,7 @@
|
|||||||
---
|
---
|
||||||
import { getCollection } from 'astro:content';
|
|
||||||
import { readItems } from '@directus/sdk';
|
import { readItems } from '@directus/sdk';
|
||||||
|
|
||||||
import type { Post } from '@lib/directusTypes';
|
import type { Post, Category } from '@lib/directusTypes';
|
||||||
|
|
||||||
import CategoryCard from '@components/cards/CategoryCard.astro';
|
import CategoryCard from '@components/cards/CategoryCard.astro';
|
||||||
import directus from '@lib/directus';
|
import directus from '@lib/directus';
|
||||||
@@ -43,7 +42,7 @@ const postMap: Map<string, Post[]> = posts
|
|||||||
return acc;
|
return acc;
|
||||||
}, new Map<string, Post[]>());
|
}, new Map<string, Post[]>());
|
||||||
|
|
||||||
const categories = (await getCollection('categories'))
|
const categories = (await directus.request(readItems('categories')))
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
const aCount = postMap.get(a.slug)?.length ?? 0;
|
const aCount = postMap.get(a.slug)?.length ?? 0;
|
||||||
const bCount = postMap.get(b.slug)?.length ?? 0;
|
const bCount = postMap.get(b.slug)?.length ?? 0;
|
||||||
@@ -81,8 +80,8 @@ const categories = (await getCollection('categories'))
|
|||||||
>
|
>
|
||||||
<CategoryCard
|
<CategoryCard
|
||||||
slug={category.slug}
|
slug={category.slug}
|
||||||
title={category.data.title}
|
title={category.title}
|
||||||
description={category.data.description}
|
description={category.description}
|
||||||
count={postMap.get(category.slug)?.length ?? 0}
|
count={postMap.get(category.slug)?.length ?? 0}
|
||||||
publishDate={timeago(postMap.get(category.slug)?.[0]?.published_date)}
|
publishDate={timeago(postMap.get(category.slug)?.[0]?.published_date)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Books'
|
|
||||||
description: 'Books I have read or listened to'
|
|
||||||
---
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Cloud'
|
|
||||||
description: "Its just someone else's server"
|
|
||||||
---
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Homelab'
|
|
||||||
description: 'What happens when rack servers find a home'
|
|
||||||
---
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Kubernetes'
|
|
||||||
description: 'The container orchestration system'
|
|
||||||
---
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Life'
|
|
||||||
description: 'Just random musings on everyday stuff'
|
|
||||||
---
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Minnesota'
|
|
||||||
description: 'Land of 10,000 Lakes'
|
|
||||||
---
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'PostgreSQL'
|
|
||||||
description: 'PostgreSQL is an open-source relational database management system (RDBMS)'
|
|
||||||
---
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Python'
|
|
||||||
description: 'Generally my go to language'
|
|
||||||
---
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Tool'
|
|
||||||
description: 'Usually just the software kind'
|
|
||||||
---
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'What Is?'
|
|
||||||
description: 'A series on discovery'
|
|
||||||
---
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
import { defineCollection, z } from 'astro:content';
|
|
||||||
|
|
||||||
const categoryCollection = defineCollection({
|
|
||||||
type: 'content',
|
|
||||||
schema: () =>
|
|
||||||
z.object({
|
|
||||||
title: z.string(),
|
|
||||||
description: z.string(),
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const collections = { categories: categoryCollection };
|
|
||||||
@@ -4,6 +4,7 @@ import type {
|
|||||||
Global,
|
Global,
|
||||||
Weather,
|
Weather,
|
||||||
Post,
|
Post,
|
||||||
|
Category,
|
||||||
Application,
|
Application,
|
||||||
Experience,
|
Experience,
|
||||||
Education,
|
Education,
|
||||||
@@ -18,6 +19,7 @@ type Schema = {
|
|||||||
site_global: Global;
|
site_global: Global;
|
||||||
site_weather: Weather;
|
site_weather: Weather;
|
||||||
posts: Post[];
|
posts: Post[];
|
||||||
|
categories: Category[];
|
||||||
site_applications: Application;
|
site_applications: Application;
|
||||||
site_experience: Experience;
|
site_experience: Experience;
|
||||||
site_education: Education;
|
site_education: Education;
|
||||||
|
|||||||
@@ -49,6 +49,12 @@ export type Post = {
|
|||||||
updated_date: Date;
|
updated_date: Date;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type Category = {
|
||||||
|
slug: string;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type Application = {
|
export type Application = {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
import { type CollectionEntry, getCollection } from 'astro:content';
|
|
||||||
import { Image } from 'astro:assets';
|
import { Image } from 'astro:assets';
|
||||||
import getReadingTime from 'reading-time';
|
import getReadingTime from 'reading-time';
|
||||||
import { marked } from 'marked';
|
import { marked } from 'marked';
|
||||||
@@ -7,6 +7,8 @@ import markedShiki from 'marked-shiki';
|
|||||||
import { createHighlighter } from 'shiki';
|
import { createHighlighter } from 'shiki';
|
||||||
import { readItems, readSingleton } from '@directus/sdk';
|
import { readItems, readSingleton } from '@directus/sdk';
|
||||||
|
|
||||||
|
import type { Category } from '@lib/directusTypes';
|
||||||
|
|
||||||
import SocialShareButton from '@components/buttons/SocialShareButton.astro';
|
import SocialShareButton from '@components/buttons/SocialShareButton.astro';
|
||||||
import BaseLayout from '@layouts/BaseLayout.astro';
|
import BaseLayout from '@layouts/BaseLayout.astro';
|
||||||
import directus from '@lib/directus';
|
import directus from '@lib/directus';
|
||||||
@@ -24,11 +26,14 @@ export async function getStaticPaths() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const global = await directus.request(readSingleton('site_global'));
|
const global = await directus.request(readSingleton('site_global'));
|
||||||
const category: CollectionEntry<'categories'> = (await getCollection('categories'))
|
const [category] = post.category ? await directus.request(
|
||||||
.filter((c) => c.slug === post.category)
|
readItems('categories', {
|
||||||
.pop() as CollectionEntry<'categories'>;
|
filter: { slug: { _eq: post.category },},
|
||||||
|
limit: 1,
|
||||||
|
}))
|
||||||
|
: [];
|
||||||
|
|
||||||
const readingTime = getReadingTime(post.content);
|
const readingTime = getReadingTime(post.content || '');
|
||||||
|
|
||||||
const highlighter = await createHighlighter({
|
const highlighter = await createHighlighter({
|
||||||
themes: ['github-light', 'github-dark'],
|
themes: ['github-light', 'github-dark'],
|
||||||
@@ -48,7 +53,7 @@ marked.use(markedShiki({
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const content = marked.parse(post.content);
|
const content = marked.parse(post.content || '');
|
||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout
|
<BaseLayout
|
||||||
@@ -100,18 +105,20 @@ const content = marked.parse(post.content);
|
|||||||
{post.title}
|
{post.title}
|
||||||
</h2>
|
</h2>
|
||||||
<ol class="flex items-center justify-center sm:justify-start whitespace-nowrap gap-2 sm:gap-0 mt-6 sm:mt-4">
|
<ol class="flex items-center justify-center sm:justify-start whitespace-nowrap gap-2 sm:gap-0 mt-6 sm:mt-4">
|
||||||
|
{category && (
|
||||||
<li class="inline-flex items-center">
|
<li class="inline-flex items-center">
|
||||||
<a
|
<a
|
||||||
class="inline-flex items-center text-secondary hover:text-secondary-hover text-sm transition-all duration-300"
|
class="inline-flex items-center text-secondary hover:text-secondary-hover text-sm transition-all duration-300"
|
||||||
href=`/categories/${category.slug}`
|
href=`/categories/${category.slug}`
|
||||||
data-astro-prefetch
|
data-astro-prefetch
|
||||||
>
|
>
|
||||||
{category?.data?.title}
|
{category.title}
|
||||||
</a>
|
</a>
|
||||||
<span class="shrink-0 text-secondary text-sm mx-2 sm:mx-4">
|
<span class="shrink-0 text-secondary text-sm mx-2 sm:mx-4">
|
||||||
/
|
/
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
|
)}
|
||||||
<li class="inline-flex items-center">
|
<li class="inline-flex items-center">
|
||||||
<span class="shrink-0 text-secondary text-sm">
|
<span class="shrink-0 text-secondary text-sm">
|
||||||
{formatDate(post.published_date)}
|
{formatDate(post.published_date)}
|
||||||
|
|||||||
@@ -1,21 +1,20 @@
|
|||||||
---
|
---
|
||||||
import { getCollection } from 'astro:content';
|
|
||||||
import { readItems, readSingleton } from '@directus/sdk';
|
import { readItems, readSingleton } from '@directus/sdk';
|
||||||
|
|
||||||
import type { Post } from '@lib/directusTypes';
|
import type { Post, Category } from '@lib/directusTypes';
|
||||||
|
|
||||||
import HeaderSection from '@components/sections/HeaderSection.astro';
|
import HeaderSection from '@components/sections/HeaderSection.astro';
|
||||||
import BlogCard from '@components/cards/BlogCard.astro';
|
import BlogCard from '@components/cards/BlogCard.astro';
|
||||||
import BaseLayout from '@layouts/BaseLayout.astro';
|
import BaseLayout from '@layouts/BaseLayout.astro';
|
||||||
import directus from '@lib/directus';
|
import directus from '@lib/directus';
|
||||||
|
|
||||||
const { category } = Astro.props;
|
const category = Astro.props;
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
export async function getStaticPaths() {
|
||||||
const categories = await getCollection('categories');
|
const categories = await directus.request(readItems('categories'));
|
||||||
return categories.map((category) => ({
|
return categories.map((category) => ({
|
||||||
params: { slug: category.slug },
|
params: { slug: category.slug },
|
||||||
props: { category },
|
props: category,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,16 +35,16 @@ const categoriesPosts = posts
|
|||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout
|
<BaseLayout
|
||||||
title={category.data.title}
|
title={category.title}
|
||||||
description={category.data.description}
|
description={category.description}
|
||||||
structuredData={{
|
structuredData={{
|
||||||
'@context': 'https://schema.org',
|
'@context': 'https://schema.org',
|
||||||
'@type': 'WebPage',
|
'@type': 'WebPage',
|
||||||
inLanguage: 'en-US',
|
inLanguage: 'en-US',
|
||||||
'@id': Astro.url.href,
|
'@id': Astro.url.href,
|
||||||
url: Astro.url.href,
|
url: Astro.url.href,
|
||||||
name: `${category.data.title} | ${global.name}`,
|
name: `${category.title} | ${global.name}`,
|
||||||
description: category.data.description,
|
description: category.description,
|
||||||
isPartOf: {
|
isPartOf: {
|
||||||
url: `${global.site_url}/categories`,
|
url: `${global.site_url}/categories`,
|
||||||
name: global.name,
|
name: global.name,
|
||||||
@@ -55,8 +54,8 @@ const categoriesPosts = posts
|
|||||||
>
|
>
|
||||||
|
|
||||||
<HeaderSection
|
<HeaderSection
|
||||||
title={category.data.title}
|
title={category.title}
|
||||||
subTitle={category.data.description}
|
subTitle={category.description}
|
||||||
btnExists
|
btnExists
|
||||||
btnTitle="Back to Categories"
|
btnTitle="Back to Categories"
|
||||||
btnURL="/categories"
|
btnURL="/categories"
|
||||||
|
|||||||
Reference in New Issue
Block a user