changeset 4281:6564d82e1469

pull requests: add new "my" page, separate from "my account" and prominently shown in the page headers
author Mads Kiilerich <madski@unity3d.com>
date Fri, 18 Jul 2014 18:44:54 +0200
parents 27f498ee6db0
children 99997d8f31eb
files kallithea/config/routing.py kallithea/controllers/pullrequests.py kallithea/lib/base.py kallithea/model/pull_request.py kallithea/templates/base/base.html kallithea/templates/pullrequests/pullrequest_show_my.html kallithea/templates/pullrequests/pullrequest_show_my_data.html
diffstat 7 files changed, 230 insertions(+), 73 deletions(-) [+]
line wrap: on
line diff
--- a/kallithea/config/routing.py	Tue Jul 02 00:37:01 2013 +0200
+++ b/kallithea/config/routing.py	Fri Jul 18 18:44:54 2014 +0200
@@ -718,6 +718,15 @@
                  action='show_all', conditions=dict(function=check_repo,
                                                 method=["GET"]))
 
+    rmap.connect('my_pullrequests',
+                 '/my_pullrequests',
+                 controller='pullrequests',
+                 action='show_my', conditions=dict(method=["GET"]))
+    rmap.connect('my_pullrequests_data',
+                 '/my_pullrequests_data',
+                 controller='pullrequests',
+                 action='show_my_data', conditions=dict(method=["GET"]))
+
     rmap.connect('pullrequest_comment',
                  '/{repo_name:.*?}/pull-request-comment/{pull_request_id}',
                  controller='pullrequests',
--- a/kallithea/controllers/pullrequests.py	Tue Jul 02 00:37:01 2013 +0200
+++ b/kallithea/controllers/pullrequests.py	Fri Jul 18 18:44:54 2014 +0200
@@ -48,7 +48,8 @@
 from kallithea.lib.vcs.utils import safe_str
 from kallithea.lib.vcs.exceptions import EmptyRepositoryError
 from kallithea.lib.diffs import LimitedDiffContainer
-from kallithea.model.db import  PullRequest, ChangesetStatus, ChangesetComment
+from kallithea.model.db import  PullRequest, ChangesetStatus, ChangesetComment,\
+    PullRequestReviewers
 from kallithea.model.pull_request import PullRequestModel
 from kallithea.model.meta import Session
 from kallithea.model.repo import RepoModel
@@ -257,6 +258,34 @@
         return render('/pullrequests/pullrequest_show_all.html')
 
     @LoginRequired()
+    def show_my(self): # my_account_my_pullrequests
+        c.show_closed = request.GET.get('pr_show_closed')
+        return render('/pullrequests/pullrequest_show_my.html')
+
+    @NotAnonymous()
+    def show_my_data(self):
+        c.show_closed = request.GET.get('pr_show_closed')
+
+        def _filter(pr):
+            s = sorted(pr, key=lambda o: o.created_on, reverse=True)
+            if not c.show_closed:
+                s = filter(lambda p: p.status != PullRequest.STATUS_CLOSED, s)
+            return s
+
+        c.my_pull_requests = _filter(PullRequest.query()\
+                                .filter(PullRequest.user_id ==
+                                        self.authuser.user_id)\
+                                .all())
+
+        c.participate_in_pull_requests = _filter(PullRequest.query()\
+                                .join(PullRequestReviewers)\
+                                .filter(PullRequestReviewers.user_id ==
+                                        self.authuser.user_id)\
+                                                 )
+
+        return render('/pullrequests/pullrequest_show_my_data.html')
+
+    @LoginRequired()
     @NotAnonymous()
     @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
                                    'repository.admin')
--- a/kallithea/lib/base.py	Tue Jul 02 00:37:01 2013 +0200
+++ b/kallithea/lib/base.py	Fri Jul 18 18:44:54 2014 +0200
@@ -55,6 +55,7 @@
 from kallithea.model.notification import NotificationModel
 from kallithea.model.scm import ScmModel
 from kallithea.model.meta import Session
+from kallithea.model.pull_request import PullRequestModel
 
 log = logging.getLogger(__name__)
 
@@ -319,6 +320,9 @@
                         .get_unread_cnt_for_user(c.authuser.user_id)
 
         self.cut_off_limit = safe_int(config.get('cut_off_limit'))
