Skip to content

Commit

Permalink
feat: πŸš€ Added changelog page
Browse files Browse the repository at this point in the history
Added changelog page to show releases with there changes, these
changelog page will show data from generated changelog file from relase
script

βœ… Closes: #143
  • Loading branch information
growupanand committed Jan 22, 2024
1 parent 461f525 commit 8ff20ea
Show file tree
Hide file tree
Showing 21 changed files with 259 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .release-it.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ module.exports = {
},
hooks: {
"before:init": [
"npx auto-changelog --stdout --commit-limit false -p --template ./templates/changelog-template.hbs --handlebars-setup ./templates/handlebars-setup.js > ./src/lib/data/changelog.json",
"npx auto-changelog --stdout --commit-limit false -p --template ./templates/changelog-template.hbs --handlebars-setup ./templates/handlebars-setup.js > ./src/lib/data/changelog.ts",
],
},
};
2 changes: 1 addition & 1 deletion changelog.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module.exports = {
},
feat: {
description: "A new feature",
emoji: "🎸",
emoji: "πŸš€",
value: "feat",
},
fix: {
Expand Down
49 changes: 49 additions & 0 deletions src/app/(publicPage)/changelog/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Metadata } from "next";

import { ReleaseCard } from "@/components/changeLogPage/releaseCard";
import BrandName from "@/components/common/brandName";
import { Badge } from "@/components/ui/badge";
import { changelog } from "@/lib/data/changelog";
import { changeLogSchema } from "@/lib/validations/changeLog";

export const metadata: Metadata = {
title: "Changelog",
};

