Feat and fix cards 9021963555964763502#13
Merged
Conversation
…umentation. - Refactored `src/github.js` for robust data fetching with `safeFetch` and timeouts. - Optimized API usage by reducing page limits and streamlining language fetching. - Improved contribution graph scraping to handle `td` and `rect` elements. - Updated all API handlers to handle null/empty data gracefully without crashing. - Implemented the Mastercard (Dashboard) card at `/api/master`. - Implemented the Issues stats card at `/api/issues`. - Updated `README.md` and `public/index.html` with new card examples and parameters. - Added CI workflow and `package-lock.json`. Co-authored-by: Chintanpatel24 <216989679+Chintanpatel24@users.noreply.github.com>
- Redesigned Mastercard into a structured, vertical dashboard for GitHub READMEs. - Fixed text overlap in Full PR card using dynamic truncation. - Optimized Mastercard data fetching to include accurate Merged PR counts. - Ensured all card handlers handle rate limits and API errors gracefully. - Updated documentation and landing page with new Mastercard and Issues cards. - Restored PR summary card layout as requested. Co-authored-by: Chintanpatel24 <216989679+Chintanpatel24@users.noreply.github.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
This PR updates Gitly’s SVG cards and GitHub data-fetching logic with a focus on a redesigned “master” dashboard card, improved visual spacing/truncation, and more resilient API handlers that return fallback (zero) data instead of error SVGs.
Changes:
- Redesign the master dashboard SVG into a vertical, structured layout (heatmap, languages, PR/issues summary, top repos).
- Tweak PR card rendering (dynamic repo-name truncation, color fallbacks, bar/value spacing).
- Adjust GitHub fetching behavior to reduce rate-limit pressure (shorter pagination/concurrency, some endpoints now return fallback data instead of erroring).
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| src/svg-pr.js | PR card styling adjustments, dynamic name truncation, color fallback variables. |
| src/svg-master.js | Major master dashboard SVG layout redesign (vertical sections, stacked language bar, PR/issues summary). |
| src/github.js | Rate-limit-oriented fetch changes, updated contribution HTML parsing, reduced pagination/concurrency. |
| api/working-hours.js | Return zero-data fallback on fetch failure instead of rendering an error SVG. |
| api/streak.js | Harden contribution parsing usage with defaults; return zero-data fallback on failure. |
| api/profile.js | Add fallback profile object on fetch failure. |
| api/pr-stats.js | Use null-safe counts/profile access; continue rendering with fallback data on fetch failure. |
| api/overview.js | Tighten PR line-change sampling limits; add fallback data on fetch failure; adjust max_prs defaults. |
| api/master.js | Add issues + merged PR counts into master payload; fallback data on failure. |
| api/languages.js | Validate language fetch result and fallback to empty language data on failure. |
| api/issues.js | Null-safe counts/profile access; continue rendering with fallback data on fetch failure. |
| api/contribution.js | Fallback to empty contribution data on fetch failure. |
| api/commits.js | Fallback to empty contribution data on fetch failure. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <g transform="translate(${P}, 52)"><rect width="${sw}" height="78" rx="8" fill="#${colors.accent_color}" opacity=".06"/><text x="${sw / 2}" y="40" text-anchor="middle" class="n" fill="#${colors.accent_color}">${mergedPRs}</text><text x="${sw / 2}" y="58" text-anchor="middle" class="l" fill="#8b949e">Merged</text></g> | ||
| <g transform="translate(${P + sw + 12}, 52)"><rect width="${sw}" height="78" rx="8" fill="#${colors.accent_color}" opacity=".04"/><text x="${sw / 2}" y="40" text-anchor="middle" class="n" fill="#${colors.accent_color}">${totalPRs}</text><text x="${sw / 2}" y="58" text-anchor="middle" class="l" fill="#8b949e">Total PRs</text></g> | ||
| <g transform="translate(${P}, 52)"><rect width="${sw}" height="78" rx="8" fill="#${accentColor}" opacity=".06"/><text x="${sw / 2}" y="40" text-anchor="middle" class="n" fill="#${accentColor}">${mergedPRs}</text><text x="${sw / 2}" y="58" text-anchor="middle" class="l" fill="#8b949e">Merged</text></g> | ||
| <g transform="translate(${P + sw + 12}, 52)"><rect width="${sw}" height="78" rx="8" fill="#${accentColor}" opacity=".04"/><text x="${sw / 2}" y="40" text-anchor="middle" class="n" fill="#${accentColor}">${totalPRs}</text><text x="${sw / 2}" y="58" text-anchor="middle" class="l" fill="#8b949e">Closed</text></g> |
Comment on lines
+119
to
+120
| sections += `<rect x="${barX}" y="0" width="${w}" height="10" fill="#${getLanguageColor(lang.name)}" ${barX === 0 ? 'rx="5"' : ''} ${barX + w >= innerW - 1 ? 'rx="5"' : ''}/>`; | ||
| barX += w; |
| * Master Card SVG generation - all cards merged into one dashboard SVG. | ||
| * Enhanced design with streaks, trend line, and polished visuals. | ||
| * Master Card SVG generation - Vertical Structured Dashboard. | ||
| * Clean, classic, and fited for GitHub Readme. |
Comment on lines
43
to
+53
| /** | ||
| * Fetch all pull requests by a user across all public repos. | ||
| * Fetch all pull requests by a user. | ||
| */ | ||
| async function fetchUserPullRequests(username) { | ||
| const perPage = 100; | ||
| let page = 1; | ||
| let allPRs = []; | ||
|
|
||
| while (page <= 5) { | ||
| const url = `${GITHUB_API}/search/issues?q=author:${encodeURIComponent(username)}+type:pr&per_page=${perPage}&page=${page}`; | ||
| const data = await safeFetch(url); | ||
| if (!data || !data.items || data.items.length === 0) break; | ||
|
|
||
| allPRs = allPRs.concat(data.items); | ||
| if (allPRs.length >= data.total_count || data.items.length < perPage) break; | ||
| page++; | ||
| } | ||
|
|
||
| return allPRs; | ||
| try { | ||
| while (page <= 2) { // Limited to 2 pages to save rate limit | ||
| const url = `${GITHUB_API}/search/issues?q=author:${encodeURIComponent(username)}+type:pr&per_page=${perPage}&page=${page}`; | ||
| const data = await safeFetch(url); |
Comment on lines
+142
to
156
| const entryRegex = /<(?:td|rect)\b[^>]*\bdata-date="(\d{4}-\d{2}-\d{2})"[^>]*data-level="(\d+)"[^>]*>/g; | ||
| const dates = []; | ||
| let match; | ||
| while ((match = tdRegex.exec(html)) !== null) { | ||
| while ((match = entryRegex.exec(html)) !== null) { | ||
| const date = match[1]; | ||
| const level = parseInt(match[2], 10); | ||
| const tag = match[0]; | ||
| const idMatch = tag.match(/\bid="([^"]+)"/); | ||
| const dateMatch = tag.match(/\bdata-date="(\d{4}-\d{2}-\d{2})"/); | ||
| const levelMatch = tag.match(/\bdata-level="(\d+)"/); | ||
| if (!dateMatch || !levelMatch) continue; | ||
|
|
||
| dates.push({ | ||
| id: idMatch ? idMatch[1] : `day-${dates.length}`, | ||
| date: dateMatch[1], | ||
| level: parseInt(levelMatch[1], 10), | ||
| date, | ||
| level, | ||
| }); | ||
| } |
Comment on lines
49
to
53
| const scope = normalizeLinesScope(lines_scope); | ||
| const maxPRs = scope === "all" ? 0 : parseMaxPRs(max_prs, 30, 200); | ||
| const maxPRs = scope === "all" ? 50 : parseMaxPRs(max_prs, 20, 50); | ||
| const cacheKey = scope === "all" | ||
| ? `overview:${username.toLowerCase()}:lines_scope=all` | ||
| : `overview:${username.toLowerCase()}:lines_scope=recent:max_prs=${maxPRs}`; |
Comment on lines
88
to
+93
| data = { | ||
| username: profile.login || username, | ||
| totalPRs: prs.length, | ||
| openPRs: prs.filter(pr => pr.state === "open").length, | ||
| repoCount: profile.public_repos || 0, | ||
| languages: langData.languages, | ||
| contributions: contributionData.totalContributions, | ||
| username: profile?.login || username, | ||
| totalPRs: prs?.length || 0, | ||
| openPRs: (prs || []).filter(pr => pr.state === "open").length, | ||
| mergedPRs: mergedPRCount || 0, | ||
| repoCount: profile?.public_repos || 0, |
Comment on lines
51
to
+58
| data = { | ||
| repoMap, | ||
| totalPRs: prs.length, | ||
| openPRs: openPRCount, | ||
| closedPRs: closedPRCount, | ||
| mergedPRs: mergedPRCount, | ||
| totalPRs: prs?.length || 0, | ||
| openPRs: openPRCount || 0, | ||
| closedPRs: closedPRCount || 0, | ||
| mergedPRs: mergedPRCount || 0, | ||
| repoCount: Object.keys(repoMap).length, | ||
| profileName: profile.name || profile.login || username, | ||
| profileName: profile?.name || profile?.login || username, |
Comment on lines
80
to
86
| data = { | ||
| totalStars, | ||
| totalCommits: contributionData.totalContributions || 0, | ||
| totalPRs: prs.length, | ||
| totalIssues, | ||
| contributedTo: reposContributed.size || profile.public_repos || 0, | ||
| totalStars: totalStars || 0, | ||
| totalCommits: contributionData?.totalContributions || 0, | ||
| totalPRs: prs?.length || 0, | ||
| totalIssues: totalIssues || 0, | ||
| contributedTo: reposContributed.size || profile?.public_repos || 0, | ||
| linesChanged, |
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.