pull-request-reviewers: added option to add reviewers by picking an user group for pull requests.
- fixes #5228
This commit is contained in:
parent
a3ed262ffd
commit
0b80fe66c9
7 changed files with 90 additions and 57 deletions
|
|
@ -53,6 +53,7 @@ class HomeView(BaseAppView):
|
|||
query = self.request.GET.get('query')
|
||||
active = str2bool(self.request.GET.get('active') or True)
|
||||
include_groups = str2bool(self.request.GET.get('user_groups'))
|
||||
expand_groups = str2bool(self.request.GET.get('user_groups_expand'))
|
||||
|
||||
log.debug('generating user list, query:%s, active:%s, with_groups:%s',
|
||||
query, active, include_groups)
|
||||
|
|
@ -63,7 +64,8 @@ class HomeView(BaseAppView):
|
|||
if include_groups:
|
||||
# extend with user groups
|
||||
_user_groups = UserGroupModel().get_user_groups(
|
||||
name_contains=query, only_active=active)
|
||||
name_contains=query, only_active=active,
|
||||
expand_groups=expand_groups)
|
||||
_users = _users + _user_groups
|
||||
|
||||
return {'suggestions': _users}
|
||||
|
|
@ -76,11 +78,14 @@ class HomeView(BaseAppView):
|
|||
def user_group_autocomplete_data(self):
|
||||
query = self.request.GET.get('query')
|
||||
active = str2bool(self.request.GET.get('active') or True)
|
||||
expand_groups = str2bool(self.request.GET.get('user_groups_expand'))
|
||||
|
||||
log.debug('generating user group list, query:%s, active:%s',
|
||||
query, active)
|
||||
|
||||
_user_groups = UserGroupModel().get_user_groups(
|
||||
name_contains=query, only_active=active)
|
||||
name_contains=query, only_active=active,
|
||||
expand_groups=expand_groups)
|
||||
_user_groups = _user_groups
|
||||
|
||||
return {'suggestions': _user_groups}
|
||||
|
|
|
|||
|
|
@ -65,9 +65,24 @@ class UserModel(BaseModel):
|
|||
def get_user(self, user):
|
||||
return self._get_user(user)
|
||||
|
||||
def get_users(self, name_contains=None, limit=20, only_active=True):
|
||||
def _serialize_user(self, user):
|
||||
import rhodecode.lib.helpers as h
|
||||
|
||||
return {
|
||||
'id': user.user_id,
|
||||
'first_name': user.name,
|
||||
'last_name': user.lastname,
|
||||
'username': user.username,
|
||||
'email': user.email,
|
||||
'icon_link': h.gravatar_url(user.email, 30),
|
||||
'value_display': h.person(user),
|
||||
'value': user.username,
|
||||
'value_type': 'user',
|
||||
'active': user.active,
|
||||
}
|
||||
|
||||
def get_users(self, name_contains=None, limit=20, only_active=True):
|
||||
|
||||
query = self.sa.query(User)
|
||||
if only_active:
|
||||
query = query.filter(User.active == true())
|
||||
|
|
@ -85,19 +100,7 @@ class UserModel(BaseModel):
|
|||
users = query.all()
|
||||
|
||||
_users = [
|
||||
{
|
||||
'id': user.user_id,
|
||||
'first_name': user.name,
|
||||
'last_name': user.lastname,
|
||||
'username': user.username,
|
||||
'email': user.email,
|
||||
'icon_link': h.gravatar_url(user.email, 30),
|
||||
'value_display': h.person(user),
|
||||
'value': user.username,
|
||||
'value_type': 'user',
|
||||
'active': user.active,
|
||||
}
|
||||
for user in users
|
||||
self._serialize_user(user) for user in users
|
||||
]
|
||||
return _users
|
||||
|
||||
|
|
|
|||
|
|
@ -30,12 +30,14 @@ import traceback
|
|||
from rhodecode.lib.utils2 import safe_str, safe_unicode
|
||||
from rhodecode.model import BaseModel
|
||||
from rhodecode.model.scm import UserGroupList
|
||||
from rhodecode.model.db import true, func, UserGroupMember, UserGroup,\
|
||||
UserGroupRepoToPerm, Permission, UserGroupToPerm, User, UserUserGroupToPerm,\
|
||||
UserGroupUserGroupToPerm, UserGroupRepoGroupToPerm
|
||||
from rhodecode.lib.exceptions import UserGroupAssignedException,\
|
||||
RepoGroupAssignmentError
|
||||
from rhodecode.lib.utils2 import get_current_rhodecode_user, action_logger_generic
|
||||
from rhodecode.model.db import (
|
||||
true, func, User, UserGroupMember, UserGroup,
|
||||
UserGroupRepoToPerm, Permission, UserGroupToPerm, UserUserGroupToPerm,
|
||||
UserGroupUserGroupToPerm, UserGroupRepoGroupToPerm)
|
||||
from rhodecode.lib.exceptions import (
|
||||
UserGroupAssignedException, RepoGroupAssignmentError)
|
||||
from rhodecode.lib.utils2 import (
|
||||
get_current_rhodecode_user, action_logger_generic)
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -113,7 +115,7 @@ class UserGroupModel(BaseModel):
|
|||
if member_type == 'user':
|
||||
self.revoke_user_permission(user_group=user_group, user=member_id)
|
||||
else:
|
||||
#check if we have permissions to alter this usergroup
|
||||
# check if we have permissions to alter this usergroup
|
||||
member_name = UserGroup.get(member_id).users_group_name
|
||||
if not check_perms or HasUserGroupPermissionAny(*req_perms)(member_name, user=cur_user):
|
||||
self.revoke_user_group_permission(
|
||||
|
|
@ -540,10 +542,28 @@ class UserGroupModel(BaseModel):
|
|||
log.debug('Adding user %s to user group %s', user.username, gr.users_group_name)
|
||||
UserGroupModel().add_user_to_group(gr.users_group_name, user.username)
|
||||
|
||||
def _serialize_user_group(self, user_group):
|
||||
import rhodecode.lib.helpers as h
|
||||
return {
|
||||
'id': user_group.users_group_id,
|
||||
# TODO: marcink figure out a way to generate the url for the
|
||||
# icon
|
||||
'icon_link': '',
|
||||
'value_display': 'Group: %s (%d members)' % (
|
||||
user_group.users_group_name, len(user_group.members),),
|
||||
'value': user_group.users_group_name,
|
||||
'description': user_group.user_group_description,
|
||||
'owner': user_group.user.username,
|
||||
|
||||
'owner_icon': h.gravatar_url(user_group.user.email, 30),
|
||||
'value_display_owner': h.person(user_group.user.email),
|
||||
|
||||
'value_type': 'user_group',
|
||||
'active': user_group.users_group_active,
|
||||
}
|
||||
|
||||
def get_user_groups(self, name_contains=None, limit=20, only_active=True,
|
||||
expand_groups=False):
|
||||
import rhodecode.lib.helpers as h
|
||||
|
||||
query = self.sa.query(UserGroup)
|
||||
if only_active:
|
||||
query = query.filter(UserGroup.users_group_active == true())
|
||||
|
|
@ -560,26 +580,19 @@ class UserGroupModel(BaseModel):
|
|||
perm_set = ['usergroup.read', 'usergroup.write', 'usergroup.admin']
|
||||
user_groups = UserGroupList(user_groups, perm_set=perm_set)
|
||||
|
||||
_groups = [
|
||||
{
|
||||
'id': group.users_group_id,
|
||||
# TODO: marcink figure out a way to generate the url for the
|
||||
# icon
|
||||
'icon_link': '',
|
||||
'value_display': 'Group: %s (%d members)' % (
|
||||
group.users_group_name, len(group.members),),
|
||||
'value': group.users_group_name,
|
||||
'description': group.user_group_description,
|
||||
'owner': group.user.username,
|
||||
# store same serialize method to extract data from User
|
||||
from rhodecode.model.user import UserModel
|
||||
serialize_user = UserModel()._serialize_user
|
||||
|
||||
'owner_icon': h.gravatar_url(group.user.email, 30),
|
||||
'value_display_owner': h.person(group.user.email),
|
||||
|
||||
'value_type': 'user_group',
|
||||
'active': group.users_group_active,
|
||||
}
|
||||
for group in user_groups
|
||||
]
|
||||
_groups = []
|
||||
for group in user_groups:
|
||||
entry = self._serialize_user_group(group)
|
||||
if expand_groups:
|
||||
expanded_members = []
|
||||
for member in group.members:
|
||||
expanded_members.append(serialize_user(member.user))
|
||||
entry['members'] = expanded_members
|
||||
_groups.append(entry)
|
||||
return _groups
|
||||
|
||||
@staticmethod
|
||||
|
|
|
|||
|
|
@ -198,8 +198,8 @@ var initPullRequestsCodeMirror = function (textAreaId) {
|
|||
/**
|
||||
* Reviewer autocomplete
|
||||
*/
|
||||
var ReviewerAutoComplete = function(input_id) {
|
||||
$('#'+input_id).autocomplete({
|
||||
var ReviewerAutoComplete = function(inputId) {
|
||||
$(inputId).autocomplete({
|
||||
serviceUrl: pyroutes.url('user_autocomplete_data'),
|
||||
minChars:2,
|
||||
maxHeight:400,
|
||||
|
|
@ -207,14 +207,26 @@ var ReviewerAutoComplete = function(input_id) {
|
|||
showNoSuggestionNotice: true,
|
||||
tabDisabled: true,
|
||||
autoSelectFirst: true,
|
||||
params: { user_id: templateContext.rhodecode_user.user_id, user_groups:true, user_groups_expand:true },
|
||||
formatResult: autocompleteFormatResult,
|
||||
lookupFilter: autocompleteFilterResult,
|
||||
onSelect: function(suggestion, data){
|
||||
var msg = _gettext('added manually by "{0}"');
|
||||
var reasons = [msg.format(templateContext.rhodecode_user.username)];
|
||||
addReviewMember(data.id, data.first_name, data.last_name,
|
||||
data.username, data.icon_link, reasons);
|
||||
$('#'+input_id).val('');
|
||||
onSelect: function(element, data) {
|
||||
|
||||
var reasons = [_gettext('added manually by "{0}"').format(templateContext.rhodecode_user.username)];
|
||||
if (data.value_type == 'user_group') {
|
||||
reasons.push(_gettext('member of "{0}"').format(data.value_display));
|
||||
|
||||
$.each(data.members, function(index, member_data) {
|
||||
addReviewMember(member_data.id, member_data.first_name, member_data.last_name,
|
||||
member_data.username, member_data.icon_link, reasons);
|
||||
})
|
||||
|
||||
} else {
|
||||
addReviewMember(data.id, data.first_name, data.last_name,
|
||||
data.username, data.icon_link, reasons);
|
||||
}
|
||||
|
||||
$(inputId).val('');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -886,7 +886,7 @@ $(document).ready(function() {
|
|||
AJAX_COMMENT_DELETE_URL = "/rhodecode-momentum/pull-request-comment/__COMMENT_ID__/delete";
|
||||
|
||||
$(function(){
|
||||
ReviewerAutoComplete('user');
|
||||
ReviewerAutoComplete('#user');
|
||||
|
||||
$('#open_edit_reviewers').on('click', function(e){
|
||||
$('#open_edit_reviewers').hide();
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@
|
|||
<input type="hidden" name="__end__" value="review_members:sequence">
|
||||
<div id="add_reviewer_input" class='ac'>
|
||||
<div class="reviewer_ac">
|
||||
${h.text('user', class_='ac-input', placeholder=_('Add reviewer'))}
|
||||
${h.text('user', class_='ac-input', placeholder=_('Add reviewer or reviewer group'))}
|
||||
<div id="reviewers_container"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -584,7 +584,7 @@ $(function(){
|
|||
loadDefaultReviewers();
|
||||
% endif
|
||||
|
||||
ReviewerAutoComplete('user');
|
||||
ReviewerAutoComplete('#user');
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -363,7 +363,7 @@
|
|||
<div id="add_reviewer_input" class='ac' style="display: none;">
|
||||
%if c.allowed_to_update:
|
||||
<div class="reviewer_ac">
|
||||
${h.text('user', class_='ac-input', placeholder=_('Add reviewer'))}
|
||||
${h.text('user', class_='ac-input', placeholder=_('Add reviewer or reviewer group'))}
|
||||
<div id="reviewers_container"></div>
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -617,7 +617,7 @@
|
|||
|
||||
|
||||
$(function(){
|
||||
ReviewerAutoComplete('user');
|
||||
ReviewerAutoComplete('#user');
|
||||
// custom code mirror
|
||||
var codeMirrorInstance = initPullRequestsCodeMirror('#pr-description-input');
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue