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.

340 lines
7.2 KiB

  1. var nodes;
  2. var edges;
  3. var options = {
  4. nodes: {
  5. borderWidth:4,
  6. size:30,
  7. color: {
  8. border: '#222222',
  9. background: '#666666'
  10. },
  11. font:{color:'#eeeeee'}
  12. },
  13. edges: {
  14. color: 'lightgray'
  15. }
  16. };
  17. /**
  18. * Checks if a user is a node in the graph
  19. *
  20. * @param userID
  21. * @returns {boolean}
  22. */
  23. function alreadyInGraph(userID)
  24. {
  25. for(var i = 0; i < nodes.length; i++)
  26. {
  27. if(nodes[i].id === userID)
  28. {
  29. return true;
  30. }
  31. }
  32. return false;
  33. }
  34. /**
  35. * adds a person to the nodes list
  36. *
  37. * @param profileData
  38. */
  39. function addPersonToGraph(profileData)
  40. {
  41. nodes.push(
  42. {
  43. id:profileData.id,
  44. name:profileData.login,
  45. shape: 'circularImage',
  46. image:profileData.avatar_url
  47. });
  48. }
  49. /**
  50. * Adds the followers/following of a person
  51. * to the graph
  52. *
  53. * @param username
  54. * @param apiPath
  55. * @returns {Promise<any>}
  56. */
  57. function addFriends(username, apiPath, page)
  58. {
  59. updateProgress();
  60. return new Promise(function(resolve, reject)
  61. {
  62. queryAPIByUser(apiPath + "?page=" + page, username, function(data)
  63. {
  64. for(var i = 0; i < data.length; i++)
  65. {
  66. if(!alreadyInGraph(data[i].id))
  67. {
  68. addPersonToGraph(data[i]);
  69. }
  70. }
  71. if(page < 50 && data.length === 30)
  72. {
  73. addFriends(username, apiPath, page+ 1).then(function()
  74. {
  75. resolve();
  76. })
  77. }
  78. else
  79. {
  80. resolve();
  81. }
  82. },
  83. function(error)
  84. {
  85. reject(error);
  86. })
  87. });
  88. }
  89. /**
  90. * Greedy function which checks to see if a edge is in the graphs
  91. *
  92. * @param id1
  93. * @param id2
  94. * @returns {boolean}
  95. */
  96. function edgeInGraph(id1, id2)
  97. {
  98. for(var i = 0;i < edges.length; i++)
  99. {
  100. if(edges[i].from === id1 && edges[i].to === id2)
  101. {
  102. return true;
  103. }
  104. if(edges[i].to === id1 && edges[i].from === id2)
  105. {
  106. return true;
  107. }
  108. }
  109. return false;
  110. }
  111. /**
  112. * Adds a connection to the graph
  113. *
  114. * @param person1
  115. * @param person2
  116. */
  117. function addConnection(person1, person2)
  118. {
  119. if(person1.id !== person2.id)
  120. {
  121. if(alreadyInGraph(person2.id) && !edgeInGraph(person1.id, person2.id))
  122. {
  123. edges.push(
  124. {
  125. from: person1.id,
  126. to: person2.id
  127. });
  128. }
  129. }
  130. }
  131. function processConnections(user, apiPoint, page)
  132. {
  133. return new Promise(function(resolve, reject)
  134. {
  135. queryAPIByUser(apiPoint + "?page=" + page, user.name,
  136. function(data)
  137. {
  138. for(var i = 0; i < data.length; i++)
  139. {
  140. addConnection(user, data[i])
  141. }
  142. if(page < 50 && data.length === 30)
  143. {
  144. processConnections(user, apiPoint, page + 1).then(function()
  145. {
  146. resolve();
  147. });
  148. }
  149. else
  150. {
  151. resolve();
  152. }
  153. }, function(error)
  154. {
  155. console.log(error);
  156. resolve();
  157. })
  158. })
  159. }
  160. /**
  161. * Processes all the connections of a user and adds them to the graph
  162. *
  163. * @param user has .id and .name
  164. * @returns {Promise<any>}
  165. */
  166. function processUserConnections(user)
  167. {
  168. return new Promise(function(resolve, reject)
  169. {
  170. if(user.id === baseID)
  171. {
  172. processConnections(user, API_FOLLOWING, 1).then(function()
  173. {
  174. processConnections(user, API_FOLLOWERS, 1).then(function()
  175. {
  176. updateProgress();
  177. resolve();
  178. })
  179. })
  180. }
  181. else
  182. {
  183. processConnections(user, API_FOLLOWING, 1).then(function()
  184. {
  185. updateProgress();
  186. resolve();
  187. })
  188. }
  189. });
  190. }
  191. /**
  192. * Creates connections between all the nodes in
  193. * the graph.
  194. *
  195. * @returns {Promise<any>}
  196. */
  197. function createConnections()
  198. {
  199. return new Promise(function(resolve, reject)
  200. {
  201. var prom = [];
  202. for(var i = 0; i < nodes.length; i++)
  203. {
  204. prom.push(processUserConnections(nodes[i]));
  205. }
  206. Promise.all(prom).then(function()
  207. {
  208. resolve();
  209. }).catch(function(error)
  210. {
  211. console.log(error);
  212. resolve();
  213. });
  214. });
  215. }
  216. var total = 1;
  217. var indexed = 0;
  218. var progressID;
  219. function updateProgress()
  220. {
  221. indexed++;
  222. var percent = parseInt((indexed/total)*100);
  223. $("#" + progressID).html("<div class=\"progress\">\n" +
  224. " <div class=\"progress-bar progress-bar-striped progress-bar-animated\" role=\"progressbar\" style=\"width: " + percent + "%\" aria-valuenow=\"" + percent + "\" aria-valuemin=\"0\" aria-valuemax=\"100\"></div>\n" +
  225. "</div>");
  226. console.log();
  227. }
  228. var baseID;
  229. /**
  230. * Adds the base person to the graph.
  231. *
  232. * @param username
  233. * @returns {Promise<any>}
  234. */
  235. function addSelfToGraph(username)
  236. {
  237. return new Promise(function(resolve, reject)
  238. {
  239. queryAPIByUser("", username, function(data)
  240. {
  241. baseID = data.id;
  242. total = (data.followers + data.following);
  243. addPersonToGraph(data);
  244. resolve();
  245. },
  246. function(error)
  247. {
  248. reject(error);
  249. });
  250. });
  251. }
  252. function bringUpProfileView(id)
  253. {
  254. for(var i = 0; i < nodes.length; i++)
  255. {
  256. if(nodes[i].id === id)
  257. {
  258. profileGen(nodes[i].name, "profileGen");
  259. }
  260. }
  261. }
  262. /**
  263. * Creates a graph
  264. * @param username
  265. * @param containerName
  266. * @param graphsTitle
  267. */
  268. function createFriendsGraph(username, containerName, graphsTitle)
  269. {
  270. progressID = graphsTitle;
  271. nodes = [];
  272. edges = [];
  273. addSelfToGraph(username).then(function()
  274. {
  275. addFriends(username, API_FOLLOWERS,1).then(function()
  276. {
  277. addFriends(username, API_FOLLOWING,1).then(function()
  278. {
  279. createConnections().then(function()
  280. {
  281. $("#" + progressID).html("");
  282. var container = document.getElementById(containerName);
  283. var data =
  284. {
  285. nodes: nodes,
  286. edges: edges
  287. };
  288. var network = new vis.Network(container, data, options);
  289. network.on("click", function (params)
  290. {
  291. params.event = "[original event]";
  292. if(Number(this.getNodeAt(params.pointer.DOM)) !== NaN)
  293. {
  294. bringUpProfileView(Number(this.getNodeAt(params.pointer.DOM)));
  295. }
  296. });
  297. });
  298. });
  299. })
  300. }).catch(function(error)
  301. {
  302. $("#" + graphsTitle).html("Error Fetching Data From API");
  303. alert("Invalid User");
  304. });
  305. }