diff --git a/media/css/core.css b/media/css/core.css index b02168877..56f14c95a 100644 --- a/media/css/core.css +++ b/media/css/core.css @@ -217,6 +217,10 @@ p.build-success { font-size: .8em; color: #108830; margin: 0 0 3px; } p.build-failure { font-size: .8em; color: #dc1020; margin: 0 0 3px; } p.build-missing { font-size: .8em; color: #9d9a55; margin: 0 0 3px; } +/* build page */ + +#build_list select { width: 10em; } + /* dashboard bar */ diff --git a/readthedocs/builds/filters.py b/readthedocs/builds/filters.py new file mode 100644 index 000000000..effbc2b0a --- /dev/null +++ b/readthedocs/builds/filters.py @@ -0,0 +1,29 @@ +import django_filters + +from builds import constants +from builds.models import Build, Version + + +ANY_REPO = ( + ('', 'Any'), +) + +BUILD_TYPES = ANY_REPO + constants.BUILD_TYPES + + +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') + + class Meta: + model = Version + fields = ['project', 'slug'] + +class BuildFilter(django_filters.FilterSet): + date = django_filters.DateRangeFilter(label="Build Date", name="date") + type = django_filters.ChoiceFilter(label="Build Type", choices=BUILD_TYPES) + + class Meta: + model = Build + fields = ['type', 'date', 'version', 'success'] + diff --git a/readthedocs/builds/views.py b/readthedocs/builds/views.py index 2087825d5..51bfa41d4 100644 --- a/readthedocs/builds/views.py +++ b/readthedocs/builds/views.py @@ -4,6 +4,7 @@ from django.shortcuts import get_object_or_404 from django.views.generic.list_detail import object_list, object_detail from builds.models import Build +from builds.filters import BuildFilter from projects.models import Project from taggit.models import Tag @@ -12,6 +13,7 @@ def build_list(request, project_slug=None, tag=None): """Show a list of builds. """ queryset = Build.objects.all() + filter = BuildFilter(request.GET, queryset=queryset) if tag: tag = get_object_or_404(Tag, slug=tag) @@ -28,6 +30,7 @@ def build_list(request, project_slug=None, tag=None): queryset=queryset, extra_context={ 'project': project, + 'filter': filter, 'tag': tag, 'active_builds': active_builds }, diff --git a/readthedocs/projects/filters.py b/readthedocs/projects/filters.py new file mode 100644 index 000000000..15f6aa6cd --- /dev/null +++ b/readthedocs/projects/filters.py @@ -0,0 +1,25 @@ +import django_filters + +from projects import constants +from projects.models import Project + +ANY_REPO = ( + ('', 'Any'), +) + +REPO_CHOICES = ANY_REPO + constants.REPO_CHOICES + +class ProjectFilter(django_filters.FilterSet): + name = django_filters.CharFilter(label="Name", name='name', lookup_type='icontains') + pub_date = django_filters.DateRangeFilter(label="Created Date", name="pub_date") + repo = django_filters.CharFilter(label="Repository URL", name='repo', lookup_type='icontains') + repo_type = django_filters.ChoiceFilter( + label="Repository", + name='repo', + lookup_type='icontains', + choices=REPO_CHOICES, + ) + + class Meta: + model = Project + fields = ['name', 'pub_date', 'repo', 'repo_type'] diff --git a/readthedocs/templates/base_filter.html b/readthedocs/templates/base_filter.html new file mode 100644 index 000000000..aa886f3b2 --- /dev/null +++ b/readthedocs/templates/base_filter.html @@ -0,0 +1,29 @@ +{% extends "base.html" %} + +{% load i18n %} + +{% block nav-dashboard %} class="active"{% endblock %} + +{% block project_editing %} + + +
+
+ +
+

Filter

+
+ +
+ +
    + {% block filter_bar %}{% endblock %} +
+
+ + +
+
+ + +{% endblock %} diff --git a/readthedocs/templates/builds/build_list.html b/readthedocs/templates/builds/build_list.html index 81c58aabe..59a01ca43 100644 --- a/readthedocs/templates/builds/build_list.html +++ b/readthedocs/templates/builds/build_list.html @@ -7,30 +7,40 @@ {% block title %}Builds{% endblock %} {% block content %} +
- {% autopaginate build_list 15 %} +
+ {{ filter.form.as_p }} + +
- -
-
+ {% autopaginate filter 15 %} -
-

{% trans "Recent Builds" %}

-
- -
-
-
    - {% include "core/build_list_detailed.html" %} -
-
-
+ +
+
+
+

{% trans "Recent Builds" %}

-
- - {% paginate %} +
+
+
    + {% with filter as build_list %} + {% include "core/build_list_detailed.html" %} + {% endwith %} +
+
+
+ +
+
+ + + {% paginate %} + +
{% endblock %} diff --git a/readthedocs/templates/core/filter_bar.html b/readthedocs/templates/core/filter_bar.html new file mode 100644 index 000000000..db401c78a --- /dev/null +++ b/readthedocs/templates/core/filter_bar.html @@ -0,0 +1,22 @@ +{% load i18n %} + + +
+
+ +
+

Filter

+
+ +
+ + +
    + {% block filter_bar %}{% endblock %} +
+
+ + +
+
+ diff --git a/readthedocs/templates/core/filter_list.html b/readthedocs/templates/core/filter_list.html new file mode 100644 index 000000000..3fcfdbc1d --- /dev/null +++ b/readthedocs/templates/core/filter_list.html @@ -0,0 +1,13 @@ +{% load i18n %} + + {% for obj in filter %} +
  • + +
  • + {% empty %} +
  • {% trans "No projects found" %}
  • + {% endfor %} diff --git a/readthedocs/templates/filter.html b/readthedocs/templates/filter.html new file mode 100644 index 000000000..48102bb12 --- /dev/null +++ b/readthedocs/templates/filter.html @@ -0,0 +1,43 @@ +{% extends "base_filter.html" %} + +{% load i18n %} + +{% load pagination_tags %} + +{% block title %}Filter{% endblock %} + +{% block filter_bar %} +
    + {{ filter.form.as_p }} + +
    +{% endblock %} + +{% block content %} + + + {% autopaginate filter 15 %} + + +
    +
    + +
    +

    {% trans "Filtered Results" %}

    +
    + +
    +
    +
      + {% include "core/filter_list.html" %} +
    +
    +
    + +
    +
    + + + {% paginate %} + +{% endblock %} diff --git a/readthedocs/urls.py b/readthedocs/urls.py index c8ebe62e6..93536a829 100644 --- a/readthedocs/urls.py +++ b/readthedocs/urls.py @@ -6,9 +6,11 @@ from django.views.generic.simple import direct_to_template from tastypie.api import Api from api.base import ProjectResource, UserResource, BuildResource, VersionResource, FileResource +from builds.filters import VersionFilter from core.forms import UserProfileForm from core.views import SearchView from projects.feeds import LatestProjectsFeed, NewProjectsFeed +from projects.filters import ProjectFilter v1_api = Api(api_name='v1') v1_api.register(BuildResource()) @@ -60,6 +62,16 @@ urlpatterns = patterns('', url(r'^random/$', 'core.views.random_page', name='random_page'), url(r'^depth/$', 'core.views.queue_depth', name='queue_depth'), url(r'^live/$', 'core.views.live_builds', name='live_builds'), + url(r'^filter/version/$', + 'django_filters.views.object_filter', + { 'filter_class': VersionFilter, 'template_name': 'filter.html' }, + name='filter_version' + ), + url(r'^filter/project/$', + 'django_filters.views.object_filter', + { 'filter_class': ProjectFilter, 'template_name': 'filter.html' }, + name='filter_project' + ), url(r'^wipe/(?P[-\w]+)/(?P[-\w]+)/$', 'core.views.wipe_version', name='wipe_version'