mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-30 14:58:08 +00:00
The past year is kept per public repository and rolled up per organization. zeekay's commits and merged pull requests sit inside those totals and on a line of their own. Private repository names stay off the record. The daily build refreshes the slices with the global census. Co-authored-by: z <[email protected]>
172 lines
11 KiB
TypeScript
172 lines
11 KiB
TypeScript
'use client'
|
|
|
|
import { useI18n } from '@hanzo/i18n/react'
|
|
import { Text, View, XStack, YStack } from '@hanzo/ui'
|
|
import { Heatmap, More, Sparkline } from '@hanzo/ui/marketing'
|
|
import activity from '@/lib/data/oss-activity.json'
|
|
import stats from '@/lib/data/oss-stats.json'
|
|
import velocity from '@/lib/data/velocity.json'
|
|
import { Card, Caption, Mono } from '@/components/home/plate'
|
|
import { Onward } from '@/components/home/label'
|
|
import { figures, weekly, type Figure as Counted } from '@/lib/activity'
|
|
|
|
/**
|
|
* What the public repositories shipped, counted and not typed.
|
|
*
|
|
* Every figure and every cell is read from the snapshot. scripts/sync-oss.ts
|
|
* writes the grid, and scripts/velocity.mjs rewrites it to the stack total:
|
|
* each commit once, forks only after the fork, other branches included,
|
|
* private commits we can date included. `stats.read` is when it was read.
|
|
* A figure the snapshot does not hold is not drawn.
|
|
* and with no activity at all the section is not drawn: there is no placeholder
|
|
* number and no fallback. The grid and the bars are @hanzo/ui's (`Heatmap`,
|
|
* `Sparkline`): this file hands them the data and the words.
|
|
*/
|
|
|
|
const daily = activity.daily as Record<string, number>
|
|
const active = activity.active as Record<string, number>
|
|
const people = (stats as { contributors?: { login: string; contributions: number; restricted?: number }[] }).contributors ?? []
|
|
const privateCommits = (stats as { private?: { commits?: number } }).private?.commits
|
|
const privateContributions = people.reduce((n, p) => n + (p.restricted ?? 0), 0)
|
|
|
|
const fmt = (n: number) => n.toLocaleString('en-US')
|
|
const label = (k: string) => new Date(`${k}T00:00:00Z`).toLocaleDateString('en-US', { timeZone: 'UTC', month: 'short', day: 'numeric', year: 'numeric' })
|
|
const hour = (iso: string) => new Date(iso).toLocaleString('en-US', { timeZone: 'UTC', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit', hour12: false })
|
|
|
|
function Figure({ id, title, value, caption, children }: { id: string; title: string; value: string; caption?: string; children?: React.ReactNode }) {
|
|
return (
|
|
<Card title={title}>
|
|
<Text fontFamily="$mono" fontSize="2rem" lineHeight="2.25rem" fontWeight="600" color="var(--foreground)" $platform-web={{ fontVariantNumeric: 'tabular-nums' }} data-figure={id}>
|
|
{value}
|
|
</Text>
|
|
{children}
|
|
{caption ? <Caption>{caption}</Caption> : null}
|
|
</Card>
|
|
)
|
|
}
|
|
|
|
function Latest() {
|
|
const { t } = useI18n()
|
|
const rows = activity.latest as { repo: string; at: string; sha: string; message: string }[]
|
|
if (!rows.length) return null
|
|
return (
|
|
<Card title={t('Latest commits')}>
|
|
<YStack render="ul" $platform-web={{ listStyle: 'none', margin: 0, padding: 0 }} data-slot="latest">
|
|
{rows.map((r) => (
|
|
<XStack key={`${r.repo}@${r.sha}`} render="li" items="baseline" gap={16} py={10} borderTopWidth={1} borderColor="var(--border)" flexWrap="wrap" $md={{ flexWrap: 'nowrap' }}>
|
|
<Mono color="var(--muted-foreground)" shrink={0} width={200} $platform-web={{ whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
|
|
{r.repo}
|
|
</Mono>
|
|
<Text render={<a href={`https://github.com/${r.repo}/commit/${r.sha}`} target="_blank" rel="noopener noreferrer" />} flex={1} minW={200} fontSize="$2" lineHeight="$2" color="var(--foreground)" $platform-web={{ textDecoration: 'none' }}>
|
|
{r.message}
|
|
</Text>
|
|
<Mono color="var(--muted-foreground)" shrink={0} data-i18n-ltr>
|
|
<time dateTime={r.at}>{hour(r.at)} UTC</time>
|
|
</Mono>
|
|
</XStack>
|
|
))}
|
|
</YStack>
|
|
</Card>
|
|
)
|
|
}
|
|
|
|
/** The panel: the counted figures the snapshot holds, the year as a grid, and the newest commits. Not drawn without activity. */
|
|
export default function Activity() {
|
|
const { t } = useI18n()
|
|
if (!Object.keys(daily).length) return null
|
|
const titles = { year: t('Commits, past year'), week: t('Commits, past 7 days'), repos: t('Public repositories'), active: t('Active this month') } as const
|
|
const notes = (f: Counted) => (f.id === 'repos' && f.of != null ? t('{n} organizations', { n: f.of }) : f.id === 'active' ? t('repositories with a commit in 30 days') : undefined)
|
|
const shown = figures(stats)
|
|
const pace = velocity.commits as { week: number; month: number; year: number } | null
|
|
const merged = velocity.merges as { week: number; month: number; year: number; missed?: number } | null
|
|
const back = velocity.contributedBack as { week: number; month: number; year: number; capped?: boolean } | null
|
|
const forgeRead = (velocity as { forge?: unknown }).forge
|
|
const orgs = (velocity as { orgs?: { name: string; commits: { year: number }; merges: { year: number }; repositories: number }[] }).orgs ?? []
|
|
const zach = (velocity as { zeekay?: { commits: { year: number }; merges: { year: number }; capped?: boolean; privateCommits?: number } }).zeekay
|
|
return (
|
|
<YStack gap={16} data-slot="activity">
|
|
{pace ? (
|
|
<Card title={t('How fast our stack is evolving')}>
|
|
<Text fontFamily="$mono" fontSize="2rem" lineHeight="2.25rem" fontWeight="600" color="var(--foreground)" $platform-web={{ fontVariantNumeric: 'tabular-nums' }} data-figure="pace" data-i18n-ltr>
|
|
{fmt(pace.year)}
|
|
</Text>
|
|
<Caption>{t('Commits in the past year, each commit once. Our repositories count the default branch and commits on other branches that are not already on it. A fork counts commits by Hanzo people after the fork. Private commits we can date are included. Names of private repositories are not shown.')}</Caption>
|
|
<Caption>{t('{week} in the past 7 days. {month} in the past 30 days.', { week: fmt(pace.week), month: fmt(pace.month) })}</Caption>
|
|
{merged && (merged.missed ?? 0) === 0 ? <Caption>{t('{week} pull requests merged in 7 days, {month} in 30 days, {year} in the past year.', { week: fmt(merged.week), month: fmt(merged.month), year: fmt(merged.year) })}</Caption> : null}
|
|
{back ? <Caption>{back.capped
|
|
? t('At least {week} commits contributed back upstream in 7 days, {month} in 30 days, {year} in the past year.', { week: fmt(back.week), month: fmt(back.month), year: fmt(back.year) })
|
|
: t('{week} commits contributed back upstream in 7 days, {month} in 30 days, {year} in the past year.', { week: fmt(back.week), month: fmt(back.month), year: fmt(back.year) })}</Caption> : null}
|
|
{forgeRead ? null : <Caption>{t('GitHub. The forge is counted when its admin token is present at the build.')}</Caption>}
|
|
</Card>
|
|
) : null}
|
|
{orgs.length ? (
|
|
<Card title={t('Each organization, past year')}>
|
|
<YStack data-slot="orgs">
|
|
{orgs.map((org) => (
|
|
<XStack key={org.name} items="baseline" justify="space-between" gap={12} py={8} borderTopWidth={1} borderColor="var(--border)">
|
|
<Text flex={1} minW={0} fontSize="$2" lineHeight="$2" color="var(--foreground)">{org.name}</Text>
|
|
<Text data-i18n-ltr fontFamily="$mono" fontSize="$2" color="var(--foreground)" $platform-web={{ fontVariantNumeric: 'tabular-nums' }}>{fmt(org.commits.year)}</Text>
|
|
<Text data-i18n-ltr fontFamily="$mono" fontSize="$2" color="var(--muted-foreground)" $platform-web={{ fontVariantNumeric: 'tabular-nums' }}>{t('{n} merged', { n: fmt(org.merges.year) })}</Text>
|
|
</XStack>
|
|
))}
|
|
</YStack>
|
|
<Caption>{t('Commits on the default branch. A fork counts commits by Hanzo people after the fork. Merged pull requests are counted in the same repositories. Each public repository is in the snapshot. Merged pull requests in private repositories are in the organization total, and those names are not shown.')}</Caption>
|
|
{zach ? <Caption>{zach.capped
|
|
? t('At least {commits} commits in the past year are by zeekay on these accounts, and {merges} of his pull requests were merged. {private} more of his commits are in private repositories and are included in the headline.', { commits: fmt(zach.commits.year), merges: fmt(zach.merges.year), private: fmt(zach.privateCommits ?? 0) })
|
|
: t('{commits} commits in the past year are by zeekay on these accounts, and {merges} of his pull requests were merged. {private} more of his commits are in private repositories and are included in the headline.', { commits: fmt(zach.commits.year), merges: fmt(zach.merges.year), private: fmt(zach.privateCommits ?? 0) })}</Caption> : null}
|
|
</Card>
|
|
) : null}
|
|
{shown.length ? (
|
|
<View display="grid" gridTemplateColumns="repeat(2, minmax(0, 1fr))" gap={12} $md={{ gridTemplateColumns: `repeat(${shown.length}, minmax(0, 1fr))`, gap: 16 }}>
|
|
{shown.map((f) => (
|
|
<Figure key={f.id} id={f.id} title={titles[f.id]} value={fmt(f.value)} caption={notes(f)}>
|
|
{f.id === 'year' ? <Sparkline values={weekly(daily, activity.from, activity.to)} label={t('Commits a week over the past year')} height={28} /> : null}
|
|
</Figure>
|
|
))}
|
|
</View>
|
|
) : null}
|
|
{privateCommits || privateContributions ? (
|
|
<View display="grid" gridTemplateColumns="repeat(2, minmax(0, 1fr))" gap={12}>
|
|
{privateCommits ? (
|
|
<Figure id="private" title={t('Commits in private repos')} value={fmt(privateCommits)} caption={t('Past year. The repository names are not shown.')} />
|
|
) : null}
|
|
{privateContributions ? (
|
|
<Figure id="private-contributions" title={t('Private contributions')} value={fmt(privateContributions)} caption={t('Past year, including issues and reviews.')} />
|
|
) : null}
|
|
</View>
|
|
) : null}
|
|
{people.length ? (
|
|
<View display="grid" gridTemplateColumns="repeat(2, minmax(0, 1fr))" gap={12} $md={{ gridTemplateColumns: `repeat(${people.length}, minmax(0, 1fr))`, gap: 16 }}>
|
|
{people.map((p) => (
|
|
<Figure
|
|
key={p.login}
|
|
id={p.login}
|
|
title={t('{name}, past year', { name: p.login })}
|
|
value={fmt(p.contributions)}
|
|
caption={p.restricted ? t('GitHub contributions, private included') : t('GitHub contributions')}
|
|
/>
|
|
))}
|
|
</View>
|
|
) : null}
|
|
<Card title={t('Commits a day')}>
|
|
<Heatmap
|
|
days={daily}
|
|
from={activity.from}
|
|
to={activity.to}
|
|
locale="en-US"
|
|
label={t('Commits a day over the past year: public repositories, plus the private commits we can read, {n} in all.', { n: fmt(stats.commits.year) })}
|
|
line={(day, n) => t('{date} ยท {n} commits across {repos} repositories', { date: label(day), n: fmt(n), repos: fmt(active[day] ?? 0) })}
|
|
rest={t('Commits a day, from {from} to {to}', { from: label(activity.from), to: label(activity.to) })}
|
|
legend={{ less: t('Less'), more: t('More') }}
|
|
/>
|
|
</Card>
|
|
<Latest />
|
|
<XStack justify="flex-end">
|
|
<More href="https://github.com/hanzoai">
|
|
<Onward>{t('Read the source')}</Onward>
|
|
</More>
|
|
</XStack>
|
|
</YStack>
|
|
)
|
|
}
|