From d21e880da20154bc19c59a5e4b1dd4783fa11ab3 Mon Sep 17 00:00:00 2001 From: Eric Holscher Date: Sun, 16 Oct 2011 19:11:12 -0700 Subject: [PATCH] Added a basic front-end for adding subprojects. --- readthedocs/projects/forms.py | 20 ++++++++ readthedocs/projects/models.py | 17 +++++++ readthedocs/projects/urls/private.py | 4 ++ readthedocs/projects/views/private.py | 33 +++++++++---- readthedocs/templates/base.html | 20 ++++---- readthedocs/templates/core/project_bar.html | 1 + .../templates/core/project_details.html | 10 ++-- .../templates/projects/project_dashboard.html | 5 ++ .../projects/project_subprojects.html | 47 +++++++++++++++++++ 9 files changed, 133 insertions(+), 24 deletions(-) create mode 100644 readthedocs/templates/projects/project_subprojects.html diff --git a/readthedocs/projects/forms.py b/readthedocs/projects/forms.py index bac123ac4..9052b21fc 100644 --- a/readthedocs/projects/forms.py +++ b/readthedocs/projects/forms.py @@ -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 diff --git a/readthedocs/projects/models.py b/readthedocs/projects/models.py index d7908d4ab..b9c03cd72 100644 --- a/readthedocs/projects/models.py +++ b/readthedocs/projects/models.py @@ -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): diff --git a/readthedocs/projects/urls/private.py b/readthedocs/projects/urls/private.py index 026d0655c..b269bb723 100644 --- a/readthedocs/projects/urls/private.py +++ b/readthedocs/projects/urls/private.py @@ -49,6 +49,10 @@ urlpatterns = patterns('projects.views.private', 'project_delete', name='projects_delete' ), + url(r'^(?P[-\w]+)/subprojects/$', + 'project_subprojects', + name='projects_subprojects' + ), url(r'^(?P[-\w]+)/add/$', 'file_add', name='projects_file_add' diff --git a/readthedocs/projects/views/private.py b/readthedocs/projects/views/private.py index c33e9ece5..d24e39cdf 100644 --- a/readthedocs/projects/views/private.py +++ b/readthedocs/projects/views/private.py @@ -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) + ) diff --git a/readthedocs/templates/base.html b/readthedocs/templates/base.html index 05324ea4b..23a382cba 100644 --- a/readthedocs/templates/base.html +++ b/readthedocs/templates/base.html @@ -2,7 +2,7 @@ - + @@ -15,7 +15,7 @@ {% block extra_links %}{% endblock %} - + @@ -23,7 +23,7 @@ - + @@ -63,13 +63,13 @@ +
@@ -59,20 +60,17 @@

This project has more information available about it on Django Packages!

{% endif %} -{% comment %} -{% if project.subprojects.count %} +{% if project.subprojects.exists %}

Sub Projects

- {% for project in project.subprojects.all %} -

  • {{ project.child }}
  • + {% for rel in project.subprojects.all %} +
  • {{ rel.child }}
  • {% empty %} No tags {% endfor %}

    {% endif %} -{% endcomment %} -

    Last Built

    {{ project.modified_date|timesince }} ago

    diff --git a/readthedocs/templates/projects/project_dashboard.html b/readthedocs/templates/projects/project_dashboard.html index 2611d2c66..fbe262c02 100644 --- a/readthedocs/templates/projects/project_dashboard.html +++ b/readthedocs/templates/projects/project_dashboard.html @@ -34,6 +34,11 @@ {% if project.has_aliases %}
  • Aliases
  • {% endif %} + + {% comment %} +
  • Subprojects
  • + {% endcomment %} +
  • Edit
  • View Docs
  • diff --git a/readthedocs/templates/projects/project_subprojects.html b/readthedocs/templates/projects/project_subprojects.html new file mode 100644 index 000000000..3a8f29787 --- /dev/null +++ b/readthedocs/templates/projects/project_subprojects.html @@ -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 %}

    Edit Subprojects

    {% endblock %} + +{% block content %} +

    + 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. +

    + +

    Existing Subprojects

    +

    +

    +

    + Choose which project you would like to add as a subproject. +

    +
    {% csrf_token %} + {{ form.as_p }} +

    + +

    +
    +{% 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 %}