Skip to content

Commit 756a4d2

Browse files
committed
feat: forks statistic
1 parent 455ec9d commit 756a4d2

File tree

6 files changed

+184
-126
lines changed

6 files changed

+184
-126
lines changed

components/LineGraph.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export default function LineGraph({ data, startYear, thisYear }) {
1616
<YAxis tick={false} tickLine={false} />
1717
<Tooltip />
1818
<Line type="monotone" dataKey="issues" stroke="#C2DEFB" dot={false} />
19+
<Line type="monotone" dataKey="forks" stroke="#FFCCB6" dot={false} />
1920
</LineChart>
2021
</ResponsiveContainer>
2122
)

libs/formatDataByYear.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export const formatDataByYear = (data) => {
2+
//get only the year of each item
3+
const occurencePerYear = data.map((datum) => ({ year: datum.created_at.split("-").slice(0,1)[0] }));
4+
//group and count items by year
5+
const itemCounts =occurencePerYear.reduce((p, c) => {
6+
const year = c.year;
7+
if (!p.hasOwnProperty(year)) {
8+
p[year] = 0;
9+
}
10+
p[year]++;
11+
return p;
12+
}, {});
13+
const itemCountsExtended = Object.keys(itemCounts).map(year => {
14+
return {year, count: itemCounts[year]};
15+
});
16+
return itemCountsExtended;
17+
}

libs/index.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { range } from './range'
2+
import { mergeData } from './mergeData'
3+
import { formatDataByYear } from './formatDataByYear'
4+
5+
export {
6+
range,
7+
mergeData,
8+
formatDataByYear
9+
}

libs/mergeData.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export const mergeData = (baseData, key, merge) => {
2+
baseData.forEach((data) => {
3+
merge.forEach((item) => {
4+
if (data.year == item.year) {
5+
data[key] = item.count
6+
}
7+
})
8+
})
9+
}

pages/[name].js

Lines changed: 111 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,147 +1,157 @@
1-
import Head from 'next/head'
2-
import containerStyles from '../styles/Container.module.css'
3-
import styles from '../styles/RepoPage.module.css'
4-
import { useEffect, useState, useMemo } from 'react'
5-
import Link from 'next/link'
6-
import RepoHeader from '../components/RepoHeader'
7-
import { range } from '../libs/range'
8-
import LineGraph from '../components/LineGraph'
1+
import Head from "next/head";
2+
import containerStyles from "../styles/Container.module.css";
3+
import styles from "../styles/RepoPage.module.css";
4+
import { useEffect, useState, useMemo } from "react";
5+
import Link from "next/link";
6+
import RepoHeader from "../components/RepoHeader";
7+
import { range, mergeData, formatDataByYear } from "../libs";
8+
import LineGraph from "../components/LineGraph";
99

1010
export async function getStaticPaths() {
1111
return {
12-
paths: [],
13-
fallback: true
12+
paths: [],
13+
fallback: true,
1414
};
1515
}
1616

17-
1817
export async function getStaticProps({ params }) {
19-
const res = await fetch(`https://api.github.com/repos/${process.env.REPO_USERNAME}/${params.name}`)
20-
const repoData = await res.json()
21-
22-
2318
let myHeaders = new Headers();
24-
myHeaders.append('Authorization', `token ${process.env.API_TOKEN}`);
19+
myHeaders.append("Authorization", `token ${process.env.API_TOKEN}`);
20+
21+
const res = await fetch(
22+
`https://api.github.com/repos/${process.env.REPO_USERNAME}/${params.name}`,
23+
{ headers: myHeaders }
24+
);
25+
const repoData = await res.json();
2526

2627
/*
27-
const collaboratorsRes = await fetch(`https://api.github.com/repos/${process.env.REPO_USERNAME}/${params.name}/collaborators`,
28-
{
29-
headers: myHeaders
30-
})
31-
const collaborators = await collaboratorsRes.json()
32-
*/
33-
34-
const issuesRes = await fetch(`https://api.github.com/repos/${process.env.REPO_USERNAME}/${params.name}/issues`,
35-
{
36-
headers: myHeaders
37-
})
38-
const issues = await issuesRes.json()
39-
28+
const collaboratorsRes = await fetch(`https://api.github.com/repos/${process.env.REPO_USERNAME}/${params.name}/collaborators`,
29+
{
30+
headers: myHeaders
31+
})
32+
const collaborators = await collaboratorsRes.json()
33+
*/
34+
35+
const issuesRes = await fetch(
36+
`https://api.github.com/repos/${process.env.REPO_USERNAME}/${params.name}/issues?per_page=100`,
37+
{ headers: myHeaders }
38+
);
39+
const issues = await issuesRes.json();
40+
41+
const forksRes = await fetch(
42+
`https://api.github.com/repos/${process.env.REPO_USERNAME}/${params.name}/forks?per_page=100`,
43+
{ headers: myHeaders }
44+
);
45+
const forks = await forksRes.json();
46+
4047
if (!repoData) {
41-
return {
48+
return {
4249
notFound: true,
43-
}
50+
};
4451
}
45-
52+
4653
return {
47-
props: {
48-
repoData,
49-
issues
50-
},
54+
props: {
55+
repoData,
56+
issues,
57+
forks,
58+
},
59+
};
5160
}
52-
}
5361

