##// END OF EJS Templates
#179 Added followers page
marcink -
r1279:cb216757 beta
parent child Browse files
Show More
@@ -0,0 +1,57
1 # -*- coding: utf-8 -*-
2 """
3 rhodecode.controllers.followers
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
6 Followers controller for rhodecode
7
8 :created_on: Apr 23, 2011
9 :author: marcink
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
12 """
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
17 #
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
22 #
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 import logging
26
27 from pylons import tmpl_context as c, request
28
29 from rhodecode.lib.helpers import Page
30 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
31 from rhodecode.lib.base import BaseRepoController, render
32 from rhodecode.model.db import Repository, User, UserFollowing
33
34 log = logging.getLogger(__name__)
35
36
37 class FollowersController(BaseRepoController):
38
39 @LoginRequired()
40 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
41 'repository.admin')
42 def __before__(self):
43 super(FollowersController, self).__before__()
44
45 def followers(self, repo_name):
46 p = int(request.params.get('page', 1))
47 repo_id = getattr(Repository.by_repo_name(repo_name), 'repo_id')
48 d = UserFollowing.get_repo_followers(repo_id)\
49 .order_by(UserFollowing.follows_from)
50 c.followers_pager = Page(d, page=p, items_per_page=20)
51
52 c.followers_data = render('/followers/followers_data.html')
53
54 if request.params.get('partial'):
55 return c.followers_data
56
57 return render('/followers/followers.html')
@@ -0,0 +1,33
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
3
4 <%def name="title()">
5 ${c.repo_name} ${_('Followers')} - ${c.rhodecode_name}
6 </%def>
7
8
9 <%def name="breadcrumbs_links()">
10 ${h.link_to(u'Home',h.url('/'))}
11 &raquo;
12 ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
13 &raquo;
14 ${_('followers')}
15 </%def>
16
17 <%def name="page_nav()">
18 ${self.menu('followers')}
19 </%def>
20 <%def name="main()">
21 <div class="box">
22 <!-- box / title -->
23 <div class="title">
24 ${self.breadcrumbs()}
25 </div>
26 <!-- end box / title -->
27 <div class="table">
28 <div id="followers">
29 ${c.followers_data}
30 </div>
31 </div>
32 </div>
33 </%def> No newline at end of file
@@ -0,0 +1,37
1 ## -*- coding: utf-8 -*-
2
3
4 % for f in c.followers_pager:
5 <div>
6 <div class="follower_user">
7 <div class="gravatar">
8 <img alt="gravatar" src="${h.gravatar_url(f.user.email,24)}"/>
9 </div>
10 <span style="font-size: 20px"> <b>${f.user.username}</b> (${f.user.name} ${f.user.lastname})</span>
11 </div>
12 <div style="clear:both;padding-top: 10px"></div>
13 <div class="follower_date">${_('Started following on')} - ${f.follows_from}</div>
14 <div style="border-bottom: 1px solid #DDD;margin:10px 0px 10px 0px"></div>
15 </div>
16 % endfor
17
18
19 <div class="pagination-wh pagination-left">
20 <script type="text/javascript">
21 var data_div = 'followers';
22 YAHOO.util.Event.onDOMReady(function(){
23 YAHOO.util.Event.addListener(
24 YUD.getElementsByClassName('pager_link'),"click",
25 function(){
26 YAHOO.util.Dom.setStyle(data_div,'opacity','0.3');
27 });
28 });
29 </script>
30
31 ${c.followers_pager.pager('$link_previous ~2~ $link_next',
32 onclick="""YAHOO.util.Connect.asyncRequest('GET','$partial_url',{
33 success:function(o){YAHOO.util.Dom.get(data_div).innerHTML=o.responseText;
34 YUE.on(YAHOO.util.Dom.getElementsByClassName('pager_link'),"click",function(){
35 YAHOO.util.Dom.setStyle(data_div,'opacity','0.3');});
36 YAHOO.util.Dom.setStyle(data_div,'opacity','1');}},null); return false;""")}
37 </div> No newline at end of file
@@ -261,7 +261,9 def make_map(config):
261 controller='feed', action='atom',
261 controller='feed', action='atom',
262 conditions=dict(function=check_repo))
262 conditions=dict(function=check_repo))
263
263
264 #==========================================================================
264 #REPOSITORY ROUTES
265 # REPOSITORY ROUTES
266 #==========================================================================
265 rmap.connect('changeset_home', '/{repo_name:.*}/changeset/{revision}',
267 rmap.connect('changeset_home', '/{repo_name:.*}/changeset/{revision}',
266 controller='changeset', revision='tip',
268 controller='changeset', revision='tip',
267 conditions=dict(function=check_repo))
269 conditions=dict(function=check_repo))
@@ -336,4 +338,7 def make_map(config):
336 controller='settings', action='fork',
338 controller='settings', action='fork',
337 conditions=dict(function=check_repo))
339 conditions=dict(function=check_repo))
338
340
341 rmap.connect('repo_followers_home', '/{repo_name:.*}/followers',
342 controller='followers', action='followers',
343 conditions=dict(function=check_repo))
339 return rmap
344 return rmap
@@ -487,12 +487,19 class UserFollowing(Base):
487 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
487 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
488 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
488 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
489 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
489 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
490 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
490
491
491 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
492 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
492
493
493 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
494 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
494 follows_repository = relationship('Repository', order_by='Repository.repo_name')
495 follows_repository = relationship('Repository', order_by='Repository.repo_name')
495
496
497
498
499 @classmethod
500 def get_repo_followers(cls, repo_id):
501 return Session.query(cls).filter(cls.follows_repo_id == repo_id)
502
496 class CacheInvalidation(Base):
503 class CacheInvalidation(Base):
497 __tablename__ = 'cache_invalidation'
504 __tablename__ = 'cache_invalidation'
498 __table_args__ = (UniqueConstraint('cache_key'), {'useexisting':True})
505 __table_args__ = (UniqueConstraint('cache_key'), {'useexisting':True})
@@ -290,7 +290,7
290 </li>
290 </li>
291
291
292 <li>
292 <li>
293 <a title="${_('Followers')}" href="#">
293 <a title="${_('Followers')}" href="${h.url('repo_followers_home',repo_name=c.repo_name)}">
294 <span class="icon_short">
294 <span class="icon_short">
295 <img src="${h.url("/images/icons/heart.png")}" alt="${_('Followers')}" />
295 <img src="${h.url("/images/icons/heart.png")}" alt="${_('Followers')}" />
296 </span>
296 </span>
General Comments 0
You need to be logged in to leave comments. Login now