+
+        c.my_pr_count = PullRequestModel().get_pullrequest_cnt_for_user(c.authuser.user_id)
+
         self.sa = meta.Session
         self.scm_model = ScmModel(self.sa)
 
--- a/kallithea/model/pull_request.py	Tue Jul 02 00:37:01 2013 +0200
+++ b/kallithea/model/pull_request.py	Fri Jul 18 18:44:54 2014 +0200
@@ -49,6 +49,13 @@
     def __get_pull_request(self, pull_request):
         return self._get_instance(PullRequest, pull_request)
 
+    def get_pullrequest_cnt_for_user(self, user):
+        return PullRequest.query()\
+                                .join(PullRequestReviewers)\
+                                .filter(PullRequestReviewers.user_id == user)\
+                                .filter(PullRequest.status != PullRequest.STATUS_CLOSED)\
+                                .count()
+
     def get_all(self, repo_name, from_=False, closed=False):
         """Get all PRs for repo.
         Default is all PRs to the repo, PRs from the repo if from_.
--- a/kallithea/templates/base/base.html	Tue Jul 02 00:37:01 2013 +0200
+++ b/kallithea/templates/base/base.html	Fri Jul 18 18:44:54 2014 +0200
@@ -222,7 +222,78 @@
   <!--- END CONTEXT BAR -->
 </%def>
 
-<%def name="usermenu()">
+<%def name="menu(current=None)">
+  <%
+  def is_current(selected):
+      if selected == current:
+          return h.literal('class="current"')
+  %>
+
+  <ul id="quick" class="horizontal-list">
+    <!-- repo switcher -->
+    <li ${is_current('repositories')}>
+      <input id="repo_switcher" name="repo_switcher" type="hidden">
+    </li>
+
+    ##ROOT MENU
+    %if c.authuser.username != 'default':
+      <li ${is_current('journal')}>
+        <a class="menu_link" title="${_('Show recent activity')}"  href="${h.url('journal')}">
+          <i class="icon-book"></i> ${_('Journal')}
+        </a>
+      </li>
+    %else:
+      <li ${is_current('journal')}>
+        <a class="menu_link" title="${_('Public journal')}"  href="${h.url('public_journal')}">
+          <i class="icon-book"></i> ${_('Public journal')}
+        </a>
+      </li>
+    %endif
+      <li ${is_current('gists')}>
+        <a class="menu_link childs" title="${_('Show public gists')}"  href="${h.url('gists')}">
+          <i class="icon-file-2"></i> ${_('Gists')}
+        </a>
+          <ul class="admin_menu">
+            <li><a href="${h.url('new_gist', public=1)}"><i class="icon-file-alt"></i> ${_('Create new gist')}</a></li>
+            <li><a href="${h.url('gists')}"><i class="icon-copy"></i> ${_('All public gists')}</a></li>
+            %if c.authuser.username != 'default':
+              <li><a href="${h.url('gists', public=1)}"><i class="icon-copy"></i> ${_('My public gists')}</a></li>
+              <li><a href="${h.url('gists', private=1)}"><i class="icon-file-text"></i> ${_('My private gists')}</a></li>
+            %endif
+          </ul>
+      </li>
+    <li ${is_current('search')}>
+        <a class="menu_link" title="${_('Search in repositories')}"  href="${h.url('search')}">
+          <i class="icon-search"></i> ${_('Search')}
+        </a>
+    </li>
+    % if h.HasPermissionAll('hg.admin')('access admin main page'):
+      <li ${is_current('admin')}>
+        <a class="menu_link childs" title="${_('Admin')}" href="${h.url('admin_home')}">
+          <i class="icon-cog"></i> ${_('Admin')}
+        </a>
+        ${admin_menu()}
+      </li>
+    % elif c.authuser.repositories_admin or c.authuser.repository_groups_admin or c.authuser.user_groups_admin:
+    <li ${is_current('admin')}>
+        <a class="menu_link childs" title="${_('Admin')}">
+          <i class="icon-cog"></i> ${_('Admin')}
+        </a>
+        ${admin_menu_simple(c.authuser.repositories_admin,
+                            c.authuser.repository_groups_admin,
+                            c.authuser.user_groups_admin or h.HasPermissionAny('hg.usergroup.create.true')())}
+    </li>
+    % endif
+
+    <li ${is_current('my_pullrequests')}>
+      <a class="menu_link" title="${_('My Pull Requests')}" href="${h.url('my_pullrequests')}">
+        <i class="icon-code-fork"></i> ${_('My Pull Requests')}
+        %if c.my_pr_count != 0:
+          <span class="menu_link_notifications">${c.my_pr_count}</span>
+        %endif
+      </a>
+    </li>
+
     ## USER MENU
     <li>
       <a class="menu_link childs" id="quick_login_link">
@@ -239,9 +310,9 @@
           %endif
       </a>
 
-  <div class="user-menu">
-      <div id="quick_login">
-        %if c.authuser.username == 'default':
+      <div class="user-menu">
+        <div id="quick_login">
+          %if c.authuser.username == 'default':
             <h4>${_('Login to your account')}</h4>
             ${h.form(h.url('login_home',came_from=h.url.current()))}
             <div class="form">
@@ -278,7 +349,7 @@
                 </div>
             </div>
             ${h.end_form()}
-        %else:
+          %else:
             <div class="links_left">
                 <div class="big_gravatar"><img alt="gravatar" src="${h.gravatar_url(c.authuser.email,48)}" /></div>
                 <div class="full_name">${c.authuser.full_name_or_username}</div>
@@ -291,75 +362,10 @@
               <li class="logout">${h.link_to(_(u'Log Out'),h.url('logout_home'))}</li>
             </ol>
             </div>
-        %endif
+          %endif
+        </div>
       </div>
-  </div>
-
     </li>
-</%def>
-
-<%def name="menu(current=None)">
-        <%
-        def is_current(selected):
-            if selected == current:
-                return h.literal('class="current"')
-        %>
-        <ul id="quick" class="horizontal-list">
-          <!-- repo switcher -->
-          <li ${is_current('repositories')}>
-            <input id="repo_switcher" name="repo_switcher" type="hidden">
-          </li>
-
-          ##ROOT MENU
-          %if c.authuser.username != 'default':
-            <li ${is_current('journal')}>
-              <a class="menu_link" title="${_('Show recent activity')}"  href="${h.url('journal')}">
-                <i class="icon-book"></i> ${_('Journal')}
-              </a>
-            </li>
-          %else:
-            <li ${is_current('journal')}>
-              <a class="menu_link" title="${_('Public journal')}"  href="${h.url('public_journal')}">
-                <i class="icon-book"></i> ${_('Public journal')}
-              </a>
-            </li>
-          %endif
-            <li ${is_current('gists')}>
-              <a class="menu_link childs" title="${_('Show public gists')}"  href="${h.url('gists')}">
-                <i class="icon-file-2"></i> ${_('Gists')}
-              </a>
-                <ul class="admin_menu">
-                  <li><a href="${h.url('new_gist', public=1)}"><i class="icon-file-alt"></i> ${_('Create new gist')}</a></li>
-                  <li><a href="${h.url('gists')}"><i class="icon-copy"></i> ${_('All public gists')}</a></li>
-                  %if c.authuser.username != 'default':
-                    <li><a href="${h.url('gists', public=1)}"><i class="icon-copy"></i> ${_('My public gists')}</a></li>
-                    <li><a href="${h.url('gists', private=1)}"><i class="icon-file-text"></i> ${_('My private gists')}</a></li>
-                  %endif
-                </ul>
-            </li>
-          <li ${is_current('search')}>
-              <a class="menu_link" title="${_('Search in repositories')}"  href="${h.url('search')}">
-                <i class="icon-search"></i> ${_('Search')}
-              </a>
-          </li>
-          % if h.HasPermissionAll('hg.admin')('access admin main page'):
-            <li ${is_current('admin')}>
-              <a class="menu_link childs" title="${_('Admin')}" href="${h.url('admin_home')}">
-                <i class="icon-cog"></i> ${_('Admin')}
-              </a>
-              ${admin_menu()}
-            </li>
-          % elif c.authuser.repositories_admin or c.authuser.repository_groups_admin or c.authuser.user_groups_admin:
-          <li ${is_current('admin')}>
-              <a class="menu_link childs" title="${_('Admin')}">
-                <i class="icon-cog"></i> ${_('Admin')}
-              </a>
-              ${admin_menu_simple(c.authuser.repositories_admin,
-                                  c.authuser.repository_groups_admin,
-                                  c.authuser.user_groups_admin or h.HasPermissionAny('hg.usergroup.create.true')())}
-          </li>
-          % endif
-          ${usermenu()}
 
     <script type="text/javascript">
         var visual_show_public_icon = "${c.visual.show_public_icon}" == "True";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kallithea/templates/pullrequests/pullrequest_show_my.html	Fri Jul 18 18:44:54 2014 +0200
@@ -0,0 +1,49 @@
+<%inherit file="/base/base.html"/>
+
+<%def name="title()">
+    ${_('My Pull Requests')} &middot; ${c.site_name}
+</%def>
+
+<%def name="breadcrumbs_links()">
+    ${_('My Pull Requests')}
+</%def>
+
+<%def name="page_nav()">
+    ${self.menu('my_pullrequests')}
+</%def>
+
+<%def name="main()">
+
+<div class="box">
+    <!-- box / title -->
+    <div class="title">
+        ${self.breadcrumbs()}
+    </div>
+
+    <div id="pullrequests_container" class="table">
+        ## loaded via AJAX
+        ${_('Loading...')}
+    </div>
+
+<script type="text/javascript">
+pyroutes.register('my_pullrequests_data', "${url('my_pullrequests_data')}", []);
+
+var show_pullrequests = function(e){
+
+    var url = pyroutes.url('my_pullrequests_data');
+    if(YUD.get('show_closed') && YUD.get('show_closed').checked) {
+        var url = pyroutes.url('my_pullrequests_data', {'pr_show_closed': '1'});
+    }
+    ypjax(url, 'pullrequests_container', function(){
+        YUE.on('show_closed','change',function (e) {
+            show_pullrequests(e);
+        });
+    });
+}
+show_pullrequests()
+
+</script>
+
+</div>
+
+</%def>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kallithea/templates/pullrequests/pullrequest_show_my_data.html	Fri Jul 18 18:44:54 2014 +0200
@@ -0,0 +1,53 @@
+%if c.show_closed:
+  ${h.checkbox('show_closed',checked="checked", label=_('Show closed pull requests'))}
+%else:
+  ${h.checkbox('show_closed',label=_('Show closed pull requests'))}
+%endif
+<div class="pullrequests_section_head">${_('Opened by me')}</div>
+<ul>
+    %if c.my_pull_requests:
+      %for pull_request in c.my_pull_requests:
+      <li class="${'closed' if pull_request.is_closed() else ''}">
+        <div style="height: 12px">
+          <div style="float:left">
+            <img src="${h.url('/images/icons/flag_status_%s.png' % str(pull_request.last_review_status))}" />
+            <a href="${h.url('pullrequest_show',repo_name=pull_request.other_repo.repo_name,pull_request_id=pull_request.pull_request_id)}">
+              ${_('Pull request #%s opened on %s') % (pull_request.pull_request_id, h.fmt_date(pull_request.created_on))}
+              %if pull_request.is_closed():
+                (${_('Closed')})
+              %endif
+            </a>
+          </div>
+          <div style="float:left">
+            ${h.form(url('pullrequest_delete', repo_name=pull_request.other_repo.repo_name, pull_request_id=pull_request.pull_request_id),method='delete')}
+              ${h.submit('remove_%s' % pull_request.pull_request_id, '', title=_('Delete Pull Request'),class_="delete_icon action_button",onclick="return confirm('"+_('Confirm to delete this pull request')+"');")}
+            ${h.end_form()}
+          </div>
+        </div>
+      </li>
+      %endfor
+   %else:
+    <li><span class="empty_data">${_('Nothing here yet')}</span></li>
+   %endif
+</ul>
+
+<div class="pullrequests_section_head" style="clear:both">${_('I participate in')}</div>
+<ul>
+    %if c.participate_in_pull_requests:
+      %for pull_request in c.participate_in_pull_requests:
+      <li class="${'closed' if pull_request.is_closed() else ''}">
+        <div style="height: 12px">
+          <img src="${h.url('/images/icons/flag_status_%s.png' % str(pull_request.last_review_status))}" />
+          <a href="${h.url('pullrequest_show',repo_name=pull_request.other_repo.repo_name,pull_request_id=pull_request.pull_request_id)}">
+            ${_('Pull request #%s opened by %s on %s') % (pull_request.pull_request_id, pull_request.author.full_name, h.fmt_date(pull_request.created_on))}
+          </a>
+          %if pull_request.is_closed():
+            (${_('Closed')})
+          %endif
+        </div>
+      </li>
+      %endfor
+    %else:
+     <li><span class="empty_data">${_('Nothing here yet')}</span></li>
+    %endif
+</ul>