diff --git a/readme.md b/readme.md
index 2760b191c38c3..d993558a76cc1 100644
--- a/readme.md
+++ b/readme.md
@@ -156,10 +156,10 @@ You can pass a query parameter `&hide=` to hide any specific stats with comma-se
You can pass a query parameter `&show=` to show any specific additional stats with comma-separated values.
-> Options: `&show=reviews,discussions_started,discussions_answered`
+> Options: `&show=reviews,discussions_started,discussions_answered,prs_merged,prs_merged_percentage`
```md
-![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&show=reviews)
+![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra&show=reviews,discussions_started,discussions_answered,prs_merged,prs_merged_percentage)
```
### Showing icons
@@ -548,7 +548,7 @@ Change the `?username=` value to your [Wakatime](https://wakatime.com) username.
* Showing additional stats
-![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra\&show=reviews,discussions_started,discussions_answered)
+![Anurag's GitHub stats](https://github-readme-stats.vercel.app/api?username=anuraghazra\&show=reviews,discussions_started,discussions_answered,prs_merged,prs_merged_percentage)
* Showing icons
diff --git a/src/cards/stats-card.js b/src/cards/stats-card.js
index 7c5d43740c919..778e67647f342 100644
--- a/src/cards/stats-card.js
+++ b/src/cards/stats-card.js
@@ -28,6 +28,7 @@ const RANK_ONLY_CARD_DEFAULT_WIDTH = 290;
* @param {string} createTextNodeParams.label The label to display.
* @param {number} createTextNodeParams.value The value to display.
* @param {string} createTextNodeParams.id The id of the stat.
+ * @param {string=} createTextNodeParams.unitSymbol The unit symbol of the stat.
* @param {number} createTextNodeParams.index The index of the stat.
* @param {boolean} createTextNodeParams.showIcons Whether to show icons.
* @param {number} createTextNodeParams.shiftValuePos Number of pixels the value has to be shifted to the right.
@@ -40,6 +41,7 @@ const createTextNode = ({
label,
value,
id,
+ unitSymbol,
index,
showIcons,
shiftValuePos,
@@ -69,7 +71,7 @@ const createTextNode = ({
x="${(showIcons ? 140 : 120) + shiftValuePos}"
y="12.5"
data-testid="${id}"
- >${kValue}
+ >${kValue}${unitSymbol ? ` ${unitSymbol}` : ""}
`;
};
@@ -93,6 +95,8 @@ const renderStatsCard = (stats, options = {}) => {
totalCommits,
totalIssues,
totalPRs,
+ totalPRsMerged,
+ mergedPRsPercentage,
totalReviews,
totalDiscussionsStarted,
totalDiscussionsAnswered,
@@ -171,6 +175,25 @@ const renderStatsCard = (stats, options = {}) => {
id: "prs",
};
+ if (show.includes("prs_merged")) {
+ STATS.prs_merged = {
+ icon: icons.prs_merged,
+ label: i18n.t("statcard.prs-merged"),
+ value: totalPRsMerged,
+ id: "prs_merged",
+ };
+ }
+
+ if (show.includes("prs_merged_percentage")) {
+ STATS.prs_merged_percentage = {
+ icon: icons.prs_merged_percentage,
+ label: i18n.t("statcard.prs-merged-percentage"),
+ value: mergedPRsPercentage.toFixed(2),
+ id: "prs_merged_percentage",
+ unitSymbol: "%",
+ };
+ }
+
if (show.includes("reviews")) {
STATS.reviews = {
icon: icons.reviews,
@@ -235,7 +258,11 @@ const renderStatsCard = (stats, options = {}) => {
.map((key, index) =>
// create the text nodes, and pass index so that we can calculate the line spacing
createTextNode({
- ...STATS[key],
+ icon: STATS[key].icon,
+ label: STATS[key].label,
+ value: STATS[key].value,
+ id: STATS[key].id,
+ unitSymbol: STATS[key].unitSymbol,
index,
showIcons: show_icons,
shiftValuePos: 79.01 + (isLongLocale ? 50 : 0),
diff --git a/src/common/icons.js b/src/common/icons.js
index 3f91d86658c93..d600c14f64af7 100644
--- a/src/common/icons.js
+++ b/src/common/icons.js
@@ -2,6 +2,8 @@ const icons = {
star: ``,
commits: ``,
prs: ``,
+ prs_merged: ``,
+ prs_merged_percentage: ``,
issues: ``,
icon: ``,
contribs: ``,
diff --git a/src/fetchers/stats-fetcher.js b/src/fetchers/stats-fetcher.js
index a1e282187a756..6cffdfdca680d 100644
--- a/src/fetchers/stats-fetcher.js
+++ b/src/fetchers/stats-fetcher.js
@@ -54,6 +54,9 @@ const GRAPHQL_STATS_QUERY = `
pullRequests(first: 1) {
totalCount
}
+ mergedPullRequests: pullRequests(states: MERGED) {
+ totalCount
+ }
openIssues: issues(states: OPEN) {
totalCount
}
@@ -201,6 +204,8 @@ const fetchStats = async (
const stats = {
name: "",
totalPRs: 0,
+ totalPRsMerged: 0,
+ mergedPRsPercentage: 0,
totalReviews: 0,
totalCommits: 0,
totalIssues: 0,
@@ -246,6 +251,9 @@ const fetchStats = async (
}
stats.totalPRs = user.pullRequests.totalCount;
+ stats.totalPRsMerged = user.mergedPullRequests.totalCount;
+ stats.mergedPRsPercentage =
+ (user.mergedPullRequests.totalCount / user.pullRequests.totalCount) * 100;
stats.totalReviews =
user.contributionsCollection.totalPullRequestReviewContributions;
stats.totalIssues = user.openIssues.totalCount + user.closedIssues.totalCount;
diff --git a/src/fetchers/types.d.ts b/src/fetchers/types.d.ts
index 3a86205834c12..b0cc2f4c33b05 100644
--- a/src/fetchers/types.d.ts
+++ b/src/fetchers/types.d.ts
@@ -18,6 +18,8 @@ export type RepositoryData = {
export type StatsData = {
name: string;
totalPRs: number;
+ totalPRsMerged: number;
+ mergedPRsPercentage: number;
totalReviews: number;
totalCommits: number;
totalIssues: number;
diff --git a/src/translations.js b/src/translations.js
index b39f17b3916ae..1ced5f69263fd 100644
--- a/src/translations.js
+++ b/src/translations.js
@@ -325,6 +325,66 @@ const statCardLocales = ({ name, apostrophe }) => {
vi: "Tổng Số Thảo Luận Đã Trả Lời",
se: "Totalt antal diskussioner besvarade",
},
+ "statcard.prs-merged": {
+ ar: "مجموع الطلبات المدمجة",
+ cn: "合并的 PR 总数",
+ "zh-tw": "合併的 PR 總數",
+ cs: "Celkem sloučených PR",
+ de: "Insgesamt zusammengeführte PRs",
+ en: "Total PRs Merged",
+ bn: "সর্বমোট PR একত্রীকৃত",
+ es: "PR totales fusionados",
+ fr: "Nombre total de PR fusionnés",
+ hu: "Összes egyesített PR",
+ it: "PR totali uniti",
+ ja: "マージされた PR の総数",
+ kr: "병합된 총 PR",
+ nl: "Totaal samengevoegde PR's",
+ "pt-pt": "Total de PRs Fundidos",
+ "pt-br": "Total de PRs Fundidos",
+ np: "कुल PRs मर्ज गरिएको",
+ el: "Σύνολο Συγχωνευμένων PR",
+ ru: "Всего объединённых pull request`ов",
+ "uk-ua": "Всього об'єднаних pull request`iв",
+ id: "Total PR Digabungkan",
+ my: "Jumlah PR Digabungkan",
+ sk: "Celkový počet zlúčených PR",
+ tr: "Toplam Birleştirilmiş PR",
+ pl: "Łącznie połączonych PR",
+ uz: "Birlangan PR-lar soni",
+ vi: "Tổng Số PR Đã Hợp Nhất",
+ se: "Totalt antal sammanfogade PR",
+ },
+ "statcard.prs-merged-percentage": {
+ ar: "نسبة الطلبات المدمجة",
+ cn: "合并的 PR 百分比",
+ "zh-tw": "合併的 PR 百分比",
+ cs: "Sloučené PRs v procentech",
+ de: "Zusammengeführte PRs in Prozent",
+ en: "Merged PRs Percentage",
+ bn: "PR একত্রীকরণের শতাংশ",
+ es: "Porcentaje de PR fusionados",
+ fr: "Pourcentage de PR fusionnés",
+ hu: "Egyesített PR-k százaléka",
+ it: "Percentuale di PR uniti",
+ ja: "マージされた PR の割合",
+ kr: "병합된 PR의 비율",
+ nl: "Percentage samengevoegde PR's",
+ "pt-pt": "Percentagem de PRs Fundidos",
+ "pt-br": "Porcentagem de PRs Fundidos",
+ np: "PR मर्ज गरिएको प्रतिशत",
+ el: "Ποσοστό Συγχωνευμένων PR",
+ ru: "Процент объединённых pull request`ов",
+ "uk-ua": "Відсоток об'єднаних pull request`iв",
+ id: "Persentase PR Digabungkan",
+ my: "Peratus PR Digabungkan",
+ sk: "Percento zlúčených PR",
+ tr: "Birleştirilmiş PR Yüzdesi",
+ pl: "Procent połączonych PR",
+ uz: "Birlangan PR-lar foizi",
+ vi: "Tỷ Lệ PR Đã Hợp Nhất",
+ se: "Procent av sammanfogade PR",
+ },
};
};
diff --git a/tests/api.test.js b/tests/api.test.js
index 3c72583cb47a0..567d2c12fd7de 100644
--- a/tests/api.test.js
+++ b/tests/api.test.js
@@ -13,6 +13,8 @@ const stats = {
totalCommits: 200,
totalIssues: 300,
totalPRs: 400,
+ totalPRsMerged: 320,
+ mergedPRsPercentage: 80,
totalReviews: 50,
totalDiscussionsStarted: 10,
totalDiscussionsAnswered: 40,
@@ -41,6 +43,7 @@ const data_stats = {
totalPullRequestReviewContributions: stats.totalReviews,
},
pullRequests: { totalCount: stats.totalPRs },
+ mergedPullRequests: { totalCount: stats.totalPRsMerged },
openIssues: { totalCount: stats.totalIssues },
closedIssues: { totalCount: 0 },
followers: { totalCount: 0 },
diff --git a/tests/fetchStats.test.js b/tests/fetchStats.test.js
index 80b19bfeecc3d..6db4ef48fa677 100644
--- a/tests/fetchStats.test.js
+++ b/tests/fetchStats.test.js
@@ -16,6 +16,7 @@ const data_stats = {
totalPullRequestReviewContributions: 50,
},
pullRequests: { totalCount: 300 },
+ mergedPullRequests: { totalCount: 240 },
openIssues: { totalCount: 100 },
closedIssues: { totalCount: 100 },
followers: { totalCount: 100 },
@@ -121,6 +122,8 @@ describe("Test fetchStats", () => {
totalCommits: 100,
totalIssues: 200,
totalPRs: 300,
+ totalPRsMerged: 240,
+ mergedPRsPercentage: 80,
totalReviews: 50,
totalStars: 300,
totalDiscussionsStarted: 10,
@@ -155,6 +158,8 @@ describe("Test fetchStats", () => {
totalCommits: 100,
totalIssues: 200,
totalPRs: 300,
+ totalPRsMerged: 240,
+ mergedPRsPercentage: 80,
totalReviews: 50,
totalStars: 300,
totalDiscussionsStarted: 10,
@@ -195,6 +200,8 @@ describe("Test fetchStats", () => {
totalCommits: 1000,
totalIssues: 200,
totalPRs: 300,
+ totalPRsMerged: 240,
+ mergedPRsPercentage: 80,
totalReviews: 50,
totalStars: 300,
totalDiscussionsStarted: 10,
@@ -226,6 +233,8 @@ describe("Test fetchStats", () => {
totalCommits: 1000,
totalIssues: 200,
totalPRs: 300,
+ totalPRsMerged: 240,
+ mergedPRsPercentage: 80,
totalReviews: 50,
totalStars: 200,
totalDiscussionsStarted: 10,
@@ -255,6 +264,8 @@ describe("Test fetchStats", () => {
totalCommits: 100,
totalIssues: 200,
totalPRs: 300,
+ totalPRsMerged: 240,
+ mergedPRsPercentage: 80,
totalReviews: 50,
totalStars: 400,
totalDiscussionsStarted: 10,
@@ -284,6 +295,8 @@ describe("Test fetchStats", () => {
totalCommits: 100,
totalIssues: 200,
totalPRs: 300,
+ totalPRsMerged: 240,
+ mergedPRsPercentage: 80,
totalReviews: 50,
totalStars: 300,
totalDiscussionsStarted: 10,
@@ -313,6 +326,8 @@ describe("Test fetchStats", () => {
totalCommits: 100,
totalIssues: 200,
totalPRs: 300,
+ totalPRsMerged: 240,
+ mergedPRsPercentage: 80,
totalReviews: 50,
totalStars: 300,
totalDiscussionsStarted: 10,
diff --git a/tests/renderStatsCard.test.js b/tests/renderStatsCard.test.js
index 174aa07310f7a..fbc02a93ca41a 100644
--- a/tests/renderStatsCard.test.js
+++ b/tests/renderStatsCard.test.js
@@ -18,6 +18,8 @@ const stats = {
totalCommits: 200,
totalIssues: 300,
totalPRs: 400,
+ totalPRsMerged: 320,
+ mergedPRsPercentage: 80,
totalReviews: 50,
totalDiscussionsStarted: 10,
totalDiscussionsAnswered: 50,
@@ -52,6 +54,10 @@ describe("Test renderStatsCard", () => {
expect(
queryByTestId(document.body, "discussions_answered"),
).not.toBeInTheDocument();
+ expect(queryByTestId(document.body, "prs_merged")).not.toBeInTheDocument();
+ expect(
+ queryByTestId(document.body, "prs_merged_percentage"),
+ ).not.toBeInTheDocument();
});
it("should have proper name apostrophe", () => {
@@ -85,16 +91,24 @@ describe("Test renderStatsCard", () => {
expect(queryByTestId(document.body, "reviews")).toBeNull();
expect(queryByTestId(document.body, "discussions_started")).toBeNull();
expect(queryByTestId(document.body, "discussions_answered")).toBeNull();
+ expect(queryByTestId(document.body, "prs_merged")).toBeNull();
+ expect(queryByTestId(document.body, "prs_merged_percentage")).toBeNull();
});
it("should show additional stats", () => {
document.body.innerHTML = renderStatsCard(stats, {
- show: ["reviews", "discussions_started", "discussions_answered"],
+ show: [
+ "reviews",
+ "discussions_started",
+ "discussions_answered",
+ "prs_merged",
+ "prs_merged_percentage",
+ ],
});
expect(
document.body.getElementsByTagName("svg")[0].getAttribute("height"),
- ).toBe("270");
+ ).toBe("320");
expect(queryByTestId(document.body, "stars")).toBeDefined();
expect(queryByTestId(document.body, "commits")).toBeDefined();
@@ -104,6 +118,8 @@ describe("Test renderStatsCard", () => {
expect(queryByTestId(document.body, "reviews")).toBeDefined();
expect(queryByTestId(document.body, "discussions_started")).toBeDefined();
expect(queryByTestId(document.body, "discussions_answered")).toBeDefined();
+ expect(queryByTestId(document.body, "prs_merged")).toBeDefined();
+ expect(queryByTestId(document.body, "prs_merged_percentage")).toBeDefined();
});
it("should hide_rank", () => {