diff --git a/api/index.js b/api/index.js index 67619f4..a3d9f2a 100644 --- a/api/index.js +++ b/api/index.js @@ -37,6 +37,7 @@ export default async (req, res) => { number_format, border_color, rank_icon, + show_total_reviews, } = req.query; res.setHeader("Content-Type", "image/svg+xml"); @@ -95,6 +96,7 @@ export default async (req, res) => { locale: locale ? locale.toLowerCase() : null, disable_animations: parseBoolean(disable_animations), rank_icon, + show_total_reviews: parseBoolean(show_total_reviews), }), ); } catch (err) { diff --git a/readme.md b/readme.md index 2bc0863..4e4de58 100644 --- a/readme.md +++ b/readme.md @@ -306,6 +306,7 @@ You can provide multiple comma-separated values in the bg_color option to render - `disable_animations` - Disables all animations in the card _(boolean)_. Default: `false`. - `ring_color` - Color of the rank circle _(hex color)_. Defaults to the theme ring color if it exists and otherwise the title color. - `number_format` - Switch between two available formats for displaying the card values `short` (i.e. `6.6k`) and `long` (i.e. `6626`). Default: `short`. +- `show_total_reviews` - Show total PR reviews _(boolean)_. Default: `false`. > **Note** > When hide_rank=`true`, the minimum card width is 270 px + the title length and padding. diff --git a/src/cards/stats-card.js b/src/cards/stats-card.js index c483cdd..30f85f7 100644 --- a/src/cards/stats-card.js +++ b/src/cards/stats-card.js @@ -85,6 +85,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => { totalCommits, totalIssues, totalPRs, + totalReviews, contributedTo, rank, } = stats; @@ -111,6 +112,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => { locale, disable_animations = false, rank_icon = "default", + show_total_reviews = false, } = options; const lheight = parseInt(String(line_height), 10); @@ -136,40 +138,50 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => { }); // Meta data for creating text nodes with createTextNode function - const STATS = { - stars: { - icon: icons.star, - label: i18n.t("statcard.totalstars"), - value: totalStars, - id: "stars", - }, - commits: { - icon: icons.commits, - label: `${i18n.t("statcard.commits")}${ - include_all_commits ? "" : ` (${new Date().getFullYear()})` - }`, - value: totalCommits, - id: "commits", - }, - prs: { - icon: icons.prs, - label: i18n.t("statcard.prs"), - value: totalPRs, - id: "prs", - }, - issues: { - icon: icons.issues, - label: i18n.t("statcard.issues"), - value: totalIssues, - id: "issues", - }, - contribs: { - icon: icons.contribs, - label: i18n.t("statcard.contribs"), - value: contributedTo, - id: "contribs", - }, + const STATS = {}; + + STATS.stars = { + icon: icons.star, + label: i18n.t("statcard.totalstars"), + value: totalStars, + id: "stars", }; + STATS.commits = { + icon: icons.commits, + label: `${i18n.t("statcard.commits")}${ + include_all_commits ? "" : ` (${new Date().getFullYear()})` + }`, + value: totalCommits, + id: "commits", + }; + STATS.prs = { + icon: icons.prs, + label: i18n.t("statcard.prs"), + value: totalPRs, + id: "prs", + }; + STATS.issues = { + icon: icons.issues, + label: i18n.t("statcard.issues"), + value: totalIssues, + id: "issues", + }; + STATS.contribs = { + icon: icons.contribs, + label: i18n.t("statcard.contribs"), + value: contributedTo, + id: "contribs", + }; + + // Extra stats items. + if (show_total_reviews) { + STATS.reviews = { + icon: icons.reviews, + label: i18n.t("statcard.reviews"), + value: totalReviews, + id: "reviews", + }; + } const longLocales = [ "cn", diff --git a/src/cards/types.d.ts b/src/cards/types.d.ts index d6a1de0..cec7b7f 100644 --- a/src/cards/types.d.ts +++ b/src/cards/types.d.ts @@ -27,6 +27,7 @@ export type StatCardOptions = CommonOptions & { ring_color: string; text_bold: boolean; rank_icon: RankIcon; + show_total_reviews: boolean; }; export type RepoCardOptions = CommonOptions & { diff --git a/src/common/icons.js b/src/common/icons.js index 948ca0b..949ce65 100644 --- a/src/common/icons.js +++ b/src/common/icons.js @@ -6,6 +6,7 @@ const icons = { icon: ``, contribs: ``, fork: ``, + reviews: ``, }; /** diff --git a/src/fetchers/stats-fetcher.js b/src/fetchers/stats-fetcher.js index cebc38e..931f3e2 100644 --- a/src/fetchers/stats-fetcher.js +++ b/src/fetchers/stats-fetcher.js @@ -45,7 +45,8 @@ const GRAPHQL_STATS_QUERY = ` name login contributionsCollection { - totalCommitContributions + totalCommitContributions, + totalPullRequestReviewContributions } repositoriesContributedTo(first: 1, contributionTypes: [COMMIT, ISSUE, PULL_REQUEST, REPOSITORY]) { totalCount @@ -185,6 +186,7 @@ const fetchStats = async ( const stats = { name: "", totalPRs: 0, + totalReviews: 0, totalCommits: 0, totalIssues: 0, totalStars: 0, @@ -227,6 +229,8 @@ const fetchStats = async ( } stats.totalPRs = user.pullRequests.totalCount; + stats.totalReviews = + user.contributionsCollection.totalPullRequestReviewContributions; stats.totalIssues = user.openIssues.totalCount + user.closedIssues.totalCount; stats.contributedTo = user.repositoriesContributedTo.totalCount; diff --git a/src/fetchers/types.d.ts b/src/fetchers/types.d.ts index 3e7381a..a810c6c 100644 --- a/src/fetchers/types.d.ts +++ b/src/fetchers/types.d.ts @@ -18,6 +18,7 @@ export type RepositoryData = { export type StatsData = { name: string; totalPRs: number; + totalReviews: number; totalCommits: number; totalIssues: number; totalStars: number; diff --git a/src/translations.js b/src/translations.js index cea5059..fd36b48 100644 --- a/src/translations.js +++ b/src/translations.js @@ -196,6 +196,32 @@ const statCardLocales = ({ name, apostrophe }) => { vi: "Đã Đóng Góp (năm ngoái)", se: "Bidragit till (förra året)", }, + "statcard.reviews": { + ar: "Total PR reviews", + cn: "Total PR reviews", + cs: "Total PR reviews", + de: "Total PR reviews", + en: "Total PR reviews", + bn: "Total PR reviews", + es: "Total PR reviews", + fr: "Total PR reviews", + hu: "Total PR reviews", + it: "Total PR reviews", + ja: "Total PR reviews", + kr: "Total PR reviews", + nl: "Total PR reviews", + "pt-pt": "Total PR reviews", + "pt-br": "Total PR reviews", + np: "Total PR reviews", + el: "Total PR reviews", + ru: "Total PR reviews", + "uk-ua": "Total PR reviews", + id: "Total PR reviews", + my: "Total PR reviews", + sk: "Total PR reviews", + tr: "Total PR reviews", + pl: "Total PR reviews", + }, }; }; diff --git a/tests/fetchStats.test.js b/tests/fetchStats.test.js index f42b8fa..3b0f915 100644 --- a/tests/fetchStats.test.js +++ b/tests/fetchStats.test.js @@ -12,6 +12,7 @@ const data_stats = { repositoriesContributedTo: { totalCount: 61 }, contributionsCollection: { totalCommitContributions: 100, + totalPullRequestReviewContributions: 50, }, pullRequests: { totalCount: 300 }, openIssues: { totalCount: 100 }, @@ -116,6 +117,7 @@ describe("Test fetchStats", () => { totalCommits: 100, totalIssues: 200, totalPRs: 300, + totalReviews: 50, totalStars: 300, rank, }); @@ -146,6 +148,7 @@ describe("Test fetchStats", () => { totalCommits: 100, totalIssues: 200, totalPRs: 300, + totalReviews: 50, totalStars: 300, rank, }); @@ -182,6 +185,7 @@ describe("Test fetchStats", () => { totalCommits: 1000, totalIssues: 200, totalPRs: 300, + totalReviews: 50, totalStars: 300, rank, }); @@ -209,6 +213,7 @@ describe("Test fetchStats", () => { totalCommits: 1000, totalIssues: 200, totalPRs: 300, + totalReviews: 50, totalStars: 200, rank, }); @@ -234,6 +239,7 @@ describe("Test fetchStats", () => { totalCommits: 100, totalIssues: 200, totalPRs: 300, + totalReviews: 50, totalStars: 400, rank, }); @@ -259,6 +265,7 @@ describe("Test fetchStats", () => { totalCommits: 100, totalIssues: 200, totalPRs: 300, + totalReviews: 50, totalStars: 300, rank, }); @@ -284,6 +291,7 @@ describe("Test fetchStats", () => { totalCommits: 100, totalIssues: 200, totalPRs: 300, + totalReviews: 50, totalStars: 300, rank, }); diff --git a/tests/renderStatsCard.test.js b/tests/renderStatsCard.test.js index 0dd5883..6b751d9 100644 --- a/tests/renderStatsCard.test.js +++ b/tests/renderStatsCard.test.js @@ -16,6 +16,7 @@ const stats = { totalCommits: 200, totalIssues: 300, totalPRs: 400, + totalReviews: 50, contributedTo: 500, rank: { level: "A+", score: 40 }, }; @@ -38,6 +39,9 @@ describe("Test renderStatsCard", () => { expect(getByTestId(document.body, "contribs").textContent).toBe("500"); expect(queryByTestId(document.body, "card-bg")).toBeInTheDocument(); expect(queryByTestId(document.body, "rank-circle")).toBeInTheDocument(); + + // Default hidden stats + expect(queryByTestId(document.body, "reviews")).not.toBeInTheDocument(); }); it("should have proper name apostrophe", () => { @@ -68,6 +72,24 @@ describe("Test renderStatsCard", () => { expect(queryByTestId(document.body, "issues")).toBeNull(); expect(queryByTestId(document.body, "prs")).toBeNull(); expect(queryByTestId(document.body, "contribs")).toBeNull(); + expect(queryByTestId(document.body, "reviews")).toBeNull(); + }); + + it("should show total reviews", () => { + document.body.innerHTML = renderStatsCard(stats, { + show_total_reviews: true, + }); + + expect( + document.body.getElementsByTagName("svg")[0].getAttribute("height"), + ).toBe("220"); + + expect(queryByTestId(document.body, "stars")).toBeDefined(); + expect(queryByTestId(document.body, "commits")).toBeDefined(); + expect(queryByTestId(document.body, "issues")).toBeDefined(); + expect(queryByTestId(document.body, "prs")).toBeDefined(); + expect(queryByTestId(document.body, "contribs")).toBeDefined(); + expect(queryByTestId(document.body, "reviews")).toBeDefined(); }); it("should hide_rank", () => {