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.

398 lines
8.3 KiB

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