From 717c473967c637840823ffc4b436c8b57da0a0a8 Mon Sep 17 00:00:00 2001
From: Simon Vrachliotis
Date: Tue, 5 Dec 2023 09:26:54 +1100
Subject: [PATCH] New Keystatic YouTube playlist with playlist block in CMS
(#801)
---
docs/keystatic.config.tsx | 20 +++++++++
docs/src/app/(public)/resources/page.tsx | 45 +++++++++++++++++--
...wered-blog-with-keystatic-and-next-js.yaml | 15 +++++++
3 files changed, 77 insertions(+), 3 deletions(-)
create mode 100644 docs/src/content/resources/mini-course-create-a-git-hub-powered-blog-with-keystatic-and-next-js.yaml
diff --git a/docs/keystatic.config.tsx b/docs/keystatic.config.tsx
index 29f82bbfa..f6ee823ad 100644
--- a/docs/keystatic.config.tsx
+++ b/docs/keystatic.config.tsx
@@ -275,11 +275,13 @@ export default config({
label: 'Resource type',
options: [
{ label: 'YouTube video', value: 'youtube-video' },
+ { label: 'YouTube playlist', value: 'youtube-playlist' },
{ label: 'Article', value: 'article' },
],
defaultValue: 'youtube-video',
}),
{
+ // Single videos
'youtube-video': fields.object({
videoId: fields.text({
label: 'Video ID',
@@ -304,6 +306,24 @@ export default config({
validation: { length: { min: 1 } },
}),
}),
+ // Playlists
+ 'youtube-playlist': fields.object({
+ playlistId: fields.text({
+ label: 'Playlist ID',
+ description: 'The ID of the playlist (not the URL!)',
+ validation: { length: { min: 1 } },
+ }),
+ thumbnail: fields.cloudImage({
+ label: 'Video thumbnail',
+ description: 'A 16/9 thumbnail image for the video.',
+ }),
+ description: fields.text({
+ label: 'Playlist description',
+ multiline: true,
+ validation: { length: { min: 1 } },
+ }),
+ }),
+ // Articles
article: fields.object({
url: fields.url({
label: 'Article URL',
diff --git a/docs/src/app/(public)/resources/page.tsx b/docs/src/app/(public)/resources/page.tsx
index 14e106998..cc32de659 100644
--- a/docs/src/app/(public)/resources/page.tsx
+++ b/docs/src/app/(public)/resources/page.tsx
@@ -19,6 +19,13 @@ type VideoProps = {
'kind'
>;
+type PlaylistProps = {
+ title: ResourceEntry['title'];
+} & Extract<
+ ResourceEntry['type'],
+ { discriminant: 'youtube-playlist' }
+>['value'];
+
type ArticleProps = {
title: ResourceEntry['title'];
} & Omit<
@@ -30,6 +37,18 @@ export default async function Resources() {
const resources = await reader().collections.resources.all();
if (!resources) notFound();
+ // Preparing sorted data
+ const sortedPlaylists = resources
+ .filter(resource => resource.entry.type.discriminant === 'youtube-playlist')
+ .sort((a, b) => {
+ return (a.entry.sortIndex as number) - (b.entry.sortIndex as number);
+ })
+ .map(resource => ({
+ title: resource.entry.title,
+ sortIndex: resource.entry.sortIndex,
+ ...resource.entry.type.value,
+ })) as PlaylistProps[];
+
const sortedVideos = resources
.filter(
resource =>
@@ -96,6 +115,14 @@ export default async function Resources() {
has a growing collection of content about Keystatic.
+ {sortedPlaylists.map(video => (
+
+ ))}
{sortedVideos.map(video => (