Skip to content
Snippets Groups Projects
Commit 423809be authored by Doug Stull's avatar Doug Stull :two:
Browse files

Merge branch 'sy-add-member-limit-banner-to-usage-quota-seats-page' into 'master'

Add member limit banner to usage quota seats page

See merge request !91505
parents af0d7a25 c77e97e7
No related branches found
No related tags found
1 merge request!91505Add member limit banner to usage quota seats page
Pipeline #583532120 passed
Showing
with 315 additions and 68 deletions
.container-fluid.container-limited{ class: "gl-pb-2! gl-pt-6! #{content_class}" }
%div{ class: "#{container_class}" }
= render Pajamas::AlertComponent.new(variant: variant,
alert_options: { class: 'js-user-over-limit-free-plan-alert', data: alert_data },
title: alert_attributes[:title],
......
......@@ -109,6 +109,10 @@ def namespace_secondary_cta
def link_end
'</a>'.html_safe
end
def container_class
"container-fluid container-limited gl-pb-2! gl-pt-6! #{content_class}"
end
end
end
end
# frozen_string_literal: true
module Namespaces
module FreeUserCap
class UsageQuotaAlertComponent < AlertComponent
private
FREE_GROUP_LIMITED_ALERT = 'free_group_limited_alert'
def breached_cap_limit?
return false unless subscription_expired? || expired_trial?
::Namespaces::FreeUserCap::Standard.new(namespace).over_limit?
end
def base_alert_data
{
track_action: 'render',
track_property: 'free_group_limited_usage_quota_banner',
feature_id: feature_name,
testid: 'free-group-limited-alert'
}
end
def close_button_data
{
track_action: 'dismiss_banner',
track_property: 'free_group_limited_usage_quota_banner',
testid: 'free-group-limited-dismiss'
}
end
def feature_name
FREE_GROUP_LIMITED_ALERT
end
def alert_attributes
{
title: s_('Billing|Your free group is now limited to %{free_user_limit} members') % {
free_user_limit: ::Namespaces::FreeUserCap::FREE_USER_LIMIT
},
body: s_(
'Billing|Your group recently changed to use the Free plan. Free groups are limited to ' \
'%{free_user_limit} members and the remaining members will get a status of over-limit ' \
'and lose access to the group. You can free up space for new members by removing ' \
'those who no longer need access or toggling them to over-limit. To get an unlimited ' \
'number of members, you can %{link_start}upgrade%{link_end} to a paid tier.'
).html_safe % {
free_user_limit: ::Namespaces::FreeUserCap::FREE_USER_LIMIT,
link_start: '<a data-track-action="click_link" data-track-label="upgrade" ' \
'data-track-property="free_group_limited_usage_quota_banner" ' \
'href="%{url}">'.html_safe % { url: group_billings_path(namespace) },
link_end: '</a>'.html_safe
}
}
end
def container_class
content_class
end
def subscription_expired?
# sometimes namespaces don't have subscriptions, so we need to protect here
namespace.gitlab_subscription&.expired?
end
def expired_trial?
namespace.trial_expired?
end
end
end
end
......@@ -4,12 +4,6 @@
module Namespaces
module FreeUserCap
class Preview < Standard
def over_limit?
return false unless enforce_cap?
users_count > FREE_USER_LIMIT
end
private
def feature_enabled?
......
......@@ -7,6 +7,12 @@ def initialize(root_namespace)
@root_namespace = root_namespace.root_ancestor # just in case the true root isn't passed
end
def over_limit?
return false unless enforce_cap?
users_count > FREE_USER_LIMIT
end
def reached_limit?
return false unless enforce_cap?
......
......@@ -25,6 +25,10 @@
.tab-content
.tab-pane.active#seats-quota-tab
= render Namespaces::FreeUserCap::UsageQuotaAlertComponent.new(namespace: @group.root_ancestor,
user: current_user,
content_class: 'gl-my-3')
#js-seat-usage-app{ data: group_seats_usage_quota_app_data(@group) }
.tab-pane#pipelines-quota-tab
- if Feature.enabled?(:usage_quotas_pipelines_vue, @group)
......
......@@ -24,10 +24,13 @@
it 'has content for the alert' do
render_inline(component)
expect(rendered_component).to have_selector(".#{content_class}")
expect(rendered_component).to have_content(title)
expect(rendered_component).to have_link('Manage members', href: group_usage_quotas_path(namespace))
expect(rendered_component).to have_link('Explore paid plans', href: group_billings_path(namespace))
expect(rendered_component)
.to match("container-fluid container-limited gl-pb-2! gl-pt-6! #{content_class}")
expect(rendered_component)
.to have_css("[data-testid='user-over-limit-free-plan-alert']" \
"[data-dismiss-endpoint='#{group_callouts_path}']" \
......
# frozen_string_literal: true
require "spec_helper"
RSpec.describe Namespaces::FreeUserCap::UsageQuotaAlertComponent, :saas, :aggregate_failures, type: :component do
let_it_be(:namespace, refind: true) { create(:group) }
let_it_be(:user, refind: true) { create(:user) }
let_it_be(:content_class) { '_content_class_' }
let(:free_plan_members_count) { Namespaces::FreeUserCap::FREE_USER_LIMIT + 1 }
let!(:gitlab_subscription) { create(:gitlab_subscription, :expired, :free, namespace: namespace) }
let(:title) do
"Your free group is now limited to #{::Namespaces::FreeUserCap::FREE_USER_LIMIT} members"
end
let(:body) do
'Your group recently changed to use the Free plan. Free groups are limited to 5 members and ' \
'the remaining members will get a status of over-limit and lose access to the group. You can ' \
'free up space for new members by removing those who no longer need access or toggling them ' \
'to over-limit. To get an unlimited number of members, you can upgrade to a paid tier.'
end
subject(:component) { described_class.new(namespace: namespace, user: user, content_class: content_class) }
before do
namespace.add_owner(user)
stub_ee_application_setting(should_check_namespace_plan: true)
allow(namespace).to receive(:free_plan_members_count).and_return(free_plan_members_count)
end
shared_examples 'renders the alert' do
it 'has content for the alert' do
render_inline(component)
expect(rendered_component).to have_selector(".#{content_class}")
expect(rendered_component).to have_content(title)
expect(rendered_component).to have_content(body)
expect(rendered_component).to have_link('upgrade', href: group_billings_path(namespace))
expect(rendered_component)
.to have_css('.js-user-over-limit-free-plan-alert' \
"[data-dismiss-endpoint='#{group_callouts_path}']" \
"[data-feature-id='#{described_class::FREE_GROUP_LIMITED_ALERT}']" \
"[data-group-id='#{namespace.id}']")
end
it 'renders all the expected tracking items' do
render_inline(component)
expect(rendered_component).to have_css('[data-testid="free-group-limited-alert"]' \
'[data-track-action="render"]' \
'[data-track-property="free_group_limited_usage_quota_banner"]')
expect(rendered_component).to have_css('[data-testid="free-group-limited-dismiss"]' \
'[data-track-action="dismiss_banner"]' \
'[data-track-property="free_group_limited_usage_quota_banner"]')
expect(rendered_component).to have_css('[data-track-action="click_link"]' \
'[data-track-label="upgrade"]' \
'[data-track-property="free_group_limited_usage_quota_banner"]')
end
end
shared_examples 'does not render the alert' do
it 'does not have the title' do
render_inline(component)
expect(rendered_component).not_to have_content(title)
end
end
context 'when under the limit' do
let(:free_plan_members_count) { Namespaces::FreeUserCap::FREE_USER_LIMIT }
it_behaves_like 'does not render the alert'
end
context 'when over the limit' do
context 'when paid subscription is expired' do
let!(:gitlab_subscription) do
create(:gitlab_subscription, :expired, namespace: namespace)
end
it_behaves_like 'does not render the alert'
context 'when it is a trial' do
let!(:gitlab_subscription) do
create(:gitlab_subscription, :expired, :active_trial, namespace: namespace)
end
it_behaves_like 'does not render the alert'
end
end
context 'when free subscription' do
context 'when subscription is expired' do
it_behaves_like 'renders the alert'
end
context 'when trial is expired' do
let!(:gitlab_subscription) { create(:gitlab_subscription, :expired_trial, :free, namespace: namespace) }
it_behaves_like 'renders the alert'
end
context 'when trial is active' do
let!(:gitlab_subscription) { create(:gitlab_subscription, :active_trial, :free, namespace: namespace) }
it_behaves_like 'does not render the alert'
end
end
end
end
......@@ -397,6 +397,25 @@
end
end
context 'when on a paid expired plan and over limit that is now free' do
let_it_be(:gitlab_subscription) { create(:gitlab_subscription, :expired, :free, namespace: group) }
let_it_be(:active_members) do
create_list(:group_member, ::Namespaces::FreeUserCap::FREE_USER_LIMIT + 1, source: group)
end
it 'shows usage quota alert' do
expect(page).to have_content('Your free group is now limited to')
expect(page).to have_link('upgrade')
page.find("[data-testid='free-group-limited-dismiss']").click
expect(page).not_to have_content('Your free group is now limited to')
page.refresh
expect(page).not_to have_content('Your free group is now limited to')
end
end
context 'when on a trial' do
let_it_be(:gitlab_subscription) { create(:gitlab_subscription, :active_trial, seats_in_use: 4, seats: 10, namespace: group) }
......
......@@ -3,24 +3,16 @@
require 'spec_helper'
RSpec.describe Namespaces::FreeUserCap::Preview, :saas do
let_it_be(:namespace, reload: true) { create(:group_with_plan, plan: :free_plan) }
let(:should_check_namespace_plan) { true }
let_it_be(:namespace) { create(:group_with_plan, plan: :free_plan) }
before do
stub_ee_application_setting(should_check_namespace_plan: should_check_namespace_plan)
stub_ee_application_setting(should_check_namespace_plan: true)
allow(namespace).to receive(:free_plan_members_count).and_return(Namespaces::FreeUserCap::FREE_USER_LIMIT + 1)
end
describe '#over_limit?' do
let(:free_plan_members_count) { Namespaces::FreeUserCap::FREE_USER_LIMIT + 1 }
subject(:over_limit?) { described_class.new(namespace).over_limit? }
before do
stub_ee_application_setting(should_check_namespace_plan: should_check_namespace_plan)
allow(namespace).to receive(:free_plan_members_count).and_return(free_plan_members_count)
end
context 'when :preview_free_user_cap is disabled' do
before do
stub_feature_flags(preview_free_user_cap: false)
......@@ -34,58 +26,14 @@
stub_feature_flags(preview_free_user_cap: true)
end
context 'when under the number of free users limit' do
let(:free_plan_members_count) { Namespaces::FreeUserCap::FREE_USER_LIMIT - 1 }
it { is_expected.to be false }
end
context 'when at the same number as the free users limit' do
let(:free_plan_members_count) { Namespaces::FreeUserCap::FREE_USER_LIMIT }
it { is_expected.to be false }
end
context 'when over the number of free users limit' do
context 'when it is a free plan' do
it { is_expected.to be true }
context 'when the namespace is not a group' do
let_it_be(:namespace) do
namespace = create(:user).namespace
create(:gitlab_subscription, hosted_plan: create(:free_plan), namespace: namespace)
namespace
end
it { is_expected.to be true }
it { is_expected.to be true }
end
context 'when excluded from free user cap' do
before do
namespace.namespace_settings.update_column(:exclude_from_free_user_cap, true)
end
context 'when it is a non free plan' do
let_it_be(:namespace) { create(:group_with_plan, plan: :ultimate_plan) }
it { is_expected.to be false }
end
context 'when no plan exists' do
let_it_be(:namespace) { create(:group) }
it { is_expected.to be true }
end
context 'when should check namespace plan is false' do
let(:should_check_namespace_plan) { false }
it { is_expected.to be false }
end
context 'when excluded from free user cap' do
before do
namespace.namespace_settings.update_column(:exclude_from_free_user_cap, true)
end
it { is_expected.to be false }
end
it { is_expected.to be false }
end
end
end
......
......@@ -11,6 +11,85 @@
stub_ee_application_setting(should_check_namespace_plan: should_check_namespace_plan)
end
describe '#over_limit?' do
let(:free_plan_members_count) { Namespaces::FreeUserCap::FREE_USER_LIMIT + 1 }
subject(:over_limit?) { described_class.new(namespace).over_limit? }
before do
stub_ee_application_setting(should_check_namespace_plan: should_check_namespace_plan)
allow(namespace).to receive(:free_plan_members_count).and_return(free_plan_members_count)
end
context 'when :free_user_cap is disabled' do
before do
stub_feature_flags(free_user_cap: false)
end
it { is_expected.to be false }
end
context 'when :free_user_cap is enabled' do
before do
stub_feature_flags(free_user_cap: true)
end
context 'when under the number of free users limit' do
let(:free_plan_members_count) { Namespaces::FreeUserCap::FREE_USER_LIMIT - 1 }
it { is_expected.to be false }
end
context 'when at the same number as the free users limit' do
let(:free_plan_members_count) { Namespaces::FreeUserCap::FREE_USER_LIMIT }
it { is_expected.to be false }
end
context 'when over the number of free users limit' do
context 'when it is a free plan' do
it { is_expected.to be true }
context 'when the namespace is not a group' do
let_it_be(:namespace) do
namespace = create(:user).namespace
create(:gitlab_subscription, hosted_plan: create(:free_plan), namespace: namespace)
namespace
end
it { is_expected.to be true }
end
end
context 'when it is a non free plan' do
let_it_be(:namespace) { create(:group_with_plan, plan: :ultimate_plan) }
it { is_expected.to be false }
end
context 'when no plan exists' do
let_it_be(:namespace) { create(:group) }
it { is_expected.to be true }
end
context 'when should check namespace plan is false' do
let(:should_check_namespace_plan) { false }
it { is_expected.to be false }
end
context 'when excluded from free user cap' do
before do
namespace.namespace_settings.update_column(:exclude_from_free_user_cap, true)
end
it { is_expected.to be false }
end
end
end
end
describe '#reached_limit?' do
let(:free_plan_members_count) { Namespaces::FreeUserCap::FREE_USER_LIMIT + 1 }
......
......@@ -6261,6 +6261,12 @@ msgstr ""
msgid "Billing|You can begin moving members in %{namespaceName} now. A member loses access to the group when you turn off %{strongStart}In a seat%{strongEnd}. If over 5 members have %{strongStart}In a seat%{strongEnd} enabled after June 22, 2022, we'll select the 5 members who maintain access. We'll first count members that have Owner and Maintainer roles, then the most recently active members until we reach 5 members. The remaining members will get a status of Over limit and lose access to the group."
msgstr ""
 
msgid "Billing|Your free group is now limited to %{free_user_limit} members"
msgstr ""
msgid "Billing|Your group recently changed to use the Free plan. Free groups are limited to %{free_user_limit} members and the remaining members will get a status of over-limit and lose access to the group. You can free up space for new members by removing those who no longer need access or toggling them to over-limit. To get an unlimited number of members, you can %{link_start}upgrade%{link_end} to a paid tier."
msgstr ""
msgid "Bitbucket Server Import"
msgstr ""
 
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment