]> git.openstreetmap.org Git - osqa.git/commitdiff
Adds the user menu to the injectable places, makes several improvements in the user...
authorhernani <hernani@0cfe37f9-358a-4d5e-be75-b63607b5c754>
Mon, 5 Jul 2010 10:29:48 +0000 (10:29 +0000)
committerhernani <hernani@0cfe37f9-358a-4d5e-be75-b63607b5c754>
Mon, 5 Jul 2010 10:29:48 +0000 (10:29 +0000)
git-svn-id: http://svn.osqa.net/svnroot/osqa/trunk@487 0cfe37f9-358a-4d5e-be75-b63607b5c754

18 files changed:
forum/forms/qanda.py
forum/models/user.py
forum/modules/ui.py
forum/modules/ui_objects.py
forum/registry.py [new file with mode: 0644]
forum/skins/default/media/js/osqa.main.js
forum/skins/default/media/js/osqa.user.js [deleted file]
forum/skins/default/media/style/style.css
forum/skins/default/templates/node/post_controls.html
forum/skins/default/templates/user.html
forum/skins/default/templates/users/edit.html
forum/skins/default/templates/users/footer.html [deleted file]
forum/skins/default/templates/users/karma_bonus.html [new file with mode: 0644]
forum/skins/default/templates/users/menu.html
forum/skins/default/templates/users/subscriptions.html
forum/startup.py
forum/utils/html.py
forum/views/users.py

index d482d01e190750db27dcf833bf205d734b420cef..a98ef38ad6b5e54a24c79d1bb7f641cff28126ff 100644 (file)
@@ -276,7 +276,7 @@ NOTIFICATION_CHOICES = (
 )
 
 class SubscriptionSettingsForm(forms.ModelForm):
-    user = forms.IntegerField(widget=forms.HiddenInput)
+    enable_notifications = forms.BooleanField(widget=forms.HiddenInput, required=False)
     member_joins = forms.ChoiceField(widget=forms.RadioSelect, choices=NOTIFICATION_CHOICES)
     new_question = forms.ChoiceField(widget=forms.RadioSelect, choices=NOTIFICATION_CHOICES)
     new_question_watched_tags = forms.ChoiceField(widget=forms.RadioSelect, choices=NOTIFICATION_CHOICES)
@@ -286,3 +286,4 @@ class SubscriptionSettingsForm(forms.ModelForm):
         model = SubscriptionSettings
 
 
+
index f3a038993deba9762ce454313bb24cc89c4b5c4e..7f1df5f65598ed958d762d6356eaf259b9c05f2c 100644 (file)
@@ -331,13 +331,13 @@ class User(BaseModel, DjangoUser):
     def suspension(self):
         if self.__dict__.get('_suspension_dencache_', False) != None:
             try:
-                self.__dict__['_suspension_dencache_'] = self.actions.get(action_type="suspend", canceled=False)
+                self.__dict__['_suspension_dencache_'] = self.reputes.get(action__action_type="suspend", action__canceled=False).action
             except ObjectDoesNotExist:
                 self.__dict__['_suspension_dencache_'] = None
             except MultipleObjectsReturned:
                 logging.error("Multiple suspension actions found for user %s (%s)" % (self.username, self.id))
-                self.__dict__['_suspension_dencache_'] = self.actions.filter(action_type="suspend", canceled=False
-                                                                             ).order_by('-action_date')[0]
+                self.__dict__['_suspension_dencache_'] = self.reputes.filter(action__action_type="suspend", action__canceled=False
+                                                                             ).order_by('-action__action_date')[0]
 
         return self.__dict__['_suspension_dencache_']
 
@@ -419,7 +419,7 @@ class UserPropertyDict(object):
 
 
 class SubscriptionSettings(models.Model):
-    user = models.OneToOneField(User, related_name='subscription_settings')
+    user = models.OneToOneField(User, related_name='subscription_settings', editable=False)
 
     enable_notifications = models.BooleanField(default=True)
 
