From cbc53a66d8c3fea87c9423f744db74b2261f6611 Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Mon, 2 Jan 2023 20:34:03 +0400 Subject: [PATCH] Add video listing on homepage --- src/components/FeaturedGuides.astro | 32 +++++++------ src/components/FeaturedVideos.astro | 35 ++++++++++++++ src/components/VideoListItem.astro | 40 ++++++++++++++++ src/guides/http-basic-authentication.md | 2 +- src/lib/video.ts | 61 +++++++++++++++++++++++++ src/pages/index.astro | 8 ++-- src/pages/videos/index.astro | 23 ++++++++++ 7 files changed, 182 insertions(+), 19 deletions(-) create mode 100644 src/components/FeaturedVideos.astro create mode 100644 src/components/VideoListItem.astro create mode 100644 src/lib/video.ts create mode 100644 src/pages/videos/index.astro diff --git a/src/components/FeaturedGuides.astro b/src/components/FeaturedGuides.astro index 8e707a202..a9c5ec032 100644 --- a/src/components/FeaturedGuides.astro +++ b/src/components/FeaturedGuides.astro @@ -10,24 +10,26 @@ export interface Props { const { heading, guides } = Astro.props; --- -

{heading}

+
+

{heading}

-
- {guides.map((guide) => )} -
+
+ {guides.map((guide) => )} +
- - - + + +
\ No newline at end of file diff --git a/src/components/FeaturedVideos.astro b/src/components/FeaturedVideos.astro new file mode 100644 index 000000000..267e9b217 --- /dev/null +++ b/src/components/FeaturedVideos.astro @@ -0,0 +1,35 @@ +--- +import type { VideoFileType } from '../lib/video'; +import VideoListItem from './VideoListItem.astro'; + +export interface Props { + heading: string; + videos: VideoFileType[]; +} + +const { heading, videos } = Astro.props; +--- + +
+

{heading}

+ +
+ {videos.map((video) => )} +
+ + + + +
\ No newline at end of file diff --git a/src/components/VideoListItem.astro b/src/components/VideoListItem.astro new file mode 100644 index 000000000..0dc9ac5f8 --- /dev/null +++ b/src/components/VideoListItem.astro @@ -0,0 +1,40 @@ +--- +import type { VideoFileType } from "../lib/video"; + +export interface Props { + video: VideoFileType; +} + +const { video } = Astro.props; +const { frontmatter, id } = video; +--- + + + + {frontmatter.title} + + { + frontmatter.isNew && ( + + New + + + ) + } + + + + » + diff --git a/src/guides/http-basic-authentication.md b/src/guides/http-basic-authentication.md index 93b66e4ff..9cd9568df 100644 --- a/src/guides/http-basic-authentication.md +++ b/src/guides/http-basic-authentication.md @@ -40,7 +40,7 @@ Now that we know what basic authentication is, the question is, how does it work ### Step 1 When the browser first requests the server, the server tries to check the availability of the `Authorization` header in the request. Because it is the first request, no `Authorization` header is found in the request. So the server responds with the `401 Unauthorized` response code and also sends the `WWW-Authenticate` header with the value set to `Basic`, which tells the browser that it needs to trigger the basic authentication flow. -```text +```plaintext 401 Unauthorized WWW-Authenticate: Basic realm='user_pages' ``` diff --git a/src/lib/video.ts b/src/lib/video.ts new file mode 100644 index 000000000..4ac098120 --- /dev/null +++ b/src/lib/video.ts @@ -0,0 +1,61 @@ +import type { MarkdownFileType } from './file'; + +export interface VideoFrontmatter { + title: string; + description: string; + author: { + name: string; + url: string; + imageUrl: string; + }; + seo: { + title: string; + description: string; + }; + isNew: boolean; + duration: string; + date: string; + sitemap: { + priority: number; + changefreq: 'daily' | 'weekly' | 'monthly' | 'yealry'; + }; + tags: string[]; +} + +export type VideoFileType = MarkdownFileType & { + id: string; +}; + +/** + * Generates id from the given video file + * @param filePath Markdown file path + * + * @returns unique video identifier + */ +function videoPathToId(filePath: string): string { + const fileName = filePath.split('/').pop() || ''; + + return fileName.replace('.md', ''); +} + +/** + * Gets all the videos sorted by the publishing date + * @returns Promisifed video files + */ +export async function getAllVideos(): Promise { + const videos = await import.meta.glob('/src/videos/*.md', { + eager: true, + }); + + const videoFiles = Object.values(videos); + const enrichedVideos = videoFiles.map((videoFile) => ({ + ...videoFile, + id: videoPathToId(videoFile.file), + })); + + return enrichedVideos.sort( + (a, b) => + new Date(b.frontmatter.date).valueOf() - + new Date(a.frontmatter.date).valueOf() + ); +} diff --git a/src/pages/index.astro b/src/pages/index.astro index 21d3bff89..095e87052 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -1,13 +1,16 @@ --- import FeaturedGuides from '../components/FeaturedGuides.astro'; import FeaturedRoadmaps from '../components/FeaturedRoadmaps/FeaturedRoadmaps.astro'; +import FeaturedVideos from '../components/FeaturedVideos.astro'; import BaseLayout from '../layouts/BaseLayout.astro'; import { getAllGuides } from '../lib/guide'; import { getRoadmapsByTag } from '../lib/roadmap'; +import { getAllVideos } from '../lib/video'; const roleRoadmaps = await getRoadmapsByTag('role-roadmap'); const skillRoadmaps = await getRoadmapsByTag('skill-roadmap'); const guides = await getAllGuides(); +const videos = await getAllVideos(); --- @@ -39,9 +42,8 @@ const guides = await getAllGuides();
-
- -
+ +
diff --git a/src/pages/videos/index.astro b/src/pages/videos/index.astro new file mode 100644 index 000000000..f5daef6bf --- /dev/null +++ b/src/pages/videos/index.astro @@ -0,0 +1,23 @@ +--- +import VideoListItem from '../../components/VideoListItem.astro'; +import SimplePageHeader from '../../components/SimplePageHeader.astro'; +import BaseLayout from '../../layouts/BaseLayout.astro'; +import { getAllVideos } from '../../lib/video'; + +const guides = await getAllGuides(); +--- + + + + +
+
+
+ {guides.map((guide) => )} +
+
+
+