pull-requests: added awaiting my review filter for users pull-requests.

- additionally the awaiting my review now properly filters pull requests that have no review votes on them
This commit is contained in:
RhodeCode Admin 2021-04-20 12:59:31 +02:00
parent 0031dcc28b
commit aded27dc31
11 changed files with 347 additions and 131 deletions

View file

@ -76,7 +76,11 @@ class TestMyAccountEdit(TestController):
'requests requiring your participation.')
@pytest.mark.backends("git", "hg")
def test_my_account_my_pullrequests_data(self, pr_util, xhr_header):
@pytest.mark.parametrize('params, expected_title', [
({'closed': 1}, 'Closed'),
({'awaiting_my_review': 1}, 'Awaiting my review'),
])
def test_my_account_my_pullrequests_data(self, pr_util, xhr_header, params, expected_title):
self.log_user()
response = self.app.get(route_path('my_account_pullrequests_data'),
extra_environ=xhr_header)

View file

@ -43,7 +43,7 @@ from rhodecode.model.comment import CommentsModel
from rhodecode.model.db import (
IntegrityError, or_, in_filter_generator,
Repository, UserEmailMap, UserApiKeys, UserFollowing,
PullRequest, UserBookmark, RepoGroup)
PullRequest, UserBookmark, RepoGroup, ChangesetStatus)
from rhodecode.model.meta import Session
from rhodecode.model.pull_request import PullRequestModel
from rhodecode.model.user import UserModel
@ -654,21 +654,31 @@ class MyAccountView(BaseAppView, DataGridAppView):
Session().commit()
return user.user_data['notification_status']
def _get_pull_requests_list(self, statuses):
def _get_pull_requests_list(self, statuses, filter_type=None):
draw, start, limit = self._extract_chunk(self.request)
search_q, order_by, order_dir = self._extract_ordering(self.request)
_render = self.request.get_partial_renderer(
'rhodecode:templates/data_table/_dt_elements.mako')
pull_requests = PullRequestModel().get_im_participating_in(
user_id=self._rhodecode_user.user_id,
statuses=statuses, query=search_q,
offset=start, length=limit, order_by=order_by,
order_dir=order_dir)
if filter_type == 'awaiting_my_review':
pull_requests = PullRequestModel().get_im_participating_in_for_review(
user_id=self._rhodecode_user.user_id,
statuses=statuses, query=search_q,
offset=start, length=limit, order_by=order_by,
order_dir=order_dir)
pull_requests_total_count = PullRequestModel().count_im_participating_in(
user_id=self._rhodecode_user.user_id, statuses=statuses, query=search_q)
pull_requests_total_count = PullRequestModel().count_im_participating_in_for_review(
user_id=self._rhodecode_user.user_id, statuses=statuses, query=search_q)
else:
pull_requests = PullRequestModel().get_im_participating_in(
user_id=self._rhodecode_user.user_id,
statuses=statuses, query=search_q,
offset=start, length=limit, order_by=order_by,
order_dir=order_dir)
pull_requests_total_count = PullRequestModel().count_im_participating_in(
user_id=self._rhodecode_user.user_id, statuses=statuses, query=search_q)
data = []
comments_model = CommentsModel()
@ -678,6 +688,12 @@ class MyAccountView(BaseAppView, DataGridAppView):
repo_id, pull_request=pr, include_drafts=False, count_only=True)
owned = pr.user_id == self._rhodecode_user.user_id
review_statuses = pr.reviewers_statuses(user=self._rhodecode_db_user)
my_review_status = ChangesetStatus.STATUS_NOT_REVIEWED
if review_statuses and review_statuses[4]:
_review_obj, _user, _reasons, _mandatory, statuses = review_statuses
my_review_status = statuses[0][1].status
data.append({
'target_repo': _render('pullrequest_target_repo',
pr.target_repo.repo_name),
@ -688,6 +704,8 @@ class MyAccountView(BaseAppView, DataGridAppView):
'name_raw': pr.pull_request_id,
'status': _render('pullrequest_status',
pr.calculated_review_status()),
'my_status': _render('pullrequest_status',
my_review_status),
'title': _render('pullrequest_title', pr.title, pr.description),
'description': h.escape(pr.description),
'updated_on': _render('pullrequest_updated_on',
@ -723,7 +741,14 @@ class MyAccountView(BaseAppView, DataGridAppView):
c.active = 'pullrequests'
req_get = self.request.GET
c.closed = str2bool(req_get.get('pr_show_closed'))
c.closed = str2bool(req_get.get('closed'))
c.awaiting_my_review = str2bool(req_get.get('awaiting_my_review'))
c.selected_filter = 'all'
if c.closed:
c.selected_filter = 'all_closed'
if c.awaiting_my_review:
c.selected_filter = 'awaiting_my_review'
return self._get_template_context(c)
@ -732,13 +757,19 @@ class MyAccountView(BaseAppView, DataGridAppView):
def my_account_pullrequests_data(self):
self.load_default_context()
req_get = self.request.GET
awaiting_my_review = str2bool(req_get.get('awaiting_my_review'))
closed = str2bool(req_get.get('closed'))
statuses = [PullRequest.STATUS_NEW, PullRequest.STATUS_OPEN]
if closed:
statuses += [PullRequest.STATUS_CLOSED]
data = self._get_pull_requests_list(statuses=statuses)
filter_type = \
'awaiting_my_review' if awaiting_my_review \
else None
data = self._get_pull_requests_list(statuses=statuses, filter_type=filter_type)
return data
@LoginRequired()

View file

@ -41,7 +41,7 @@ class TestPullRequestList(object):
@pytest.mark.parametrize('params, expected_title', [
({'source': 0, 'closed': 1}, 'Closed'),
({'source': 0, 'my': 1}, 'Opened by me'),
({'source': 0, 'my': 1}, 'Created by me'),
({'source': 0, 'awaiting_review': 1}, 'Awaiting review'),
({'source': 0, 'awaiting_my_review': 1}, 'Awaiting my review'),
({'source': 1}, 'From this repo'),

View file

@ -79,21 +79,20 @@ class RepoPullRequestsView(RepoAppView, DataGridAppView):
if filter_type == 'awaiting_review':
pull_requests = PullRequestModel().get_awaiting_review(
repo_name, search_q=search_q, source=source, opened_by=opened_by,
statuses=statuses, offset=start, length=limit,
order_by=order_by, order_dir=order_dir)
repo_name,
search_q=search_q, statuses=statuses,
offset=start, length=limit, order_by=order_by, order_dir=order_dir)
pull_requests_total_count = PullRequestModel().count_awaiting_review(
repo_name, search_q=search_q, source=source, statuses=statuses,
opened_by=opened_by)
repo_name,
search_q=search_q, statuses=statuses)
elif filter_type == 'awaiting_my_review':
pull_requests = PullRequestModel().get_awaiting_my_review(
repo_name, search_q=search_q, source=source, opened_by=opened_by,
user_id=self._rhodecode_user.user_id, statuses=statuses,
offset=start, length=limit, order_by=order_by,
order_dir=order_dir)
repo_name, self._rhodecode_user.user_id,
search_q=search_q, statuses=statuses,
offset=start, length=limit, order_by=order_by, order_dir=order_dir)
pull_requests_total_count = PullRequestModel().count_awaiting_my_review(
repo_name, search_q=search_q, source=source, user_id=self._rhodecode_user.user_id,
statuses=statuses, opened_by=opened_by)
repo_name, self._rhodecode_user.user_id,
search_q=search_q, statuses=statuses)
else:
pull_requests = PullRequestModel().get_all(
repo_name, search_q=search_q, source=source, opened_by=opened_by,
@ -110,6 +109,12 @@ class RepoPullRequestsView(RepoAppView, DataGridAppView):
self.db_repo.repo_id, pull_request=pr,
include_drafts=False, count_only=True)
review_statuses = pr.reviewers_statuses(user=self._rhodecode_db_user)
my_review_status = ChangesetStatus.STATUS_NOT_REVIEWED
if review_statuses and review_statuses[4]:
_review_obj, _user, _reasons, _mandatory, statuses = review_statuses
my_review_status = statuses[0][1].status
data.append({
'name': _render('pullrequest_name',
pr.pull_request_id, pr.pull_request_state,
@ -118,6 +123,8 @@ class RepoPullRequestsView(RepoAppView, DataGridAppView):
'name_raw': pr.pull_request_id,
'status': _render('pullrequest_status',
pr.calculated_review_status()),
'my_status': _render('pullrequest_status',
my_review_status),
'title': _render('pullrequest_title', pr.title, pr.description),
'description': h.escape(pr.description),
'updated_on': _render('pullrequest_updated_on',

View file

@ -354,7 +354,7 @@ class ChangesetStatusModel(BaseModel):
Session().add(new_status)
return new_statuses
def aggregate_votes_by_user(self, commit_statuses, reviewers_data):
def aggregate_votes_by_user(self, commit_statuses, reviewers_data, user=None):
commit_statuses_map = collections.defaultdict(list)
for st in commit_statuses:
@ -368,6 +368,10 @@ class ChangesetStatusModel(BaseModel):
for obj in reviewers_data:
if not obj.user:
continue
if user and obj.user.username != user.username:
# single user filter
continue
statuses = commit_statuses_map.get(obj.user.username, None)
if statuses:
status_groups = itertools.groupby(
@ -376,16 +380,19 @@ class ChangesetStatusModel(BaseModel):
reviewers.append((obj, obj.user, obj.reasons, obj.mandatory, statuses))
return reviewers
if user:
return reviewers[0] if reviewers else reviewers
else:
return reviewers
def reviewers_statuses(self, pull_request):
def reviewers_statuses(self, pull_request, user=None):
_commit_statuses = self.get_statuses(
pull_request.source_repo,
pull_request=pull_request,
with_revisions=True)
reviewers = pull_request.get_pull_request_reviewers(
role=PullRequestReviewers.ROLE_REVIEWER)
return self.aggregate_votes_by_user(_commit_statuses, reviewers)
return self.aggregate_votes_by_user(_commit_statuses, reviewers, user=user)
def calculated_review_status(self, pull_request):
"""

View file

@ -41,10 +41,10 @@ from sqlalchemy import (
Index, Sequence, UniqueConstraint, ForeignKey, CheckConstraint, Column,
Boolean, String, Unicode, UnicodeText, DateTime, Integer, LargeBinary,
Text, Float, PickleType, BigInteger)
from sqlalchemy.sql.expression import true, false, case
from sqlalchemy.sql.expression import true, false, case, null
from sqlalchemy.sql.functions import coalesce, count # pragma: no cover
from sqlalchemy.orm import (
relationship, joinedload, class_mapper, validates, aliased)
relationship, lazyload, joinedload, class_mapper, validates, aliased)
from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.exc import IntegrityError # pragma: no cover
@ -4479,9 +4479,9 @@ class PullRequest(Base, _PullRequestBase):
from rhodecode.model.changeset_status import ChangesetStatusModel
return ChangesetStatusModel().calculated_review_status(self)
def reviewers_statuses(self):
def reviewers_statuses(self, user=None):
from rhodecode.model.changeset_status import ChangesetStatusModel
return ChangesetStatusModel().reviewers_statuses(self)
return ChangesetStatusModel().reviewers_statuses(self, user=user)
def get_pull_request_reviewers(self, role=None):
qry = PullRequestReviewers.query()\

View file

@ -56,7 +56,7 @@ from rhodecode.model import BaseModel
from rhodecode.model.changeset_status import ChangesetStatusModel
from rhodecode.model.comment import CommentsModel
from rhodecode.model.db import (
or_, String, cast, PullRequest, PullRequestReviewers, ChangesetStatus,
aliased, null, lazyload, and_, or_, func, String, cast, PullRequest, PullRequestReviewers, ChangesetStatus,
PullRequestVersion, ChangesetComment, Repository, RepoReviewRule, User)
from rhodecode.model.meta import Session
from rhodecode.model.notification import NotificationModel, \
@ -319,7 +319,7 @@ class PullRequestModel(BaseModel):
if search_q:
like_expression = u'%{}%'.format(safe_unicode(search_q))
q = q.join(User)
q = q.join(User, User.user_id == PullRequest.user_id)
q = q.filter(or_(
cast(PullRequest.pull_request_id, String).ilike(like_expression),
User.username.ilike(like_expression),
@ -405,36 +405,30 @@ class PullRequestModel(BaseModel):
return pull_requests
def count_awaiting_review(self, repo_name, search_q=None, source=False, statuses=None,
opened_by=None):
def count_awaiting_review(self, repo_name, search_q=None, statuses=None):
"""
Count the number of pull requests for a specific repository that are
awaiting review.
:param repo_name: target or source repo
:param search_q: filter by text
:param source: boolean flag to specify if repo_name refers to source
:param statuses: list of pull request statuses
:param opened_by: author user of the pull request
:returns: int number of pull requests
"""
pull_requests = self.get_awaiting_review(
repo_name, search_q=search_q, source=source, statuses=statuses, opened_by=opened_by)
repo_name, search_q=search_q, statuses=statuses)
return len(pull_requests)
def get_awaiting_review(self, repo_name, search_q=None, source=False, statuses=None,
opened_by=None, offset=0, length=None,
order_by=None, order_dir='desc'):
def get_awaiting_review(self, repo_name, search_q=None, statuses=None,
offset=0, length=None, order_by=None, order_dir='desc'):
"""
Get all pull requests for a specific repository that are awaiting
review.
:param repo_name: target or source repo
:param search_q: filter by text
:param source: boolean flag to specify if repo_name refers to source
:param statuses: list of pull request statuses
:param opened_by: author user of the pull request
:param offset: pagination offset
:param length: length of returned list
:param order_by: order of the returned list
@ -442,8 +436,8 @@ class PullRequestModel(BaseModel):
:returns: list of pull requests
"""
pull_requests = self.get_all(
repo_name, search_q=search_q, source=source, statuses=statuses,
opened_by=opened_by, order_by=order_by, order_dir=order_dir)
repo_name, search_q=search_q, statuses=statuses,
order_by=order_by, order_dir=order_dir)
_filtered_pull_requests = []
for pr in pull_requests:
@ -456,68 +450,117 @@ class PullRequestModel(BaseModel):
else:
return _filtered_pull_requests
def count_awaiting_my_review(self, repo_name, search_q=None, source=False, statuses=None,
opened_by=None, user_id=None):
def _prepare_awaiting_my_review_review_query(
self, repo_name, user_id, search_q=None, statuses=None,
order_by=None, order_dir='desc'):
for_review_statuses = [
ChangesetStatus.STATUS_UNDER_REVIEW, ChangesetStatus.STATUS_NOT_REVIEWED
]
pull_request_alias = aliased(PullRequest)
status_alias = aliased(ChangesetStatus)
reviewers_alias = aliased(PullRequestReviewers)
repo_alias = aliased(Repository)
last_ver_subq = Session()\
.query(func.min(ChangesetStatus.version)) \
.filter(ChangesetStatus.pull_request_id == reviewers_alias.pull_request_id)\
.filter(ChangesetStatus.user_id == reviewers_alias.user_id) \
.subquery()
q = Session().query(pull_request_alias) \
.options(lazyload(pull_request_alias.author)) \
.join(reviewers_alias,
reviewers_alias.pull_request_id == pull_request_alias.pull_request_id) \
.join(repo_alias,
repo_alias.repo_id == pull_request_alias.target_repo_id) \
.outerjoin(status_alias,
and_(status_alias.user_id == reviewers_alias.user_id,
status_alias.pull_request_id == reviewers_alias.pull_request_id)) \
.filter(or_(status_alias.version == null(),
status_alias.version == last_ver_subq)) \
.filter(reviewers_alias.user_id == user_id) \
.filter(repo_alias.repo_name == repo_name) \
.filter(or_(status_alias.status == null(), status_alias.status.in_(for_review_statuses))) \
.group_by(pull_request_alias)
# closed,opened
if statuses:
q = q.filter(pull_request_alias.status.in_(statuses))
if search_q:
like_expression = u'%{}%'.format(safe_unicode(search_q))
q = q.join(User, User.user_id == pull_request_alias.user_id)
q = q.filter(or_(
cast(pull_request_alias.pull_request_id, String).ilike(like_expression),
User.username.ilike(like_expression),
pull_request_alias.title.ilike(like_expression),
pull_request_alias.description.ilike(like_expression),
))
if order_by:
order_map = {
'name_raw': pull_request_alias.pull_request_id,
'title': pull_request_alias.title,
'updated_on_raw': pull_request_alias.updated_on,
'target_repo': pull_request_alias.target_repo_id
}
if order_dir == 'asc':
q = q.order_by(order_map[order_by].asc())
else:
q = q.order_by(order_map[order_by].desc())
return q
def count_awaiting_my_review(self, repo_name, user_id, search_q=None, statuses=None):
"""
Count the number of pull requests for a specific repository that are
awaiting review from a specific user.
:param repo_name: target or source repo
:param search_q: filter by text
:param source: boolean flag to specify if repo_name refers to source
:param statuses: list of pull request statuses
:param opened_by: author user of the pull request
:param user_id: reviewer user of the pull request
:param search_q: filter by text
:param statuses: list of pull request statuses
:returns: int number of pull requests
"""
pull_requests = self.get_awaiting_my_review(
repo_name, search_q=search_q, source=source, statuses=statuses,
opened_by=opened_by, user_id=user_id)
q = self._prepare_awaiting_my_review_review_query(
repo_name, user_id, search_q=search_q, statuses=statuses)
return q.count()
return len(pull_requests)
def get_awaiting_my_review(self, repo_name, search_q=None, source=False, statuses=None,
opened_by=None, user_id=None, offset=0,
length=None, order_by=None, order_dir='desc'):
def get_awaiting_my_review(self, repo_name, user_id, search_q=None, statuses=None,
offset=0, length=None, order_by=None, order_dir='desc'):
"""
Get all pull requests for a specific repository that are awaiting
review from a specific user.
:param repo_name: target or source repo
:param search_q: filter by text
:param source: boolean flag to specify if repo_name refers to source
:param statuses: list of pull request statuses
:param opened_by: author user of the pull request
:param user_id: reviewer user of the pull request
:param search_q: filter by text
:param statuses: list of pull request statuses
:param offset: pagination offset
:param length: length of returned list
:param order_by: order of the returned list
:param order_dir: 'asc' or 'desc' ordering direction
:returns: list of pull requests
"""
pull_requests = self.get_all(
repo_name, search_q=search_q, source=source, statuses=statuses,
opened_by=opened_by, order_by=order_by, order_dir=order_dir)
_my = PullRequestModel().get_not_reviewed(user_id)
my_participation = []
for pr in pull_requests:
if pr in _my:
my_participation.append(pr)
_filtered_pull_requests = my_participation
q = self._prepare_awaiting_my_review_review_query(
repo_name, user_id, search_q=search_q, statuses=statuses,
order_by=order_by, order_dir=order_dir)
if length:
return _filtered_pull_requests[offset:offset+length]
pull_requests = q.limit(length).offset(offset).all()
else:
return _filtered_pull_requests
pull_requests = q.all()
def get_not_reviewed(self, user_id):
return [
x.pull_request for x in PullRequestReviewers.query().filter(
PullRequestReviewers.user_id == user_id).all()
]
return pull_requests
def _prepare_participating_query(self, user_id=None, statuses=None, query='',
order_by=None, order_dir='desc'):
def _prepare_im_participating_query(self, user_id=None, statuses=None, query='',
order_by=None, order_dir='desc'):
"""
return a query of pull-requests user is an creator, or he's added as a reviewer
"""
q = PullRequest.query()
if user_id:
reviewers_subquery = Session().query(
@ -535,7 +578,7 @@ class PullRequestModel(BaseModel):
if query:
like_expression = u'%{}%'.format(safe_unicode(query))
q = q.join(User)
q = q.join(User, User.user_id == PullRequest.user_id)
q = q.filter(or_(
cast(PullRequest.pull_request_id, String).ilike(like_expression),
User.username.ilike(like_expression),
@ -557,17 +600,97 @@ class PullRequestModel(BaseModel):
return q
def count_im_participating_in(self, user_id=None, statuses=None, query=''):
q = self._prepare_participating_query(user_id, statuses=statuses, query=query)
q = self._prepare_im_participating_query(user_id, statuses=statuses, query=query)
return q.count()
def get_im_participating_in(
self, user_id=None, statuses=None, query='', offset=0,
length=None, order_by=None, order_dir='desc'):
"""
Get all Pull requests that i'm participating in, or i have opened
Get all Pull requests that i'm participating in as a reviewer, or i have opened
"""
q = self._prepare_participating_query(
q = self._prepare_im_participating_query(
user_id, statuses=statuses, query=query, order_by=order_by,
order_dir=order_dir)
if length:
pull_requests = q.limit(length).offset(offset).all()
else:
pull_requests = q.all()
return pull_requests
def _prepare_participating_in_for_review_query(
self, user_id, statuses=None, query='', order_by=None, order_dir='desc'):
for_review_statuses = [
ChangesetStatus.STATUS_UNDER_REVIEW, ChangesetStatus.STATUS_NOT_REVIEWED
]
pull_request_alias = aliased(PullRequest)
status_alias = aliased(ChangesetStatus)
reviewers_alias = aliased(PullRequestReviewers)
last_ver_subq = Session()\
.query(func.min(ChangesetStatus.version)) \
.filter(ChangesetStatus.pull_request_id == reviewers_alias.pull_request_id)\
.filter(ChangesetStatus.user_id == reviewers_alias.user_id) \
.subquery()
q = Session().query(pull_request_alias) \
.options(lazyload(pull_request_alias.author)) \
.join(reviewers_alias,
reviewers_alias.pull_request_id == pull_request_alias.pull_request_id) \
.outerjoin(status_alias,
and_(status_alias.user_id == reviewers_alias.user_id,
status_alias.pull_request_id == reviewers_alias.pull_request_id)) \
.filter(or_(status_alias.version == null(),
status_alias.version == last_ver_subq)) \
.filter(reviewers_alias.user_id == user_id) \
.filter(or_(status_alias.status == null(), status_alias.status.in_(for_review_statuses))) \
.group_by(pull_request_alias)
# closed,opened
if statuses:
q = q.filter(pull_request_alias.status.in_(statuses))
if query:
like_expression = u'%{}%'.format(safe_unicode(query))
q = q.join(User, User.user_id == pull_request_alias.user_id)
q = q.filter(or_(
cast(pull_request_alias.pull_request_id, String).ilike(like_expression),
User.username.ilike(like_expression),
pull_request_alias.title.ilike(like_expression),
pull_request_alias.description.ilike(like_expression),
))
if order_by:
order_map = {
'name_raw': pull_request_alias.pull_request_id,
'title': pull_request_alias.title,
'updated_on_raw': pull_request_alias.updated_on,
'target_repo': pull_request_alias.target_repo_id
}
if order_dir == 'asc':
q = q.order_by(order_map[order_by].asc())
else:
q = q.order_by(order_map[order_by].desc())
return q
def count_im_participating_in_for_review(self, user_id, statuses=None, query=''):
q = self._prepare_participating_in_for_review_query(user_id, statuses=statuses, query=query)
return q.count()
def get_im_participating_in_for_review(
self, user_id, statuses=None, query='', offset=0,
length=None, order_by=None, order_dir='desc'):
"""
Get all Pull requests that needs user approval or rejection
"""
q = self._prepare_participating_in_for_review_query(
user_id, statuses=statuses, query=query, order_by=order_by,
order_dir=order_dir)

View file

@ -618,13 +618,13 @@ input[type="reset"] {
text-align: right;
li {
list-style: none;
text-align: right;
display: inline-block;
}
li.active {
background-color: @grey6;
.border ( @border-thickness, @grey4 );
a.active {
border: 2px solid @rcblue;
}
}

View file

@ -44,7 +44,7 @@
padding: @panel-padding;
&.panel-body-min-height {
min-height: 150px
min-height: 200px
}
}

View file

@ -1,17 +1,29 @@
<%namespace name="base" file="/base/base.mako"/>
<div class="panel panel-default">
<div class="panel-body">
<div style="height: 35px">
<%
selected_filter = 'all'
if c.closed:
selected_filter = 'all_closed'
%>
<div class="panel-heading">
<h3 class="panel-title">${_('Pull Requests You Participate In')}</h3>
</div>
<div class="panel-body panel-body-min-height">
<div class="title">
<ul class="button-links">
<li class="btn ${h.is_active('all', selected_filter)}"><a href="${h.route_path('my_account_pullrequests')}">${_('All')}</a></li>
<li class="btn ${h.is_active('all_closed', selected_filter)}"><a href="${h.route_path('my_account_pullrequests', _query={'pr_show_closed':1})}">${_('All + Closed')}</a></li>
<li><a class="btn ${h.is_active('all', c.selected_filter)}"
href="${h.route_path('my_account_pullrequests', _query={})}">
${_('Open')}
</a>
</li>
<li><a class="btn ${h.is_active('all_closed', c.selected_filter)}"
href="${h.route_path('my_account_pullrequests', _query={'closed':1})}">
${_('All + Closed')}
</a>
</li>
<li><a class="btn ${h.is_active('awaiting_my_review', c.selected_filter)}"
href="${h.route_path('my_account_pullrequests', _query={'awaiting_my_review':1})}">
${_('Awaiting my review')}
</a>
</li>
</ul>
<div class="grid-quick-filter">
@ -20,19 +32,13 @@
<i class="icon-search"></i>
</li>
<li class="grid-filter-box-input">
<input class="q_filter_box" id="q_filter" size="15" type="text" name="filter" placeholder="${_('quick filter...')}" value=""/>
<input class="q_filter_box" id="q_filter" size="15" type="text" name="filter"
placeholder="${_('quick filter...')}" value=""/>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">${_('Pull Requests You Participate In')}</h3>
</div>
<div class="panel-body panel-body-min-height">
<table id="pull_request_list_table" class="rctable table-bordered"></table>
</div>
</div>
@ -52,6 +58,7 @@
"url": "${h.route_path('my_account_pullrequests_data')}",
"data": function (d) {
d.closed = "${c.closed}";
d.awaiting_my_review = "${c.awaiting_my_review}";
},
"dataSrc": function (json) {
return json.data;
@ -60,13 +67,19 @@
dom: 'rtp',
pageLength: ${c.visual.dashboard_items},
order: [[1, "desc"]],
order: [[2, "desc"]],
columns: [
{
data: {
"_": "status",
"sort": "status"
}, title: "", className: "td-status", orderable: false
}, title: "PR", className: "td-status", orderable: false
},
{
data: {
"_": "my_status",
"sort": "status"
}, title: "You", className: "td-status", orderable: false
},
{
data: {

View file

@ -23,13 +23,14 @@
<div class="box">
<div class="title">
<ul class="button-links">
<li class="btn ${h.is_active('open', c.active)}"><a href="${h.route_path('pullrequest_show_all',repo_name=c.repo_name, _query={'source':0})}">${_('Opened')}</a></li>
<li class="btn ${h.is_active('my', c.active)}"><a href="${h.route_path('pullrequest_show_all',repo_name=c.repo_name, _query={'source':0,'my':1})}">${_('Opened by me')}</a></li>
<li class="btn ${h.is_active('awaiting', c.active)}"><a href="${h.route_path('pullrequest_show_all',repo_name=c.repo_name, _query={'source':0,'awaiting_review':1})}">${_('Awaiting review')}</a></li>
<li class="btn ${h.is_active('awaiting_my', c.active)}"><a href="${h.route_path('pullrequest_show_all',repo_name=c.repo_name, _query={'source':0,'awaiting_my_review':1})}">${_('Awaiting my review')}</a></li>
<li class="btn ${h.is_active('closed', c.active)}"><a href="${h.route_path('pullrequest_show_all',repo_name=c.repo_name, _query={'source':0,'closed':1})}">${_('Closed')}</a></li>
<li class="btn ${h.is_active('source', c.active)}"><a href="${h.route_path('pullrequest_show_all',repo_name=c.repo_name, _query={'source':1})}">${_('From this repo')}</a></li>
<li><a class="btn ${h.is_active('open', c.active)}" href="${h.route_path('pullrequest_show_all',repo_name=c.repo_name, _query={'source':0,'open':1})}">${_('Open')}</a></li>
<li><a class="btn ${h.is_active('my', c.active)}" href="${h.route_path('pullrequest_show_all',repo_name=c.repo_name, _query={'source':0,'my':1})}">${_('Created by me')}</a></li>
<li><a class="btn ${h.is_active('awaiting', c.active)}" href="${h.route_path('pullrequest_show_all',repo_name=c.repo_name, _query={'source':0,'awaiting_review':1})}">${_('Awaiting review')}</a></li>
<li><a class="btn ${h.is_active('awaiting_my', c.active)}" href="${h.route_path('pullrequest_show_all',repo_name=c.repo_name, _query={'source':0,'awaiting_my_review':1})}">${_('Awaiting my review')}</a></li>
<li><a class="btn ${h.is_active('closed', c.active)}" href="${h.route_path('pullrequest_show_all',repo_name=c.repo_name, _query={'source':0,'closed':1})}">${_('Closed')}</a></li>
<li><a class="btn ${h.is_active('source', c.active)}" href="${h.route_path('pullrequest_show_all',repo_name=c.repo_name, _query={'source':1})}">${_('From this repo')}</a></li>
</ul>
<ul class="links">
@ -88,20 +89,50 @@ $(document).ready(function() {
},
dom: 'rtp',
pageLength: ${c.visual.dashboard_items},
order: [[ 1, "desc" ]],
order: [[ 2, "desc" ]],
columns: [
{ data: {"_": "status",
"sort": "status"}, title: "", className: "td-status", orderable: false},
{ data: {"_": "name",
"sort": "name_raw"}, title: "${_('Id')}", className: "td-componentname", "type": "num" },
{ data: {"_": "title",
"sort": "title"}, title: "${_('Title')}", className: "td-description" },
{ data: {"_": "author",
"sort": "author_raw"}, title: "${_('Author')}", className: "td-user", orderable: false },
{ data: {"_": "comments",
"sort": "comments_raw"}, title: "", className: "td-comments", orderable: false},
{ data: {"_": "updated_on",
"sort": "updated_on_raw"}, title: "${_('Last Update')}", className: "td-time" }
{
data: {
"_": "status",
"sort": "status"
}, title: "PR", className: "td-status", orderable: false
},
{
data: {
"_": "my_status",
"sort": "status"
}, title: "You", className: "td-status", orderable: false
},
{
data: {
"_": "name",
"sort": "name_raw"
}, title: "${_('Id')}", className: "td-componentname", "type": "num"
},
{
data: {
"_": "title",
"sort": "title"
}, title: "${_('Title')}", className: "td-description"
},
{
data: {
"_": "author",
"sort": "author_raw"
}, title: "${_('Author')}", className: "td-user", orderable: false
},
{
data: {
"_": "comments",
"sort": "comments_raw"
}, title: "", className: "td-comments", orderable: false
},
{
data: {
"_": "updated_on",
"sort": "updated_on_raw"
}, title: "${_('Last Update')}", className: "td-time"
}
],
language: {
paginate: DEFAULT_GRID_PAGINATION,