Commit 8bb137a9 authored by Jacques Erasmus's avatar Jacques Erasmus

Merge branch 'add-project-to-invite-members-modal' into 'master'

Add project support to Invite Members modal

See merge request gitlab-org/gitlab!44785
parents 4a6bbc73 a2f5507f
...@@ -22,6 +22,7 @@ const Api = { ...@@ -22,6 +22,7 @@ const Api = {
projectLabelsPath: '/:namespace_path/:project_path/-/labels', projectLabelsPath: '/:namespace_path/:project_path/-/labels',
projectFileSchemaPath: '/:namespace_path/:project_path/-/schema/:ref/:filename', projectFileSchemaPath: '/:namespace_path/:project_path/-/schema/:ref/:filename',
projectUsersPath: '/api/:version/projects/:id/users', projectUsersPath: '/api/:version/projects/:id/users',
projectMembersPath: '/api/:version/projects/:id/members',
projectMergeRequestsPath: '/api/:version/projects/:id/merge_requests', projectMergeRequestsPath: '/api/:version/projects/:id/merge_requests',
projectMergeRequestPath: '/api/:version/projects/:id/merge_requests/:mrid', projectMergeRequestPath: '/api/:version/projects/:id/merge_requests/:mrid',
projectMergeRequestChangesPath: '/api/:version/projects/:id/merge_requests/:mrid/changes', projectMergeRequestChangesPath: '/api/:version/projects/:id/merge_requests/:mrid/changes',
...@@ -214,6 +215,12 @@ const Api = { ...@@ -214,6 +215,12 @@ const Api = {
.then(({ data }) => data); .then(({ data }) => data);
}, },
inviteProjectMembers(id, data) {
const url = Api.buildUrl(this.projectMembersPath).replace(':id', encodeURIComponent(id));
return axios.post(url, data);
},
// Return single project // Return single project
project(projectPath) { project(projectPath) {
const url = Api.buildUrl(Api.projectPath).replace(':id', encodeURIComponent(projectPath)); const url = Api.buildUrl(Api.projectPath).replace(':id', encodeURIComponent(projectPath));
......
...@@ -10,7 +10,7 @@ import { ...@@ -10,7 +10,7 @@ import {
GlFormInput, GlFormInput,
} from '@gitlab/ui'; } from '@gitlab/ui';
import eventHub from '../event_hub'; import eventHub from '../event_hub';
import { s__, sprintf } from '~/locale'; import { s__, __, sprintf } from '~/locale';
import Api from '~/api'; import Api from '~/api';
import MembersTokenSelect from '~/invite_members/components/members_token_select.vue'; import MembersTokenSelect from '~/invite_members/components/members_token_select.vue';
...@@ -28,11 +28,15 @@ export default { ...@@ -28,11 +28,15 @@ export default {
MembersTokenSelect, MembersTokenSelect,
}, },
props: { props: {
groupId: { id: {
type: String, type: String,
required: true, required: true,
}, },
groupName: { isProject: {
type: Boolean,
required: true,
},
name: {
type: String, type: String,
required: true, required: true,
}, },
...@@ -59,9 +63,16 @@ export default { ...@@ -59,9 +63,16 @@ export default {
}; };
}, },
computed: { computed: {
inviteToName() {
return this.name.toUpperCase();
},
inviteToType() {
return this.isProject ? __('project') : __('group');
},
introText() { introText() {
return sprintf(s__("InviteMembersModal|You're inviting members to the %{group_name} group"), { return sprintf(s__("InviteMembersModal|You're inviting members to the %{name} %{type}"), {
group_name: this.groupName, name: this.inviteToName,
type: this.inviteToType,
}); });
}, },
toastOptions() { toastOptions() {
...@@ -110,13 +121,14 @@ export default { ...@@ -110,13 +121,14 @@ export default {
this.selectedAccessLevel = item; this.selectedAccessLevel = item;
}, },
submitForm(formData) { submitForm(formData) {
return Api.inviteGroupMember(this.groupId, formData) if (this.isProject) {
.then(() => { return Api.inviteProjectMembers(this.id, formData)
this.showToastMessageSuccess(); .then(this.showToastMessageSuccess)
}) .catch(this.showToastMessageError);
.catch(error => { }
this.showToastMessageError(error); return Api.inviteGroupMember(this.id, formData)
}); .then(this.showToastMessageSuccess)
.catch(this.showToastMessageError);
}, },
showToastMessageSuccess() { showToastMessageSuccess() {
this.$toast.show(this.$options.labels.toastMessageSuccessful, this.toastOptions); this.$toast.show(this.$options.labels.toastMessageSuccessful, this.toastOptions);
......
...@@ -18,7 +18,6 @@ export default function initInviteMembersModal() { ...@@ -18,7 +18,6 @@ export default function initInviteMembersModal() {
props: { props: {
...el.dataset, ...el.dataset,
accessLevels: JSON.parse(el.dataset.accessLevels), accessLevels: JSON.parse(el.dataset.accessLevels),
groupName: el.dataset.groupName.toUpperCase(),
}, },
}), }),
}); });
......
...@@ -10,6 +10,8 @@ import leaveByUrl from '~/namespaces/leave_by_url'; ...@@ -10,6 +10,8 @@ import leaveByUrl from '~/namespaces/leave_by_url';
import Star from '../../../star'; import Star from '../../../star';
import notificationsDropdown from '../../../notifications_dropdown'; import notificationsDropdown from '../../../notifications_dropdown';
import { showLearnGitLabProjectPopover } from '~/onboarding_issues'; import { showLearnGitLabProjectPopover } from '~/onboarding_issues';
import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
initReadMore(); initReadMore();
new Star(); // eslint-disable-line no-new new Star(); // eslint-disable-line no-new
...@@ -42,3 +44,6 @@ showLearnGitLabProjectPopover(); ...@@ -42,3 +44,6 @@ showLearnGitLabProjectPopover();
notificationsDropdown(); notificationsDropdown();
new ShortcutsNavigation(); // eslint-disable-line no-new new ShortcutsNavigation(); // eslint-disable-line no-new
initInviteMembersTrigger();
initInviteMembersModal();
- if invite_members_allowed?(group) - if invite_members_allowed?(group)
.js-invite-members-modal{ data: { group_id: group.id, .js-invite-members-modal{ data: { id: group.id,
group_name: group.name, name: group.name,
is_project: false,
access_levels: GroupMember.access_level_roles.to_json, access_levels: GroupMember.access_level_roles.to_json,
default_access_level: Gitlab::Access::GUEST, default_access_level: Gitlab::Access::GUEST,
help_link: help_page_url('user/permissions') } } help_link: help_page_url('user/permissions') } }
- if invite_members_allowed?(group) && body_data_page == 'groups:show' - if invite_members_allowed?(group) && body_data_page == 'groups:show'
%li %li
.js-invite-members-trigger{ data: { icon: 'plus', display_text: 'Invite team members' } } .js-invite-members-trigger{ data: { icon: 'plus', display_text: _('Invite team members') } }
...@@ -380,6 +380,8 @@ ...@@ -380,6 +380,8 @@
%strong.fly-out-top-item-name %strong.fly-out-top-item-name
= _('Members') = _('Members')
= render_if_exists 'projects/invite_members_side_nav_link', project: @project
- if project_nav_tab? :settings - if project_nav_tab? :settings
= nav_link(path: sidebar_settings_paths) do = nav_link(path: sidebar_settings_paths) do
= link_to edit_project_path(@project) do = link_to edit_project_path(@project) do
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
- max_project_topic_length = 15 - max_project_topic_length = 15
- emails_disabled = @project.emails_disabled? - emails_disabled = @project.emails_disabled?
= render_if_exists 'projects/invite_members_modal', project: @project
.project-home-panel.js-show-on-project-root.gl-my-5{ class: [("empty-project" if empty_repo)] } .project-home-panel.js-show-on-project-root.gl-my-5{ class: [("empty-project" if empty_repo)] }
.row.gl-mb-3 .row.gl-mb-3
.home-panel-title-row.col-md-12.col-lg-6.d-flex .home-panel-title-row.col-md-12.col-lg-6.d-flex
......
- if invite_members_allowed?(project.group)
.js-invite-members-modal{ data: { id: project.id,
name: project.name,
is_project: true,
access_levels: GroupMember.access_level_roles.to_json,
default_access_level: Gitlab::Access::GUEST,
help_link: help_page_url('user/permissions') } }
- if invite_members_allowed?(project.group) && body_data_page == 'projects:show'
%li
.js-invite-members-trigger{ data: { icon: 'plus', display_text: _('Invite team members') } }
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
#{ _('This means you can not push code until you create an empty repository or import existing one.') } #{ _('This means you can not push code until you create an empty repository or import existing one.') }
%hr %hr
= render_if_exists 'projects/invite_members_modal', project: @project
.no-repo-actions .no-repo-actions
= link_to project_repository_path(@project), method: :post, class: 'btn btn-primary' do = link_to project_repository_path(@project), method: :post, class: 'btn btn-primary' do
#{ _('Create empty repository') } #{ _('Create empty repository') }
......
...@@ -14813,6 +14813,9 @@ msgstr "" ...@@ -14813,6 +14813,9 @@ msgstr ""
msgid "Invite member" msgid "Invite member"
msgstr "" msgstr ""
msgid "Invite team members"
msgstr ""
msgid "Invite teammates (optional)" msgid "Invite teammates (optional)"
msgstr "" msgstr ""
...@@ -14879,7 +14882,7 @@ msgstr "" ...@@ -14879,7 +14882,7 @@ msgstr ""
msgid "InviteMembersModal|Some of the members could not be added" msgid "InviteMembersModal|Some of the members could not be added"
msgstr "" msgstr ""
msgid "InviteMembersModal|You're inviting members to the %{group_name} group" msgid "InviteMembersModal|You're inviting members to the %{name} %{type}"
msgstr "" msgstr ""
msgid "InviteMembers|Invite team members" msgid "InviteMembers|Invite team members"
......
...@@ -67,4 +67,23 @@ RSpec.describe 'Project navbar' do ...@@ -67,4 +67,23 @@ RSpec.describe 'Project navbar' do
it_behaves_like 'verified navigation bar' it_behaves_like 'verified navigation bar'
end end
context 'when invite team members is not available' do
it 'does not display the js-invite-members-trigger' do
visit project_path(project)
expect(page).not_to have_selector('.js-invite-members-trigger')
end
end
context 'when invite team members is available' do
it 'includes the div for js-invite-members-trigger' do
stub_feature_flags(invite_members_group_modal: true)
allow_any_instance_of(InviteMembersHelper).to receive(:invite_members_allowed?).and_return(true)
visit project_path(project)
expect(page).to have_selector('.js-invite-members-trigger')
end
end
end end
...@@ -3,8 +3,9 @@ import { GlDropdown, GlDropdownItem, GlDatepicker, GlSprintf, GlLink } from '@gi ...@@ -3,8 +3,9 @@ import { GlDropdown, GlDropdownItem, GlDatepicker, GlSprintf, GlLink } from '@gi
import Api from '~/api'; import Api from '~/api';
import InviteMembersModal from '~/invite_members/components/invite_members_modal.vue'; import InviteMembersModal from '~/invite_members/components/invite_members_modal.vue';
const groupId = '1'; const id = '1';
const groupName = 'testgroup'; const name = 'testgroup';
const isProject = false;
const accessLevels = { Guest: 10, Reporter: 20, Developer: 30, Maintainer: 40, Owner: 50 }; const accessLevels = { Guest: 10, Reporter: 20, Developer: 30, Maintainer: 40, Owner: 50 };
const defaultAccessLevel = '10'; const defaultAccessLevel = '10';
const helpLink = 'https://example.com'; const helpLink = 'https://example.com';
...@@ -12,8 +13,9 @@ const helpLink = 'https://example.com'; ...@@ -12,8 +13,9 @@ const helpLink = 'https://example.com';
const createComponent = (data = {}) => { const createComponent = (data = {}) => {
return shallowMount(InviteMembersModal, { return shallowMount(InviteMembersModal, {
propsData: { propsData: {
groupId, id,
groupName, name,
isProject,
accessLevels, accessLevels,
defaultAccessLevel, defaultAccessLevel,
helpLink, helpLink,
...@@ -113,7 +115,7 @@ describe('InviteMembersModal', () => { ...@@ -113,7 +115,7 @@ describe('InviteMembersModal', () => {
}); });
it('calls Api inviteGroupMember with the correct params', () => { it('calls Api inviteGroupMember with the correct params', () => {
expect(Api.inviteGroupMember).toHaveBeenCalledWith(groupId, postData); expect(Api.inviteGroupMember).toHaveBeenCalledWith(id, postData);
}); });
}); });
......
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