diff options
author | Evgeny Fadeev <evgeny.fadeev@gmail.com> | 2011-05-24 02:31:27 -0400 |
---|---|---|
committer | Evgeny Fadeev <evgeny.fadeev@gmail.com> | 2011-05-24 02:31:27 -0400 |
commit | 899cd7376580b9238bdb12ddc1f097bcb9912730 (patch) | |
tree | 3ba4b1a3df67756e3e5fcfe0f7666fc083869b78 | |
parent | c7cc2ddce4e0daec3bf6966cc7e4f6b7e794e148 (diff) | |
parent | 1243d42844613a5e04d8f40b7d3cc525f9ff8979 (diff) | |
download | askbot-899cd7376580b9238bdb12ddc1f097bcb9912730.tar.gz askbot-899cd7376580b9238bdb12ddc1f097bcb9912730.tar.bz2 askbot-899cd7376580b9238bdb12ddc1f097bcb9912730.zip |
merged follow user feature
21 files changed, 340 insertions, 99 deletions
diff --git a/MANIFEST.in b/MANIFEST.in index 556620c4..1512a8ac 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -13,6 +13,7 @@ exclude urls.py exclude askbot/upfiles/*.* recursive-exclude avatar * recursive-exclude adzone * +recursive-exclude follow * recursive-exclude categories * recursive-exclude follow * recursive-exclude env diff --git a/askbot/doc/source/optional-modules.rst b/askbot/doc/source/optional-modules.rst index 8a96acbd..15db2e94 100644 --- a/askbot/doc/source/optional-modules.rst +++ b/askbot/doc/source/optional-modules.rst @@ -5,6 +5,17 @@ Optional modules Askbot supports a number of optional modules, enabling certain features, not available in askbot by default. +.. _follow-users: + +Follow users +============ + +Install ``django-followit`` app:: + + pip install -e git+git://github.com/ASKBOT/django-followit.git#egg=followit + +Then add ``followit`` to the ``INSTALLED_APPS`` and run ``syncdb`` management command. + .. _embedding-video: Embedding video @@ -59,7 +70,7 @@ Uploaded avatars To enable uploadable avatars (in addition to :ref:`gravatars <gravatar>`), please install development version of -application ``django-avatar``, with the following command: +application ``django-avatar``, with the following command:: pip install -e git+git://github.com/ericflo/django-avatar.git#egg=django-avatar @@ -68,6 +79,8 @@ and run (to install database table used by the avatar app): python manage.py syncdb +Also, settings ``MEDIA_ROOT`` and ``MEDIA_URL`` will need to be added to your ``settings.py`` file. + .. note:: Version of the ``avatar`` application available at pypi may not diff --git a/askbot/models/__init__.py b/askbot/models/__init__.py index 24ec6418..42690512 100644 --- a/askbot/models/__init__.py +++ b/askbot/models/__init__.py @@ -1208,19 +1208,6 @@ def user_edit_answer( timestamp = timestamp ) -def user_is_following(self, followed_item): - if isinstance(followed_item, Question): - followers = User.objects.filter( - id = self.id, - followed_questions = followed_item, - ) - if self in followers: - return True - else: - return False - else: - raise NotImplementedError('function only works for questions so far') - def user_post_answer( self, question = None, @@ -1719,6 +1706,16 @@ def user_follow_question(self, question = None): if self not in question.followed_by.all(): question.followed_by.add(self) +def user_is_following_question(user, question): + """True if user is following a question""" + followers = question.followed_by.all() + try: + followers.get(id = user.id) + return True + except User.DoesNotExist: + return False + + def upvote(self, post, timestamp=None, cancel=False): return _process_vote( self,post, @@ -1872,8 +1869,8 @@ User.add_to_class('delete_messages', delete_messages) User.add_to_class('toggle_favorite_question', toggle_favorite_question) User.add_to_class('follow_question', user_follow_question) User.add_to_class('unfollow_question', user_unfollow_question) +User.add_to_class('is_following_question', user_is_following_question) User.add_to_class('mark_tags', user_mark_tags) -User.add_to_class('is_following', user_is_following) User.add_to_class('update_response_counts', user_update_response_counts) User.add_to_class('can_have_strong_url', user_can_have_strong_url) User.add_to_class('is_administrator', user_is_administrator) @@ -2434,27 +2431,12 @@ signals.post_updated.connect( ) signals.site_visited.connect(record_user_visit) -#todo: wtf??? what is x=x about? - -Question = Question -QuestionRevision = QuestionRevision -QuestionView = QuestionView -FavoriteQuestion = FavoriteQuestion -AnonymousQuestion = AnonymousQuestion - -Answer = Answer -AnswerRevision = AnswerRevision -AnonymousAnswer = AnonymousAnswer - - -BadgeData = BadgeData -Award = Award -Repute = Repute - -Activity = Activity -ActivityAuditStatus = ActivityAuditStatus -EmailFeedSetting = EmailFeedSetting -#AuthKeyUserAssociation = AuthKeyUserAssociation +#set up a possibility for the users to follow others +try: + import followit + followit.register(User) +except ImportError: + pass __all__ = [ 'signals', @@ -2487,3 +2469,4 @@ __all__ = [ 'get_model' ] + diff --git a/askbot/models/question.py b/askbot/models/question.py index 797d1c84..41579c11 100644 --- a/askbot/models/question.py +++ b/askbot/models/question.py @@ -211,7 +211,12 @@ class QuestionQuerySet(models.query.QuerySet): else: raise Exception('UNANSWERED_QUESTION_MEANING setting is wrong') elif scope_selector == 'favorite': - qs = qs.filter(favorited_by = request_user) + favorite_filter = models.Q(favorited_by = request_user) + if 'followit' in settings.INSTALLED_APPS: + followed_users = request_user.get_followed_users() + favorite_filter |= models.Q(author__in = followed_users) + favorite_filter |= models.Q(answers__author__in = followed_users) + qs = qs.filter(favorite_filter) #user contributed questions & answers if author_selector: diff --git a/askbot/setup_templates/settings.py b/askbot/setup_templates/settings.py index 4e22346a..65007676 100644 --- a/askbot/setup_templates/settings.py +++ b/askbot/setup_templates/settings.py @@ -164,6 +164,7 @@ INSTALLED_APPS = ( 'django_countries', 'djcelery', 'djkombu', + 'follow', #'avatar',#experimental use git clone git://github.com/ericflo/django-avatar.git$ #requires setting of MEDIA_ROOT and MEDIA_URL ) diff --git a/askbot/skins/default/media/js/user.js b/askbot/skins/default/media/js/user.js index 7877a828..ec169f9d 100644 --- a/askbot/skins/default/media/js/user.js +++ b/askbot/skins/default/media/js/user.js @@ -97,3 +97,81 @@ $(document).ready(function(){ } ); }); + +/** + * @constructor + * allows to follow/unfollow users + */ +var FollowUser = function(){ + WrappedElement.call(this); + this._user_id = null; + this._user_name = null; +}; +inherits(FollowUser, WrappedElement); + +/** + * @param {string} user_name + */ +FollowUser.prototype.setUserName = function(user_name){ + this._user_name = user_name; +}; + +FollowUser.prototype.decorate = function(element){ + this._element = element; + this._user_id = parseInt(element.attr('id').split('-').pop()); + this._available_action = element.hasClass('follow') ? 'follow':'unfollow'; + var me = this; + setupButtonEventHandlers(this._element, function(){ me.go() }); +}; + +FollowUser.prototype.go = function(){ + if (askbot['data']['userIsAuthenticated'] === false){ + var message = gettext('Please <a href="%(signin_url)s">signin</a> to follow %(username)s'); + var message_data = { + signin_url: askbot['urls']['user_signin'] + '?next=' + window.location.href, + username: this._user_name + } + message = interpolate(message, message_data, true); + showMessage(this._element, message); + return; + } + var user_id = this._user_id; + if (this._available_action === 'follow'){ + var url = askbot['urls']['follow_user']; + } else { + var url = askbot['urls']['unfollow_user']; + } + var me = this; + $.ajax({ + type: 'POST', + cache: false, + dataType: 'json', + url: url.replace('{{userId}}', user_id), + success: function(){ me.toggleState() } + }); +}; + +FollowUser.prototype.toggleState = function(){ + if (this._available_action === 'follow'){ + this._available_action = 'unfollow'; + this._element.removeClass('follow'); + this._element.addClass('unfollow'); + var fmts = gettext('unfollow %s'); + } else { + this._available_action = 'follow'; + this._element.removeClass('unfollow'); + this._element.addClass('follow'); + var fmts = gettext('follow %s'); + } + this._element.html(interpolate(fmts, [this._user_name])); +}; + +(function(){ + var fbtn = $('.follow-user'); + if (fbtn.length === 1){ + var follow_user = new FollowUser(); + follow_user.decorate(fbtn); + follow_user.setUserName(askbot['data']['viewUserName']); + } +})(); + diff --git a/askbot/skins/default/media/style/style.css b/askbot/skins/default/media/style/style.css index ff8b997d..24b01672 100755 --- a/askbot/skins/default/media/style/style.css +++ b/askbot/skins/default/media/style/style.css @@ -778,11 +778,10 @@ a:hover.medal { height: 24px; line-height: 26px; margin-top: 3px; - padding: 0px 11px 0px 11px; } -.tabsA a.on, tabsA a.on:hover { - padding: 0px 6px 0px 11px; +.tabsA a.rev.on, tabsA a.rev.on:hover { + padding: 0px 2px 0px 7px; } .tabsA a, .tabsC a{ @@ -797,7 +796,7 @@ a:hover.medal { height: 20px; line-height: 22px; margin: 5px 0 0 4px; - padding: 0 11px 0 11px; + padding: 0 7px; text-decoration: none; } @@ -2172,3 +2171,19 @@ pre.prettyprint { padding: 3px; border: 0px solid #888; } .atn { color: #404; } .atv { color: #060; } } + +.follow-toggle { + border-radius: 3px; + -moz-border-radius: 3px; + background: #fff0e0; + color: #777; + font-weight: bolder; + border: 1px solid #aaa; + cursor: pointer; +} + +.follow-toggle.unfollow:hover { + background: #a40000; + color: #fff; + border: 1px solid #d40000; +} diff --git a/askbot/skins/default/templates/blocks/bottom_scripts.html b/askbot/skins/default/templates/blocks/bottom_scripts.html index 3ba2d959..b5b88bce 100644 --- a/askbot/skins/default/templates/blocks/bottom_scripts.html +++ b/askbot/skins/default/templates/blocks/bottom_scripts.html @@ -20,6 +20,9 @@ askbot['urls']['mark_read_message'] = '{% url "read_message" %}'; askbot['urls']['get_tags_by_wildcard'] = '{% url "get_tags_by_wildcard" %}'; askbot['urls']['get_tag_list'] = '{% url "get_tag_list" %}'; + askbot['urls']['follow_user'] = scriptUrl + 'followit/follow/user/{{'{{'}}userId{{'}}'}}/'; + askbot['urls']['unfollow_user'] = scriptUrl + 'followit/unfollow/user/{{'{{'}}userId{{'}}'}}/'; + askbot['urls']['user_signin'] = '{% url "user_signin" %}'; </script> <script type="text/javascript" diff --git a/askbot/skins/default/templates/macros.html b/askbot/skins/default/templates/macros.html index 0eb0b303..fb3e3898 100644 --- a/askbot/skins/default/templates/macros.html +++ b/askbot/skins/default/templates/macros.html @@ -20,6 +20,34 @@ {% endif %} {%- endmacro -%} +{%- macro follow_toggle(follow, name, alias, id) -%} + {# follow - boolean; name - object type name; alias - e.g. users name; id - object id #} + <div + class="follow-toggle follow-{{name}} {% if follow %}follow{% else %}unfollow{% endif %}" + id="follow-{{ name }}-{{ id }}" + > + {% if follow %} + {% trans %}follow {{alias}}{% endtrans %} + {% else %} + {% trans %}unfollow {{alias}}{% endtrans %} + {% endif %} + </div> +{%- endmacro -%} + +{%- macro follow_user_toggle(visitor = None, subject = None) -%} + {% if visitor.is_anonymous() %} + {{ follow_toggle(True, 'user', subject.username, subject.id) }} + {% else %} + {% if visitor != subject %} + {% if visitor.is_following(subject) %} + {{ follow_toggle(False, 'user', subject.username, subject.id) }} + {% else %} + {{ follow_toggle(True, 'user', subject.username, subject.id) }} + {% endif %} + {% endif %} + {% endif %} +{%- endmacro -%} + {%- macro user_long_score_and_badge_summary(user) -%} <a class="user-micro-info" href="{{user.get_absolute_url()}}?sort=reputation" @@ -74,6 +102,30 @@ {{ user_country_name_and_flag(user) }} {%- endmacro -%} +{%- macro user_list(users, profile_section = None) -%} +<div class="userList"> + <table class="list-table"> + <tr> + <td class="list-td"> + {% for user in users %} + <div class="user"> + <ul> + <li class="thumb">{{ gravatar(user, 32) }}</li> + <li><a href="{% url user_profile user.id, user.username|slugify %}{% if profile_section %}?sort={{profile_section}}{% endif %}">{{user.username}}</a>{{ user_country_flag(user) }}</li> + <li>{{ user_score_and_badge_summary(user) }}</li> + </ul> + </div> + {% if loop.index is divisibleby 7 %} + </td> + <td> + {% endif %} + {% endfor %} + </td> + </tr> + </table> +</div> +{%- endmacro -%} + {%- macro paginator(p, position='left') -%}{# p is paginator context dictionary #} {% spaceless %} {% if p.is_paginated %} @@ -510,12 +562,12 @@ poor design of the data or methods on data objects #} {% if sort == key_name + "-asc" %}{# "worst" first #} <a id="by_{{key_name}}" href="?sort={{key_name}}-desc" - class="on" + class="rev on" title="{{desc_tooltip}}"><span>{{label}} ▲</span></a> {% elif sort == key_name + "-desc" %}{# "best first" #} <a id="by_{{key_name}}" href="?sort={{key_name}}-asc" - class="on" + class="rev on" title="{{asc_tooltip}}"><span>{{label}} ▼</span></a> {% else %}{# default, when other button is active #} <a id="by_{{key_name}}" diff --git a/askbot/skins/default/templates/main_page/nothing_found.html b/askbot/skins/default/templates/main_page/nothing_found.html index bc58fc27..50f2f340 100644 --- a/askbot/skins/default/templates/main_page/nothing_found.html +++ b/askbot/skins/default/templates/main_page/nothing_found.html @@ -4,8 +4,8 @@ {% trans %}There are no unanswered questions here{% endtrans %} {% endif %} {% if scope == "favorite" %} - {% trans %}No favorite questions here. {% endtrans %} - {% trans %}Please start (bookmark) some questions when you visit them{% endtrans %} + {% trans %}No questions here. {% endtrans %} + {% trans %}Please star (bookmark) some questions or follow some users.{% endtrans %} {% endif %} </p> {% if query or search_tags or author_name %} diff --git a/askbot/skins/default/templates/main_page/tab_bar.html b/askbot/skins/default/templates/main_page/tab_bar.html index 12096a3b..e398be87 100644 --- a/askbot/skins/default/templates/main_page/tab_bar.html +++ b/askbot/skins/default/templates/main_page/tab_bar.html @@ -17,8 +17,8 @@ <a id="favorite" class="{% if scope == 'favorite' %}on{% else %}off{% endif %}" href="?scope=favorite" - title="{% trans %}see your favorite questions{% endtrans %}" - ><span>{% trans %}favorite{% endtrans %}</span></a> + title="{% trans %}see your followed questions{% endtrans %}" + ><span>{% trans %}followed{% endtrans %}</span></a> {% endif %} </div> <div id="sort_tabs" class="tabsA"> diff --git a/askbot/skins/default/templates/user_profile/user.html b/askbot/skins/default/templates/user_profile/user.html index e8abdf4b..cc1895fb 100644 --- a/askbot/skins/default/templates/user_profile/user.html +++ b/askbot/skins/default/templates/user_profile/user.html @@ -21,12 +21,14 @@ </div> {% endblock %}<!-- end user.html --> {% block endjs %} - {% if request.user|can_moderate_user(view_user) %} - <script type='text/javascript' src='{{"/js/jquery.form.js"|media}}'></script> - {% endif %} <script type="text/javascript"> var viewUserID = {{view_user.id}}; + askbot['data']['viewUserName'] = '{{ view_user.username }}'; </script> + {% if request.user|can_moderate_user(view_user) %} + <script type='text/javascript' src='{{"/js/jquery.form.js"|media}}'></script> + {% endif %} + <script type="text/javascript" src='{{"/js/user.js"|media}}'></script> {% block userjs %} {% endblock %} {% endblock %} diff --git a/askbot/skins/default/templates/user_profile/user_info.html b/askbot/skins/default/templates/user_profile/user_info.html index 6c6868c7..5aa5c094 100644 --- a/askbot/skins/default/templates/user_profile/user_info.html +++ b/askbot/skins/default/templates/user_profile/user_info.html @@ -23,6 +23,9 @@ </div> <div class="scoreNumber">{{view_user.reputation|intcomma}}</div> <p><b style="color:#777;">{% trans %}reputation{% endtrans %}</b></p> + {% if user_follow_feature_on %} + {{ macros.follow_user_toggle(visitor = request.user, subject = view_user) }} + {% endif %} </td> <td width="360" style="padding-left:5px;vertical-align: top;"> <table class="user-details"> diff --git a/askbot/skins/default/templates/user_profile/user_network.html b/askbot/skins/default/templates/user_profile/user_network.html new file mode 100644 index 00000000..cc741bb1 --- /dev/null +++ b/askbot/skins/default/templates/user_profile/user_network.html @@ -0,0 +1,25 @@ +{% extends "user_profile/user.html" %} +{% import "macros.html" as macros %} +<!-- user_network.html --> +{% block profileseciton %} + {% trans %}network{% endtrans %} +{% endblock %} +{% block usercontent %} + {% if followed_users or followers %} + {% if followers %} + <h2>{% trans count=followers|length %}Followed by {{count}} person{% pluralize count %}Followed by {{count}} people{% endtrans %}</h2> + {{ macros.user_list(followers, profile_section = 'network') }} + {% endif %} + {% if followed_users %} + <h2>{% trans count=followed_users|length %}Following {{count}} person{% pluralize count %}Followed by {{count}} people{% endtrans %}</h2> + {{ macros.user_list(followed_users, profile_section = 'network') }} + {% endif %} + {% else %} + {% if request.user == view_user %} + <p>{% trans %}Your network is empty. Would you like to follow someone? - Just visit their profiles and click "follow"{% endtrans %}</p> + {% else %} + <p>{% trans username = view_user.username %}{{user}}'s network is empty{% endtrans %}</p> + {% endif %} + {% endif %} +{% endblock %} +<!-- end user_network.html --> diff --git a/askbot/skins/default/templates/user_profile/user_tabs.html b/askbot/skins/default/templates/user_profile/user_tabs.html index 276590c9..92c42ea8 100644 --- a/askbot/skins/default/templates/user_profile/user_tabs.html +++ b/askbot/skins/default/templates/user_profile/user_tabs.html @@ -11,6 +11,12 @@ href="{% url user_profile view_user.id, view_user.username|slugify %}?sort=inbox" ><span>{% trans %}inbox{% endtrans %}</span></a> {% endif %} + {% if user_follow_feature_on %} + <a id="network" {% if tab_name=="network" %}class="on"{% endif %} + title="{% trans %}followers and followed users{% endtrans %}" + href="{% url user_profile view_user.id, view_user.username|slugify %}?sort=network" + ><span>{% trans %}network{% endtrans %}</span></a> + {% endif %} <a id="reputation" {% if tab_name=="reputation" %}class="on"{% endif %} title="{% trans %}graph of user reputation{% endtrans %}" href="{% url user_profile view_user.id, view_user.username|slugify %}?sort=reputation" diff --git a/askbot/skins/default/templates/users.html b/askbot/skins/default/templates/users.html index 74c171c8..750b3abb 100644 --- a/askbot/skins/default/templates/users.html +++ b/askbot/skins/default/templates/users.html @@ -40,28 +40,7 @@ <span>{% trans %}Nothing found.{% endtrans %}</span> {% endif %} </p> -<div class="userList"> - <table class="list-table"> - <tr> - <td class="list-td"> - {% for user in users.object_list %} - <div class="user"> - <ul> - <li class="thumb">{{ macros.gravatar(user, 32) }}</li> - <li><a href="{% url user_profile user.id, user.username|slugify %}">{{user.username}}</a>{{ macros.user_country_flag(user) }}</li> - <li>{{ macros.user_score_and_badge_summary(user) }}</li> - </ul> - </div> - - {% if loop.index is divisibleby 7 %} - </td> - <td> - {% endif %} - {% endfor %} - </td> - </tr> - </table> -</div> +{{ macros.user_list(users.object_list) }} <div class="pager"> {{ macros.paginator(paginator_context) }} </div> diff --git a/askbot/tests/__init__.py b/askbot/tests/__init__.py index 1cb8d37b..a2d0bdc0 100644 --- a/askbot/tests/__init__.py +++ b/askbot/tests/__init__.py @@ -8,3 +8,4 @@ from askbot.tests.badge_tests import * from askbot.tests.management_command_tests import * from askbot.tests.search_state_tests import * from askbot.tests.form_tests import * +from askbot.tests.follow_tests import * diff --git a/askbot/tests/email_alert_tests.py b/askbot/tests/email_alert_tests.py index 069ad264..071aa5ad 100644 --- a/askbot/tests/email_alert_tests.py +++ b/askbot/tests/email_alert_tests.py @@ -261,7 +261,7 @@ class EmailAlertTests(TestCase): timestamp = self.setup_timestamp if follow is None: - if author.is_following(question): + if author.is_following_question(question): follow = True else: follow = False diff --git a/askbot/tests/follow_tests.py b/askbot/tests/follow_tests.py new file mode 100644 index 00000000..f583c836 --- /dev/null +++ b/askbot/tests/follow_tests.py @@ -0,0 +1,40 @@ +from django.conf import settings as django_settings +from askbot.tests.utils import AskbotTestCase + +if 'followit' in django_settings.INSTALLED_APPS: + TEST_PROTOTYPE = AskbotTestCase +else: + TEST_PROTOTYPE = object + +class FollowUserTests(TEST_PROTOTYPE): + + def setUp(self): + self.u1 = self.create_user('user1') + self.u2 = self.create_user('user2') + self.u3 = self.create_user('user3') + + def test_multiple_follow(self): + + self.u1.follow_user(self.u2) + self.u1.follow_user(self.u3) + self.u2.follow_user(self.u1) + + self.assertEquals( + set(self.u1.get_followers()), + set([self.u2]) + ) + + self.assertEquals( + set(self.u2.get_followers()), + set([self.u1]) + ) + + self.assertEquals( + set(self.u1.get_followed_users()), + set([self.u2, self.u3]) + ) + + def test_unfollow(self): + self.u1.follow_user(self.u2) + self.u1.unfollow_user(self.u2) + self.assertEquals(self.u1.get_followed_users().count(), 0) diff --git a/askbot/views/users.py b/askbot/views/users.py index d96ceece..cd3aa421 100644 --- a/askbot/views/users.py +++ b/askbot/views/users.py @@ -54,14 +54,14 @@ repute_type_id = repute_type.id def owner_or_moderator_required(f): @functools.wraps(f) - def wrapped_func(request, profile_owner): + def wrapped_func(request, profile_owner, context): if profile_owner == request.user: pass elif request.user.is_authenticated() and request.user.can_moderate_user(profile_owner): pass else: raise Http404 #todo: change to access forbidden? - return f(request, profile_owner) + return f(request, profile_owner, context) return wrapped_func def users(request): @@ -131,7 +131,7 @@ def users(request): return render_into_skin('users.html', data, request) @csrf.csrf_protect -def user_moderate(request, subject): +def user_moderate(request, subject, context): """user subview for moderation """ moderator = request.user @@ -213,7 +213,6 @@ def user_moderate(request, subject): 'tab_name': 'moderation', 'tab_description': _('moderate this user'), 'page_title': _('moderate user'), - 'view_user': subject, 'change_user_status_form': user_status_form, 'change_user_reputation_form': user_rep_form, 'send_message_form': send_message_form, @@ -222,7 +221,8 @@ def user_moderate(request, subject): 'user_rep_changed': user_rep_changed, 'user_status_changed': user_status_changed } - return render_into_skin('user_profile/user_moderate.html', data, request) + context.update(data) + return render_into_skin('user_profile/user_moderate.html', context, request) #non-view function def set_new_email(user, new_email, nomessage=False): @@ -278,7 +278,7 @@ def edit_user(request, id): } return render_into_skin('user_profile/user_edit.html', data, request) -def user_stats(request, user): +def user_stats(request, user, context): question_filter = {'author': user} if request.user != user: @@ -379,7 +379,6 @@ def user_stats(request, user): 'tab_name' : 'stats', 'tab_description' : _('user profile'), 'page_title' : _('user profile overview'), - 'view_user' : user, 'user_status_for_display': user.get_status_display(soft = True), 'questions' : questions, 'favorited_myself': favorited_myself, @@ -394,9 +393,10 @@ def user_stats(request, user): 'awarded_badge_counts': dict(awarded_badge_counts), 'total_awards' : total_awards, } - return render_into_skin('user_profile/user_stats.html', data, request) + context.update(data) + return render_into_skin('user_profile/user_stats.html', context, request) -def user_recent(request, user): +def user_recent(request, user, context): def get_type_name(type_id): for item in const.TYPE_ACTIVITY: @@ -663,13 +663,13 @@ def user_recent(request, user): 'tab_name' : 'recent', 'tab_description' : _('recent user activity'), 'page_title' : _('profile - recent activity'), - 'view_user' : user, 'activities' : activities[:const.USER_VIEW_DATA_SIZE] } - return render_into_skin('user_profile/user_recent.html', data, request) + context.update(data) + return render_into_skin('user_profile/user_recent.html', context, request) @owner_or_moderator_required -def user_responses(request, user): +def user_responses(request, user, context): """ We list answers for question, comments, and answer accepted by others for this user. @@ -730,13 +730,24 @@ def user_responses(request, user): 'inbox_section':section, 'tab_description' : _('comments and answers to others questions'), 'page_title' : _('profile - responses'), - 'view_user' : user, 'responses' : response_list, } - return render_into_skin('user_profile/user_inbox.html', data, request) + context.update(data) + return render_into_skin('user_profile/user_inbox.html', context, request) + +def user_network(request, user, context): + if 'followit' not in django_settings.INSTALLED_APPS: + raise Http404 + data = { + 'tab_name': 'network', + 'followed_users': user.get_followed_users(), + 'followers': user.get_followers(), + } + context.update(data) + return render_into_skin('user_profile/user_network.html', context, request) @owner_or_moderator_required -def user_votes(request, user): +def user_votes(request, user, context): votes = [] question_votes = models.Vote.objects.extra( @@ -794,12 +805,12 @@ def user_votes(request, user): 'tab_name' : 'votes', 'tab_description' : _('user vote record'), 'page_title' : _('profile - votes'), - 'view_user' : user, 'votes' : votes[:const.USER_VIEW_DATA_SIZE] } - return render_into_skin('user_profile/user_votes.html', data, request) + context.update(data) + return render_into_skin('user_profile/user_votes.html', context, request) -def user_reputation(request, user): +def user_reputation(request, user, context): reputes = models.Repute.objects.filter(user=user).order_by('-reputed_at') #select_related() adds stuff needed for the query reputes = reputes.select_related( @@ -834,9 +845,10 @@ def user_reputation(request, user): 'reputation': reputes, 'reps': reps } - return render_into_skin('user_profile/user_reputation.html', data, request) + context.update(data) + return render_into_skin('user_profile/user_reputation.html', context, request) -def user_favorites(request, user): +def user_favorites(request, user, context): favorited_q_id_list= models.FavoriteQuestion.objects.filter( user = user ).values_list('question__id', flat=True) @@ -860,13 +872,13 @@ def user_favorites(request, user): 'page_title' : _('profile - favorite questions'), 'questions' : questions, 'favorited_myself': favorited_q_id_list, - 'view_user' : user } - return render_into_skin('user_profile/user_favorites.html', data, request) + context.update(data) + return render_into_skin('user_profile/user_favorites.html', context, request) @owner_or_moderator_required @csrf.csrf_protect -def user_email_subscriptions(request, user): +def user_email_subscriptions(request, user, context): logging.debug(get_request_info(request)) if request.method == 'POST': @@ -900,14 +912,14 @@ def user_email_subscriptions(request, user): 'tab_name': 'email_subscriptions', 'tab_description': _('email subscription settings'), 'page_title': _('profile - email subscriptions'), - 'view_user': user, 'email_feeds_form': email_feeds_form, 'tag_filter_selection_form': tag_filter_form, 'action_status': action_status, } + context.update(data) return render_into_skin( 'user_profile/user_email_subscriptions.html', - data, + context, request ) @@ -915,6 +927,7 @@ user_view_call_table = { 'stats': user_stats, 'recent': user_recent, 'inbox': user_responses, + 'network': user_network, 'reputation': user_reputation, 'favorites': user_favorites, 'votes': user_votes, @@ -943,4 +956,9 @@ def user(request, id, slug=None): else: user_view_func = user_stats - return user_view_func(request, profile_owner) + context = { + 'view_user': profile_owner, + 'user_follow_feature_on': ('followit' in django_settings.INSTALLED_APPS), + } + + return user_view_func(request, profile_owner, context) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..ba72edb8 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,16 @@ +django>=1.1.2 +Jinja2 +Coffin>=0.3 +South>=0.7.1 +oauth2 +recaptcha-client +markdown2 +html5lib +django-keyedcache +django-threaded-multihost +django-robots +unidecode +django-countries==1.0.5 +django-celery==2.2.3 +django-kombu==0.9.2 +-e git+git://github.com/ASKBOT/django-followit.git#egg=followit |