export default function Page() {
const changeLogValidation = changeLogSchema.safeParse(changelog);
const changeLogs = changeLogValidation.success
? changeLogValidation.data
: [];
const removedEmptyReleases = changeLogs.filter(
(release) =>
release.commits.features.length > 0 ||
release.commits.improvements.length > 0 ||
release.commits.fixes.length > 0,
);

return (
<div>
<div className="sticky top-0 z-50 mb-10 border-b bg-white/70 shadow-sm backdrop-blur">
<div className=" w-full p-3 lg:container ">
<BrandName className="text-xl lg:text-2xl" />
</div>
</div>
<main className="lg:container">
<div className="mb-10 flex flex-col items-center justify-center lg:mb-20">
<Badge variant="secondary" className="font-medium">
Changelog
</Badge>
<h1 className="text-xl font-bold lg:text-5xl">Changes and updates</h1>
</div>
<div className="flex items-start justify-center">
<div className="w-full max-w-[700px]">
{removedEmptyReleases.map((release) => (
<ReleaseCard key={release.title} release={release} />
))}
</div>
</div>
</main>
</div>
);
}
8 changes: 7 additions & 1 deletion src/app/sitemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@ import { MetadataRoute } from "next";
export default function sitemap(): MetadataRoute.Sitemap {
return [
{
url: "https://convoform.com",
url: "https://www.convoform.com",
lastModified: new Date(),
changeFrequency: "daily",
priority: 1,
},
{
url: "https://www.convoform.com/changelog",
lastModified: new Date(),
changeFrequency: "daily",
priority: 1,
Expand Down
25 changes: 25 additions & 0 deletions src/components/changeLogPage/commitItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import Link from "next/link";
import { GitCommitHorizontal } from "lucide-react";

import { extractCommitMessage } from "@/lib/github";
import { Commit } from "@/lib/validations/changeLog";

export const CommitItem = ({ commit }: { commit: Commit }) => {
const commitMessage = extractCommitMessage(commit.message);

return (
<div className="items-start lg:flex">
<Link
href={commit.href}
target="_blank"
rel="noopener noreferrer nofollow"
>
<div className="flex items-center pt-1">
<GitCommitHorizontal size={20} className="mr-2" />{" "}
<span className="mr-2 text-xs">{commit.shorthash}</span>
</div>
</Link>
<span className="text-md first-letter:capitalize">{commitMessage}</span>
</div>
);
};
35 changes: 35 additions & 0 deletions src/components/changeLogPage/commitSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Commit, CommitSections } from "@/lib/validations/changeLog";
import { Badge } from "../ui/badge";
import { CommitItem } from "./commitItem";

const sectionBadgeVariants = {
features: "customSuccess",
improvements: "customInfo",
fixes: "customDanger",
} as const;

export const CommitSection = ({
section,
commits,
}: {
section: CommitSections;
commits: Commit[];
}) => {
return (
<div>
<Badge
variant={sectionBadgeVariants[section]}
className="mb-3 text-xs font-normal capitalize"
>
{section}
</Badge>
<ul className="grid gap-2 ps-3">
{commits.map((commit) => (
<li key={commit.shorthash} className="border-b pb-2">
<CommitItem commit={commit} />
</li>
))}
</ul>
</div>
);
};
33 changes: 33 additions & 0 deletions src/components/changeLogPage/releaseCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { CommitSections, Release } from "@/lib/validations/changeLog";
import { SectionCard } from "../landingPage/sectionCard";
import { CommitSection } from "./commitSection";

export const commitsSections = [
"features",
"improvements",
"fixes",
] as CommitSections[];

export const ReleaseCard = ({ release }: { release: Release }) => {
const commitSectionsWithCommits = commitsSections.filter(
(section) => release.commits[section].length > 0,
);

return (
<SectionCard
stickyHeader
title={`${release.title} - ${release.isoDate}`}
headerClassName="bg-transparent top-12 py-2 lg:py-3"
>
<div className="grid gap-3">
{commitSectionsWithCommits.map((section) => (
<CommitSection
key={section}
section={section}
commits={release.commits[section]}
/>
))}
</div>
</SectionCard>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default function ConversationDetail({ conversation }: Props) {
</div>
<div className="max-w-lg space-y-10">
{!isFormDataEmpty && (
<SectionCard title="Form Data">
<SectionCard stickyHeader title="Form Data">
<div className="overflow-hidden rounded-md border">
<Table className="">
<TableBody>
Expand All @@ -53,7 +53,7 @@ export default function ConversationDetail({ conversation }: Props) {
</div>
</SectionCard>
)}
<SectionCard title="Transcript">
<SectionCard stickyHeader title="Transcript">
<TranscriptCard transcript={transcript} />
</SectionCard>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/landingPage/features.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { SectionCard } from "./sectionCard";

export function Features() {
return (
<SectionCard title="Features" headerClassName="bg-gray-50/60">
<SectionCard stickyHeader title="Features" headerClassName="bg-gray-50/60">
<div className="grid grid-cols-1 gap-5 md:grid-cols-2">
<FeatureListItem
title="Easy to use"
Expand Down
5 changes: 5 additions & 0 deletions src/components/landingPage/footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ export function Footer() {
<span aria-label="App name" className={montserrat.className}>
{brandName}
</span>

<div className="flex items-center gap-3">
<Button variant="link" size="sm" asChild>
<Link href="/changelog">Changelog</Link>
</Button>
<Button variant="link" className="px-0" asChild>
<Link
href="https://github.com/growupanand/ConvoForm"
Expand Down Expand Up @@ -56,6 +60,7 @@ export function Footer() {
</Link>
</Button>
</div>

<span className="lg:ml-auto">
<span className={cn("text-sm font-light", montserrat.className)}>
Created by
Expand Down
2 changes: 1 addition & 1 deletion src/components/landingPage/githubStar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ async function GithubStars() {
>
<Star
size={15}
className="fill-yellow-500 stroke-yellow-600 transition-all group-[:active]:-translate-y-2 group-[:active]:rotate-180 group-[:hover]:rotate-45 group-[:active]:scale-150"
className="fill-yellow-500 stroke-yellow-600 transition-all group-[:active]:-translate-y-10 group-[:hover]:-rotate-90 group-[:active]:scale-150"
/>
<span>{stars} Stars</span>
</Badge>
Expand Down
16 changes: 8 additions & 8 deletions src/components/landingPage/hero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,14 @@ export function Hero() {

return (
<section className="md:my-15 my-10 flex w-full flex-col justify-center gap-1 py-4 text-center">
<div className="flex items-center justify-center gap-3">
<div className="flex flex-col items-center justify-center gap-3">
<Link
href="https://github.com/growupanand/ConvoForm"
target="_blank"
rel="noreferrer nofollow noopener"
>
<GithubStars />
</Link>
<Badge variant="outline" className="group text-sm font-normal">
<Link
href="https://github.com/growupanand/ConvoForm"
Expand All @@ -32,13 +39,6 @@ export function Hero() {
/>
</Link>
</Badge>
<Link
href="https://github.com/growupanand/ConvoForm"
target="_blank"
rel="noreferrer nofollow noopener"
>
<GithubStars />
</Link>
</div>
<div className="mb-3 flex flex-col gap-6">
<h1 className="text-3xl font-semibold text-gray-700 lg:text-6xl ">
Expand Down
6 changes: 5 additions & 1 deletion src/components/landingPage/howToUse.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ import { SectionCard } from "./sectionCard";

export function HowToUseSection() {
return (
<SectionCard title="How to use" headerClassName="bg-gray-50/60">
<SectionCard
stickyHeader
title="How to use"
headerClassName="bg-gray-50/60"
>
<div className="space-y-6 ">
<div className="flex items-start">
<Badge variant="outline" className="bg-white text-lg font-extrabold">
Expand Down
2 changes: 1 addition & 1 deletion src/components/landingPage/pricing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { SectionCard } from "./sectionCard";

export function Pricing() {
return (
<SectionCard title="Pricing" headerClassName="bg-gray-50/60">
<SectionCard stickyHeader title="Pricing" headerClassName="bg-gray-50/60">
<div className="grid grid-cols-1">
<PlanCard plan={freePlan} />
</div>
Expand Down
21 changes: 18 additions & 3 deletions src/components/landingPage/sectionCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,30 @@ type Props = {
children: React.ReactNode;
title: string;
headerClassName?: string;
sectionClassName?: string;
stickyHeader?: boolean;
};

export function SectionCard({ children, title, headerClassName }: Props) {
export function SectionCard({
children,
title,
headerClassName,
sectionClassName,
stickyHeader,
}: Props) {
return (
<section>
<Card className="w-full border-none bg-transparent shadow-none">
<Card
className={cn(
"w-full border-none bg-transparent shadow-none",
sectionClassName,
)}
>
<CardHeader
className={cn(
"sticky top-14 z-30 bg-background/70 pb-4 backdrop-blur ",
"pb-4 ",
stickyHeader &&
" sticky top-14 z-30 bg-background/70 backdrop-blur",
headerClassName,
)}
>
Expand Down
8 changes: 8 additions & 0 deletions src/components/ui/badge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ const badgeVariants = cva(
destructive:
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
outline: "text-foreground",
customSuccess:
"bg-green-50 text-green-700 ring-1 ring-inset ring-green-600/20",
customInfo:
"bg-blue-50 text-blue-700 ring-1 ring-inset ring-blue-600/20",
customWarning:
"bg-yellow-50 text-yellow-700 ring-1 ring-inset ring-yellow-600/20",
customDanger:
"bg-red-50 text-red-700 ring-1 ring-inset ring-red-600/20",
},
},
defaultVariants: {
Expand Down
1 change: 1 addition & 0 deletions src/lib/data/changelog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const changelog = [];
24 changes: 24 additions & 0 deletions src/lib/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,27 @@ export async function getGitHubStars() {
if (!github.success) return 0;
return github.data.stargazers_count;
}

/**
* This function is designed to extract commit messages from given message string using regex.
*
* The function can handle commit messages in the following formats:
* - "type: #153 this is commit subject"
* - "#153 this is commit subject"
* - "type: this is commit subject"
*
* In each of these formats, it locates and extracts the 'commit message' part.
*
* @param {string} message - The commit message that needs to be parsed. This will be a string
* that matches one of the formats specified above.
*
* @returns {string} - The extracted commit message if the input matches any expected format.
* If the input string doesn't match any expected format, it returns the original commit message".
*/
export function extractCommitMessage(message: string) {
const regex = /(\w+:\s)?#?\d*\s?(.+)/;
const match = message.match(regex);

// match[2] would contain the commit message if the regex matches the string
return match ? match[2] : message;
}
26 changes: 26 additions & 0 deletions src/lib/validations/changeLog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { z } from "zod";

export type CommitSections = "features" | "improvements" | "fixes";

export const commitSchema = z.object({
message: z.string(),
shorthash: z.string(),
href: z.string(),
});

export type Commit = z.infer<typeof commitSchema>;

export const releaseSchema = z.object({
title: z.string(),
tag: z.string(),
isoDate: z.string(),
commits: z.object({
features: z.array(commitSchema),
improvements: z.array(commitSchema),
fixes: z.array(commitSchema),
}),
});

export type Release = z.infer<typeof releaseSchema>;

export const changeLogSchema = z.array(releaseSchema);

0 comments on commit 8ff20ea

Please sign in to comment.