Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions Frontend/src/components/TopContributorsRepos.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
Component to display the top contributors and top repositories.

This component is responsible only for rendering UI elements.
All data aggregation and processing logic is delegated to a helper
function to maintain separation of concenrs and improve reusability.

Parms:
events (Array<Object>): List of GitHub event objects passed from the parent component
*/

import { getTopContributorsAndRepos } from "../utils/getTopContributorsAndRepos";

const TOP_N = 5;

const TopContributorsRepos = ({ events = [] }) => {
/*
Retrieve pre-processes contributor and repository statistics
The helper function handles counting, sorting, and limiting results
*/
const { topContributors, topRepos } =
getTopContributorsAndRepos(events, TOP_N);

return (
<div style={{ display: "flex", gap: "30px" }}>
{/* Render list of top contributors by activity count */}
<div>
<h3>Top Contributors</h3>
<ul>
{topContributors.map((user) => (
<li key={user.name}>
{user.name} ({user.count})
</li>
))}
</ul>
</div>

{/* Render list of top repositories by activity count */}
<div>
<h3>Top Repositories</h3>
<ul>
{topRepos.map((repo) => (
<li key={repo.name}>
{repo.name} ({repo.count})
</li>
))}
</ul>
</div>
</div>
);
};

export default TopContributorsRepos;
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
Unit tests for the getTopContributorsAndRepos helper function

These tests focus exclusively on verifying the correctness of
counting and ranking logic for contributors and repositories.
UI rendering is intentionally excluded to keep tests isolated
and easy to maintain.
*/
import { getTopContributorsAndRepos } from "../../../utils/getTopContributorsAndRepos";

describe("getTopContributorsAndRepos", () => {
it("counts contributor activity and sorts correctly", () => {
const events = [
{ author: "alice", repo: "repo1" },
{ author: "bob", repo: "repo1" },
{ author: "alice", repo: "repo2" },
];

const { topContributors } =
getTopContributorsAndRepos(events, 5);

// alice should rank first since she appears twice
expect(topContributors).toEqual([
{ name: "alice", count: 2 },
{ name: "bob", count: 1 },
]);
});

it("counts repository activity and sorts correctly", () => {
const events = [
{ author: "alice", repo: "repo1" },
{ author: "bob", repo: "repo1" },
{ author: "charlie", repo: "repo2" },
];

const { topRepos } =
getTopContributorsAndRepos(events, 5);

// repo1 should rank higher since it appears more frequently
expect(topRepos).toEqual([
{ name: "repo1", count: 2 },
{ name: "repo2", count: 1 },
]);
});

it("handles empty input without crashing", () => {
const { topContributors, topRepos } =
getTopContributorsAndRepos([], 5);

expect(topContributors).toEqual([]);
expect(topRepos).toEqual([]);
});
});
35 changes: 33 additions & 2 deletions Frontend/src/features/home/routes/Home.jsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,39 @@
// Home dashboard page
// Shows org-level overview using existing components

import TopContributorsRepos from "../../../components/TopContributorsRepos";
import VolumeChart from "../../../components/charts/VolumeBased";

import testData from "../../../test_data.json";
import { transformVolumeData } from "../../../utils/TransformVolumeData";

export const Home = () => {
const volumeData = transformVolumeData(testData);

return (
<div>
<h1>OSS Dev Analytics - Home</h1>
<p>Welcome to the dashboard.</p>
<h1>Organization Overview</h1>

{/* Top contributors & repositories */}
<section
style={{
display: "flex",
gap: "20px",
marginBottom: "30px",
}}
>
<TopContributorsRepos events={testData.events || []} />
</section>

{/* Existing volume chart (already on main) */}
<section
style={{
display: "flex",
gap: "20px",
}}
>
<VolumeChart data={volumeData} />
</section>
</div>
);
};
1 change: 1 addition & 0 deletions Frontend/src/features/team-stats/routes/TeamStats.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export const TeamStats = () => {
return (
<div>
<h1>Team Statistics</h1>
{/* Repository and user-level metrics will be added here */}
</div>
);
};
Loading
Loading