Commit 01e2be5f authored by Ammar Alakkad's avatar Ammar Alakkad Committed by Peter Leitzen

Add manual renew button to billings page

parent 87a0c544
......@@ -7,7 +7,7 @@ export default {
components: {
SubscriptionTable,
},
inject: ['planUpgradeHref', 'namespaceId', 'customerPortalUrl', 'namespaceName'],
inject: ['planUpgradeHref', 'planRenewHref', 'namespaceId', 'customerPortalUrl', 'namespaceName'],
created() {
this.setNamespaceId(this.namespaceId);
},
......@@ -21,6 +21,7 @@ export default {
<subscription-table
:namespace-name="namespaceName"
:plan-upgrade-href="planUpgradeHref"
:plan-renew-href="planRenewHref"
:customer-portal-url="customerPortalUrl"
/>
</template>
......@@ -27,6 +27,11 @@ export default {
required: false,
default: '',
},
planRenewHref: {
type: String,
required: false,
default: '',
},
},
computed: {
...mapState(['isLoadingSubscription', 'hasErrorSubscription', 'plan', 'tables', 'endpoint']),
......@@ -48,6 +53,16 @@ export default {
!this.isFreePlan && this.planUpgradeHref ? this.planUpgradeHref : this.customerPortalUrl,
};
},
renewButton() {
if (this.isFreePlan && !this.plan.trial && !gon.features.saasManualRenewButton) {
return null;
}
return {
text: s__('SubscriptionTable|Renew'),
href: this.planRenewHref,
};
},
manageButton() {
if (this.isFreePlan) {
return null;
......@@ -59,7 +74,7 @@ export default {
};
},
buttons() {
return [this.upgradeButton, this.manageButton].filter(Boolean);
return [this.upgradeButton, this.renewButton, this.manageButton].filter(Boolean);
},
visibleRows() {
let tableKey = TABLE_TYPE_DEFAULT;
......
......@@ -16,6 +16,7 @@ export default (containerId = 'js-billing-plans') => {
namespaceId,
namespaceName,
planUpgradeHref,
planRenewHref,
customerPortalUrl,
billableSeatsHref,
} = containerEl.dataset;
......@@ -27,6 +28,7 @@ export default (containerId = 'js-billing-plans') => {
namespaceId,
namespaceName,
planUpgradeHref,
planRenewHref,
customerPortalUrl,
billableSeatsHref,
apiBillableMemberListFeatureEnabled: gon?.features?.apiBillableMemberList || false,
......
......@@ -6,6 +6,7 @@ class Groups::BillingsController < Groups::ApplicationController
before_action only: [:index] do
push_frontend_feature_flag(:api_billable_member_list)
push_frontend_feature_flag(:saas_manual_renew_button)
end
layout 'group_settings'
......
......@@ -16,6 +16,7 @@ module BillingPlansHelper
namespace_id: group.id,
namespace_name: group.name,
plan_upgrade_href: plan_upgrade_url(group, plan),
plan_renew_href: plan_renew_url(group),
customer_portal_url: "#{EE::SUBSCRIPTIONS_URL}/subscriptions",
billable_seats_href: billable_seats_href(group)
}
......@@ -95,6 +96,12 @@ module BillingPlansHelper
"#{EE::SUBSCRIPTIONS_URL}/gitlab/namespaces/#{group.id}/upgrade/#{plan.id}"
end
def plan_renew_url(group)
return unless group
"#{EE::SUBSCRIPTIONS_URL}/gitlab/namespaces/#{group.id}/renew"
end
def billable_seats_href(group)
return unless Feature.enabled?(:api_billable_member_list, group)
......
---
title: Add manual renew button to billings page
merge_request: 48610
author:
type: other
---
name: saas_manual_renew_button
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48610
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/288804
milestone: '13.7'
type: development
group: group::fulfillment
default_enabled: false
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`SubscriptionTable component given a bronze plan with state: isFreePlan=false, upgradable=true, isTrialPlan=false has Upgrade and Manage buttons 1`] = `
exports[`SubscriptionTable component given a bronze plan with state: isFreePlan=false, upgradable=true, isTrialPlan=false has Upgrade and Renew and Manage buttons 1`] = `
Array [
Object {
"href": "http://test.host/plan/upgrade/bronze",
"text": "Upgrade",
},
Object {
"href": "http://test.host/plan/renew",
"text": "Renew",
},
Object {
"href": "https://customers.gitlab.com/subscriptions",
"text": "Manage",
......@@ -13,12 +17,16 @@ Array [
]
`;
exports[`SubscriptionTable component given a free plan with state: isFreePlan=true, upgradable=true, isTrialPlan=false has Upgrade and Manage buttons 1`] = `
exports[`SubscriptionTable component given a free plan with state: isFreePlan=true, upgradable=true, isTrialPlan=false has Upgrade and Renew and Manage buttons 1`] = `
Array [
Object {
"href": "http://test.host/plan/upgrade/free",
"text": "Upgrade",
},
Object {
"href": "http://test.host/plan/renew",
"text": "Renew",
},
Object {
"href": "https://customers.gitlab.com/subscriptions",
"text": "Manage",
......@@ -26,8 +34,12 @@ Array [
]
`;
exports[`SubscriptionTable component given a gold plan with state: isFreePlan=false, upgradable=false, isTrialPlan=false has Manage button 1`] = `
exports[`SubscriptionTable component given a gold plan with state: isFreePlan=false, upgradable=false, isTrialPlan=false has Renew and Manage buttons 1`] = `
Array [
Object {
"href": "http://test.host/plan/renew",
"text": "Renew",
},
Object {
"href": "https://customers.gitlab.com/subscriptions",
"text": "Manage",
......@@ -37,6 +49,10 @@ Array [
exports[`SubscriptionTable component given a trial-gold plan with state: isFreePlan=false, upgradable=false, isTrialPlan=true has Manage button 1`] = `
Array [
Object {
"href": "http://test.host/plan/renew",
"text": "Renew",
},
Object {
"href": "https://customers.gitlab.com/subscriptions",
"text": "Manage",
......
......@@ -17,6 +17,7 @@ describe('SubscriptionApp component', () => {
namespaceId: '42',
namespaceName: 'bronze',
planUpgradeHref: '/url',
planRenewHref: '/url/for/renew',
customerPortalUrl: 'https://customers.gitlab.com/subscriptions',
};
......@@ -58,6 +59,7 @@ describe('SubscriptionApp component', () => {
expectComponentWithProps(SubscriptionTable, {
namespaceName: providedFields.namespaceName,
planUpgradeHref: providedFields.planUpgradeHref,
planRenewHref: providedFields.planRenewHref,
customerPortalUrl: providedFields.customerPortalUrl,
});
});
......
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui';
import { TEST_HOST } from 'helpers/test_constants';
import initialStore from 'ee/billings/subscriptions/store';
import * as types from 'ee/billings/subscriptions/store/mutation_types';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import SubscriptionTable from 'ee/billings/subscriptions/components/subscription_table.vue';
import SubscriptionTableRow from 'ee/billings/subscriptions/components/subscription_table_row.vue';
import initialStore from 'ee/billings/subscriptions/store';
import * as types from 'ee/billings/subscriptions/store/mutation_types';
import { mockDataSubscription } from 'ee_jest/billings/mock_data';
import { TEST_HOST } from 'helpers/test_constants';
import Vuex from 'vuex';
const TEST_NAMESPACE_NAME = 'GitLab.com';
const CUSTOMER_PORTAL_URL = 'https://customers.gitlab.com/subscriptions';
......@@ -42,6 +42,7 @@ describe('SubscriptionTable component', () => {
propsData: {
namespaceName: TEST_NAMESPACE_NAME,
planUpgradeHref: '/url/',
planRenewHref: '/url/for/renew',
customerPortalUrl: CUSTOMER_PORTAL_URL,
},
});
......@@ -90,21 +91,23 @@ describe('SubscriptionTable component', () => {
describe.each`
planName | isFreePlan | upgradable | isTrialPlan | snapshotDesc
${'free'} | ${true} | ${true} | ${false} | ${'has Upgrade and Manage buttons'}
${'free'} | ${true} | ${true} | ${false} | ${'has Upgrade and Renew and Manage buttons'}
${'trial-gold'} | ${false} | ${false} | ${true} | ${'has Manage button'}
${'gold'} | ${false} | ${false} | ${false} | ${'has Manage button'}
${'bronze'} | ${false} | ${true} | ${false} | ${'has Upgrade and Manage buttons'}
${'gold'} | ${false} | ${false} | ${false} | ${'has Renew and Manage buttons'}
${'bronze'} | ${false} | ${true} | ${false} | ${'has Upgrade and Renew and Manage buttons'}
`(
'given a $planName plan with state: isFreePlan=$isFreePlan, upgradable=$upgradable, isTrialPlan=$isTrialPlan',
({ planName, isFreePlan, upgradable, snapshotDesc }) => {
beforeEach(() => {
const planUpgradeHref = `${TEST_HOST}/plan/upgrade/${planName}`;
const planRenewHref = `${TEST_HOST}/plan/renew`;
factory({
propsData: {
namespaceName: TEST_NAMESPACE_NAME,
customerPortalUrl: CUSTOMER_PORTAL_URL,
planUpgradeHref,
planRenewHref,
},
});
......@@ -126,4 +129,27 @@ describe('SubscriptionTable component', () => {
});
},
);
describe('render button', () => {
window.gon = { features: {} };
afterEach(() => {
window.gon.features = {};
});
it('renders the renew button when feature flag is on', () => {
gon.features.saasManualRenewButton = true;
factory({ propsData: { namespaceName: TEST_NAMESPACE_NAME } });
expect(findButtonProps()).toStrictEqual([
{ text: 'Upgrade', href: '' },
{ text: 'Renew', href: '' },
]);
});
it('does not render the renew button when the feature flag is off', () => {
gon.features.saasManualRenewButton = false;
factory({ propsData: { namespaceName: TEST_NAMESPACE_NAME } });
expect(findButtonProps()).toStrictEqual([{ text: 'Upgrade', href: '' }]);
});
});
});
......@@ -15,12 +15,15 @@ RSpec.describe BillingPlansHelper do
it 'returns data attributes' do
upgrade_href =
"#{EE::SUBSCRIPTIONS_URL}/gitlab/namespaces/#{group.id}/upgrade/#{plan.id}"
renew_href =
"#{EE::SUBSCRIPTIONS_URL}/gitlab/namespaces/#{group.id}/renew"
billable_seats_href = helper.group_seat_usage_path(group)
expect(helper.subscription_plan_data_attributes(group, plan))
.to eq(namespace_id: group.id,
namespace_name: group.name,
plan_upgrade_href: upgrade_href,
plan_renew_href: renew_href,
customer_portal_url: customer_portal_url,
billable_seats_href: billable_seats_href)
end
......@@ -38,6 +41,7 @@ RSpec.describe BillingPlansHelper do
let(:plan) { Hashie::Mash.new(id: nil) }
it 'returns data attributes without upgrade href' do
renew_href = "#{EE::SUBSCRIPTIONS_URL}/gitlab/namespaces/#{group.id}/renew"
billable_seats_href = helper.group_seat_usage_path(group)
expect(helper.subscription_plan_data_attributes(group, plan))
......@@ -45,6 +49,7 @@ RSpec.describe BillingPlansHelper do
namespace_name: group.name,
customer_portal_url: customer_portal_url,
billable_seats_href: billable_seats_href,
plan_renew_href: renew_href,
plan_upgrade_href: nil)
end
end
......
......@@ -26188,6 +26188,9 @@ msgstr ""
msgid "SubscriptionTable|Next invoice"
msgstr ""
msgid "SubscriptionTable|Renew"
msgstr ""
msgid "SubscriptionTable|Seats currently in use"
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