From c753c001bcf47916fc7d2d1569853d86413d79d4 Mon Sep 17 00:00:00 2001 From: vedika76 Date: Mon, 18 May 2026 15:23:10 +0530 Subject: [PATCH] feat(issues): add mostActiveRepo, assigned issues, and caching to Issue Metrics widget --- package-lock.json | 13 ------------- src/app/api/metrics/issues/route.ts | 1 + src/components/IssueMetrics.tsx | 10 ++++++---- src/lib/github.ts | 15 ++++++++++++++- 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/package-lock.json b/package-lock.json index 467c781..df0ab10 100644 --- a/package-lock.json +++ b/package-lock.json @@ -746,7 +746,6 @@ "integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.2.2" @@ -1185,7 +1184,6 @@ "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1638,7 +1636,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", @@ -2508,7 +2505,6 @@ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -2677,7 +2673,6 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -4118,7 +4113,6 @@ "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", "dev": true, "license": "MIT", - "peer": true, "bin": { "jiti": "bin/jiti.js" } @@ -4190,7 +4184,6 @@ "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-4.2.1.tgz", "integrity": "sha512-YyAXyvnmjTbR4bHQRLzex3CuINCDlQnBqoSYyjJwTP2x9jDLuKDzy7aKUl0hgx3uhcl7xzg32agn5vlie6HIlQ==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.28.6", "fast-png": "^6.2.0", @@ -5033,7 +5026,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -5204,7 +5196,6 @@ "resolved": "https://registry.npmjs.org/preact/-/preact-10.29.1.tgz", "integrity": "sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg==", "license": "MIT", - "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/preact" @@ -5295,7 +5286,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -5308,7 +5298,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -6362,7 +6351,6 @@ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -6532,7 +6520,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/src/app/api/metrics/issues/route.ts b/src/app/api/metrics/issues/route.ts index 1f62383..a94b544 100644 --- a/src/app/api/metrics/issues/route.ts +++ b/src/app/api/metrics/issues/route.ts @@ -3,6 +3,7 @@ import { authOptions } from "@/lib/auth"; import { fetchIssuesMetrics } from "@/lib/github"; export const dynamic = "force-dynamic"; +export const revalidate=300; export async function GET() { const session = await getServerSession(authOptions); diff --git a/src/components/IssueMetrics.tsx b/src/components/IssueMetrics.tsx index 9b6d0f2..a06cb67 100644 --- a/src/components/IssueMetrics.tsx +++ b/src/components/IssueMetrics.tsx @@ -8,6 +8,7 @@ interface IssueData { currentlyOpen: number; avgCloseTimeDays: number; trend: number; + mostActiveRepo: string | null; } export default function IssueMetrics() { @@ -40,6 +41,7 @@ export default function IssueMetrics() { { label: "Issues Closed (30d)", value: metrics.closed }, { label: "Currently Open", value: metrics.currentlyOpen }, { label: "Avg Close Time", value: `${metrics.avgCloseTimeDays}d` }, + { label: "Most Active Repo", value: metrics.mostActiveRepo ?? "—" }, ] : []; @@ -59,8 +61,8 @@ export default function IssueMetrics() { Issue Analytics {loading ? ( -
- {[1, 2, 3, 4].map((i) => ( +
+ {[1, 2, 3, 4, 5].map((i) => (
) : ( -
+
{stats.map((stat, idx) => (
-
+
{stat.value}
diff --git a/src/lib/github.ts b/src/lib/github.ts index 707e796..b15cf83 100644 --- a/src/lib/github.ts +++ b/src/lib/github.ts @@ -45,6 +45,7 @@ export interface GitHubIssueItem { state: string; created_at: string; closed_at: string | null; + repository_url: string; } export interface IssuesMetrics { @@ -53,6 +54,7 @@ export interface IssuesMetrics { currentlyOpen: number; avgCloseTimeDays: number; trend: number; + mostActiveRepo: string | null; } export async function fetchIssuesMetrics( @@ -106,11 +108,22 @@ export async function fetchIssuesMetrics( const thisMonthCount = thisMonthRes.ok ? ((await thisMonthRes.json()) as { total_count: number }).total_count : 0; const lastMonthCount = lastMonthRes.ok ? ((await lastMonthRes.json()) as { total_count: number }).total_count : 0; + const repoCounts: Record = {}; + for (const item of items) { + const repo = item.repository_url.split("/").pop() ?? ""; + repoCounts[repo] = (repoCounts[repo] ?? 0) + 1; + } + const mostActiveRepo = + Object.keys(repoCounts).length > 0 + ? Object.entries(repoCounts).sort((a, b) => b[1] - a[1])[0][0] + : null; + return { opened, closed, currentlyOpen, avgCloseTimeDays, trend: thisMonthCount - lastMonthCount, + mostActiveRepo, }; -} +} \ No newline at end of file