]> git.openstreetmap.org Git - osqa.git/blobdiff - forum/modules/ui_objects.py
OSQA-266
[osqa.git] / forum / modules / ui_objects.py
index caa221fcd7c0d9c555d80c98341e1ddd621cc036..e42c94017ce6545cdc70ffbf8187607a71652a98 100644 (file)
@@ -2,6 +2,9 @@ from django.core.urlresolvers import reverse
 from django.template.defaultfilters import slugify
 from django import template
 from forum.utils import html
+from forum.models.user import AnonymousUser
+from ui import Registry
+from copy import copy
 
 class Visibility(object):
     def __init__(self, level='public'):
@@ -15,17 +18,28 @@ class Visibility(object):
             self.by_reputation = False
 
         self.level = level
+        self.negated = False
 
     def show_to(self, user):
         if self.by_reputation:
-            return user.is_authenticated() and (user.reputation >= int(self.level) or user.is_staff or user.is_superuser)
+            res = user.is_authenticated() and (user.reputation >= int(self.level) or user.is_staff or user.is_superuser)
         else:
-            return self.level == 'public' or (user.is_authenticated() and (
+            res = self.level == 'public' or (user.is_authenticated() and (
                 self.level == 'authenticated' or (
                 self.level == 'superuser' and user.is_superuser) or (
                 self.level == 'staff' and (user.is_staff or user.is_superuser)) or (
                 self.level == 'owner' and user.is_siteowner)))
 
+        if self.negated:
+            return not res
+        else:
+            return res
+
+    def __invert__(self):
+        inverted = copy(self)
+        inverted.negated = True
+        
+
 Visibility.PUBLIC = Visibility('public')
 Visibility.AUTHENTICATED = Visibility('authenticated')
 Visibility.STAFF = Visibility('staff')
@@ -49,7 +63,8 @@ class ObjectBase(object):
 
         def __call__(self, context):
             if callable(self.argument):
-                return self.argument(context['request'].user, context)
+                user = context.get('request', None) and context['request'].user or AnonymousUser()
+                return self.argument(user, context)
             else:
                 return self.argument
 
@@ -57,8 +72,17 @@ class ObjectBase(object):
         self.visibility = visibility
         self.weight = weight
 
+    def _visible_to(self, user):
+        return (not self.visibility) or (self.visibility and self.visibility.show_to(user))
+
     def can_render(self, context):
-        return (not self.visibility) or (self.visibility and self.visibility.show_to(context['request'].user))
+        try:
+            return self._visible_to(context['request'].user)
+        except KeyError:
+            try:
+                return self._visible_to(context['viewer'])
+            except KeyError:
+                return self._visible_to(AnonymousUser())
 
     def render(self, context):
         return ''
@@ -89,6 +113,8 @@ class Include(ObjectBase):
         self.template = template.loader.get_template(tpl)
 
     def render(self, context):
+        if not isinstance(context, template.Context):
+            context = template.Context(context)
         return self.template.render(context)
         
 
@@ -117,17 +143,19 @@ class PageTab(LoopBase):
 
 
 class ProfileTab(LoopBase):
-    def __init__(self, name, title, description, url_getter, private=False, weight=500):
+    def __init__(self, name, title, description, url_getter, private=False, render_to=None, weight=500):
         super(ProfileTab, self).__init__(weight=weight)
         self.name = name
         self.title = title
         self.description = description
         self.url_getter = url_getter
         self.private = private
+        self.render_to = render_to
 
     def can_render(self, context):
-        return not self.private or (
-            context['view_user'] == context['request'].user or context['request'].user.is_superuser)
+        return (not self.render_to or (self.render_to(context['view_user']))) and (
+            not self.private or (
+            context['view_user'] == context['request'].user or context['request'].user.is_superuser))
 
     def update_context(self, context):        
         context.update(dict(
@@ -135,4 +163,48 @@ class ProfileTab(LoopBase):
             tab_title=self.title,
             tab_description = self.description,
             tab_url=self.url_getter(context['view_user'])
-        ))
\ No newline at end of file
+        ))
+
+
+class AjaxMenuItem(ObjectBase):
+    def __init__(self, label, url, a_attrs=None, span_label='', span_attrs=None, visibility=None, weight=500):
+        super(AjaxMenuItem, self).__init__(visibility, weight)
+        self.label = self.Argument(label)
+        self.url = self.Argument(url)
+        self.a_attrs = self.Argument(a_attrs or {})
+        self.span_label = self.Argument(span_label)
+        self.span_attrs = self.Argument(span_attrs or {})
+
+    def render(self, context):
+        return html.buildtag('li',
+            html.buildtag('span', self.span_label(context), **self.span_attrs(context)) + \
+            html.hyperlink(self.url(context), self.label(context), **self.a_attrs(context)),
+            **{'class': 'item'})
+
+class AjaxMenuGroup(ObjectBase, Registry):
+    def __init__(self, label, items, visibility=None, weight=500):
+        super(AjaxMenuGroup, self).__init__(visibility, weight)
+        self.label = label
+
+        for item in items:
+            self.add(item)
+
+    def can_render(self, context):
+        if super(AjaxMenuGroup, self).can_render(context):
+            for item in self:
+                if item.can_render(context): return True
+
+        return False
+
+    def render(self, context):
+        return html.buildtag('li', self.label, **{'class': 'separator'}) + "".join([
+            item.render(context) for item in self if item.can_render(context)
+        ])
+
+class UserMenuItem(AjaxMenuItem):
+    def __init__(self, render_to=None, *args, **kwargs):
+        super(UserMenuItem, self).__init__(*args, **kwargs)
+        self.render_to = render_to
+
+    def can_render(self, context):
+        return (not self.render_to or (self.render_to(context['user']))) and super(UserMenuItem, self)._visible_to(context['viewer'])