Commit 1dc056b3 authored by Michael Kozono's avatar Michael Kozono

Merge branch 'add-purchase-point-to-group-billing-page' into 'master'

Use Billing Plan Card layout in profile/billing and group/billing

Closes #13485 and #31471

See merge request gitlab-org/gitlab!15437
parents 623a3db3 1938962d
...@@ -20,133 +20,36 @@ ...@@ -20,133 +20,36 @@
} }
.billing-plans { .billing-plans {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
margin-top: 8px;
.card-header {
border-bottom: 0;
}
.card { .card {
display: flex; &-header {
flex-direction: column; line-height: $gl-line-height-20;
margin: 8px;
width: 100%;
border: 0;
&:first-of-type {
margin-left: 0;
}
&:last-of-type {
margin-right: 0;
} }
@include media-breakpoint-up(sm) { &-active {
width: 280px; background-color: $gray-light;
}
.card-header,
.card-body {
border-left: 1px solid $list-border;
border-right: 1px solid $list-border;
}
.card-header {
background-color: $blue-500;
color: $white-light;
border: 0;
border-radius: 4px 4px 0 0;
font-size: 20px;
text-align: center;
} }
.card-body { .card-body {
flex-grow: 1;
border-radius: 0 0 4px 4px;
border-bottom: 1px solid $list-border;
padding: 0;
display: flex;
flex-direction: column;
.price-per-month { .price-per-month {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
color: $blue-500; color: $blue-500;
padding: 16px; font-size: 48px;
padding-bottom: 0;
justify-content: center;
font-size: 50px;
font-weight: $gl-font-weight-bold; font-weight: $gl-font-weight-bold;
line-height: 1;
.billing-conditions { .conditions {
list-style: none; list-style: none;
font-size: 20px; font-size: $gl-font-size-large;
font-weight: $gl-font-weight-bold; font-weight: $gl-font-weight-bold;
margin: auto 0; line-height: $gl-line-height;
line-height: 20px;
padding: 0;
} }
} }
.price-per-year { .price-per-year {
color: $blue-500; color: $blue-500;
text-align: center; font-size: $gl-font-size-small;
font-size: 12px;
font-weight: $gl-font-weight-bold; font-weight: $gl-font-weight-bold;
padding-bottom: 16px;
height: 32px;
}
.feature-list {
display: flex;
flex-direction: column;
flex-grow: 1;
text-align: center;
margin: 0;
li {
background-color: $gray-light;
&:first-child {
border-top: 1px solid $list-border;
}
&:last-child {
border-bottom: 1px solid $list-border;
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: flex-end;
}
&:last-child:hover {
background-color: $gray-light;
}
}
}
.plan-action {
padding: 16px;
.btn {
width: 100%;
}
}
}
&.current {
.card-body {
border-color: $blue-600;
border-width: 2px;
.price-per-month,
.price-per-year {
color: $blue-600;
}
} }
} }
} }
......
...@@ -15,7 +15,7 @@ module BillingPlansHelper ...@@ -15,7 +15,7 @@ module BillingPlansHelper
def plan_purchase_link(href, link_text) def plan_purchase_link(href, link_text)
if href if href
link_to link_text, href, class: 'btn btn-primary btn-inverted' link_to link_text, href, class: 'btn btn-success'
else else
button_tag link_text, class: 'btn disabled' button_tag link_text, class: 'btn disabled'
end end
...@@ -42,6 +42,24 @@ module BillingPlansHelper ...@@ -42,6 +42,24 @@ module BillingPlansHelper
"#{EE::SUBSCRIPTIONS_URL}/gitlab/namespaces/#{group.id}/upgrade/#{plan.id}" "#{EE::SUBSCRIPTIONS_URL}/gitlab/namespaces/#{group.id}/upgrade/#{plan.id}"
end end
def plan_purchase_url(group, plan)
"#{plan.purchase_link.href}&gl_namespace_id=#{group.id}"
end
def plan_feature_short_list(plan)
return [] unless plan.features
plan.features.sort_by! { |feature| feature.highlight ? 0 : 1 }[0...4]
end
def plan_purchase_or_upgrade_url(group, plan, current_plan)
if group.upgradable?
plan_upgrade_url(group, current_plan)
else
plan_purchase_url(group, plan)
end
end
def show_trial_banner?(namespace) def show_trial_banner?(namespace)
return false unless params[:trial] return false unless params[:trial]
......
- page_title "Billing" - page_title "Billing"
- current_plan = subscription_plan_info(@plans_data, @group.actual_plan_name) - current_plan = subscription_plan_info(@plans_data, @group.actual_plan_name)
- support_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: EE::CUSTOMER_SUPPORT_URL }
- support_link_end = '</a>'.html_safe
- if @top_most_group - if @top_most_group
- top_most_group_plan = subscription_plan_info(@plans_data, @top_most_group.actual_plan_name) - 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 = render 'shared/billings/billing_plan_header', namespace: @group, plan: top_most_group_plan, parent_group: @top_most_group
- else - else
= render 'shared/billings/billing_plan_header', namespace: @group, plan: current_plan = render 'shared/billings/billing_plans', plans_data: @plans_data, namespace: @group
#js-billing-plans{ data: subscription_plan_data_attributes(@group, current_plan) }
- if @group.actual_plan #js-billing-plans{ data: subscription_plan_data_attributes(@group, current_plan) }
.center
= 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 }
.card{ class: ('current' if current_plan?(plan)) } - purchase_link = plan.purchase_link
.card-header.bg-info.text-white - is_current_plan = purchase_link.action == 'current_plan'
.col-md-6.col-lg-3
.card.mb-5{ class: ("card-active" if is_current_plan) }
.card-header.font-weight-bold.p-3
= plan.name = plan.name
- if is_current_plan
.pull-right.text-muted
= _("Current Plan")
.card-body .card-body
.price-per-month .price-per-month
.append-right-5 .append-right-5
= number_to_plan_currency(plan.price_per_month) = number_to_plan_currency(plan.price_per_month)
%ul.billing-conditions %ul.conditions.p-0.my-auto
%li= s_("BillingPlans|per user") %li= s_("BillingPlans|per user")
%li= s_("BillingPlans|monthly") %li= s_("BillingPlans|monthly")
.price-per-year .price-per-year.text-left{ class: ("invisible" unless plan.price_per_year.positive?) }
- if plan.price_per_year > 0
- price_per_year = number_to_plan_currency(plan.price_per_year) - price_per_year = number_to_plan_currency(plan.price_per_year)
= s_("BillingPlans|paid annually at %{price_per_year}") % { price_per_year: price_per_year } = s_("BillingPlans|billed annually at %{price_per_year}") % { price_per_year: price_per_year }
%hr.mt-3.mb-3
%ul.feature-list.bordered-list %ul.unstyled-list
- plan.features.each do |feature| - plan_feature_short_list(plan).each do |feature|
%li %li.p-0{ class: ("font-weight-bold" if feature.highlight) }
- if feature.highlight
%strong= feature.title
- else
= feature.title = feature.title
%li %li.p-0.pt-3
- if plan.about_page_href - if plan.about_page_href
= link_to s_("BillingPlans|See all %{plan_name} features") % { plan_name: plan.name }, plan.about_page_href = link_to s_("BillingPlans|See all %{plan_name} features") % { plan_name: plan.name }, EE::SUBSCRIPTIONS_COMPARISON_URL
- purchase_link = plan.purchase_link
- if purchase_link - if purchase_link
.plan-action .card-footer.p-3
- href = purchase_link.href&.concat("&gl_namespace_id=#{namespace.id}") .pull-right{ class: ("invisible" unless purchase_link.action == 'upgrade' || is_current_plan) }
- upgrade_button_class = "disabled" if is_current_plan
- case purchase_link.action = link_to s_('BillingPlan|Upgrade'), plan_purchase_or_upgrade_url(namespace, plan, current_plan), class: "btn btn-success #{upgrade_button_class}"
- when 'downgrade'
= plan_purchase_link(href, s_("BillingPlans|Downgrade"))
- when 'current_plan'
= plan_purchase_link(href, s_("BillingPlans|Current plan"))
- when 'upgrade'
= plan_purchase_link(href, s_("BillingPlans|Upgrade"))
...@@ -25,11 +25,10 @@ ...@@ -25,11 +25,10 @@
= group_icon(@group, class: 'avatar avatar-tile s96', width: 96, height: 96, alt: @group.name) = group_icon(@group, class: 'avatar avatar-tile s96', width: 96, height: 96, alt: @group.name)
%h4 %h4
- plan_link = plan.about_page_href ? link_to(plan.code.titleize, plan.about_page_href) : plan.name
- if namespace == current_user.namespace - if namespace == current_user.namespace
= s_("BillingPlans|@%{user_name} you are currently using the %{plan_link} plan.").html_safe % { user_name: current_user.username, plan_link: plan_link } = s_("BillingPlans|@%{user_name} you are currently using the %{plan_name} plan.").html_safe % { user_name: current_user.username, plan_name: plan.code.titleize }
- else - else
= s_("BillingPlans|%{group_name} is currently using the %{plan_link} plan.").html_safe % { group_name: namespace.full_name, plan_link: plan_link } = s_("BillingPlans|%{group_name} is currently using the %{plan_name} plan.").html_safe % { group_name: namespace.full_name, plan_name: plan.code.titleize }
- if parent_group - if parent_group
%p= s_("BillingPlans|This group uses the plan associated with its parent group.") %p= s_("BillingPlans|This group uses the plan associated with its parent group.")
......
...@@ -6,14 +6,9 @@ ...@@ -6,14 +6,9 @@
= render 'shared/billings/billing_plan_header', namespace: namespace, plan: current_plan = render 'shared/billings/billing_plan_header', namespace: namespace, plan: current_plan
- unless namespace.gold_plan? - unless namespace.gold_plan?
- if namespace.upgradable? .billing-plans.mt-5.row
.gl-p-4.center
= link_to s_('BillingPlan|Upgrade plan'), plan_upgrade_url(namespace, current_plan), class: 'btn btn-success'
- else
.billing-plans
- plans_data.each do |plan| - plans_data.each do |plan|
= render 'shared/billings/billing_plan', namespace: namespace, plan: plan = render 'shared/billings/billing_plan', namespace: namespace, plan: plan, current_plan: current_plan
- if namespace.actual_plan - if namespace.actual_plan
.center .center
......
---
title: Show Billing Plan as Cards in profile and groups
merge_request: 15437
author:
type: added
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
module EE module EE
SUBSCRIPTIONS_URL = ENV.fetch('CUSTOMER_PORTAL_URL', 'https://customers.gitlab.com').freeze SUBSCRIPTIONS_URL = ENV.fetch('CUSTOMER_PORTAL_URL', 'https://customers.gitlab.com').freeze
SUBSCRIPTIONS_PLANS_URL = "#{SUBSCRIPTIONS_URL}/plans".freeze SUBSCRIPTIONS_COMPARISON_URL = "https://about.gitlab.com/pricing/gitlab-com/feature-comparison".freeze
SUBSCRIPTIONS_MORE_MINUTES_URL = "#{SUBSCRIPTIONS_URL}/buy_pipeline_minutes".freeze SUBSCRIPTIONS_MORE_MINUTES_URL = "#{SUBSCRIPTIONS_URL}/buy_pipeline_minutes".freeze
SUBSCRIPTIONS_PLANS_URL = "#{SUBSCRIPTIONS_URL}/plans".freeze
CUSTOMER_SUPPORT_URL = 'https://support.gitlab.com'.freeze CUSTOMER_SUPPORT_URL = 'https://support.gitlab.com'.freeze
end end
...@@ -60,7 +60,7 @@ describe 'Billing plan pages', :feature do ...@@ -60,7 +60,7 @@ describe 'Billing plan pages', :feature do
it 'displays correct plan actions' do it 'displays correct plan actions' do
expected_actions = plans_data.map { |data| data.fetch(:purchase_link).fetch(:action) } expected_actions = plans_data.map { |data| data.fetch(:purchase_link).fetch(:action) }
plan_actions = page.all('.billing-plans .card .plan-action') plan_actions = page.all('.billing-plans .card .card-footer')
expect(plan_actions.length).to eq(expected_actions.length) expect(plan_actions.length).to eq(expected_actions.length)
expected_actions.each_with_index do |expected_action, index| expected_actions.each_with_index do |expected_action, index|
...@@ -68,13 +68,13 @@ describe 'Billing plan pages', :feature do ...@@ -68,13 +68,13 @@ describe 'Billing plan pages', :feature do
case expected_action case expected_action
when 'downgrade' when 'downgrade'
expect(action).to have_content('Downgrade') expect(action).not_to have_link('Upgrade')
expect(action).to have_css('.disabled') expect(action).not_to have_css('.disabled')
when 'current_plan' when 'current_plan'
expect(action).to have_content('Current plan') expect(action).to have_link('Upgrade')
expect(action).to have_css('.disabled') expect(action).to have_css('.disabled')
when 'upgrade' when 'upgrade'
expect(action).to have_content('Upgrade') expect(action).to have_link('Upgrade')
expect(action).not_to have_css('.disabled') expect(action).not_to have_css('.disabled')
end end
end end
...@@ -100,7 +100,7 @@ describe 'Billing plan pages', :feature do ...@@ -100,7 +100,7 @@ describe 'Billing plan pages', :feature do
end end
page.within('.content') do page.within('.content') do
expect(page).to have_link('Upgrade plan', href: external_upgrade_url(namespace, bronze_plan)) expect(page).to have_link('Upgrade', href: external_upgrade_url(namespace, bronze_plan))
expect(page).to have_content('downgrade your plan') expect(page).to have_content('downgrade your plan')
expect(page).to have_link('Customer Support', href: EE::CUSTOMER_SUPPORT_URL) expect(page).to have_link('Customer Support', href: EE::CUSTOMER_SUPPORT_URL)
end end
...@@ -126,7 +126,6 @@ describe 'Billing plan pages', :feature do ...@@ -126,7 +126,6 @@ describe 'Billing plan pages', :feature do
end end
page.within('.content') do page.within('.content') do
expect(page).not_to have_link('Upgrade plan')
expect(page).to have_content('downgrade your plan') expect(page).to have_content('downgrade your plan')
expect(page).to have_link('Customer Support', href: EE::CUSTOMER_SUPPORT_URL) expect(page).to have_link('Customer Support', href: EE::CUSTOMER_SUPPORT_URL)
end end
...@@ -162,8 +161,8 @@ describe 'Billing plan pages', :feature do ...@@ -162,8 +161,8 @@ describe 'Billing plan pages', :feature do
end end
end end
it 'does not display the billing plans table' do it 'does display the billing plans table' do
expect(page).not_to have_css('.billing-plans') expect(page).to have_css('.billing-plans')
end end
it 'displays subscription table', :js do it 'displays subscription table', :js do
......
...@@ -13,6 +13,10 @@ describe 'Groups > Billing', :js do ...@@ -13,6 +13,10 @@ describe 'Groups > Billing', :js do
date.strftime("%B %-d, %Y") date.strftime("%B %-d, %Y")
end end
def subscription_table
'.subscription-table'
end
before do before do
stub_full_request("https://customers.gitlab.com/gitlab_plans?plan=#{plan}") stub_full_request("https://customers.gitlab.com/gitlab_plans?plan=#{plan}")
.to_return(status: 200, body: File.new(Rails.root.join('ee/spec/fixtures/gitlab_com_plans.json'))) .to_return(status: 200, body: File.new(Rails.root.join('ee/spec/fixtures/gitlab_com_plans.json')))
...@@ -34,11 +38,13 @@ describe 'Groups > Billing', :js do ...@@ -34,11 +38,13 @@ describe 'Groups > Billing', :js do
visit group_billings_path(group) visit group_billings_path(group)
expect(page).to have_content("#{group.name} is currently using the Free plan") expect(page).to have_content("#{group.name} is currently using the Free plan")
within subscription_table do
expect(page).to have_content("start date #{formatted_date(subscription.start_date)}") expect(page).to have_content("start date #{formatted_date(subscription.start_date)}")
expect(page).to have_link("Upgrade", href: "#{EE::SUBSCRIPTIONS_URL}/subscriptions") expect(page).to have_link("Upgrade", href: "#{EE::SUBSCRIPTIONS_URL}/subscriptions")
expect(page).not_to have_link("Manage") expect(page).not_to have_link("Manage")
end end
end end
end
context 'with a paid plan' do context 'with a paid plan' do
let(:plan) { 'bronze' } let(:plan) { 'bronze' }
...@@ -54,25 +60,29 @@ describe 'Groups > Billing', :js do ...@@ -54,25 +60,29 @@ describe 'Groups > Billing', :js do
"#{EE::SUBSCRIPTIONS_URL}/gitlab/namespaces/#{group.id}/upgrade/bronze-external-id" "#{EE::SUBSCRIPTIONS_URL}/gitlab/namespaces/#{group.id}/upgrade/bronze-external-id"
expect(page).to have_content("#{group.name} is currently using the Bronze plan") expect(page).to have_content("#{group.name} is currently using the Bronze plan")
within subscription_table do
expect(page).to have_content("start date #{formatted_date(subscription.start_date)}") expect(page).to have_content("start date #{formatted_date(subscription.start_date)}")
expect(page).to have_link("Upgrade", href: upgrade_url) expect(page).to have_link("Upgrade", href: upgrade_url)
expect(page).to have_link("Manage", href: "#{EE::SUBSCRIPTIONS_URL}/subscriptions") expect(page).to have_link("Manage", href: "#{EE::SUBSCRIPTIONS_URL}/subscriptions")
end end
end end
end
context 'with a legacy paid plan' do context 'with a legacy paid plan' do
let(:plan) { 'bronze' } let(:plan) { 'bronze' }
before do let!(:subscription) do
group.update_attribute(:plan, bronze_plan) create(:gitlab_subscription, end_date: 1.week.ago, namespace: group, hosted_plan: bronze_plan, seats: 15)
end end
it 'shows the proper title and subscription data' do it 'shows the proper title and subscription data' do
visit group_billings_path(group) visit group_billings_path(group)
expect(page).to have_content("#{group.name} is currently using the Bronze plan") expect(page).to have_content("#{group.name} is currently using the Bronze plan")
within subscription_table do
expect(page).not_to have_link("Upgrade") expect(page).not_to have_link("Upgrade")
expect(page).to have_link("Manage", href: "#{EE::SUBSCRIPTIONS_URL}/subscriptions") expect(page).to have_link("Manage", href: "#{EE::SUBSCRIPTIONS_URL}/subscriptions")
end end
end end
end
end end
...@@ -2376,21 +2376,15 @@ msgstr "" ...@@ -2376,21 +2376,15 @@ msgstr ""
msgid "Billing" msgid "Billing"
msgstr "" msgstr ""
msgid "BillingPlans|%{group_name} is currently using the %{plan_link} plan." msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
msgstr "" msgstr ""
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_link} plan." msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
msgstr "" msgstr ""
msgid "BillingPlans|Congratulations, your new trial is activated" msgid "BillingPlans|Congratulations, your new trial is activated"
msgstr "" msgstr ""
msgid "BillingPlans|Current plan"
msgstr ""
msgid "BillingPlans|Downgrade"
msgstr ""
msgid "BillingPlans|If you would like to downgrade your plan please contact %{support_link_start}Customer Support%{support_link_end}." msgid "BillingPlans|If you would like to downgrade your plan please contact %{support_link_start}Customer Support%{support_link_end}."
msgstr "" msgstr ""
...@@ -2415,15 +2409,15 @@ msgstr "" ...@@ -2415,15 +2409,15 @@ msgstr ""
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}." msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
msgstr "" msgstr ""
msgid "BillingPlans|Upgrade"
msgstr ""
msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. %{learn_more_text}" msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. %{learn_more_text}"
msgstr "" msgstr ""
msgid "BillingPlans|Your GitLab.com trial will <strong>expire after %{expiration_date}</strong>. You can learn more about GitLab.com Gold by reading about our %{features_link}." msgid "BillingPlans|Your GitLab.com trial will <strong>expire after %{expiration_date}</strong>. You can learn more about GitLab.com Gold by reading about our %{features_link}."
msgstr "" msgstr ""
msgid "BillingPlans|billed annually at %{price_per_year}"
msgstr ""
msgid "BillingPlans|features" msgid "BillingPlans|features"
msgstr "" msgstr ""
...@@ -2433,13 +2427,10 @@ msgstr "" ...@@ -2433,13 +2427,10 @@ msgstr ""
msgid "BillingPlans|monthly" msgid "BillingPlans|monthly"
msgstr "" msgstr ""
msgid "BillingPlans|paid annually at %{price_per_year}"
msgstr ""
msgid "BillingPlans|per user" msgid "BillingPlans|per user"
msgstr "" msgstr ""
msgid "BillingPlan|Upgrade plan" msgid "BillingPlan|Upgrade"
msgstr "" msgstr ""
msgid "Bitbucket Server Import" msgid "Bitbucket Server Import"
...@@ -4798,6 +4789,9 @@ msgstr "" ...@@ -4798,6 +4789,9 @@ msgstr ""
msgid "Current Branch" msgid "Current Branch"
msgstr "" msgstr ""
msgid "Current Plan"
msgstr ""
msgid "Current Project" msgid "Current Project"
msgstr "" msgstr ""
......
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