Commit caedf9de authored by Gabriel Mazetto's avatar Gabriel Mazetto

Merge branch '219241-add-a-form-for-inviting-teammates-to-the-create-group-page' into 'master'

Add inviting teammates to Create group page

See merge request gitlab-org/gitlab!48794
parents d3aefd0b b97b354c
...@@ -293,12 +293,6 @@ table.pipeline-project-metrics tr td { ...@@ -293,12 +293,6 @@ table.pipeline-project-metrics tr td {
padding: $gl-padding; padding: $gl-padding;
} }
.mattermost-icon svg {
width: 16px;
height: 16px;
vertical-align: text-bottom;
}
.mattermost-team-name { .mattermost-team-name {
color: $gl-text-color-secondary; color: $gl-text-color-secondary;
} }
......
...@@ -69,7 +69,7 @@ class GroupsController < Groups::ApplicationController ...@@ -69,7 +69,7 @@ class GroupsController < Groups::ApplicationController
@group = Groups::CreateService.new(current_user, group_params).execute @group = Groups::CreateService.new(current_user, group_params).execute
if @group.persisted? if @group.persisted?
track_experiment_event(:onboarding_issues, 'created_namespace') successful_creation_hooks
notice = if @group.chat_team.present? notice = if @group.chat_team.present?
"Group '#{@group.name}' and its Mattermost team were successfully created." "Group '#{@group.name}' and its Mattermost team were successfully created."
...@@ -319,6 +319,10 @@ class GroupsController < Groups::ApplicationController ...@@ -319,6 +319,10 @@ class GroupsController < Groups::ApplicationController
private private
def successful_creation_hooks
track_experiment_event(:onboarding_issues, 'created_namespace')
end
def groups def groups
if @group.supports_events? if @group.supports_events?
@group.self_and_descendants.public_or_visible_to_user(current_user) @group.self_and_descendants.public_or_visible_to_user(current_user)
......
.form-group .form-group
.col-sm-2.col-form-label .col-sm-2.col-form-label
= f.label :create_chat_team do = f.label :create_chat_team do
%span.mattermost-icon %span.gl-display-flex
= custom_icon('icon_mattermost') = custom_icon('icon_mattermost')
Mattermost %span.gl-ml-2 Mattermost
.col-sm-10 .col-sm-12
.form-check.js-toggle-container .form-check.js-toggle-container
.js-toggle-button.form-check-input= f.check_box(:create_chat_team, { checked: false }, true, false) .js-toggle-button.form-check-input= f.check_box(:create_chat_team, { checked: false }, true, false)
= f.label :create_chat_team, class: 'form-check-label' do = f.label :create_chat_team, class: 'form-check-label' do
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
= render 'shared/group_form', f: f, autofocus: true = render 'shared/group_form', f: f, autofocus: true
.row .row
.form-group.col-sm-12 .form-group.col-sm-12.gl-mb-0
%label.label-bold %label.label-bold
= _('Visibility level') = _('Visibility level')
%p %p
...@@ -10,8 +10,13 @@ ...@@ -10,8 +10,13 @@
= link_to _('View the documentation'), help_page_path("public_access/public_access"), target: '_blank' = link_to _('View the documentation'), help_page_path("public_access/public_access"), target: '_blank'
= render 'shared/visibility_level', f: f, visibility_level: default_group_visibility, can_change_visibility_level: true, form_model: @group, with_label: false = render 'shared/visibility_level', f: f, visibility_level: default_group_visibility, can_change_visibility_level: true, form_model: @group, with_label: false
= render 'create_chat_team', f: f if Gitlab.config.mattermost.enabled - if Gitlab.config.mattermost.enabled
.row
= render 'create_chat_team', f: f
.row
.col-sm-4
= render_if_exists 'shared/groups/invite_members'
.row
.form-actions.col-sm-12 .form-actions.col-sm-12
= f.submit _('Create group'), class: "btn btn-success" = f.submit _('Create group'), class: "btn btn-success"
= link_to _('Cancel'), dashboard_groups_path, class: 'btn btn-cancel' = link_to _('Cancel'), dashboard_groups_path, class: 'btn btn-cancel'
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500"><path d="M250.05 34c1.9.04 3.8.11 5.6.2l-29.79 35.51c-.07.01-.15.03-.23.04C149.26 84.1 98.22 146.5 98.22 222.97c0 41.56 23.07 90.5 59.75 119.1 28.61 22.32 64.29 36.9 101.21 36.9 93.4 0 160.15-68.61 160.15-156 0-34.91-15.99-72.77-41.76-100.76l-1.63-47.39c54.45 39.15 89.95 103.02 90.06 175.17v.01c0 119.29-96.7 216-216 216-119.29 0-216-96.71-216-216S130.71 34 250 34h.05zm64.1 20.29c.66-.04 1.32.03 1.96.25 3.01 1 3.85 3.57 3.93 6.45l3.84 146.88c.76 28.66-17.16 68.44-60.39 68.56-30.97.08-63.68-20.83-63.68-60.13.01-14.73 5.61-31.26 19.25-48.11l90.03-111.18c1.15-1.42 3.08-2.58 5.06-2.72z"/></svg> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 500 500"><path d="M250.05 34c1.9.04 3.8.11 5.6.2l-29.79 35.51c-.07.01-.15.03-.23.04C149.26 84.1 98.22 146.5 98.22 222.97c0 41.56 23.07 90.5 59.75 119.1 28.61 22.32 64.29 36.9 101.21 36.9 93.4 0 160.15-68.61 160.15-156 0-34.91-15.99-72.77-41.76-100.76l-1.63-47.39c54.45 39.15 89.95 103.02 90.06 175.17v.01c0 119.29-96.7 216-216 216-119.29 0-216-96.71-216-216S130.71 34 250 34h.05zm64.1 20.29c.66-.04 1.32.03 1.96.25 3.01 1 3.85 3.57 3.93 6.45l3.84 146.88c.76 28.66-17.16 68.44-60.39 68.56-30.97.08-63.68-20.83-63.68-60.13.01-14.73 5.61-31.26 19.25-48.11l90.03-111.18c1.15-1.42 3.08-2.58 5.06-2.72z"/></svg>
import '~/pages/groups/new/index';
import mountInviteMembers from 'ee/groups/invite';
mountInviteMembers();
...@@ -5,11 +5,13 @@ module GroupInviteMembers ...@@ -5,11 +5,13 @@ module GroupInviteMembers
def invite_members(group) def invite_members(group)
invite_params = { invite_params = {
user_ids: emails_param[:emails].reject(&:blank?).join(','), user_ids: emails_param[:emails]&.reject(&:blank?)&.join(','),
access_level: Gitlab::Access::DEVELOPER access_level: Gitlab::Access::DEVELOPER
} }
Members::CreateService.new(current_user, invite_params).execute(group) result = Members::CreateService.new(current_user, invite_params).execute(group)
track_event('invite_members', { label: 'new_group_form' }) if result[:status] == :success
end end
def emails_param def emails_param
......
...@@ -5,6 +5,7 @@ module EE ...@@ -5,6 +5,7 @@ module EE
extend ActiveSupport::Concern extend ActiveSupport::Concern
extend ::Gitlab::Utils::Override extend ::Gitlab::Utils::Override
include PreventForkingHelper include PreventForkingHelper
include GroupInviteMembers
prepended do prepended do
alias_method :ee_authorize_admin_group!, :authorize_admin_group! alias_method :ee_authorize_admin_group!, :authorize_admin_group!
...@@ -96,5 +97,12 @@ module EE ...@@ -96,5 +97,12 @@ module EE
def default_group_view def default_group_view
EE::User::DEFAULT_GROUP_VIEW EE::User::DEFAULT_GROUP_VIEW
end end
override :successful_creation_hooks
def successful_creation_hooks
super
invite_members(group)
end
end end
end end
---
title: Add a form for inviting teammates to the Create group page
merge_request: 48794
author:
type: added
...@@ -89,7 +89,7 @@ RSpec.describe GroupsController do ...@@ -89,7 +89,7 @@ RSpec.describe GroupsController do
end end
describe 'POST #restore' do describe 'POST #restore' do
let(:group) do let_it_be(:group) do
create(:group_with_deletion_schedule, create(:group_with_deletion_schedule,
marked_for_deletion_on: 1.day.ago, marked_for_deletion_on: 1.day.ago,
deleting_user: user) deleting_user: user)
...@@ -256,27 +256,33 @@ RSpec.describe GroupsController do ...@@ -256,27 +256,33 @@ RSpec.describe GroupsController do
end end
describe 'POST #create' do describe 'POST #create' do
let(:group_params) { { name: 'new_group', path: 'new_group' } }
subject { post :create, params: { group: group_params } }
context 'authorization' do context 'authorization' do
it 'allows an auditor with "can_create_group" set to true to create a group' do it 'allows an auditor with "can_create_group" set to true to create a group' do
sign_in(create(:user, :auditor, can_create_group: true)) sign_in(create(:user, :auditor, can_create_group: true))
expect do expect { subject }.to change { Group.count }.by(1)
post :create, params: { group: { name: 'new_group', path: "new_group" } }
end.to change { Group.count }.by(1)
expect(response).to have_gitlab_http_status(:found) expect(response).to have_gitlab_http_status(:found)
end end
end end
it_behaves_like GroupInviteMembers do
before do
sign_in(user)
end
end
context 'when creating a group with `default_branch_protection` attribute' do context 'when creating a group with `default_branch_protection` attribute' do
using RSpec::Parameterized::TableSyntax using RSpec::Parameterized::TableSyntax
let(:params) do subject do
{ group: { name: 'new_group', path: 'new_group', default_branch_protection: Gitlab::Access::PROTECTION_NONE } } post :create, params: { group: group_params.merge(default_branch_protection: Gitlab::Access::PROTECTION_NONE) }
end end
subject { post :create, params: params }
shared_examples_for 'creates the group with the expected `default_branch_protection` value' do shared_examples_for 'creates the group with the expected `default_branch_protection` value' do
it 'creates the group with the expected `default_branch_protection` value' do it 'creates the group with the expected `default_branch_protection` value' do
subject subject
...@@ -331,7 +337,7 @@ RSpec.describe GroupsController do ...@@ -331,7 +337,7 @@ RSpec.describe GroupsController do
end end
describe 'PUT #update' do describe 'PUT #update' do
let(:group) { create(:group) } let_it_be(:group, refind: true) { create(:group) }
context 'when max_pages_size param is specified' do context 'when max_pages_size param is specified' do
let(:params) { { max_pages_size: 100 } } let(:params) { { max_pages_size: 100 } }
...@@ -340,8 +346,6 @@ RSpec.describe GroupsController do ...@@ -340,8 +346,6 @@ RSpec.describe GroupsController do
post :update, params: { id: group.to_param, group: params } post :update, params: { id: group.to_param, group: params }
end end
let(:user) { create(:user) }
before do before do
stub_licensed_features(pages_size_limit: true) stub_licensed_features(pages_size_limit: true)
group.add_owner(user) group.add_owner(user)
...@@ -376,11 +380,11 @@ RSpec.describe GroupsController do ...@@ -376,11 +380,11 @@ RSpec.describe GroupsController do
end end
context 'when `max_personal_access_token_lifetime` is specified' do context 'when `max_personal_access_token_lifetime` is specified' do
let!(:managed_group) do let_it_be(:managed_group) do
create(:group_with_managed_accounts, :private, max_personal_access_token_lifetime: 1) create(:group_with_managed_accounts, :private, max_personal_access_token_lifetime: 1)
end end
let(:user) { create(:user, :group_managed, managing_group: managed_group ) } let_it_be(:user) { create(:user, :group_managed, managing_group: managed_group ) }
let(:params) { { max_personal_access_token_lifetime: max_personal_access_token_lifetime } } let(:params) { { max_personal_access_token_lifetime: max_personal_access_token_lifetime } }
let(:max_personal_access_token_lifetime) { 10 } let(:max_personal_access_token_lifetime) { 10 }
......
...@@ -46,9 +46,11 @@ RSpec.describe Registrations::GroupsController do ...@@ -46,9 +46,11 @@ RSpec.describe Registrations::GroupsController do
end end
describe 'POST #create' do describe 'POST #create' do
subject { post :create, params: { group: params } } let(:group_params) do
{ name: 'Group name', path: 'group-path', visibility_level: Gitlab::VisibilityLevel::PRIVATE, emails: ['', ''] }
end
let(:params) { { name: 'Group name', path: 'group-path', visibility_level: Gitlab::VisibilityLevel::PRIVATE, emails: ['', ''] } } subject { post :create, params: { group: group_params } }
context 'with an unauthenticated user' do context 'with an unauthenticated user' do
it { is_expected.to have_gitlab_http_status(:redirect) } it { is_expected.to have_gitlab_http_status(:redirect) }
...@@ -71,7 +73,7 @@ RSpec.describe Registrations::GroupsController do ...@@ -71,7 +73,7 @@ RSpec.describe Registrations::GroupsController do
it_behaves_like GroupInviteMembers it_behaves_like GroupInviteMembers
context 'when the group cannot be saved' do context 'when the group cannot be saved' do
let(:params) { { name: '', path: '' } } let(:group_params) { { name: '', path: '' } }
it 'does not create a group' do it 'does not create a group' do
expect { subject }.not_to change { Group.count } expect { subject }.not_to change { Group.count }
......
# frozen_string_literal: true # frozen_string_literal: true
RSpec.shared_examples GroupInviteMembers do RSpec.shared_examples GroupInviteMembers do
context 'inviting members' do context 'when inviting members', :snowplow do
context 'with no valid emails in the params' do context 'without valid emails in the params' do
it 'does not add members' do it 'only adds creator as member' do
expect { subject }.to change(Member, :count).by(1) expect { subject }.to change(Member, :count).by(1)
end end
it 'does not call the Members::CreateService' do it 'does not track the event' do
expect(Members::CreateService).not_to receive(:new) subject
expect_no_snowplow_event
end end
end end
context 'with valid emails in the params' do context 'with valid emails in the params' do
before do before do
params[:emails] = ['a@a.a', 'b@b.b', '', '', 'x', 'y'] group_params[:emails] = ['a@a.a', 'b@b.b', '', '', 'x', 'y']
end end
it 'adds users with developer access and ignores blank emails' do it 'adds users with developer access and ignores blank emails' do
...@@ -38,6 +40,12 @@ RSpec.shared_examples GroupInviteMembers do ...@@ -38,6 +40,12 @@ RSpec.shared_examples GroupInviteMembers do
expect(emails).to include('a@a.a', 'b@b.b') expect(emails).to include('a@a.a', 'b@b.b')
expect(emails).not_to include('x', 'y') expect(emails).not_to include('x', 'y')
end end
it 'tracks the event' do
subject
expect_snowplow_event(category: anything, action: 'invite_members', label: 'new_group_form')
end
end end
end end
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