diff options
author | Magnus Hagander | 2013-07-19 16:48:37 +0000 |
---|---|---|
committer | Magnus Hagander | 2013-07-19 16:48:37 +0000 |
commit | b6f1afa4f3ff72b737c510a23dac2b7fa04ace05 (patch) | |
tree | d9861054b9f754dd248cbe32328b858d5f0b3681 /pgcommitfest/commitfest | |
parent | cd605547cc679bba7fdb2d8d5d2639c5a152be95 (diff) |
Add basic filtering support
Diffstat (limited to 'pgcommitfest/commitfest')
-rw-r--r-- | pgcommitfest/commitfest/forms.py | 24 | ||||
-rw-r--r-- | pgcommitfest/commitfest/models.py | 4 | ||||
-rw-r--r-- | pgcommitfest/commitfest/templates/commitfest.html | 30 | ||||
-rw-r--r-- | pgcommitfest/commitfest/views.py | 34 |
4 files changed, 87 insertions, 5 deletions
diff --git a/pgcommitfest/commitfest/forms.py b/pgcommitfest/commitfest/forms.py index 9838ce6..8f2e33c 100644 --- a/pgcommitfest/commitfest/forms.py +++ b/pgcommitfest/commitfest/forms.py @@ -1,13 +1,35 @@ from django import forms from django.forms import ValidationError +from django.db.models import Q +from django.contrib.auth.models import User from selectable.forms.widgets import AutoCompleteSelectMultipleWidget -from models import Patch, MailThread +from models import Patch, MailThread, PatchOnCommitFest from lookups import UserLookup from widgets import ThreadPickWidget from ajax import _archivesAPI +class CommitFestFilterForm(forms.Form): + text = forms.CharField(max_length=50, required=False) + status = forms.ChoiceField(required=False) + author = forms.ChoiceField(required=False) + reviewer = forms.ChoiceField(required=False) + + def __init__(self, cf, *args, **kwargs): + super(CommitFestFilterForm, self).__init__(*args, **kwargs) + + c = [(-1, '* All')] + list(PatchOnCommitFest._STATUS_CHOICES) + self.fields['status'] = forms.ChoiceField(choices=c, required=False) + + q = Q(patch_author__commitfests=cf) | Q(patch_reviewer__commitfests=cf) + userchoices = [(-1, '* All'), (-2, '* None'), ] + [(u.id, '%s %s (%s)' % (u.first_name, u.last_name, u.username)) for u in User.objects.filter(q).distinct()] + self.fields['author'] = forms.ChoiceField(choices=userchoices, required=False) + self.fields['reviewer'] = forms.ChoiceField(choices=userchoices, required=False) + + for f in ('status', 'author', 'reviewer',): + self.fields[f].widget.attrs = {'class': 'input-medium'} + class PatchForm(forms.ModelForm): class Meta: model = Patch diff --git a/pgcommitfest/commitfest/models.py b/pgcommitfest/commitfest/models.py index 44dd884..e4326db 100644 --- a/pgcommitfest/commitfest/models.py +++ b/pgcommitfest/commitfest/models.py @@ -68,8 +68,8 @@ class Patch(models.Model): # Mailthreads are OneToMany in the other direction #mailthreads_set = ... - authors = models.ManyToManyField(User, related_name='author', blank=True) - reviewers = models.ManyToManyField(User, related_name='reviewer', blank=True) + authors = models.ManyToManyField(User, related_name='patch_author', blank=True) + reviewers = models.ManyToManyField(User, related_name='patch_reviewer', blank=True) committer = models.ForeignKey(Committer, blank=True, null=True) diff --git a/pgcommitfest/commitfest/templates/commitfest.html b/pgcommitfest/commitfest/templates/commitfest.html index 19f2739..946560b 100644 --- a/pgcommitfest/commitfest/templates/commitfest.html +++ b/pgcommitfest/commitfest/templates/commitfest.html @@ -1,6 +1,36 @@ {%extends "base.html"%} {%load commitfest %} {%block contents%} + +<div class="accordion" id="filteraccordion"> + <div class="accordion-group"> + <div class="accordion-heading"> + <a class="accordion-toggle" data-toggle="collapse" data-parent="#filteraccordion" href="#collapseFilters"><h4>Filters</h4></a> + </div> + <div id="collapseFilters" class="accordion-body collapse {%if has_filter%}in{%endif%}"> + <form id="filterform" method="GET" action="."> + <table class="table table-condensed"> + <thead> + <tr> +{%for f in form%} + <td>{{f.label}}</td> +{%endfor%} + <td></td> + </tr> + </thead> + <tbody> + <tr> +{%for f in form%} + <td>{{f}}</td> +{%endfor%} + <td><input type="submit" class="btn" value="Filter"></td> + </tr> + </tbody> + </table> + </form> + </div> +</div> + {%for p in patches %} {%ifchanged p.is_open%} {%if not forloop.first%} diff --git a/pgcommitfest/commitfest/views.py b/pgcommitfest/commitfest/views.py index 5e77d6e..ede222e 100644 --- a/pgcommitfest/commitfest/views.py +++ b/pgcommitfest/commitfest/views.py @@ -2,6 +2,7 @@ from django.shortcuts import render_to_response, get_object_or_404 from django.http import HttpResponseRedirect, Http404 from django.template import RequestContext from django.db import transaction +from django.db.models import Q from django.contrib import messages from django.contrib.auth.decorators import login_required @@ -12,7 +13,7 @@ from email.utils import formatdate, make_msgid from mailqueue.util import send_mail from models import CommitFest, Patch, PatchOnCommitFest, PatchHistory, Committer -from forms import PatchForm, NewPatchForm, CommentForm +from forms import PatchForm, NewPatchForm, CommentForm, CommitFestFilterForm from ajax import doAttachThread def home(request): @@ -30,16 +31,45 @@ def home(request): def commitfest(request, cfid): # Find ourselves cf = get_object_or_404(CommitFest, pk=cfid) - patches = cf.patch_set.all().select_related().extra(select={ + + # Build a dynamic filter based on the filtering options entered + q = Q() + if request.GET.has_key('status') and request.GET['status'] != "-1": + q = q & Q(patchoncommitfest__status=int(request.GET['status'])) + if request.GET.has_key('author') and request.GET['author'] != "-1": + if request.GET['author'] == '-2': + q = q & Q(authors=None) + else: + q = q & Q(authors__id=int(request.GET['author'])) + if request.GET.has_key('reviewer') and request.GET['reviewer'] != "-1": + if request.GET['reviewer'] == '-2': + q = q & Q(reviewers=None) + else: + q = q & Q(reviewers__id=int(request.GET['reviewer'])) + + if request.GET.has_key('text') and request.GET['text'] != '': + q = q & Q(name__icontains=request.GET['text']) + + # Not sure if this is correct? + has_filter = len(q.children) > 0 + if not has_filter and request.GET: + # Redirect to get rid of the ugly url + return HttpResponseRedirect('/%s/' % cf.id) + + patches = cf.patch_set.filter(q).select_related().extra(select={ 'status':'commitfest_patchoncommitfest.status', 'author_names':"SELECT string_agg(first_name || ' ' || last_name || ' (' || username || ')', ', ') FROM auth_user INNER JOIN commitfest_patch_authors cpa ON cpa.user_id=auth_user.id WHERE cpa.patch_id=commitfest_patch.id", 'reviewer_names':"SELECT string_agg(first_name || ' ' || last_name || ' (' || username || ')', ', ') FROM auth_user INNER JOIN commitfest_patch_reviewers cpr ON cpr.user_id=auth_user.id WHERE cpr.patch_id=commitfest_patch.id", 'is_open':'commitfest_patchoncommitfest.status IN (%s)' % ','.join([str(x) for x in PatchOnCommitFest.OPEN_STATUSES]), }).order_by('-is_open', 'topic__topic', 'created') + form = CommitFestFilterForm(cf, request.GET) + return render_to_response('commitfest.html', { 'cf': cf, + 'form': form, 'patches': patches, + 'has_filter': has_filter, 'title': 'Commitfest %s' % cf.name, }, context_instance=RequestContext(request)) |