Commit 067abf4f authored by Andrew Fontaine's avatar Andrew Fontaine

Merge branch 'vs-refactor-subscription-table-row' into 'master'

Remove redundant request for fetching billable members

See merge request gitlab-org/gitlab!56874
parents 33702b3f 0aba6869
...@@ -108,7 +108,7 @@ export default { ...@@ -108,7 +108,7 @@ export default {
return this.tables[tableKey].rows; return this.tables[tableKey].rows;
}, },
}, },
mounted() { created() {
this.fetchSubscription(); this.fetchSubscription();
}, },
methods: { methods: {
...@@ -151,6 +151,7 @@ export default { ...@@ -151,6 +151,7 @@ export default {
:last="isLast(i)" :last="isLast(i)"
:header="row.header" :header="row.header"
:columns="row.columns" :columns="row.columns"
:is-free-plan="isFreePlan"
/> />
</div> </div>
</div> </div>
......
<script> <script>
import { GlIcon, GlButton } from '@gitlab/ui'; import { GlIcon, GlButton } from '@gitlab/ui';
import { mapActions, mapGetters, mapState } from 'vuex';
import { dateInWords } from '~/lib/utils/datetime_utility'; import { dateInWords } from '~/lib/utils/datetime_utility';
import Popover from '~/vue_shared/components/help_popover.vue'; import Popover from '~/vue_shared/components/help_popover.vue';
...@@ -11,7 +10,11 @@ export default { ...@@ -11,7 +10,11 @@ export default {
GlIcon, GlIcon,
Popover, Popover,
}, },
inject: ['billableSeatsHref', 'isGroup'], inject: {
billableSeatsHref: {
default: '',
},
},
props: { props: {
header: { header: {
type: Object, type: Object,
...@@ -26,21 +29,18 @@ export default { ...@@ -26,21 +29,18 @@ export default {
required: false, required: false,
default: false, default: false,
}, },
isFreePlan: {
type: Boolean,
required: false,
default: false,
},
}, },
computed: { computed: {
...mapState(['hasBillableGroupMembers']),
...mapGetters(['isFreePlan']),
rowClasses() { rowClasses() {
return !this.last ? 'gl-border-b-gray-100 gl-border-b-1 gl-border-b-solid' : null; return !this.last ? 'gl-border-b-gray-100 gl-border-b-1 gl-border-b-solid' : null;
}, },
}, },
created() {
if (this.isGroup) {
this.fetchHasBillableGroupMembers();
}
},
methods: { methods: {
...mapActions(['fetchHasBillableGroupMembers']),
getPopoverOptions(col) { getPopoverOptions(col) {
const defaults = { const defaults = {
placement: 'bottom', placement: 'bottom',
...@@ -63,7 +63,7 @@ export default { ...@@ -63,7 +63,7 @@ export default {
return typeof col.value !== 'undefined' && col.value !== null ? col.value : ' - '; return typeof col.value !== 'undefined' && col.value !== null ? col.value : ' - ';
}, },
isSeatsUsageButtonShown(col) { isSeatsUsageButtonShown(col) {
return this.hasBillableGroupMembers && this.billableSeatsHref && col.id === 'seatsInUse'; return this.billableSeatsHref && col.id === 'seatsInUse';
}, },
}, },
}; };
......
import Vue from 'vue'; import Vue from 'vue';
import Vuex from 'vuex'; import Vuex from 'vuex';
import { parseBoolean } from '~/lib/utils/common_utils';
import SubscriptionApp from './components/app.vue'; import SubscriptionApp from './components/app.vue';
import initialStore from './store'; import initialStore from './store';
...@@ -17,7 +16,6 @@ export default (containerId = 'js-billing-plans') => { ...@@ -17,7 +16,6 @@ export default (containerId = 'js-billing-plans') => {
namespaceId, namespaceId,
namespaceName, namespaceName,
addSeatsHref, addSeatsHref,
isGroup,
planUpgradeHref, planUpgradeHref,
planRenewHref, planRenewHref,
customerPortalUrl, customerPortalUrl,
...@@ -32,7 +30,6 @@ export default (containerId = 'js-billing-plans') => { ...@@ -32,7 +30,6 @@ export default (containerId = 'js-billing-plans') => {
namespaceId, namespaceId,
namespaceName, namespaceName,
addSeatsHref, addSeatsHref,
isGroup: parseBoolean(isGroup),
planUpgradeHref, planUpgradeHref,
planRenewHref, planRenewHref,
customerPortalUrl, customerPortalUrl,
......
...@@ -29,27 +29,3 @@ export const receiveSubscriptionError = ({ commit }) => { ...@@ -29,27 +29,3 @@ export const receiveSubscriptionError = ({ commit }) => {
}); });
commit(types.RECEIVE_SUBSCRIPTION_ERROR); commit(types.RECEIVE_SUBSCRIPTION_ERROR);
}; };
/**
* Billable Members
*/
export const fetchHasBillableGroupMembers = ({ dispatch, state }) => {
dispatch('requestHasBillableGroupMembers');
return Api.fetchBillableGroupMembersList(state.namespaceId, { per_page: 1, page: 1 })
.then((data) => dispatch('receiveHasBillableGroupMembersSuccess', data))
.catch(() => dispatch('receiveHasBillableGroupMembersError'));
};
export const requestHasBillableGroupMembers = ({ commit }) =>
commit(types.REQUEST_HAS_BILLABLE_MEMBERS);
export const receiveHasBillableGroupMembersSuccess = ({ commit }, response) =>
commit(types.RECEIVE_HAS_BILLABLE_MEMBERS_SUCCESS, response);
export const receiveHasBillableGroupMembersError = ({ commit }) => {
createFlash({
message: s__('SubscriptionTable|An error occurred while loading billable members list'),
});
commit(types.RECEIVE_HAS_BILLABLE_MEMBERS_ERROR);
};
...@@ -3,7 +3,3 @@ export const SET_NAMESPACE_ID = 'SET_NAMESPACE_ID'; ...@@ -3,7 +3,3 @@ export const SET_NAMESPACE_ID = 'SET_NAMESPACE_ID';
export const REQUEST_SUBSCRIPTION = 'REQUEST_SUBSCRIPTION'; export const REQUEST_SUBSCRIPTION = 'REQUEST_SUBSCRIPTION';
export const RECEIVE_SUBSCRIPTION_SUCCESS = 'RECEIVE_SUBSCRIPTION_SUCCESS'; export const RECEIVE_SUBSCRIPTION_SUCCESS = 'RECEIVE_SUBSCRIPTION_SUCCESS';
export const RECEIVE_SUBSCRIPTION_ERROR = 'RECEIVE_SUBSCRIPTION_ERROR'; export const RECEIVE_SUBSCRIPTION_ERROR = 'RECEIVE_SUBSCRIPTION_ERROR';
export const REQUEST_HAS_BILLABLE_MEMBERS = 'REQUEST_HAS_BILLABLE_MEMBERS';
export const RECEIVE_HAS_BILLABLE_MEMBERS_SUCCESS = 'RECEIVE_HAS_BILLABLE_MEMBERS_SUCCESS';
export const RECEIVE_HAS_BILLABLE_MEMBERS_ERROR = 'RECEIVE_HAS_BILLABLE_MEMBERS_ERROR';
import { parseInt } from 'lodash';
import Vue from 'vue'; import Vue from 'vue';
import { import { TABLE_TYPE_DEFAULT, TABLE_TYPE_FREE, TABLE_TYPE_TRIAL } from 'ee/billings/constants';
TABLE_TYPE_DEFAULT,
TABLE_TYPE_FREE,
TABLE_TYPE_TRIAL,
HEADER_TOTAL_ENTRIES,
} from 'ee/billings/constants';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import * as types from './mutation_types'; import * as types from './mutation_types';
...@@ -49,22 +43,4 @@ export default { ...@@ -49,22 +43,4 @@ export default {
state.isLoadingSubscription = false; state.isLoadingSubscription = false;
state.hasErrorSubscription = true; state.hasErrorSubscription = true;
}, },
[types.REQUEST_HAS_BILLABLE_MEMBERS](state) {
state.isLoadingHasBillableMembers = true;
state.hasErrorHasBillableMembers = false;
},
[types.RECEIVE_HAS_BILLABLE_MEMBERS_SUCCESS](state, payload) {
const { headers } = payload;
const hasBillableGroupMembers = parseInt(headers[HEADER_TOTAL_ENTRIES], 10) > 0;
state.hasBillableGroupMembers = hasBillableGroupMembers;
state.isLoadingHasBillableMembers = false;
},
[types.RECEIVE_HAS_BILLABLE_MEMBERS_ERROR](state) {
state.isLoadinggHasBillableMembers = false;
state.hasErrorHasBillableMembers = true;
},
}; };
...@@ -3,8 +3,6 @@ import { s__ } from '~/locale'; ...@@ -3,8 +3,6 @@ import { s__ } from '~/locale';
export default () => ({ export default () => ({
isLoadingSubscription: false, isLoadingSubscription: false,
hasErrorSubscription: false, hasErrorSubscription: false,
isLoadingBillableMembers: false,
hasErrorBillableMembers: false,
namespaceId: null, namespaceId: null,
plan: { plan: {
code: null, code: null,
...@@ -171,5 +169,4 @@ export default () => ({ ...@@ -171,5 +169,4 @@ export default () => ({
], ],
}, },
}, },
hasBillableGroupMembers: false,
}); });
...@@ -40,7 +40,6 @@ module BillingPlansHelper ...@@ -40,7 +40,6 @@ module BillingPlansHelper
{ {
namespace_id: namespace.id, namespace_id: namespace.id,
namespace_name: namespace.name, namespace_name: namespace.name,
is_group: namespace.group?.to_s,
add_seats_href: add_seats_url(namespace), add_seats_href: add_seats_url(namespace),
plan_upgrade_href: plan_upgrade_url(namespace, plan), plan_upgrade_href: plan_upgrade_url(namespace, plan),
plan_renew_href: plan_renew_url(namespace), plan_renew_href: plan_renew_url(namespace),
...@@ -155,8 +154,10 @@ module BillingPlansHelper ...@@ -155,8 +154,10 @@ module BillingPlansHelper
"#{EE::SUBSCRIPTIONS_URL}/gitlab/namespaces/#{group.id}/renew" "#{EE::SUBSCRIPTIONS_URL}/gitlab/namespaces/#{group.id}/renew"
end end
def billable_seats_href(group) def billable_seats_href(namespace)
group_seat_usage_path(group) return unless namespace.group?
group_seat_usage_path(namespace)
end end
def offer_from_previous_tier?(namespace_id, plan_id) def offer_from_previous_tier?(namespace_id, plan_id)
......
...@@ -2,8 +2,6 @@ import { shallowMount, createLocalVue } from '@vue/test-utils'; ...@@ -2,8 +2,6 @@ import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex'; import Vuex from 'vuex';
import SubscriptionApp from 'ee/billings/subscriptions/components/app.vue'; import SubscriptionApp from 'ee/billings/subscriptions/components/app.vue';
import initialStore from 'ee/billings/subscriptions/store'; import initialStore from 'ee/billings/subscriptions/store';
import * as types from 'ee/billings/subscriptions/store/mutation_types';
import { mockDataSeats } from 'ee_jest/billings/mock_data';
const localVue = createLocalVue(); const localVue = createLocalVue();
localVue.use(Vuex); localVue.use(Vuex);
...@@ -35,13 +33,11 @@ describe('SubscriptionApp component', () => { ...@@ -35,13 +33,11 @@ describe('SubscriptionApp component', () => {
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
wrapper = null;
}); });
describe('on creation', () => { describe('on creation', () => {
beforeEach(() => { beforeEach(() => {
factory(); factory();
store.commit(`${types.RECEIVE_HAS_BILLABLE_MEMBERS_SUCCESS}`, mockDataSeats);
}); });
it('dispatches expected actions on created', () => { it('dispatches expected actions on created', () => {
......
...@@ -39,15 +39,7 @@ describe('subscription table row', () => { ...@@ -39,15 +39,7 @@ describe('subscription table row', () => {
const defaultProps = { header: HEADER, columns: COLUMNS }; const defaultProps = { header: HEADER, columns: COLUMNS };
const createComponent = ({ const createComponent = ({ props = {}, billableSeatsHref = BILLABLE_SEATS_URL } = {}) => {
props = {},
billableSeatsHref = BILLABLE_SEATS_URL,
isGroup = true,
} = {}) => {
if (wrapper) {
throw new Error('wrapper already exists!');
}
wrapper = shallowMount(SubscriptionTableRow, { wrapper = shallowMount(SubscriptionTableRow, {
propsData: { propsData: {
...defaultProps, ...defaultProps,
...@@ -55,7 +47,6 @@ describe('subscription table row', () => { ...@@ -55,7 +47,6 @@ describe('subscription table row', () => {
}, },
provide: { provide: {
billableSeatsHref, billableSeatsHref,
isGroup,
}, },
store, store,
localVue, localVue,
...@@ -69,7 +60,6 @@ describe('subscription table row', () => { ...@@ -69,7 +60,6 @@ describe('subscription table row', () => {
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
wrapper = null;
}); });
const findHeaderCell = () => wrapper.find('[data-testid="header-cell"]'); const findHeaderCell = () => wrapper.find('[data-testid="header-cell"]');
...@@ -88,18 +78,6 @@ describe('subscription table row', () => { ...@@ -88,18 +78,6 @@ describe('subscription table row', () => {
const findUsageButton = () => findContentCells().at(0).find('[data-testid="seats-usage-button"]'); const findUsageButton = () => findContentCells().at(0).find('[data-testid="seats-usage-button"]');
describe('dispatched actions', () => {
it('dispatches action when created if namespace is group', () => {
createComponent();
expect(store.dispatch).toHaveBeenCalledWith('fetchHasBillableGroupMembers');
});
it('does not dispatch action when created if namespace is not group', () => {
createComponent({ isGroup: false });
expect(store.dispatch).not.toHaveBeenCalledWith('fetchHasBillableGroupMembers');
});
});
describe('default', () => { describe('default', () => {
beforeEach(() => { beforeEach(() => {
createComponent(); createComponent();
...@@ -156,7 +134,7 @@ describe('subscription table row', () => { ...@@ -156,7 +134,7 @@ describe('subscription table row', () => {
}; };
it('renders a dash when the value is zero', () => { it('renders a dash when the value is zero', () => {
createComponent({ props: { columns: [dateColumn] } }); createComponent({ props: { isFreePlan: true, columns: [dateColumn] } });
expect(wrapper.find('[data-testid="property-value"]').text()).toBe('-'); expect(wrapper.find('[data-testid="property-value"]').text()).toBe('-');
}); });
...@@ -185,22 +163,23 @@ describe('subscription table row', () => { ...@@ -185,22 +163,23 @@ describe('subscription table row', () => {
}); });
}); });
it.each` describe('seats in use button', () => {
state | columnId | provide | exists | attrs it.each`
${{ hasBillableGroupMembers: true }} | ${'seatsInUse'} | ${{}} | ${true} | ${{ href: BILLABLE_SEATS_URL }} columnId | provide | exists | attrs
${{ hasBillableGroupMembers: true }} | ${'seatsInUse'} | ${{ billableSeatsHref: '' }} | ${false} | ${{}} ${'seatsInUse'} | ${{}} | ${true} | ${{ href: BILLABLE_SEATS_URL }}
${{ hasBillableGroupMembers: true }} | ${'some_value'} | ${{}} | ${false} | ${{}} ${'seatsInUse'} | ${{ billableSeatsHref: '' }} | ${false} | ${{}}
${{ hasBillableGroupMembers: false }} | ${'seatsInUse'} | ${{}} | ${false} | ${{}} ${'some_value'} | ${{}} | ${false} | ${{}}
`( ${'seatsInUse'} | ${{ billableSeatsHref: null }} | ${false} | ${{}}
'should exists=$exists with (state=$state, columnId=$columnId, provide=$provide)', `(
({ state, columnId, provide, exists, attrs }) => { 'should exists=$exists with (columnId=$columnId, provide=$provide)',
Object.assign(store.state, state); ({ columnId, provide, exists, attrs }) => {
createComponent({ props: { columns: [{ id: columnId }] }, ...provide }); createComponent({ props: { columns: [{ id: columnId }] }, ...provide });
expect(findUsageButton().exists()).toBe(exists); expect(findUsageButton().exists()).toBe(exists);
if (exists) { if (exists) {
expect(findUsageButton().attributes()).toMatchObject(attrs); expect(findUsageButton().attributes()).toMatchObject(attrs);
} }
}, },
); );
});
}); });
...@@ -21,7 +21,6 @@ RSpec.describe BillingPlansHelper do ...@@ -21,7 +21,6 @@ RSpec.describe BillingPlansHelper do
expect(helper.subscription_plan_data_attributes(group, plan)) expect(helper.subscription_plan_data_attributes(group, plan))
.to eq(namespace_id: group.id, .to eq(namespace_id: group.id,
namespace_name: group.name, namespace_name: group.name,
is_group: "true",
add_seats_href: add_seats_href, add_seats_href: add_seats_href,
plan_upgrade_href: upgrade_href, plan_upgrade_href: upgrade_href,
plan_renew_href: renew_href, plan_renew_href: renew_href,
...@@ -51,7 +50,6 @@ RSpec.describe BillingPlansHelper do ...@@ -51,7 +50,6 @@ RSpec.describe BillingPlansHelper do
.to eq(add_seats_href: add_seats_href, .to eq(add_seats_href: add_seats_href,
billable_seats_href: billable_seats_href, billable_seats_href: billable_seats_href,
customer_portal_url: customer_portal_url, customer_portal_url: customer_portal_url,
is_group: "true",
namespace_id: nil, namespace_id: nil,
namespace_name: group.name, namespace_name: group.name,
plan_renew_href: renew_href, plan_renew_href: renew_href,
...@@ -71,7 +69,6 @@ RSpec.describe BillingPlansHelper do ...@@ -71,7 +69,6 @@ RSpec.describe BillingPlansHelper do
expect(helper.subscription_plan_data_attributes(group, plan)) expect(helper.subscription_plan_data_attributes(group, plan))
.to eq(namespace_id: group.id, .to eq(namespace_id: group.id,
namespace_name: group.name, namespace_name: group.name,
is_group: "true",
customer_portal_url: customer_portal_url, customer_portal_url: customer_portal_url,
billable_seats_href: billable_seats_href, billable_seats_href: billable_seats_href,
add_seats_href: add_seats_href, add_seats_href: add_seats_href,
...@@ -81,13 +78,23 @@ RSpec.describe BillingPlansHelper do ...@@ -81,13 +78,23 @@ RSpec.describe BillingPlansHelper do
end end
end end
context 'when namespace is passed in' do context 'with different namespaces' do
it 'returns false for is_group' do subject { helper.subscription_plan_data_attributes(namespace, plan) }
namespace = build(:namespace)
result = helper.subscription_plan_data_attributes(namespace, plan) context 'with namespace' do
let(:namespace) { build(:namespace) }
expect(result).to include(is_group: "false") it 'does not return billable_seats_href' do
expect(subject).not_to include(billable_seats_href: helper.group_seat_usage_path(namespace))
end
end
context 'with group' do
let(:namespace) { build(:group) }
it 'returns billable_seats_href for group' do
expect(subject).to include(billable_seats_href: helper.group_seat_usage_path(namespace))
end
end end
end end
end end
......
...@@ -29191,9 +29191,6 @@ msgstr "" ...@@ -29191,9 +29191,6 @@ msgstr ""
msgid "SubscriptionTable|Add seats" msgid "SubscriptionTable|Add seats"
msgstr "" msgstr ""
msgid "SubscriptionTable|An error occurred while loading billable members list"
msgstr ""
msgid "SubscriptionTable|An error occurred while loading the subscription details." msgid "SubscriptionTable|An error occurred while loading the subscription details."
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