Commit d7840984 authored by Jan Provaznik's avatar Jan Provaznik

Merge branch '291940-ee-group-improvements' into 'master'

Refactoring and improvements for ee/lib/ee/api/members.rb

See merge request gitlab-org/gitlab!49357
parents 0b13cce3 03843402
# frozen_string_literal: true # frozen_string_literal: true
module SortingHelper module SortingHelper
include SortingTitlesValuesHelper
def sort_options_hash def sort_options_hash
{ {
sort_value_created_date => sort_title_created_date, sort_value_created_date => sort_title_created_date,
...@@ -113,19 +115,6 @@ module SortingHelper ...@@ -113,19 +115,6 @@ module SortingHelper
) )
end end
def member_sort_options_hash
{
sort_value_access_level_asc => sort_title_access_level_asc,
sort_value_access_level_desc => sort_title_access_level_desc,
sort_value_last_joined => sort_title_last_joined,
sort_value_name => sort_title_name_asc,
sort_value_name_desc => sort_title_name_desc,
sort_value_oldest_joined => sort_title_oldest_joined,
sort_value_oldest_signin => sort_title_oldest_signin,
sort_value_recently_signin => sort_title_recently_signin
}
end
def milestone_sort_options_hash def milestone_sort_options_hash
{ {
sort_value_name => sort_title_name_asc, sort_value_name => sort_title_name_asc,
...@@ -187,6 +176,19 @@ module SortingHelper ...@@ -187,6 +176,19 @@ module SortingHelper
} }
end end
def member_sort_options_hash
{
sort_value_access_level_asc => sort_title_access_level_asc,
sort_value_access_level_desc => sort_title_access_level_desc,
sort_value_last_joined => sort_title_last_joined,
sort_value_name => sort_title_name_asc,
sort_value_name_desc => sort_title_name_desc,
sort_value_oldest_joined => sort_title_oldest_joined,
sort_value_oldest_signin => sort_title_oldest_signin,
sort_value_recently_signin => sort_title_recently_signin
}
end
def sortable_item(item, path, sorted_by) def sortable_item(item, path, sorted_by)
link_to item, path, class: sorted_by == item ? 'is-active' : '' link_to item, path, class: sorted_by == item ? 'is-active' : ''
end end
...@@ -276,340 +278,6 @@ module SortingHelper ...@@ -276,340 +278,6 @@ module SortingHelper
sort_direction_button(url, reverse_sort, sort_value) sort_direction_button(url, reverse_sort, sort_value)
end end
# Titles.
def sort_title_access_level_asc
s_('SortOptions|Access level, ascending')
end
def sort_title_access_level_desc
s_('SortOptions|Access level, descending')
end
def sort_title_created_date
s_('SortOptions|Created date')
end
def sort_title_downvotes
s_('SortOptions|Least popular')
end
def sort_title_due_date
s_('SortOptions|Due date')
end
def sort_title_due_date_later
s_('SortOptions|Due later')
end
def sort_title_due_date_soon
s_('SortOptions|Due soon')
end
def sort_title_label_priority
s_('SortOptions|Label priority')
end
def sort_title_largest_group
s_('SortOptions|Largest group')
end
def sort_title_largest_repo
s_('SortOptions|Largest repository')
end
def sort_title_last_joined
s_('SortOptions|Last joined')
end
def sort_title_latest_activity
s_('SortOptions|Last updated')
end
def sort_title_milestone
s_('SortOptions|Milestone due date')
end
def sort_title_milestone_later
s_('SortOptions|Milestone due later')
end
def sort_title_milestone_soon
s_('SortOptions|Milestone due soon')
end
def sort_title_name
s_('SortOptions|Name')
end
def sort_title_name_asc
s_('SortOptions|Name, ascending')
end
def sort_title_name_desc
s_('SortOptions|Name, descending')
end
def sort_title_oldest_activity
s_('SortOptions|Oldest updated')
end
def sort_title_oldest_created
s_('SortOptions|Oldest created')
end
def sort_title_oldest_joined
s_('SortOptions|Oldest joined')
end
def sort_title_oldest_signin
s_('SortOptions|Oldest sign in')
end
def sort_title_oldest_starred
s_('SortOptions|Oldest starred')
end
def sort_title_oldest_updated
s_('SortOptions|Oldest updated')
end
def sort_title_popularity
s_('SortOptions|Popularity')
end
def sort_title_priority
s_('SortOptions|Priority')
end
def sort_title_recently_created
s_('SortOptions|Last created')
end
def sort_title_recently_signin
s_('SortOptions|Recent sign in')
end
def sort_title_recently_starred
s_('SortOptions|Recently starred')
end
def sort_title_recently_updated
s_('SortOptions|Last updated')
end
def sort_title_start_date_later
s_('SortOptions|Start later')
end
def sort_title_start_date_soon
s_('SortOptions|Start soon')
end
def sort_title_upvotes
s_('SortOptions|Most popular')
end
def sort_title_contacted_date
s_('SortOptions|Last Contact')
end
def sort_title_most_stars
s_('SortOptions|Most stars')
end
def sort_title_stars
s_('SortOptions|Stars')
end
def sort_title_oldest_last_activity
s_('SortOptions|Oldest last activity')
end
def sort_title_recently_last_activity
s_('SortOptions|Recent last activity')
end
def sort_title_relative_position
s_('SortOptions|Manual')
end
def sort_title_size
s_('SortOptions|Size')
end
def sort_title_expire_date
s_('SortOptions|Expired date')
end
def sort_title_relevant
s_('SortOptions|Relevant')
end
# Values.
def sort_value_access_level_asc
'access_level_asc'
end
def sort_value_access_level_desc
'access_level_desc'
end
def sort_value_created_date
'created_date'
end
def sort_value_downvotes
'downvotes_desc'
end
def sort_value_due_date
'due_date'
end
def sort_value_due_date_later
'due_date_desc'
end
def sort_value_due_date_soon
'due_date_asc'
end
def sort_value_label_priority
'label_priority'
end
def sort_value_largest_group
'storage_size_desc'
end
def sort_value_largest_repo
'storage_size_desc'
end
def sort_value_last_joined
'last_joined'
end
def sort_value_latest_activity
'latest_activity_desc'
end
def sort_value_milestone
'milestone'
end
def sort_value_milestone_later
'milestone_due_desc'
end
def sort_value_milestone_soon
'milestone_due_asc'
end
def sort_value_name
'name_asc'
end
def sort_value_name_desc
'name_desc'
end
def sort_value_oldest_activity
'latest_activity_asc'
end
def sort_value_oldest_created
'created_asc'
end
def sort_value_oldest_signin
'oldest_sign_in'
end
def sort_value_oldest_joined
'oldest_joined'
end
def sort_value_oldest_updated
'updated_asc'
end
def sort_value_popularity
'popularity'
end
def sort_value_most_popular
'popularity_desc'
end
def sort_value_least_popular
'popularity_asc'
end
def sort_value_priority
'priority'
end
def sort_value_recently_created
'created_desc'
end
def sort_value_recently_signin
'recent_sign_in'
end
def sort_value_recently_updated
'updated_desc'
end
def sort_value_start_date_later
'start_date_desc'
end
def sort_value_start_date_soon
'start_date_asc'
end
def sort_value_upvotes
'upvotes_desc'
end
def sort_value_contacted_date
'contacted_asc'
end
def sort_value_stars_desc
'stars_desc'
end
def sort_value_stars_asc
'stars_asc'
end
def sort_value_oldest_last_activity
'last_activity_on_asc'
end
def sort_value_recently_last_activity
'last_activity_on_desc'
end
def sort_value_relative_position
'relative_position'
end
def sort_value_size
'size_desc'
end
def sort_value_expire_date
'expired_asc'
end
def sort_value_relevant
'relevant'
end
def packages_sort_options_hash def packages_sort_options_hash
{ {
sort_value_recently_created => sort_title_created_date, sort_value_recently_created => sort_title_created_date,
......
# frozen_string_literal: true
module SortingTitlesValuesHelper
# Titles.
def sort_title_access_level_asc
s_('SortOptions|Access level, ascending')
end
def sort_title_access_level_desc
s_('SortOptions|Access level, descending')
end
def sort_title_created_date
s_('SortOptions|Created date')
end
def sort_title_downvotes
s_('SortOptions|Least popular')
end
def sort_title_due_date
s_('SortOptions|Due date')
end
def sort_title_due_date_later
s_('SortOptions|Due later')
end
def sort_title_due_date_soon
s_('SortOptions|Due soon')
end
def sort_title_label_priority
s_('SortOptions|Label priority')
end
def sort_title_largest_group
s_('SortOptions|Largest group')
end
def sort_title_largest_repo
s_('SortOptions|Largest repository')
end
def sort_title_last_joined
s_('SortOptions|Last joined')
end
def sort_title_latest_activity
s_('SortOptions|Last updated')
end
def sort_title_milestone
s_('SortOptions|Milestone due date')
end
def sort_title_milestone_later
s_('SortOptions|Milestone due later')
end
def sort_title_milestone_soon
s_('SortOptions|Milestone due soon')
end
def sort_title_name
s_('SortOptions|Name')
end
def sort_title_name_asc
s_('SortOptions|Name, ascending')
end
def sort_title_name_desc
s_('SortOptions|Name, descending')
end
def sort_title_oldest_activity
s_('SortOptions|Oldest updated')
end
def sort_title_oldest_created
s_('SortOptions|Oldest created')
end
def sort_title_oldest_joined
s_('SortOptions|Oldest joined')
end
def sort_title_oldest_signin
s_('SortOptions|Oldest sign in')
end
def sort_title_oldest_starred
s_('SortOptions|Oldest starred')
end
def sort_title_oldest_updated
s_('SortOptions|Oldest updated')
end
def sort_title_popularity
s_('SortOptions|Popularity')
end
def sort_title_priority
s_('SortOptions|Priority')
end
def sort_title_recently_created
s_('SortOptions|Last created')
end
def sort_title_recently_signin
s_('SortOptions|Recent sign in')
end
def sort_title_recently_starred
s_('SortOptions|Recently starred')
end
def sort_title_recently_updated
s_('SortOptions|Last updated')
end
def sort_title_start_date_later
s_('SortOptions|Start later')
end
def sort_title_start_date_soon
s_('SortOptions|Start soon')
end
def sort_title_upvotes
s_('SortOptions|Most popular')
end
def sort_title_contacted_date
s_('SortOptions|Last Contact')
end
def sort_title_most_stars
s_('SortOptions|Most stars')
end
def sort_title_stars
s_('SortOptions|Stars')
end
def sort_title_oldest_last_activity
s_('SortOptions|Oldest last activity')
end
def sort_title_recently_last_activity
s_('SortOptions|Recent last activity')
end
def sort_title_relative_position
s_('SortOptions|Manual')
end
def sort_title_size
s_('SortOptions|Size')
end
def sort_title_expire_date
s_('SortOptions|Expired date')
end
def sort_title_relevant
s_('SortOptions|Relevant')
end
# Values.
def sort_value_access_level_asc
'access_level_asc'
end
def sort_value_access_level_desc
'access_level_desc'
end
def sort_value_created_date
'created_date'
end
def sort_value_downvotes
'downvotes_desc'
end
def sort_value_due_date
'due_date'
end
def sort_value_due_date_later
'due_date_desc'
end
def sort_value_due_date_soon
'due_date_asc'
end
def sort_value_label_priority
'label_priority'
end
def sort_value_largest_group
'storage_size_desc'
end
def sort_value_largest_repo
'storage_size_desc'
end
def sort_value_last_joined
'last_joined'
end
def sort_value_latest_activity
'latest_activity_desc'
end
def sort_value_milestone
'milestone'
end
def sort_value_milestone_later
'milestone_due_desc'
end
def sort_value_milestone_soon
'milestone_due_asc'
end
def sort_value_name
'name_asc'
end
def sort_value_name_desc
'name_desc'
end
def sort_value_oldest_activity
'latest_activity_asc'
end
def sort_value_oldest_created
'created_asc'
end
def sort_value_oldest_signin
'oldest_sign_in'
end
def sort_value_oldest_joined
'oldest_joined'
end
def sort_value_oldest_updated
'updated_asc'
end
def sort_value_popularity
'popularity'
end
def sort_value_most_popular
'popularity_desc'
end
def sort_value_least_popular
'popularity_asc'
end
def sort_value_priority
'priority'
end
def sort_value_recently_created
'created_desc'
end
def sort_value_recently_signin
'recent_sign_in'
end
def sort_value_recently_updated
'updated_desc'
end
def sort_value_start_date_later
'start_date_desc'
end
def sort_value_start_date_soon
'start_date_asc'
end
def sort_value_upvotes
'upvotes_desc'
end
def sort_value_contacted_date
'contacted_asc'
end
def sort_value_stars_desc
'stars_desc'
end
def sort_value_stars_asc
'stars_asc'
end
def sort_value_oldest_last_activity
'last_activity_on_asc'
end
def sort_value_recently_last_activity
'last_activity_on_desc'
end
def sort_value_relative_position
'relative_position'
end
def sort_value_size
'size_desc'
end
def sort_value_expire_date
'expired_asc'
end
def sort_value_relevant
'relevant'
end
end
SortingHelper.include_if_ee('::EE::SortingTitlesValuesHelper')
# frozen_string_literal: true
class BilledUsersFinder
def initialize(group, search_term: nil, order_by: 'name_asc')
@group = group
@search_term = search_term
@order_by = order_by
end
def execute
return User.none unless group_billed_user_ids.any?
users = ::User.id_in(group_billed_user_ids)
users = users.search(search_term) if search_term
users.sort_by_attribute(order_by)
end
private
attr_reader :group, :search_term, :order_by
def group_billed_user_ids
@group_billed_user_ids ||= group.billed_user_ids
end
end
...@@ -75,93 +75,5 @@ module EE ...@@ -75,93 +75,5 @@ module EE
class: "btn btn-default has-tooltip qa-reverse-sort btn-sort-direction", class: "btn btn-default has-tooltip qa-reverse-sort btn-sort-direction",
title: _("Sort direction") title: _("Sort direction")
end end
def sort_title_start_date
s_('SortOptions|Start date')
end
def sort_title_end_date
s_('SortOptions|Due date')
end
def sort_title_less_weight
s_('SortOptions|Less weight')
end
def sort_title_more_weight
s_('SortOptions|More weight')
end
def sort_title_weight
s_('SortOptions|Weight')
end
def sort_title_blocking
s_('SortOptions|Blocking')
end
def sort_title_project_name
s_('SortOptions|Project')
end
def sort_title_version
s_('SortOptions|Version')
end
def sort_title_type
s_('SortOptions|Type')
end
def sort_value_start_date
'start_date_asc'
end
def sort_value_end_date
'end_date_asc'
end
def sort_value_end_date_later
'end_date_desc'
end
def sort_value_less_weight
'weight_asc'
end
def sort_value_more_weight
'weight_desc'
end
def sort_value_weight
'weight'
end
def sort_value_blocking_desc
'blocking_issues_desc'
end
def sort_value_project_name_asc
'project_name_asc'
end
def sort_value_project_name_desc
'project_name_desc'
end
def sort_value_version_asc
'version_asc'
end
def sort_value_version_desc
'version_desc'
end
def sort_value_type_asc
'type_asc'
end
def sort_value_type_desc
'type_desc'
end
end end
end end
# frozen_string_literal: true
module EE
module SortingTitlesValuesHelper
def sort_title_start_date
s_('SortOptions|Start date')
end
def sort_title_end_date
s_('SortOptions|Due date')
end
def sort_title_less_weight
s_('SortOptions|Less weight')
end
def sort_title_more_weight
s_('SortOptions|More weight')
end
def sort_title_weight
s_('SortOptions|Weight')
end
def sort_title_blocking
s_('SortOptions|Blocking')
end
def sort_title_project_name
s_('SortOptions|Project')
end
def sort_title_version
s_('SortOptions|Version')
end
def sort_title_type
s_('SortOptions|Type')
end
def sort_value_start_date
'start_date_asc'
end
def sort_value_end_date
'end_date_asc'
end
def sort_value_end_date_later
'end_date_desc'
end
def sort_value_less_weight
'weight_asc'
end
def sort_value_more_weight
'weight_desc'
end
def sort_value_weight
'weight'
end
def sort_value_blocking_desc
'blocking_issues_desc'
end
def sort_value_project_name_asc
'project_name_asc'
end
def sort_value_project_name_desc
'project_name_desc'
end
def sort_value_version_asc
'version_asc'
end
def sort_value_version_desc
'version_desc'
end
def sort_value_type_asc
'type_asc'
end
def sort_value_type_desc
'type_desc'
end
end
end
...@@ -8,10 +8,8 @@ module EE ...@@ -8,10 +8,8 @@ module EE
extend ::Gitlab::Utils::Override extend ::Gitlab::Utils::Override
class << self class << self
include ::SortingHelper
def member_sort_options def member_sort_options
member_sort_options_hash.keys %w(access_level_asc access_level_desc last_joined name_asc name_desc oldest_joined oldest_sign_in recent_sign_in)
end end
end end
...@@ -83,13 +81,6 @@ module EE ...@@ -83,13 +81,6 @@ module EE
action: :create action: :create
).for_member(member).security_event ).for_member(member).security_event
end end
def billed_users_for(group, search_term, order_by)
users = ::User.id_in(group.billed_user_ids)
users = users.search(search_term) if search_term
users.sort_by_attribute(order_by || 'name_asc')
end
end end
end end
end end
......
...@@ -57,7 +57,11 @@ module EE ...@@ -57,7 +57,11 @@ module EE
bad_request!(nil) unless ::Ability.allowed?(current_user, :admin_group_member, group) bad_request!(nil) unless ::Ability.allowed?(current_user, :admin_group_member, group)
sorting = params[:sort] || 'id_asc' sorting = params[:sort] || 'id_asc'
users = paginate(billed_users_for(group, params[:search], sorting)) users = paginate(
BilledUsersFinder.new(group,
search_term: params[:search],
order_by: sorting).execute
)
present users, with: ::API::Entities::UserBasic, current_user: current_user present users, with: ::API::Entities::UserBasic, current_user: current_user
end end
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe BilledUsersFinder do
let_it_be(:group) { create(:group) }
let(:search_term) { nil }
let(:order_by) { nil }
describe '#execute' do
let_it_be(:maria) { create(:group_member, group: group, user: create(:user, name: 'Maria Gomez')) }
let_it_be(:john_smith) { create(:group_member, group: group, user: create(:user, name: 'John Smith')) }
let_it_be(:john_doe) { create(:group_member, group: group, user: create(:user, name: 'John Doe')) }
let_it_be(:sophie) { create(:group_member, group: group, user: create(:user, name: 'Sophie Dupont')) }
subject { described_class.new(group, search_term: search_term, order_by: order_by) }
context 'when a group does not have any billed users' do
it 'returns an empty array' do
allow(group).to receive(:billed_user_ids).and_return([])
expect(subject.execute).to be_empty
end
end
context 'when a search parameter is provided' do
let(:search_term) { 'John' }
context 'when a sorting parameter is provided (eg name descending)' do
let(:order_by) { 'name_desc' }
it 'sorts results accordingly' do
expect(subject.execute).to eq([john_smith, john_doe].map(&:user))
end
end
context 'when a sorting parameter is not provided' do
subject { described_class.new(group, search_term: search_term) }
it 'sorts expected results in name_asc order' do
expect(subject.execute).to eq([john_doe, john_smith].map(&:user))
end
end
end
context 'when a search parameter is not present' do
subject { described_class.new(group) }
it 'returns expected users in name asc order when a sorting is not provided either' do
allow(group).to receive(:billed_user_members).and_return([john_doe, john_smith, sophie, maria])
expect(subject.execute).to eq([john_doe, john_smith, maria, sophie].map(&:user))
end
context 'and when a sorting parameter is provided (eg name descending)' do
let(:order_by) { 'name_desc' }
subject { described_class.new(group, search_term: search_term, order_by: order_by) }
it 'sorts results accordingly' do
expect(subject.execute).to eq([sophie, maria, john_smith, john_doe].map(&:user))
end
end
end
end
end
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe EE::API::Helpers::MembersHelpers do RSpec.describe EE::API::Helpers::MembersHelpers do
include SortingHelper
let(:members_helpers) { Class.new.include(described_class).new } let(:members_helpers) { Class.new.include(described_class).new }
before do before do
...@@ -34,51 +36,9 @@ RSpec.describe EE::API::Helpers::MembersHelpers do ...@@ -34,51 +36,9 @@ RSpec.describe EE::API::Helpers::MembersHelpers do
end end
end end
describe '#billed_users_for' do describe '.member_sort_options' do
let_it_be(:group) { create(:group) } it 'lists all keys available in group member view' do
let_it_be(:maria) { create(:group_member, group: group, user: create(:user, name: 'Maria Gomez')) } expect(described_class.member_sort_options).to match_array(member_sort_options_hash.keys)
let_it_be(:john_smith) { create(:group_member, group: group, user: create(:user, name: 'John Smith')) }
let_it_be(:john_doe) { create(:group_member, group: group, user: create(:user, name: 'John Doe')) }
let_it_be(:sophie) { create(:group_member, group: group, user: create(:user, name: 'Sophie Dupont')) }
let(:search_term) { nil }
let(:order_by) { nil }
subject { members_helpers.billed_users_for(group, search_term, order_by) }
context 'when a search parameter is present' do
let(:search_term) { 'John' }
context 'when a sorting parameter is provided (eg name descending)' do
let(:order_by) { 'name_desc' }
it 'sorts results accordingly' do
expect(subject).to eq([john_smith, john_doe].map(&:user))
end
end
context 'when a sorting parameter is not provided' do
let(:order_by) { nil }
it 'sorts results by name ascending' do
expect(subject).to eq([john_doe, john_smith].map(&:user))
end
end
end
context 'when a search parameter is not present' do
it 'returns expected users in name asc order' do
allow(group).to receive(:billed_user_members).and_return([john_doe, john_smith, sophie, maria])
expect(subject).to eq([john_doe, john_smith, maria, sophie].map(&:user))
end
context 'and when a sorting parameter is provided (eg name descending)' do
let(:order_by) { 'name_desc' }
it 'sorts results accordingly' do
expect(subject).to eq([sophie, maria, john_smith, john_doe].map(&:user))
end
end
end end
end end
end end
...@@ -399,6 +399,16 @@ RSpec.describe API::Members do ...@@ -399,6 +399,16 @@ RSpec.describe API::Members do
expect_paginated_array_response(*[owner, maintainer, nested_user, project_user, linked_group_user].map(&:id)) expect_paginated_array_response(*[owner, maintainer, nested_user, project_user, linked_group_user].map(&:id))
end end
context 'when the current user does not have the :admin_group_member ability' do
it 'is a bad request' do
not_an_owner = create(:user)
get api(url, not_an_owner), params: params
expect(response).to have_gitlab_http_status(:bad_request)
end
end
context 'with seach params provided' do context 'with seach params provided' do
let(:params) { { search: nested_user.name } } let(:params) { { search: nested_user.name } }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment