Added a basic front-end for adding subprojects.

rtd2
Eric Holscher 2011-10-16 19:11:12 -07:00
parent 5d670a97eb
commit d21e880da2
9 changed files with 133 additions and 24 deletions

View File

@ -216,3 +216,23 @@ def build_upload_html_form(project):
choices=choices,
)
return type('UploadHTMLForm', (BaseUploadHTMLForm,), attrs)
class SubprojectForm(forms.Form):
subproject = forms.CharField()
def __init__(self, *args, **kwargs):
self.parent = kwargs.pop('parent', None)
super(SubprojectForm, self).__init__(*args, **kwargs)
def clean_subproject(self):
subproject_name = self.cleaned_data['subproject']
subproject_qs = Project.objects.filter(name=subproject_name)
if not subproject_qs.exists():
raise forms.ValidationError("Project %s does not exist" % subproject_name)
self.subproject = subproject_qs[0]
return subproject_name
def save(self):
relationship = self.parent.add_subproject(self.subproject)
return relationship

View File

@ -31,6 +31,10 @@ class ProjectRelationship(models.Model):
def __unicode__(self):
return "%s -> %s" % (self.parent, self.child)
#HACK
def get_absolute_url(self):
return "http://%s.readthedocs.org/docs/%s/en/latest/" % (self.parent.slug, self.child.slug)
class Project(models.Model):
#Auto fields
pub_date = models.DateTimeField(auto_now_add=True)
@ -377,6 +381,19 @@ class Project(models.Model):
return self.default_version
return 'latest'
def add_subproject(self, child):
subproject, created = ProjectRelationship.objects.get_or_create(
parent=self,
child=child,
)
return subproject
def remove_subproject(self, child):
ProjectRelationship.objects.filter(
parent=self,
child=child).delete()
return
class FileManager(models.Manager):
def live(self, *args, **kwargs):

View File

@ -49,6 +49,10 @@ urlpatterns = patterns('projects.views.private',
'project_delete',
name='projects_delete'
),
url(r'^(?P<project_slug>[-\w]+)/subprojects/$',
'project_subprojects',
name='projects_subprojects'
),
url(r'^(?P<project_slug>[-\w]+)/add/$',
'file_add',
name='projects_file_add'

View File

@ -18,7 +18,8 @@ from builds.forms import AliasForm
from projects import constants
from projects.forms import (FileForm, CreateProjectForm,
ImportProjectForm, FileRevisionForm,
build_versions_form, build_upload_html_form)
build_versions_form, build_upload_html_form,
SubprojectForm)
from projects.models import Project, File
from projects.tasks import unzip_files
@ -363,10 +364,6 @@ def upload_html(request, project_slug):
@login_required
def edit_alias(request, project_slug, id=None):
"""
The view for creating a new project where the docs will be hosted
as objects and edited through the site
"""
proj = get_object_or_404(Project.objects.all(), slug=project_slug)
if id:
alias = proj.aliases.get(pk=id)
@ -385,10 +382,6 @@ def edit_alias(request, project_slug, id=None):
@login_required
def list_alias(request, project_slug):
"""
The view for creating a new project where the docs will be hosted
as objects and edited through the site
"""
proj = get_object_or_404(Project.objects.all(), slug=project_slug)
return object_list(
request,
@ -396,3 +389,25 @@ def list_alias(request, project_slug):
template_object_name='alias',
template_name='projects/alias_list.html',
)
@login_required
def project_subprojects(request, project_slug):
project = get_object_or_404(request.user.projects.live(), slug=project_slug)
if not project.is_imported:
raise Http404
form = SubprojectForm(data=request.POST or None, parent=project)
if request.method == 'POST' and form.is_valid():
form.save()
project_dashboard = reverse('projects_manage', args=[project.slug])
return HttpResponseRedirect(project_dashboard)
subprojects = project.subprojects.all()
return render_to_response(
'projects/project_subprojects.html',
{'form': form, 'project': project, 'subprojects': subprojects},
context_instance=RequestContext(request)
)

View File

