Commit 440e22f6 authored by Jackie Fraser's avatar Jackie Fraser Committed by Nicolò Maria Mezzopera

Replace invite form on Members page with modal

parent 6aa030d8
...@@ -19,6 +19,11 @@ export default { ...@@ -19,6 +19,11 @@ export default {
required: false, required: false,
default: '', default: '',
}, },
classes: {
type: String,
required: false,
default: '',
},
}, },
methods: { methods: {
openModal() { openModal() {
...@@ -29,7 +34,7 @@ export default { ...@@ -29,7 +34,7 @@ export default {
</script> </script>
<template> <template>
<gl-link @click="openModal"> <gl-link :class="classes" @click="openModal">
<div v-if="icon" class="nav-icon-container"> <div v-if="icon" class="nav-icon-container">
<gl-icon :size="16" :name="icon" /> <gl-icon :size="16" :name="icon" />
</div> </div>
......
...@@ -4,6 +4,8 @@ import UsersSelect from '~/users_select'; ...@@ -4,6 +4,8 @@ import UsersSelect from '~/users_select';
import groupsSelect from '~/groups_select'; import groupsSelect from '~/groups_select';
import RemoveMemberModal from '~/vue_shared/components/remove_member_modal.vue'; import RemoveMemberModal from '~/vue_shared/components/remove_member_modal.vue';
import { initGroupMembersApp } from '~/groups/members'; import { initGroupMembersApp } from '~/groups/members';
import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
import { memberRequestFormatter, groupLinkRequestFormatter } from '~/groups/members/utils'; import { memberRequestFormatter, groupLinkRequestFormatter } from '~/groups/members/utils';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
...@@ -64,5 +66,7 @@ groupsSelect(); ...@@ -64,5 +66,7 @@ groupsSelect();
memberExpirationDate(); memberExpirationDate();
memberExpirationDate('.js-access-expiration-date-groups'); memberExpirationDate('.js-access-expiration-date-groups');
mountRemoveMemberModal(); mountRemoveMemberModal();
initInviteMembersModal();
initInviteMembersTrigger();
new UsersSelect(); // eslint-disable-line no-new new UsersSelect(); // eslint-disable-line no-new
...@@ -4,6 +4,8 @@ import memberExpirationDate from '~/member_expiration_date'; ...@@ -4,6 +4,8 @@ import memberExpirationDate from '~/member_expiration_date';
import UsersSelect from '~/users_select'; import UsersSelect from '~/users_select';
import groupsSelect from '~/groups_select'; import groupsSelect from '~/groups_select';
import RemoveMemberModal from '~/vue_shared/components/remove_member_modal.vue'; import RemoveMemberModal from '~/vue_shared/components/remove_member_modal.vue';
import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
function mountRemoveMemberModal() { function mountRemoveMemberModal() {
const el = document.querySelector('.js-remove-member-modal'); const el = document.querySelector('.js-remove-member-modal');
...@@ -24,6 +26,8 @@ document.addEventListener('DOMContentLoaded', () => { ...@@ -24,6 +26,8 @@ document.addEventListener('DOMContentLoaded', () => {
memberExpirationDate(); memberExpirationDate();
memberExpirationDate('.js-access-expiration-date-groups'); memberExpirationDate('.js-access-expiration-date-groups');
mountRemoveMemberModal(); mountRemoveMemberModal();
initInviteMembersModal();
initInviteMembersTrigger();
new Members(); // eslint-disable-line no-new new Members(); // eslint-disable-line no-new
new UsersSelect(); // eslint-disable-line no-new new UsersSelect(); // eslint-disable-line no-new
......
...@@ -8,20 +8,28 @@ ...@@ -8,20 +8,28 @@
.js-remove-member-modal .js-remove-member-modal
.project-members-page.gl-mt-3 .project-members-page.gl-mt-3
%h4 .gl-display-flex.gl-flex-wrap
= _('Group members') - if can_manage_members
%hr .gl-w-half.gl-xs-w-full
- if can_manage_members %h4
%ul.nav-links.nav.nav-tabs.gitlab-tabs{ role: 'tablist' } = _('Group members')
%li.nav-tab{ role: 'presentation' } - if invite_members_allowed?(@group)
%a.nav-link.active{ href: '#invite-member-pane', id: 'invite-member-tab', data: { toggle: 'tab' }, role: 'tab' }= _('Invite member') .gl-w-half.gl-xs-w-full
.gl-display-flex.gl-flex-wrap.gl-lg-justify-content-end.gl-mx-n2.gl-mb-3
.js-invite-members-trigger.gl-px-2.gl-sm-w-auto.gl-w-full.gl-mb-4{ data: { classes: 'btn btn-success gl-button gl-mt-3 gl-sm-w-auto gl-w-full', display_text: _('Invite members') } }
= render_if_exists 'groups/invite_members_modal', group: @group
- if can_manage_members && !invite_members_allowed?(@group)
%hr.gl-mt-4
%ul.nav-links.nav.nav-tabs.gitlab-tabs{ role: 'tablist' }
%li.nav-tab{ role: 'presentation' } %li.nav-tab{ role: 'presentation' }
%a.nav-link{ href: '#invite-group-pane', id: 'invite-group-tab', data: { toggle: 'tab', qa_selector: 'invite_group_tab' }, role: 'tab' }= _('Invite group') %a.nav-link.active{ href: '#invite-member-pane', id: 'invite-member-tab', data: { toggle: 'tab' }, role: 'tab' }= _('Invite member')
.tab-content.gitlab-tab-content %li.nav-tab{ role: 'presentation' }
.tab-pane.active{ id: 'invite-member-pane', role: 'tabpanel' } %a.nav-link{ href: '#invite-group-pane', id: 'invite-group-tab', data: { toggle: 'tab', qa_selector: 'invite_group_tab' }, role: 'tab' }= _('Invite group')
= render_invite_member_for_group(@group, @group_member.access_level) .tab-content.gitlab-tab-content
.tab-pane{ id: 'invite-group-pane', role: 'tabpanel' } .tab-pane.active{ id: 'invite-member-pane', role: 'tabpanel' }
= render 'shared/members/invite_group', submit_url: group_group_links_path(@group), access_levels: GroupMember.access_level_roles, default_access_level: @group_member.access_level, group_link_field: 'shared_with_group_id', group_access_field: 'shared_group_access' = render_invite_member_for_group(@group, @group_member.access_level)
.tab-pane{ id: 'invite-group-pane', role: 'tabpanel' }
= render 'shared/members/invite_group', submit_url: group_group_links_path(@group), access_levels: GroupMember.access_level_roles, default_access_level: @group_member.access_level, group_link_field: 'shared_with_group_id', group_access_field: 'shared_group_access'
= render_if_exists 'groups/group_members/ldap_sync' = render_if_exists 'groups/group_members/ldap_sync'
......
...@@ -4,16 +4,34 @@ ...@@ -4,16 +4,34 @@
.js-remove-member-modal .js-remove-member-modal
.row.gl-mt-3 .row.gl-mt-3
.col-lg-12 .col-lg-12
- if project_can_be_shared? - if invite_members_allowed?(group)
%h4 .row
= _("Project members") .col-md-12.col-lg-6.gl-display-flex
- if can_manage_project_members?(@project) .gl-flex-direction-column.gl-flex-wrap.align-items-baseline
%p= share_project_description(@project) %h4
- else = _("Project members")
%p .gl-justify-content-bottom.gl-display-flex.align-items-center
= html_escape(_("Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}")) % { i_open: '<i>'.html_safe, i_close: '</i>'.html_safe } - if can_manage_project_members?(@project)
%p= share_project_description(@project)
- else
%p
= html_escape(_("Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}")) % { i_open: '<i>'.html_safe, i_close: '</i>'.html_safe }
.col-md-12.col-lg-6
.gl-display-flex.gl-flex-wrap.gl-lg-justify-content-end.gl-mx-n2.gl-mb-3
.js-invite-members-trigger.gl-px-2.gl-sm-w-auto.gl-w-full.gl-mb-4{ data: { classes: 'btn btn-success gl-button gl-mt-3 gl-sm-w-auto gl-w-full', display_text: _('Invite members') } }
= render_if_exists 'projects/invite_members_modal', project: @project
- if can_manage_project_members?(@project) && project_can_be_shared? - else
- if project_can_be_shared?
%h4
= _("Project members")
- if can_manage_project_members?(@project)
%p= share_project_description(@project)
- else
%p
= html_escape(_("Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}")) % { i_open: '<i>'.html_safe, i_close: '</i>'.html_safe }
- if !invite_members_allowed?(group) && can_manage_project_members?(@project) && project_can_be_shared?
- if !membership_locked? && @project.allowed_to_share_with_group? - if !membership_locked? && @project.allowed_to_share_with_group?
%ul.nav-links.nav.nav-tabs.gitlab-tabs{ role: 'tablist' } %ul.nav-links.nav.nav-tabs.gitlab-tabs{ role: 'tablist' }
%li.nav-tab{ role: 'presentation' } %li.nav-tab{ role: 'presentation' }
......
...@@ -51,6 +51,7 @@ RSpec.describe 'Groups > Members > List members' do ...@@ -51,6 +51,7 @@ RSpec.describe 'Groups > Members > List members' do
before do before do
stub_licensed_features(group_saml: true) stub_licensed_features(group_saml: true)
stub_feature_flags(invite_members_group_modal: false)
allow(Gitlab::Session).to receive(:current).and_return(session) allow(Gitlab::Session).to receive(:current).and_return(session)
create(:identity, saml_provider: saml_provider, user: user1) create(:identity, saml_provider: saml_provider, user: user1)
......
...@@ -8,6 +8,7 @@ RSpec.describe "User manages members" do ...@@ -8,6 +8,7 @@ RSpec.describe "User manages members" do
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
before do before do
stub_feature_flags(invite_members_group_modal: false)
sign_in(user) sign_in(user)
end end
......
...@@ -15458,6 +15458,9 @@ msgstr "" ...@@ -15458,6 +15458,9 @@ msgstr ""
msgid "Invite member" msgid "Invite member"
msgstr "" msgstr ""
msgid "Invite members"
msgstr ""
msgid "Invite team members" msgid "Invite team members"
msgstr "" msgstr ""
......
...@@ -175,6 +175,7 @@ RSpec.describe 'Admin Groups' do ...@@ -175,6 +175,7 @@ RSpec.describe 'Admin Groups' do
describe 'add admin himself to a group' do describe 'add admin himself to a group' do
before do before do
stub_feature_flags(invite_members_group_modal: false)
group.add_user(:user, Gitlab::Access::OWNER) group.add_user(:user, Gitlab::Access::OWNER)
end end
......
...@@ -17,6 +17,7 @@ RSpec.describe 'Groups > Members > Manage groups', :js do ...@@ -17,6 +17,7 @@ RSpec.describe 'Groups > Members > Manage groups', :js do
let_it_be(:group_to_add) { create(:group) } let_it_be(:group_to_add) { create(:group) }
before do before do
stub_feature_flags(invite_members_group_modal: false)
group.add_owner(user) group.add_owner(user)
visit group_group_members_path(group) visit group_group_members_path(group)
end end
......
...@@ -11,9 +11,37 @@ RSpec.describe 'Groups > Members > Manage members' do ...@@ -11,9 +11,37 @@ RSpec.describe 'Groups > Members > Manage members' do
let(:group) { create(:group) } let(:group) { create(:group) }
before do before do
stub_feature_flags(invite_members_group_modal: false)
sign_in(user1) sign_in(user1)
end end
shared_examples 'includes the correct Invite Members link' do |should_include, should_not_include|
it 'includes either the form or the modal trigger' do
group.add_owner(user1)
visit group_group_members_path(group)
expect(page).to have_selector(should_include)
expect(page).not_to have_selector(should_not_include)
end
end
context 'when Invite Members modal is enabled' do
before do
stub_feature_flags(invite_members_group_modal: true)
end
it_behaves_like 'includes the correct Invite Members link', '.js-invite-members-trigger', '.invite-users-form'
end
context 'when Invite Members modal is disabled' do
before do
stub_feature_flags(invite_members_group_modal: false)
end
it_behaves_like 'includes the correct Invite Members link', '.invite-users-form', '.js-invite-members-trigger'
end
it 'update user to owner level', :js do it 'update user to owner level', :js do
group.add_owner(user1) group.add_owner(user1)
group.add_developer(user2) group.add_developer(user2)
......
...@@ -11,6 +11,7 @@ RSpec.describe 'Groups > Members > Owner adds member with expiration date', :js ...@@ -11,6 +11,7 @@ RSpec.describe 'Groups > Members > Owner adds member with expiration date', :js
let(:new_member) { create(:user, name: 'Mary Jane') } let(:new_member) { create(:user, name: 'Mary Jane') }
before do before do
stub_feature_flags(invite_members_group_modal: false)
group.add_owner(user1) group.add_owner(user1)
sign_in(user1) sign_in(user1)
end end
......
...@@ -111,6 +111,7 @@ RSpec.describe 'Projects members', :js do ...@@ -111,6 +111,7 @@ RSpec.describe 'Projects members', :js do
context 'with a group requester' do context 'with a group requester' do
before do before do
stub_feature_flags(invite_members_group_modal: false)
group.request_access(group_requester) group.request_access(group_requester)
visit project_project_members_path(project) visit project_project_members_path(project)
end end
......
...@@ -12,6 +12,7 @@ RSpec.describe 'Project members list' do ...@@ -12,6 +12,7 @@ RSpec.describe 'Project members list' do
let(:project) { create(:project, namespace: group) } let(:project) { create(:project, namespace: group) }
before do before do
stub_feature_flags(invite_members_group_modal: false)
sign_in(user1) sign_in(user1)
group.add_owner(user1) group.add_owner(user1)
end end
......
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