feat: implement changelog page (#7099)
* feat: implement leaderboard page * feat: sample changelog files * Update UI for changelog page * Make changelog page noindex --------- Co-authored-by: Kamran Ahmed <kamranahmed.se@gmail.com>feat/collection
parent
3166a02f23
commit
9948e89b84
9 changed files with 214 additions and 2 deletions
@ -0,0 +1,37 @@ |
|||||||
|
--- |
||||||
|
import type { ChangelogFileType } from '../../lib/changelog'; |
||||||
|
import { DateTime } from 'luxon'; |
||||||
|
import MarkdownFile from '../MarkdownFile.astro'; |
||||||
|
|
||||||
|
interface Props { |
||||||
|
changelog: ChangelogFileType; |
||||||
|
} |
||||||
|
|
||||||
|
const { changelog } = Astro.props; |
||||||
|
const { frontmatter } = changelog; |
||||||
|
|
||||||
|
const formattedDate = DateTime.fromISO(frontmatter.date).toFormat( |
||||||
|
'dd LLL, yyyy', |
||||||
|
); |
||||||
|
--- |
||||||
|
|
||||||
|
<div class='relative'> |
||||||
|
<span class='h-2 w-2 flex-shrink-0 rounded-full bg-gray-300 absolute top-2 -left-6'></span> |
||||||
|
|
||||||
|
<div class='mb-3 flex items-center gap-2'> |
||||||
|
<span class='flex-shrink-0 text-xs tracking-wide text-gray-400'> |
||||||
|
{formattedDate} |
||||||
|
</span> |
||||||
|
<span class='truncate text-base font-medium'> |
||||||
|
{changelog.frontmatter.title} |
||||||
|
</span> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class='rounded-xl border bg-white p-6'> |
||||||
|
<div |
||||||
|
class='prose prose-h2:text-lg prose-h2:font-medium prose-h2:mt-3 prose-sm prose-p:mb-0 prose-blockquote:font-normal prose-blockquote:text-gray-500 prose-ul:my-0 prose-img:mt-0 prose-img:rounded-lg [&>blockquote>p]:mt-0 prose-ul:bg-gray-100 prose-ul:rounded-lg prose-ul:px-4 prose-ul:py-4 prose-ul:pl-7 [&>ul>li]:my-0 [&>ul>li]:mb-1 [&>ul]:mt-3' |
||||||
|
> |
||||||
|
<changelog.Content /> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
@ -1,5 +1,16 @@ |
|||||||
|
--- |
||||||
|
interface Props { |
||||||
|
class?: string; |
||||||
|
} |
||||||
|
|
||||||
|
const { class: className } = Astro.props; |
||||||
|
--- |
||||||
|
|
||||||
<div |
<div |
||||||
class='container prose-h2:text-balance prose-h3:text-balance prose-h4:text-balance prose-h5:text-balance prose prose-xl prose-h2:mb-3 prose-h2:mt-10 prose-h2:scroll-mt-5 prose-h2:text-3xl prose-h3:mt-2 prose-h3:scroll-mt-5 prose-h5:font-medium prose-blockquote:font-normal prose-code:bg-transparent prose-img:mt-1 prose-h2:sm:scroll-mt-10 prose-h3:sm:scroll-mt-10' |
class:list={[ |
||||||
|
'container prose prose-xl prose-h2:mb-3 prose-h2:mt-10 prose-h2:scroll-mt-5 prose-h2:text-balance prose-h2:text-3xl prose-h3:mt-2 prose-h3:scroll-mt-5 prose-h3:text-balance prose-h4:text-balance prose-h5:text-balance prose-h5:font-medium prose-blockquote:font-normal prose-code:bg-transparent prose-img:mt-1 prose-h2:sm:scroll-mt-10 prose-h3:sm:scroll-mt-10', |
||||||
|
className, |
||||||
|
]} |
||||||
> |
> |
||||||
<slot /> |
<slot /> |
||||||
</div> |
</div> |
||||||
|
@ -0,0 +1,25 @@ |
|||||||
|
--- |
||||||
|
title: 'New Dashboard, Leaderboards and Projects' |
||||||
|
description: 'New leaderboard page showing the most active users' |
||||||
|
seo: |
||||||
|
title: 'Leaderboard Page - roadmap.sh' |
||||||
|
description: '' |
||||||
|
date: 2024-09-13 |
||||||
|
--- |
||||||
|
|
||||||
|
TL;DR: new dashboard, leaderboard page and projects page. |
||||||
|
|
||||||
|
- New dashboard for logged-in users |
||||||
|
- New leaderboard page |
||||||
|
- Projects page listing all projects |
||||||
|
- Ability to stop a started project |
||||||
|
- Frontend and backend content improvements |
||||||
|
- Bug fixes |
||||||
|
|
||||||
|
![Leaderboard Page](https://assets.roadmap.sh/guest/personal-dashboard.png) |
||||||
|
|
||||||
|
We just launched a dedicated dashboard for logged-in users to showing progress, projects, bookmarks and more. You can still access the old homepage by visiting [this page](https://roadmap.sh/home). |
||||||
|
|
||||||
|
We also launched a new [leaderboard page](/leaderboard) showing the most active users, users who completed most projects and more. |
||||||
|
|
||||||
|
There is also a [new projects page](/projects) where you can see all the projects you have been working on. You can also now stop a started project. |
@ -0,0 +1,12 @@ |
|||||||
|
--- |
||||||
|
title: 'New Dashboard Page' |
||||||
|
description: 'We have added a new dashboard page to help you track your progress' |
||||||
|
seo: |
||||||
|
title: 'New Dashboard Page - roadmap.sh' |
||||||
|
description: 'We have added a new dashboard page to help you track your progress' |
||||||
|
date: 2024-09-12 |
||||||
|
--- |
||||||
|
|
||||||
|
We have revamped the dashboard page for logged-in users. The new dashboard page will help you track your progress and see your overall progress in a single view. We have also added a new progress bar to help you visualize your progress. |
||||||
|
|
||||||
|
If you want to access the guest homepage, you check check it out [here](/home). |
@ -0,0 +1,69 @@ |
|||||||
|
import type { MarkdownFileType } from './file'; |
||||||
|
|
||||||
|
export interface ChangelogFrontmatter { |
||||||
|
title: string; |
||||||
|
description: string; |
||||||
|
seo: { |
||||||
|
title: string; |
||||||
|
description: string; |
||||||
|
}; |
||||||
|
date: string; |
||||||
|
} |
||||||
|
|
||||||
|
export type ChangelogFileType = MarkdownFileType<ChangelogFrontmatter> & { |
||||||
|
id: string; |
||||||
|
}; |
||||||
|
|
||||||
|
/** |
||||||
|
* Generates id from the given changelog file |
||||||
|
* @param filePath Markdown file path |
||||||
|
* |
||||||
|
* @returns unique changelog identifier |
||||||
|
*/ |
||||||
|
function changelogPathToId(filePath: string): string { |
||||||
|
const fileName = filePath.split('/').pop() || ''; |
||||||
|
|
||||||
|
return fileName.replace('.md', ''); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Gets all the changelogs sorted by the publishing date |
||||||
|
* @returns Promisifed guide files |
||||||
|
*/ |
||||||
|
export async function getAllChangelogs(): Promise<ChangelogFileType[]> { |
||||||
|
// @ts-ignore
|
||||||
|
const changelogs = import.meta.glob<ChangelogFileType>( |
||||||
|
'/src/data/changelogs/*.md', |
||||||
|
{ |
||||||
|
eager: true, |
||||||
|
}, |
||||||
|
); |
||||||
|
|
||||||
|
const changelogFiles = Object.values(changelogs) as ChangelogFileType[]; |
||||||
|
const enrichedChangelogs: ChangelogFileType[] = changelogFiles.map( |
||||||
|
(changelogFile) => ({ |
||||||
|
...changelogFile, |
||||||
|
id: changelogPathToId(changelogFile.file), |
||||||
|
}), |
||||||
|
); |
||||||
|
|
||||||
|
return enrichedChangelogs.sort( |
||||||
|
(a, b) => |
||||||
|
new Date(b.frontmatter.date).valueOf() - |
||||||
|
new Date(a.frontmatter.date).valueOf(), |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Gets the changelog by the given id |
||||||
|
* @param id Changelog identifier |
||||||
|
* @returns Promisified changelog file |
||||||
|
*/ |
||||||
|
|
||||||
|
export async function getChangelogById( |
||||||
|
id: string, |
||||||
|
): Promise<ChangelogFileType | undefined> { |
||||||
|
const allChangelogs = await getAllChangelogs(); |
||||||
|
|
||||||
|
return allChangelogs.find((changelog) => changelog.id === id); |
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
--- |
||||||
|
import SimplePageHeader from '../components/SimplePageHeader.astro'; |
||||||
|
import BaseLayout from '../layouts/BaseLayout.astro'; |
||||||
|
import { getAllChangelogs } from '../lib/changelog'; |
||||||
|
import ChangelogItem from '../components/Changelog/ChangelogItem.astro'; |
||||||
|
|
||||||
|
const allChangelogs = await getAllChangelogs(); |
||||||
|
--- |
||||||
|
|
||||||
|
<BaseLayout |
||||||
|
title='Changelogs' |
||||||
|
description='Changelogs for the updates and changes in the website' |
||||||
|
permalink='/changelogs' |
||||||
|
noIndex={true} |
||||||
|
> |
||||||
|
<div class='bg-gray-100'> |
||||||
|
<div class='rounded-lg border-b bg-white text-left'> |
||||||
|
<div class='mx-auto max-w-[500px] pt-12 pb-10 text-center'> |
||||||
|
<h1 class='mb-3 text-4xl font-semibold'>Changelog</h1> |
||||||
|
<p>Here is everything we have been shipping recently</p> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class='relative mx-auto max-w-[500px] pb-8 pt-4'> |
||||||
|
<div class='space-y-6'> |
||||||
|
<div |
||||||
|
class='absolute inset-y-0 -left-5 w-px -translate-x-[0.5px] bg-gray-300' |
||||||
|
> |
||||||
|
</div> |
||||||
|
|
||||||
|
{ |
||||||
|
allChangelogs.map((changelog) => ( |
||||||
|
<ChangelogItem changelog={changelog} /> |
||||||
|
)) |
||||||
|
} |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</BaseLayout> |
Loading…
Reference in new issue