-
-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Website: new page for GitHub insights (#926)
- Loading branch information
Showing
20 changed files
with
1,971 additions
and
1 deletion.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
{ | ||
"metadata": { | ||
"title": "Open-Source Insights ", | ||
"heading": "Contributors" | ||
}, | ||
"contributors": { | ||
"title": "Contributors" | ||
}, | ||
"hero": { | ||
"title-1": [ | ||
{ | ||
"text": "Tools for Change. " | ||
}, | ||
{ | ||
"text": "Open to All.", | ||
"color": "accent" | ||
} | ||
], | ||
"subtitle": "Everything we build is open source—free to use, adapt, and improve. Join our volunteer community creating tools for equality and change." | ||
}, | ||
"overview": { | ||
"forks": { | ||
"title": "Forks", | ||
"time": "last month" | ||
}, | ||
"commits": { | ||
"title": "Commits", | ||
"time": "last month" | ||
}, | ||
"stars": { | ||
"title": "GitHub Stars", | ||
"time": "last month" | ||
} | ||
}, | ||
"issues": { | ||
"title": "Open Issues", | ||
"header": "Issue Title", | ||
"link": "View on GitHub", | ||
"filter": "All Issues" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import * as AvatarPrimitive from '@radix-ui/react-avatar'; | ||
import * as React from 'react'; | ||
|
||
import { cn } from '../lib/utils'; | ||
|
||
const Avatar = React.forwardRef< | ||
React.ElementRef<typeof AvatarPrimitive.Root>, | ||
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root> | ||
>(({ className, ...props }, ref) => ( | ||
<AvatarPrimitive.Root | ||
ref={ref} | ||
className={cn('relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full', className)} | ||
{...props} | ||
/> | ||
)); | ||
Avatar.displayName = AvatarPrimitive.Root.displayName; | ||
|
||
const AvatarImage = React.forwardRef< | ||
React.ElementRef<typeof AvatarPrimitive.Image>, | ||
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image> | ||
>(({ className, ...props }, ref) => ( | ||
<AvatarPrimitive.Image ref={ref} className={cn('aspect-square h-full w-full', className)} {...props} /> | ||
)); | ||
AvatarImage.displayName = AvatarPrimitive.Image.displayName; | ||
|
||
const AvatarFallback = React.forwardRef< | ||
React.ElementRef<typeof AvatarPrimitive.Fallback>, | ||
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback> | ||
>(({ className, ...props }, ref) => ( | ||
<AvatarPrimitive.Fallback | ||
ref={ref} | ||
className={cn('bg-muted flex h-full w-full items-center justify-center rounded-full', className)} | ||
{...props} | ||
/> | ||
)); | ||
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName; | ||
|
||
export { Avatar, AvatarFallback, AvatarImage }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
76 changes: 76 additions & 0 deletions
76
website/src/app/[lang]/[region]/(website)/open-source/(components)/contributors-client.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
'use client'; | ||
|
||
import { Avatar, AvatarFallback, AvatarImage, Button, Typography } from '@socialincome/ui'; | ||
import { useState } from 'react'; | ||
|
||
type ContributorProp = { | ||
name: string; | ||
commits: number; | ||
avatarUrl: string; | ||
}; | ||
|
||
function Contributor({ name, commits, avatarUrl }: ContributorProp) { | ||
return ( | ||
<article className="flex min-w-60 flex-row items-center py-2"> | ||
<Avatar className="h-12 w-12 flex-shrink-0"> | ||
<AvatarImage src={avatarUrl} alt={`${name}'s avatar`} /> | ||
<AvatarFallback>{name.slice(0, 2).toUpperCase()}</AvatarFallback> | ||
</Avatar> | ||
<div className="ml-4 flex flex-col items-start"> | ||
<Typography as="p" size="xl"> | ||
{name} | ||
</Typography> | ||
<Typography as="span" size="md" className="text-card-foreground-muted mt-1"> | ||
{commits} {commits === 1 ? 'commit' : 'commits'} | ||
</Typography> | ||
</div> | ||
</article> | ||
); | ||
} | ||
|
||
export function OpenSourceContributorsClient({ | ||
contributors, | ||
heading, | ||
totalContributors, | ||
}: { | ||
contributors: Array<{ name: string; commits: number; avatarUrl: string; id: number }>; | ||
heading: string; | ||
totalContributors: number; | ||
}) { | ||
const [showAllContributors, setShowAllContributors] = useState(false); | ||
|
||
const displayedContributors = showAllContributors ? contributors : contributors.slice(0, 16); | ||
|
||
return ( | ||
<section className="flex flex-col justify-self-start"> | ||
<section> | ||
<Typography as="h2" size="3xl" lineHeight="snug" className="mb-10"> | ||
{`${totalContributors} ${heading}`} | ||
</Typography> | ||
</section> | ||
|
||
<section className="flex flex-wrap gap-4"> | ||
{displayedContributors.map((contributor) => ( | ||
<Contributor | ||
key={contributor.id} | ||
name={contributor.name} | ||
commits={contributor.commits} | ||
avatarUrl={contributor.avatarUrl} | ||
/> | ||
))} | ||
</section> | ||
|
||
{!showAllContributors && totalContributors > 16 && ( | ||
<div className="mt-12 flex justify-center"> | ||
<Button | ||
variant="link" | ||
onClick={() => setShowAllContributors(true)} | ||
className="text-card-foreground mr-20 text-xl" | ||
> | ||
{`Show all ${totalContributors} contributors`} | ||
</Button> | ||
</div> | ||
)} | ||
</section> | ||
); | ||
} |
42 changes: 42 additions & 0 deletions
42
website/src/app/[lang]/[region]/(website)/open-source/(components)/filterForm.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
'use client'; | ||
|
||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@socialincome/ui'; | ||
import { useState } from 'react'; | ||
|
||
interface FilterFormProps { | ||
labels: string[]; | ||
handleLabel: (label: string) => void; | ||
filterText: string; | ||
} | ||
|
||
export function FilterForm({ labels, handleLabel, filterText }: FilterFormProps) { | ||
const [selectedLabel, setSelectedLabel] = useState(''); | ||
|
||
const handleChange = (value: string) => { | ||
if (value === filterText) { | ||
setSelectedLabel(''); | ||
handleLabel(''); | ||
} else { | ||
setSelectedLabel(value); | ||
handleLabel(value); | ||
} | ||
}; | ||
|
||
return ( | ||
<section className="mb-8 max-w-44"> | ||
<Select value={selectedLabel} onValueChange={handleChange}> | ||
<SelectTrigger aria-label="Filter issues by label"> | ||
<SelectValue placeholder={filterText} /> | ||
</SelectTrigger> | ||
<SelectContent> | ||
<SelectItem value={filterText}>{filterText}</SelectItem> | ||
{labels.map((label) => ( | ||
<SelectItem key={label} value={label}> | ||
{label} | ||
</SelectItem> | ||
))} | ||
</SelectContent> | ||
</Select> | ||
</section> | ||
); | ||
} |
91 changes: 91 additions & 0 deletions
91
website/src/app/[lang]/[region]/(website)/open-source/(components)/get-commits.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
const owner = 'socialincome-san'; | ||
const repo = 'public'; | ||
|
||
interface GitHubCommit { | ||
author: { | ||
id: number; | ||
login: string; | ||
avatar_url: string; | ||
} | null; | ||
commit: { | ||
author: { | ||
date: string; | ||
}; | ||
}; | ||
} | ||
|
||
export async function getCommits() { | ||
// Calculate the date 30 days ago from today | ||
const endDate = new Date().toISOString(); | ||
const startDate = new Date(); | ||
startDate.setDate(startDate.getDate() - 30); | ||
const startDateISO = startDate.toISOString(); | ||
|
||
// Fetch recent commits from the last 30 days | ||
const commitUrl = `https://api.github.com/repos/${owner}/${repo}/commits?since=${startDateISO}&until=${endDate}`; | ||
const headers: Record<string, string> = { | ||
Accept: 'application/vnd.github+json', | ||
}; | ||
// Conditionally add the Authorization header if GITHUB_PAT is available | ||
if (process.env.GITHUB_PAT) { | ||
headers['Authorization'] = `Bearer ${process.env.GITHUB_PAT}`; | ||
} | ||
const res = await fetch(commitUrl, { | ||
headers, | ||
}); | ||
|
||
if (!res.ok) { | ||
const errorDetails = await res.text(); | ||
const status = res.status; | ||
if (status === 403) { | ||
throw new Error( | ||
'GitHub API rate limit exceeded. Please try again later or increase rate limit by authenticating.', | ||
); | ||
} else if (status === 404) { | ||
throw new Error(`GitHub repository ${owner}/${repo} not found.`); | ||
} else { | ||
throw new Error(`Failed to fetch recent commits from GitHub: ${status} - ${errorDetails}`); | ||
} | ||
} | ||
|
||
const recentCommits: GitHubCommit[] = await res.json(); | ||
|
||
// Fetch total commit count | ||
const totalCommitsUrl = `https://api.github.com/repos/${owner}/${repo}/commits?per_page=1`; | ||
const totalCommitsRes = await fetch(totalCommitsUrl, { | ||
headers, | ||
}); | ||
|
||
if (!totalCommitsRes.ok) { | ||
const errorDetails = await totalCommitsRes.text(); | ||
const status = totalCommitsRes.status; | ||
if (status === 403) { | ||
throw new Error(`GitHub API rate limit exceeded: ${status} - ${errorDetails}.`); | ||
} else if (status === 404) { | ||
throw new Error(`GitHub repository ${owner}/${repo} not found while fetching total commits.`); | ||
} else { | ||
throw new Error(`Failed to fetch total commits from GitHub: ${status} - ${errorDetails}`); | ||
} | ||
} | ||
|
||
// Extract the last page number from the Link header to get the total commit count | ||
const linkHeader = totalCommitsRes.headers.get('link'); | ||
// Default to 1 in case no Link header is provided | ||
let totalCommits = 1; | ||
|
||
if (linkHeader) { | ||
const match = linkHeader.match(/&page=(\d+)>; rel="last"/); | ||
if (match) { | ||
totalCommits = parseInt(match[1], 10); | ||
} else { | ||
console.warn('Link header exists but could not parse total commits page count.'); | ||
} | ||
} else { | ||
console.warn('No Link header found; assuming a single commit.'); | ||
} | ||
|
||
return { | ||
totalCommits, | ||
newCommits: recentCommits.length, | ||
}; | ||
} |
Oops, something went wrong.