]> git.openstreetmap.org Git - osqa.git/blobdiff - forum/modules/ui_objects.py
Adds the user menu to the injectable places, makes several improvements in the user...
[osqa.git] / forum / modules / ui_objects.py
index 70bee93a1b695d69aa9325a93ad1668a127c29e9..7fcf96caea9ccb155a4854492279f7c5ff452937 100644 (file)
@@ -1,6 +1,9 @@
 from django.core.urlresolvers import reverse
 from django.template.defaultfilters import slugify
+from django import template
 from forum.utils import html
+from ui import Registry
+from copy import copy
 
 class Visibility(object):
     def __init__(self, level='public'):
@@ -14,17 +17,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')
@@ -48,7 +62,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 None
+                return self.argument(user, context)
             else:
                 return self.argument
 
@@ -56,8 +71,14 @@ 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:
+            return True
 
     def render(self, context):
         return ''
@@ -82,6 +103,16 @@ class Link(ObjectBase):
             html.hyperlink(self.url(context), self.text(context), **self.attrs(context)),
             self.post_code(context))
 
+class Include(ObjectBase):
+    def __init__(self, tpl, visibility=None, weight=500):
+        super(Include, self).__init__(visibility, weight)
+        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)
+        
 
 class LoopContext(LoopBase):
     def __init__(self, loop_context, visibility=None, weight=500):
@@ -108,17 +139,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(
@@ -126,4 +159,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'])