Merge branch 'master' of github.com:beetletweezers/tweezers
Conflicts: core/views.pyrtd2
commit
45a523f143
|
@ -1,4 +1,5 @@
|
|||
from django.conf import settings
|
||||
from django.db.models import F
|
||||
from django.http import HttpResponse
|
||||
from django.shortcuts import render_to_response
|
||||
from django.template import RequestContext
|
||||
|
@ -11,6 +12,7 @@ import os
|
|||
from projects.models import Project
|
||||
from projects.tasks import update_docs
|
||||
from projects.utils import find_file
|
||||
from watching.models import PageView
|
||||
|
||||
|
||||
@csrf_view_exempt
|
||||
|
@ -29,6 +31,11 @@ def serve_docs(request, username, project_slug, filename):
|
|||
filename = filename.rstrip('/')
|
||||
if not os.path.exists(os.path.join(proj.full_html_path, filename)):
|
||||
return HttpResponse("These docs haven't been built yet :(")
|
||||
if 'html' in filename:
|
||||
pageview, created = PageView.objects.get_or_create(project=proj, url=filename)
|
||||
if not created:
|
||||
pageview.count = F('count') + 1
|
||||
pageview.save()
|
||||
return serve(request, filename, proj.full_html_path)
|
||||
|
||||
def render_header(request):
|
||||
|
|
|
@ -53,37 +53,16 @@ input[type="text"], input[type="password"] { width: 250px; height: 20px; margin-
|
|||
select { display: block; max-height: 300px; width: 250px; margin-bottom: 10px; font: 16/20px "inconsolata-1", "inconsolata-2", 'bitstream vera sans mono', 'andale mono', 'lucida console', monospace; }
|
||||
textarea { width: 435px; height: 150px; }
|
||||
input[type="submit"], input[type="button"], button { font-family: "ff-meta-web-pro-1", "ff-meta-web-pro-2", Arial, "Helvetica Neue", sans-serif; color: #666; font-weight: bold; padding: 4px 10px; border: none; background: #e6e6e6 url(../images/gradient.png) repeat-x bottom left; margin: 30px 5px 20px 0; text-shadow: 0 1px 0 rgba(255, 255, 255, 1); border: 1px solid #bfbfbf; }
|
||||
input[type="submit"]:hover, input[type="button"]:hover, button:hover { background: #8ECC4C url(../images/gradient.png) repeat-x bottom left; color: #fff; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.5); }
|
||||
input[type="submit"]:hover, input[type="button"]:hover, button:hover { background-color: #8ECC4C; color: #fff; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.5); border-color: #8ECC4C; }
|
||||
fieldset { border: 1px solid #bfbfbf; padding: 15px; -moz-border-radius: 3px; -webkit-border-radius: 3px; margin-bottom: 15px; }
|
||||
input[type="hidden"] { display: none; }
|
||||
input[type="checkbox"], input[type="radio"] { display: inline; }
|
||||
label { display: block; margin-bottom: 4px; font-weight: bold; }
|
||||
|
||||
|
||||
/* header */
|
||||
|
||||
#rtfd-header { height: 50px; min-width: 780px; background: #465158; overflow: hidden; text-align: left; border-bottom: 1px solid #ccc; }
|
||||
|
||||
/* header title */
|
||||
.rtfd-header-title h1 { font-size: 20px; padding: 5px 20px; color: #fff; }
|
||||
|
||||
/* header search */
|
||||
.rtfd-header-search { position: absolute; top: 10px; left: 230px; }
|
||||
.rtfd-header-search input { padding: 0 5px; margin: 0; height: 25px; font-size: 14px; float: left; -moz-border-radius: 0; -webkit-border-radius: 0; border: none; }
|
||||
.rtfd-header-search input[type="text"] { -moz-border-radius-topleft: 3px; -moz-border-radius-bottomleft: 3px; -webkit-border-top-left-radius: 3px; -webkit-border-bottom-left-radius: 3px; }
|
||||
.rtfd-header-search input[type="submit"] { -moz-border-radius-topright: 3px; -moz-border-radius-bottomright: 3px; -webkit-border-top-right-radius: 3px; -webkit-border-bottom-right-radius: 3px; padding: 0 12px; }
|
||||
|
||||
/* header nav */
|
||||
.rtfd-header-nav { position: absolute; top: 0; right: 10px; }
|
||||
.rtfd-header-nav ul li { float: left; }
|
||||
.rtfd-header-nav ul li a { display: block; text-decoration: none; background: url(../images/gradient.png) bottom left repeat-x #697983; padding: 15px; color: #fff; }
|
||||
.rtfd-header-nav ul li a:hover { background-color: #8CA1AF; }
|
||||
.rtfd-header-nav ul li.active a, .header-nav ul li.active a:hover { background-color: #BAC7CF; }
|
||||
|
||||
|
||||
/* content */
|
||||
|
||||
#content { margin-top: 80px; }
|
||||
#content { padding-top: 80px; }
|
||||
|
||||
|
||||
/* module */
|
||||
|
@ -127,6 +106,13 @@ label { display: block; margin-bottom: 4px; font-weight: bold; }
|
|||
.pagination .current.page, .pagination .current.page:hover { color: #444; background: url("../images/gradient-light.png") repeat-x scroll left bottom #d9d9d9; }
|
||||
|
||||
|
||||
/* footer */
|
||||
|
||||
#footer { margin: 100px 0; color: #aaa; }
|
||||
#footer a { color: #aaa; }
|
||||
#footer a:hover { color: #666; }
|
||||
|
||||
|
||||
/* utils */
|
||||
|
||||
.clear { clear: both; }
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
|
||||
body { padding-top: 50px; }
|
||||
|
||||
/* header */
|
||||
|
||||
#rtfd-header { position: absolute; top: 0; left: 0; width: 100%; font: 16px/20px "ff-meta-web-pro-1","ff-meta-web-pro-2", Arial, "Helvetica Neue", sans-serif; height: 50px; min-width: 780px; background: #465158; overflow: hidden; text-align: left; }
|
||||
#rtfd-header ul { margin: 0; padding: 0; list-style: none; }
|
||||
|
||||
/* header title */
|
||||
.rtfd-header-title h1 { font-size: 20px; padding: 5px 20px; color: #fff; }
|
||||
|
||||
/* header search */
|
||||
.rtfd-header-search { position: absolute; top: 10px; left: 230px; }
|
||||
.rtfd-header-search input { padding: 0 5px; margin: 0; height: 25px; font-size: 14px; float: left; -moz-border-radius: 0; -webkit-border-radius: 0; border: none; }
|
||||
.rtfd-header-search input[type="text"] { -moz-border-radius-topleft: 3px; -moz-border-radius-bottomleft: 3px; -webkit-border-top-left-radius: 3px; -webkit-border-bottom-left-radius: 3px; width: 220px; }
|
||||
.rtfd-header-search input[type="submit"] { font-family: "ff-meta-web-pro-1", "ff-meta-web-pro-2", Arial, "Helvetica Neue", sans-serif; -moz-border-radius-topright: 3px; -moz-border-radius-bottomright: 3px; -webkit-border-top-right-radius: 3px; -webkit-border-bottom-right-radius: 3px; padding: 0 12px; background: #e6e6e6 url(../images/gradient.png) repeat-x bottom left; font-weight: bold; color: #666; }
|
||||
.rtfd-header-search input[type="submit"]:hover { text-shadow: 0 1px 1px rgba(0, 0, 0, 0.5); background-color: #8ECC4C; color: #fff; }
|
||||
|
||||
/* header nav */
|
||||
.rtfd-header-nav { position: absolute; top: 0; right: 10px; }
|
||||
.rtfd-header-nav ul li { float: left; }
|
||||
.rtfd-header-nav ul li a { display: block; text-decoration: none; background: url(../images/gradient.png) bottom left repeat-x #697983; padding: 15px; color: #fff; }
|
||||
.rtfd-header-nav ul li a:hover { background-color: #8CA1AF; }
|
||||
.rtfd-header-nav ul li.active a, .header-nav ul li.active a:hover { background-color: #BAC7CF; }
|
|
@ -15,3 +15,4 @@ django-extensions
|
|||
-e git+http://github.com/ericflo/django-pagination.git#egg=pagination
|
||||
-e hg+http://bitbucket.org/ubernostrum/django-profiles/#egg=profiles
|
||||
-e git+http://github.com/nathanborror/django-registration.git#egg=django-registration
|
||||
-e git+http://github.com/nathanborror/django-basic-apps.git#egg=django-basic-apps
|
||||
|
|
|
@ -36,7 +36,7 @@ class Project(models.Model):
|
|||
return self.name
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('projects_detail', args=[self.user.username, self.slug, ''])
|
||||
return reverse('projects_detail', args=[self.user.username, self.slug])
|
||||
|
||||
def user_doc_path(self):
|
||||
return os.path.join(settings.DOCROOT, self.user.username, self.slug)
|
||||
|
@ -182,7 +182,6 @@ class File(models.Model):
|
|||
def filename(self):
|
||||
return os.path.join(
|
||||
self.project.conf.path,
|
||||
self.project.slug,
|
||||
'%s.rst' % self.denormalized_path
|
||||
)
|
||||
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
Contents:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:glob:
|
||||
|
||||
{{ project.slug }}/*
|
||||
{% load projects_tags %}
|
||||
{% for file in project|annotated_tree %}
|
||||
{{ file.denormalized_path }}
|
||||
{% endfor %}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
from django import template
|
||||
|
||||
register = template.Library()
|
||||
|
||||
@register.filter
|
||||
def top_level_files(project):
|
||||
return project.files.filter(parent__isnull=True)
|
||||
|
||||
@register.filter
|
||||
def annotated_tree(project, max_depth=99):
|
||||
annotated = []
|
||||
def walk_tree(qs, depth=1):
|
||||
for obj in qs:
|
||||
obj.depth = depth
|
||||
annotated.append(obj)
|
||||
if depth < max_depth:
|
||||
walk_tree(obj.children.order_by('ordering'), depth+1)
|
||||
walk_tree(project.files.filter(parent__isnull=True).order_by('ordering'))
|
||||
return annotated
|
|
@ -17,6 +17,10 @@ urlpatterns = patterns('projects.views.public',
|
|||
'project_index',
|
||||
name='project_tag_detail',
|
||||
),
|
||||
url(r'^(?P<username>\w+)/(?P<project_slug>[-\w]+)/$',
|
||||
'project_detail',
|
||||
name='projects_detail'
|
||||
),
|
||||
url(r'^(?P<username>\w+)/$',
|
||||
'project_index',
|
||||
name='projects_user_list'
|
||||
|
|
|
@ -85,10 +85,12 @@ INSTALLED_APPS = (
|
|||
'south',
|
||||
'taggit',
|
||||
'django_extensions',
|
||||
'basic.flagging',
|
||||
|
||||
# our apps
|
||||
'projects',
|
||||
'core',
|
||||
'watching',
|
||||
)
|
||||
|
||||
|
||||
|
@ -99,4 +101,3 @@ EMAIL_USE_TLS = True
|
|||
EMAIL_HOST = 'golem'
|
||||
EMAIL_HOST_USER = 'no-reply@readthedocs.com'
|
||||
EMAIL_PORT = 25
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
<!-- css -->
|
||||
<link rel="stylesheet" href="{{ MEDIA_URL }}css/core.css">
|
||||
<link rel="stylesheet" href="{{ MEDIA_URL }}css/header.css">
|
||||
|
||||
<!-- js -->
|
||||
|
||||
|
@ -43,6 +44,20 @@
|
|||
</div>
|
||||
<!-- END content-->
|
||||
|
||||
<!-- BEGIN footer-->
|
||||
<div id="footer">
|
||||
<div class="wrapper">
|
||||
|
||||
<hr>
|
||||
|
||||
{% block footer-content %}
|
||||
2010. Created by <a href="http://ericholscher.com/">Eric Holscher</a>, <a href="http://charlesleifer.com/">Charles Leifer</a>, and <a href="http://bobbygrace.info/">Bobby Grace</a> for the 2010 <a href="http://djangodash.com/">Django Dash</a>.
|
||||
{% endblock %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- END footer-->
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
4
urls.py
4
urls.py
|
@ -7,9 +7,9 @@ admin.autodiscover()
|
|||
urlpatterns = patterns('',
|
||||
url(r'^accounts/', include('registration.backends.default.urls')),
|
||||
url(r'^dashboard/', include('projects.urls.private')),
|
||||
url(r'^projects/(?P<username>\w+)/(?P<project_slug>[-\w]+)/(?P<filename>.*)$',
|
||||
url(r'^projects/(?P<username>\w+)/(?P<project_slug>[-\w]+)/docs/(?P<filename>.*)$',
|
||||
'core.views.serve_docs',
|
||||
name='projects_detail'
|
||||
name='docs_detail'
|
||||
),
|
||||
url(r'render_header/',
|
||||
'core.views.render_header',
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
from watching.models import PageView
|
||||
from django.contrib import admin
|
||||
|
||||
admin.site.register(PageView)
|
|
@ -0,0 +1,11 @@
|
|||
from django.db import models
|
||||
from projects.models import Project
|
||||
|
||||
class PageView(models.Model):
|
||||
project = models.ForeignKey(Project, related_name='page_views')
|
||||
url = models.CharField(max_length=255)
|
||||
count = models.IntegerField(default=1)
|
||||
|
||||
|
||||
def __unicode__(self):
|
||||
return u"Page views for %s's url %s" % (self.project, self.url)
|
|
@ -0,0 +1,67 @@
|
|||
from django.conf import settings
|
||||
from django.test import TestCase
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
import json
|
||||
|
||||
from projects.models import Conf
|
||||
|
||||
data = """
|
||||
{
|
||||
"before": "5aef35982fb2d34e9d9d4502f6ede1072793222d",
|
||||
"repository": {
|
||||
"url": "http://github.com/beetletweezers/tweezers",
|
||||
"name": "github",
|
||||
"description": "You're lookin' at it.",
|
||||
"watchers": 5,
|
||||
"forks": 2,
|
||||
"private": 1,
|
||||
"owner": {
|
||||
"email": "chris@ozmm.org",
|
||||
"name": "defunkt"
|
||||
}
|
||||
},
|
||||
"commits": [
|
||||
{
|
||||
"id": "41a212ee83ca127e3c8cf465891ab7216a705f59",
|
||||
"url": "http://github.com/defunkt/github/commit/41a212ee83ca127e3c8cf465891ab7216a705f59",
|
||||
"author": {
|
||||
"email": "chris@ozmm.org",
|
||||
"name": "Chris Wanstrath"
|
||||
},
|
||||
"message": "okay i give in",
|
||||
"timestamp": "2008-02-15T14:57:17-08:00",
|
||||
"added": ["filepath.rb"]
|
||||
},
|
||||
{
|
||||
"id": "de8251ff97ee194a289832576287d6f8ad74e3d0",
|
||||
"url": "http://github.com/defunkt/github/commit/de8251ff97ee194a289832576287d6f8ad74e3d0",
|
||||
"author": {
|
||||
"email": "chris@ozmm.org",
|
||||
"name": "Chris Wanstrath"
|
||||
},
|
||||
"message": "update pricing a tad",
|
||||
"timestamp": "2008-02-15T14:36:34-08:00"
|
||||
}
|
||||
],
|
||||
"after": "de8251ff97ee194a289832576287d6f8ad74e3d0",
|
||||
"ref": "refs/heads/master"
|
||||
}
|
||||
"""
|
||||
|
||||
class Basic(TestCase):
|
||||
fixtures=['eric', 'test_data']
|
||||
|
||||
def setUp(self):
|
||||
settings.CELERY_ALWAYS_EAGER = True
|
||||
|
||||
def tearDown(self):
|
||||
settings.CELERY_ALWAYS_EAGER = False
|
||||
|
||||
def test_github(self):
|
||||
resp = self.client.post('/github', {'payload': data})
|
||||
self.assertEqual(Conf.objects.count(), 1)
|
||||
conf = Conf.objects.all()[0]
|
||||
self.assertEqual(conf.theme, 'default')
|
||||
self.assertTrue(conf.path is not None)
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
from django.conf.urls.defaults import *
|
||||
|
||||
urlpatterns = patterns('watching.views',
|
||||
url(r'^$',
|
||||
'project_index',
|
||||
name='projects_list'
|
||||
),
|
||||
url(r'^tags/$',
|
||||
'tag_index',
|
||||
name='project_tag_list',
|
||||
),
|
||||
url(r'^search/',
|
||||
'search',
|
||||
name='search',
|
||||
),
|
||||
url(r'^tags/(?P<tag>\w+)/$',
|
||||
'project_index',
|
||||
name='project_tag_detail',
|
||||
),
|
||||
url(r'^projects/(?P<username>\w+)/(?P<project_slug>[-\w]+)/$',
|
||||
'project_detail',
|
||||
name='projects_detail'
|
||||
),
|
||||
url(r'^(?P<username>\w+)/$',
|
||||
'project_index',
|
||||
name='projects_user_list'
|
||||
),
|
||||
)
|
|
@ -0,0 +1,33 @@
|
|||
from django.conf import settings
|
||||
from django.http import HttpResponse
|
||||
from django.shortcuts import render_to_response
|
||||
from django.template import RequestContext
|
||||
from django.views.decorators.csrf import csrf_view_exempt
|
||||
from django.views.static import serve
|
||||
|
||||
import json
|
||||
|
||||
from projects.models import Project
|
||||
from projects.tasks import update_docs
|
||||
from projects.utils import find_file
|
||||
|
||||
|
||||
@csrf_view_exempt
|
||||
def github_build(request):
|
||||
obj = json.loads(request.POST['payload'])
|
||||
name = obj['repository']['name']
|
||||
url = obj['repository']['url']
|
||||
project = Project.objects.get(repo=url)
|
||||
update_docs.delay(pk=project.pk)
|
||||
return HttpResponse('Build Started')
|
||||
|
||||
def serve_docs(request, username, project_slug, filename):
|
||||
proj = Project.objects.get(slug=project_slug, user__username=username)
|
||||
if not filename:
|
||||
filename = "index.html"
|
||||
filename = filename.rstrip('/')
|
||||
return serve(request, filename, proj.full_html_path)
|
||||
|
||||
def render_header(request):
|
||||
return render_to_response('core/header.html', {},
|
||||
context_instance=RequestContext(request))
|
Loading…
Reference in New Issue