mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2025-08-11 19:53:59 +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'>
|
<div class='py-7 pb-6'>
|
||||||
<!-- Desktop breadcrums -->
|
<!-- Desktop breadcrums -->
|
||||||
<p class='text-gray-500 container hidden sm:block'>
|
<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) => {
|
{ breadcrumbs.map((breadcrumb, counter) => {
|
||||||
const isLast = counter === breadcrumbs.length - 1;
|
const isLast = counter === breadcrumbs.length - 1;
|
||||||
|
|
||||||
|
@@ -80,6 +80,7 @@ export interface TopicFileContentType {
|
|||||||
|
|
||||||
export interface TopicFileType {
|
export interface TopicFileType {
|
||||||
url: string;
|
url: string;
|
||||||
|
text: string;
|
||||||
file: TopicFileContentType;
|
file: TopicFileContentType;
|
||||||
roadmap: RoadmapFrontmatter;
|
roadmap: RoadmapFrontmatter;
|
||||||
roadmapId: string;
|
roadmapId: string;
|
||||||
@@ -101,9 +102,8 @@ export async function getTopicFiles(): Promise<Record<string, TopicFileType>> {
|
|||||||
const fileHeadings = fileContent.getHeadings();
|
const fileHeadings = fileContent.getHeadings();
|
||||||
const firstHeading = fileHeadings[0];
|
const firstHeading = fileHeadings[0];
|
||||||
|
|
||||||
const [, roadmapId, pathInsideContent] =
|
const [, roadmapId] =
|
||||||
filePath.match(/^\/src\/roadmaps\/(.+)?\/content\/(.+)?$/) || [];
|
filePath.match(/^\/src\/roadmaps\/(.+)?\/content\/(.+)?$/) || [];
|
||||||
|
|
||||||
const topicUrl = generateTopicUrl(filePath);
|
const topicUrl = generateTopicUrl(filePath);
|
||||||
|
|
||||||
const currentRoadmap = await import(
|
const currentRoadmap = await import(
|
||||||
@@ -112,6 +112,7 @@ export async function getTopicFiles(): Promise<Record<string, TopicFileType>> {
|
|||||||
|
|
||||||
mapping[topicUrl] = {
|
mapping[topicUrl] = {
|
||||||
url: topicUrl,
|
url: topicUrl,
|
||||||
|
text: firstHeading?.text,
|
||||||
file: fileContent,
|
file: fileContent,
|
||||||
roadmap: currentRoadmap.frontmatter,
|
roadmap: currentRoadmap.frontmatter,
|
||||||
roadmapId: roadmapId,
|
roadmapId: roadmapId,
|
||||||
@@ -130,6 +131,10 @@ export async function getTopicFiles(): Promise<Record<string, TopicFileType>> {
|
|||||||
|
|
||||||
// Breadcrumbs for the file
|
// Breadcrumbs for the file
|
||||||
const breadcrumbs: BreadcrumbItem[] = [
|
const breadcrumbs: BreadcrumbItem[] = [
|
||||||
|
{
|
||||||
|
title: 'Roadmaps',
|
||||||
|
url: '/roadmaps',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: currentRoadmap.featuredTitle,
|
title: currentRoadmap.featuredTitle,
|
||||||
url: `${roadmapUrl}`,
|
url: `${roadmapUrl}`,
|
||||||
@@ -146,3 +151,17 @@ export async function getTopicFiles(): Promise<Record<string, TopicFileType>> {
|
|||||||
|
|
||||||
return mapping;
|
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