Commit e4375a34 authored by Angelo Gulina's avatar Angelo Gulina Committed by Vitaly Slobodin

Add message for user count overage

Notify the user of QSR process around user seats overage.

Changelog: changed
MR: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80149
EE: true
parent 43d680b3
...@@ -31,3 +31,5 @@ export const STEPS = [ ...@@ -31,3 +31,5 @@ export const STEPS = [
]; ];
export const TRACK_SUCCESS_MESSAGE = 'Success'; export const TRACK_SUCCESS_MESSAGE = 'Success';
/* eslint-enable @gitlab/require-i18n-strings */ /* eslint-enable @gitlab/require-i18n-strings */
export const QSR_RECONCILIATION_PATH = 'subscriptions/quarterly_reconciliation.html';
<script> <script>
import { GlFormGroup, GlFormSelect, GlFormInput, GlSprintf, GlLink } from '@gitlab/ui'; import { GlAlert, GlFormGroup, GlFormSelect, GlFormInput, GlSprintf, GlLink } from '@gitlab/ui';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import { mapState, mapGetters, mapActions } from 'vuex'; import { mapState, mapGetters, mapActions } from 'vuex';
import { STEP_SUBSCRIPTION_DETAILS } from 'ee/subscriptions/constants'; import { QSR_RECONCILIATION_PATH, STEP_SUBSCRIPTION_DETAILS } from 'ee/subscriptions/constants';
import { NEW_GROUP } from 'ee/subscriptions/new/constants'; import { NEW_GROUP } from 'ee/subscriptions/new/constants';
import Step from 'ee/vue_shared/purchase_flow/components/step.vue'; import Step from 'ee/vue_shared/purchase_flow/components/step.vue';
import { sprintf, s__ } from '~/locale'; import { sprintf, s__, __ } from '~/locale';
import autofocusonshow from '~/vue_shared/directives/autofocusonshow'; import autofocusonshow from '~/vue_shared/directives/autofocusonshow';
import Tracking from '~/tracking'; import Tracking from '~/tracking';
import { helpPagePath } from '~/helpers/help_page_helper';
export default { export default {
components: { components: {
GlAlert,
GlFormGroup, GlFormGroup,
GlFormSelect, GlFormSelect,
GlFormInput, GlFormInput,
...@@ -170,8 +172,12 @@ export default { ...@@ -170,8 +172,12 @@ export default {
selectedPlan: s__('Checkout|%{selectedPlanText} plan'), selectedPlan: s__('Checkout|%{selectedPlanText} plan'),
group: s__('Checkout|Group'), group: s__('Checkout|Group'),
users: s__('Checkout|Users'), users: s__('Checkout|Users'),
qsrOverageMessage: __(
'You are billed if you exceed this number. %{qsrOverageLinkStart}How does billing work?%{qsrOverageLinkEnd}',
),
}, },
stepId: STEP_SUBSCRIPTION_DETAILS, stepId: STEP_SUBSCRIPTION_DETAILS,
qsrReconciliationLink: helpPagePath(QSR_RECONCILIATION_PATH),
}; };
</script> </script>
<template> <template>
...@@ -215,7 +221,11 @@ export default { ...@@ -215,7 +221,11 @@ export default {
<gl-form-input ref="organization-name" v-model="organizationNameModel" type="text" /> <gl-form-input ref="organization-name" v-model="organizationNameModel" type="text" />
</gl-form-group> </gl-form-group>
<div class="combined d-flex"> <div class="combined d-flex">
<gl-form-group :label="$options.i18n.numberOfUsersLabel" label-size="sm" class="number"> <gl-form-group
:label="$options.i18n.numberOfUsersLabel"
label-size="sm"
class="number gl-mb-0"
>
<gl-form-input <gl-form-input
ref="number-of-users" ref="number-of-users"
v-model.number="numberOfUsersModel" v-model.number="numberOfUsersModel"
...@@ -237,6 +247,18 @@ export default { ...@@ -237,6 +247,18 @@ export default {
</gl-sprintf> </gl-sprintf>
</gl-form-group> </gl-form-group>
</div> </div>
<gl-alert
class="gl-mt-5 gl-mb-6"
:dismissible="false"
variant="info"
data-testid="qsr-overage-message"
>
<gl-sprintf :message="$options.i18n.qsrOverageMessage">
<template #qsrOverageLink="{ content }">
<gl-link :href="$options.qsrReconciliationLink" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</gl-alert>
</template> </template>
<template #summary> <template #summary>
<strong ref="summary-line-1"> <strong ref="summary-line-1">
......
import { mount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue'; import Vue, { nextTick } from 'vue';
import { GlLink } from '@gitlab/ui';
import VueApollo from 'vue-apollo'; import VueApollo from 'vue-apollo';
import Vuex from 'vuex'; import Vuex from 'vuex';
import { mockTracking } from 'helpers/tracking_helper'; import { mockTracking } from 'helpers/tracking_helper';
import { STEPS } from 'ee/subscriptions/constants'; import { QSR_RECONCILIATION_PATH, STEPS } from 'ee/subscriptions/constants';
import Component from 'ee/subscriptions/new/components/checkout/subscription_details.vue'; import Component from 'ee/subscriptions/new/components/checkout/subscription_details.vue';
import { NEW_GROUP } from 'ee/subscriptions/new/constants'; import { NEW_GROUP } from 'ee/subscriptions/new/constants';
import createStore from 'ee/subscriptions/new/store'; import createStore from 'ee/subscriptions/new/store';
import * as types from 'ee/subscriptions/new/store/mutation_types'; import * as types from 'ee/subscriptions/new/store/mutation_types';
import Step from 'ee/vue_shared/purchase_flow/components/step.vue'; import Step from 'ee/vue_shared/purchase_flow/components/step.vue';
import { createMockApolloProvider } from 'ee_jest/vue_shared/purchase_flow/spec_helper'; import { createMockApolloProvider } from 'ee_jest/vue_shared/purchase_flow/spec_helper';
import { mountExtended } from 'helpers/vue_test_utils_helper';
const availablePlans = [ const availablePlans = [
{ id: 'firstPlanId', code: 'bronze', price_per_year: 48, name: 'bronze' }, { id: 'firstPlanId', code: 'bronze', price_per_year: 48, name: 'bronze' },
...@@ -38,7 +39,7 @@ describe('Subscription Details', () => { ...@@ -38,7 +39,7 @@ describe('Subscription Details', () => {
function createComponent(options = {}) { function createComponent(options = {}) {
const { apolloProvider, store } = options; const { apolloProvider, store } = options;
return mount(Component, { return mountExtended(Component, {
store, store,
apolloProvider, apolloProvider,
stubs: { stubs: {
...@@ -51,11 +52,34 @@ describe('Subscription Details', () => { ...@@ -51,11 +52,34 @@ describe('Subscription Details', () => {
const groupSelect = () => wrapper.findComponent({ ref: 'group-select' }); const groupSelect = () => wrapper.findComponent({ ref: 'group-select' });
const numberOfUsersInput = () => wrapper.findComponent({ ref: 'number-of-users' }); const numberOfUsersInput = () => wrapper.findComponent({ ref: 'number-of-users' });
const companyLink = () => wrapper.findComponent({ ref: 'company-link' }); const companyLink = () => wrapper.findComponent({ ref: 'company-link' });
const findQsrOverageMessage = () => wrapper.findByTestId('qsr-overage-message');
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
}); });
describe('when rendering', () => {
beforeEach(() => {
const mockApollo = createMockApolloProvider(STEPS);
const store = createStore(
createDefaultInitialStoreData({ newUser: 'true', setupForCompany: '' }),
);
wrapper = createComponent({ apolloProvider: mockApollo, store });
});
it('has an alert displaying a message related to QSR process', () => {
expect(findQsrOverageMessage().text()).toMatchInterpolatedText(
'You are billed if you exceed this number. How does billing work?',
);
});
it('has a link to QSR process help page', () => {
expect(findQsrOverageMessage().findComponent(GlLink).attributes('href')).toMatch(
QSR_RECONCILIATION_PATH,
);
});
});
describe('A new user for which we do not have setupForCompany info', () => { describe('A new user for which we do not have setupForCompany info', () => {
beforeEach(() => { beforeEach(() => {
const mockApollo = createMockApolloProvider(STEPS); const mockApollo = createMockApolloProvider(STEPS);
......
...@@ -41183,6 +41183,9 @@ msgstr "" ...@@ -41183,6 +41183,9 @@ msgstr ""
msgid "You are attempting to update a file that has changed since you started editing it." msgid "You are attempting to update a file that has changed since you started editing it."
msgstr "" msgstr ""
msgid "You are billed if you exceed this number. %{qsrOverageLinkStart}How does billing work?%{qsrOverageLinkEnd}"
msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display." msgid "You are connected to the Prometheus server, but there is currently no data to display."
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