Add new fancy detail pages.

rtd2
Eric Holscher 2012-12-17 22:07:12 -08:00
parent 5129a8391f
commit acf27880f6
12 changed files with 336 additions and 143 deletions

View File

@ -76,7 +76,7 @@ label { display: block; margin-bottom: 4px; font-weight: bold; color: #444; }
#content { padding-top: 50px; }
#content ul { margin-bottom: 20px; }
#content #project_description { background-color: #eee; }
#content #project_description { margin-bottom: 20px; }
/* Commenting this for now. Want to figure out how to make it look sane with small amounts of text. */
/* #content p { background-color: #eee; } */
@ -141,6 +141,10 @@ i { display: inline-block; padding:0; margin:0; padding-right:6px; position: rel
/* search */
.search { border-bottom: solid 1px #bfbfbf; }
.search input[type=text] { float: left; margin-right: 10px; padding: 8px 10px; }
.search input[type=submit] { margin-top: 0; }
.filter { margin-bottom: 1em; }
.filter dd { display: inline-block; margin-right: 0.75em; }
.filter dd small { opacity: 0.7; }
@ -325,6 +329,34 @@ p.build-missing { font-size: .8em; color: #9d9a55; margin: 0 0 3px; }
.clearfix:after, .wrapper:after { content: "\0020"; display: block; height: 0; clear: both; visibility: hidden; overflow: hidden; }
.clearfix, .wrapper { display: block; }
/* project detail */
.project_detail .module {
float: left;
width: 500px;
}
.project_detail .module .help_text {
font-size: 14px;
}
.project_detail .help_text em {
color: #666;
}
.project_detail .build_a_version {
margin-top: 40px;
}
.project_detail .project_details {
float: right;
width: 250px;
margin-top: 34px;
}
.project_detail .project_details h3 {
margin-bottom: 0;
font-size: 16px;
}
.when-editing { opacity: 0; -webkit-transition:opacity 0.2s ease-in-out; -moz-transition:opacity 0.2s ease-in-out; -ms-transition:opacity 0.2s ease-in-out; -o-transition:opacity 0.2s ease-in-out; transition:opacity 0.2s ease-in-out; pointer-events:none; -webkit-user-select:none; }
.editing .when-editing { opacity: 1; }
@ -365,4 +397,3 @@ select.dropdown { display: none; }
.dropdown > ul.js-open { display:block; }
.dropdown > ul:before { content:' '; visibility: visible; border:8px solid transparent; border-bottom-color: #465158; position:absolute; top:-16px; left:104px; }

View File

@ -12,10 +12,17 @@ ANY_REPO = (
BUILD_TYPES = ANY_REPO + constants.BUILD_TYPES
class VersionSlugFilter(django_filters.FilterSet):
slug = django_filters.CharFilter(label=_("Name"), name='slug', lookup_type='icontains')
tag = django_filters.CharFilter(label=_("Tag"), name='tags', lookup_type='name__icontains')
class Meta:
model = Version
fields = ['slug', 'tag']
class VersionFilter(django_filters.FilterSet):
project = django_filters.CharFilter(name='project__name', lookup_type="icontains")
slug= django_filters.CharFilter(label=_("Slug"), name='slug', lookup_type='icontains')
slug = django_filters.CharFilter(label=_("Name"), name='slug', lookup_type='icontains')
class Meta:
model = Version

View File

@ -1,9 +1,8 @@
from django import forms
from builds.models import VersionAlias
from builds.models import VersionAlias, Version
from projects.models import Project
class AliasForm(forms.ModelForm):
class Meta:
model = VersionAlias
@ -12,3 +11,10 @@ class AliasForm(forms.ModelForm):
super(AliasForm, self).__init__(instance=instance, *args, **kwargs)
if instance:
self.fields['project'].queryset = Project.objects.filter(pk=instance.project.pk)
class VersionForm(forms.ModelForm):
class Meta:
model = Version
fields = ['active', 'privacy_level', 'tags']

View File

@ -2,6 +2,7 @@ from django.db import models
from django.utils.translation import ugettext_lazy as _, ugettext
from guardian.shortcuts import assign, get_objects_for_user
from taggit.managers import TaggableManager
from projects.models import Project
from projects import constants
@ -80,6 +81,7 @@ class Version(models.Model):
choices=constants.PRIVACY_CHOICES, default='public',
help_text=_("Level of privacy for this Version."))
tags = TaggableManager(blank=True)
objects = VersionManager()
class Meta:

View File

@ -37,6 +37,10 @@ urlpatterns = patterns('projects.views.private',
'project_edit',
name='projects_edit'
),
url(r'^(?P<project_slug>[-\w]+)/version/(?P<version_slug>[-\w.]+)/$',
'project_version_detail',
name='project_version_detail'
),
url(r'^(?P<project_slug>[-\w]+)/versions/$',
'project_versions',
name='projects_versions'

View File

@ -17,6 +17,14 @@ urlpatterns = patterns('projects.views.public',
'search_autocomplete',
name='search_autocomplete',
),
url(r'^autocomplete/version/(?P<project_slug>[-\w]+)/$',
'version_autocomplete',
name='version_autocomplete',
),
url(r'^autocomplete/filter/version/(?P<project_slug>[-\w]+)/$',
'version_filter_autocomplete',
name='version_filter_autocomplete',
),
url(r'^tags/(?P<tag>[-\w]+)/$',
'project_index',
name='projects_tag_detail',

View File

@ -13,7 +13,7 @@ from django.views.generic.list_detail import object_list
from guardian.shortcuts import assign
from builds.forms import AliasForm
from builds.forms import AliasForm, VersionForm
from builds.filters import VersionFilter
from builds.models import Version
from projects.forms import (ImportProjectForm, build_versions_form,
@ -103,6 +103,24 @@ def project_versions(request, project_slug):
context_instance=RequestContext(request)
)
@login_required
def project_version_detail(request, project_slug, version_slug):
project = get_object_or_404(request.user.projects.live(), slug=project_slug)
version = get_object_or_404(project.versions.all(), slug=version_slug)
form = VersionForm(request.POST or None, instance=version)
if request.method == 'POST' and form.is_valid():
form.save()
url = reverse('projects_versions', args=[project.slug])
return HttpResponseRedirect(url)
return render_to_response(
'projects/project_version_detail.html',
{'form': form, 'project': project, 'version': version},
context_instance=RequestContext(request)
)
@login_required
def project_delete(request, project_slug):
"""

View File

@ -13,6 +13,8 @@ from guardian.decorators import permission_required_or_403
from guardian.shortcuts import get_objects_for_user
from taggit.models import Tag
from builds.filters import VersionSlugFilter
from builds.models import Version
from core.views import serve_docs
from projects.models import Project
from projects.utils import highest_version
@ -52,11 +54,13 @@ def project_detail(request, project_slug):
queryset = Project.objects.protected(request.user)
project = get_object_or_404(queryset, slug=project_slug)
versions = project.versions.public(request.user, project)
filter = VersionSlugFilter(request.GET, queryset=versions)
return render_to_response(
'projects/project_detail.html',
{
'project': project,
'versions': versions,
'filter': filter,
},
context_instance=RequestContext(request),
)
@ -132,10 +136,51 @@ def search_autocomplete(request):
term = request.GET['term']
else:
raise Http404
queryset = Project.objects.live(name__icontains=term)[:20]
queryset = Project.objects.public(request.user).filter(name__icontains=term)[:20]
project_names = queryset.values_list('name', flat=True)
json_response = json.dumps(list(project_names))
return HttpResponse(json_response, mimetype='text/javascript')
def version_autocomplete(request, project_slug):
"""
return a json list of version names
"""
queryset = Project.objects.protected(request.user)
project = get_object_or_404(queryset, slug=project_slug)
versions = Version.objects.public(request.user)
if 'term' in request.GET:
term = request.GET['term']
else:
raise Http404
version_queryset = versions.filter(slug__icontains=term)[:20]
names = version_queryset.values_list('slug', flat=True)
json_response = simplejson.dumps(list(names))
return HttpResponse(json_response, mimetype='text/javascript')
def version_filter_autocomplete(request, project_slug):
queryset = Project.objects.protected(request.user)
project = get_object_or_404(queryset, slug=project_slug)
versions = Version.objects.public(request.user)
filter = VersionSlugFilter(request.GET, queryset=versions)
format = request.GET.get('format', 'json')
if format == 'json':
names = filter.qs.values_list('slug', flat=True)
json_response = simplejson.dumps(list(names))
return HttpResponse(json_response, mimetype='text/javascript')
elif format == 'html':
return render_to_response(
'core/version_list.html',
{
'project': project,
'versions': versions,
'filter': filter,
},
context_instance=RequestContext(request),
)
else:
raise HttpResponse(status=400)

View File

@ -1,5 +1,4 @@
{% load i18n %}
{% load markup %}
{% if project.description %}
@ -11,51 +10,61 @@
</div>
{% endif %}
<!-- BEGIN search bar -->
<h3>{% trans "Search this project" %}</h3>
<div>
<div class="search">
<form action="{% url haystack_project %}" method="GET">
<input type="text" name="q" value="" id="id_site_search">
<input type="text" name="q" value="" placeholder="{% blocktrans %}Search {{ project }}{% endblocktrans %}" id="id_site_search">
<input type="hidden" name="selected_facets" value="project_exact:{{ project.name }}">
<!-- <input type="submit" value="Go"> -->
<input type="submit" value="Search">
</form>
</div>
<br>
<!-- BEGIN search bar -->
<h3>{% trans "Project Privacy Level" %}</h3>
<div id="privacy_level">
<p>
{{ project.get_privacy_level_display }}
</p>
</div>
<!-- END search bar -->
{% if versions %}
<div class="module">
<div class="module-header">
<h3>{% trans "Versions" %}</h3>
</div>
<p>
{% for version in versions %}
<div style="float: left;" class="version_left">
<div class="module-list">
{% comment %}
<div class="filter_form">
<form id="filter_form">
{{ filter.form }}
<input type="submit" value="Filter">
</form>
</div>
{% endcomment %}
<div class="module-list-wrapper">
<ul>
{% for version in filter %}
<li class="module-item col-span">
{% if version.uploaded or version.built %}
{# Link to the docs #}
<a href="{{ version.get_absolute_url }}">{{ version.slug }}</a>
<a class="module-item-title" href="{{ version.get_absolute_url }}">{{ version.slug }}
{% if request.user in project.users.all %}
({{ version.get_privacy_level_display }})
<span class="right-menu quiet">{{ version.get_privacy_level_display }}</span>
{% endif %}
</a>
{% else %}
{% blocktrans with version.slug as slug %}{{ slug }} (Build Failed){% endblocktrans %}
{% endif %}
</div>
<div style="clear: both;"></div>
{% if request.user in project.users.all %}
<ul class="module-item-menu">
<li><a href="{% url project_version_detail project.slug version.slug %}">Edit</a></li>
</ul>
{% endif %}
</li>
{% endfor %}
</p>
</ul>
</div>
</div>
<div class="build_a_version">
<h3>Build a version</h3>
<p>
<div style="float: left; margin-right: 5px;" class="version_right">
<form method="post" action="{% url generic_build project.pk %}">
<select id="id_version" name="version_slug">
@ -66,11 +75,17 @@
<input type="submit" value="Build">
</form>
</div>
</p>
<div style="clear: both;"></div>
</div>
</div>{# END .module #}
{% endif %}
<div class="project_details">
<h3>{% trans "Project Privacy Level" %}</h3>
<div id="privacy_level">
<p>
{{ project.get_privacy_level_display }}
</p>
</div>
<h3>{% trans "Short URLs" %}</h3>
<p>
@ -99,11 +114,9 @@
</ul>
{% endif %}
<h3>{% trans "Last Built" %}</h3>
<p>{{ project.modified_date|timesince }} ago</p>
{% if project.repo %}
<h3>{% trans "Repository" %}</h3>
<p>{{ project.repo }}</p>
@ -127,7 +140,6 @@
</p>
{% endif %}
{% if project.get_latest_revisions.count %}
<h3>{% trans "Latest Revisions" %}</h3>
<ul>
@ -172,6 +184,7 @@
</div>
<!-- END projects list -->
{% endif %}
</div>{# END .project_details #}
{% if request.user not in project.users.all %}
{% include "projects/includes/flagging.html" %}

View File

@ -0,0 +1,18 @@
<div class="module-list-wrapper">
<ul>
{% for version in filter %}
<li class="module-item">
{# Link to the docs #}
<a class="module-item-title" href="{{ version.get_absolute_url }}">{{ version.slug }}</a>
{% if request.user in project.users.all %}
<span class="right-menu quiet">{{ version.get_privacy_level_display }}</span>
{% endif %}
{% if request.user in project.users.all %}
<ul class="module-item-menu">
<li><a href="{% url project_version_detail project.slug version.slug %}">Add tags</a></li>
</ul>
{% endif %}
</li>
{% endfor %}
</ul>
</div>

View File

@ -0,0 +1,23 @@
{% extends "projects/base_project.html" %}
{% load i18n %}
{% block title %}{{ version.name }}{% endblock %}
{% block project_editing %}
{% with versions_active="active" %}
{% include "core/project_bar.html" %}
{% endwith %}
{% endblock %}
{% block content-header %}<h1>{% blocktrans with version.name as version_name %}{{ version_name }}{% endblocktrans %}</h1>{% endblock %}
{% block content %}
<h3> {{ version.slug }} </h3>
<form method="post" action=".">
{% csrf_token %}
{{ form.as_p }}
<input type="submit">
</form>
{% endblock %}

View File

@ -13,22 +13,40 @@
{% trans "If you are having trouble building older versions of your Documentation, then you can" %} <a href="{% url projects_upload_html project.slug %}">{% trans "Upload a Zip file of HTML" %}</a> {% trans "instead. This is to support versions that may not build anymore with current Sphinx, or to support plugins and extensions that we may not have on our server." %}
</p>
<p>
{% trans "Choose which versions you would like to publish besides the latest revision." %}
</p>
<form method="post" action=".">{% csrf_token %}
{% for field in form %}
{% if forloop.first %}
{# For choosing the default version #}
<h5> {{ field.label }} </h5>
{# This is a custom form listing the possible active versions, to make 1 the default #}
<h2> {{ field.label }} </h2>
{{ field }}
<p>
{% trans "Choose the version that / will redirect to." %}
</p>
{% else %}
{% if field.label != "privacy" %}
<h3> {{ field.label}} </h3>
{% if forloop.counter0 == 1 %}
<h2> {% trans "Choose Active Verisons" %} </h2>
<p>
{% trans "Active versions below will show up on the site." %}
</p>
{% endif %}
{% if field.label == "privacy" %}
{{ field }}
{% comment %}
{% elif field.label == "tags" %}
Tags: {{ field }}
{% endcomment %}
{% else %}
{{ field }}
{# This is a custom field with a label of the version, and a value of a checkbox denoting if it is active #}
<h3> <a href="{% url project_version_detail project.slug field.label %}"> {{ field.label}}</a> </h3>
Active {{ field }}
{% endif %}
{% endif %}
<br>