]> git.openstreetmap.org Git - osqa.git/blob - forum/modules/ui_objects.py
7fcf96caea9ccb155a4854492279f7c5ff452937
[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             return True
82
83     def render(self, context):
84         return ''
85
86 class LoopBase(ObjectBase):
87     def update_context(self, context):
88         pass
89
90
91
92 class Link(ObjectBase):
93     def __init__(self, text, url, attrs=None, pre_code='', post_code='', visibility=None, weight=500):
94         super(Link, self).__init__(visibility, weight)
95         self.text = self.Argument(text)
96         self.url = self.Argument(url)
97         self.attrs = self.Argument(attrs or {})
98         self.pre_code = self.Argument(pre_code)
99         self.post_code = self.Argument(post_code)
100
101     def render(self, context):
102         return "%s %s %s" % (self.pre_code(context),
103             html.hyperlink(self.url(context), self.text(context), **self.attrs(context)),
104             self.post_code(context))
105
106 class Include(ObjectBase):
107     def __init__(self, tpl, visibility=None, weight=500):
108         super(Include, self).__init__(visibility, weight)
109         self.template = template.loader.get_template(tpl)
110
111     def render(self, context):
112         if not isinstance(context, template.Context):
113             context = template.Context(context)
114         return self.template.render(context)
115         
116
117 class LoopContext(LoopBase):
118     def __init__(self, loop_context, visibility=None, weight=500):
119         super(LoopContext, self).__init__(visibility, weight)
120         self.loop_context = self.Argument(loop_context)
121
122     def update_context(self, context):
123         context.update(self.loop_context(context))
124
125
126 class PageTab(LoopBase):
127     def __init__(self, tab_name, tab_title, url_getter, weight):
128         super(PageTab, self).__init__(weight=weight)
129         self.tab_name = tab_name
130         self.tab_title = tab_title
131         self.url_getter = url_getter
132
133     def update_context(self, context):
134         context.update(dict(
135             tab_name=self.tab_name,
136             tab_title=self.tab_title,
137             tab_url=self.url_getter()
138         ))
139
140
141 class ProfileTab(LoopBase):
142     def __init__(self, name, title, description, url_getter, private=False, render_to=None, weight=500):
143         super(ProfileTab, self).__init__(weight=weight)
144         self.name = name
145         self.title = title
146         self.description = description
147         self.url_getter = url_getter
148         self.private = private
149         self.render_to = render_to
150
151     def can_render(self, context):
152         return (not self.render_to or (self.render_to(context['view_user']))) and (
153             not self.private or (
154             context['view_user'] == context['request'].user or context['request'].user.is_superuser))
155
156     def update_context(self, context):        
157         context.update(dict(
158             tab_name=self.name,
159             tab_title=self.title,
160             tab_description = self.description,
161             tab_url=self.url_getter(context['view_user'])
162         ))
163
164
165 class AjaxMenuItem(ObjectBase):
166     def __init__(self, label, url, a_attrs=None, span_label='', span_attrs=None, visibility=None, weight=500):
167         super(AjaxMenuItem, self).__init__(visibility, weight)
168         self.label = self.Argument(label)
169         self.url = self.Argument(url)
170         self.a_attrs = self.Argument(a_attrs or {})
171         self.span_label = self.Argument(span_label)
172         self.span_attrs = self.Argument(span_attrs or {})
173
174     def render(self, context):
175         return html.buildtag('li',
176             html.buildtag('span', self.span_label(context), **self.span_attrs(context)) + \
177             html.hyperlink(self.url(context), self.label(context), **self.a_attrs(context)),
178             **{'class': 'item'})
179
180 class AjaxMenuGroup(ObjectBase, Registry):
181     def __init__(self, label, items, visibility=None, weight=500):
182         super(AjaxMenuGroup, self).__init__(visibility, weight)
183         self.label = label
184
185         for item in items:
186             self.add(item)
187
188     def can_render(self, context):
189         if super(AjaxMenuGroup, self).can_render(context):
190             for item in self:
191                 if item.can_render(context): return True
192
193         return False
194
195     def render(self, context):
196         return html.buildtag('li', self.label, **{'class': 'separator'}) + "".join([
197             item.render(context) for item in self if item.can_render(context)
198         ])
199
200 class UserMenuItem(AjaxMenuItem):
201     def __init__(self, render_to=None, *args, **kwargs):
202         super(UserMenuItem, self).__init__(*args, **kwargs)
203         self.render_to = render_to
204
205     def can_render(self, context):
206         return (not self.render_to or (self.render_to(context['user']))) and super(UserMenuItem, self)._visible_to(context['viewer'])