]> git.ozlabs.org Git - patchwork/blob - apps/patchwork/filters.py
Resolve removed 'AUTH_PROFILE_MODULE' setting
[patchwork] / apps / patchwork / filters.py
1 # Patchwork - automated patch tracking system
2 # Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org>
3 #
4 # This file is part of the Patchwork package.
5 #
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.
10 #
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.
15 #
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
19
20
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
25 from urllib import quote
26
27 class Filter(object):
28     def __init__(self, filters):
29         self.filters = filters
30         self.applied = False
31         self.forced = False
32
33     def name(self):
34         """The 'name' of the filter, to be displayed in the filter UI"""
35         return self.name
36
37     def condition(self):
38         """The current condition of the filter, to be displayed in the
39            filter UI"""
40         return self.key
41
42     def key(self):
43         """The key for this filter, to appear in the querystring. A key of
44            None will remove the param=ley pair from the querystring."""
45         return None
46
47     def set_status(self, *kwargs):
48         """Views can call this to force a specific filter status. For example,
49            a user's todo page needs to setup the delegate filter to show
50            that user's delegated patches"""
51         pass
52
53     def parse(self, dict):
54         if self.param not in dict.keys():
55             return
56         self._set_key(dict[self.param])
57
58     def url_without_me(self):
59         return self.filters.querystring_without_filter(self)
60
61     def form_function(self):
62         return 'function(form) { return "unimplemented" }'
63
64     def form(self):
65         if self.forced:
66             return mark_safe('<input type="hidden" value="%s">%s' % (self.param,
67                         self.condition()))
68             return self.condition()
69         return self._form()
70
71     def kwargs(self):
72         return {}
73
74     def __str__(self):
75         return '%s: %s' % (self.name, self.kwargs())
76
77
78 class SubmitterFilter(Filter):
79     param = 'submitter'
80     def __init__(self, filters):
81         super(SubmitterFilter, self).__init__(filters)
82         self.name = 'Submitter'
83         self.person = None
84         self.person_match = None
85
86     def _set_key(self, str):
87         self.person = None
88         self.person_match = None
89         submitter_id = None
90         try:
91             submitter_id = int(str)
92         except ValueError:
93             pass
94         except:
95             return
96
97         if submitter_id:
98             self.person = Person.objects.get(id = int(str))
99             self.applied = True
100             return
101
102
103         people = Person.objects.filter(name__icontains = str)
104
105         if not people:
106             return
107
108         self.person_match = str
109         self.applied = True
110
111     def kwargs(self):
112         if self.person:
113             user = self.person.user
114             if user:
115                 return {'submitter__in':
116                     Person.objects.filter(user = user).values('pk').query}
117             return {'submitter': self.person}
118
119         if self.person_match:
120             return {'submitter__name__icontains': self.person_match}
121         return {}
122
123     def condition(self):
124         if self.person:
125             return self.person.name
126         elif self.person_match:
127             return self.person_match
128         return ''
129
130     def _form(self):
131         name = ''
132         if self.person:
133             name = self.person.name
134         return mark_safe(('<input onKeyUp="submitter_field_change(this)" ' +
135                 'name="submitter" id="submitter_input" ' +
136                         'value="%s">&nbsp;' % escape(name)) +
137                 '<select id="submitter_select" ' +
138                 'disabled="true"></select>')
139
140     def key(self):
141         if self.person:
142             return self.person.id
143         return self.person_match
144
145 class StateFilter(Filter):
146     param = 'state'
147     any_key = '*'
148     action_req_str = 'Action Required'
149
150     def __init__(self, filters):
151         super(StateFilter, self).__init__(filters)
152         self.name = 'State'
153         self.state = None
154         self.applied = True
155
156     def _set_key(self, str):
157         self.state = None
158
159         if str == self.any_key:
160             self.applied = False
161             return
162
163         try:
164             self.state = State.objects.get(id=int(str))
165         except:
166             return
167
168         self.applied = True
169
170     def kwargs(self):
171         if self.state is not None:
172             return {'state': self.state}
173         else:
174             return {'state__in': \
175                         State.objects.filter(action_required = True) \
176                             .values('pk').query}
177
178     def condition(self):
179         if self.state:
180             return self.state.name
181         return self.action_req_str
182
183     def key(self):
184         if self.state is not None:
185             return self.state.id
186         if not self.applied:
187             return '*'
188         return None
189
190     def _form(self):
191         str = '<select name="%s">' % self.param
192
193         selected = ''
194         if not self.applied:
195             selected = 'selected'
196         str += '<option %s value="%s">any</option>' % (selected, self.any_key)
197
198         selected = ''
199         if self.applied and self.state == None:
200             selected = 'selected'
201         str += '<option %s value="">%s</option>' % \
202                (selected, self.action_req_str)
203
204         for state in State.objects.all():
205             selected = ''
206             if self.state and self.state == state:
207                 selected = ' selected="true"'
208
209             str += '<option value="%d" %s>%s</option>' % \
210                 (state.id, selected, state.name)
211         str += '</select>'
212         return mark_safe(str);
213
214     def form_function(self):
215         return 'function(form) { return form.x.value }'
216
217     def url_without_me(self):
218         qs = self.filters.querystring_without_filter(self)
219         if qs != '?':
220             qs += '&'
221         return qs + '%s=%s' % (self.param, self.any_key)
222
223 class SearchFilter(Filter):
224     param = 'q'
225     def __init__(self, filters):
226         super(SearchFilter, self).__init__(filters)
227         self.name = 'Search'
228         self.param = 'q'
229         self.search = None
230
231     def _set_key(self, str):
232         str = str.strip()
233         if str == '':
234             return
235         self.search = str
236         self.applied = True
237
238     def kwargs(self):
239         return {'name__icontains': self.search}
240
241     def condition(self):
242         return self.search
243
244     def key(self):
245         return self.search
246
247     def _form(self):
248         value = ''
249         if self.search:
250             value = escape(self.search)
251         return mark_safe('<input name="%s" value="%s">' %\
252                 (self.param, value))
253
254     def form_function(self):
255         return mark_safe('function(form) { return form.x.value }')
256
257 class ArchiveFilter(Filter):
258     param = 'archive'
259     def __init__(self, filters):
260         super(ArchiveFilter, self).__init__(filters)
261         self.name = 'Archived'
262         self.archive_state = False
263         self.applied = True
264         self.param_map = {
265             True: 'true',
266             False: '',
267             None:  'both'
268         }
269         self.description_map = {
270             True: 'Yes',
271             False: 'No',
272             None: 'Both'
273         }
274
275     def _set_key(self, str):
276         self.archive_state = False
277         self.applied = True
278         for (k, v) in self.param_map.iteritems():
279             if str == v:
280                 self.archive_state = k
281         if self.archive_state == None:
282             self.applied = False
283
284     def kwargs(self):
285         if self.archive_state == None:
286             return {}
287         return {'archived': self.archive_state}
288
289     def condition(self):
290         return self.description_map[self.archive_state]
291
292     def key(self):
293         if self.archive_state == False:
294             return None
295         return self.param_map[self.archive_state]
296
297     def _form(self):
298         s = ''
299         for b in [False, True, None]:
300             label = self.description_map[b]
301             selected = ''
302             if self.archive_state == b:
303                 selected = 'checked="true"'
304             s += ('<input type="radio" name="%(param)s" ' + \
305                    '%(selected)s value="%(value)s">%(label)s' + \
306                    '&nbsp;&nbsp;&nbsp;&nbsp;') % \
307                     {'label': label,
308                      'param': self.param,
309                      'selected': selected,
310                      'value': self.param_map[b]
311                     }
312         return mark_safe(s)
313
314     def url_without_me(self):
315         qs = self.filters.querystring_without_filter(self)
316         if qs != '?':
317             qs += '&'
318         return qs + 'archive=both'
319
320
321 class DelegateFilter(Filter):
322     param = 'delegate'
323     no_delegate_key = '-'
324     no_delegate_str = 'Nobody'
325     AnyDelegate = 1
326
327     def __init__(self, filters):
328         super(DelegateFilter, self).__init__(filters)
329         self.name = 'Delegate'
330         self.param = 'delegate'
331         self.delegate = None
332
333     def _set_key(self, str):
334         if str == self.no_delegate_key:
335             self.applied = True
336             self.delegate = None
337             return
338
339         applied = False
340         try:
341             self.delegate = User.objects.get(id = str)
342             self.applied = True
343         except:
344             pass
345
346     def kwargs(self):
347         if not self.applied:
348             return {}
349         return {'delegate': self.delegate}
350
351     def condition(self):
352         if self.delegate:
353             return self.delegate.profile.name()
354         return self.no_delegate_str
355
356     def _form(self):
357         delegates = User.objects.filter(profile__maintainer_projects =
358                 self.filters.project)
359
360         str = '<select name="delegate">'
361
362         selected = ''
363         if not self.applied:
364             selected = 'selected'
365
366         str += '<option %s value="">------</option>' % selected
367
368         selected = ''
369         if self.applied and self.delegate is None:
370             selected = 'selected'
371
372         str += '<option %s value="%s">%s</option>' % \
373                 (selected, self.no_delegate_key, self.no_delegate_str)
374
375         for d in delegates:
376             selected = ''
377             if d == self.delegate:
378                 selected = ' selected'
379
380             str += '<option %s value="%s">%s</option>' % (selected,
381                     d.id, d.profile.name())
382         str += '</select>'
383
384         return mark_safe(str)
385
386     def key(self):
387         if self.delegate:
388             return self.delegate.id
389         if self.applied:
390             return self.no_delegate_key
391         return None
392
393     def set_status(self, *args, **kwargs):
394         if 'delegate' in kwargs:
395             self.applied = self.forced = True
396             self.delegate = kwargs['delegate']
397         if self.AnyDelegate in args:
398             self.applied = False
399             self.forced = True
400
401 filterclasses = [SubmitterFilter, \
402                  StateFilter,
403                  SearchFilter,
404                  ArchiveFilter,
405                  DelegateFilter]
406
407 class Filters:
408
409     def __init__(self, request):
410         self._filters = map(lambda c: c(self), filterclasses)
411         self.dict = request.GET
412         self.project = None
413
414         for f in self._filters:
415             f.parse(self.dict)
416
417     def set_project(self, project):
418         self.project = project
419
420     def filter_conditions(self):
421         kwargs = {}
422         for f in self._filters:
423             if f.applied:
424                 kwargs.update(f.kwargs())
425         return kwargs
426
427     def apply(self, queryset):
428         kwargs = self.filter_conditions()
429         if not kwargs:
430             return queryset
431         return queryset.filter(**kwargs)
432
433     def params(self):
434         return [ (f.param, f.key()) for f in self._filters \
435                 if f.key() is not None ]
436
437     def querystring(self, remove = None):
438         params = dict(self.params())
439
440         for (k, v) in self.dict.iteritems():
441             if k not in params:
442                 params[k] = v
443
444         if remove is not None:
445             if remove.param in params.keys():
446                 del params[remove.param]
447
448         pairs = params.iteritems()
449
450         def sanitise(s):
451             if not isinstance(s, basestring):
452                 s = unicode(s)
453             return quote(s.encode('utf-8'))
454
455         return '?' + '&'.join(['%s=%s' % (sanitise(k), sanitise(v))
456                                     for (k, v) in pairs])
457
458     def querystring_without_filter(self, filter):
459         return self.querystring(filter)
460
461     def applied_filters(self):
462         return filter(lambda x: x.applied, self._filters)
463
464     def available_filters(self):
465         return self._filters
466
467     def set_status(self, filterclass, *args, **kwargs):
468         for f in self._filters:
469             if isinstance(f, filterclass):
470                 f.set_status(*args, **kwargs)
471                 return