54-
export default function RepoStatPage ({ repoData, issues}) {
62+
export default function RepoStatPage({ repoData, issues, forks }) {
5563
const [displayedData, setDisplayedData] = useState(repoData);
56-
const [graphData, setGraphData] = useState([]);
5764
const startYear = useMemo(() => {
5865
if (repoData) {
59-
return repoData?.created_at.split("-").slice(0,1)
66+
return repoData?.created_at.split("-").slice(0, 1);
6067
}
61-
}, [repoData])
68+
}, [repoData]);
6269

6370
const todayDate = new Date();
6471
const thisYear = Number(todayDate.getFullYear());
6572
//set a base array of objects to keep the data
6673
let baseData = useMemo(() => {
6774
const years = range(Number(startYear), thisYear, 1);
68-
return years.map((year) => ({ year, issues: 0 }))
75+
return years.map((year) => ({ year, issues: 0, forks: 0 }));
6976
}, [startYear]);
7077

7178
useEffect(() => {
7279
if (repoData) {
7380
setDisplayedData(repoData);
7481
}
7582
}, [repoData]);
76-
77-
const filteredIssues = useMemo(() => {
83+
84+
const issuesData = useMemo(() => {
7885
if (issues) {
79-
const filtered = issues.filter((issue) => {
80-
return issue.state === 'open'
86+
const filteredIssues = issues
87+
.filter((issue) => {
88+
return issue.state === "open";
8189
})
82-
return filtered.reverse();
90+
.reverse();
91+
92+
return formatDataByYear(filteredIssues);
8393
}
8494
}, [issues]);
8595

86-
const issuesData = useMemo(() => {
87-
if (filteredIssues) {
88-
//get only the year of each issues
89-
const issuesPerYear = filteredIssues.map((issue) => ({ year: issue.created_at.split("-").slice(0,1)[0] }));
90-
//group and count issues by year
91-
const issuesCounts = issuesPerYear.reduce((p, c) => {
92-
const year = c.year;
93-
if (!p.hasOwnProperty(year)) {
94-
p[year] = 0;
95-
}
96-
p[year]++;
97-
return p;
98-
}, {});
99-
const issuesCountsExtended = Object.keys(issuesCounts).map(year => {
100-
return {year, count: issuesCounts[year]};
101-
});
102-
//merge into baseData
103-
baseData.forEach((data) => {
104-
issuesCountsExtended.forEach((issue) => {
105-
if (data.year == issue.year) {
106-
data.issues = issue.count
107-
}
108-
})
109-
})
110-
return baseData
96+
const forksData = useMemo(() => {
97+
if (forks) {
98+
return formatDataByYear(forks.reverse());
99+
}
100+
}, [forks]);
101+
102+
useEffect(() => {
103+
if (repoData) {
104+
mergeData(baseData, "issues", issuesData);
111105
}
112-
}, [filteredIssues]);
106+
}, [issuesData]);
113107

114108
useEffect(() => {
115-
if (issuesData) {
116-
setGraphData(issuesData)
109+
if (repoData) {
110+
mergeData(baseData, "forks", forksData);
117111
}
118-
}, [issuesData])
112+
}, [forksData]);
119113

120114
return (
121115
<div className={containerStyles.container}>
122-
<Head>
123-
<title>{displayedData?.full_name}</title>
124-
<meta name="Github Indicators Explorer" content={`${displayedData?.full_name} indicator`} />
125-
<link rel="icon" href="/favicon.ico" />
126-
</Head>
127-
128-
<main className={styles.main}>
129-
<Link href='/'>
130-
<p className={styles.choose_repo}>Choose another repository</p>
131-
</Link>
132-
133-
<RepoHeader data={displayedData} />
134-
135-
<div className={styles.option_container}>
136-
<p className={styles.data_option} style={{ backgroundColor: "#C2DEFB" }}>Open issues</p>
137-
<p className={styles.data_option} style={{ backgroundColor: "#FFCCB6" }}>Collaborators</p>
138-
</div>
139-
140-
<div className={styles.graph_container}>
141-
<LineGraph data={graphData} startYear={startYear} thisYear={thisYear} />
142-
</div>
143-
</main>
144-
116+
<Head>
117+
<title>{displayedData?.full_name}</title>
118+
<meta
119+
name="Github Indicators Explorer"
120+
content={`${displayedData?.full_name} indicator`}
121+
/>
122+
<link rel="icon" href="/favicon.ico" />
123+
</Head>
124+
125+
<main className={styles.main}>
126+
<Link href="/">
127+
<p className={styles.choose_repo}>Choose another repository</p>
128+
</Link>
129+
130+
<RepoHeader data={displayedData} />
131+
132+
<div className={styles.option_container}>
133+
<p
134+
className={styles.data_option}
135+
style={{ backgroundColor: "#C2DEFB" }}
136+
>
137+
Open issues
138+
</p>
139+
<p
140+
className={styles.data_option}
141+
style={{ backgroundColor: "#FFCCB6" }}
142+
>
143+
Forks
144+
</p>
145+
</div>
146+
147+
<div className={styles.graph_container}>
148+
<LineGraph
149+
data={baseData}
150+
startYear={startYear}
151+
thisYear={thisYear}
152+
/>
153+
</div>
154+
</main>
145155
</div>
146-
)
147-
}
156+
);
157+
}

0 commit comments

Comments
 (0)