Commit 5df205dc authored by Ezekiel Kigbo's avatar Ezekiel Kigbo

Merge branch '219240-show-an-invite-your-teammates-banner-on-group-overview' into 'master'

Display invite members banner on group page

See merge request gitlab-org/gitlab!37658
parents 4c0ee663 e3d05350
<script>
import { GlBanner } from '@gitlab/ui';
import { s__ } from '~/locale';
export default {
components: {
GlBanner,
},
inject: ['svgPath', 'inviteMembersPath'],
data() {
return {
visible: true,
};
},
methods: {
handleClose() {
this.visible = false;
},
},
i18n: {
title: s__('InviteMembersBanner|Collaborate with your team'),
body: s__(
"InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge.",
),
button_text: s__('InviteMembersBanner|Invite your colleagues'),
},
};
</script>
<template>
<gl-banner
v-if="visible"
ref="banner"
:title="$options.i18n.title"
:button-text="$options.i18n.button_text"
:svg-path="svgPath"
:button-link="inviteMembersPath"
@close="handleClose"
>
<p>{{ $options.i18n.body }}</p>
</gl-banner>
</template>
import Vue from 'vue';
import InviteMembersBanner from '~/groups/components/invite_members_banner.vue';
export default function initInviteMembersBanner() {
const el = document.querySelector('.js-group-invite-members-banner');
if (!el) {
return false;
}
const { svgPath, inviteMembersPath } = el.dataset;
return new Vue({
el,
provide: {
svgPath,
inviteMembersPath,
},
render: createElement => createElement(InviteMembersBanner),
});
}
...@@ -8,6 +8,7 @@ import NotificationsForm from '~/notifications_form'; ...@@ -8,6 +8,7 @@ import NotificationsForm from '~/notifications_form';
import ProjectsList from '~/projects_list'; import ProjectsList from '~/projects_list';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation'; import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import GroupTabs from './group_tabs'; import GroupTabs from './group_tabs';
import initInviteMembersBanner from '~/groups/init_invite_members_banner';
export default function initGroupDetails(actionName = 'show') { export default function initGroupDetails(actionName = 'show') {
const newGroupChildWrapper = document.querySelector('.js-new-project-subgroup'); const newGroupChildWrapper = document.querySelector('.js-new-project-subgroup');
...@@ -27,4 +28,5 @@ export default function initGroupDetails(actionName = 'show') { ...@@ -27,4 +28,5 @@ export default function initGroupDetails(actionName = 'show') {
if (newGroupChildWrapper) { if (newGroupChildWrapper) {
new NewGroupChild(newGroupChildWrapper); new NewGroupChild(newGroupChildWrapper);
} }
initInviteMembersBanner();
} }
...@@ -167,8 +167,23 @@ module GroupsHelper ...@@ -167,8 +167,23 @@ module GroupsHelper
@group.packages_feature_enabled? @group.packages_feature_enabled?
end end
def show_invite_banner?(group)
Feature.enabled?(:invite_your_teammates_banner_a, group) &&
can?(current_user, :admin_group, group) &&
!just_created? &&
!multiple_members?(group)
end
private private
def just_created?
flash[:notice] =~ /successfully created/
end
def multiple_members?(group)
group.member_count > 1
end
def get_group_sidebar_links def get_group_sidebar_links
links = [:overview, :group_members] links = [:overview, :group_members]
......
...@@ -2,6 +2,12 @@ ...@@ -2,6 +2,12 @@
- page_title _("Groups") - page_title _("Groups")
- @content_class = "limit-container-width" unless fluid_layout - @content_class = "limit-container-width" unless fluid_layout
- if show_invite_banner?(@group)
= content_for :group_invite_members_banner do
.container-fluid.container-limited{ class: "gl-pb-2! gl-pt-6! #{@content_class}" }
.js-group-invite-members-banner{ data: { svg_path: image_path('illustrations/merge_requests.svg'),
invite_members_path: group_group_members_path(@group) } }
= content_for :meta_tags do = content_for :meta_tags do
= auto_discovery_link_tag(:atom, group_url(@group, rss_url_options), title: "#{@group.name} activity") = auto_discovery_link_tag(:atom, group_url(@group, rss_url_options), title: "#{@group.name} activity")
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
= render "layouts/nav/sidebar/#{nav}" = render "layouts/nav/sidebar/#{nav}"
.content-wrapper{ class: "#{@content_wrapper_class}" } .content-wrapper{ class: "#{@content_wrapper_class}" }
.mobile-overlay .mobile-overlay
= yield :group_invite_members_banner
.alert-wrapper .alert-wrapper
= render 'shared/outdated_browser' = render 'shared/outdated_browser'
= render_if_exists "layouts/header/licensed_user_count_threshold" = render_if_exists "layouts/header/licensed_user_count_threshold"
......
---
name: invite_your_teammates_banner_a
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37658
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/231275
group: group::expansion
type: development
default_enabled: false
\ No newline at end of file
...@@ -13492,6 +13492,15 @@ msgstr "" ...@@ -13492,6 +13492,15 @@ msgstr ""
msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}" msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
msgstr "" msgstr ""
msgid "InviteMembersBanner|Collaborate with your team"
msgstr ""
msgid "InviteMembersBanner|Invite your colleagues"
msgstr ""
msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
msgstr ""
msgid "Invited" msgid "Invited"
msgstr "" msgstr ""
......
import { shallowMount } from '@vue/test-utils';
import { GlBanner } from '@gitlab/ui';
import InviteMembersBanner from '~/groups/components/invite_members_banner.vue';
const expectedTitle = 'Collaborate with your team';
const expectedBody =
"We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge";
const expectedSvgPath = '/illustrations/background';
const expectedInviteMembersPath = 'groups/members';
const expectedButtonText = 'Invite your colleagues';
const createComponent = (stubs = {}) => {
return shallowMount(InviteMembersBanner, {
provide: {
svgPath: expectedSvgPath,
inviteMembersPath: expectedInviteMembersPath,
},
stubs,
});
};
describe('InviteMembersBanner', () => {
let wrapper;
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
describe('rendering', () => {
const findBanner = () => {
return wrapper.find(GlBanner);
};
beforeEach(() => {
wrapper = createComponent();
});
it('uses the svgPath for the banner svgpath', () => {
expect(findBanner().attributes('svgpath')).toBe(expectedSvgPath);
});
it('uses the title from options for title', () => {
expect(findBanner().attributes('title')).toBe(expectedTitle);
});
it('includes the body text from options', () => {
expect(findBanner().html()).toContain(expectedBody);
});
it('uses the button_text text from options for buttontext', () => {
expect(findBanner().attributes('buttontext')).toBe(expectedButtonText);
});
it('uses the href from inviteMembersPath for buttonlink', () => {
expect(findBanner().attributes('buttonlink')).toBe(expectedInviteMembersPath);
});
});
describe('dismissing', () => {
const findButton = () => {
return wrapper.find('button');
};
const stubs = {
GlBanner,
};
it('sets visible to false', () => {
wrapper = createComponent(stubs);
findButton().trigger('click');
expect(wrapper.vm.visible).toBe(false);
});
});
});
...@@ -369,4 +369,48 @@ RSpec.describe GroupsHelper do ...@@ -369,4 +369,48 @@ RSpec.describe GroupsHelper do
it { is_expected.to be_falsey } it { is_expected.to be_falsey }
end end
end end
describe '#show_invite_banner?' do
let_it_be(:current_user) { create(:user) }
let_it_be_with_refind(:group) { create(:group) }
let_it_be(:users) { [current_user, create(:user)] }
subject { helper.show_invite_banner?(group) }
before do
allow(helper).to receive(:current_user) { current_user }
allow(helper).to receive(:can?).with(current_user, :admin_group, group).and_return(can_admin_group)
stub_feature_flags(invite_your_teammates_banner_a: feature_enabled_flag)
users.take(group_members_count).each { |user| group.add_guest(user) }
end
using RSpec::Parameterized::TableSyntax
where(:feature_enabled_flag, :can_admin_group, :group_members_count, :expected_result) do
true | true | 1 | true
true | false | 1 | false
false | true | 1 | false
false | false | 1 | false
true | true | 2 | false
true | false | 2 | false
false | true | 2 | false
false | false | 2 | false
end
with_them do
context 'when the group was just created' do
before do
flash[:notice] = "Group #{group.name} was successfully created"
end
it { is_expected.to be_falsey }
end
context 'when no flash message' do
it 'returns the expected result' do
expect(subject).to eq(expected_result)
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