just showing off, don't merge this!
This commit is contained in:
		
							parent
							
								
									f7938a9dc1
								
							
						
					
					
						commit
						8b988be06e
					
				
					 8 changed files with 7203 additions and 1 deletions
				
			
		|  | @ -43,6 +43,8 @@ class GitHub(object): | |||
|         Returns an iterator over a resource, eg 'repos/divio/django-cms/watchers' that automatically handles | ||||
|         pagination. | ||||
|         """ | ||||
|         if params is None: | ||||
|             params = {} | ||||
|         data, response = self._get(path, params) | ||||
|         for thing in data: | ||||
|             yield thing | ||||
|  |  | |||
							
								
								
									
										15
									
								
								githubnetwork/middleware.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								githubnetwork/middleware.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| from django.utils.functional import SimpleLazyObject | ||||
| from githubnetwork.models import GHUser | ||||
| 
 | ||||
| 
 | ||||
| def get_github_user(request): | ||||
|     if not request.user.is_authenticated(): | ||||
|         return None | ||||
|     return GHUser.objects.get(user=request.user) | ||||
| 
 | ||||
| 
 | ||||
| class GithubUserMiddleware(object): | ||||
|     def process_request(self, request): | ||||
|         request.gh_user = SimpleLazyObject(lambda: get_github_user(request)) | ||||
| 
 | ||||
|  | @ -0,0 +1,19 @@ | |||
| from django.contrib.auth.decorators import login_required | ||||
| from django.http import HttpResponseBadRequest, HttpResponse | ||||
| from django.shortcuts import render_to_response | ||||
| from django.template.context import RequestContext | ||||
| from django.utils import simplejson | ||||
| 
 | ||||
| @login_required | ||||
| def me(request): | ||||
|     context = RequestContext(request) | ||||
|     context['followers'] = simplejson.dumps([{'name': unicode(follower), 'group': 2} for follower in request.gh_user.following.all()]) | ||||
|     return render_to_response('graph.html', context) | ||||
| 
 | ||||
| @login_required | ||||
| def get_user_followers(request): | ||||
|     name = request.GET.get('user', None) | ||||
|     if not name: | ||||
|         raise HttpResponseBadRequest() | ||||
|     names = simplejson.dumps([user['login'] for user in request.github.get_iter('users/%s/followers' % name)]) | ||||
|     return HttpResponse(names, content_type='application/json') | ||||
|  | @ -43,6 +43,7 @@ MIDDLEWARE_CLASSES = [ | |||
|     'django.contrib.auth.middleware.AuthenticationMiddleware', | ||||
|     'django.contrib.messages.middleware.MessageMiddleware', | ||||
|     'ghapi.middleware.GithubAPIMiddleware', | ||||
|     'githubnetwork.middleware.GithubUserMiddleware', | ||||
| ] | ||||
| 
 | ||||
| TEMPLATE_CONTEXT_PROCESSORS = [ | ||||
|  | @ -85,7 +86,7 @@ AUTHENTICATION_BACKENDS = [ | |||
| ] | ||||
| 
 | ||||
| LOGIN_URL          = '/login/' | ||||
| LOGIN_REDIRECT_URL = '/' | ||||
| LOGIN_REDIRECT_URL = '/me/' | ||||
| LOGIN_ERROR_URL    = '/login/failed/' | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										7034
									
								
								static/d3/d3.v2.js
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7034
									
								
								static/d3/d3.v2.js
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										4
									
								
								static/d3/d3.v2.min.js
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								static/d3/d3.v2.min.js
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										125
									
								
								templates/graph.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								templates/graph.html
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,125 @@ | |||
| {% extends "base.html" %} | ||||
| 
 | ||||
| {% block body %} | ||||
|     <div id='chart'> </div> | ||||
|     <style> | ||||
|         circle.node { | ||||
|             stroke: #fff; | ||||
|             stroke-width: 1.5px; | ||||
|         } | ||||
| 
 | ||||
|         line.link { | ||||
|             stroke: #999; | ||||
|             stroke-opacity: .6; | ||||
|         } | ||||
|         .nodetext { | ||||
|             pointer-events: none; | ||||
|             font: 10px sans-serif; | ||||
|         } | ||||
| 
 | ||||
|     </style> | ||||
|     <script src="{{ STATIC_URL }}d3/d3.v2.js"></script> | ||||
|     <script src="{{ STATIC_URL }}/js/jquery.js"></script> | ||||
|     <script> | ||||
|     $(document).ready(function(){ | ||||
| 
 | ||||
|         var followers = {{ followers|safe }}; | ||||
|         var map = {}; | ||||
| 
 | ||||
|         var w = 960, | ||||
|             h = 500; | ||||
|         var color = d3.scale.category20(); | ||||
| 
 | ||||
|         var force = d3.layout.force() | ||||
|                 .gravity(.05) | ||||
|                 .distance(100) | ||||
|                 .charge(-100) | ||||
|                 .size([w, h]); | ||||
| 
 | ||||
|         var nodes = force.nodes(), | ||||
|                 links = force.links(); | ||||
| 
 | ||||
|         var vis = d3.select("body").append("svg:svg") | ||||
|                 .attr("width", w) | ||||
|                 .attr("height", h); | ||||
| 
 | ||||
|         force.on("tick", function() { | ||||
|             vis.selectAll("g.node") | ||||
|                     .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); | ||||
| 
 | ||||
|             vis.selectAll("line.link") | ||||
|                     .attr("x1", function(d) { return d.source.x; }) | ||||
|                     .attr("y1", function(d) { return d.source.y; }) | ||||
|                     .attr("x2", function(d) { return d.target.x; }) | ||||
|                     .attr("y2", function(d) { return d.target.y; }); | ||||
|         }); | ||||
| 
 | ||||
|         function restart() { | ||||
|             var link = vis.selectAll("line.link") | ||||
|                     .data(links, function(d) { return d.source.id + "-" + d.target.id; }); | ||||
| 
 | ||||
|             link.enter().insert("svg:line", "g.node") | ||||
|                     .attr("class", "link"); | ||||
| 
 | ||||
|             link.exit().remove(); | ||||
| 
 | ||||
|             var node = vis.selectAll("g.node") | ||||
|                     .data(nodes, function(d) { return d.id;}); | ||||
| 
 | ||||
|             var nodeEnter = node.enter().append("svg:g").attr('class', 'node').call(force.drag); | ||||
|                 nodeEnter.append("circle") | ||||
|                     .attr("class", "node") | ||||
|                     .attr("r", 5) | ||||
|                     .style("fill", function(d) { return color(d.group); }) | ||||
|                     .attr("x", "-8px") | ||||
|                     .attr("y", "-8px") | ||||
|                     .attr("width", "16px") | ||||
|                     .attr("height", "16px"); | ||||
|                 nodeEnter.append("svg:text") | ||||
|                     .attr("class", "nodetext") | ||||
|                     .attr("dx", 12) | ||||
|                     .attr("dy", ".35em") | ||||
|                     .text(function(d) { return d.name }); | ||||
| 
 | ||||
|             node.exit().remove(); | ||||
| 
 | ||||
|             force.start(); | ||||
|         } | ||||
| 
 | ||||
|         // Add three nodes and three links. | ||||
|         function init() { | ||||
|             var center = {"name": "{{ request.gh_user.gh_login }}", "group": 1}; | ||||
|             nodes.push(center); | ||||
|             for (var i = 0; i<followers.length;i++){ | ||||
|                 nodes.push(followers[i]); | ||||
|                 links.push({source:center, target:followers[i]}); | ||||
|                 map[followers[i].name] = followers[i]; | ||||
|             } | ||||
|             restart(); | ||||
|         } | ||||
| 
 | ||||
|         function addLink(link) { | ||||
|             links.push(link); | ||||
|             restart(); | ||||
|         } | ||||
| 
 | ||||
|         restart(); | ||||
|         init(); | ||||
|         function loadFollowerFollowers(follower){ | ||||
|             $.getJSON('{%  url get_user_followers %}?user=' + follower.name, function(data){ | ||||
|                 for (var i = 0; i<data.length; i++){ | ||||
|                     var target = map[data[i]]; | ||||
|                     if (target){ | ||||
|                         addLink({source:follower, target:target}) | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|             // addLink({source: followers[15], target: followers[5]}); | ||||
|         } | ||||
|         for (var i = 0; i<followers.length; i++){ | ||||
|             loadFollowerFollowers(followers[i]); | ||||
|         } | ||||
|     }); | ||||
|     </script> | ||||
| {% endblock %} | ||||
| 
 | ||||
							
								
								
									
										2
									
								
								urls.py
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								urls.py
									
										
									
									
									
								
							|  | @ -12,6 +12,8 @@ urlpatterns = patterns('', | |||
|     url(r'^%s(?P<path>.*)$' % re.escape(settings.STATIC_URL.lstrip('/')), 'django.contrib.staticfiles.views.serve', {'insecure': True}), | ||||
|     url(r'^admin/', include(admin.site.urls)), | ||||
|     url(r'^login/$', views.login, name='login'), | ||||
|     url(r'^me/$', 'githubnetwork.views.me', name='me'), | ||||
|     url(r'^ajax/$', 'githubnetwork.views.get_user_followers', name='get_user_followers'), | ||||
|     url(r'^$', views.index, name='index'), | ||||
|     url(r'', include('social_auth.urls')), | ||||
| ) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jonas Obrist
						Jonas Obrist