index 49ce249b1c2b282a5d4ee619035dd9e1a934e1cc..48c0246efc6d67dafd055d75fe5ab1027093a8d8 100644 (file)
@@ -1,13 +1,13 @@
 
 
 class Registry(list):
-    def add(self, register):
+    def add(self, item):
         for i, r in enumerate(self):
-            if r.weight > register.weight:
-                self.insert(i, register)
+            if r.weight > item.weight:
+                self.insert(i, item)
                 return
 
-        self.append(register)
+        self.append(item)
 
 
 HEAD_CONTENT = 'HEAD_CONTENT'
@@ -16,6 +16,8 @@ PAGE_TOP_TABS = 'PAGE_TOP_TABS'
 FOOTER_LINKS = 'FOOTER_LINKS'
 PROFILE_TABS = 'PROFILE_TABS'
 
+USER_MENU = 'USER_MENU'
+
 
 __CONTAINER = {
     HEAD_CONTENT: Registry(),
@@ -23,6 +25,8 @@ __CONTAINER = {
     PAGE_TOP_TABS: Registry(),
     FOOTER_LINKS: Registry(),
     PROFILE_TABS: Registry(),
+
+    USER_MENU: Registry(),
 }
 
 
index b88ea50029c5b6c12e40bd0e37ae8a9a3a0ce877..7fcf96caea9ccb155a4854492279f7c5ff452937 100644 (file)
@@ -2,6 +2,8 @@ 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'):
@@ -15,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')
@@ -49,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
 
@@ -57,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 ''
@@ -139,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'])
diff --git a/forum/registry.py b/forum/registry.py
new file mode 100644 (file)
index 0000000..6fad2f0
--- /dev/null
@@ -0,0 +1,103 @@
+from forum.modules import ui
+from django.utils.translation import ugettext as _
+from django.core.urlresolvers import reverse
+from django.template.defaultfilters import slugify
+from forum.templatetags.extra_tags import get_score_badge
+from forum import settings
+
+
+ui.register(ui.HEADER_LINKS,
+            ui.Link(_('faq'), ui.Url('faq'), weight=400),
+            ui.Link(_('about'), ui.Url('about'), weight=300),
+
+            ui.Link(
+                    text=lambda u, c: u.is_authenticated() and _('logout') or _('login'),
+                    url=lambda u, c: u.is_authenticated() and reverse('logout') or reverse('auth_signin'),
+                    weight=200),
+
+            ui.Link(
+                    visibility=ui.Visibility.AUTHENTICATED,
+                    text=lambda u, c: u.username,
+                    url=lambda u, c: u.get_profile_url(),
+                    post_code=lambda u, c: get_score_badge(u),
+                    weight=100),
+
+            ui.Link(
+                    visibility=ui.Visibility.SUPERUSER,
+                    text=_('administration'),
+                    url=lambda u, c: reverse('admin_index'),
+                    weight=0)
+
+)
+
+class SupportLink(ui.Link):
+    def can_render(self, context):
+        return bool(settings.SUPPORT_URL)
+
+
+ui.register(ui.FOOTER_LINKS,
+            ui.Link(
+                    text=_('contact'),
+                    url=lambda u, c: settings.CONTACT_URL and settings.CONTACT_URL or "%s?next=%s" % (reverse('feedback'), c['request'].path),
+                    weight=400),
+            SupportLink(_('support'), settings.SUPPORT_URL, attrs={'target': '_blank'}, weight=300),
+            ui.Link(_('privacy'), ui.Url('privacy'), weight=200),
+            ui.Link(_('faq'), ui.Url('faq'), weight=100),
+            ui.Link(_('about'), ui.Url('about'), weight=0),
+)
+
+class ModerationMenuGroup(ui.AjaxMenuGroup):
+    def can_render(self, context):
+        return context['user'] != context['viewer'] and super(ModerationMenuGroup, self).can_render(context)
+
+class SuperUserSwitchMenuItem(ui.UserMenuItem):
+    def can_render(self, context):
+        return context['viewer'].is_siteowner or not context['user'].is_superuser
+
+ui.register(ui.USER_MENU,
+            ui.UserMenuItem(
+                label=_("edit profile"),
+                url=lambda u, c: reverse('edit_user', kwargs={'id': c['user'].id}),
+                span_attrs={'class': 'user-edit'},
+                weight=0
+            ),
+            ui.UserMenuItem(
+                label=_("authentication settings"),
+                url=lambda u, c: reverse('user_authsettings', kwargs={'id': c['user'].id}),
+                span_attrs={'class': 'user-auth'},
+                weight=100
+            ),
+            ui.UserMenuItem(
+                label=_("email notification settings"),
+                url=lambda u, c: reverse('user_subscriptions', kwargs={'id': c['user'].id, 'slug': slugify(c['user'].username)}),
+                span_attrs={'class': 'user-subscriptions'},
+                weight=200
+            ),
+            ModerationMenuGroup(_("Moderation tools"), items=(
+                ui.UserMenuItem(
+                    label=lambda u, c: c['user'].is_suspended() and _("withdraw suspension") or _("suspend this user"),
+                    url=lambda u, c: reverse('user_suspend', kwargs={'id': c['user'].id}),
+                    a_attrs=lambda u, c: {'class': c['user'].is_suspended() and 'ajax-command confirm' or 'ajax-command withprompt'},
+                    render_to=lambda u: not u.is_superuser,
+                ),
+                ui.UserMenuItem(
+                    label=lambda u, c: _("give/take karma"),
+                    url=lambda u, c: reverse('user_award_points', kwargs={'id': c['user'].id}),
+                    a_attrs=lambda u, c: {'id': 'award-rep-points', 'class': 'ajax-command withprompt'},
+                    span_attrs={'class': 'user-award_rep'},
+                    render_to=lambda u: not u.is_suspended(),
+                ),
+                ui.UserMenuItem(
+                    label=lambda u, c: c['user'].is_staff and _("remove moderator status") or _("grant moderator status"),
+                    url=lambda u, c: reverse('user_powers', kwargs={'id': c['user'].id, 'action':c['user'].is_staff and 'remove' or 'grant', 'status': 'staff'}),
+                    a_attrs=lambda u, c: {'class': 'ajax-command confirm'},
+                    span_attrs={'class': 'user-moderator'},
+                ),
+                SuperUserSwitchMenuItem(
+                    label=lambda u, c: c['user'].is_superuser and _("remove super user status") or _("grant super user status"),
+                    url=lambda u, c: reverse('user_powers', kwargs={'id': c['user'].id, 'action':c['user'].is_superuser and 'remove' or 'grant', 'status': 'super'}),
+                    a_attrs=lambda u, c: {'class': 'ajax-command confirm'},
+                    span_attrs={'class': 'user-superuser'},
+                ),
+            ), visibility=ui.Visibility.SUPERUSER, weight=500)
+)
index 270a6b4ab985a213e6bd9cca28816419d7dc6c6b..2a2a48e343a56672a5f5187f7d0b52d508663687 100644 (file)
@@ -299,6 +299,8 @@ $(function() {
     $('a.ajax-command').live('click', function(evt) {\r
         if (running) return false;\r
 \r
+        $('.context-menu-dropdown').slideUp('fast');\r
+\r
         var el = $(this);\r
 \r
         if (el.is('.withprompt')) {\r
@@ -344,7 +346,8 @@ $(function() {
             $dropdown.slideToggle('fast', function() {\r
                 if ($dropdown.is(':visible')) {\r
                    $dropdown.one('clickoutside', function() {\r
-                        $dropdown.slideUp('fast')\r
+                       if ($dropdown.is(':visible'))\r
+                            $dropdown.slideUp('fast');\r
                     });\r
                 }\r
             });    \r
diff --git a/forum/skins/default/media/js/osqa.user.js b/forum/skins/default/media/js/osqa.user.js
deleted file mode 100644 (file)
index 5241880..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-$().ready(function() {
-    var $dropdown = $('#user-menu-dropdown');
-
-    $('#user-menu').click(function() {
-        $('.dialog').fadeOut('fast', function() {
-            $dialog.remove();
-        });
-        $dropdown.slideToggle('fast', function() {
-            if ($dropdown.is(':visible')) {
-                $dropdown.one('clickoutside', function() {
-                    $dropdown.slideUp('fast')
-                });
-            }
-        });
-    });
-
-    $('.confirm').each(function() {
-        var $link = $(this);
-
-        $link.click(function(e) {
-            $dropdown.slideUp('fast');
-
-            show_dialog({
-                html: messages.confirm,
-                extra_class: 'confirm',
-                event: e,
-                yes_callback: function() {
-                    window.location = $link.attr('href');
-                },
-                yes_text: messages.yes,
-                show_no: true,
-                no_text: messages.no
-            });
-
-            return false;
-        });
-    });
-
-    $('#award-rep-points').click(function(e) {
-        $dropdown.slideUp('fast');
-
-        var table = '<table><tr><th>' + messages.points + '</th><td><input type="text" id="points-to-award" value="1" /></td></tr>'
-                + '<tr><th>' + messages.message + '</th><td><textarea id="award-message"></textarea></td></tr></table>';
-
-        show_dialog({
-            html: table,
-            extra_class: 'award-rep-points',
-            event: e,
-            yes_callback: function($dialog) {
-                var $points_input = $('#points-to-award');
-                var _points = parseInt($points_input.val());
-
-                if (!isNaN(_points)) {
-                    $dialog.fadeOut('fast');
-                    var _message = $('#award-message').val();
-                    $.post($('#award-rep-points').attr('href'), {points: _points, message: _message}, function(data) {
-                        if (data.success) {
-                            $('#user-reputation').css('background', 'yellow');
-                            $('#user-reputation').html(data.reputation);
-
-                            $('#user-reputation').animate({ backgroundColor: "transparent" }, 1000);
-
-                        }
-                    }, 'json')
-                }
-            },
-            show_no: true
-        });
-
-        return false;
-    });
-
-});
\ No newline at end of file
index e0605d6e77adb546a5601e38fb7fb2dd4ca0168e..c61c065daa746e0e5b707d2b087b69fcdb1d5fb1 100644 (file)
@@ -1622,6 +1622,7 @@ div.dialog, .context-menu-dropdown {
     top: 1.5em;
     text-align: left;
     list-style-type: none;
+    z-index: 500;
 }
 
 .context-menu-dropdown li.item {
@@ -1661,6 +1662,7 @@ div.dialog, .context-menu-dropdown {
 
 div.dialog .dialog-content {
     padding: 12px 12px 37px 12px;
+    z-index: 1000;
 }
 
 div.dialog .dialog-buttons {
index c34e50fff1cf6af442fb9304953770e085b13c6f..e756fff3be992e219c70909ddca5f5e507064fd3 100644 (file)
@@ -10,9 +10,9 @@
 {% endfor %}\r
 {% if menu|length %}\r
     <span class="action-link-separator">|</span>\r
-    <span id="node-{{ node.id }}-menu" class="context-menu">\r
-        <span id="node-{{ node.id }}-menu-trigger" class="action-link context-menu-trigger">{% trans "more" %} &#9660;</span>\r
-        <ul id="node-{{ node.id }}-menu-dropdown" class="context-menu-dropdown">\r
+    <span id="node-{{ post.id }}-menu" class="context-menu">\r
+        <span id="node-{{ post.id }}-menu-trigger" class="action-link context-menu-trigger">{% trans "more" %} &#9660;</span>\r
+        <ul id="node-{{ post.id }}-menu-dropdown" class="context-menu-dropdown">\r
             {% for item in menu %}\r
             <li class="item"><a class="{{ item.classes }}" href="{{ item.url }}" title="{{ item.title }}" >{{ item.text }}</a></li>\r
             {% endfor %}\r
index 89fd69f396ecf9de6111b72722506c8bfce3b9b7..ec852cc3896fea4a62387a63522d753bd89c69b4 100644 (file)
 {% block forejs %}
     {% if request.user.is_superuser or request.user == view_user %}
         <script type="text/javascript">google.load("jquery", "1.4.2");google.load("jqueryui", "1.8.1");</script>
-        <script src="{% media "/media/js/osqa.user.js" %}" type="text/javascript"></script>
+        <script type="text/javascript">
+            response_commands['update_profile_karma'] = function(new_karma) {
+                $('#user-reputation').css('background', 'yellow');
+                $('#user-reputation').html(new_karma);
+                $('#user-reputation').animate({ backgroundColor: "transparent" }, 1000);
+            }
+        </script>
 
         <link rel="stylesheet" href="http://jquery-ui.googlecode.com/svn/tags/latest/themes/base/jquery-ui.css" type="text/css" media="all" />
         <link rel="stylesheet" href="http://static.jquery.com/ui/css/demo-docs-theme/ui.theme.css" type="text/css" media="all" />
         <link rel="stylesheet" type="text/css" media="screen" href="{% media "/media/style/user.css" %}"/>
     {% endif %}
-    <script type="text/javascript">
-        var viewUserID = {{view_user.id}};
-        $().ready(function(){
-            {% ifequal view_user request.user%}
-                $("#nav_profile").attr('className',"on");
-            {% else %}
-                $("#nav_users").attr('className',"on");
-            {% endifequal %}
-        });
-    </script>
-    {% block userjs %}
-    {% endblock %}
+    {% block userjs %}{% endblock %}
 {% endblock %}
 {% block content %}
     <div id="mainbar-full">
@@ -40,6 +35,5 @@
         {% include "users/tabs.html" %}
         {% block usercontent %}
         {% endblock %}
-        {%comment%}{% include "users/footer.html" %}{%endcomment%}
        </div>
 {% endblock %}<!-- end user.html -->
index e21bf32e3d8c51427c32a3a4f3ba8cc3338572f5..3240fd25f91efa91566249f26c0a30ca8d063371 100644 (file)
@@ -42,7 +42,7 @@
             {% endif %}\r
             <div style="padding:20px 0 0 20px;font-weight:bold;font-size:150%">\r
                 <a href="http://www.gravatar.com/" target="_blank" \r
-                                       title="gravatar {% trans "image associated with your email address" %}">{% blocktrans %}avatar, see {{gravatar_faq_url}}{% endblocktrans %}</a>\r
+                                       title="gravatar {% trans "image associated with your email address" %}">{% trans "gravatar" %}</a>\r
             </div>\r
         </div>\r
         \r
diff --git a/forum/skins/default/templates/users/footer.html b/forum/skins/default/templates/users/footer.html
deleted file mode 100644 (file)
index ee34774..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-<!-- user_footer.html -->
-<div id="mainbar-footer">
-
-</div><!-- end user_footer.html -->
diff --git a/forum/skins/default/templates/users/karma_bonus.html b/forum/skins/default/templates/users/karma_bonus.html
new file mode 100644 (file)
index 0000000..b39c276
--- /dev/null
@@ -0,0 +1,12 @@
+{% load i18n %}
+
+<table>
+    <tr>
+        <th>{% trans "Points" %}:</th>
+        <td><input type="text" id="points-to-award" name="points" value="1" /></td>
+    </tr>
+    <tr>
+        <th>{% trans "Message" %}:</th>
+        <td><textarea id="award-message" name="message"></textarea></td>
+    </tr>
+</table>
\ No newline at end of file
index 650c41f4e996d09661775ba05086b44c2cc20bee..24d213d06cb72e9dfaa44759107c7830bbf5187e 100644 (file)
@@ -1,57 +1,8 @@
-{% load i18n %}\r
-{% load smart_if %}\r
+{% load i18n smart_if ui_registry %}\r
 \r
-<script type="text/javascript">\r
-    messages['points'] = "{% trans "Points" %}"\r
-</script>\r
-\r
-<div id="user-menu-container">\r
-    <span id="user-menu">{% trans "User tools" %} &#9660;</span>\r
-    <ul id="user-menu-dropdown">\r
-        <li class="item"><span class="user-edit"></span><a href="{% url edit_user id=user.id %}">{% trans "edit profile" %}</a></li>\r
-        <li class="item"><span class="user-auth"></span><a href="{% url user_authsettings id=user.id %}">{% trans "authentication settings" %}</a></li>\r
-        <li class="item"><span class="user-subscriptions"></span><a href="{% url user_subscriptions id=user.id,slug=user.username|slugify %}">{% trans "email notification settings" %}</a></li>\r
-        {% ifnotequal user viewer %}\r
-            {% if viewer.is_superuser %}\r
-            <li class="separator">{% trans "Moderation tools" %}</li>\r
-            {% if not user.is_superuser %}\r
-                {% if user.is_suspended %}\r
-                <li class="item"><span></span>\r
-                    <a href="{% url user_suspend id=user.id %}" class="ajax-command confirm" id="suspend-user">{% trans "withdraw suspension" %}</a>\r
-                </li>\r
-                {% else %}\r
-                <li class="item"><span></span>\r
-                    <a href="{% url user_suspend id=user.id %}" class="ajax-command withprompt" id="suspend-user">{% trans "suspend this user" %}</a>\r
-                </li>\r
-                {% endif %}\r
-            {% endif %}\r
-            {% if not user.is_suspended %}\r
-                <li class="item"><span class="user-award_rep"></span>\r
-                    <a href="{% url user_award_points id=user.id %}" id="award-rep-points">{% trans "reputation bonus" %}</a>\r
-                </li>\r
-            {% endif %}\r
-                {% if not user.is_superuser %}\r
-                    {% if not user.is_staff %}\r
-                    <li class="item"><span class="user-moderator"></span>\r
-                        <a class="confirm" href="{% url user_powers id=user.id,action="grant",status="staff" %}">{% trans "grant moderator status" %}</a>\r
-                    </li>\r
-                    {% else %}\r
-                    <li class="item"><span class="user-moderator"></span>\r
-                        <a class="confirm" href="{% url user_powers id=user.id,action="remove",status="staff" %}">{% trans "remove moderator status" %}</a>\r
-                    </li>\r
-                    {% endif %}\r
-                    <li class="item"><span class="user-superuser"></span>\r
-                        <a class="confirm" href="{% url user_powers id=user.id,action="grant",status="super" %}">{% trans "grant super user status" %}</a>\r
-                    </li>\r
-                {% else %}\r
-                    {% if viewer.is_siteowner %}\r
-                    <li class="item"><span class="user-superuser"></span>\r
-                        <a class="confirm" href="{% url user_powers id=user.id,action="remove",status="super" %}">{% trans "remove super user status" %}</a>\r
-                    </li>\r
-                    {% endif %}\r
-                {% endif %}\r
-            {% endif %}\r
-        {% endifnotequal %}\r
+<div id="user-menu-container" class="context-menu">\r
+    <span id="user-menu" class="context-menu-trigger">{% trans "User tools" %} &#9660;</span>\r
+    <ul id="user-menu-dropdown" class="context-menu-dropdown">\r
+        {% loadregistry user_menu %}{% endloadregistry %}\r
     </ul>\r
 </div>\r
-\r
index dcbea98dc006e728004d135a580353ba219f8b50..a6a93e3c5ea2cdd93f18ae6e618d4b7b94950dfd 100644 (file)
             <input type="submit" class="submit" name="notswitch" value="{% trans "Start notifications" %}"/>            \r
             {% endif %}\r
         </div>\r
-        {{ form.user }}\r
     </form>\r
     </div>\r
 {% endblock %}\r
index d203ab2dfec0e0e8e0beb85008504566f772cb90..a5ae1dbbc1a2f6526c962dac7e80f21fbf8320b7 100644 (file)
@@ -3,7 +3,7 @@ import os
 sys.path.append(os.path.join(os.path.dirname(__file__),'markdownext'))
 
 
-from forum.modules import get_modules_script, ui
+from forum.modules import get_modules_script
 
 get_modules_script('settings')
 get_modules_script('startup')
@@ -11,55 +11,7 @@ get_modules_script('startup')
 
 import forum.badges
 import forum.subscriptions
-
-
-from django.utils.translation import ugettext as _
-from django.core.urlresolvers import reverse
-from forum.templatetags.extra_tags import get_score_badge
-from forum import settings
-
-
-ui.register(ui.HEADER_LINKS,
-            ui.Link(_('faq'), ui.Url('faq'), weight=400),
-            ui.Link(_('about'), ui.Url('about'), weight=300),
-
-            ui.Link(
-                    text=lambda u, c: u.is_authenticated() and _('logout') or _('login'),
-                    url=lambda u, c: u.is_authenticated() and reverse('logout') or reverse('auth_signin'),
-                    weight=200),
-
-            ui.Link(
-                    visibility=ui.Visibility.AUTHENTICATED,
-                    text=lambda u, c: u.username,
-                    url=lambda u, c: u.get_profile_url(),
-                    post_code=lambda u, c: get_score_badge(u),
-                    weight=100),
-
-            ui.Link(
-                    visibility=ui.Visibility.SUPERUSER,
-                    text=_('administration'),
-                    url=lambda u, c: reverse('admin_index'),
-                    weight=0)
-
-)
-
-class SupportLink(ui.Link):    
-    def can_render(self, context):
-        return bool(settings.SUPPORT_URL)
-
-
-ui.register(ui.FOOTER_LINKS,
-            ui.Link(
-                    text=_('contact'),
-                    url=lambda u, c: settings.CONTACT_URL and settings.CONTACT_URL or "%s?next=%s" % (reverse('feedback'), c['request'].path),
-                    weight=400),
-            SupportLink(_('support'), settings.SUPPORT_URL, attrs={'target': '_blank'}, weight=300),
-            ui.Link(_('privacy'), ui.Url('privacy'), weight=200),
-            ui.Link(_('faq'), ui.Url('faq'), weight=100),
-            ui.Link(_('about'), ui.Url('about'), weight=0),
-)
-
-
+import forum.registry
 
 
 
index d424382b9b150311d0ef4f392a56a8df9e6515be..70fe1b38c9fcbd8cf52f9151ab8af0626b690fee 100644 (file)
@@ -58,7 +58,7 @@ def html2text(s, ignore_tags=(), indent_width=4, page_width=80):
     return mark_safe(parser.result)
 
 def buildtag(name, content, **attrs):
-    return mark_safe('<%s %s>%s</a>' % (name, " ".join('%s="%s"' % i for i in attrs.items()), str(content)))
+    return mark_safe('<%s %s>%s</%s>' % (name, " ".join('%s="%s"' % i for i in attrs.items()), str(content), name))
 
 def hyperlink(url, title, **attrs):
     return mark_safe('<a href="%s" %s>%s</a>' % (url, " ".join('%s="%s"' % i for i in attrs.items()), title))
index 43464d80dd5a4de035f2c107f7cdec2a3eeae562..4222acf98d8cd82b493f467e296581ba8e21ac16 100644 (file)
@@ -115,10 +115,13 @@ def edit_user(request, id):
     }, context_instance=RequestContext(request))\r
 \r
 \r
-@login_required\r
+@decorate.withfn(decorators.command)\r
 def user_powers(request, id, action, status):\r
     if not request.user.is_superuser:\r
-        return HttpResponseUnauthorized(request)\r
+        raise decorators.CommandException(_("Only superusers are allowed to alter other users permissions."))\r
+\r
+    if (action == 'remove' and 'status' == 'super') and not request.user.is_siteowner():\r
+        raise decorators.CommandException(_("Only the site owner can remove the super user status from other user."))\r
 \r
     user = get_object_or_404(User, id=id)\r
     new_state = action == 'grant'\r
@@ -131,26 +134,32 @@ def user_powers(request, id, action, status):
         raise Http404()\r
 \r
     user.save()\r
-    return HttpResponseRedirect(user.get_profile_url())\r
+    return decorators.RefreshPageCommand()\r
 \r
 \r
 @decorate.withfn(decorators.command)\r
 def award_points(request, id):\r
-    if (not request.POST) and request.POST.get('points', None):\r
-        raise decorators.CommandException(_("Invalid request type"))\r
+    if not request.POST:\r
+        return render_to_response('users/karma_bonus.html')\r
 \r
     if not request.user.is_superuser:\r
         raise decorators.CommandException(_("Only superusers are allowed to award reputation points"))\r
 \r
+    try:\r
+        points = int(request.POST['points'])\r
+    except:\r
+        raise decorators.CommandException(_("Invalid number of points to award."))\r
+\r
     user = get_object_or_404(User, id=id)\r
-    points = int(request.POST['points'])\r
 \r
     extra = dict(message=request.POST.get('message', ''), awarding_user=request.user.id, value=points)\r
 \r
     BonusRepAction(user=request.user, extra=extra).save(data=dict(value=points, affected=user))\r
 \r
-    return dict(reputation=user.reputation)\r
-\r
+    return {'commands': {\r
+            'update_profile_karma': [user.reputation]\r
+        }}\r
+    \r
 \r
 @decorate.withfn(decorators.command)\r
 def suspend(request, id):\r
@@ -159,7 +168,7 @@ def suspend(request, id):
     if not request.user.is_superuser:\r
         raise decorators.CommandException(_("Only superusers can suspend other users"))\r
 \r
-    if not request.POST:\r
+    if not request.POST.get('bantype', None):\r
         if user.is_suspended():\r
             suspension = user.suspension\r
             suspension.cancel(user=request.user, ip=request.META['REMOTE_ADDR'])\r
@@ -196,6 +205,7 @@ def user_view(template, tab_name, tab_title, tab_description, private=False, tab
             rev_page_title = user.username + " - " + tab_description\r
 \r
             context.update({\r
+            "tab": "users",\r
             "active_tab" : tab_name,\r
             "tab_description" : tab_description,\r
             "page_title" : rev_page_title,\r
@@ -287,30 +297,31 @@ def user_favorites(request, user):
 \r
 @user_view('users/subscriptions.html', 'subscriptions', _('subscription settings'), _('subscriptions'), True, tabbed=False)\r
 def user_subscriptions(request, user):\r
+    enabled = user.subscription_settings.enable_notifications\r
+\r
     if request.method == 'POST':        \r
         form = SubscriptionSettingsForm(data=request.POST, instance=user.subscription_settings)\r
 \r
         if form.is_valid():\r
-            if form.cleaned_data['user'] != user.id:\r
-                return HttpResponseUnauthorized(request)\r
+            form.save()\r
+            message = _('New subscription settings are now saved')\r
 \r
             if 'notswitch' in request.POST:\r
-                user.subscription_settings.enable_notifications = not user.subscription_settings.enable_notifications\r
-                user.subscription_settings.save()\r
+                enabled = not enabled\r
 \r
-                if user.subscription_settings.enable_notifications:\r
-                    request.user.message_set.create(message=_('Notifications are now enabled'))\r
+                if enabled:\r
+                    message = _('Notifications are now enabled')\r
                 else:\r
-                    request.user.message_set.create(message=_('Notifications are now disabled'))\r
+                    message = _('Notifications are now disabled')\r
 \r
-            form.save()\r
-            request.user.message_set.create(message=_('New subscription settings are now saved'))\r
+            user.subscription_settings.enable_notifications = enabled\r
+            user.subscription_settings.save()\r
+\r
+            request.user.message_set.create(message=message)\r
     else:\r
         form = SubscriptionSettingsForm(instance=user.subscription_settings)\r
 \r
-    notificatons_on = user.subscription_settings.enable_notifications\r
-\r
-    return {'view_user':user, 'notificatons_on': notificatons_on, 'form':form}\r
+    return {'view_user':user, 'notificatons_on': enabled, 'form':form}\r
 \r
 @login_required\r
 def account_settings(request):\r