Skip to content

Commit

Permalink
feat: update stars and forks stats on repo pages (#3199)
Browse files Browse the repository at this point in the history
Co-authored-by: Nick Taylor <nick@nickyt.co>
Co-authored-by: Brian Douglas <bdougie@users.noreply.github.com>
  • Loading branch information
3 people committed Apr 25, 2024
1 parent 2732c03 commit 43ffce4
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 159 deletions.
56 changes: 0 additions & 56 deletions components/Graphs/MetricCard.stories.tsx

This file was deleted.

78 changes: 0 additions & 78 deletions components/Graphs/MetricCard.tsx

This file was deleted.

30 changes: 28 additions & 2 deletions components/Workspaces/RepositoryStatCard.tsx
@@ -1,5 +1,8 @@
import { FaStar } from "react-icons/fa6";
import { BiGitRepoForked } from "react-icons/bi";
import { ArrowTrendingDownIcon, ArrowTrendingUpIcon, MinusSmallIcon } from "@heroicons/react/24/solid";
import { GitPullRequestIcon, HeartIcon, IssueOpenedIcon } from "@primer/octicons-react";

import Card from "components/atoms/Card/card";
import Pill from "components/atoms/Pill/pill";
import SkeletonWrapper from "components/atoms/SkeletonLoader/skeleton-wrapper";
Expand All @@ -21,12 +24,22 @@ type RepositoryStatCardProps = {
type: "engagement";
stats: { stars: number; forks: number; activity_ratio: number } | undefined;
}
| {
type: "stars";
stats: { total: number; range: number; over_range: number; average_over_range: number } | undefined;
}
| {
type: "forks";
stats: { total: number; range: number; over_range: number; average_over_range: number } | undefined;
}
);

const titles = {
pulls: "Pull Requests",
issues: "Issues",
engagement: "Engagement",
stars: "Stars",
forks: "Forks",
} as const;

type CardType = RepositoryStatCardProps["type"];
Expand All @@ -39,6 +52,10 @@ function getIcon(type: CardType) {
return <IssueOpenedIcon size={18} className="text-slate-600 border-1 rounded-md p-2 h-8 w-8 shadow-xs" />;
case "engagement":
return <HeartIcon size={18} className="text-slate-600 border-1 rounded-md p-2 h-8 w-8 shadow-xs" />;
case "stars":
return <FaStar size={18} className="text-slate-600 border-1 rounded-md p-2 h-8 w-8 shadow-xs" />;
case "forks":
return <BiGitRepoForked size={18} className="text-slate-600 border-1 rounded-md p-2 h-8 w-8 shadow-xs" />;
}
}

