summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStan Hu <stanhu@gmail.com>2019-05-18 08:06:20 -0700
committerGeorge Tsiolis <tsiolis.g@gmail.com>2019-08-05 11:21:41 +0300
commitcaac3104c4e77a40ad8ec3d1275f7b47c0fc8f68 (patch)
tree2c0fec3d934326d1b28401289dfd330e13c6b7b5
parent523e00abd74a9067fb17129faa1d35bfa107e04a (diff)
downloadgitlab-ce-caac3104c4e77a40ad8ec3d1275f7b47c0fc8f68.tar.gz
Make it easier to find invited group members
We had a number of team members struggle to find invited members of a group. Searching for the e-mail address did not work because search only works with members with user accounts. This commit changes two things: 1. Breaks out the invited members into a separate table. 2. Adds search capability for the invited members. Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/61948
-rw-r--r--app/controllers/groups/group_members_controller.rb13
-rw-r--r--app/models/member.rb4
-rw-r--r--app/views/groups/group_members/index.html.haml23
-rw-r--r--changelogs/unreleased/sh-break-out-invited-group-members.yml5
-rw-r--r--spec/controllers/groups/group_members_controller_spec.rb33
-rw-r--r--spec/factories/group_members.rb4
-rw-r--r--spec/features/groups/members/manage_members_spec.rb2
-rw-r--r--spec/models/member_spec.rb11
8 files changed, 90 insertions, 5 deletions
diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb
index f1d6fb00cfc..fc5cb3f0b5c 100644
--- a/app/controllers/groups/group_members_controller.rb
+++ b/app/controllers/groups/group_members_controller.rb
@@ -5,6 +5,8 @@ class Groups::GroupMembersController < Groups::ApplicationController
include MembersPresentation
include SortingHelper
+ MEMBER_PER_PAGE_LIMIT = 50
+
def self.admin_not_required_endpoints
%i[index leave request_access]
end
@@ -24,7 +26,14 @@ class Groups::GroupMembersController < Groups::ApplicationController
@project = @group.projects.find(params[:project_id]) if params[:project_id]
@members = GroupMembersFinder.new(@group).execute
- @members = @members.non_invite unless can_manage_members
+
+ if can_manage_members
+ @invited_members = @members.invite
+ @invited_members = @invited_members.search_invited(params[:search_invited]) if params[:search_invited].present?
+ @invited_members = present_members(@invited_members.page(params[:invited_members_page]).per(MEMBER_PER_PAGE_LIMIT))
+ end
+
+ @members = @members.non_invite
@members = @members.search(params[:search]) if params[:search].present?
@members = @members.sort_by_attribute(@sort)
@@ -32,7 +41,7 @@ class Groups::GroupMembersController < Groups::ApplicationController
@members = @members.filter_by_2fa(params[:two_factor])
end
- @members = @members.page(params[:page]).per(50)
+ @members = @members.page(params[:page]).per(MEMBER_PER_PAGE_LIMIT)
@members = present_members(@members)
@requesters = present_members(
diff --git a/app/models/member.rb b/app/models/member.rb
index c7583434148..ada779f0583 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -107,6 +107,10 @@ class Member < ApplicationRecord
joins(:user).merge(User.search(query))
end
+ def search_invited(query)
+ invite.where(['invite_email ILIKE ?', "%#{query}%"])
+ end
+
def filter_by_2fa(value)
case value
when 'enabled'
diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml
index 021c0b6c429..ddbf89a5fb7 100644
--- a/app/views/groups/group_members/index.html.haml
+++ b/app/views/groups/group_members/index.html.haml
@@ -36,4 +36,25 @@
= render 'shared/members/sort_dropdown'
%ul.content-list.members-list
= render partial: 'shared/members/member', collection: @members, as: :member
- = paginate @members, theme: 'gitlab'
+ = paginate @members, theme: 'gitlab'
+
+ - if can_manage_members && @invited_members.exists?
+ .clearfix
+ %h5.member.existing-title
+ Invited members
+ .card
+ .card-header.flex-project-members-panel
+ %span.flex-project-title
+ Pending members to
+ %strong= @group.name
+ %span.badge.badge-pill= @invited_members.total_count
+ = form_tag group_group_members_path(@group), method: :get, class: 'form-inline member-search-form flex-project-members-form' do
+ .form-group
+ .position-relative.append-right-8
+ = search_field_tag :search_invited, params[:search_invited], { placeholder: 'Find invited members by e-mail', class: 'form-control', spellcheck: false }
+ %button.member-search-btn{ type: "submit", "aria-label" => "Submit search" }
+ = icon("search")
+ = render 'shared/members/sort_dropdown'
+ %ul.content-list.invited-members-list
+ = render partial: 'shared/members/member', collection: @invited_members, as: :member
+ = paginate @invited_members, param_name: 'invited_members_page', theme: 'gitlab'
diff --git a/changelogs/unreleased/sh-break-out-invited-group-members.yml b/changelogs/unreleased/sh-break-out-invited-group-members.yml
new file mode 100644
index 00000000000..091f1d48843
--- /dev/null
+++ b/changelogs/unreleased/sh-break-out-invited-group-members.yml
@@ -0,0 +1,5 @@
+---
+title: Make it easier to find invited group members
+merge_request: 28436
+author:
+type: fixed
diff --git a/spec/controllers/groups/group_members_controller_spec.rb b/spec/controllers/groups/group_members_controller_spec.rb
index 413598ddde0..908c564e761 100644
--- a/spec/controllers/groups/group_members_controller_spec.rb
+++ b/spec/controllers/groups/group_members_controller_spec.rb
@@ -16,6 +16,39 @@ describe Groups::GroupMembersController do
expect(response).to have_gitlab_http_status(200)
expect(response).to render_template(:index)
end
+
+ context 'user with owner access' do
+ let!(:invited) { create_list(:group_member, 3, :invited, group: group) }
+
+ before do
+ group.add_owner(user)
+ sign_in(user)
+ end
+
+ it 'assigns invited members' do
+ get :index, params: { group_id: group }
+
+ expect(assigns(:invited_members).map(&:invite_email)).to match_array(invited.map(&:invite_email))
+ end
+
+ it 'restricts search to one email' do
+ get :index, params: { group_id: group, search_invited: invited.first.invite_email }
+
+ expect(assigns(:invited_members).map(&:invite_email)).to match_array(invited.first.invite_email)
+ end
+
+ it 'paginates invited list' do
+ stub_const('Groups::GroupMembersController::MEMBER_PER_PAGE_LIMIT', 2)
+
+ get :index, params: { group_id: group, invited_members_page: 1 }
+
+ expect(assigns(:invited_members).count).to eq(2)
+
+ get :index, params: { group_id: group, invited_members_page: 2 }
+
+ expect(assigns(:invited_members).count).to eq(1)
+ end
+ end
end
describe 'POST create' do
diff --git a/spec/factories/group_members.rb b/spec/factories/group_members.rb
index 3bf9cdef253..8dab6c71b06 100644
--- a/spec/factories/group_members.rb
+++ b/spec/factories/group_members.rb
@@ -16,7 +16,9 @@ FactoryBot.define do
trait(:invited) do
user_id nil
invite_token 'xxx'
- invite_email 'email@email.com'
+ sequence :invite_email do |n|
+ "email#{n}@email.com"
+ end
end
end
end
diff --git a/spec/features/groups/members/manage_members_spec.rb b/spec/features/groups/members/manage_members_spec.rb
index 779fa74501a..48603058dac 100644
--- a/spec/features/groups/members/manage_members_spec.rb
+++ b/spec/features/groups/members/manage_members_spec.rb
@@ -98,7 +98,7 @@ describe 'Groups > Members > Manage members' do
add_user('test@example.com', 'Reporter')
- page.within(second_row) do
+ page.within('.content-list.invited-members-list') do
expect(page).to have_content('test@example.com')
expect(page).to have_content('Invited')
expect(page).to have_button('Reporter')
diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb
index 782a84f922b..99b268b07e8 100644
--- a/spec/models/member_spec.rb
+++ b/spec/models/member_spec.rb
@@ -172,6 +172,17 @@ describe Member do
it { expect(described_class.non_request).to include @accepted_request_member }
end
+ describe '.search_invited' do
+ it 'returns only the matching e-mail' do
+ create(:group_member, :invited)
+
+ invited = described_class.search_invited(@invited_member.invite_email)
+
+ expect(invited.count).to eq(1)
+ expect(invited.first).to eq(@invited_member)
+ end
+ end
+
describe '.developers' do
subject { described_class.developers.to_a }