Commit 74bd49b1 authored by Jason Goodman's avatar Jason Goodman Committed by Etienne Baqué

Make User Cap Reached Banner Dismissible

parent eb09de51
......@@ -2,9 +2,11 @@ import 'bootstrap/js/dist/modal';
import initEETrialBanner from 'ee/ee_trial_banner';
import trackNavbarEvents from 'ee/event_tracking/navbar';
import initNamespaceStorageLimitAlert from 'ee/namespace_storage_limit_alert';
import initNamespaceUserCapReachedAlert from 'ee/namespace_user_cap_reached_alert';
// EE specific calls
initEETrialBanner();
initNamespaceStorageLimitAlert();
initNamespaceUserCapReachedAlert();
trackNavbarEvents();
import Cookies from 'js-cookie';
const handleOnDismiss = ({ currentTarget }) => {
const {
dataset: { cookieId },
} = currentTarget;
Cookies.set(cookieId, true, { expires: 30 });
};
export default () => {
const alert = document.querySelector('.js-namespace-user-cap-alert-dismiss');
if (alert) {
alert.addEventListener('click', handleOnDismiss);
}
};
......@@ -8,11 +8,21 @@ module EE
return false if root_namespace.user_namespace?
return false if alert_has_been_dismissed?(root_namespace)
can?(current_user, :admin_namespace, root_namespace) && user_cap_reached?(root_namespace)
end
def hide_user_cap_alert_cookie_id(root_namespace)
"hide_user_cap_alert_#{root_namespace.id}"
end
private
def alert_has_been_dismissed?(root_namespace)
cookies[hide_user_cap_alert_cookie_id(root_namespace)] == 'true'
end
def user_cap_reached?(root_namespace)
Rails.cache.fetch("namespace_user_cap_reached:#{root_namespace.id}", expires_in: 2.hours) do
root_namespace.user_cap_reached?
......
......@@ -16,7 +16,7 @@
.gl-alert-title
%h4.gl-alert-title= s_('NamespaceUserCap|Your group has reached its billable member limit')
%button.gl-alert-dismiss.gl-cursor-pointer{ type: 'button', 'aria-label' => _('Dismiss'), data: { level: :warning } }
%button.js-namespace-user-cap-alert-dismiss.gl-alert-dismiss.gl-cursor-pointer{ type: 'button', 'aria-label' => _('Dismiss'), data: { cookie_id: hide_user_cap_alert_cookie_id(root_namespace), level: :warning, testid: 'namespace_user_cap_alert_dismiss' } }
= sprite_icon('close', css_class: 'gl-icon')
.gl-alert-body
......
......@@ -25,21 +25,24 @@ RSpec.describe 'Namespace user cap reached alert', :feature, :js do
sign_in(owner)
visit group_path(group)
expect(page).to have_text 'Your group has reached its billable member limit'
expect_group_page_for(group)
expect_banner_to_be_present
end
it 'displays the banner to a group owner on a subgroup page' do
sign_in(owner)
visit group_path(subgroup)
expect(page).to have_text 'Your group has reached its billable member limit'
expect_group_page_for(subgroup)
expect_banner_to_be_present
end
it 'displays the banner to a group owner on a project page' do
sign_in(owner)
visit project_path(project)
expect(page).to have_text 'Your group has reached its billable member limit'
expect_project_page_for(project)
expect_banner_to_be_present
end
it 'does not display the banner when the feature flag is off' do
......@@ -47,27 +50,76 @@ RSpec.describe 'Namespace user cap reached alert', :feature, :js do
sign_in(owner)
visit group_path(group)
expect_banner_to_be_absent(group)
expect_group_page_for(group)
expect_banner_to_be_absent
end
it 'does not display the banner to a user who is not a group owner' do
sign_in(developer)
visit group_path(group)
expect_banner_to_be_absent(group)
expect_group_page_for(group)
expect_banner_to_be_absent
end
it 'does not display the banner to a user who owns a subgroup' do
sign_in(subgroup_owner)
visit group_path(subgroup)
expect_banner_to_be_absent(subgroup)
expect_group_page_for(subgroup)
expect_banner_to_be_absent
end
it 'does not display the banner to an unauthenticated user' do
visit group_path(group)
expect_banner_to_be_absent(group)
expect_group_page_for(group)
expect_banner_to_be_absent
end
it 'can be dismissed' do
sign_in(owner)
visit group_path(group)
dismiss_button.click
expect_group_page_for(group)
expect_banner_to_be_absent
end
it 'remains dismissed' do
sign_in(owner)
visit group_path(group)
dismiss_button.click
visit group_path(group)
expect_group_page_for(group)
expect_banner_to_be_absent
end
it 'is dismissed independently for each root group' do
other_group = create(:group, :public,
namespace_settings: create(:namespace_settings, new_user_signups_cap: 1))
other_group.add_owner(owner)
sign_in(owner)
visit group_path(group)
dismiss_button.click
visit group_path(other_group)
expect_group_page_for(other_group)
expect_banner_to_be_present
end
it 'is dismissed for a root group when dismissed from a subgroup' do
sign_in(owner)
visit group_path(subgroup)
dismiss_button.click
visit group_path(group)
expect_group_page_for(group)
expect_banner_to_be_absent
end
end
......@@ -80,7 +132,8 @@ RSpec.describe 'Namespace user cap reached alert', :feature, :js do
sign_in(owner)
visit group_path(group)
expect_banner_to_be_absent(group)
expect_group_page_for(group)
expect_banner_to_be_absent
end
end
......@@ -93,7 +146,8 @@ RSpec.describe 'Namespace user cap reached alert', :feature, :js do
sign_in(owner)
visit group_path(group)
expect_banner_to_be_absent(group)
expect_group_page_for(group)
expect_banner_to_be_absent
end
end
......@@ -104,15 +158,30 @@ RSpec.describe 'Namespace user cap reached alert', :feature, :js do
sign_in(owner)
visit project_path(personal_project)
expect(page).to have_text owner.name
expect(page).to have_text personal_project.name
expect(page).not_to have_text 'Your group has reached its billable member limit'
expect_project_page_for(personal_project)
expect_banner_to_be_absent
end
end
def expect_banner_to_be_absent(group)
def dismiss_button
find('button[data-testid="namespace_user_cap_alert_dismiss"]')
end
def expect_group_page_for(group)
expect(page).to have_text group.name
expect(page).to have_text "Group ID: #{group.id}"
end
def expect_project_page_for(project)
expect(page).to have_text project.namespace.name
expect(page).to have_text project.name
end
def expect_banner_to_be_present
expect(page).to have_text 'Your group has reached its billable member limit'
end
def expect_banner_to_be_absent
expect(page).not_to have_text 'Your group has reached its billable member limit'
end
end
import Cookies from 'js-cookie';
import initNamespaceUserCapReachedAlert from 'ee/namespace_user_cap_reached_alert';
describe('dismissing the alert', () => {
const clickDismissButton = () => {
const button = document.querySelector('.js-namespace-user-cap-alert-dismiss');
button.click();
};
beforeEach(() => {
setFixtures(`
<div class="js-namespace-user-cap-alert">
<button class="js-namespace-user-cap-alert-dismiss" data-cookie-id="hide_user_cap_alert_1" data-level="info"></button>
</div>
`);
initNamespaceUserCapReachedAlert();
});
it('sets the banner to be hidden for thirty days', () => {
jest.spyOn(Cookies, 'set');
clickDismissButton();
expect(Cookies.set).toHaveBeenCalledWith('hide_user_cap_alert_1', true, { expires: 30 });
});
});
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