Commit f931054f authored by Doug Stull's avatar Doug Stull Committed by Bob Van Landuyt

Fix invite member div on projects page

- wasn't showing up due to incorrect helper logic
parent beb6ecab
......@@ -8,6 +8,8 @@ import ProjectsList from '~/projects_list';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import GroupTabs from './group_tabs';
import initInviteMembersBanner from '~/groups/init_invite_members_banner';
import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
export default function initGroupDetails(actionName = 'show') {
const loadableActions = [ACTIVE_TAB_SHARED, ACTIVE_TAB_ARCHIVED];
......@@ -24,4 +26,6 @@ export default function initGroupDetails(actionName = 'show') {
new ProjectsList();
initInviteMembersBanner();
initInviteMembersModal();
initInviteMembersTrigger();
}
......@@ -3,10 +3,14 @@
module InviteMembersHelper
include Gitlab::Utils::StrongMemoize
def invite_members_allowed?(group)
def can_invite_members_for_group?(group)
Feature.enabled?(:invite_members_group_modal, group) && can?(current_user, :admin_group_member, group)
end
def can_invite_members_for_project?(project)
Feature.enabled?(:invite_members_group_modal, project.group) && can_import_members?
end
def directly_invite_members?
strong_memoize(:directly_invite_members) do
experiment_enabled?(:invite_members_version_a) && can_import_members?
......
- if invite_members_allowed?(group)
- if can_invite_members_for_group?(group)
.js-invite-members-modal{ data: { id: group.id,
name: group.name,
is_project: 'false',
......
- if invite_members_allowed?(group) && body_data_page == 'groups:show'
%li
.js-invite-members-trigger{ data: { icon: 'plus', display_text: _('Invite team members') } }
......@@ -14,12 +14,12 @@
= _('Group members')
%p
= html_escape(_('You can invite a new member to %{strong_start}%{group_name}%{strong_end}.')) % { group_name: @group.name, strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe }
- if invite_members_allowed?(@group)
- if can_invite_members_for_group?(@group)
.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)
= render 'groups/invite_members_modal', group: @group
- if can_manage_members && !can_invite_members_for_group?(@group)
%hr.gl-mt-4
%ul.nav-links.nav.nav-tabs.gitlab-tabs{ role: 'tablist' }
%li.nav-tab{ role: 'presentation' }
......
......@@ -16,6 +16,11 @@
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, group_url(@group, rss_url_options), title: "#{@group.name} activity")
= content_for :invite_members_sidebar do
- if can_invite_members_for_group?(@group)
%li
.js-invite-members-trigger{ data: { icon: 'plus', classes: 'gl-text-decoration-none! gl-shadow-none!', display_text: _('Invite team members') } }
= render partial: 'flash_messages'
= render_if_exists 'trials/banner', namespace: @group
......@@ -26,7 +31,7 @@
= render_if_exists 'groups/group_activity_analytics', group: @group
= render_if_exists 'groups/invite_members_modal', group: @group
= render 'groups/invite_members_modal', group: @group
.groups-listing{ data: { endpoints: { default: group_children_path(@group, format: :json), shared: group_shared_projects_path(@group, format: :json) } } }
.top-area.group-nav-container.justify-content-between
......
......@@ -141,7 +141,7 @@
%strong.fly-out-top-item-name
= _('Members')
= render_if_exists 'groups/invite_members_side_nav_link', group: @group
= content_for :invite_members_sidebar
- if group_sidebar_link?(:settings)
= nav_link(path: group_settings_nav_link_paths) do
......
......@@ -383,7 +383,7 @@
%strong.fly-out-top-item-name
= _('Members')
= render_if_exists 'projects/invite_members_side_nav_link', project: @project
= content_for :invite_members_sidebar
- if project_nav_tab? :settings
= nav_link(path: sidebar_settings_paths) do
......
......@@ -3,7 +3,7 @@
- max_project_topic_length = 15
- emails_disabled = @project.emails_disabled?
= render_if_exists 'projects/invite_members_modal', project: @project
= render 'projects/invite_members_modal', project: @project
.project-home-panel.js-show-on-project-root.gl-my-5{ class: [("empty-project" if empty_repo)] }
.row.gl-mb-3
......
- return unless can_invite_members_for_project?(@project)
%li
.js-invite-members-trigger{ data: { icon: 'plus', classes: 'gl-text-decoration-none! gl-shadow-none!', display_text: _('Invite team members') } }
- if invite_members_allowed?(project.group)
- if can_invite_members_for_project?(project)
.js-invite-members-modal{ data: { id: project.id,
name: project.name,
is_project: 'true',
......
- if invite_members_allowed?(project.group) && body_data_page == 'projects:show'
%li
.js-invite-members-trigger{ data: { icon: 'plus', display_text: _('Invite team members') } }
......@@ -2,6 +2,9 @@
- default_branch_name = @project.default_branch || "master"
- @skip_current_level_breadcrumb = true
= content_for :invite_members_sidebar do
= render partial: 'projects/invite_members_link'
= render partial: 'flash_messages', locals: { project: @project }
= render "home_panel"
......
......@@ -12,7 +12,7 @@
#{ _('This means you can not push code until you create an empty repository or import existing one.') }
%hr
= render_if_exists 'projects/invite_members_modal', project: @project
= render 'projects/invite_members_modal', project: @project
.no-repo-actions
= link_to project_repository_path(@project), method: :post, class: 'btn btn-primary' do
......
......@@ -4,7 +4,7 @@
.js-remove-member-modal
.row.gl-mt-3
.col-lg-12
- if invite_members_allowed?(group)
- if can_invite_members_for_project?(@project)
.row
.col-md-12.col-lg-6.gl-display-flex
.gl-flex-direction-column.gl-flex-wrap.align-items-baseline
......@@ -19,7 +19,7 @@
.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
= render 'projects/invite_members_modal', project: @project
- else
- if project_can_be_shared?
......@@ -31,7 +31,7 @@
%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 !can_invite_members_for_project?(@project) && can_manage_project_members?(@project) && project_can_be_shared?
- if !membership_locked? && @project.allowed_to_share_with_group?
%ul.nav-links.nav.nav-tabs.gitlab-tabs{ role: 'tablist' }
%li.nav-tab{ role: 'presentation' }
......
......@@ -6,6 +6,9 @@
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, project_path(@project, rss_url_options), title: "#{@project.name} activity")
= content_for :invite_members_sidebar do
= render partial: 'projects/invite_members_link'
= render partial: 'flash_messages', locals: { project: @project }
= render "projects/last_push"
......
......@@ -2,12 +2,8 @@ import initGroupAnalytics from 'ee/analytics/group_analytics/group_analytics_bun
import leaveByUrl from '~/namespaces/leave_by_url';
import initGroupDetails from '~/pages/groups/shared/group_details';
import initVueAlerts from '~/vue_alerts';
import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
leaveByUrl('group');
initGroupDetails();
initGroupAnalytics();
initVueAlerts();
initInviteMembersModal();
initInviteMembersTrigger();
......@@ -205,15 +205,4 @@ RSpec.describe 'Group navbar' do
it_behaves_like 'verified navigation bar'
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 group_path(group)
expect(page).to have_selector('.js-invite-members-trigger')
end
end
end
......@@ -8,6 +8,10 @@ RSpec.describe 'Project > Members > Invite group and members', :js do
let(:maintainer) { create(:user) }
before do
stub_feature_flags(invite_members_group_modal: false)
end
describe 'Share group lock' do
shared_examples 'the project cannot be shared with groups' do
it 'user is only able to share with members' do
......
......@@ -94,6 +94,7 @@ RSpec.describe "Admin::Projects" do
describe 'add admin himself to a project' do
before do
project.add_maintainer(user)
stub_feature_flags(invite_members_group_modal: false)
end
it 'adds admin a to a project as developer', :js do
......
......@@ -87,12 +87,4 @@ RSpec.describe 'Group navbar' do
it_behaves_like 'verified navigation bar'
end
context 'when invite team members is not available' do
it 'does not display the js-invite-members-trigger' do
visit group_path(group)
expect(page).not_to have_selector('.js-invite-members-trigger')
end
end
end
......@@ -8,6 +8,10 @@ RSpec.describe 'Project > Members > Invite group', :js do
let(:maintainer) { create(:user) }
before do
stub_feature_flags(invite_members_group_modal: false)
end
describe 'Share with group lock' do
shared_examples 'the project can be shared with groups' do
it 'the "Invite group" tab exists' do
......
......@@ -18,6 +18,8 @@ RSpec.describe 'Projects > Members > Maintainer adds member with expiration date
end
it 'expiration date is displayed in the members list' do
stub_feature_flags(invite_members_group_modal: false)
visit project_project_members_path(project)
page.within '.invite-users-form' do
......
......@@ -67,23 +67,4 @@ RSpec.describe 'Project navbar' do
it_behaves_like 'verified navigation bar'
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
......@@ -37,6 +37,8 @@ RSpec.describe 'Projects > Settings > User manages project members' do
end
it 'imports a team from another project' do
stub_feature_flags(invite_members_group_modal: false)
project2.add_maintainer(user)
project2.add_reporter(user_mike)
......
......@@ -12,6 +12,40 @@ RSpec.describe InviteMembersHelper do
assign(:project, project)
end
describe "#can_invite_members_for_project?" do
context 'when the user can_import_members' do
before do
allow(helper).to receive(:can_import_members?).and_return(true)
end
it 'returns true' do
expect(helper.can_invite_members_for_project?(project)).to eq true
expect(helper).to have_received(:can_import_members?)
end
context 'when feature flag is disabled' do
before do
stub_feature_flags(invite_members_group_modal: false)
end
it 'returns false' do
expect(helper.can_invite_members_for_project?(project)).to eq false
expect(helper).not_to have_received(:can_import_members?)
end
end
end
context 'when the user can not invite members' do
before do
expect(helper).to receive(:can_import_members?).and_return(false)
end
it 'returns false' do
expect(helper.can_invite_members_for_project?(project)).to eq false
end
end
end
describe "#directly_invite_members?" do
context 'when the user is an owner' do
before do
......@@ -80,6 +114,51 @@ RSpec.describe InviteMembersHelper do
context 'with group' do
let_it_be(:group) { create(:group) }
describe "#can_invite_members_for_group?" do
include Devise::Test::ControllerHelpers
let_it_be(:user) { create(:user) }
before do
sign_in(user)
allow(helper).to receive(:current_user) { user }
end
context 'when the user can_import_members' do
before do
allow(helper).to receive(:can?).with(user, :admin_group_member, group).and_return(true)
end
it 'returns true' do
expect(helper.can_invite_members_for_group?(group)).to eq true
expect(helper).to have_received(:can?).with(user, :admin_group_member, group)
end
context 'when feature flag is disabled' do
before do
stub_feature_flags(invite_members_group_modal: false)
end
it 'returns false' do
stub_feature_flags(invite_members_group_modal: false)
expect(helper.can_invite_members_for_group?(group)).to eq false
expect(helper).not_to have_received(:can?)
end
end
end
context 'when the user can not invite members' do
before do
expect(helper).to receive(:can?).with(user, :admin_group_member, group).and_return(false)
end
it 'returns false' do
expect(helper.can_invite_members_for_group?(group)).to eq false
end
end
end
describe "#invite_group_members?" do
context 'when the user is an owner' do
before do
......
......@@ -854,16 +854,36 @@ RSpec.describe ProjectsHelper do
end
describe '#can_import_members?' do
let(:owner) { project.owner }
context 'when user is project owner' do
before do
allow(helper).to receive(:current_user) { project.owner }
end
it 'returns false if user cannot admin_project_member' do
allow(helper).to receive(:current_user) { user }
expect(helper.can_import_members?).to eq false
it 'returns true for owner of project' do
expect(helper.can_import_members?).to eq true
end
end
it 'returns true if user can admin_project_member' do
allow(helper).to receive(:current_user) { owner }
expect(helper.can_import_members?).to eq true
context 'when user is not a project owner' do
using RSpec::Parameterized::TableSyntax
where(:user_project_role, :can_import) do
:maintainer | true
:developer | false
:reporter | false
:guest | false
end
with_them do
before do
project.add_role(user, user_project_role)
allow(helper).to receive(:current_user) { user }
end
it 'resolves if the user can import members' do
expect(helper.can_import_members?).to eq can_import
end
end
end
end
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'groups/show.html.haml' do
let_it_be(:user) { build(:user) }
let_it_be(:group) { create(:group) }
before do
assign(:group, group)
end
context 'when rendering with the layout' do
subject(:render_page) { render template: 'groups/show.html.haml', layout: 'layouts/group' }
describe 'invite team members' do
before do
allow(view).to receive(:session).and_return({})
allow(view).to receive(:current_user_mode).and_return(Gitlab::Auth::CurrentUserMode.new(user))
allow(view).to receive(:current_user).and_return(user)
allow(view).to receive(:experiment_enabled?).and_return(false)
allow(view).to receive(:group_path).and_return('')
allow(view).to receive(:group_shared_path).and_return('')
allow(view).to receive(:group_archived_path).and_return('')
end
context 'when invite team members is not available in sidebar' do
before do
allow(view).to receive(:can_invite_members_for_group?).and_return(false)
end
it 'does not display the js-invite-members-trigger' do
render_page
expect(rendered).not_to have_selector('.js-invite-members-trigger')
end
end
context 'when invite team members is available' do
before do
allow(view).to receive(:can_invite_members_for_group?).and_return(true)
end
it 'includes the div for js-invite-members-trigger' do
render_page
expect(rendered).to have_selector('.js-invite-members-trigger')
end
end
end
end
end
......@@ -48,7 +48,7 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
end
describe 'Packages' do
let(:user) { create(:user) }
let_it_be(:user) { create(:user) }
let_it_be(:package_menu_name) { 'Packages & Registries' }
let_it_be(:package_entry_name) { 'Package Registry' }
......
......@@ -79,4 +79,41 @@ RSpec.describe 'projects/empty' do
it_behaves_like 'no invite member info'
end
end
context 'when rendering with the layout' do
subject(:render_page) { render template: 'projects/empty.html.haml', layout: 'layouts/project' }
describe 'invite team members' do
before do
allow(view).to receive(:session).and_return({})
allow(view).to receive(:current_user_mode).and_return(Gitlab::Auth::CurrentUserMode.new(user))
allow(view).to receive(:current_user).and_return(user)
allow(view).to receive(:experiment_enabled?).and_return(false)
end
context 'when invite team members is not available in sidebar' do
before do
allow(view).to receive(:can_invite_members_for_project?).and_return(false)
end
it 'does not display the js-invite-members-trigger' do
render_page
expect(rendered).not_to have_selector('.js-invite-members-trigger')
end
end
context 'when invite team members is available' do
before do
allow(view).to receive(:can_invite_members_for_project?).and_return(true)
end
it 'includes the div for js-invite-members-trigger' do
render_page
expect(rendered).to have_selector('.js-invite-members-trigger')
end
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'projects/show.html.haml' do
let_it_be(:user) { build(:user) }
let_it_be(:project) { ProjectPresenter.new(create(:project, :repository), current_user: user) }
before do
assign(:project, project)
end
context 'when rendering with the layout' do
subject(:render_page) { render template: 'projects/show.html.haml', layout: 'layouts/project' }
describe 'invite team members' do
before do
allow(view).to receive(:event_filter_link)
allow(view).to receive(:session).and_return({})
allow(view).to receive(:current_user_mode).and_return(Gitlab::Auth::CurrentUserMode.new(user))
allow(view).to receive(:current_user).and_return(user)
allow(view).to receive(:experiment_enabled?).and_return(false)
allow(view).to receive(:add_page_startup_graphql_call)
end
context 'when invite team members is not available in sidebar' do
before do
allow(view).to receive(:can_invite_members_for_project?).and_return(false)
end
it 'does not display the js-invite-members-trigger' do
render_page
expect(rendered).not_to have_selector('.js-invite-members-trigger')
end
end
context 'when invite team members is available' do
before do
allow(view).to receive(:can_invite_members_for_project?).and_return(true)
end
it 'includes the div for js-invite-members-trigger' do
render_page
expect(rendered).to have_selector('.js-invite-members-trigger')
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