• Giuseppe Terrasi's avatar
    · 795d73a4
    Giuseppe Terrasi authored
    Initial release based on svn rev 1272 with no changes
    795d73a4
ui_objects.py.svn-base 7.33 KB
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', negated=False):
        if level not in ['public', 'authenticated', 'staff', 'superuser', 'owner']:
            try:
                int(level)
                self.by_reputation = True
            except:
                raise "Invalid visibility level for ui object: %s" % level
        else:
            self.by_reputation = False

        self.level = level
        self.negated = negated

    def show_to(self, user):
        if self.by_reputation:
            res = user.is_authenticated() and (user.reputation >= int(self.level) or user.is_staff or user.is_superuser)
        else:
            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):
        return Visibility(self.level, not self.negated)
        

Visibility.PUBLIC = Visibility('public')
Visibility.AUTHENTICATED = Visibility('authenticated')
Visibility.STAFF = Visibility('staff')
Visibility.SUPERUSER = Visibility('superuser')
Visibility.OWNER = Visibility('owner')
Visibility.REPUTED = lambda r: Visibility(r)


class Url(object):
    def __init__(self, url_pattern):
        self.url_pattern = url_pattern

    def __call__(self, u, c):
        return reverse(self.url_pattern)


class ObjectBase(object):
    class Argument(object):
        def __init__(self, argument):
            self.argument = argument

        def __call__(self, context):
            if callable(self.argument):
                user = context.get('request', None) and context['request'].user or AnonymousUser()
                return self.argument(user, context)
            else:
                return self.argument

    def __init__(self, visibility=None, weight=500, name=''):
        self.visibility = visibility
        self.weight = weight
        self.name = name

    def _visible_to(self, user):
        return (not self.visibility) or (self.visibility and self.visibility.show_to(user))

    def can_render(self, context):
        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 ''

class LoopBase(ObjectBase):
    def update_context(self, context):
        pass



class Link(ObjectBase):
    def __init__(self, text, url, attrs=None, pre_code='', post_code='', visibility=None, weight=500, name=''):
        super(Link, self).__init__(visibility, weight, name)
        self.text = self.Argument(text)
        self.url = self.Argument(url)
        self.attrs = self.Argument(attrs or {})
        self.pre_code = self.Argument(pre_code)
        self.post_code = self.Argument(post_code)

    def render(self, context):
        return "%s %s %s" % (self.pre_code(context),
            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, name=''):
        super(Include, self).__init__(visibility, weight, name)
        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, name=''):
        super(LoopContext, self).__init__(visibility, weight, name)
        self.loop_context = self.Argument(loop_context)

    def update_context(self, context):
        context.update(self.loop_context(context))


class PageTab(LoopBase):
    def __init__(self, tab_name, tab_title, url_getter, weight, name=''):
        super(PageTab, self).__init__(weight=weight, name=name)
        self.tab_name = tab_name
        self.tab_title = tab_title
        self.url_getter = url_getter

    def update_context(self, context):
        context.update(dict(
            tab_name=self.tab_name,
            tab_title=self.tab_title,
            tab_url=self.url_getter()
        ))


class ProfileTab(LoopBase):
    def __init__(self, name, title, description, url_getter, private=False, render_to=None, weight=500):
        super(ProfileTab, self).__init__(weight=weight, name=name)
        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.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(
            tab_name=self.name,
            tab_title=self.title,
            tab_description = self.description,
            tab_url=self.url_getter(context['view_user'])
        ))


class AjaxMenuItem(ObjectBase):
    def __init__(self, label, url, a_attrs=None, span_label='', span_attrs=None, visibility=None, weight=500, name=''):
        super(AjaxMenuItem, self).__init__(visibility, weight, name)
        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, name=''):
        super(AjaxMenuGroup, self).__init__(visibility, weight, name)
        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'])