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 forum.models.user import AnonymousUser
 
   6 from ui import Registry
 
   9 class Visibility(object):
 
  10     def __init__(self, level='public', negated=False):
 
  11         if level not in ['public', 'authenticated', 'staff', 'superuser', 'owner']:
 
  14                 self.by_reputation = True
 
  16                 raise "Invalid visibility level for ui object: %s" % level
 
  18             self.by_reputation = False
 
  21         self.negated = negated
 
  23     def show_to(self, user):
 
  24         if self.by_reputation:
 
  25             res = user.is_authenticated() and (user.reputation >= int(self.level) or user.is_staff or user.is_superuser)
 
  27             res = self.level == 'public' or (user.is_authenticated() and (
 
  28                 self.level == 'authenticated' or (
 
  29                 self.level == 'superuser' and user.is_superuser) or (
 
  30                 self.level == 'staff' and (user.is_staff or user.is_superuser)) or (
 
  31                 self.level == 'owner' and user.is_siteowner)))
 
  39         return Visibility(self.level, not self.negated)
 
  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)
 
  51     def __init__(self, url_pattern):
 
  52         self.url_pattern = url_pattern
 
  54     def __call__(self, u, c):
 
  55         return reverse(self.url_pattern)
 
  58 class ObjectBase(object):
 
  59     class Argument(object):
 
  60         def __init__(self, argument):
 
  61             self.argument = argument
 
  63         def __call__(self, context):
 
  64             if callable(self.argument):
 
  65                 user = context.get('request', None) and context['request'].user or AnonymousUser()
 
  66                 return self.argument(user, context)
 
  70     def __init__(self, visibility=None, weight=500, name=''):
 
  71         self.visibility = visibility
 
  75     def _visible_to(self, user):
 
  76         return (not self.visibility) or (self.visibility and self.visibility.show_to(user))
 
  78     def can_render(self, context):
 
  80             return self._visible_to(context['request'].user)
 
  83                 return self._visible_to(context['viewer'])
 
  85                 return self._visible_to(AnonymousUser())
 
  87     def render(self, context):
 
  90 class LoopBase(ObjectBase):
 
  91     def update_context(self, context):
 
  96 class Link(ObjectBase):
 
  97     def __init__(self, text, url, attrs=None, pre_code='', post_code='', visibility=None, weight=500, name=''):
 
  98         super(Link, self).__init__(visibility, weight, name)
 
  99         self.text = self.Argument(text)
 
 100         self.url = self.Argument(url)
 
 101         self.attrs = self.Argument(attrs or {})
 
 102         self.pre_code = self.Argument(pre_code)
 
 103         self.post_code = self.Argument(post_code)
 
 105     def render(self, context):
 
 106         return "%s %s %s" % (self.pre_code(context),
 
 107             html.hyperlink(self.url(context), self.text(context), **self.attrs(context)),
 
 108             self.post_code(context))
 
 110 class Include(ObjectBase):
 
 111     def __init__(self, tpl, visibility=None, weight=500, name=''):
 
 112         super(Include, self).__init__(visibility, weight, name)
 
 113         self.template = template.loader.get_template(tpl)
 
 115     def render(self, context):
 
 116         if not isinstance(context, template.Context):
 
 117             context = template.Context(context)
 
 118         return self.template.render(context)
 
 121 class LoopContext(LoopBase):
 
 122     def __init__(self, loop_context, visibility=None, weight=500, name=''):
 
 123         super(LoopContext, self).__init__(visibility, weight, name)
 
 124         self.loop_context = self.Argument(loop_context)
 
 126     def update_context(self, context):
 
 127         context.update(self.loop_context(context))
 
 130 class PageTab(LoopBase):
 
 131     def __init__(self, tab_name, tab_title, url_getter, weight, name=''):
 
 132         super(PageTab, self).__init__(weight=weight, name=name)
 
 133         self.tab_name = tab_name
 
 134         self.tab_title = tab_title
 
 135         self.url_getter = url_getter
 
 137     def update_context(self, context):
 
 139             tab_name=self.tab_name,
 
 140             tab_title=self.tab_title,
 
 141             tab_url=self.url_getter()
 
 145 class ProfileTab(LoopBase):
 
 146     def __init__(self, name, title, description, url_getter, private=False, render_to=None, weight=500):
 
 147         super(ProfileTab, self).__init__(weight=weight, name=name)
 
 150         self.description = description
 
 151         self.url_getter = url_getter
 
 152         self.private = private
 
 153         self.render_to = render_to
 
 155     def can_render(self, context):
 
 156         return (not self.render_to or (self.render_to(context['view_user']))) and (
 
 157             not self.private or (
 
 158             context['view_user'] == context['request'].user or context['request'].user.is_superuser))
 
 160     def update_context(self, context):        
 
 163             tab_title=self.title,
 
 164             tab_description = self.description,
 
 165             tab_url=self.url_getter(context['view_user'])
 
 169 class AjaxMenuItem(ObjectBase):
 
 170     def __init__(self, label, url, a_attrs=None, span_label='', span_attrs=None, visibility=None, weight=500, name=''):
 
 171         super(AjaxMenuItem, self).__init__(visibility, weight, name)
 
 172         self.label = self.Argument(label)
 
 173         self.url = self.Argument(url)
 
 174         self.a_attrs = self.Argument(a_attrs or {})
 
 175         self.span_label = self.Argument(span_label)
 
 176         self.span_attrs = self.Argument(span_attrs or {})
 
 178     def render(self, context):
 
 179         return html.buildtag('li',
 
 180             html.buildtag('span', self.span_label(context), **self.span_attrs(context)) + \
 
 181             html.hyperlink(self.url(context), self.label(context), **self.a_attrs(context)),
 
 184 class AjaxMenuGroup(ObjectBase, Registry):
 
 185     def __init__(self, label, items, visibility=None, weight=500, name=''):
 
 186         super(AjaxMenuGroup, self).__init__(visibility, weight, name)
 
 192     def can_render(self, context):
 
 193         if super(AjaxMenuGroup, self).can_render(context):
 
 195                 if item.can_render(context): return True
 
 199     def render(self, context):
 
 200         return html.buildtag('li', self.label, **{'class': 'separator'}) + "".join([
 
 201             item.render(context) for item in self if item.can_render(context)
 
 204 class UserMenuItem(AjaxMenuItem):
 
 205     def __init__(self, render_to=None, *args, **kwargs):
 
 206         super(UserMenuItem, self).__init__(*args, **kwargs)
 
 207         self.render_to = render_to
 
 209     def can_render(self, context):
 
 210         return (not self.render_to or (self.render_to(context['user']))) and super(UserMenuItem, self)._visible_to(context['viewer'])