Roadmap filtering by tags

astro
Kamran Ahmed 2 years ago
parent 32761b5587
commit b176d2c23e
  1. 26
      src/components/SimplePageHeader.astro
  2. 11
      src/lib/File.ts
  3. 29
      src/lib/roadmap.ts
  4. 20
      src/lib/topic.ts
  5. 25
      src/pages/roadmaps.astro

@ -0,0 +1,26 @@
---
import YouTubeAlert from './YouTubeAlert.astro';
export interface Props {
title: string;
description: string;
showYouTubeAlert?: boolean;
}
const { title, description, showYouTubeAlert = false } = Astro.props;
---
<div class="bg-white border-b pt-6 pb-5 sm:pt-12 sm:pb-10">
<div class="container">
{
showYouTubeAlert && (
<div class="mb-4 hidden sm:block">
<YouTubeAlert />
</div>
)
}
<h1 class="text-3xl sm:text-5xl mb-1 sm:mb-2 font-bold">{title}</h1>
<p class="text-gray-500 text-sm sm:text-lg">{description}</p>
</div>
</div>

@ -0,0 +1,11 @@
export interface MarkdownFileType<T = Record<string, string>> {
frontmatter: T;
file: string;
url: string;
Content: any;
getHeadings: () => {
depth: number;
slug: string;
text: string;
}[];
}

@ -1,3 +1,7 @@
import type { MarkdownFileType } from "./File";
type RoadmapFileType = MarkdownFileType<RoadmapFrontmatter>;
export interface RoadmapFrontmatter {
id: string;
jsonUrl: string;
@ -25,6 +29,11 @@ export interface RoadmapFrontmatter {
tags: string[];
}
/**
* Gets the IDs of all the roadmaps available on the website
*
* @returns string[] Array of roadmap IDs
*/
export async function getRoadmapIds() {
const roadmapFiles = await import.meta.glob<string>("/src/roadmaps/*/*.md", {
eager: true,
@ -36,3 +45,23 @@ export async function getRoadmapIds() {
return fileName.replace(".md", "");
});
}
/**
* Gets the roadmap files which have the given tag assigned
*
* @param tag Tag assigned to roadmap
* @returns Promisified RoadmapFileType[]
*/
export async function getRoadmapsByTag(tag: string): Promise<RoadmapFileType[]> {
const roadmapFilesMap = await import.meta.glob<RoadmapFileType>(
'/src/roadmaps/*/*.md',
{
eager: true,
}
);
const roadmapFiles: MarkdownFileType<RoadmapFrontmatter>[] = Object.values(roadmapFilesMap);
const filteredRoadmaps = roadmapFiles.filter(roadmapFile => roadmapFile.frontmatter.tags.includes(tag));
return filteredRoadmaps;
}

@ -1,4 +1,4 @@
import { joinPath } from './path';
import type { MarkdownFileType } from './File';
import type { RoadmapFrontmatter } from './roadmap';
// Generates URL from the topic file path e.g.
@ -64,24 +64,10 @@ export type BreadcrumbItem = {
url: string;
};
type FileHeadingType = {
depth: number;
slug: string;
text: string;
};
export interface TopicFileContentType {
frontMatter: Record<string, string>;
file: string;
url: string;
Content: any;
getHeadings: () => FileHeadingType[];
}
export interface TopicFileType {
url: string;
text: string;
file: TopicFileContentType;
file: MarkdownFileType;
roadmap: RoadmapFrontmatter;
roadmapId: string;
breadcrumbs: BreadcrumbItem[];
@ -102,7 +88,7 @@ export async function getTopicFiles(): Promise<Record<string, TopicFileType>> {
const mapping: Record<string, TopicFileType> = {};
for (let filePath of Object.keys(contentFiles)) {
const fileContent: TopicFileContentType = contentFiles[filePath] as any;
const fileContent: MarkdownFileType = contentFiles[filePath] as any;
const fileHeadings = fileContent.getHeadings();
const firstHeading = fileHeadings[0];

@ -0,0 +1,25 @@
---
import SimplePageHeader from '../components/SimplePageHeader.astro';
import BaseLayout from '../layouts/BaseLayout.astro';
import { getRoadmapsByTag } from '../lib/roadmap';
const roleRoadmaps = await getRoadmapsByTag('role-roadmap');
const skillRoadmaps = await getRoadmapsByTag('skill-roadmap');
---
<BaseLayout title="Roadmap">
<SimplePageHeader
title="Developer Roadmaps"
description="Step by step guides and paths to learn different tools or technologies"
showYouTubeAlert={true}
/>
<div class="bg-gray-100 pt-4 pb-14 sm:pt-8 sm:pb-16">
<div class="container">
<div class="grid grid-cols-1 sm:grid-cols-2 gap-0.5 sm:gap-3">
<h1>{ roleRoadmaps.length }</h1>
<h1>{ skillRoadmaps.length }</h1>
</div>
</div>
</div>
</BaseLayout>
Loading…
Cancel
Save