1 # Patchwork - automated patch tracking system
2 # Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org>
4 # This file is part of the Patchwork package.
6 # Patchwork is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # Patchwork is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with Patchwork; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 from patchwork.models import Person, State
22 from django.utils.safestring import mark_safe
23 from django.utils.html import escape
24 from django.contrib.auth.models import User
27 def __init__(self, filters):
28 self.filters = filters
33 """The 'name' of the filter, to be displayed in the filter UI"""
37 """The current condition of the filter, to be displayed in the
42 """The key for this filter, to appear in the querystring. A key of
43 None will remove the param=ley pair from the querystring."""
46 def set_status(self, *kwargs):
47 """Views can call this to force a specific filter status. For example,
48 a user's todo page needs to setup the delegate filter to show
49 that user's delegated patches"""
52 def parse(self, dict):
53 if self.param not in dict.keys():
55 self._set_key(dict[self.param])
57 def url_without_me(self):
58 return self.filters.querystring_without_filter(self)
60 def form_function(self):
61 return 'function(form) { return "unimplemented" }'
65 return mark_safe('<input type="hidden" value="%s">%s' % (self.param,
67 return self.condition()
74 return '%s: %s' % (self.name, self.kwargs())
77 class SubmitterFilter(Filter):
79 def __init__(self, filters):
80 super(SubmitterFilter, self).__init__(filters)
81 self.name = 'Submitter'
83 self.person_match = None
85 def _set_key(self, str):
87 self.person_match = None
90 submitter_id = int(str)
97 self.person = Person.objects.get(id = int(str))
102 people = Person.objects.filter(name__icontains = str)
107 self.person_match = str
112 user = self.person.user
114 return {'submitter__in':
115 Person.objects.filter(user = user).values('pk').query}
116 return {'submitter': self.person}
118 if self.person_match:
119 return {'submitter__name__icontains': self.person_match}
124 return self.person.name
125 elif self.person_match:
126 return self.person_match
132 name = self.person.name
133 return mark_safe(('<input onKeyUp="submitter_field_change(this)" ' +
134 'name="submitter" id="submitter_input" ' +
135 'value="%s"> ' % escape(name)) +
136 '<select id="submitter_select" ' +
137 'disabled="true"></select>')
141 return self.person.id
142 return self.person_match
144 class StateFilter(Filter):
147 action_req_str = 'Action Required'
149 def __init__(self, filters):
150 super(StateFilter, self).__init__(filters)
155 def _set_key(self, str):
158 if str == self.any_key:
163 self.state = State.objects.get(id=int(str))
170 if self.state is not None:
171 return {'state': self.state}
173 return {'state__in': \
174 State.objects.filter(action_required = True) \
179 return self.state.name
180 return self.action_req_str
183 if self.state is not None:
190 str = '<select name="%s">' % self.param
191 str += '<option value="%s">any</option>' % self.any_key
192 str += '<option value="">%s</option>' % self.action_req_str
193 for state in State.objects.all():
195 if self.state and self.state == state:
196 selected = ' selected="true"'
198 str += '<option value="%d" %s>%s</option>' % \
199 (state.id, selected, state.name)
201 return mark_safe(str);
203 def form_function(self):
204 return 'function(form) { return form.x.value }'
206 def url_without_me(self):
207 qs = self.filters.querystring_without_filter(self)
210 return qs + '%s=%s' % (self.param, self.any_key)
212 class SearchFilter(Filter):
214 def __init__(self, filters):
215 super(SearchFilter, self).__init__(filters)
220 def _set_key(self, str):
228 return {'name__icontains': self.search}
239 value = escape(self.search)
240 return mark_safe('<input name="%s" value="%s">' %\
243 def form_function(self):
244 return mark_safe('function(form) { return form.x.value }')
246 class ArchiveFilter(Filter):
248 def __init__(self, filters):
249 super(ArchiveFilter, self).__init__(filters)
250 self.name = 'Archived'
251 self.archive_state = False
258 self.description_map = {
264 def _set_key(self, str):
265 self.archive_state = False
267 for (k, v) in self.param_map.iteritems():
269 self.archive_state = k
270 if self.archive_state == None:
274 if self.archive_state == None:
276 return {'archived': self.archive_state}
279 return self.description_map[self.archive_state]
282 if self.archive_state == False:
284 return self.param_map[self.archive_state]
288 for b in [False, True, None]:
289 label = self.description_map[b]
291 if self.archive_state == b:
292 selected = 'checked="true"'
293 s += ('<input type="radio" name="%(param)s" ' + \
294 '%(selected)s value="%(value)s">%(label)s' + \
295 ' ') % \
298 'selected': selected,
299 'value': self.param_map[b]
303 def url_without_me(self):
304 qs = self.filters.querystring_without_filter(self)
307 return qs + 'archive=both'
310 class DelegateFilter(Filter):
312 no_delegate_key = '-'
313 no_delegate_str = 'Nobody'
316 def __init__(self, filters):
317 super(DelegateFilter, self).__init__(filters)
318 self.name = 'Delegate'
319 self.param = 'delegate'
322 def _set_key(self, str):
323 if str == self.no_delegate_key:
330 self.delegate = User.objects.get(id = str)
338 return {'delegate': self.delegate}
342 return self.delegate.get_profile().name()
343 return self.no_delegate_str
346 delegates = User.objects.filter(userprofile__maintainer_projects =
347 self.filters.project)
349 str = '<select name="delegate">'
353 selected = 'selected'
355 str += '<option %s value="">------</option>' % selected
358 if self.applied and self.delegate is None:
359 selected = 'selected'
361 str += '<option %s value="%s">%s</option>' % \
362 (selected, self.no_delegate_key, self.no_delegate_str)
366 if d == self.delegate:
367 selected = ' selected'
369 str += '<option %s value="%s">%s</option>' % (selected,
370 d.id, d.get_profile().name())
373 return mark_safe(str)
377 return self.delegate.id
379 return self.no_delegate_key
382 def set_status(self, *args, **kwargs):
383 if 'delegate' in kwargs:
384 self.applied = self.forced = True
385 self.delegate = kwargs['delegate']
386 if self.AnyDelegate in args:
390 filterclasses = [SubmitterFilter, \
398 def __init__(self, request):
399 self._filters = map(lambda c: c(self), filterclasses)
400 self.dict = request.GET
403 for f in self._filters:
406 def set_project(self, project):
407 self.project = project
409 def filter_conditions(self):
411 for f in self._filters:
413 kwargs.update(f.kwargs())
416 def apply(self, queryset):
417 kwargs = self.filter_conditions()
420 return queryset.filter(**kwargs)
423 return [ (f.param, f.key()) for f in self._filters \
424 if f.key() is not None ]
426 def querystring(self, remove = None):
427 params = dict(self.params())
429 for (k, v) in self.dict.iteritems():
433 if remove is not None:
434 if remove.param in params.keys():
435 del params[remove.param]
437 return '?' + '&'.join(['%s=%s' % x for x in params.iteritems()])
439 def querystring_without_filter(self, filter):
440 return self.querystring(filter)
442 def applied_filters(self):
443 return filter(lambda x: x.applied, self._filters)
445 def available_filters(self):
448 def set_status(self, filterclass, *args, **kwargs):
449 for f in self._filters:
450 if isinstance(f, filterclass):
451 f.set_status(*args, **kwargs)