Commit 50a6fe4f authored by Doug Stull's avatar Doug Stull Committed by Miguel Rincon

Re-organize billing views into a layout and be more declarative

- currently these are hard to reason about in terms of
  subgroup or top-level group or user namespace and
  hopefully this update will make the view layer a bit easier
  to reason about.
parent b835e77f
......@@ -14,8 +14,8 @@ class Groups::BillingsController < Groups::ApplicationController
def index
@hide_search_settings = true
@top_most_group = @group.root_ancestor if @group.has_parent?
relevant_group = (@top_most_group || @group)
@top_level_group = @group.root_ancestor if @group.has_parent?
relevant_group = (@top_level_group || @group)
current_plan = relevant_group.plan_name_for_upgrading
@plans_data = GitlabSubscriptions::FetchSubscriptionPlansService
.new(plan: current_plan, namespace_id: relevant_group.id)
......
= render layout: 'shared/billings/billing_plans_layout', locals: { namespace: namespace, current_plan: current_plan } do
%p= s_("BillingPlans|This group uses the plan associated with its parent group.")
- parent_billing_page_link = link_to top_level_group.full_name, group_billings_path(top_level_group)
%p= s_("BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}.").html_safe % { parent_billing_page_link: parent_billing_page_link }
= link_to s_("BillingPlans|Manage plan"), group_billings_path(top_level_group), class: 'btn btn-success gl-button'
= render layout: 'shared/billings/billing_plans_layout', locals: { namespace: namespace, current_plan: current_plan } do
= render 'shared/billings/trial_status', namespace: namespace
= render 'shared/billings/trial_buttons', namespace: namespace, glm_content: 'group-billing'
- page_title _("Billing")
- current_plan = subscription_plan_info(@plans_data, @group.actual_plan_name)
= render_if_exists 'shared/qrtly_reconciliation_alert', group: @group
= render 'shared/qrtly_reconciliation_alert', group: @group
- if @top_most_group # subgroup
- top_most_group_plan = subscription_plan_info(@plans_data, @top_most_group.actual_plan_name)
= render 'shared/billings/billing_plan_header', namespace: @group, plan: top_most_group_plan, parent_group: @top_most_group
- if @top_level_group # we are in subgroup mode
- current_plan = subscription_plan_info(@plans_data, @top_level_group.actual_plan_name)
= render 'subgroup_billing_plan_header',
namespace: @group,
current_plan: current_plan,
top_level_group: @top_level_group
- else
= content_for :flash_message do
= render 'shared/billings/eoa_bronze_plan_banner', namespace: @group, eoa_bronze_plan_end_date: eoa_bronze_plan_end_date
- current_plan = subscription_plan_info(@plans_data, @group.actual_plan_name)
- if current_plan
= render 'top_level_billing_plan_header', namespace: @group, current_plan: current_plan
= render 'shared/billings/billing_plans', plans_data: @plans_data, namespace: @group, current_plan: current_plan
- data_attributes = subscription_plan_data_attributes(@group, current_plan).merge(extend_reactivate_trial_button_data(@group))
......
= render 'trials/banner', namespace: namespace
.billing-plan-header.content-block.gl-text-center
.billing-plan-logo
.avatar-container.s96.home-panel-avatar.gl-mr-3.float-none.gl-mb-6.gl-mt-2{ class: 'gl-mx-auto!' }
= user_avatar_without_link(user: current_user, class: 'mb-3', size: 96)
%h4
= s_("BillingPlans|@%{user_name} you are currently using the %{plan_name}.").html_safe % { user_name: current_user.username, plan_name: current_plan.name }
- if namespace.free_personal?
- groups_link = link_to s_("BillingPlans|group"), dashboard_groups_path
%p= html_escape_once(s_("BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}")).html_safe % { groups_link: groups_link.html_safe,
strong_open: '<strong>'.html_safe,
strong_close: '</strong>'.html_safe }
%p.gl-mt-1
= add_namespace_plan_to_group_instructions
- else
= render 'shared/billings/trial_status', namespace: namespace
= render 'shared/billings/trial_buttons', namespace: namespace, glm_content: 'user-billing'
......@@ -3,6 +3,12 @@
- current_plan = subscription_plan_info(@plans_data, namespace.actual_plan_name)
- data_attributes = subscription_plan_data_attributes(namespace, current_plan).merge(extend_reactivate_trial_button_data(namespace))
= render 'shared/billings/billing_plans', plans_data: @plans_data, namespace: current_user.namespace, current_plan: current_plan
= content_for :flash_message do
= render 'shared/billings/eoa_bronze_plan_banner', namespace: namespace, eoa_bronze_plan_end_date: eoa_bronze_plan_end_date
- if current_plan
= render 'billing_plan_header', namespace: namespace, current_plan: current_plan
= render 'shared/billings/billing_plans', plans_data: @plans_data, namespace: namespace, current_plan: current_plan
#js-billing-plans{ data: data_attributes }
- parent_group = local_assigns[:parent_group]
- namespace_for_user = namespace_for_user?(namespace)
- if namespace_for_user
= render_if_exists 'trials/banner', namespace: namespace
.billing-plan-header.content-block.center
.billing-plan-logo
- if namespace_for_user
.avatar-container.s96.home-panel-avatar.gl-mr-3.float-none.mx-auto.mb-4.mt-1
= user_avatar_without_link(user: current_user, class: 'mb-3', size: 96)
- elsif @group.avatar_url.present?
= group_icon(@group, class: 'border rounded mb-3 mt-1', width: 96, height: 96, alt: @group.name)
- else
.avatar-container.rect-avatar.s96.home-panel-avatar.gl-mr-3.float-none.mx-auto.mb-4.mt-1.rounded.border
= group_icon(@group, class: 'avatar avatar-tile s96', width: 96, height: 96, alt: @group.name)
%h4
- if namespace_for_user
= s_("BillingPlans|@%{user_name} you are currently using the %{plan_name}.").html_safe % { user_name: current_user.username, plan_name: plan.name }
- else
= s_("BillingPlans|%{group_name} is currently using the %{plan_name}.").html_safe % { group_name: namespace.full_name, plan_name: plan.name }
- if namespace.free_personal?
- groups_link = link_to s_("BillingPlans|group"), dashboard_groups_path
%p= html_escape_once(s_("BillingPlans|Looking to purchase or manage a subscription for your group? Navigate to your %{groups_link} and go to %{strong_open}Settings &gt; Billing.%{strong_close}")).html_safe % { groups_link: groups_link.html_safe, strong_open: '<strong>'.html_safe, strong_close: '</strong>'.html_safe }
%p.gl-mt-1
= add_namespace_plan_to_group_instructions
- elsif parent_group
%p= s_("BillingPlans|This group uses the plan associated with its parent group.")
- parent_billing_page_link = link_to parent_group.full_name, group_billings_path(parent_group)
%p= s_("BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}.").html_safe % { parent_billing_page_link: parent_billing_page_link }
= link_to s_("BillingPlans|Manage plan"), group_billings_path(parent_group), class: 'btn btn-success gl-button'
- else
= render 'shared/billings/trial_status', namespace: namespace
- if show_start_free_trial_messages?(namespace)
- glm_content = namespace_for_user ? 'user-billing' : 'group-billing'
%p
= link_to 'Start your free trial',
new_trial_registration_path(glm_source: 'gitlab.com', glm_content: glm_content),
class: 'btn btn-confirm gl-button',
data: start_free_trial_data
- if show_extend_reactivate_trial_button?(namespace)
.gl-mt-3
.js-extend-reactivate-trial-button.gl-mt-3{ data: extend_reactivate_trial_button_data(namespace) }
- support_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: EE::CUSTOMER_SUPPORT_URL }
- support_link_end = '</a>'.html_safe
= content_for :flash_message do
= render_if_exists 'shared/billings/eoa_bronze_plan_banner', namespace: namespace, eoa_bronze_plan_end_date: eoa_bronze_plan_end_date
- if current_plan
= render 'shared/billings/billing_plan_header', namespace: namespace, plan: current_plan
- if show_plans?(namespace)
- plans = billing_available_plans(plans_data, current_plan)
.billing-plans.gl-mt-7{ data: { track_action: 'render', track_label: 'billing' } }
.billing-plans.gl-mt-7{ data: { track_action: 'render', track_label: 'billing', testid: 'billing-plans' } }
- plans.each do |plan|
- next if plan.hide_card
- is_default_plan = current_plan.nil? && plan.default?
......@@ -19,6 +10,9 @@
plan_offer_type: upgrade_offer_type(namespace, plan)
- if namespace.gitlab_subscription&.has_a_paid_hosted_plan?
- support_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: EE::CUSTOMER_SUPPORT_URL }
- support_link_end = '</a>'.html_safe
.center.gl-mb-7
&= s_('BillingPlans|If you would like to downgrade your plan please contact %{support_link_start}Customer Support%{support_link_end}.').html_safe % { support_link_start: support_link_start, support_link_end: support_link_end }
......
.billing-plan-header.content-block.gl-text-center
.billing-plan-logo
- if namespace.avatar_url.present?
= group_icon(namespace, class: 'border rounded gl-mb-5 gl-mt-2', width: 96, height: 96, alt: namespace.name)
- else
.avatar-container.rect-avatar.s96.home-panel-avatar.gl-mr-3.float-none.gl-mb-6.gl-mt-2.rounded.border{ class: 'gl-mx-auto!' }
= group_icon(namespace, class: 'avatar avatar-tile s96', width: 96, height: 96, alt: namespace.name)
%h4
= s_("BillingPlans|%{group_name} is currently using the %{plan_name}.").html_safe % { group_name: namespace.full_name,
plan_name: current_plan.name }
= yield
- if show_start_free_trial_messages?(namespace)
%p
= link_to _('Start your free trial'),
new_trial_registration_path(glm_source: 'gitlab.com', glm_content: glm_content),
class: 'btn btn-confirm gl-button',
data: start_free_trial_data
- if show_extend_reactivate_trial_button?(namespace)
.gl-mt-3
.js-extend-reactivate-trial-button.gl-mt-3{ data: extend_reactivate_trial_button_data(namespace) }
......@@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe 'Billing plan pages', :feature, :js do
RSpec.describe 'Billing plan pages', :feature, :saas, :js do
include SubscriptionPortalHelpers
let(:user) { create(:user, first_name: 'James', last_name: 'Bond', organization: 'ACME') }
......@@ -24,8 +24,6 @@ RSpec.describe 'Billing plan pages', :feature, :js do
stub_billing_plans(namespace.id, plan.name, plans_data.to_json)
stub_eoa_eligibility_request(namespace.id)
allow(Gitlab).to receive(:com?) { true }
sign_in(user)
end
......@@ -47,7 +45,7 @@ RSpec.describe 'Billing plan pages', :feature, :js do
shared_examples 'does not display the billing plans' do
it 'does not display the plans' do
expect(page).not_to have_css('.billing-plans')
expect(page).not_to have_selector("[data-testid='billing-plans']")
end
end
......@@ -204,7 +202,7 @@ RSpec.describe 'Billing plan pages', :feature, :js do
end
it 'renders the plan card marked as Legacy' do
page.within('.billing-plans') do
page.within("[data-testid='billing-plans']") do
panels = page.all('.card')
expect(panels.length).to eq(plans_data.length)
......@@ -410,7 +408,7 @@ RSpec.describe 'Billing plan pages', :feature, :js do
let(:namespace) { create(:group) }
let!(:group_member) { create(:group_member, :owner, group: namespace, user: user) }
context 'top-most group' do
context 'when a group is the top-level group' do
let(:page_path) { group_billings_path(namespace) }
context 'on ultimate' do
......@@ -431,7 +429,7 @@ RSpec.describe 'Billing plan pages', :feature, :js do
end
it 'does not display the billing plans table' do
expect(page).not_to have_css('.billing-plans')
expect(page).not_to have_selector("[data-testid='billing-plans']")
end
it_behaves_like 'plan with subscription table'
......@@ -455,7 +453,7 @@ RSpec.describe 'Billing plan pages', :feature, :js do
end
it 'does display the billing plans table' do
expect(page).to have_css('.billing-plans')
expect(page).to have_selector("[data-testid='billing-plans']")
end
it_behaves_like 'can contact sales'
......@@ -484,7 +482,7 @@ RSpec.describe 'Billing plan pages', :feature, :js do
end
it 'displays the billing plans table' do
expect(page).to have_css('.billing-plans')
expect(page).to have_selector("[data-testid='billing-plans']")
end
it_behaves_like 'non-upgradable plan'
......@@ -493,6 +491,21 @@ RSpec.describe 'Billing plan pages', :feature, :js do
end
end
context 'when a group is the subgroup' do
let(:namespace) { create(:group_with_plan)}
let(:plan) { namespace.actual_plan }
let(:subgroup) { create(:group, parent: namespace)}
it 'shows the subgroup page context for billing', :aggregate_failures do
visit group_billings_path(subgroup)
expect(page).to have_text('is currently using the')
expect(page).to have_text('This group uses the plan associated with its parent group')
expect(page).to have_link('Manage plan')
expect(page).not_to have_selector("[data-testid='billing-plans']")
end
end
context 'seat refresh button' do
let!(:subscription) { create(:gitlab_subscription, namespace: namespace, hosted_plan: plan, seats: 15) }
......@@ -550,7 +563,7 @@ RSpec.describe 'Billing plan pages', :feature, :js do
end
it 'displays all plans' do
page.within('.billing-plans') do
page.within("[data-testid='billing-plans']") do
panels = page.all('.card')
expect(panels.length).to eq(plans_data.length)
plans_data.each_with_index do |data, index|
......
......@@ -43,7 +43,7 @@ RSpec.describe 'Profiles > Billing', :js do
expect(page).not_to have_field(placeholder: SearchHelpers::INPUT_PLACEHOLDER)
end
context "wtihout a group" do
context "without a group" do
it 'displays help for moving groups' do
visit profile_billings_path
......
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