Skip to content
代码片段 群组 项目
未验证 提交 332f61ca 编辑于 作者: Ryan Cobb's avatar Ryan Cobb 提交者: GitLab
浏览文件

Show subscription next term start date

Show a subscriptions next term start date on the billing page.

Changelog: changed
EE: true
上级 aeccd3c3
No related branches found
No related tags found
无相关合并请求
显示 79 个添加30 个删除
......@@ -140,6 +140,9 @@ export default {
temporaryExtensionEndDate() {
return this.temporaryExtension?.endDate;
},
nextTermStartDate() {
return this.subscription?.nextTermStartDate;
},
buttons() {
return [this.addSeatsButton, this.renewButton, this.manageButton].filter(Boolean);
},
......@@ -234,6 +237,7 @@ export default {
:columns="row.columns"
:is-free-plan="isFreePlan"
:temporary-extension-end-date="temporaryExtensionEndDate"
:next-term-start-date="nextTermStartDate"
/>
</gl-card>
......
......@@ -45,11 +45,24 @@ export default {
required: false,
default: '',
},
nextTermStartDate: {
type: String,
required: false,
default: null,
},
},
computed: {
rowClasses() {
return !this.last ? 'gl-border-b-gray-100 gl-border-b-1 gl-border-b-solid' : null;
},
formattedNextTermStartDate() {
if (!this.nextTermStartDate) return ' - ';
const [year, month, day] = this.nextTermStartDate.split('-');
const formattedDate = dateInWords(new Date(year, month - 1, day));
return formattedDate;
},
},
methods: {
getPopoverOptions(col) {
......@@ -75,8 +88,13 @@ export default {
return ' - ';
}
if (col.id === 'nextTermStartDate') {
return this.formattedNextTermStartDate;
}
return typeof col.value !== 'undefined' && col.value !== null ? col.value : ' - ';
},
temporaryExtensionDisplayValue() {
const [year, month, day] = this.temporaryExtensionEndDate.split('-');
......
......@@ -145,16 +145,10 @@ export default () => ({
isDate: true,
},
{
id: 'lastInvoice',
label: s__('SubscriptionTable|Last invoice'),
id: 'nextTermStartDate',
label: s__('SubscriptionTable|Next subscription term start date'),
value: null,
isDate: true,
popover: {
content: s__(
'SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances.',
),
},
hideContent: true, // temporarily display a blank cell (as we don't have content yet)
},
{
id: 'nextInvoice',
......
......@@ -2,5 +2,6 @@ query getSubscriptionData($namespaceId: ID!) {
subscription(namespaceId: $namespaceId) {
canAddSeats
canRenew
nextTermStartDate
}
}
import { GlIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
// eslint-disable-next-line no-restricted-imports
import Vuex from 'vuex';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import SubscriptionTableRow from 'ee/billings/subscriptions/components/subscription_table_row.vue';
import initialStore from 'ee/billings/subscriptions/store';
import { TABLE_TYPE_DEFAULT } from 'ee/billings/constants';
......@@ -46,7 +46,7 @@ describe('subscription table row', () => {
billableSeatsHref = BILLABLE_SEATS_URL,
seatsLastUpdated = '12:13:14',
} = {}) => {
wrapper = shallowMount(SubscriptionTableRow, {
wrapper = shallowMountExtended(SubscriptionTableRow, {
propsData: {
...defaultProps,
...props,
......@@ -64,8 +64,8 @@ describe('subscription table row', () => {
jest.spyOn(store, 'dispatch').mockImplementation();
});
const findHeaderCell = () => wrapper.find('[data-testid="header-cell"]');
const findContentCells = () => wrapper.findAll('[data-testid="content-cell"]');
const findHeaderCell = () => wrapper.findByTestId('header-cell');
const findContentCells = () => wrapper.findAllByTestId('content-cell');
const findHeaderIcon = () => findHeaderCell().findComponent(GlIcon);
const findColumnLabelAndTitle = (columnWrapper) => {
......@@ -156,7 +156,7 @@ describe('subscription table row', () => {
])('renders seats last updated time when $description', ({ columns, expected }) => {
createComponent({ props: { columns } });
expect(wrapper.find('[data-testid="seats-last-updated"]').text()).toBe(expected);
expect(wrapper.findByTestId('seats-last-updated').text()).toBe(expected);
});
it('does not render seats last updated block when table type is not default', () => {
......@@ -175,7 +175,7 @@ describe('subscription table row', () => {
},
});
expect(wrapper.find('[data-testid="seats-last-updated"]').exists()).toBe(false);
expect(wrapper.findByTestId('seats-last-updated').exists()).toBe(false);
});
it('does not render seats last updated block when seatsLastUpdated is not available', () => {
......@@ -192,7 +192,7 @@ describe('subscription table row', () => {
},
});
expect(wrapper.find('[data-testid="seats-last-updated"]').exists()).toBe(false);
expect(wrapper.findByTestId('seats-last-updated').exists()).toBe(false);
});
});
......@@ -267,7 +267,39 @@ describe('subscription table row', () => {
props: { temporaryExtensionEndDate: '2023-12-28', columns: [dateColumn] },
});
expect(wrapper.find('[data-testid="temporary-extension-label"]').exists()).toBe(true);
expect(wrapper.findByTestId('temporary-extension-label').exists()).toBe(true);
});
});
describe('next term start date', () => {
const testId = 'next-subscription-term-start-date';
const dateColumn = {
id: 'nextTermStartDate',
label: 'Next subscription term start date',
value: null,
isDate: true,
};
describe('when next term start date is present', () => {
it('renders next term start date', () => {
createComponent({
props: { nextTermStartDate: '2023-12-28', columns: [dateColumn] },
});
expect(wrapper.findByTestId(testId).exists()).toBe(true);
expect(wrapper.findByTestId(testId).text()).toBe('December 28, 2023');
});
});
describe('when next term start date is null', () => {
it('renders dash', () => {
createComponent({
props: { nextTermStartDate: null, columns: [dateColumn] },
});
expect(wrapper.findByTestId(testId).exists()).toBe(true);
expect(wrapper.findByTestId(testId).text()).toBe('-');
});
});
});
});
......@@ -47,7 +47,7 @@ describe('SubscriptionTable component', () => {
props = {},
provide = {},
state = {},
apolloMock = { subscription: { canAddSeats: true, canRenew: true } },
apolloMock = { subscription: { canAddSeats: true, canRenew: true, nextTermStartDate: null } },
temporaryExtensionMock = { temporaryExtension: { endDate: '2023-12-28' } },
} = {}) => {
store = new Vuex.Store(initialStore());
......@@ -246,7 +246,7 @@ describe('SubscriptionTable component', () => {
code: planCode,
},
},
apolloMock: { subscription: { canAddSeats: true, canRenew } },
apolloMock: { subscription: { canAddSeats: true, canRenew, nextTermStartDate: null } },
});
});
......@@ -276,7 +276,7 @@ describe('SubscriptionTable component', () => {
upgradable: true,
},
},
apolloMock: { subscription: { canAddSeats, canRenew: true } },
apolloMock: { subscription: { canAddSeats, canRenew: true, nextTermStartDate: null } },
});
await waitForPromises();
......@@ -298,7 +298,9 @@ describe('SubscriptionTable component', () => {
upgradable: true,
},
},
apolloMock: { subscription: { canAddSeats: true, canRenew: true } },
apolloMock: {
subscription: { canAddSeats: true, canRenew: true, nextTermStartDate: null },
},
});
await waitForPromises();
......
......@@ -18,8 +18,8 @@ Array [
"seatsOwed": 4,
},
Object {
"lastInvoice": "2018-09-01",
"nextInvoice": "2018-10-01",
"nextTermStartDate": null,
"subscriptionEndDate": "2019-07-11",
"subscriptionStartDate": "2018-07-11",
},
......
......@@ -74,16 +74,17 @@ def stub_reconciliation_request(eligible)
}.to_json, headers: { 'Content-Type' => 'application/json' })
end
def stub_subscription_management_data(namespace_id, can_add_seats: true, can_renew: true)
def stub_subscription_management_data(namespace_id, can_add_seats: true, can_renew: true, next_term_start_date: nil)
stub_full_request(graphql_url, method: :post)
.with(
body: "{\"operationName\":\"getSubscriptionData\",\"variables\":{\"namespaceId\":#{namespace_id}},\"query\":\"query getSubscriptionData($namespaceId: ID!) {\\n subscription(namespaceId: $namespaceId) {\\n canAddSeats\\n canRenew\\n __typename\\n }\\n}\\n\"}"
body: "{\"operationName\":\"getSubscriptionData\",\"variables\":{\"namespaceId\":#{namespace_id}},\"query\":\"query getSubscriptionData($namespaceId: ID!) {\\n subscription(namespaceId: $namespaceId) {\\n canAddSeats\\n canRenew\\n nextTermStartDate\\n __typename\\n }\\n}\\n\"}"
)
.to_return(status: 200, body: {
"data": {
"subscription": {
"canAddSeats": can_add_seats,
"canRenew": can_renew
"canRenew": can_renew,
"nextTermStartDate": next_term_start_date
}
}
}.to_json)
......
......@@ -48323,9 +48323,6 @@ msgstr ""
msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
msgstr ""
 
msgid "SubscriptionTable|Last invoice"
msgstr ""
msgid "SubscriptionTable|Last updated at %{seatsLastUpdated} UTC"
msgstr ""
 
......@@ -48341,6 +48338,9 @@ msgstr ""
msgid "SubscriptionTable|Next invoice"
msgstr ""
 
msgid "SubscriptionTable|Next subscription term start date"
msgstr ""
msgid "SubscriptionTable|Refresh Seats"
msgstr ""
 
......@@ -48368,9 +48368,6 @@ msgstr ""
msgid "SubscriptionTable|Subscription start date"
msgstr ""
 
msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
msgstr ""
msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
msgstr ""
 
0% 加载中 .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册