X-Git-Url: https://git.openstreetmap.org./osqa.git/blobdiff_plain/d2410575d72f68d7777c4344600b1af75f2515c1..c8c6b98a7b2a365878871131e0f42c40d6b499fc:/forum/modules/ui_objects.py diff --git a/forum/modules/ui_objects.py b/forum/modules/ui_objects.py index 01a61d3..e7f626f 100644 --- a/forum/modules/ui_objects.py +++ b/forum/modules/ui_objects.py @@ -1,96 +1,212 @@ 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'): + 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 -class UiObjectUserLevelBase(object): - def show_to(self, user): - return True + self.level = level + self.negated = False -class SuperuserUiObject(UiObjectUserLevelBase): def show_to(self, user): - return user.is_superuser - -class StaffUiObject(UiObjectUserLevelBase): - def show_to(self, user): - return user.is_staff or user.is_superuser - -class ReputedUserUiObject(UiObjectUserLevelBase): - def __init__(self, min_rep): - self.min_rep = min_rep + 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 show_to(self, user): - return user.is_authenticated() and user.reputation >= int(self.min_rep) + def __invert__(self): + inverted = copy(self) + inverted.negated = True + -class LoggedInUserUiObject(UiObjectUserLevelBase): - def show_to(self, user): - return user.is_authenticated() +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 PublicUiObject(UiObjectUserLevelBase): - pass +class Url(object): + def __init__(self, url_pattern): + self.url_pattern = url_pattern + def __call__(self, u, c): + return reverse(self.url_pattern) -class UiObjectArgument(object): - def __init__(self, argument): - self.argument = argument - def __call__(self, context): - if callable(self.argument): - return self.argument(context) - else: - return self.argument +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 None + return self.argument(user, context) + else: + return self.argument -class UiObjectBase(object): - def __init__(self, user_level=None, weight=500): - self.user_level = user_level or PublicUiObject() + def __init__(self, visibility=None, weight=500): + 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 self.user_level.show_to(context['request'].user) + try: + return self._visible_to(context['request'].user) + except KeyError: + try: + return self._visible_to(context['viewer']) + except KeyError: + if self.visibility: + return False + else: + return True def render(self, context): return '' -class UiLoopObjectBase(UiObjectBase): +class LoopBase(ObjectBase): def update_context(self, context): pass -class UiLinkObject(UiObjectBase): - def __init__(self, text, url, attrs=None, pre_code='', post_code='', user_level=None, weight=500): - super(UiLinkObject, self).__init__(user_level, weight) - self.text = UiObjectArgument(text) - self.url = UiObjectArgument(url) - self.attrs = UiObjectArgument(attrs or {}) - self.pre_code = UiObjectArgument(pre_code) - self.post_code = UiObjectArgument(post_code) +class Link(ObjectBase): + def __init__(self, text, url, attrs=None, pre_code='', post_code='', visibility=None, weight=500): + super(Link, self).__init__(visibility, weight) + 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): + 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 UiLoopContextObject(UiLoopObjectBase): - def __init__(self, loop_context, user_level=None, weight=500): - super(UiLoopContextObject, self).__init__(user_level, weight) - self.loop_context = UiObjectArgument(loop_context) +class LoopContext(LoopBase): + def __init__(self, loop_context, visibility=None, weight=500): + super(LoopContext, self).__init__(visibility, weight) + self.loop_context = self.Argument(loop_context) def update_context(self, context): context.update(self.loop_context(context)) -class UiTopPageTabObject(UiLoopObjectBase): - def __init__(self, tab_name, tab_title, url_pattern, weight): - super(UiTopPageTabObject, self).__init__(weight=weight) +class PageTab(LoopBase): + def __init__(self, tab_name, tab_title, url_getter, weight): + super(PageTab, self).__init__(weight=weight) self.tab_name = tab_name self.tab_title = tab_title - self.url_pattern = url_pattern + 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=reverse(self.url_pattern) + 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) + 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): + 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'])