feat: add all-time variants of productive, language, contribution cards

Four time-bounded cards ("last year") now have all-time counterparts, and
the stats card gains a lifetime commits row.

New cards:
- 6-most-commit-language-all-time.svg (byte-weighted, all lifetime commits)
- 7-productive-time-all-time.svg       (hour histogram over all lifetime commits)
- 8-contributions-all-time.svg         (area chart spanning every active year)

Data pipeline:
- Drop the "since" filter from commitHistoryQuery; FetchProductive now
  paginates unbounded commits and splits each commit into last-year and
  all-time buckets in a single pass — no extra API calls.
- New contributionYearQuery iterates user.contributionYears to
  concatenate calendar data and accumulate TotalCommitsAllTime.
- -commits-per-repo default bumped 100 → 500 to give all-time depth.

Polish:
- Productive-time title embeds the configured tz as "UTC±N.NN" (e.g.
  UTC+7.00) on both last-year and all-time cards.
- Contribution x-axis flipped to mm/yy with an "mm/yy" footer caption
  paralleling productive-time's "hour of day".
- Contribution x-axis label stride now targets ~6 labels regardless of
  bucket count so the all-time chart (~100 months) stays readable while
  the underlying curve still samples every month.
This commit is contained in:
tiennm99 committed 2026-04-18 21:40:46 +07:00
1 parent 1ad861787a
commit 50b29b4a78
11 files changed
+280 -58

No files matched your search

+8 -6
View File
@@ -28,12 +28,13 @@ type profileGQL struct {
RepositoriesContributedTo struct{ TotalCount int } `json:"repositoriesContributedTo"`
ContributionsCollection struct {
TotalCommitContributions int `json:"totalCommitContributions"`
TotalIssueContributions int `json:"totalIssueContributions"`
TotalPullRequestContributions int `json:"totalPullRequestContributions"`
TotalPullRequestReviewContributions int `json:"totalPullRequestReviewContributions"`
TotalRepositoryContributions int `json:"totalRepositoryContributions"`
RestrictedContributionsCount int `json:"restrictedContributionsCount"`
ContributionYears []int `json:"contributionYears"`
TotalCommitContributions int `json:"totalCommitContributions"`
TotalIssueContributions int `json:"totalIssueContributions"`
TotalPullRequestContributions int `json:"totalPullRequestContributions"`
TotalPullRequestReviewContributions int `json:"totalPullRequestReviewContributions"`
TotalRepositoryContributions int `json:"totalRepositoryContributions"`
RestrictedContributionsCount int `json:"restrictedContributionsCount"`
ContributionCalendar struct {
TotalContributions int `json:"totalContributions"`
Weeks []struct {
@@ -107,6 +108,7 @@ func (c *Client) FetchProfile(login string) (*Profile, error) {
p.TotalCommits = cc.TotalCommitContributions
p.TotalReviews = cc.TotalPullRequestReviewContributions
p.TotalContributions = cc.ContributionCalendar.TotalContributions + cc.RestrictedContributionsCount
p.ContributionYears = append([]int(nil), cc.ContributionYears...)
// Flatten week → day into a linear daily series sorted by date.
for _, w := range cc.ContributionCalendar.Weeks {