Website for visualizing a persons github network.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

242 lines
6.9 KiB

  1. <html>
  2. <head>
  3. <title>Stack Overflow - Calendar Heatmap</title>
  4. <style>
  5. .body {
  6. height: 97%;
  7. }
  8. svg {
  9. height: 1800;
  10. width: 97%;
  11. }
  12. </style>
  13. <script
  14. src="https://code.jquery.com/jquery-3.3.1.min.js"
  15. integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
  16. crossorigin="anonymous">
  17. </script>
  18. <script src="js/githubAPI.js"></script>
  19. <script src="js/utilities.js"></script>
  20. <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.9.2/d3.js"></script>
  21. <script src="https://cdnjs.cloudflare.com/ajax/libs/d3-color/1.2.1/d3-color.js"></script>
  22. </head>
  23. <body>
  24. <h3>Stack Overflow - Calendar Heatmap</h3>
  25. <h4>Daily Commits to RITlug/teleirc</h4>
  26. <svg id="svg"></svg>
  27. <script>
  28. function countCommitsPerDay(commits)
  29. {
  30. var reduce = [];
  31. console.log(commits);
  32. var current_date = new Date(commits[0].date);
  33. current_date.setHours(0,0,0,0);
  34. var current_count = 0;
  35. for(var i = 1; i < commits.length; i++)
  36. {
  37. var d = new Date(commits[i].date);
  38. d.setHours(0,0,0,0);
  39. console.log(d);
  40. if(current_date.getTime() == d.getTime())
  41. {
  42. console.log("Stonks");
  43. current_count++;
  44. }
  45. else
  46. {
  47. reduce.push({Date:current_date.toISOString(), AnswerCount: current_count});
  48. current_count = 1;
  49. current_date = d;
  50. }
  51. reduce.push({Date:current_date.toISOString(), AnswerCount: current_count});
  52. }
  53. console.log(reduce);
  54. return reduce;
  55. }
  56. function createHeatmapGraph(commits, containerID)
  57. {
  58. var sample = countCommitsPerDay(commits);
  59. sample.sort((a, b) => new Date(a.Date) - new Date(b.Date));
  60. const dateValues = sample.map(dv => ({
  61. date: d3.timeDay(new Date(dv.Date)),
  62. value: Number(dv.AnswerCount)
  63. }));
  64. const svg = d3.select("#" + containerID);
  65. const { width, height } = document
  66. .getElementById(containerID)
  67. .getBoundingClientRect();
  68. function draw() {
  69. const years = d3
  70. .nest()
  71. .key(d => d.date.getUTCFullYear())
  72. .entries(dateValues)
  73. .reverse();
  74. const values = dateValues.map(c => c.value);
  75. const maxValue = d3.max(values);
  76. const minValue = d3.min(values);
  77. const cellSize = 15;
  78. const yearHeight = cellSize * 7;
  79. const group = svg.append("g");
  80. const year = group
  81. .selectAll("g")
  82. .data(years)
  83. .join("g")
  84. .attr(
  85. "transform",
  86. (d, i) => `translate(50, ${yearHeight * i + cellSize * 1.5})`
  87. );
  88. year
  89. .append("text")
  90. .attr("x", -5)
  91. .attr("y", -30)
  92. .attr("text-anchor", "end")
  93. .attr("font-size", 16)
  94. .attr("font-weight", 550)
  95. .attr("transform", "rotate(270)")
  96. .text(d => d.key);
  97. const formatDay = d =>
  98. ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"][d.getUTCDay()];
  99. const countDay = d => d.getUTCDay();
  100. const timeWeek = d3.utcSunday;
  101. const formatDate = d3.utcFormat("%x");
  102. const colorFn = d3
  103. .scaleSequential(d3.interpolateBuGn)
  104. .domain([Math.floor(minValue) -1, Math.ceil(maxValue)]);
  105. const format = d3.format("+.2%");
  106. year
  107. .append("g")
  108. .attr("text-anchor", "end")
  109. .selectAll("text")
  110. .data(d3.range(7).map(i => new Date(1995, 0, i)))
  111. .join("text")
  112. .attr("x", -5)
  113. .attr("y", d => (countDay(d) + 0.5) * cellSize)
  114. .attr("dy", "0.31em")
  115. .attr("font-size", 12)
  116. .text(formatDay);
  117. year
  118. .append("g")
  119. .selectAll("rect")
  120. .data(d => d.values)
  121. .join("rect")
  122. .attr("width", cellSize - 1.5)
  123. .attr("height", cellSize - 1.5)
  124. .attr(
  125. "x",
  126. (d, i) => timeWeek.count(d3.utcYear(d.date), d.date) * cellSize + 10
  127. )
  128. .attr("y", d => countDay(d.date) * cellSize + 0.5)
  129. .attr("fill", d => colorFn(d.value))
  130. .append("title")
  131. .text(d => `${formatDate(d.date)}: ${d.value.toFixed(2)}`);
  132. const legend = group
  133. .append("g")
  134. .attr(
  135. "transform",
  136. `translate(10, ${years.length * yearHeight + cellSize * 4})`
  137. );
  138. const categoriesCount = 10;
  139. const categories = [...Array(categoriesCount)].map((_, i) => {
  140. const upperBound = (maxValue / categoriesCount) * (i + 1);
  141. const lowerBound = (maxValue / categoriesCount) * i;
  142. return {
  143. upperBound,
  144. lowerBound,
  145. color: d3.interpolateBuGn(upperBound / maxValue),
  146. selected: true
  147. };
  148. });
  149. const legendWidth = 60;
  150. function toggle(legend) {
  151. const { lowerBound, upperBound, selected } = legend;
  152. legend.selected = !selected;
  153. const highlightedDates = years.map(y => ({
  154. key: y.key,
  155. values: y.values.filter(
  156. v => v.value > lowerBound && v.value <= upperBound
  157. )
  158. }));
  159. year
  160. .data(highlightedDates)
  161. .selectAll("rect")
  162. .data(d => d.values, d => d.date)
  163. .transition()
  164. .duration(500)
  165. .attr("fill", d => (legend.selected ? colorFn(d.value) : "white"));
  166. }
  167. legend
  168. .selectAll("rect")
  169. .data(categories)
  170. .enter()
  171. .append("rect")
  172. .attr("fill", d => d.color)
  173. .attr("x", (d, i) => legendWidth * i)
  174. .attr("width", legendWidth)
  175. .attr("height", 15)
  176. .on("click", toggle);
  177. legend
  178. .selectAll("text")
  179. .data(categories)
  180. .join("text")
  181. .attr("transform", "rotate(90)")
  182. .attr("y", (d, i) => -legendWidth * i)
  183. .attr("dy", -30)
  184. .attr("x", 18)
  185. .attr("text-anchor", "start")
  186. .attr("font-size", 11)
  187. .text(d => `${d.lowerBound.toFixed(2)} - ${d.upperBound.toFixed(2)}`);
  188. legend
  189. .append("text")
  190. .attr("dy", -5)
  191. .attr("font-size", 14)
  192. .attr("text-decoration", "underline");
  193. }
  194. draw();
  195. }
  196. getRepoCommits("torvalds/linux", (data)=>
  197. {
  198. console.log(data);
  199. createHeatmapGraph(data, "svg");
  200. },
  201. (error)=>
  202. {
  203. console.log(error);
  204. })
  205. </script>
  206. </body>
  207. </html>