Skip to content

Instantly share code, notes, and snippets.

@vjwilson
Last active April 27, 2019 16:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vjwilson/b530938232834fdff1e493b07e1dd085 to your computer and use it in GitHub Desktop.
Save vjwilson/b530938232834fdff1e493b07e1dd085 to your computer and use it in GitHub Desktop.
pie chart repos by language
license: mit
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
</style>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="search-block">
<label for="username">GitHub Username</label>
<input name="username" id="username" value="vjwilson">
<button type="button" id="search">Graph Repos</button>
</div>
<div class="github-link" id="github-link">
</div>
<div class="container">
</div>
<script>
const container = d3.select('.container')
const svg = container.append("svg")
.attr("width", 960)
.attr("height", 500);
const width = svg.attr("width");
const height = svg.attr("height");
const radius = Math.min(width, height) / 2;
const searchBox = document.getElementById('username');
const triggerBtn = document.getElementById('search');
let username = searchBox.value;
const githubLink = document.getElementById('github-link');
triggerBtn.addEventListener('click', function(e) {
username = searchBox.value.trim();
graphRepos(username);
});
searchBox.addEventListener('keypress', function(e) {
const code = e.which;
if (code === 13) {
username = searchBox.value.trim();
graphRepos(username);
}
});
graphRepos(username);
function graphRepos(user) {
svg.selectAll("*").remove();
while (githubLink.firstChild) {
githubLink.removeChild(githubLink.firstChild);
}
fetch(`https://api.github.com/users/${user}/repos?per_page=100`)
.then(function(response) {
if (!response.ok) {
throw new Error("HTTP error, status = " + response.status);
}
return response.json();
})
.then(function(repos) {
if (!repos.length) {
throw new Error(`No public repos for user ${user}`);
}
const g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
const totals = repos.reduce((sums, repo) => {
sums[repo.language] = (sums[repo.language] || 0) + 1;
return sums;
}, {});
const int = Object.entries(totals);
const newData = int.map((sum) => {
return {
language: sum[0],
count: sum[1]
};
});
const color = d3.scaleOrdinal(['#4daf4a','#377eb8','#ff7f00','#984ea3','#e41a1c']);
// Generate the pie
const pie = d3.pie().value(function(d) {
return d.count;
});
// Generate the arcs
const arc = d3.arc()
.innerRadius(0)
.outerRadius(radius - 50);
const label = d3.arc()
.outerRadius(radius - 5)
.innerRadius(radius - 35);
//Generate groups
const arcs = g.selectAll(".arc")
.data(pie(newData))
.enter()
.append("g")
.attr("class", "arc")
//Draw arc paths
arcs.append("path")
.attr("fill", function(d) {
return color(d.data.language);
})
.attr('stroke', 'white')
.attr("d", arc);
arcs.append("text")
.attr("transform", function(d) {
return "translate(" + label.centroid(d) + ")";
})
.attr('text-anchor', 'middle')
.attr('font-size', '14px')
.text(function(d) {
return d.data.language + ' (' + d.data.count + ')';
});
const newLink = document.createElement('a');
newLink.setAttribute('href', `https://github.com/${user}?tab=repositories`);
newLink.setAttribute('target', '_blank');
newLink.setAttribute('rel', 'noopener noreferrer');
newLink.setAttribute('target', '_top');
const newContent = document.createTextNode(`View repos for ${user}`);
newLink.appendChild(newContent);
githubLink.append(newLink);
svg.append("g")
.attr("transform", "translate(" + 40 + "," + (height / 2) + ")rotate(270)")
.append("text")
.text("Public Repos by Language")
.attr("class", "title")
.attr('font-size', '24px')
.attr('text-anchor', 'middle');
})
.catch(function(error) {
var p = document.createElement('p');
p.classList.add('error')
p.appendChild(
document.createTextNode('Error: ' + error.message)
);
document.body.insertBefore(p, container.node());
});
}
</script>
</body>
*:focus {
outline: thin rebeccapurple dotted;
}
.search-block {
border: 1px solid rebeccapurple;
border-radius: 4px;
padding: .5rem;
position: absolute;
width: 200px;
}
.search-block label {
color: grey;
display: block;
margin-bottom: .125rem;
}
.search-block input {
color: rebeccapurple;
font-size: 1rem;
margin-bottom: .75rem;
width: 100%
}
.search-block button {
background-color: rebeccapurple;
color: white;
display: block;
font-size: 1rem;
font-weight: bold;
width: 100%;
}
.github-link {
padding: 1rem;
position: absolute;
right: 0;
}
.error {
color: red;
position: absolute;
left: 0;
text-align: center;
top: 50%;
width: 100%;
z-index: 1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment