changeset 1279:cb216757a62d beta

#179 Added followers page
author Marcin Kuzminski <marcin@python-works.com>
date Sat, 23 Apr 2011 17:11:12 +0200
parents 2b098619e238
children 215a4801bb1e
files rhodecode/config/routing.py rhodecode/controllers/followers.py rhodecode/model/db.py rhodecode/templates/base/base.html rhodecode/templates/followers/followers.html rhodecode/templates/followers/followers_data.html
diffstat 6 files changed, 141 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/rhodecode/config/routing.py	Sat Apr 23 16:38:10 2011 +0200
+++ b/rhodecode/config/routing.py	Sat Apr 23 17:11:12 2011 +0200
@@ -261,7 +261,9 @@
                 controller='feed', action='atom',
                 conditions=dict(function=check_repo))
 
-    #REPOSITORY ROUTES
+    #==========================================================================
+    # REPOSITORY ROUTES
+    #==========================================================================
     rmap.connect('changeset_home', '/{repo_name:.*}/changeset/{revision}',
                 controller='changeset', revision='tip',
                 conditions=dict(function=check_repo))
@@ -336,4 +338,7 @@
                 controller='settings', action='fork',
                 conditions=dict(function=check_repo))
 
+    rmap.connect('repo_followers_home', '/{repo_name:.*}/followers',
+                 controller='followers', action='followers',
+                 conditions=dict(function=check_repo))
     return rmap
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/controllers/followers.py	Sat Apr 23 17:11:12 2011 +0200
@@ -0,0 +1,57 @@
+# -*- coding: utf-8 -*-
+"""
+    rhodecode.controllers.followers
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    Followers controller for rhodecode
+
+    :created_on: Apr 23, 2011
+    :author: marcink
+    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
+    :license: GPLv3, see COPYING for more details.
+"""
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+import logging
+
+from pylons import tmpl_context as c, request
+
+from rhodecode.lib.helpers import Page
+from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
+from rhodecode.lib.base import BaseRepoController, render
+from rhodecode.model.db import Repository, User, UserFollowing
+
+log = logging.getLogger(__name__)
+
+
+class FollowersController(BaseRepoController):
+
+    @LoginRequired()
+    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
+                                   'repository.admin')
+    def __before__(self):
+        super(FollowersController, self).__before__()
+
+    def followers(self, repo_name):
+        p = int(request.params.get('page', 1))
+        repo_id = getattr(Repository.by_repo_name(repo_name), 'repo_id')
+        d = UserFollowing.get_repo_followers(repo_id)\
+            .order_by(UserFollowing.follows_from)
+        c.followers_pager = Page(d, page=p, items_per_page=20)
+
+        c.followers_data = render('/followers/followers_data.html')
+
+        if request.params.get('partial'):
+            return c.followers_data
+
+        return render('/followers/followers.html')
--- a/rhodecode/model/db.py	Sat Apr 23 16:38:10 2011 +0200
+++ b/rhodecode/model/db.py	Sat Apr 23 17:11:12 2011 +0200
@@ -487,12 +487,19 @@
     user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
     follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
     follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
+    follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
 
     user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
 
     follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
     follows_repository = relationship('Repository', order_by='Repository.repo_name')
 
+
+
+    @classmethod
+    def get_repo_followers(cls, repo_id):
+        return Session.query(cls).filter(cls.follows_repo_id == repo_id)
+
 class CacheInvalidation(Base):
     __tablename__ = 'cache_invalidation'
     __table_args__ = (UniqueConstraint('cache_key'), {'useexisting':True})
--- a/rhodecode/templates/base/base.html	Sat Apr 23 16:38:10 2011 +0200
+++ b/rhodecode/templates/base/base.html	Sat Apr 23 17:11:12 2011 +0200
@@ -290,7 +290,7 @@
                 </li>
                 
                 <li>
-                    <a title="${_('Followers')}" href="#">
+                    <a title="${_('Followers')}" href="${h.url('repo_followers_home',repo_name=c.repo_name)}">
                     <span class="icon_short">
                         <img src="${h.url("/images/icons/heart.png")}" alt="${_('Followers')}" />
                     </span>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/templates/followers/followers.html	Sat Apr 23 17:11:12 2011 +0200
@@ -0,0 +1,33 @@
+## -*- coding: utf-8 -*-
+<%inherit file="/base/base.html"/>
+
+<%def name="title()">
+    ${c.repo_name} ${_('Followers')} - ${c.rhodecode_name}
+</%def>
+
+
+<%def name="breadcrumbs_links()">
+    ${h.link_to(u'Home',h.url('/'))}
+    &raquo; 
+    ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
+    &raquo;
+    ${_('followers')}
+</%def>
+
+<%def name="page_nav()">
+    ${self.menu('followers')}
+</%def>
+<%def name="main()">
+<div class="box">
+    <!-- box / title -->
+    <div class="title">
+        ${self.breadcrumbs()}
+    </div>
+    <!-- end box / title -->
+    <div class="table">
+        <div id="followers">
+            ${c.followers_data}
+        </div>   
+    </div>
+</div>    
+</%def> 
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/templates/followers/followers_data.html	Sat Apr 23 17:11:12 2011 +0200
@@ -0,0 +1,37 @@
+## -*- coding: utf-8 -*-
+
+
+% for f in c.followers_pager:
+    <div>
+        <div class="follower_user">
+            <div class="gravatar">
+                <img alt="gravatar" src="${h.gravatar_url(f.user.email,24)}"/>
+            </div>
+            <span style="font-size: 20px"> <b>${f.user.username}</b> (${f.user.name} ${f.user.lastname})</span>
+        </div>
+        <div style="clear:both;padding-top: 10px"></div>
+        <div class="follower_date">${_('Started following on')} - ${f.follows_from}</div>
+        <div style="border-bottom: 1px solid #DDD;margin:10px 0px 10px 0px"></div>
+    </div>                
+% endfor 
+
+
+<div class="pagination-wh pagination-left">
+<script type="text/javascript">
+  var data_div = 'followers';
+  YAHOO.util.Event.onDOMReady(function(){
+    YAHOO.util.Event.addListener(
+    		YUD.getElementsByClassName('pager_link'),"click",
+    		function(){
+            YAHOO.util.Dom.setStyle(data_div,'opacity','0.3');
+            });
+    });
+</script>
+
+${c.followers_pager.pager('$link_previous ~2~ $link_next',     
+onclick="""YAHOO.util.Connect.asyncRequest('GET','$partial_url',{
+success:function(o){YAHOO.util.Dom.get(data_div).innerHTML=o.responseText;
+YUE.on(YAHOO.util.Dom.getElementsByClassName('pager_link'),"click",function(){
+        YAHOO.util.Dom.setStyle(data_div,'opacity','0.3');});       
+YAHOO.util.Dom.setStyle(data_div,'opacity','1');}},null); return false;""")}
+</div>
\ No newline at end of file