mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2025-08-11 11:43:58 +02:00
Add topics listing page
This commit is contained in:
@@ -12,8 +12,6 @@ const { breadcrumbs, roadmapId } = Astro.props;
|
||||
<div class='py-7 pb-6'>
|
||||
<!-- Desktop breadcrums -->
|
||||
<p class='text-gray-500 container hidden sm:block'>
|
||||
<a href='/roadmaps' class='hover:text-gray-800'>Roadmaps</a>
|
||||
<span>·</span>
|
||||
{ breadcrumbs.map((breadcrumb, counter) => {
|
||||
const isLast = counter === breadcrumbs.length - 1;
|
||||
|
||||
|
@@ -80,6 +80,7 @@ export interface TopicFileContentType {
|
||||
|
||||
export interface TopicFileType {
|
||||
url: string;
|
||||
text: string;
|
||||
file: TopicFileContentType;
|
||||
roadmap: RoadmapFrontmatter;
|
||||
roadmapId: string;
|
||||
@@ -101,9 +102,8 @@ export async function getTopicFiles(): Promise<Record<string, TopicFileType>> {
|
||||
const fileHeadings = fileContent.getHeadings();
|
||||
const firstHeading = fileHeadings[0];
|
||||
|
||||
const [, roadmapId, pathInsideContent] =
|
||||
const [, roadmapId] =
|
||||
filePath.match(/^\/src\/roadmaps\/(.+)?\/content\/(.+)?$/) || [];
|
||||
|
||||
const topicUrl = generateTopicUrl(filePath);
|
||||
|
||||
const currentRoadmap = await import(
|
||||
@@ -112,6 +112,7 @@ export async function getTopicFiles(): Promise<Record<string, TopicFileType>> {
|
||||
|
||||
mapping[topicUrl] = {
|
||||
url: topicUrl,
|
||||
text: firstHeading?.text,
|
||||
file: fileContent,
|
||||
roadmap: currentRoadmap.frontmatter,
|
||||
roadmapId: roadmapId,
|
||||
@@ -130,6 +131,10 @@ export async function getTopicFiles(): Promise<Record<string, TopicFileType>> {
|
||||
|
||||
// Breadcrumbs for the file
|
||||
const breadcrumbs: BreadcrumbItem[] = [
|
||||
{
|
||||
title: 'Roadmaps',
|
||||
url: '/roadmaps',
|
||||
},
|
||||
{
|
||||
title: currentRoadmap.featuredTitle,
|
||||
url: `${roadmapUrl}`,
|
||||
@@ -146,3 +151,17 @@ export async function getTopicFiles(): Promise<Record<string, TopicFileType>> {
|
||||
|
||||
return mapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the the topics for a given roadmap
|
||||
* @param roadmapId Roadmap id for which you want the topics
|
||||
* @returns Promise<TopicFileType[]>
|
||||
*/
|
||||
export async function getTopicsByRoadmapId(roadmapId: string): Promise<TopicFileType[]> {
|
||||
const topicFileMapping = await getTopicFiles();
|
||||
const allTopics = Object.values(topicFileMapping);
|
||||
|
||||
return Object.values(allTopics).filter(
|
||||
(topic) => topic.roadmapId === roadmapId
|
||||
);
|
||||
}
|
@@ -1,47 +0,0 @@
|
||||
---
|
||||
import InteractiveRoadamp from "../components/InteractiveRoadmap/InteractiveRoadmap.astro";
|
||||
import MarkdownRoadmap from "../components/MarkdownRoadmap.astro";
|
||||
import RoadmapHeader from "../components/RoadmapHeader.astro";
|
||||
import BaseLayout from "../layouts/BaseLayout.astro";
|
||||
import { getRoadmapIds, RoadmapFrontmatter } from "../lib/roadmap";
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const roadmapIds = await getRoadmapIds();
|
||||
|
||||
return roadmapIds.map((roadmapId) => ({
|
||||
params: { roadmapId },
|
||||
}));
|
||||
}
|
||||
|
||||
interface Params extends Record<string, string | undefined> {
|
||||
roadmapId: string;
|
||||
}
|
||||
|
||||
const { roadmapId } = Astro.params as Params;
|
||||
const file = await import(`../roadmaps/${roadmapId}/${roadmapId}.md`);
|
||||
const frontmatter = file.frontmatter as RoadmapFrontmatter;
|
||||
---
|
||||
|
||||
<BaseLayout title="">
|
||||
<RoadmapHeader
|
||||
description={frontmatter.description}
|
||||
title={frontmatter.title}
|
||||
roadmapPermalink={`/${roadmapId}`}
|
||||
/>
|
||||
|
||||
{
|
||||
frontmatter.jsonUrl && (
|
||||
<InteractiveRoadamp
|
||||
roadmapId={roadmapId}
|
||||
description={frontmatter.description}
|
||||
roadmapPermalink={`/${roadmapId}`}
|
||||
jsonUrl={frontmatter.jsonUrl}
|
||||
dimensions={frontmatter.dimensions}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
<MarkdownRoadmap>
|
||||
<file.Content />
|
||||
</MarkdownRoadmap>
|
||||
</BaseLayout>
|
47
src/pages/[roadmapId]/index.astro
Normal file
47
src/pages/[roadmapId]/index.astro
Normal file
@@ -0,0 +1,47 @@
|
||||
---
|
||||
import InteractiveRoadamp from '../../components/InteractiveRoadmap/InteractiveRoadmap.astro';
|
||||
import MarkdownRoadmap from '../../components/MarkdownRoadmap.astro';
|
||||
import RoadmapHeader from '../../components/RoadmapHeader.astro';
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
import { getRoadmapIds, RoadmapFrontmatter } from '../../lib/roadmap';
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const roadmapIds = await getRoadmapIds();
|
||||
|
||||
return roadmapIds.map((roadmapId) => ({
|
||||
params: { roadmapId },
|
||||
}));
|
||||
}
|
||||
|
||||
interface Params extends Record<string, string | undefined> {
|
||||
roadmapId: string;
|
||||
}
|
||||
|
||||
const { roadmapId } = Astro.params as Params;
|
||||
const roadmapFile = await import(`../../roadmaps/${roadmapId}/${roadmapId}.md`);
|
||||
const roadmapData = roadmapFile.frontmatter as RoadmapFrontmatter;
|
||||
---
|
||||
|
||||
<BaseLayout title="">
|
||||
<RoadmapHeader
|
||||
description={roadmapData.description}
|
||||
title={roadmapData.title}
|
||||
roadmapPermalink={`/${roadmapId}`}
|
||||
/>
|
||||
|
||||
{
|
||||
roadmapData.jsonUrl && (
|
||||
<InteractiveRoadamp
|
||||
roadmapId={roadmapId}
|
||||
description={roadmapData.description}
|
||||
roadmapPermalink={`/${roadmapId}`}
|
||||
jsonUrl={roadmapData.jsonUrl}
|
||||
dimensions={roadmapData.dimensions}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
<MarkdownRoadmap>
|
||||
<roadmapFile.Content />
|
||||
</MarkdownRoadmap>
|
||||
</BaseLayout>
|
66
src/pages/[roadmapId]/topics.astro
Normal file
66
src/pages/[roadmapId]/topics.astro
Normal file
@@ -0,0 +1,66 @@
|
||||
---
|
||||
import RoadmapHeader from '../../components/RoadmapHeader.astro';
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
import { getRoadmapIds, RoadmapFrontmatter } from '../../lib/roadmap';
|
||||
import { getTopicsByRoadmapId } from '../../lib/topic';
|
||||
|
||||
interface Params extends Record<string, string | undefined> {
|
||||
roadmapId: string;
|
||||
}
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const roadmapIds = await getRoadmapIds();
|
||||
|
||||
return roadmapIds.map((roadmapId) => ({
|
||||
params: { roadmapId },
|
||||
}));
|
||||
}
|
||||
|
||||
const { roadmapId } = Astro.params as Params;
|
||||
const topics = await getTopicsByRoadmapId(roadmapId);
|
||||
const roadmapFile = await import(`../../roadmaps/${roadmapId}/${roadmapId}.md`);
|
||||
const roadmapData = roadmapFile.frontmatter as RoadmapFrontmatter;
|
||||
---
|
||||
|
||||
<BaseLayout title="Topics">
|
||||
<RoadmapHeader
|
||||
description={roadmapData.description}
|
||||
title={roadmapData.title}
|
||||
roadmapPermalink={`/${roadmapId}`}
|
||||
hasSearch={true}
|
||||
hasTopics={false}
|
||||
/>
|
||||
|
||||
<div class="bg-gray-50 pt-5 pb-8 sm:pt-10 sm:pb-16">
|
||||
<div class="container">
|
||||
{
|
||||
topics.map((topic) => {
|
||||
// Breadcrumbs have three additional items e.g.
|
||||
//
|
||||
// Roadmaps / Frontend / Topics / Internet / HTTP
|
||||
// ---^----------^---------^----
|
||||
//
|
||||
// Subtracting 3 to get the total parent count
|
||||
const totalParentCount = topic.breadcrumbs.length - 3;
|
||||
|
||||
return (
|
||||
<a
|
||||
data-topic={topic.text.toLowerCase()}
|
||||
class:list={[
|
||||
'cursor-pointer text-sm sm:text-md border-gray-200 border py-1.5 px-2 sm:py-2 sm:px-2.5 rounded-md block mb-0.5 sm:mb-1',
|
||||
{
|
||||
'bg-gray-400 hover:bg-gray-500': totalParentCount === 1,
|
||||
'bg-gray-300 hover:bg-gray-400': totalParentCount === 2,
|
||||
'bg-gray-200 hover:bg-gray-300': totalParentCount === 3,
|
||||
},
|
||||
]}
|
||||
href={topic.url}
|
||||
>
|
||||
{topic.text}
|
||||
</a>
|
||||
);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</BaseLayout>
|
Reference in New Issue
Block a user