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 => ( +