Public
Edited
Apr 24, 2024
Importers
Insert cell
Insert cell
GitHubRepositoryVisualizer = async function (repos, apiToken, controls) {
if (!repos) return;

const actualData = []

const getPlots = async (repoName, owner) => {
let plts = [];
if (controls.includes('Issues')) {
const issuesEndpoint = `/repos/${owner}/${repoName}/issues?per_page=100`;
const issues = await useGithubApi(issuesEndpoint, apiToken);
const groupedIssues = Object.groupBy(
issues.data,
(item) => item.created_at.split("T")[0]
);
const processedData = Object.entries(groupedIssues)
?.map(([date, items]) => ({
date: new Date(date),
noOfIssues: items.length,
items,
}))
.sort((a, b) => a.date - b.date);


const issuesPlot = Plot.plot({
y: {
grid: true,
label: "↑ Number of Issues",
labelOffset: 10,
tickSize: 5,
tickPadding: 5,
ticks: d3.range(
Math.floor(d3.min(processedData, (d) => d.noOfIssues)),
Math.ceil(d3.max(processedData, (d) => d.noOfIssues)) + 1
),
tickFormat: (d) => Math.round(d),
style: {
fontSize: "16px",
fontWeight: "bold",
},
},
x: {
label: "Date →",
labelOffset: 10,
tickSize: 5,
tickPadding: 5,
style: {
fontSize: "16px",
fontWeight: "bold",
},
},
color: {
legend: true,
},
marks: [
Plot.lineY(processedData, {
x: "date",
y: "noOfIssues",
stroke: "#D01B25",
strokeWidth: 3,
tip: true,
}),
Plot.crosshair(processedData, {
x: "date",
y: "noOfIssues",
}),
],
width: 650,
height: 400,
marginTop: 50,
marginLeft: 60,
title: "Open Issues (Latest 100)",
});
plts.push(issues.data.length ? issuesPlot : htl.html`<h1 style="color: red">No recent issues</h1>`);
}

if (controls.includes('Pull Requests')) {
const issuesEndpoint = `/repos/${owner}/${repoName}/pulls?per_page=100`;
const prs = await useGithubApi(issuesEndpoint, apiToken);
const groupedPrs = Object.groupBy(
prs.data,
(item) => item.created_at.split("T")[0]
);
const processedData = Object.entries(groupedPrs)
?.map(([date, items]) => ({
date: new Date(date),
noOfPrs: items.length,
items,
}))
.sort((a, b) => a.date - b.date);


const prsPlot = Plot.plot({
y: {
grid: true,
label: "↑ Number of PRs",
labelOffset: 10,
tickSize: 5,
tickPadding: 5,
ticks: d3.range(
Math.floor(d3.min(processedData, (d) => d.noOfPrs)),
Math.ceil(d3.max(processedData, (d) => d.noOfPrs)) + 1
),
tickFormat: (d) => Math.round(d),
style: {
fontSize: "16px",
fontWeight: "bold",
},
},
x: {
label: "Date →",
labelOffset: 10,
tickSize: 5,
tickPadding: 5,
style: {
fontSize: "16px",
fontWeight: "bold",
},
},
color: {
legend: true,
},
marks: [
Plot.lineY(processedData, {
x: "date",
y: "noOfPrs",
stroke: "steelblue",
strokeWidth: 3,
tip: true,
}),
Plot.crosshair(processedData, {
x: "date",
y: "noOfPrs",
}),
],
width: 650,
height: 400,
marginTop: 50,
marginLeft: 60,
title: "Open PRs (Latest 100)",
});
plts.push(prs.data.length ? prsPlot : htl.html`<h1 style="color: red">No recent Pull Requests</h1>`);
}
return plts
};

const getData = async () => {
for (let repo of repos) {
const repoData = repo.split(":");
const [repoName, owner] = repoData;
const plots = await getPlots(repoName, owner);
const repoEndpoint = `/repos/${owner}/${repoName}`
const languagesEndpoint = `/repos/${owner}/${repoName}/languages`
const repository = (await useGithubApi(repoEndpoint, apiToken)).data
const languages = (await useGithubApi(languagesEndpoint, apiToken)).data
const languagesAsText = Object.keys(languages).join(', ')
const outputHtml = htl.html`
<div style="width: 100%; border-bottom: 1px dashed black; padding: 20px">
<h1>${repository.full_name}</h1>
<div>
<p><a href="${repository.html_url}" target="_blank">Repository link</a></p>
<div>Created on: ${dayjs(repository.created_at).format('MMMM D, YYYY')}</div>
<div>Last updated: ${dayjs(repository.updated_at).format('MMMM D, YYYY')}</div>
<div>Stars: ${repository.stargazers_count}</div>
<div>No of forks: ${repository.forks_count}</div>
<div>No of open issues: ${repository.open_issues_count}</div>
<div>Language(s): ${languagesAsText}</div>
</div>
${plots.map((plot) => {
return htl.html`<div>${plot}</div>`;
})}
</div>`;
actualData.push(outputHtml)
}
}
await getData();

return htl.html`
${actualData.map((d) => {
return htl.html`<div>${d}</div>`
})}
`;
};
Insert cell
d3 = require('d3@7')
Insert cell
dayjs = require('dayjs')
Insert cell
import {useGithubApi} from "@nu-cs3200-spring24-db/github-user-explorer"
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more