]> git.openstreetmap.org Git - osqa.git/blob - forum/modules/ui_objects.py
Some simple fixes on ui objects to prevent missing request in the context problem.
[osqa.git] / forum / modules / ui_objects.py
1 from django.core.urlresolvers import reverse
2 from django.template.defaultfilters import slugify
3 from django import template
4 from forum.utils import html
5 from ui import Registry
6 from copy import copy
7
8 class Visibility(object):
9     def __init__(self, level='public'):
10         if level not in ['public', 'authenticated', 'staff', 'superuser', 'owner']:
11             try:
12                 int(level)
13                 self.by_reputation = True
14             except:
15                 raise "Invalid visibility level for ui object: %s" % level
16         else:
17             self.by_reputation = False
18
19         self.level = level
20         self.negated = False
21
22     def show_to(self, user):
23         if self.by_reputation:
24             res = user.is_authenticated() and (user.reputation >= int(self.level) or user.is_staff or user.is_superuser)
25         else:
26             res = self.level == 'public' or (user.is_authenticated() and (
27                 self.level == 'authenticated' or (
28                 self.level == 'superuser' and user.is_superuser) or (
29                 self.level == 'staff' and (user.is_staff or user.is_superuser)) or (
30                 self.level == 'owner' and user.is_siteowner)))
31
32         if self.negated:
33             return not res
34         else:
35             return res
36
37     def __invert__(self):
38         inverted = copy(self)
39         inverted.negated = True
40         
41
42 Visibility.PUBLIC = Visibility('public')
43 Visibility.AUTHENTICATED = Visibility('authenticated')
44 Visibility.STAFF = Visibility('staff')
45 Visibility.SUPERUSER = Visibility('superuser')
46 Visibility.OWNER = Visibility('owner')
47 Visibility.REPUTED = lambda r: Visibility(r)
48
49
50 class Url(object):
51     def __init__(self, url_pattern):
52         self.url_pattern = url_pattern
53
54     def __call__(self, u, c):
55         return reverse(self.url_pattern)
56
57
58 class ObjectBase(object):
59     class Argument(object):
60         def __init__(self, argument):
61             self.argument = argument
62
63         def __call__(self, context):
64             if callable(self.argument):
65                 user = context.get('request', None) and context['request'].user or None
66                 return self.argument(user, context)
67             else:
68                 return self.argument
69
70     def __init__(self, visibility=None, weight=500):
71         self.visibility = visibility
72         self.weight = weight
73
74     def _visible_to(self, user):
75         return (not self.visibility) or (self.visibility and self.visibility.show_to(user))
76
77     def can_render(self, context):
78         try:
79             return self._visible_to(context['request'].user)
80         except KeyError:
81             try:
82                 return self._visible_to(context['viewer'])
83             except KeyError:
84                 if self.visibility:
85                     return False
86                 else:
87                     return True
88
89     def render(self, context):
90         return ''
91
92 class LoopBase(ObjectBase):
93     def update_context(self, context):
94         pass
95
96
97
98 class Link(ObjectBase):
99     def __init__(self, text, url, attrs=None, pre_code='', post_code='', visibility=None, weight=500):
100         super(Link, self).__init__(visibility, weight)
101         self.text = self.Argument(text)
102         self.url = self.Argument(url)
103         self.attrs = self.Argument(attrs or {})
104         self.pre_code = self.Argument(pre_code)
105         self.post_code = self.Argument(post_code)
106
107     def render(self, context):
108         return "%s %s %s" % (self.pre_code(context),
109             html.hyperlink(self.url(context), self.text(context), **self.attrs(context)),
110             self.post_code(context))
111
112 class Include(ObjectBase):
113     def __init__(self, tpl, visibility=None, weight=500):
114         super(Include, self).__init__(visibility, weight)
115         self.template = template.loader.get_template(tpl)
116
117     def render(self, context):
118         if not isinstance(context, template.Context):
119             context = template.Context(context)
120         return self.template.render(context)
121         
122
123 class LoopContext(LoopBase):
124     def __init__(self, loop_context, visibility=None, weight=500):
125         super(LoopContext, self).__init__(visibility, weight)
126         self.loop_context = self.Argument(loop_context)
127
128     def update_context(self, context):
129         context.update(self.loop_context(context))
130
131
132 class PageTab(LoopBase):
133     def __init__(self, tab_name, tab_title, url_getter, weight):
134         super(PageTab, self).__init__(weight=weight)
135         self.tab_name = tab_name
136         self.tab_title = tab_title
137         self.url_getter = url_getter
138
139     def update_context(self, context):
140         context.update(dict(
141             tab_name=self.tab_name,
142             tab_title=self.tab_title,
143             tab_url=self.url_getter()
144         ))
145
146
147 class ProfileTab(LoopBase):
148     def __init__(self, name, title, description, url_getter, private=False, render_to=None, weight=500):
149         super(ProfileTab, self).__init__(weight=weight)
150         self.name = name
151         self.title = title
152         self.description = description
153         self.url_getter = url_getter
154         self.private = private
155         self.render_to = render_to
156
157     def can_render(self, context):
158         return (not self.render_to or (self.render_to(context['view_user']))) and (
159             not self.private or (
160             context['view_user'] == context['request'].user or context['request'].user.is_superuser))
161
162     def update_context(self, context):        
163         context.update(dict(
164             tab_name=self.name,
165             tab_title=self.title,
166             tab_description = self.description,
167             tab_url=self.url_getter(context['view_user'])
168         ))
169
170
171 class AjaxMenuItem(ObjectBase):
172     def __init__(self, label, url, a_attrs=None, span_label='', span_attrs=None, visibility=None, weight=500):
173         super(AjaxMenuItem, self).__init__(visibility, weight)
174         self.label = self.Argument(label)
175         self.url = self.Argument(url)
176         self.a_attrs = self.Argument(a_attrs or {})
177         self.span_label = self.Argument(span_label)
178         self.span_attrs = self.Argument(span_attrs or {})
179
180     def render(self, context):
181         return html.buildtag('li',
182             html.buildtag('span', self.span_label(context), **self.span_attrs(context)) + \
183             html.hyperlink(self.url(context), self.label(context), **self.a_attrs(context)),
184             **{'class': 'item'})
185
186 class AjaxMenuGroup(ObjectBase, Registry):
187     def __init__(self, label, items, visibility=None, weight=500):
188         super(AjaxMenuGroup, self).__init__(visibility, weight)
189         self.label = label
190
191         for item in items:
192             self.add(item)
193
194     def can_render(self, context):
195         if super(AjaxMenuGroup, self).can_render(context):
196             for item in self:
197                 if item.can_render(context): return True
198
199         return False
200
201     def render(self, context):
202         return html.buildtag('li', self.label, **{'class': 'separator'}) + "".join([
203             item.render(context) for item in self if item.can_render(context)
204         ])
205
206 class UserMenuItem(AjaxMenuItem):
207     def __init__(self, render_to=None, *args, **kwargs):
208         super(UserMenuItem, self).__init__(*args, **kwargs)
209         self.render_to = render_to
210
211     def can_render(self, context):
212         return (not self.render_to or (self.render_to(context['user']))) and super(UserMenuItem, self)._visible_to(context['viewer'])