X-Git-Url: https://git.openstreetmap.org/osqa.git/blobdiff_plain/f5fda79fa40310950e0c6f40a40619c701fd3f08..a60778963b1e3a694c83e6629b001cfc05918ad6:/forum/modules/ui_objects.py diff --git a/forum/modules/ui_objects.py b/forum/modules/ui_objects.py index b88ea50..7fae3d4 100644 --- a/forum/modules/ui_objects.py +++ b/forum/modules/ui_objects.py @@ -2,9 +2,12 @@ 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'): + def __init__(self, level='public', negated=False): if level not in ['public', 'authenticated', 'staff', 'superuser', 'owner']: try: int(level) @@ -15,18 +18,29 @@ class Visibility(object): self.by_reputation = False self.level = level + self.negated = negated 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): + return Visibility(self.level, not self.negated) + + Visibility.PUBLIC = Visibility('public') +Visibility.ANONYMOUS = Visibility('authenticated', negated=True) Visibility.AUTHENTICATED = Visibility('authenticated') Visibility.STAFF = Visibility('staff') Visibility.SUPERUSER = Visibility('superuser') @@ -49,16 +63,27 @@ 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 - def __init__(self, visibility=None, weight=500): + 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): - 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 '' @@ -70,8 +95,8 @@ class LoopBase(ObjectBase): class Link(ObjectBase): - def __init__(self, text, url, attrs=None, pre_code='', post_code='', visibility=None, weight=500): - super(Link, self).__init__(visibility, weight) + 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 {}) @@ -84,8 +109,8 @@ class Link(ObjectBase): self.post_code(context)) class Include(ObjectBase): - def __init__(self, tpl, visibility=None, weight=500): - super(Include, self).__init__(visibility, weight) + 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): @@ -95,8 +120,8 @@ class Include(ObjectBase): class LoopContext(LoopBase): - def __init__(self, loop_context, visibility=None, weight=500): - super(LoopContext, self).__init__(visibility, weight) + 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): @@ -104,8 +129,8 @@ class LoopContext(LoopBase): class PageTab(LoopBase): - def __init__(self, tab_name, tab_title, url_getter, weight): - super(PageTab, self).__init__(weight=weight) + 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 @@ -120,7 +145,7 @@ class PageTab(LoopBase): class ProfileTab(LoopBase): def __init__(self, name, title, description, url_getter, private=False, render_to=None, weight=500): - super(ProfileTab, self).__init__(weight=weight) + super(ProfileTab, self).__init__(weight=weight, name=name) self.name = name self.title = title self.description = description @@ -139,4 +164,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, 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'])