@ -2,7 +2,7 @@
<html lang="en">
<head>
<!-- meta -->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="icon" type="image/png" href="{{ MEDIA_URL }}images/favicon.png">
@ -15,7 +15,7 @@
{% block extra_links %}{% endblock %}
<!-- js -->
<!-- jquery -->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.4/jquery-ui.min.js"></script>
@ -23,7 +23,7 @@
<!-- typekit -->
<script type="text/javascript" src="http://use.typekit.com/xgl8ypn.js"></script>
<script type="text/javascript">try{Typekit.load();}catch(e){}</script>
<script type="text/javascript" src="{{ MEDIA_URL }}javascript/rtd.js"></script>
@ -63,13 +63,13 @@
<!-- BEGIN footer-->
<div id="footer">
<div class="wrapper">
<hr>
{% block footer-content %}
<p>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>.
<p>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>.
<a href="http://github.com/rtfd/readthedocs.org">Github</a> | <a href="http://read-the-docs.readthedocs.org">Docs</a>. Sponsored by <a href="http://revsys.com">RevSys</a>, <a href="http://www.python.org/psf/">The Python Software Foundation</a>, and <a href="http://blog.mozilla.com/webdev/">Mozilla Web Dev</a>.</p>
<a href="http://github.com/rtfd/readthedocs.org">Github</a> | <a href="http://read-the-docs.readthedocs.org">Docs</a>. Sponsored by <a href="http://revsys.com">RevSys</a>, <a href="http://www.python.org/psf/">The Python Software Foundation</a>, and <a href="http://blog.mozilla.com/webdev/">Mozilla Web Dev</a>.</p>
{% endblock %}
</div>
@ -94,12 +94,14 @@
$('.rtfd-header-search input:text').autocomplete({
source: '{% url search_autocomplete %}',
minLength: 2,
open: function(event, ui) {
ac_top = $('.ui-autocomplete').css('top');
$('.ui-autocomplete').css({'width': '233px', 'top': ac_top + 10 });
open: function(event, ui) {
ac_top = $('.ui-autocomplete').css('top');
$('.ui-autocomplete').css({'width': '233px', 'top': ac_top + 10 });
}
});
{% block footerjs %}{% endblock %}
</script>
<!-- END google analytics -->

View File

@ -33,6 +33,7 @@
<li {% block editing-option-manage %}{% endblock %}><a href="{% url projects_manage project.slug %}">Manage Files</a></li>
{% endif %}
<li {% block editing-option-edit-proj %}{% endblock %}><a href="{% url projects_edit project.slug %}">Edit Project</a></li>
<li><a href="{% url projects_subprojects project.slug %}">Subprojects</a></li>
{% endif %}
{% if project.get_latest_build %}

View File

@ -18,6 +18,7 @@
<!-- <input type="submit" value="Go"> -->
</form>
</div>
<br>
<!-- BEGIN search bar -->
@ -59,20 +60,17 @@
<p> This project has more information available about it on <a href="{{ project.django_packages_url }}">Django Packages!</a></p>
{% endif %}
{% comment %}
{% if project.subprojects.count %}
{% if project.subprojects.exists %}
<h3>Sub Projects</h3>
<p>
{% for project in project.subprojects.all %}
<li><a href="{{ project.get_docs_url }}">{{ project.child }}</a></li>
{% for rel in project.subprojects.all %}
<li><a href="{{ rel.get_absolute_url }}">{{ rel.child }}</a></li>
{% empty %}
<span class="quiet">No tags</span>
{% endfor %}
</p>
{% endif %}
{% endcomment %}
<h3>Last Built</h3>
<p>{{ project.modified_date|timesince }} ago</p>

View File

@ -34,6 +34,11 @@
{% if project.has_aliases %}
<li><a href="{% url projects_alias_list project.slug %}" rel="nofollow,noindex">Aliases</a></li>
{% endif %}
{% comment %}
<li><a href="{% url projects_subprojects project.slug %}">Subprojects</a></li>
{% endcomment %}
<li><a href="{% url projects_edit project.slug %}">Edit</a></li>
<li><a href="{{ project.get_docs_url }}">View Docs</a></li>
</ul>

View File

@ -0,0 +1,47 @@
{% extends "projects/base_project_editing.html" %}
{% block title %}Edit Subprojects{% endblock %}
{% block editing-option-edit-proj %}class="active"{% endblock %}
{% block content-header %}<h1>Edit Subprojects</h1>{% endblock %}
{% block content %}
<p class="help_text">
This allows you to add subprojects to your project. This allows them to live in the same namespace in the URLConf for a subdomain or CNAME.
</p>
<h3> Existing Subprojects </h3>
<p>
<ul>
{% for relationship in subprojects %}
<li>
<a href="{{ relationship.get_absolute_url }}">
{{ relationship.child }}
</a>
</li>
{% endfor %}
</ul>
<p>
Choose which project you would like to add as a subproject.
</p>
<form method="post" action=".">{% csrf_token %}
{{ form.as_p }}
<p>
<input style="display: inline;" type="submit" value="Submit">
</p>
</form>
{% endblock %}
{% block footerjs %}
$('#id_subproject').autocomplete({
source: '{% url search_autocomplete %}',
minLength: 2,
open: function(event, ui) {
ac_top = $('.ui-autocomplete').css('top');
$('.ui-autocomplete').css({'width': '233px', 'top': ac_top + 10 });
}
});
{% endblock %}