diff --git a/src/components/TutorialsGrid.astro b/src/components/TutorialsGrid.astro new file mode 100644 index 000000000000000..d1ff315d0d463dd --- /dev/null +++ b/src/components/TutorialsGrid.astro @@ -0,0 +1,152 @@ +--- +import { z } from "astro:schema"; +import { + getCollection, + getEntry, + reference, + type CollectionEntry, +} from "astro:content"; +import type { ComponentProps } from "astro/types"; +import { Badge } from "@astrojs/starlight/components"; + +type Props = z.infer; +type BadgeType = ComponentProps; + +const props = z.object({ + product: reference("products").optional(), + frontmatterBadges: z.string().array().optional(), +}); + +let { product, frontmatterBadges } = props.parse(Astro.props); + +type DocsEntry = CollectionEntry<"docs">; +type VideoEntry = CollectionEntry<"videos">; + +const tutorials: Array = []; + +if (!product) { + product = { + id: Astro.url.pathname.split("/").filter(Boolean)[0], + collection: "products", + }; +} + +const productEntry = await getEntry(product); + +if (!productEntry) { + throw new Error( + `[TutorialsGrid] Unable to find product YAML for ${product.id}.`, + ); +} + +const productTitle = productEntry.data.product.title; + +const docs = await getCollection("docs", (entry) => { + return ( + // pcx_content_type: tutorial + entry.data.pcx_content_type === "tutorial" && + // /src/content/r2/**/*.mdx + (entry.id.startsWith(`${productEntry.id}/`) || + // products: [R2] + entry.data.products?.some( + (v: string) => v.toUpperCase() === productTitle.toUpperCase(), + )) + ); +}); + +tutorials.push(...docs); + +const videos = await getCollection("videos", (entry) => { + return entry.data.products.some( + (v: string) => v.toUpperCase() === productTitle.toUpperCase(), + ); +}); + +tutorials.push(...videos); + +tutorials.sort((a, b) => Number(b.data.updated) - Number(a.data.updated)); + +const difficulties = { + Beginner: "success", + Intermediate: "caution", + Advanced: "danger", +} as Record["variant"]>; +--- + +
+ { + tutorials.map((tutorial) => { + const title = + tutorial.collection === "docs" ? tutorial.data.title : tutorial.id; + + const href = + tutorial.collection === "docs" + ? `/${tutorial.id}/` + : tutorial.data.link; + + const difficulty = tutorial.data.difficulty; + + const YOUTUBE_DOMAINS = ["www.youtube.com", "youtube.com", "youtu.be"]; + const youtube = + tutorial.collection === "videos" && + YOUTUBE_DOMAINS.includes(new URL(tutorial.data.link).hostname); + + const spotlight = + tutorial.collection === "docs" && tutorial.data.spotlight; + + const badges: BadgeType[] = []; + + if (difficulty) { + badges.push({ + text: difficulty, + variant: difficulties[difficulty], + }); + } + + if (youtube) { + badges.push({ + text: "YouTube", + variant: "note", + }); + } + + if (spotlight) { + badges.push({ + text: "Community", + variant: "tip", + }); + } + + if (frontmatterBadges) { + for (const frontmatterBadge of frontmatterBadges) { + const values = + tutorial.data[frontmatterBadge as keyof typeof tutorial.data]; + + if (values) { + if (Array.isArray(values)) { + for (const value of values) { + badges.push({ text: value.toString() }); + } + } else { + badges.push({ text: values.toString() }); + } + } + } + } + + return ( + + {title} +

+ {badges.map((badge) => ( + + ))} +

+
+ ); + }) + } +
diff --git a/src/components/index.ts b/src/components/index.ts index eea5b65c08f8449..2e279421765080d 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -52,6 +52,7 @@ export { default as SpotlightAuthorDetails } from "./SpotlightAuthorDetails.astr export { default as Stream } from "./Stream.astro"; export { default as TroubleshootingList } from "./TroubleshootingList.astro"; export { default as TunnelCalculator } from "./TunnelCalculator.astro"; +export { default as TutorialsGrid } from "./TutorialsGrid.astro"; export { default as Type } from "./Type.astro"; export { default as TypeScriptExample } from "./TypeScriptExample.astro"; export { default as WranglerConfig } from "./WranglerConfig.astro"; diff --git a/src/content/docs/ai-gateway/tutorials/index.mdx b/src/content/docs/ai-gateway/tutorials/index.mdx index e8dddb59bb5372f..2090721a6459c16 100644 --- a/src/content/docs/ai-gateway/tutorials/index.mdx +++ b/src/content/docs/ai-gateway/tutorials/index.mdx @@ -7,8 +7,8 @@ sidebar: hideIndex: true --- -import { GlossaryTooltip, ListTutorials } from "~/components"; +import { GlossaryTooltip, TutorialsGrid } from "~/components"; View tutorials to help you get started with AI Gateway. - + diff --git a/src/content/docs/style-guide/components/tutorials-grid.mdx b/src/content/docs/style-guide/components/tutorials-grid.mdx new file mode 100644 index 000000000000000..46c805e50819179 --- /dev/null +++ b/src/content/docs/style-guide/components/tutorials-grid.mdx @@ -0,0 +1,45 @@ +--- +title: Tutorials grid +--- + +This component fetches all pages with `pcx_content_type: tutorial` under a given product. + +## Import + +```mdx +import { TutorialsGrid } from "~/components"; +``` + +## Usage + +```mdx live +import { TutorialsGrid } from "~/components"; + + +``` + +## `` Props + +### `product` + +**type:** `string` + +The product to fetch tutorials for, based on the file location and the `products` frontmatter property. + +This property is optional, and will be inferred from the page it is used on if omitted. + +### `frontmatterBadges` + +**type:** `string[]` + +Frontmatter values to add badges from. + +For example, given the below frontmatter, the badges `foo` and `bar` would be added when `frontmatterBadges={["stuff"]}` is provided. + +```mdx +--- +title: Example Title +stuff: + - foo + - bar +``` diff --git a/src/content/docs/workers-ai/tutorials/index.mdx b/src/content/docs/workers-ai/tutorials/index.mdx index 50376b9ddb723a6..7844813c4ee9390 100644 --- a/src/content/docs/workers-ai/tutorials/index.mdx +++ b/src/content/docs/workers-ai/tutorials/index.mdx @@ -6,7 +6,7 @@ sidebar: order: 5 --- -import { GlossaryTooltip, ListTutorials } from "~/components"; +import { GlossaryTooltip, TutorialsGrid } from "~/components"; :::note [Explore our community-written tutorials contributed through the Developer Spotlight program.](/developer-spotlight/) @@ -14,4 +14,4 @@ import { GlossaryTooltip, ListTutorials } from "~/components"; View tutorials to help you get started with Workers AI. - + diff --git a/src/content/docs/workers/tutorials/index.mdx b/src/content/docs/workers/tutorials/index.mdx index 245c739fe0f97d3..e90b4b985b7afe5 100644 --- a/src/content/docs/workers/tutorials/index.mdx +++ b/src/content/docs/workers/tutorials/index.mdx @@ -15,4 +15,4 @@ import { GlossaryTooltip, ListTutorials } from "~/components"; View tutorials to help you get started with Workers. - + \ No newline at end of file