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
|
Returns an iterator over a resource, eg 'repos/divio/django-cms/watchers' that automatically handles
|
||||||
pagination.
|
pagination.
|
||||||
"""
|
"""
|
||||||
|
if params is None:
|
||||||
|
params = {}
|
||||||
data, response = self._get(path, params)
|
data, response = self._get(path, params)
|
||||||
for thing in data:
|
for thing in data:
|
||||||
yield thing
|
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.auth.middleware.AuthenticationMiddleware',
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
'ghapi.middleware.GithubAPIMiddleware',
|
'ghapi.middleware.GithubAPIMiddleware',
|
||||||
|
'githubnetwork.middleware.GithubUserMiddleware',
|
||||||
]
|
]
|
||||||
|
|
||||||
TEMPLATE_CONTEXT_PROCESSORS = [
|
TEMPLATE_CONTEXT_PROCESSORS = [
|
||||||
|
@ -85,7 +86,7 @@ AUTHENTICATION_BACKENDS = [
|
||||||
]
|
]
|
||||||
|
|
||||||
LOGIN_URL = '/login/'
|
LOGIN_URL = '/login/'
|
||||||
LOGIN_REDIRECT_URL = '/'
|
LOGIN_REDIRECT_URL = '/me/'
|
||||||
LOGIN_ERROR_URL = '/login/failed/'
|
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'^%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'^admin/', include(admin.site.urls)),
|
||||||
url(r'^login/$', views.login, name='login'),
|
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'^$', views.index, name='index'),
|
||||||
url(r'', include('social_auth.urls')),
|
url(r'', include('social_auth.urls')),
|
||||||
)
|
)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue