-
-
-
+
+
+
+
+
+
+
+
+
+
+
+ {/* LEFT SIDEBAR */}
+
+
+
+
+ {/* MAIN CONTENT */}
+
+
+
+
+ {/* RIGHT SIDEBAR */}
+
+
+
+
-
-
-
-
-
-
-
);
diff --git a/src/app/[interval]/[[...date]]/queries.ts b/src/app/[interval]/[[...date]]/queries.ts
index 58e1d2bc..ac7a47f5 100644
--- a/src/app/[interval]/[[...date]]/queries.ts
+++ b/src/app/[interval]/[[...date]]/queries.ts
@@ -180,6 +180,7 @@ export async function getMetricsForInterval(
codeChanges: repoMetrics.codeChanges,
topContributors: repoMetrics.topContributors,
focusAreas: repoMetrics.focusAreas,
+ topFilesChanged: repoMetrics.topFilesChanged,
topIssues,
topPullRequests,
detailedContributorSummaries, // Add the new field here
diff --git a/src/lib/pipelines/export/queries.ts b/src/lib/pipelines/export/queries.ts
index 478d1931..38199fc1 100644
--- a/src/lib/pipelines/export/queries.ts
+++ b/src/lib/pipelines/export/queries.ts
@@ -283,6 +283,18 @@ export async function getProjectMetrics(params: QueryParams = {}) {
.sort((a, b) => b.count - a.count)
.slice(0, 10);
+ // Get top files changed (by total changes: additions + deletions)
+ const topFilesChanged = prFiles
+ .map((file) => ({
+ path: file.path,
+ additions: file.additions || 0,
+ deletions: file.deletions || 0,
+ totalChanges: (file.additions || 0) + (file.deletions || 0),
+ }))
+ .filter((file) => file.totalChanges > 0)
+ .sort((a, b) => b.totalChanges - a.totalChanges)
+ .slice(0, 10);
+
// Get completed items (PRs merged in this period)
const completedItems = mergedPRsThisPeriod.map((pr) => ({
title: pr.title,
@@ -299,6 +311,7 @@ export async function getProjectMetrics(params: QueryParams = {}) {
topContributors,
codeChanges,
focusAreas,
+ topFilesChanged,
completedItems,
};
}
From 217ce3d098db4cf764515f0e1574e9a83f2cc040 Mon Sep 17 00:00:00 2001
From: madjin <32600939+madjin@users.noreply.github.com>
Date: Sun, 8 Jun 2025 00:31:25 -0400
Subject: [PATCH 2/4] update daily summary page
---
.../[[...date]]/components/LeftSidebar.tsx | 397 ++++++++++--------
.../[[...date]]/components/MainContent.tsx | 2 +
.../[[...date]]/components/RightSidebar.tsx | 58 +--
.../components/SummaryContent.skeleton.tsx | 2 +-
.../[[...date]]/components/SummaryContent.tsx | 2 +-
src/app/[interval]/[[...date]]/page.tsx | 19 +-
6 files changed, 278 insertions(+), 202 deletions(-)
diff --git a/src/app/[interval]/[[...date]]/components/LeftSidebar.tsx b/src/app/[interval]/[[...date]]/components/LeftSidebar.tsx
index c1157866..157c6072 100644
--- a/src/app/[interval]/[[...date]]/components/LeftSidebar.tsx
+++ b/src/app/[interval]/[[...date]]/components/LeftSidebar.tsx
@@ -1,9 +1,23 @@
+"use client";
+
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Badge } from "@/components/ui/badge";
+import { ScrollArea } from "@/components/ui/scroll-area";
+import {
+ Dialog,
+ DialogContent,
+ DialogHeader,
+ DialogTitle,
+ DialogTrigger,
+} from "@/components/ui/dialog";
import type { IntervalMetrics } from "@/app/[interval]/[[...date]]/queries";
import { Users, Star, TrendingUp } from "lucide-react";
import Link from "next/link";
+import PullRequestsListModalContent from "./PullRequestsListModalContent";
+import IssuesListModalContent from "./IssuesListModalContent";
+import ContributorsListModalContent from "./ContributorsListModalContent";
+import { formatTimeframeTitle } from "@/lib/date-utils";
interface LeftSidebarProps {
metrics: IntervalMetrics;
@@ -15,190 +29,237 @@ interface Contributor {
}
export function LeftSidebar({ metrics }: LeftSidebarProps) {
+ const timeframeTitle = formatTimeframeTitle(
+ metrics.interval.intervalStart,
+ metrics.interval.intervalType,
+ );
+
return (
<>
{/* Top Contributors Card */}
-
-
-
-
- Top Contributors
-
-
-
-
- {metrics.topContributors
- .slice(0, 5)
- .map((contributor: Contributor, index) => (
-
-
-
-
-
- {contributor.username[0].toUpperCase()}
-
-
-
-
- {contributor.username}
-
-
-
-
- {contributor.totalScore.toFixed(1)} pts
-
+
-
-
+
+
+
+
+
+ Contributors
+
+
+
+
{/* Pull Requests Card */}
-
-
-
-
- Recent Pull Requests
-
- {metrics.pullRequests.total}
-
-
-
-
-
- {metrics.topPullRequests.slice(0, 10).map((pr, index) => (
-
-
-
+
-
- ))}
- {metrics.topPullRequests.length > 10 && (
-
- +{metrics.topPullRequests.length - 10} more pull requests
-
- )}
-
-
-
+
+
+
+
+
+
+ Pull Requests
+
+
+
+
{/* Issues Card */}
-
-
-
-
- Recent Issues
-
- {metrics.issues.total}
-
-
-
-
-
- {metrics.topIssues.slice(0, 10).map((issue, index) => (
-
-
-
+
-
- ))}
- {metrics.topIssues.length > 10 && (
-
- +{metrics.topIssues.length - 10} more issues
-
- )}
-
-
-
+
+
+
+
+
+
+ Issues
+
+
+
+
>
);
}
diff --git a/src/app/[interval]/[[...date]]/components/MainContent.tsx b/src/app/[interval]/[[...date]]/components/MainContent.tsx
index 6d7cddf8..9283f9fb 100644
--- a/src/app/[interval]/[[...date]]/components/MainContent.tsx
+++ b/src/app/[interval]/[[...date]]/components/MainContent.tsx
@@ -1,3 +1,5 @@
+"use client";
+
import { StatCard } from "@/components/stat-card";
import { CounterWithIcon } from "@/components/counter-with-icon";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
diff --git a/src/app/[interval]/[[...date]]/components/RightSidebar.tsx b/src/app/[interval]/[[...date]]/components/RightSidebar.tsx
index 0956eb0c..61bf370b 100644
--- a/src/app/[interval]/[[...date]]/components/RightSidebar.tsx
+++ b/src/app/[interval]/[[...date]]/components/RightSidebar.tsx
@@ -1,5 +1,7 @@
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
+import { ScrollArea } from "@/components/ui/scroll-area";
+import { Progress } from "@/components/ui/progress";
import type { IntervalMetrics } from "@/app/[interval]/[[...date]]/queries";
import {
GitCommitVertical,
@@ -40,12 +42,14 @@ export function RightSidebar({ metrics }: RightSidebarProps) {
{codeChanges.commitCount} commits
-
+
@@ -87,31 +91,33 @@ export function RightSidebar({ metrics }: RightSidebarProps) {
- {/* Top Files Changed - Compact */}
+ {/* Top Files Changed - Scrollable */}
{metrics.topFilesChanged && metrics.topFilesChanged.length > 0 && (
-
- {metrics.topFilesChanged.slice(0, 6).map((file, index) => (
-
-
+
+ {metrics.topFilesChanged.slice(0, 15).map((file, index) => (
+
- {file.path.split("/").pop() || file.path}
-
-
-
- +{file.additions}
-
-
- -{file.deletions}
+
+ {file.path.split("/").pop() || file.path}
+
+
+ +{file.additions}
+
+
+ -{file.deletions}
+
+
-
- ))}
-
+ ))}
+
+
)}
diff --git a/src/app/[interval]/[[...date]]/components/SummaryContent.skeleton.tsx b/src/app/[interval]/[[...date]]/components/SummaryContent.skeleton.tsx
index 85d79695..9b421697 100644
--- a/src/app/[interval]/[[...date]]/components/SummaryContent.skeleton.tsx
+++ b/src/app/[interval]/[[...date]]/components/SummaryContent.skeleton.tsx
@@ -5,7 +5,7 @@ export function SummaryContentSkeleton({ className }: { className?: string }) {
return (
diff --git a/src/app/[interval]/[[...date]]/components/SummaryContent.tsx b/src/app/[interval]/[[...date]]/components/SummaryContent.tsx
index 97cc21f3..3673ecc2 100644
--- a/src/app/[interval]/[[...date]]/components/SummaryContent.tsx
+++ b/src/app/[interval]/[[...date]]/components/SummaryContent.tsx
@@ -48,7 +48,7 @@ export function SummaryContent({
return (
diff --git a/src/app/[interval]/[[...date]]/page.tsx b/src/app/[interval]/[[...date]]/page.tsx
index 48872dd9..34ab14f6 100644
--- a/src/app/[interval]/[[...date]]/page.tsx
+++ b/src/app/[interval]/[[...date]]/page.tsx
@@ -125,9 +125,9 @@ export default async function IntervalSummaryPage({ params }: PageProps) {
return (
-
+
-
+
-
+
{/* LEFT SIDEBAR */}
-
+
{/* MAIN CONTENT */}
-
+
- {/* RIGHT SIDEBAR */}
+ {/* RIGHT SIDEBAR - Hidden on md, shown on lg+ */}
+
+
+
+
+
+ {/* RIGHT SIDEBAR CONTENT FOR TABLET (md) - Shown below main content */}
+
From b997c55453a913ec13511d2199ef09610941c596 Mon Sep 17 00:00:00 2001
From: madjin <32600939+madjin@users.noreply.github.com>
Date: Sun, 8 Jun 2025 00:59:29 -0400
Subject: [PATCH 3/4] update interval page
---
.../components/IssuesListModalContent.tsx | 1 +
.../[[...date]]/components/LeftSidebar.tsx | 279 +++++++++---------
.../[[...date]]/components/MainContent.tsx | 2 -
.../PullRequestsListModalContent.tsx | 1 +
src/components/activity-item.tsx | 11 +-
5 files changed, 159 insertions(+), 135 deletions(-)
diff --git a/src/app/[interval]/[[...date]]/components/IssuesListModalContent.tsx b/src/app/[interval]/[[...date]]/components/IssuesListModalContent.tsx
index 0b448a35..937a851a 100644
--- a/src/app/[interval]/[[...date]]/components/IssuesListModalContent.tsx
+++ b/src/app/[interval]/[[...date]]/components/IssuesListModalContent.tsx
@@ -22,6 +22,7 @@ export default function IssuesListModalContent({
author={issue.author}
number={issue.number}
href={`https://github.com/${issue.repository}/issues/${issue.number}`}
+ allowTitleWrap={true}
icon={
issue.state === "closed" || issue.closedAt ? (
diff --git a/src/app/[interval]/[[...date]]/components/LeftSidebar.tsx b/src/app/[interval]/[[...date]]/components/LeftSidebar.tsx
index 157c6072..5c3c4f7d 100644
--- a/src/app/[interval]/[[...date]]/components/LeftSidebar.tsx
+++ b/src/app/[interval]/[[...date]]/components/LeftSidebar.tsx
@@ -12,7 +12,15 @@ import {
DialogTrigger,
} from "@/components/ui/dialog";
import type { IntervalMetrics } from "@/app/[interval]/[[...date]]/queries";
-import { Users, Star, TrendingUp } from "lucide-react";
+import {
+ Users,
+ Star,
+ TrendingUp,
+ CircleDot,
+ GitMerge,
+ CheckCircle,
+} from "lucide-react";
+import { CounterWithIcon } from "@/components/counter-with-icon";
import Link from "next/link";
import PullRequestsListModalContent from "./PullRequestsListModalContent";
import IssuesListModalContent from "./IssuesListModalContent";
@@ -26,6 +34,7 @@ interface LeftSidebarProps {
interface Contributor {
username: string;
totalScore: number;
+ summary?: string | null;
}
export function LeftSidebar({ metrics }: LeftSidebarProps) {
@@ -43,56 +52,68 @@ export function LeftSidebar({ metrics }: LeftSidebarProps) {
- Top Contributors
+ Contributors ({metrics.activeContributors})
-
-
- {metrics.topContributors
- .slice(0, 5)
- .map((contributor: Contributor, index) => (
-
e.stopPropagation()}
- >
-
-
-
-
- {contributor.username[0].toUpperCase()}
-
-
-
-
- {contributor.username}
-
-
-
-
- {contributor.totalScore.toFixed(1)} pts
-
+
+
+
+ {metrics.topContributors
+ .slice(0, 10)
+ .map((contributor: Contributor, index) => (
+
e.stopPropagation()}
+ >
+
+
+
+
+ {contributor.username[0].toUpperCase()}
+
+
+
+
+
+ {contributor.username}
+
+
+ #{index + 1}
+
+
+
+
+
+ {contributor.totalScore.toFixed(1)} pts
+
+
+ {contributor.summary && (
+
+ {contributor.summary.replace(
+ `${contributor.username}: `,
+ "",
+ )}
+
+ )}
-
-
- #{index + 1}
-
-
- ))}
- {metrics.topContributors.length > 5 && (
-
- +{metrics.topContributors.length - 5} more contributors
-
- )}
-
+
+ ))}
+ {metrics.topContributors.length > 10 && (
+
+ +{metrics.topContributors.length - 10} more contributors
+
+ )}
+
+
@@ -111,28 +132,41 @@ export function LeftSidebar({ metrics }: LeftSidebarProps) {
-
-
- Recent Pull Requests
-
- {metrics.pullRequests.total}
-
+
+
+
+ Pull Requests ({metrics.pullRequests.new})
+
+
+
+
+
+ {metrics.pullRequests.new}
+
+
+
+
+
+ {metrics.pullRequests.merged}
+
+
+
@@ -141,28 +175,14 @@ export function LeftSidebar({ metrics }: LeftSidebarProps) {
{metrics.topPullRequests.slice(0, 10).map((pr, index) => (
-
-
-
-
- #{pr.number} {pr.title}
-
-
-
- by {pr.author}
-
-
- {pr.mergedAt ? "merged" : "open"}
-
-
-
-
+
+
+ #{pr.number} {pr.title}
+
))}
{metrics.topPullRequests.length > 10 && (
@@ -190,27 +210,36 @@ export function LeftSidebar({ metrics }: LeftSidebarProps) {
-
-
- Recent Issues
-
- {metrics.issues.total}
-
+
+
+
+ Issues ({metrics.issues.new})
+
+
+
+
+ {metrics.issues.new}
+
+
+
+ {metrics.issues.closed}
+
+
@@ -219,28 +248,14 @@ export function LeftSidebar({ metrics }: LeftSidebarProps) {
{metrics.topIssues.slice(0, 10).map((issue, index) => (
-
-
-
-
- #{issue.number} {issue.title}
-
-
-
- by {issue.author}
-
-
- {issue.state}
-
-
-
-
+
+
+ #{issue.number} {issue.title}
+
))}
{metrics.topIssues.length > 10 && (
diff --git a/src/app/[interval]/[[...date]]/components/MainContent.tsx b/src/app/[interval]/[[...date]]/components/MainContent.tsx
index 9283f9fb..6d7cddf8 100644
--- a/src/app/[interval]/[[...date]]/components/MainContent.tsx
+++ b/src/app/[interval]/[[...date]]/components/MainContent.tsx
@@ -1,5 +1,3 @@
-"use client";
-
import { StatCard } from "@/components/stat-card";
import { CounterWithIcon } from "@/components/counter-with-icon";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
diff --git a/src/app/[interval]/[[...date]]/components/PullRequestsListModalContent.tsx b/src/app/[interval]/[[...date]]/components/PullRequestsListModalContent.tsx
index 9f3902b8..76dd51e4 100644
--- a/src/app/[interval]/[[...date]]/components/PullRequestsListModalContent.tsx
+++ b/src/app/[interval]/[[...date]]/components/PullRequestsListModalContent.tsx
@@ -22,6 +22,7 @@ export default function PullRequestsListModalContent({
className="px-4"
number={pr.number}
href={`https://github.com/${pr.repository}/pull/${pr.number}`}
+ allowTitleWrap={true}
icon={
pr.mergedAt ? (
diff --git a/src/components/activity-item.tsx b/src/components/activity-item.tsx
index 846b0788..1d9d1ca0 100644
--- a/src/components/activity-item.tsx
+++ b/src/components/activity-item.tsx
@@ -12,6 +12,7 @@ interface ActivityItemProps {
icon: React.ReactNode;
metadata?: React.ReactNode;
className?: string;
+ allowTitleWrap?: boolean;
}
export function ActivityItem({
@@ -23,6 +24,7 @@ export function ActivityItem({
icon,
metadata,
className,
+ allowTitleWrap = false,
}: ActivityItemProps) {
return (
-
{title}
+
+ {title}
+
From 3fbe77d922d6f7722642867baac0548b0dcad0c7 Mon Sep 17 00:00:00 2001
From: madjin <32600939+madjin@users.noreply.github.com>
Date: Sun, 8 Jun 2025 16:45:34 -0400
Subject: [PATCH 4/4] fix sidebars
---
.../[[...date]]/components/LeftSidebar.tsx | 4 +-
.../[[...date]]/components/RightSidebar.tsx | 164 +++++++++---------
src/lib/pipelines/export/queries.ts | 5 +-
3 files changed, 82 insertions(+), 91 deletions(-)
diff --git a/src/app/[interval]/[[...date]]/components/LeftSidebar.tsx b/src/app/[interval]/[[...date]]/components/LeftSidebar.tsx
index 5c3c4f7d..745dd781 100644
--- a/src/app/[interval]/[[...date]]/components/LeftSidebar.tsx
+++ b/src/app/[interval]/[[...date]]/components/LeftSidebar.tsx
@@ -170,7 +170,7 @@ export function LeftSidebar({ metrics }: LeftSidebarProps) {
-
+
{metrics.topPullRequests.slice(0, 10).map((pr, index) => (
-
+
{metrics.topIssues.slice(0, 10).map((issue, index) => (
- {/* Code Stats */}
-
-
-
-
-
- +{codeChanges.additions.toLocaleString()}
+
-
-
-
-
- -{codeChanges.deletions.toLocaleString()}
-
-
Deleted
-
-
-
-
-
-
-
- {codeChanges.files} files changed
-
-
-
- {/* Top Files Changed - Scrollable */}
- {metrics.topFilesChanged && metrics.topFilesChanged.length > 0 && (
-
-
- {metrics.topFilesChanged.slice(0, 15).map((file, index) => (
-
-
- {file.path.split("/").pop() || file.path}
-
-
-
- +{file.additions}
-
-
- -{file.deletions}
-
-
+
+
+
+
+ Files Changed ({metrics.topFilesChanged?.length || 0} of{" "}
+ {codeChanges.files})
+
+
+ Sorted by most changes (additions + deletions)
+
+
+ {metrics.topFilesChanged && metrics.topFilesChanged.length > 0 ? (
+
+
+ {metrics.topFilesChanged.map((file, index) => (
+
+
+ {file.path}
+
+
+
+ +{file.additions}
+
+
+ -{file.deletions}
+
+
+
+ ))}
- ))}
-
-
- )}
+
+ ) : (
+
+ No file changes to display.
+
+ )}
+
+
@@ -132,27 +127,24 @@ export function RightSidebar({ metrics }: RightSidebarProps) {
-
- {focusAreas.slice(0, 8).map((focusArea, index) => (
-
-
-
-
- {focusArea.area}
-
-
-
- {focusArea.count}
-
-
+
+ {focusAreas.slice(0, 10).map((focusArea, index) => (
+
+ {focusArea.area}
+
))}
- {focusAreas.length > 8 && (
-
- +{focusAreas.length - 8} more areas
-
+ {focusAreas.length > 10 && (
+
+ +{focusAreas.length - 10} more
+
)}
diff --git a/src/lib/pipelines/export/queries.ts b/src/lib/pipelines/export/queries.ts
index 38199fc1..4701300a 100644
--- a/src/lib/pipelines/export/queries.ts
+++ b/src/lib/pipelines/export/queries.ts
@@ -283,7 +283,7 @@ export async function getProjectMetrics(params: QueryParams = {}) {
.sort((a, b) => b.count - a.count)
.slice(0, 10);
- // Get top files changed (by total changes: additions + deletions)
+ // Get all files changed (sorted by total changes: additions + deletions)
const topFilesChanged = prFiles
.map((file) => ({
path: file.path,
@@ -292,8 +292,7 @@ export async function getProjectMetrics(params: QueryParams = {}) {
totalChanges: (file.additions || 0) + (file.deletions || 0),
}))
.filter((file) => file.totalChanges > 0)
- .sort((a, b) => b.totalChanges - a.totalChanges)
- .slice(0, 10);
+ .sort((a, b) => b.totalChanges - a.totalChanges);
// Get completed items (PRs merged in this period)
const completedItems = mergedPRsThisPeriod.map((pr) => ({