Expand All @@ -50,6 +67,9 @@ function getStatPropertiesByType(type: CardType) {
return ["opened", "closed", "velocity"];
case "engagement":
return ["stars", "forks", "activity_ratio"];
case "forks":
case "stars":
return ["total", "over_range", "average_over_range"];
default:
throw new Error("Invalid repository stat card type");
}
Expand Down Expand Up @@ -123,8 +143,14 @@ export const RepositoryStatCard = ({ stats, type, isLoading, hasError }: Reposit
.map(([stat, value]) => {
return (
<tr key={stat} className="flex flex-col">
<th scope="row" className="capitalize font-normal text-lg lg:text-sm text-light-slate-12 text-left">
{stat.replace("_", " ")}
<th scope="row" className="capitalize font-normal text-xs lg:text-sm text-light-slate-12 text-left">
{type === "stars" || type === "forks"
? stat === "over_range"
? `Over ${stats.range} Days`
: stat === "average_over_range"
? `Avg. per day`
: stat.replace("_", " ")
: stat.replace("_", " ")}
<span
className={`w-2 h-2 rounded-full ml-1 ${
stat === "opened"
Expand Down
1 change: 1 addition & 0 deletions next-types.d.ts
Expand Up @@ -25,6 +25,7 @@ interface DbRepo {
readonly spam_prs_count?: number;
readonly pr_velocity_count?: number;
readonly churnTotalCount?: number;
readonly activity_ratio?: number;
readonly language: string;
readonly stars: number;
readonly description: string;
Expand Down
68 changes: 45 additions & 23 deletions pages/s/[org]/[repo]/index.tsx
@@ -1,6 +1,5 @@
import { GetServerSidePropsContext } from "next";
import { useRouter } from "next/router";
import { ComponentProps } from "react";
import { HiOutlineExternalLink } from "react-icons/hi";
import { usePostHog } from "posthog-js/react";
import { FiCopy } from "react-icons/fi";
Expand All @@ -11,9 +10,9 @@ import ProfileLayout from "layouts/profile";
import Avatar from "components/atoms/Avatar/avatar";
import StarsChart from "components/Graphs/StarsChart";
import ForksChart from "components/Graphs/ForksChart";
import MetricCard from "components/Graphs/MetricCard";
import ClientOnly from "components/atoms/ClientOnly/client-only";
import { DayRangePicker } from "components/shared/DayRangePicker";
import { RepositoryStatCard } from "components/Workspaces/RepositoryStatCard";
import { getRepositoryOgImage, RepositoryOgImage } from "components/Repositories/RepositoryOgImage";
import { useToast } from "lib/hooks/useToast";
import { shortenUrl } from "lib/utils/shorten-url";
Expand Down Expand Up @@ -42,7 +41,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
return { props: { repoData, image: owner?.avatar_url || "", ogImageUrl } };
}

type Range = ComponentProps<typeof MetricCard>["range"];
type Range = 30 | 7 | 90 | 180 | 360;

interface RepoPageProps {
repoData: DbRepo;
Expand Down Expand Up @@ -82,6 +81,9 @@ export default function RepoPage({ repoData, image, ogImageUrl }: RepoPageProps)
range,
});

const starsRangedTotal = starsData?.reduce((prev, curr) => prev + curr.star_count!, 0);
const forksRangedTotal = forkStats?.reduce((prev, curr) => prev + curr.forks_count!, 0);

const copyUrlToClipboard = async () => {
const url = new URL(window.location.href).toString();
posthog!.capture(`clicked: ${repoData.full_name} repo page share`);
Expand Down Expand Up @@ -128,26 +130,46 @@ export default function RepoPage({ repoData, image, ogImageUrl }: RepoPageProps)
</Button>
</div>
</div>
<section className="flex flex-col gap-2 md:gap-4 lg:gap-8 lg:flex-row w-full justify-between">
<ClientOnly>
<MetricCard variant="stars" stats={starsData} range={range} isLoading={isStarsDataLoading} />
<MetricCard variant="forks" stats={forkStats} range={range} isLoading={isForksDataLoading} />
</ClientOnly>
</section>
<StarsChart
stats={starsData}
total={repoData.stars}
range={range}
syncId={syncId}
isLoading={isStarsDataLoading}
/>
<ForksChart
stats={forkStats}
total={repoData.forks}
range={range}
syncId={syncId}
isLoading={isForksDataLoading}
/>
<ClientOnly>
<section className="w-full h-fit grid grid-cols-1 lg:grid-cols-2 grid-flow-row gap-2">
<RepositoryStatCard
type="stars"
isLoading={isStarsDataLoading}
hasError={starsError !== undefined}
stats={{
total: repoData.stars,
over_range: starsRangedTotal!,
range,
average_over_range: Math.round(starsRangedTotal! / range),
}}
/>
<RepositoryStatCard
type="forks"
isLoading={isForksDataLoading}
hasError={forkError !== undefined}
stats={{
total: repoData.forks,
over_range: forksRangedTotal!,
range,
average_over_range: Math.round(forksRangedTotal! / range),
}}
/>
</section>
<StarsChart
stats={starsData}
total={repoData.stars}
range={range}
syncId={syncId}
isLoading={isStarsDataLoading}
/>
<ForksChart
stats={forkStats}
total={repoData.forks}
range={range}
syncId={syncId}
isLoading={isForksDataLoading}
/>
</ClientOnly>
</section>
</ProfileLayout>
</>
Expand Down

0 comments on commit 43ffce4

Please sign in to comment.